From d8f964ac7c3f6524e2c594367197a93aa5168414 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 19 Oct 2017 15:09:17 +0200 Subject: [PATCH] - MMS server: ACSE authenticator passes application reference (ap-title and ae-qualifier) --- .../server_example_password_auth.c | 23 ++++++- src/mms/asn1/ber_decode.c | 69 ++++++++++--------- src/mms/inc/iso_connection_parameters.h | 13 +--- src/mms/inc/mms_common.h | 11 +++ src/mms/inc_private/acse.h | 1 + src/mms/inc_private/ber_decode.h | 3 + src/mms/iso_acse/acse.c | 26 ++++++- 7 files changed, 98 insertions(+), 48 deletions(-) diff --git a/examples/server_example_password_auth/server_example_password_auth.c b/examples/server_example_password_auth/server_example_password_auth.c index 6c6661c..2551ac8 100644 --- a/examples/server_example_password_auth/server_example_password_auth.c +++ b/examples/server_example_password_auth/server_example_password_auth.c @@ -37,13 +37,34 @@ void sigint_handler(int signalId) static char* password1 = "user1@testpw"; static char* password2 = "user2@testpw"; +static void printAppTitle(ItuObjectIdentifier* oid) +{ + int i; + + for (i = 0; i < oid->arcCount; i++) { + printf("%i", oid->arc[i]); + + if (i != (oid->arcCount - 1)) + printf("."); + } + + printf("\n"); +} + /** * This is the AcseAuthenticator callback function that is invoked on each client connection attempt. * When returning true the server stack accepts the client. Otherwise the connection is rejected. + * + * The security token can be used to pass an application specific object to other library callbacks */ static bool -clientAuthenticator(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken) +clientAuthenticator(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken, IsoApplicationReference* appRef) { + printf("ACSE Authenticator:\n"); + printf(" client ap-title: "); printAppTitle(&(appRef->apTitle)); printf("\n"); + printf(" client ae-qualifier: %i\n", appRef->aeQualifier); + + if (authParameter->mechanism == ACSE_AUTH_PASSWORD) { if (authParameter->value.password.passwordLength == strlen(password1)) { if (memcmp(authParameter->value.password.octetString, password1, diff --git a/src/mms/asn1/ber_decode.c b/src/mms/asn1/ber_decode.c index 3818899..32be397 100644 --- a/src/mms/asn1/ber_decode.c +++ b/src/mms/asn1/ber_decode.c @@ -89,39 +89,6 @@ BerDecoder_decodeUint32(uint8_t* buffer, int intLen, int bufPos) return value; } -#if 0 -int32_t -BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos) -{ - int32_t value = 0; - - bool isNegative = ((buffer[bufPos] & 0x80) == 0x80); - - int i = 0; - - if (isNegative) { - for (i = 0; i < 4; i++) { - - value <<= 8; - - if (i < (4 - intlen)) - value += 0xff; - else - value += buffer[bufPos + i - (4 - intlen)]; - } - } - else { - for (i = 0; i < intlen; i++) { - value <<= 8; - value += buffer[bufPos + i]; - } - } - - return value; -} -#endif - -#if 1 int32_t BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos) { @@ -142,7 +109,6 @@ BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos) return value; } -#endif float BerDecoder_decodeFloat(uint8_t* buffer, int bufPos) @@ -197,3 +163,38 @@ BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos) { else return false; } + +void +BerDecoder_decodeOID(uint8_t* buffer, int bufPos, int length, ItuObjectIdentifier* oid) +{ + int startPos = bufPos; + int currentArc = 0; + + /* clear all arcs */ + int i; + for (i = 0; i < 10; i++) + oid->arc[i] = 0; + + /* parse first two arcs */ + if (length > 0) { + oid->arc[0] = buffer[bufPos] / 40; + oid->arc[1] = buffer[bufPos] % 40; + + currentArc = 2; + bufPos++; + } + + /* parse remaining arcs */ + while ((bufPos - startPos < length) && (currentArc < 10)) { + oid->arc[currentArc] = oid->arc[currentArc]<<7; + + if (buffer[bufPos] < 0x80) + oid->arc[currentArc++] += buffer[bufPos]; + else + oid->arc[currentArc] += (buffer[bufPos] & 0x7f); + + bufPos++; + } + + oid->arcCount = currentArc; +} diff --git a/src/mms/inc/iso_connection_parameters.h b/src/mms/inc/iso_connection_parameters.h index 539ba3e..6ab2270 100644 --- a/src/mms/inc/iso_connection_parameters.h +++ b/src/mms/inc/iso_connection_parameters.h @@ -48,16 +48,6 @@ typedef enum } AcseAuthenticationMechanism; -/* --> for compatibility with older versions (libiec61850 < 0.7.7) */ -#ifndef AUTH_NONE -#define AUTH_NONE ACSE_AUTH_NONE -#endif - -#ifndef AUTH_PASSWORD -#define AUTH_PASSWORD ACSE_AUTH_PASSWORD -#endif -/* <-- for compatibility with older versions (libiec61850 < 0.7.7) */ - typedef struct sAcseAuthenticationParameter* AcseAuthenticationParameter; struct sAcseAuthenticationParameter @@ -99,11 +89,12 @@ AcseAuthenticationParameter_setPassword(AcseAuthenticationParameter self, char* * \param parameter user provided parameter - set when user registers the authenticator * \param authParameter the authentication parameters provided by the client * \param securityToken pointer where to store an application specific security token - can be ignored if not used. + * \param appReference ISO application reference (ap-title + ae-qualifier) * * \return true if client connection is accepted, false otherwise */ typedef bool -(*AcseAuthenticator)(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken); +(*AcseAuthenticator)(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken, IsoApplicationReference* appReference); /** * \brief COTP T selector diff --git a/src/mms/inc/mms_common.h b/src/mms/inc/mms_common.h index 10e3537..0c3832e 100644 --- a/src/mms/inc/mms_common.h +++ b/src/mms/inc/mms_common.h @@ -155,6 +155,17 @@ typedef struct typedef struct sMmsNamedVariableList* MmsNamedVariableList; typedef struct sMmsAccessSpecifier* MmsNamedVariableListEntry; + +typedef struct { + uint16_t arc[10]; + int arcCount; +} ItuObjectIdentifier; + +typedef struct { + ItuObjectIdentifier apTitle; + int aeQualifier; +} IsoApplicationReference; + /**@}*/ diff --git a/src/mms/inc_private/acse.h b/src/mms/inc_private/acse.h index 4282508..9b36bd3 100644 --- a/src/mms/inc_private/acse.h +++ b/src/mms/inc_private/acse.h @@ -54,6 +54,7 @@ typedef struct sAcseConnection int userDataBufferSize; AcseAuthenticationParameter authentication; AcseAuthenticator authenticator; + IsoApplicationReference applicationReference; void* authenticatorParameter; void* securityToken; } AcseConnection; diff --git a/src/mms/inc_private/ber_decode.h b/src/mms/inc_private/ber_decode.h index 8bdbcc3..56f3ed2 100644 --- a/src/mms/inc_private/ber_decode.h +++ b/src/mms/inc_private/ber_decode.h @@ -46,4 +46,7 @@ BerDecoder_decodeDouble(uint8_t* buffer, int bufPos); bool BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos); +void +BerDecoder_decodeOID(uint8_t* buffer, int bufPos, int length, ItuObjectIdentifier* oid); + #endif /* BER_DECODER_H_ */ diff --git a/src/mms/iso_acse/acse.c b/src/mms/iso_acse/acse.c index 76b6f7a..7b872dc 100644 --- a/src/mms/iso_acse/acse.c +++ b/src/mms/iso_acse/acse.c @@ -69,7 +69,10 @@ authenticateClient(AcseConnection* self, AcseAuthenticationMechanism mechanism, authParameter->value.password.passwordLength = authValueLen; } - return self->authenticator(self->authenticatorParameter, authParameter, &(self->securityToken)); + //TODO Check if we are in a TLS connection: if mechanism == ACSE_AUTH_NONE provide client certificate if present + // --> mechanism = ACSE_AUTH_TLS + + return self->authenticator(self->authenticatorParameter, authParameter, &(self->securityToken), &(self->applicationReference)); } static bool @@ -241,10 +244,28 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos) break; case 0xa6: /* calling AP title */ - bufPos += len; + { + if (buffer[bufPos] == 0x06) { /* ap-title-form2 */ + + int innerLength = buffer[bufPos+1]; + + if (innerLength == len - 2) + BerDecoder_decodeOID(buffer, bufPos + 2, innerLength, &(self->applicationReference.apTitle)); + } + } + bufPos += len; break; case 0xa7: /* calling AE qualifier */ + { + if (buffer[bufPos] == 0x02) { /* ae-qualifier-form2 */ + + int innerLength = buffer[bufPos+1]; + + if (innerLength == len - 2) + self->applicationReference.aeQualifier = BerDecoder_decodeInt32(buffer + 2, buffer[bufPos+1], bufPos); + } + } bufPos += len; break; @@ -315,6 +336,7 @@ AcseConnection_init(AcseConnection* self, AcseAuthenticator authenticator, void* self->userDataBufferSize = 0; self->authenticator= authenticator; self->authenticatorParameter = parameter; + memset(&(self->applicationReference), 0, sizeof(self->applicationReference)); } void