NLA identity now a pointer, allowing NULL.
authorArmin Novak <armin.novak@thincast.com>
Mon, 15 Jun 2015 13:03:13 +0000 (15:03 +0200)
committerArmin Novak <armin.novak@thincast.com>
Mon, 15 Jun 2015 13:03:13 +0000 (15:03 +0200)
When NLA identity is NULL, the current user context
is used on windows.

libfreerdp/core/nla.c
libfreerdp/core/nla.h
libfreerdp/core/peer.c

index d2d78da..35a6033 100644 (file)
 
 #define TERMSRV_SPN_PREFIX     "TERMSRV/"
 
-BOOL nla_send(rdpNla* nla);
-int nla_recv(rdpNla* nla);
-void nla_buffer_print(rdpNla* nla);
-void nla_buffer_free(rdpNla* nla);
-SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
-SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
-SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
-SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
+static BOOL nla_send(rdpNla* nla);
+static int nla_recv(rdpNla* nla);
+static void nla_buffer_print(rdpNla* nla);
+static void nla_buffer_free(rdpNla* nla);
+static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
+static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
+static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
+static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
+static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s);
 
 #define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
 #define ber_write_sequence_octet_string(stream, context, value, length) ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), TRUE) + ber_write_octet_string(stream, value, length)
@@ -153,11 +154,18 @@ int nla_client_init(rdpNla* nla)
                }
        }
 
-       sspi_SetAuthIdentity(&(nla->identity), settings->Username, settings->Domain, settings->Password);
+       if (!settings->Username)
+       {
+               free (nla->identity);
+               nla->identity = NULL;
+       }
+       else
+               sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
+                       settings->Password);
 
 #ifndef _WIN32
        {
-               SEC_WINNT_AUTH_IDENTITY* identity = &(nla->identity);
+               SEC_WINNT_AUTH_IDENTITY* identity = nla->identity;
 
                if (settings->RestrictedAdminModeRequired)
                {
@@ -222,7 +230,8 @@ int nla_client_init(rdpNla* nla)
 
        nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
        nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
-                        SECPKG_CRED_OUTBOUND, NULL, &nla->identity, NULL, NULL, &nla->credentials, &nla->expiration);
+                       SECPKG_CRED_OUTBOUND, NULL, nla->identity, NULL, NULL, &nla->credentials,
+                       &nla->expiration);
 
        if (nla->status != SEC_E_OK)
        {
@@ -854,46 +863,57 @@ SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
 int nla_sizeof_ts_password_creds(rdpNla* nla)
 {
        int length = 0;
-       length += ber_sizeof_sequence_octet_string(nla->identity.DomainLength * 2);
-       length += ber_sizeof_sequence_octet_string(nla->identity.UserLength * 2);
-       length += ber_sizeof_sequence_octet_string(nla->identity.PasswordLength * 2);
+       if (nla->identity)
+       {
+               length += ber_sizeof_sequence_octet_string(nla->identity->DomainLength * 2);
+               length += ber_sizeof_sequence_octet_string(nla->identity->UserLength * 2);
+               length += ber_sizeof_sequence_octet_string(nla->identity->PasswordLength * 2);
+       }
        return length;
 }
 
-void nla_read_ts_password_creds(rdpNla* nla, wStream* s)
+BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
 {
        int length;
 
+       if (!nla->identity)
+       {
+               WLog_ERR(TAG, "nla->identity is NULL!");
+               return FALSE;
+       }
+
        /* 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);
-       nla->identity.DomainLength = (UINT32) length;
-       nla->identity.Domain = (UINT16*) malloc(length);
-       CopyMemory(nla->identity.Domain, Stream_Pointer(s), nla->identity.DomainLength);
-       Stream_Seek(s, nla->identity.DomainLength);
-       nla->identity.DomainLength /= 2;
+       nla->identity->DomainLength = (UINT32) length;
+       nla->identity->Domain = (UINT16*) malloc(length);
+       CopyMemory(nla->identity->Domain, Stream_Pointer(s), nla->identity->DomainLength);
+       Stream_Seek(s, nla->identity->DomainLength);
+       nla->identity->DomainLength /= 2;
 
        /* [1] userName (OCTET STRING) */
        ber_read_contextual_tag(s, 1, &length, TRUE);
        ber_read_octet_string_tag(s, &length);
-       nla->identity.UserLength = (UINT32) length;
-       nla->identity.User = (UINT16*) malloc(length);
-       CopyMemory(nla->identity.User, Stream_Pointer(s), nla->identity.UserLength);
-       Stream_Seek(s, nla->identity.UserLength);
-       nla->identity.UserLength /= 2;
+       nla->identity->UserLength = (UINT32) length;
+       nla->identity->User = (UINT16*) malloc(length);
+       CopyMemory(nla->identity->User, Stream_Pointer(s), nla->identity->UserLength);
+       Stream_Seek(s, nla->identity->UserLength);
+       nla->identity->UserLength /= 2;
 
        /* [2] password (OCTET STRING) */
        ber_read_contextual_tag(s, 2, &length, TRUE);
        ber_read_octet_string_tag(s, &length);
-       nla->identity.PasswordLength = (UINT32) length;
-       nla->identity.Password = (UINT16*) malloc(length);
-       CopyMemory(nla->identity.Password, Stream_Pointer(s), nla->identity.PasswordLength);
-       Stream_Seek(s, nla->identity.PasswordLength);
-       nla->identity.PasswordLength /= 2;
-       nla->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+       nla->identity->PasswordLength = (UINT32) length;
+       nla->identity->Password = (UINT16*) malloc(length);
+       CopyMemory(nla->identity->Password, Stream_Pointer(s), nla->identity->PasswordLength);
+       Stream_Seek(s, nla->identity->PasswordLength);
+       nla->identity->PasswordLength /= 2;
+       nla->identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+
+       return TRUE;
 }
 
 int nla_write_ts_password_creds(rdpNla* nla, wStream* s)
@@ -902,12 +922,21 @@ int nla_write_ts_password_creds(rdpNla* nla, wStream* s)
        int innerSize = nla_sizeof_ts_password_creds(nla);
        /* TSPasswordCreds (SEQUENCE) */
        size += ber_write_sequence_tag(s, innerSize);
-       /* [0] domainName (OCTET STRING) */
-       size += ber_write_sequence_octet_string(s, 0, (BYTE*) nla->identity.Domain, nla->identity.DomainLength * 2);
-       /* [1] userName (OCTET STRING) */
-       size += ber_write_sequence_octet_string(s, 1, (BYTE*) nla->identity.User, nla->identity.UserLength * 2);
-       /* [2] password (OCTET STRING) */
-       size += ber_write_sequence_octet_string(s, 2, (BYTE*) nla->identity.Password, nla->identity.PasswordLength * 2);
+       if (nla->identity)
+       {
+               /* [0] domainName (OCTET STRING) */
+               size += ber_write_sequence_octet_string(
+                               s, 0, (BYTE*) nla->identity->Domain,
+                               nla->identity->DomainLength * 2);
+               /* [1] userName (OCTET STRING) */
+               size += ber_write_sequence_octet_string(
+                               s, 1, (BYTE*) nla->identity->User,
+                               nla->identity->UserLength * 2);
+               /* [2] password (OCTET STRING) */
+               size += ber_write_sequence_octet_string(
+                               s, 2, (BYTE*) nla->identity->Password,
+                               nla->identity->PasswordLength * 2);
+       }
        return size;
 }
 
@@ -920,8 +949,9 @@ int nla_sizeof_ts_credentials(rdpNla* nla)
        return size;
 }
 
-BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
+static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
 {
+       BOOL rc;
        wStream* s;
        int length;
        int ts_password_creds_length;
@@ -946,10 +976,10 @@ BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
        ber_read_contextual_tag(s, 1, &length, TRUE);
        ber_read_octet_string_tag(s, &ts_password_creds_length);
 
-       nla_read_ts_password_creds(nla, s);
+       rc = nla_read_ts_password_creds(nla, s);
 
        Stream_Free(s, FALSE);
-       return TRUE;
+       return rc;
 }
 
 int nla_write_ts_credentials(rdpNla* nla, wStream* s)
@@ -983,19 +1013,22 @@ BOOL nla_encode_ts_credentials(rdpNla* nla)
 {
        wStream* s;
        int length;
-       int DomainLength;
-       int UserLength;
-       int PasswordLength;
+       int DomainLength = 0;
+       int UserLength = 0;
+       int PasswordLength = 0;
 
-       DomainLength = nla->identity.DomainLength;
-       UserLength = nla->identity.UserLength;
-       PasswordLength = nla->identity.PasswordLength;
+       if (nla->identity)
+       {
+               DomainLength = nla->identity->DomainLength;
+               UserLength = nla->identity->UserLength;
+               PasswordLength = nla->identity->PasswordLength;
+       }
 
-       if (nla->settings->DisableCredentialsDelegation)
+       if (nla->settings->DisableCredentialsDelegation && nla->identity)
        {
-               nla->identity.DomainLength = 0;
-               nla->identity.UserLength = 0;
-               nla->identity.PasswordLength = 0;
+               nla->identity->DomainLength = 0;
+               nla->identity->UserLength = 0;
+               nla->identity->PasswordLength = 0;
        }
 
        length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla));
@@ -1017,9 +1050,9 @@ BOOL nla_encode_ts_credentials(rdpNla* nla)
 
        if (nla->settings->DisableCredentialsDelegation)
        {
-               nla->identity.DomainLength = DomainLength;
-               nla->identity.UserLength = UserLength;
-               nla->identity.PasswordLength = PasswordLength;
+               nla->identity->DomainLength = DomainLength;
+               nla->identity->UserLength = UserLength;
+               nla->identity->PasswordLength = PasswordLength;
        }
 
        Stream_Free(s, FALSE);
@@ -1412,45 +1445,53 @@ LPTSTR nla_make_spn(const char* ServiceClass, const char* hostname)
 
 rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings)
 {
+       HKEY hKey;
+       LONG status;
+       DWORD dwType;
+       DWORD dwSize;
+
        rdpNla* nla = (rdpNla*) calloc(1, sizeof(rdpNla));
 
-       if (nla)
+       if (!nla)
+               return NULL;
+
+       nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
+       if (!nla->identity)
+       {
+               free (nla);
+               return NULL;
+       }
+
+       nla->instance = instance;
+       nla->settings = settings;
+       nla->server = settings->ServerMode;
+       nla->transport = transport;
+       nla->sendSeqNum = 0;
+       nla->recvSeqNum = 0;
+       ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
+       ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
+       ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
+       SecInvalidateHandle(&nla->context);
+
+       if (nla->server)
        {
-               HKEY hKey;
-               LONG status;
-               DWORD dwType;
-               DWORD dwSize;
-               nla->instance = instance;
-               nla->settings = settings;
-               nla->server = settings->ServerMode;
-               nla->transport = transport;
-               nla->sendSeqNum = 0;
-               nla->recvSeqNum = 0;
-               ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
-               ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
-               ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
-               SecInvalidateHandle(&nla->context);
-
-               if (nla->server)
+               status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"),
+                                                               0, KEY_READ | KEY_WOW64_64KEY, &hKey);
+
+               if (status == ERROR_SUCCESS)
                {
-                       status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"),
-                                                                 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
+                       status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize);
 
                        if (status == ERROR_SUCCESS)
                        {
-                               status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize);
+                               nla->SspiModule = (LPTSTR) malloc(dwSize + sizeof(TCHAR));
+                               status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType,
+                                                                                (BYTE*) nla->SspiModule, &dwSize);
 
                                if (status == ERROR_SUCCESS)
                                {
-                                       nla->SspiModule = (LPTSTR) malloc(dwSize + sizeof(TCHAR));
-                                       status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType,
-                                                                                        (BYTE*) nla->SspiModule, &dwSize);
-
-                                       if (status == ERROR_SUCCESS)
-                                       {
-                                               WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule);
-                                               RegCloseKey(hKey);
-                                       }
+                                       WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule);
+                                       RegCloseKey(hKey);
                                }
                        }
                }
@@ -1476,9 +1517,13 @@ void nla_free(rdpNla* nla)
        sspi_SecBufferFree(&nla->tsCredentials);
 
        free(nla->ServicePrincipalName);
-       free(nla->identity.User);
-       free(nla->identity.Domain);
-       free(nla->identity.Password);
+       if (nla->identity)
+       {
+               free(nla->identity->User);
+               free(nla->identity->Domain);
+               free(nla->identity->Password);
+       }
+       free(nla->identity);
 
        free(nla);
 }
index 18f413e..774bcc9 100644 (file)
@@ -77,7 +77,7 @@ struct rdp_nla
        SecBuffer tsCredentials;
        CryptoRc4 rc4SealState;
        LPTSTR ServicePrincipalName;
-       SEC_WINNT_AUTH_IDENTITY identity;
+       SEC_WINNT_AUTH_IDENTITY* identity;
        PSecurityFunctionTable table;
        SecPkgContext_Sizes ContextSizes;
 };
index bbde82a..1fa7633 100644 (file)
@@ -463,7 +463,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
 
                        if (rdp->nego->SelectedProtocol & PROTOCOL_NLA)
                        {
-                               sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->nla->identity));
+                               sspi_CopyAuthIdentity(&client->identity, rdp->nego->transport->nla->identity);
                                IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE);
                                nla_free(rdp->nego->transport->nla);
                                rdp->nego->transport->nla = NULL;