|
@@ -7,14 +7,24 @@ import java.util.List;
|
|
|
import java.util.Random;
|
|
|
import java.util.TimeZone;
|
|
|
|
|
|
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
|
|
|
import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
|
|
|
|
|
|
+/**
|
|
|
+ * SMB protocol
|
|
|
+ * @author Wulf Pfeiffer
|
|
|
+ */
|
|
|
public final class SMB implements Protocol<ByteArray> {
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Represents the states of the protocol
|
|
|
+ */
|
|
|
private static enum STATE {
|
|
|
NONE, CONNECTED, AUTHENTICATED, LISTING, DISCONNECTED, CLOSED
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Denotes in which state the protocol is right now
|
|
|
+ */
|
|
|
private STATE state = STATE.NONE;
|
|
|
|
|
|
@Override
|
|
@@ -27,7 +37,7 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
return TALK_FIRST.CLIENT;
|
|
|
}
|
|
|
|
|
|
- private SmbPacket packet = new SmbPacket();
|
|
|
+ private SMBPacket packet = new SMBPacket();
|
|
|
|
|
|
@Override
|
|
|
public List<ByteArray> processMessage(ByteArray message) {
|
|
@@ -122,22 +132,10 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
return "SMB";
|
|
|
}
|
|
|
|
|
|
- private byte[] concat(byte[]... bytes) {
|
|
|
- int newSize = 0;
|
|
|
- for (byte[] b : bytes)
|
|
|
- newSize += b.length;
|
|
|
- byte[] dst = new byte[newSize];
|
|
|
-
|
|
|
- int currentPos = 0;
|
|
|
- int newPos;
|
|
|
- for (byte[] b : bytes) {
|
|
|
- newPos = b.length;
|
|
|
- System.arraycopy(b, 0, dst, currentPos, newPos);
|
|
|
- currentPos += newPos;
|
|
|
- }
|
|
|
- return dst;
|
|
|
- }
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Converts the current system time into a byte[] with windows specific time
|
|
|
+ * @return current system time in windows format as byte[]
|
|
|
+ */
|
|
|
private byte[] getTimeInBytes() {
|
|
|
long time = System.currentTimeMillis();
|
|
|
Calendar calend = Calendar.getInstance();
|
|
@@ -155,7 +153,12 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
|
|
|
return b;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Generates a random byte[] of a specified size
|
|
|
+ * @param size of the byte[]
|
|
|
+ * @return random byte[]
|
|
|
+ */
|
|
|
private byte[] randomBytes(int size) {
|
|
|
byte[] bytes = new byte[size];
|
|
|
Random rdm = new Random();
|
|
@@ -163,44 +166,14 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
return bytes;
|
|
|
}
|
|
|
|
|
|
- private String byteToStr(byte[] bytes) {
|
|
|
- return charToString(byteToChar(bytes));
|
|
|
- }
|
|
|
-
|
|
|
- private String charToString(char[] chars) {
|
|
|
- char[] newChars = new char[chars.length];
|
|
|
- for (int i = 0, j = 0; i < chars.length && j < newChars.length; i++) {
|
|
|
- if (isLetter(chars[i])) {
|
|
|
- newChars[j] = chars[i];
|
|
|
- j++;
|
|
|
- }
|
|
|
- }
|
|
|
- return new String(newChars);
|
|
|
- }
|
|
|
-
|
|
|
- private byte[] charToByte(char[] chars) {
|
|
|
- byte[] bytes = new byte[chars.length];
|
|
|
- for (int i = 0; i < chars.length; i++)
|
|
|
- bytes[i] = (byte) chars[i];
|
|
|
- return bytes;
|
|
|
- }
|
|
|
-
|
|
|
- private char[] byteToChar(byte[] bytes) {
|
|
|
- char[] chars = new char[bytes.length];
|
|
|
- for (int i = 0; i < bytes.length; i++)
|
|
|
- chars[i] = (char) bytes[i];
|
|
|
- return chars;
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isLetter(char c) {
|
|
|
- return (c >= 32 && c <= 127);
|
|
|
- }
|
|
|
-
|
|
|
- private class SmbPacket {
|
|
|
- private byte[] msg = null;
|
|
|
+ /**
|
|
|
+ * Denotes a SMB packet
|
|
|
+ */
|
|
|
+ private class SMBPacket {
|
|
|
+ private byte[] message = null;
|
|
|
private final byte[] serverGUID = randomBytes(16);
|
|
|
private boolean authenticateNext = false;
|
|
|
-
|
|
|
+ //components of a SMB packet
|
|
|
private byte[] serverComp = new byte[4];
|
|
|
private byte[] smbCommand = new byte[1];
|
|
|
private byte[] ntStat = new byte[4];
|
|
@@ -213,39 +186,57 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
private byte[] processID = new byte[2];
|
|
|
private byte[] userID = new byte[2];
|
|
|
private byte[] multiplexID = new byte[2];
|
|
|
-
|
|
|
- public SmbPacket() {
|
|
|
- }
|
|
|
+
|
|
|
+ /** Constructor */
|
|
|
+ public SMBPacket() {}
|
|
|
|
|
|
- public void newMsg(byte[] msg) {
|
|
|
- this.msg = msg;
|
|
|
- serverComp = new byte[]{msg[4], msg[5], msg[6], msg[7]};
|
|
|
- smbCommand = new byte[]{msg[8]};
|
|
|
- ntStat = new byte[]{msg[9], msg[10], msg[11], msg[12]};
|
|
|
- smbFlags = new byte[]{(byte) (msg[13] | 0x80)}; // | 0x80 for mark response bit
|
|
|
- smbFlags2 = new byte[]{msg[14], msg[15]};
|
|
|
- processIDHigh = new byte[]{msg[16], msg[17]};
|
|
|
- signature = new byte[]{msg[18], msg[19], msg[20], msg[21], msg[22], msg[23], msg[24], msg[25]};
|
|
|
- reserved = new byte[]{msg[26], msg[27]};
|
|
|
- treeID = new byte[]{msg[28], msg[29]};
|
|
|
- processID = new byte[]{msg[30], msg[31]};
|
|
|
- userID = new byte[]{msg[32], msg[33]};
|
|
|
- multiplexID = new byte[]{msg[34], msg[35]};
|
|
|
+ /**
|
|
|
+ * Breaks a message from the client down into its components
|
|
|
+ * @param message that is analyzed
|
|
|
+ */
|
|
|
+ public void newMsg(byte[] message) {
|
|
|
+ this.message = message;
|
|
|
+ serverComp = new byte[]{message[4], message[5], message[6], message[7]};
|
|
|
+ smbCommand = new byte[]{message[8]};
|
|
|
+ ntStat = new byte[]{message[9], message[10], message[11], message[12]};
|
|
|
+ smbFlags = new byte[]{(byte) (message[13] | 0x80)}; // | 0x80 for mark response bit
|
|
|
+ smbFlags2 = new byte[]{message[14], message[15]};
|
|
|
+ processIDHigh = new byte[]{message[16], message[17]};
|
|
|
+ signature = new byte[]{message[18], message[19], message[20], message[21], message[22], message[23], message[24], message[25]};
|
|
|
+ reserved = new byte[]{message[26], message[27]};
|
|
|
+ treeID = new byte[]{message[28], message[29]};
|
|
|
+ processID = new byte[]{message[30], message[31]};
|
|
|
+ userID = new byte[]{message[32], message[33]};
|
|
|
+ multiplexID = new byte[]{message[34], message[35]};
|
|
|
}
|
|
|
|
|
|
- private byte[] getNetbios(byte[] response) {
|
|
|
+ /**
|
|
|
+ * Wraps the Netbios header around a response
|
|
|
+ * @param response that is wrapped
|
|
|
+ * @return wrapped response
|
|
|
+ */
|
|
|
+ private byte[] wrapNetbios(byte[] response) {
|
|
|
byte[] netbios = {0x00};
|
|
|
- byte[] buf = ByteBuffer.allocate(4).putInt(response.length).array(); // allocate(4) because int is 4 bytes long
|
|
|
- byte[] netbiosLength = {buf[1], buf[2], buf[3]}; // only bytes 1-3 needed, byte 0 is not needed
|
|
|
- return concat(netbios, netbiosLength);
|
|
|
+ byte[] buffer = ByteBuffer.allocate(4).putInt(response.length).array(); // allocate(4) because int is 4 bytes long
|
|
|
+ byte[] netbiosLength = {buffer[1], buffer[2], buffer[3]}; // only bytes 1-3 needed, byte 0 is not needed
|
|
|
+ return HelperUtils.concat(netbios, netbiosLength, response);
|
|
|
}
|
|
|
|
|
|
- private byte[] getHeader() {
|
|
|
+ /**
|
|
|
+ * Wraps the header around a response
|
|
|
+ * @param response that is wrapped
|
|
|
+ * @return wrapped response
|
|
|
+ */
|
|
|
+ private byte[] wrapHeader(byte[] response) {
|
|
|
byte[] header = new byte[0];
|
|
|
- return concat(header, serverComp, smbCommand, ntStat, smbFlags, smbFlags2, processIDHigh, signature,
|
|
|
- reserved, treeID, processID, userID, multiplexID);
|
|
|
+ return HelperUtils.concat(header, serverComp, smbCommand, ntStat, smbFlags, smbFlags2, processIDHigh, signature,
|
|
|
+ reserved, treeID, processID, userID, multiplexID, response);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the negotiate packet
|
|
|
+ * @return negotiate packet
|
|
|
+ */
|
|
|
public byte[] getNego() {
|
|
|
byte[] wordCount = {0x11};
|
|
|
byte[] dialect = evaluateDialect();
|
|
@@ -268,15 +259,19 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
byte[] mechType = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, (byte) 0x82, 0x37, 0x02, 0x02, 0x1e};
|
|
|
byte[] mechType2 = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, (byte) 0x82, 0x37, 0x02, 0x02, 0x0a};
|
|
|
|
|
|
- byte[] response = concat(getHeader(), wordCount, dialect, secMode, maxMpxC, maxVcs, maxBufSize, maxRawBuf,
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, dialect, secMode, maxMpxC, maxVcs, maxBufSize, maxRawBuf,
|
|
|
sessionKey, capabilities, sysTime, timeZone, keyLength, byteCount, guid, secBlob, oid,
|
|
|
protectNeg, negToken, mechType, mechType2);
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Evaluates what Dialects are offered by the client and which position the used NT LM 0.12 dialect is at
|
|
|
+ * @return position of the NT LM 0.12 dialect
|
|
|
+ */
|
|
|
private byte[] evaluateDialect() {
|
|
|
- byte[] dialectMsg = new byte[msg.length-39];
|
|
|
- System.arraycopy(msg, 39, dialectMsg, 0, msg.length - 39);
|
|
|
+ byte[] dialectMsg = new byte[message.length-39];
|
|
|
+ System.arraycopy(message, 39, dialectMsg, 0, message.length - 39);
|
|
|
short dialectNumber = 0;
|
|
|
for(int i = 0, start = 0; i < dialectMsg.length; i++) {
|
|
|
if(dialectMsg[i] == 0x00) {
|
|
@@ -292,6 +287,10 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
return new byte[]{0x00, 0x00};
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the session setup packet
|
|
|
+ * @return session setup packet
|
|
|
+ */
|
|
|
public byte[] getSessSetup() {
|
|
|
if(authenticateNext) return getSetupAuth();
|
|
|
else {
|
|
@@ -300,6 +299,10 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the setup challange packet
|
|
|
+ * @return setup challange packet
|
|
|
+ */
|
|
|
private byte[] getSetupChal() {
|
|
|
byte[] wordCount = {0x04};
|
|
|
byte[] andXCommand = {(byte) 0xff};
|
|
@@ -339,12 +342,16 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
ntStat = new byte[]{0x16, 0x00, 0x00, (byte) 0xc0};
|
|
|
userID = new byte[]{0x00, 0x08};
|
|
|
|
|
|
- byte[] response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
|
byteCount, secBlob, negToken, negResult, negToken2, supportedMech, negToken3,
|
|
|
respToken, challenge, respToken2, timeStamp, respToken3, nativOS, nativLanMngr);
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the setup authentication packet
|
|
|
+ * @return setup authentication packet
|
|
|
+ */
|
|
|
private byte[] getSetupAuth() {
|
|
|
byte[] wordCount = {0x04};
|
|
|
byte[] andXCommand = {(byte) 0xff};
|
|
@@ -364,11 +371,15 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x00, 0x00}; //Windows 7 Professional 6.1
|
|
|
|
|
|
|
|
|
- byte[] response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
|
byteCount, secBlob, nativOS, nativLanMngr);
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Builds the tree connect packet
|
|
|
+ * @return tree connect packet
|
|
|
+ */
|
|
|
public byte[] getTreeCon() {
|
|
|
String str = toString();
|
|
|
byte[] wordCount = {0x00};
|
|
@@ -389,19 +400,23 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
|
|
|
treeID = new byte[]{0x00, 0x08};
|
|
|
|
|
|
- response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, optionalSupport, maxShareAccess,
|
|
|
+ response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, optionalSupport, maxShareAccess,
|
|
|
guestMaxShareAccess, byteCount, service, extraParameters);
|
|
|
} else if(str.contains("C$") || str.contains("ADMIN$")) {
|
|
|
ntStat = new byte[] {0x22, 0x00, 0x00, (byte) 0xc0};
|
|
|
- response = concat(getHeader(), wordCount, andXCommand);
|
|
|
+ response = HelperUtils.concat(wordCount, andXCommand);
|
|
|
} else {
|
|
|
ntStat = new byte[] {(byte) 0xcc, 0x00, 0x00, (byte) 0xc0};
|
|
|
- response = concat(getHeader(), wordCount, andXCommand);
|
|
|
+ response = HelperUtils.concat(wordCount, andXCommand);
|
|
|
}
|
|
|
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the nt create packet
|
|
|
+ * @return nt create packet
|
|
|
+ */
|
|
|
public byte[] getNTCreate() {
|
|
|
byte[] wordCount = {0x22};
|
|
|
byte[] andXCommand = {(byte) 0xff};
|
|
@@ -422,12 +437,16 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
byte[] isDirectory = {0x00};
|
|
|
byte[] byteCount = {0x00, 0x00};
|
|
|
|
|
|
- byte[] response = concat(getHeader(), wordCount, andXCommand, reserved, andXOffset, oplockLevel, fid,
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, oplockLevel, fid,
|
|
|
createAction, created, lastAccess, lastWrite, change, fileAttributes, allocationSize,
|
|
|
endOfFile, fileType, ipcState, isDirectory, byteCount);
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the trans packet
|
|
|
+ * @return trans packet
|
|
|
+ */
|
|
|
public byte[] getTrans() {
|
|
|
byte[] transSub = getTransSub();
|
|
|
byte[] response = null;
|
|
@@ -454,7 +473,7 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
(byte) 0x88, (byte) 0x8a, (byte) 0xeb, 0x1c, (byte) 0xc9, 0x11, (byte) 0x9f, (byte) 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
|
|
|
0x00, 0x00};
|
|
|
|
|
|
- response = concat(getHeader(), wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
|
|
|
+ response = HelperUtils.concat(wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
|
|
|
paramDisplace, dataCount, dataOffset, dataDisplace, setupCount, reserved2, byteCount, padding, dcerpc);
|
|
|
|
|
|
} else if(transSub[0] == 0x00 && transSub[1] == 0x00) {
|
|
@@ -500,70 +519,120 @@ public final class SMB implements Protocol<ByteArray> {
|
|
|
byte[] resumeHandle = {0x00, 0x00, 0x00, 0x00};
|
|
|
byte[] windowsError = {0x00, 0x00, 0x00, 0x00};
|
|
|
|
|
|
- response = concat(getHeader(), wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
|
|
|
+ response = HelperUtils.concat(wordCount, totalParamCount, totalDataCount, reserved, paramCount, paramOffset,
|
|
|
paramDisplace, dataCount, dataOffset, dataDisplace, setupCount, reserved2, byteCount, padding, dcerpc,
|
|
|
serverService, totalEntries, referentID, resumeHandle, windowsError);
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the close packet
|
|
|
+ * @return close packet
|
|
|
+ */
|
|
|
public byte[] getClose() {
|
|
|
byte[] wordCount = {0x00};
|
|
|
byte[] byteCount = {0x00, 0x00};
|
|
|
|
|
|
smbCommand = new byte[]{0x04};
|
|
|
|
|
|
- byte[] response = concat(getHeader(), wordCount, byteCount);
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, byteCount);
|
|
|
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the tree disconnect packet
|
|
|
+ * @return tree disconnect packet
|
|
|
+ */
|
|
|
public byte[] getTreeDisc() {
|
|
|
byte[] wordCount = {0x00};
|
|
|
byte[] byteCount = {0x00, 0x00};
|
|
|
|
|
|
smbCommand[0] = 0x71;
|
|
|
|
|
|
- byte[] response = concat(getHeader(), wordCount, byteCount);
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, byteCount);
|
|
|
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the echo packet
|
|
|
+ * @return echo packet
|
|
|
+ */
|
|
|
public byte[] getEcho() {
|
|
|
byte[] wordCount = {0x01};
|
|
|
byte[] echoSeq = {0x01, 0x00};
|
|
|
byte[] byteCount = {0x10, 0x00};
|
|
|
byte[] echoData = {(byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0,
|
|
|
(byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0};
|
|
|
- byte[] response = concat(getHeader(), wordCount, echoSeq, byteCount, echoData);
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ byte[] response = HelperUtils.concat(wordCount, echoSeq, byteCount, echoData);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Builds the trans2 packet
|
|
|
+ * @return trans2 packet
|
|
|
+ */
|
|
|
public byte[] getTrans2() {
|
|
|
byte[] response = null;
|
|
|
byte[] wordCount = {0x00};
|
|
|
byte[] andXCommand = {0x00, 0x00};
|
|
|
ntStat = new byte[] {0x22, 0x00, 0x00, (byte) 0xc0};
|
|
|
- response = concat(getHeader(), wordCount, andXCommand);
|
|
|
- return concat(getNetbios(response), response);
|
|
|
+ response = HelperUtils.concat(wordCount, andXCommand);
|
|
|
+ return wrapNetbios(wrapHeader(response));
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Builds the trans sub packet
|
|
|
+ * @return trans sub packet
|
|
|
+ */
|
|
|
private byte[] getTransSub() {
|
|
|
byte[] transSub = new byte[2];
|
|
|
- if(smbCommand[0] == 0x32) transSub = new byte[]{msg[66], msg[65]};
|
|
|
- else if(smbCommand[0] == 0x25) transSub = new byte[]{0x00, msg[90]};
|
|
|
+ if(smbCommand[0] == 0x32) transSub = new byte[]{message[66], message[65]};
|
|
|
+ else if(smbCommand[0] == 0x25) transSub = new byte[]{0x00, message[90]};
|
|
|
else transSub = new byte[]{0x00, 0x00};
|
|
|
return transSub;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ @Override
|
|
|
public String toString() {
|
|
|
- return byteToStr(msg);
|
|
|
+ return byteToStr(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Converts a byte[] to a String, but only characters in ASCII between 32 and 127
|
|
|
+ * @param bytes that are converted
|
|
|
+ * @return converted String
|
|
|
+ */
|
|
|
+ private String byteToStr(byte[] bytes) {
|
|
|
+ char[] chars = new char[bytes.length];
|
|
|
+ for (int i = 0, j = 0; i < bytes.length && j < chars.length; i++) {
|
|
|
+ if (isLetter((char) bytes[i])) {
|
|
|
+ chars[j] = (char) bytes[i];
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new String(chars);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Determines if a character is in ASCII between 32 and 127
|
|
|
+ * @param character that is checked
|
|
|
+ * @return true if the character is between 32 and 127, else false
|
|
|
+ */
|
|
|
+ private boolean isLetter(char character) {
|
|
|
+ return (character >= 32 && character <= 127);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns the command number from the current message
|
|
|
+ * @return command number
|
|
|
+ */
|
|
|
public byte getSmbCommand() {
|
|
|
return smbCommand[0];
|
|
|
}
|