libwinpr-sspi: parse CredSSP plaintext credentials
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 24 May 2012 19:52:20 +0000 (15:52 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 24 May 2012 19:52:20 +0000 (15:52 -0400)
include/freerdp/crypto/ber.h
libfreerdp-core/mcs.c
libfreerdp-crypto/ber.c
winpr/sspi/CredSSP/credssp.c

index b82a7ee..4823982 100644 (file)
@@ -70,8 +70,8 @@ FREERDP_API int ber_write_sequence_tag(STREAM* s, int length);
 FREERDP_API int ber_skip_sequence(int length);
 FREERDP_API int ber_skip_sequence_tag(int length);
 FREERDP_API boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding);
-FREERDP_API boolean ber_read_octet_string(STREAM* s, int* length);
 FREERDP_API void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length);
+FREERDP_API boolean ber_read_octet_string_tag(STREAM* s, int* length);
 FREERDP_API int ber_write_octet_string_tag(STREAM* s, int length);
 FREERDP_API int ber_skip_octet_string(int length);
 FREERDP_API boolean ber_read_boolean(STREAM* s, boolean* value);
index 79ea2ac..5b927d1 100644 (file)
@@ -331,12 +331,12 @@ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s)
                return false;
 
        /* callingDomainSelector (OCTET_STRING) */
-       if (!ber_read_octet_string(s, &length))
+       if (!ber_read_octet_string_tag(s, &length))
                return false;
        stream_seek(s, length);
 
        /* calledDomainSelector (OCTET_STRING) */
-       if (!ber_read_octet_string(s, &length))
+       if (!ber_read_octet_string_tag(s, &length))
                return false;
        stream_seek(s, length);
 
@@ -353,7 +353,7 @@ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s)
        /* maximumParameters (DomainParameters) */
        mcs_read_domain_parameters(s, &mcs->maximumParameters);
 
-       if (!ber_read_octet_string(s, &length))
+       if (!ber_read_octet_string_tag(s, &length))
                return false;
 
        if (!gcc_read_conference_create_request(s, mcs->transport->settings))
@@ -499,7 +499,7 @@ boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s)
        if (!mcs_read_domain_parameters(s, &(mcs->domainParameters)))
                return false;
 
-       ber_read_octet_string(s, &length);
+       ber_read_octet_string_tag(s, &length);
 
        if (!gcc_read_conference_create_response(s, mcs->transport->settings))
        {
index b399056..0b30879 100644 (file)
@@ -267,14 +267,6 @@ boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding)
        return true;
 }
 
-boolean ber_read_octet_string(STREAM* s, int* length)
-{
-       ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false);
-       ber_read_length(s, length);
-
-       return true;
-}
-
 /**
  * Write a BER OCTET_STRING
  * @param s stream
@@ -289,6 +281,13 @@ void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length)
        stream_write(s, oct_str, length);
 }
 
+boolean ber_read_octet_string_tag(STREAM* s, int* length)
+{
+       ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false);
+       ber_read_length(s, length);
+       return true;
+}
+
 int ber_write_octet_string_tag(STREAM* s, int length)
 {
        ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false);
index 9a48e7b..2c47583 100644 (file)
@@ -712,85 +712,6 @@ SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp)
        return SEC_E_OK;
 }
 
-SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
-{
-       BYTE* p;
-       SecBuffer Buffers[2];
-       SecBufferDesc Message;
-       SECURITY_STATUS status;
-
-       credssp_encode_ts_credentials(credssp);
-
-       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
-       Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
-
-       Buffers[0].cbBuffer = 16;
-       Buffers[0].pvBuffer = xzalloc(Buffers[0].cbBuffer);
-
-       Buffers[1].cbBuffer = credssp->ts_credentials.cbBuffer;
-       Buffers[1].pvBuffer = xmalloc(Buffers[1].cbBuffer);
-       CopyMemory(Buffers[1].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[1].cbBuffer);
-
-       Message.cBuffers = 2;
-       Message.ulVersion = SECBUFFER_VERSION;
-       Message.pBuffers = (PSecBuffer) &Buffers;
-
-       sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
-
-       status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 1);
-
-       if (status != SEC_E_OK)
-               return status;
-
-       p = (BYTE*) credssp->authInfo.pvBuffer;
-       CopyMemory(p, Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Message Signature */
-       CopyMemory(&p[Buffers[0].cbBuffer], Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Encrypted TSCredentials */
-
-       xfree(Buffers[0].pvBuffer);
-       xfree(Buffers[1].pvBuffer);
-
-       return SEC_E_OK;
-}
-
-SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp)
-{
-       BYTE* p;
-       SecBuffer Buffers[2];
-       SecBufferDesc Message;
-       SECURITY_STATUS status;
-
-       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
-       Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
-
-       Buffers[0].cbBuffer = 16;
-       Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer);
-       CopyMemory(Buffers[0].pvBuffer, credssp->authInfo.pvBuffer, Buffers[0].cbBuffer);
-
-       Buffers[1].cbBuffer = credssp->authInfo.cbBuffer - Buffers[0].cbBuffer;
-       Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer);
-       p = (BYTE*) credssp->authInfo.pvBuffer;
-       CopyMemory(Buffers[1].pvBuffer, &p[Buffers[0].cbBuffer], Buffers[1].cbBuffer);
-
-       Message.cBuffers = 2;
-       Message.ulVersion = SECBUFFER_VERSION;
-       Message.pBuffers = (PSecBuffer) &Buffers;
-
-       sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
-
-       status = credssp->table->DecryptMessage(&credssp->context, &Message, 1, 0);
-
-       freerdp_hexdump(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
-       freerdp_hexdump(Buffers[1].pvBuffer, Buffers[1].cbBuffer);
-
-       if (status != SEC_E_OK)
-               return status;
-
-       free(Buffers[0].pvBuffer);
-       free(Buffers[1].pvBuffer);
-
-       return SEC_E_OK;
-}
-
 int credssp_skip_ts_password_creds(rdpCredssp* credssp)
 {
        int length;
@@ -813,6 +734,38 @@ int credssp_skip_ts_password_creds(rdpCredssp* credssp)
        return length;
 }
 
+void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s)
+{
+       int length;
+
+       /* TSPasswordCreds (SEQUENCE) */
+       ber_read_sequence_tag(s, &length);
+
+       /* [0] domainName (OCTET STRING) */
+       ber_read_contextual_tag(s, 0, &length, true);
+       ber_read_octet_string_tag(s, &length);
+       credssp->identity.DomainLength = (uint32) length;
+       credssp->identity.Domain = (uint16*) malloc(length);
+       CopyMemory(credssp->identity.Domain, s->p, credssp->identity.DomainLength);
+       stream_seek(s, credssp->identity.DomainLength);
+
+       /* [1] userName (OCTET STRING) */
+       ber_read_contextual_tag(s, 1, &length, true);
+       ber_read_octet_string_tag(s, &length);
+       credssp->identity.UserLength = (uint32) length;
+       credssp->identity.User = (uint16*) malloc(length);
+       CopyMemory(credssp->identity.User, s->p, credssp->identity.UserLength);
+       stream_seek(s, credssp->identity.UserLength);
+
+       /* [2] password (OCTET STRING) */
+       ber_read_contextual_tag(s, 2, &length, true);
+       ber_read_octet_string_tag(s, &length);
+       credssp->identity.PasswordLength = (uint32) length;
+       credssp->identity.Password = (uint16*) malloc(length);
+       CopyMemory(credssp->identity.Password, s->p, credssp->identity.PasswordLength);
+       stream_seek(s, credssp->identity.PasswordLength);
+}
+
 void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
 {
        int length;
@@ -825,15 +778,15 @@ void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
 
        /* [0] domainName (OCTET STRING) */
        ber_write_contextual_tag(s, 0, credssp->identity.DomainLength + 2, true);
-       ber_write_octet_string(s, (uint8*) credssp->identity.Domain, credssp->identity.DomainLength);
+       ber_write_octet_string(s, (BYTE*) credssp->identity.Domain, credssp->identity.DomainLength);
 
        /* [1] userName (OCTET STRING) */
        ber_write_contextual_tag(s, 1, credssp->identity.UserLength + 2, true);
-       ber_write_octet_string(s, (uint8*) credssp->identity.User, credssp->identity.UserLength);
+       ber_write_octet_string(s, (BYTE*) credssp->identity.User, credssp->identity.UserLength);
 
        /* [2] password (OCTET STRING) */
        ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength + 2, true);
-       ber_write_octet_string(s, (uint8*) credssp->identity.Password, credssp->identity.PasswordLength);
+       ber_write_octet_string(s, (BYTE*) credssp->identity.Password, credssp->identity.PasswordLength);
 }
 
 int credssp_skip_ts_credentials(rdpCredssp* credssp)
@@ -856,6 +809,32 @@ int credssp_skip_ts_credentials(rdpCredssp* credssp)
        return length;
 }
 
+void credssp_read_ts_credentials(rdpCredssp* credssp, PSecBuffer ts_credentials)
+{
+       STREAM* s;
+       int length;
+       int ts_password_creds_length;
+
+       s = stream_new(0);
+       stream_attach(s, ts_credentials->pvBuffer, ts_credentials->cbBuffer);
+
+       /* TSCredentials (SEQUENCE) */
+       ber_read_sequence_tag(s, &length);
+
+       /* [0] credType (INTEGER) */
+       ber_read_contextual_tag(s, 0, &length, true);
+       ber_read_integer(s, NULL);
+
+       /* [1] credentials (OCTET STRING) */
+       ber_read_contextual_tag(s, 1, &length, true);
+       ber_read_octet_string_tag(s, &ts_password_creds_length);
+
+       credssp_read_ts_password_creds(credssp, s);
+
+       stream_detach(s);
+       stream_free(s);
+}
+
 void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s)
 {
        int length;
@@ -900,6 +879,84 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp)
        stream_free(s);
 }
 
+SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
+{
+       BYTE* p;
+       SecBuffer Buffers[2];
+       SecBufferDesc Message;
+       SECURITY_STATUS status;
+
+       credssp_encode_ts_credentials(credssp);
+
+       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
+       Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
+
+       Buffers[0].cbBuffer = 16;
+       Buffers[0].pvBuffer = xzalloc(Buffers[0].cbBuffer);
+
+       Buffers[1].cbBuffer = credssp->ts_credentials.cbBuffer;
+       Buffers[1].pvBuffer = xmalloc(Buffers[1].cbBuffer);
+       CopyMemory(Buffers[1].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[1].cbBuffer);
+
+       Message.cBuffers = 2;
+       Message.ulVersion = SECBUFFER_VERSION;
+       Message.pBuffers = (PSecBuffer) &Buffers;
+
+       sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
+
+       status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 1);
+
+       if (status != SEC_E_OK)
+               return status;
+
+       p = (BYTE*) credssp->authInfo.pvBuffer;
+       CopyMemory(p, Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Message Signature */
+       CopyMemory(&p[Buffers[0].cbBuffer], Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Encrypted TSCredentials */
+
+       xfree(Buffers[0].pvBuffer);
+       xfree(Buffers[1].pvBuffer);
+
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp)
+{
+       BYTE* p;
+       SecBuffer Buffers[2];
+       SecBufferDesc Message;
+       SECURITY_STATUS status;
+
+       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
+       Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
+
+       Buffers[0].cbBuffer = 16;
+       Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer);
+       CopyMemory(Buffers[0].pvBuffer, credssp->authInfo.pvBuffer, Buffers[0].cbBuffer);
+
+       Buffers[1].cbBuffer = credssp->authInfo.cbBuffer - Buffers[0].cbBuffer;
+       Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer);
+       p = (BYTE*) credssp->authInfo.pvBuffer;
+       CopyMemory(Buffers[1].pvBuffer, &p[Buffers[0].cbBuffer], Buffers[1].cbBuffer);
+
+       Message.cBuffers = 2;
+       Message.ulVersion = SECBUFFER_VERSION;
+       Message.pBuffers = (PSecBuffer) &Buffers;
+
+       sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer);
+
+       status = credssp->table->DecryptMessage(&credssp->context, &Message, 1, 0);
+
+       if (status != SEC_E_OK)
+               return status;
+
+       credssp_read_ts_credentials(credssp, &Buffers[1]);
+
+       free(Buffers[0].pvBuffer);
+       free(Buffers[1].pvBuffer);
+
+       return SEC_E_OK;
+}
+
 int credssp_skip_nego_token(int length)
 {
        length = ber_skip_octet_string(length);
@@ -1031,7 +1088,7 @@ int credssp_recv(rdpCredssp* credssp)
                ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */
                ber_read_sequence_tag(s, &length); /* NegoDataItem */
                ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */
-               ber_read_octet_string(s, &length); /* OCTET STRING */
+               ber_read_octet_string_tag(s, &length); /* OCTET STRING */
                sspi_SecBufferAlloc(&credssp->negoToken, length);
                stream_read(s, credssp->negoToken.pvBuffer, length);
                credssp->negoToken.cbBuffer = length;
@@ -1040,7 +1097,7 @@ int credssp_recv(rdpCredssp* credssp)
        /* [2] authInfo (OCTET STRING) */
        if (ber_read_contextual_tag(s, 2, &length, true) != false)
        {
-               ber_read_octet_string(s, &length); /* OCTET STRING */
+               ber_read_octet_string_tag(s, &length); /* OCTET STRING */
                sspi_SecBufferAlloc(&credssp->authInfo, length);
                stream_read(s, credssp->authInfo.pvBuffer, length);
                credssp->authInfo.cbBuffer = length;
@@ -1049,7 +1106,7 @@ int credssp_recv(rdpCredssp* credssp)
        /* [3] pubKeyAuth (OCTET STRING) */
        if (ber_read_contextual_tag(s, 3, &length, true) != false)
        {
-               ber_read_octet_string(s, &length); /* OCTET STRING */
+               ber_read_octet_string_tag(s, &length); /* OCTET STRING */
                sspi_SecBufferAlloc(&credssp->pubKeyAuth, length);
                stream_read(s, credssp->pubKeyAuth.pvBuffer, length);
                credssp->pubKeyAuth.cbBuffer = length;