/*
* Copyright 2011 Future Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.pcap.decoder.netbios;
import java.nio.charset.Charset;
import org.krakenapps.pcap.util.Buffer;
public class NetBiosNameCodec {
//00100000 - Netbios name, length must be 32 (decimal) || 0x20
//11xxxxxx - Label string pointer || 0xc0
//10xxxxxx - Reserved || 0x80
//01xxxxxx - Reserved || 0x40
//
private NetBiosNameCodec() {
}
public static String readOemName(Buffer b , int length){
byte[] buff = new byte[length];
b.gets(buff);
return new String(buff, Charset.forName("utf-8"));
}
public static String readOemName(Buffer b){
int length = b.bytesBefore(new byte[]{0x00});
byte[] buff = new byte[length];
b.gets(buff);
b.get();
return new String(buff, Charset.forName("utf-8"));
}
public static byte[] encode(byte[] source) {
byte[] b = new byte[source.length * 2];
for (int i = 0; i < 16; i++) {
b[i * 2] = (byte) (((source[i] & (0xf0)) >> 4) + 0x41);
b[(i * 2) + 1] = (byte) ((source[i] & (0x0f)) + 0x41);
}
return b;
}
public static String readName(Buffer b) {
byte tmp = b.get();
if (tmp == (byte) 0x20) {
int length = b.bytesBefore(new byte[] { 0x00 });
byte[] buffer = new byte[length];
b.gets(buffer);
b.get();
return decodeResourceName(buffer);
} else {
short signal = 0;
signal = (short) (((tmp & 0xff) << 8) + b.get());
if ((signal & 0xc000) == 0xc000) {
b.mark();
b.rewind();
b.skip((signal & 0x3fff) + 1);
int length = b.bytesBefore(new byte[] { 0x00 });
byte[] buffer = new byte[length];
b.gets(buffer);
b.get();
b.skip(6);
return decodeResourceName(buffer);
}
else if((signal & 0x8000) == 0x8000){
throw new IllegalStateException("Name Service Reserved Mask 0x80");
}
else if((signal & 0x4000) == 0x4000){
throw new IllegalStateException("Name Service Reserved Mask 0x40");
}
else {
throw new IllegalStateException("Name Service Read Name failed");
}
}
}
public static byte decodeDomainType(Buffer b){
b.mark();
int index = b.bytesBefore(new byte[]{0x00});
b.skip(index -2);
byte []domainBuff = new byte[2];
b.gets(domainBuff);
b.reset();
int b0 = (domainBuff[0] - (byte) (0x41)) << 4;
int b1 = (domainBuff[1] - (byte) (0x41));
return (byte) (b0 + b1);
}
public static String decodeResourceName(byte[] source) {
byte[] b = new byte[source.length / 2];
for (int i = 0; i < source.length / 2; i++) {
int b0 = (source[i * 2] - (byte) (0x41)) << 4;
int b1 = (source[(i * 2) + 1] - (byte) (0x41));
b[i] = (byte) (b0 + b1);
}
// remove trailing null bytes
byte[] buffer = null;
int i = 0;
for (i = 0; i < b.length; i++) {
if ((b[i] == (byte) 0x00) || (b[i] == (byte) 0x20)) {
break;
}
}
buffer = new byte[i];
for (int j = 0; j < i; j++) {
buffer[j] = b[j];
}
return new String(buffer, Charset.forName("utf-8"));
}
public static String readSmbUnicodeName(Buffer b) {
int length = b.bytesBefore(new byte[] { 0x00, 0x00 });
// Name field in Transaction Resquest use {0x00,0x00) instead string
byte[] buffer = new byte[length + 2];
byte[] convert = new byte[(length + 2) / 2];
b.gets(buffer);
for (int i = 0; i < convert.length; i++) {
convert[i] = buffer[i * 2];
}
if(length != 0){
b.get();
}
else if(length ==0){
return null;
}
return new String(convert, Charset.forName("utf-8"));
}
public static String readSmbUnicodeName(Buffer b , int length) {
b.mark();
byte tmp = b.get();
byte tmp2 = b.get();
b.reset();
if(tmp == 0x00 && tmp2 == 0x00 && length == 0){ // 0x00, 0x00 null string
b.skip(2);
return null;
}
else if(tmp == 0x00 && tmp2 == 0x00){ // skip 1byte padding
// do nothing
}
else if(tmp == 0x00){
b.skip(1);
}
// Name field in Transaction Request use {0x00,0x00) instead string
if(length+2 == b.readableBytes()+1){
length = length -1;
}
else if(length+2 == b.readableBytes()+2){
length = length -2;
}
byte[] buffer = new byte[length];
byte[] convert = new byte[(length) / 2];
b.gets(buffer);
for (int i = 0; i < convert.length; i++) {
convert[i] = buffer[i * 2];
}
if( b.readableBytes() %2 == 1){
b.get();
}
else if(b.readableBytes() >=2 ){
b.get();
b.get();
}
return new String(convert, Charset.forName("utf-8"));
}
public static String SmbNameConvertToString(byte[] b) {
// Name field in Transaction Resquest use {0x00,0x00) instead string
byte[] convert = new byte[(b.length + 1) / 2];
for (int i = 0; i < convert.length; i++) {
convert[i] = b[i * 2];
}
return new String(convert, Charset.forName("utf-8"));
}
}