diff --git a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java index 8c0c360417..c39e9bb42f 100644 --- a/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java +++ b/android/sdl_android/src/androidTest/java/com/smartdevicelink/test/protocol/SecurityQueryPayloadTests.java @@ -25,7 +25,7 @@ public static SecurityQueryPayload createDummyBqh() { bqh.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA); bqh.setQueryType(SecurityQueryType.REQUEST); bqh.setBulkData(null); - bqh.setJsonSize(0); + bqh.setJsonData(null); return bqh; } @@ -66,9 +66,9 @@ public void testCorrectHeaderAssembly() { dummyBqh.setQueryType(SecurityQueryType.REQUEST); dummyBqh.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA); dummyBqh.setCorrelationID(3); - dummyBqh.setJsonSize(0); + dummyBqh.setJsonData(new byte[0]); - byte[] assembledHeader = dummyBqh.assembleHeaderBytes(); + byte[] assembledHeader = dummyBqh.assembleBinaryData(); assertEquals(dummyBqh.getQueryType(), SecurityQueryType.valueOf(assembledHeader[0])); byte[] queryIDFromHeader = new byte[3]; System.arraycopy(assembledHeader, 1, queryIDFromHeader, 0, 3); @@ -81,7 +81,7 @@ public void testCorrectHeaderAssembly() { public void testAssemblyAndParse() { SecurityQueryPayload bqh = createDummyBqh(); - byte[] bqhBytes = bqh.assembleHeaderBytes(); + byte[] bqhBytes = bqh.assembleBinaryData(); assertNotNull(bqhBytes); SecurityQueryPayload parsedBqh = SecurityQueryPayload.parseBinaryQueryHeader(bqhBytes); @@ -99,7 +99,7 @@ public void testAssemblyAndParse() { public void testCorruptHeader() { SecurityQueryPayload bqh = createDummyBqh(); - byte[] bqhBytes = bqh.assembleHeaderBytes(); + byte[] bqhBytes = bqh.assembleBinaryData(); assertNotNull(safeParse(bqhBytes)); @@ -114,13 +114,18 @@ public void testCorruptHeader() { } @Test - public void testJsonSetException() { - try { - SecurityQueryPayload bqh = createDummyBqh(); - bqh.setJsonData(null); - fail("Setting JSON data to null should have thrown an exception"); - } catch (Exception e) { - //Pass - } + public void testNullJsonData() { + SecurityQueryPayload bqh = createDummyBqh(); + bqh.setJsonData(null); + assertEquals(0, bqh.getJsonSize()); + assertEquals(null, bqh.getJsonData()); + } + + @Test + public void testNullBulkData() { + SecurityQueryPayload bqh = createDummyBqh(); + bqh.setBulkData(null); + assertEquals(0, bqh.getBulkDataSize()); + assertEquals(null, bqh.getBulkData()); } } diff --git a/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java b/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java index c7bc1326d9..a41052c0da 100644 --- a/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java +++ b/base/src/main/java/com/smartdevicelink/protocol/SecurityQueryPayload.java @@ -16,7 +16,7 @@ public class SecurityQueryPayload { private SecurityQueryID _securityQueryID; private int _correlationID; private int _jsonSize; - private SecurityQueryErrorCode _errorCode; + private int _bulkDataSize; private byte[] _jsonData = null; private byte[] _bulkData = null; @@ -51,11 +51,6 @@ public static SecurityQueryPayload parseBinaryQueryHeader(byte[] binHeader) { int _jsonSize = BitConverter.intFromByteArray(binHeader, 8); msg.setJsonSize(_jsonSize); - //If we get an error message we want the error code from the last 8 bits - if (msg.getQueryType() == SecurityQueryType.NOTIFICATION && msg.getQueryID() == SecurityQueryID.SEND_INTERNAL_ERROR) { - msg.setErrorCode(SecurityQueryErrorCode.valueOf(binHeader[binHeader.length - 1])); - } - try { //Get the JsonData after the header (after 96 bits) based on the jsonData size if (_jsonSize > 0 && _jsonSize <= (binHeader.length - SECURITY_QUERY_HEADER_SIZE)) { @@ -84,18 +79,28 @@ public static SecurityQueryPayload parseBinaryQueryHeader(byte[] binHeader) { return msg; } - public byte[] assembleHeaderBytes() { + public byte[] assembleBinaryData() { // From the properties, create a data buffer // Query Type - first 8 bits // Query ID - next 24 bits // Sequence Number - next 32 bits // JSON size - next 32 bits - byte[] ret = new byte[SECURITY_QUERY_HEADER_SIZE]; - ret[0] = _securityQueryType.getValue(); - System.arraycopy(_securityQueryID.getValue(), 0, ret, 1, 3); - System.arraycopy(BitConverter.intToByteArray(_correlationID), 0, ret, 4, 4); - System.arraycopy(BitConverter.intToByteArray(_jsonSize), 0, ret, 8, 4); - return ret; + byte[] header = new byte[SECURITY_QUERY_HEADER_SIZE]; + header[0] = _securityQueryType.getValue(); + System.arraycopy(_securityQueryID.getValue(), 0, header, 1, 3); + System.arraycopy(BitConverter.intToByteArray(_correlationID), 0, header, 4, 4); + System.arraycopy(BitConverter.intToByteArray(_jsonSize), 0, header, 8, 4); + + int size = _jsonSize + _bulkDataSize + SECURITY_QUERY_HEADER_SIZE; + byte[] dataOut = new byte[size]; + System.arraycopy(header, 0, dataOut, 0, SECURITY_QUERY_HEADER_SIZE); + if (_jsonData != null) { + System.arraycopy(_jsonData, 0, dataOut, SECURITY_QUERY_HEADER_SIZE, _jsonSize); + } + if (_bulkData != null) { + System.arraycopy(_bulkData, 0, dataOut, SECURITY_QUERY_HEADER_SIZE + _jsonSize, _bulkDataSize); + } + return dataOut; } public SecurityQueryType getQueryType() { @@ -126,16 +131,16 @@ public int getJsonSize() { return _jsonSize; } - public void setJsonSize(int _jsonSize) { + private void setJsonSize(int _jsonSize) { this._jsonSize = _jsonSize; } - public SecurityQueryErrorCode getErrorCode() { - return _errorCode; + public int getBulkDataSize() { + return _bulkDataSize; } - public void setErrorCode(SecurityQueryErrorCode _errorCode) { - this._errorCode = _errorCode; + private void setBulkDataSize(int _bulkDataSize) { + this._bulkDataSize = _bulkDataSize; } public byte[] getJsonData() { @@ -143,6 +148,12 @@ public byte[] getJsonData() { } public void setJsonData(byte[] _jsonData) { + if (_jsonData == null) { + this._jsonSize = 0; + this._jsonData = null; + return; + } + this._jsonSize = _jsonData.length; this._jsonData = new byte[this._jsonSize]; System.arraycopy(_jsonData, 0, this._jsonData, 0, _jsonSize); } @@ -152,6 +163,13 @@ public byte[] getBulkData() { } public void setBulkData(byte[] _bulkData) { - this._bulkData = _bulkData; + if(_bulkData == null) { + this._bulkDataSize = 0; + this._bulkData = null; + return; + } + this._bulkDataSize = _bulkData.length; + this._bulkData = new byte[this._bulkDataSize]; + System.arraycopy(_bulkData, 0, this._bulkData, 0, _bulkDataSize); } } diff --git a/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java b/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java index 5fcc8d8cac..a33d3eb048 100644 --- a/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java +++ b/base/src/main/java/com/smartdevicelink/session/BaseSdlSession.java @@ -44,6 +44,7 @@ import com.smartdevicelink.protocol.SdlPacket; import com.smartdevicelink.protocol.SdlProtocolBase; import com.smartdevicelink.protocol.enums.ControlFrameTags; +import com.smartdevicelink.protocol.enums.SecurityQueryErrorCode; import com.smartdevicelink.protocol.enums.SecurityQueryID; import com.smartdevicelink.protocol.enums.SecurityQueryType; import com.smartdevicelink.protocol.enums.SessionType; @@ -61,7 +62,9 @@ import com.smartdevicelink.util.SystemInfo; import com.smartdevicelink.util.Version; -import java.util.ArrayList; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.HashMap; import java.util.List; import java.util.ListIterator; @@ -217,8 +220,8 @@ protected void processControlService(ProtocolMessage msg) { // If the query is of type `Notification` and the id represents a client internal error, we abort the response message and the encryptionManager will not be in state ready. if (receivedHeader.getQueryID() == SecurityQueryID.SEND_INTERNAL_ERROR && receivedHeader.getQueryType() == SecurityQueryType.NOTIFICATION) { - if (receivedHeader.getErrorCode() != null) { - DebugTool.logError(TAG, "Security Query module internal error: " + receivedHeader.getErrorCode().getName()); + if (receivedHeader.getBulkData() != null && receivedHeader.getBulkDataSize() == 1) { + DebugTool.logError(TAG, "Security Query module internal error: " + SecurityQueryErrorCode.valueOf(receivedHeader.getBulkData()[0]).getName()); } else { DebugTool.logError(TAG, "Security Query module error: No information provided"); } @@ -237,29 +240,28 @@ protected void processControlService(ProtocolMessage msg) { iNumBytes = sdlSecurity.runHandshake(data, dataToRead); - // Assemble a security query payload header for our response - SecurityQueryPayload responseHeader = new SecurityQueryPayload(); - - byte[] returnBytes; + ProtocolMessage protocolMessage; if (iNumBytes == null || iNumBytes <= 0) { DebugTool.logError(TAG, "Internal Error processing control service"); - - responseHeader.setQueryID(SecurityQueryID.SEND_INTERNAL_ERROR); - responseHeader.setQueryType(SecurityQueryType.NOTIFICATION); - responseHeader.setCorrelationID(msg.getCorrID()); - responseHeader.setJsonSize(0); - returnBytes = new byte[12]; + protocolMessage = serverSecurityFailedMessageWithClientMessageHeader(msg.getCorrID()); } else { - responseHeader.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA); - responseHeader.setQueryType(SecurityQueryType.RESPONSE); - responseHeader.setCorrelationID(msg.getCorrID()); - responseHeader.setJsonSize(0); - returnBytes = new byte[iNumBytes + 12]; - System.arraycopy(dataToRead, 0, returnBytes, 12, iNumBytes); + protocolMessage = serverSecurityHandshakeMessageWithData(msg.getCorrID(), dataToRead); } + //sdlSecurity.hs(); + + sendMessage(protocolMessage); + } + + private ProtocolMessage serverSecurityHandshakeMessageWithData(int correlationId, byte[] bulkData) { + SecurityQueryPayload responseHeader = new SecurityQueryPayload(); + responseHeader.setQueryID(SecurityQueryID.SEND_HANDSHAKE_DATA); + responseHeader.setQueryType(SecurityQueryType.RESPONSE); + responseHeader.setCorrelationID(correlationId); + responseHeader.setBulkData(bulkData); + responseHeader.setJsonData(null); - System.arraycopy(responseHeader.assembleHeaderBytes(), 0, returnBytes, 0, 12); + byte[] returnBytes = responseHeader.assembleBinaryData(); ProtocolMessage protocolMessage = new ProtocolMessage(); protocolMessage.setSessionType(SessionType.CONTROL); @@ -268,9 +270,40 @@ protected void processControlService(ProtocolMessage msg) { protocolMessage.setVersion((byte) sdlProtocol.getProtocolVersion().getMajor()); protocolMessage.setSessionID((byte) this.sessionId); - //sdlSecurity.hs(); + return protocolMessage; + } - sendMessage(protocolMessage); + private ProtocolMessage serverSecurityFailedMessageWithClientMessageHeader(int correlationId) { + SecurityQueryPayload responseHeader = new SecurityQueryPayload(); + responseHeader.setQueryID(SecurityQueryID.SEND_INTERNAL_ERROR); + responseHeader.setQueryType(SecurityQueryType.NOTIFICATION); + responseHeader.setCorrelationID(correlationId); + byte[] jsonData; + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("id", SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR.getValue()); + jsonObject.put("text", SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR.getName()); + jsonData = jsonObject.toString().getBytes(); + } catch (JSONException e) { + DebugTool.logError(TAG, "JSON exception when constructing handshake error Notification"); + e.printStackTrace(); + jsonData = new byte[0]; + } + responseHeader.setJsonData(jsonData); + byte[] errorCode = new byte[1]; + errorCode[0] = SecurityQueryErrorCode.ERROR_UNKNOWN_INTERNAL_ERROR.getValue(); + responseHeader.setBulkData(errorCode); + + byte[] returnBytes = responseHeader.assembleBinaryData(); + + ProtocolMessage protocolMessage = new ProtocolMessage(); + protocolMessage.setSessionType(SessionType.CONTROL); + protocolMessage.setData(returnBytes); + protocolMessage.setFunctionID(0x01); + protocolMessage.setVersion((byte) sdlProtocol.getProtocolVersion().getMajor()); + protocolMessage.setSessionID((byte) this.sessionId); + + return protocolMessage; } /**