From 61010feae87220a80e5cd29caa1065383676b585 Mon Sep 17 00:00:00 2001 From: maelnor Date: Wed, 22 Feb 2012 13:17:59 +0400 Subject: [PATCH 1/5] Fix header files installation --- include/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index b7ffe7276..ba0ba4d3a 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -24,7 +24,9 @@ install(DIRECTORY freerdp/utils DESTINATION include/freerdp FILES_MATCHING PATTE install(DIRECTORY freerdp/channels DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/cache DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/gdi DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") -install(DIRECTORY freerdp/kbd DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/rail DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/codec DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") install(DIRECTORY freerdp/plugins DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") +install(DIRECTORY freerdp/locale DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") +install(DIRECTORY freerdp/crypto DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") +install(DIRECTORY freerdp/auth DESTINATION include/freerdp FILES_MATCHING PATTERN "*.h") From d70cc2f4eab9649f4641ae1df2516d354080156c Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Wed, 22 Feb 2012 19:23:48 +0100 Subject: [PATCH 2/5] For salted checksums we need separate counters, as the encrypt_use_count and decrypt_use_count counters are reset during key regeneration and we need counters that are never reset. --- libfreerdp-core/rdp.h | 2 ++ libfreerdp-core/security.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index 701bea4ac..6d5f3c196 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -136,8 +136,10 @@ struct rdp_rdp struct rdp_mppc* mppc; struct crypto_rc4_struct* rc4_decrypt_key; int decrypt_use_count; + int decrypt_checksum_use_count; struct crypto_rc4_struct* rc4_encrypt_key; int encrypt_use_count; + int encrypt_checksum_use_count; struct crypto_des3_struct* fips_encrypt; struct crypto_des3_struct* fips_decrypt; struct crypto_hmac_struct* fips_hmac; diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c index c79b377d0..5757cea3b 100644 --- a/libfreerdp-core/security.c +++ b/libfreerdp-core/security.c @@ -262,14 +262,17 @@ void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, bool security_uint32_le(length_le, length); /* length must be little-endian */ if (encryption) - security_uint32_le(use_count_le, rdp->encrypt_use_count); + { + security_uint32_le(use_count_le, rdp->encrypt_checksum_use_count); + } else { /* * We calculate checksum on plain text, so we must have already - * decrypt it, which means decrypt_use_count is off by one. + * decrypt it, which means decrypt_checksum_use_count is + * off by one. */ - security_uint32_le(use_count_le, rdp->decrypt_use_count - 1); + security_uint32_le(use_count_le, rdp->decrypt_checksum_use_count - 1); } /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ @@ -461,7 +464,8 @@ boolean security_encrypt(uint8* data, int length, rdpRdp* rdp) rdp->encrypt_use_count = 0; } crypto_rc4(rdp->rc4_encrypt_key, length, data, data); - rdp->encrypt_use_count += 1; + rdp->encrypt_use_count++; + rdp->encrypt_checksum_use_count++; return true; } @@ -476,6 +480,7 @@ boolean security_decrypt(uint8* data, int length, rdpRdp* rdp) } crypto_rc4(rdp->rc4_decrypt_key, length, data, data); rdp->decrypt_use_count += 1; + rdp->decrypt_checksum_use_count++; return true; } From 3a8dd077c8185313063c22c9bd981d8ef93c2f8a Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 23 Feb 2012 00:36:15 +0100 Subject: [PATCH 3/5] On SSL error print all the errors from the stack. --- libfreerdp-crypto/tls.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libfreerdp-crypto/tls.c b/libfreerdp-crypto/tls.c index b9c394fde..b6956b691 100644 --- a/libfreerdp-crypto/tls.c +++ b/libfreerdp-crypto/tls.c @@ -231,6 +231,14 @@ int tls_write(rdpTls* tls, uint8* data, int length) return status; } +static void tls_errors(const char *prefix) +{ + unsigned long error; + + while ((error = ERR_get_error()) != 0) + printf("%s: %s\n", prefix, ERR_error_string(error, NULL)); +} + boolean tls_print_error(char* func, SSL* connection, int value) { switch (SSL_get_error(connection, value)) @@ -249,14 +257,17 @@ boolean tls_print_error(char* func, SSL* connection, int value) case SSL_ERROR_SYSCALL: printf("%s: I/O error\n", func); + tls_errors(func); return true; case SSL_ERROR_SSL: printf("%s: Failure in SSL library (protocol error?)\n", func); + tls_errors(func); return true; default: printf("%s: Unknown error\n", func); + tls_errors(func); return true; } } From 59bd213cf007f36b2a857785e647bd3f9972fbc3 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 23 Feb 2012 00:38:52 +0100 Subject: [PATCH 4/5] Accept both TLSv1 and SSLv3 as a server. This fixes SSL connections from Microsoft RDC for Mac OS X to FreeRDP server. --- libfreerdp-crypto/tls.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libfreerdp-crypto/tls.c b/libfreerdp-crypto/tls.c index b6956b691..9185d0013 100644 --- a/libfreerdp-crypto/tls.c +++ b/libfreerdp-crypto/tls.c @@ -128,7 +128,7 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi { int connection_status; - tls->ctx = SSL_CTX_new(TLSv1_server_method()); + tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { @@ -136,6 +136,12 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi return false; } + /* + * We only want SSLv3 and TLSv1, so disable SSLv2. + * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. + */ + SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2); + if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); From 545c8857e300befa7a056ac0f3d5b30795936e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 22 Feb 2012 23:41:22 -0500 Subject: [PATCH 5/5] libfreerdp-auth: start implementing package management API --- cunit/CMakeLists.txt | 2 + cunit/test_freerdp.c | 2 + cunit/test_sspi.c | 134 ++++++++++++++++++++++++++++++++ cunit/test_sspi.h | 28 +++++++ include/freerdp/auth/sspi.h | 148 ++++++++++++++++++++++++++++++------ libfreerdp-auth/credssp.c | 46 +++++++++++ libfreerdp-auth/ntlmssp.c | 58 ++++++++++++++ libfreerdp-auth/sspi.c | 144 ++++++++++++++++++++++++++++++++++- 8 files changed, 537 insertions(+), 25 deletions(-) create mode 100644 cunit/test_sspi.c create mode 100644 cunit/test_sspi.h diff --git a/cunit/CMakeLists.txt b/cunit/CMakeLists.txt index 7f4ccad85..2a187964e 100644 --- a/cunit/CMakeLists.txt +++ b/cunit/CMakeLists.txt @@ -62,6 +62,8 @@ add_executable(test_freerdp test_drdynvc.h test_rfx.c test_rfx.h + test_sspi.c + test_sspi.h test_freerdp.c test_freerdp.h test_rail.c diff --git a/cunit/test_freerdp.c b/cunit/test_freerdp.c index 50b325fe2..4a8bbfe48 100644 --- a/cunit/test_freerdp.c +++ b/cunit/test_freerdp.c @@ -27,6 +27,7 @@ #include "test_bitmap.h" #include "test_gdi.h" #include "test_list.h" +#include "test_sspi.h" #include "test_stream.h" #include "test_utils.h" #include "test_orders.h" @@ -137,6 +138,7 @@ static test_suite suites[] = { "per", add_per_suite }, { "rail", add_rail_suite }, { "rfx", add_rfx_suite }, + { "sspi", add_sspi_suite }, { "stream", add_stream_suite }, { "utils", add_utils_suite }, { "", NULL } diff --git a/cunit/test_sspi.c b/cunit/test_sspi.c new file mode 100644 index 000000000..4c151feec --- /dev/null +++ b/cunit/test_sspi.c @@ -0,0 +1,134 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Security Support Provider Interface (SSPI) Tests + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "test_sspi.h" +#include + +#define NTLM_PACKAGE_NAME "NTLM" + +int init_sspi_suite(void) +{ + return 0; +} + +int clean_sspi_suite(void) +{ + return 0; +} + +int add_sspi_suite(void) +{ + add_test_suite(sspi); + + add_test_function(EnumerateSecurityPackages); + add_test_function(QuerySecurityPackageInfo); + add_test_function(AcquireCredentialsHandle); + + return 0; +} + +void test_EnumerateSecurityPackages(void) +{ + uint32 cPackages; + SECURITY_STATUS status; + SEC_PKG_INFO* pPackageInfo; + + status = EnumerateSecurityPackages(&cPackages, &pPackageInfo); + + if (status == SEC_E_OK) + { + int index; + + printf("\nEnumerateSecurityPackages (%d):\n", cPackages); + + for (index = 0; index < cPackages; index++) + { + printf("\"%s\", \"%s\"\n", + pPackageInfo[index].Name, pPackageInfo[index].Comment); + } + } +} + +void test_QuerySecurityPackageInfo(void) +{ + SECURITY_STATUS status; + SEC_PKG_INFO* pPackageInfo; + + status = QuerySecurityPackageInfo("NTLM", &pPackageInfo); + + if (status == SEC_E_OK) + { + printf("\nQuerySecurityPackageInfo:\n"); + printf("\"%s\", \"%s\"\n", pPackageInfo->Name, pPackageInfo->Comment); + } +} + +const char* test_User = "User"; +const char* test_Domain = "Domain"; +const char* test_Password = "Password"; + +void test_AcquireCredentialsHandle(void) +{ + SECURITY_STATUS status; + CRED_HANDLE credentials; + SEC_TIMESTAMP expiration; + SEC_AUTH_IDENTITY identity; + SECURITY_FUNCTION_TABLE* table; + + table = InitSecurityInterface(); + + identity.User = (uint16*) xstrdup(test_User); + identity.UserLength = sizeof(test_User); + identity.Domain = (uint16*) xstrdup(test_Domain); + identity.DomainLength = sizeof(test_Domain); + identity.Password = (uint16*) xstrdup(test_Password); + identity.PasswordLength = sizeof(test_Password); + identity.Flags = SEC_AUTH_IDENTITY_ANSI; + + status = table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, + SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); + + if (status == SEC_E_OK) + { + + } +} + + + + + + + + + + + + + + + + + + diff --git a/cunit/test_sspi.h b/cunit/test_sspi.h new file mode 100644 index 000000000..bcec0fa52 --- /dev/null +++ b/cunit/test_sspi.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Security Support Provider Interface (SSPI) Tests + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test_freerdp.h" + +int init_sspi_suite(void); +int clean_sspi_suite(void); +int add_sspi_suite(void); + +void test_EnumerateSecurityPackages(void); +void test_QuerySecurityPackageInfo(void); +void test_AcquireCredentialsHandle(void); diff --git a/include/freerdp/auth/sspi.h b/include/freerdp/auth/sspi.h index 5f396289b..fa11f4797 100644 --- a/include/freerdp/auth/sspi.h +++ b/include/freerdp/auth/sspi.h @@ -53,7 +53,94 @@ typedef uint32 SECURITY_STATUS; #define SEC_E_OK 0x00000000 #define SEC_E_INSUFFICIENT_MEMORY 0x80090300 #define SEC_E_INVALID_HANDLE 0x80090301 +#define SEC_E_UNSUPPORTED_FUNCTION 0x80090302 +#define SEC_E_TARGET_UNKNOWN 0x80090303 +#define SEC_E_INTERNAL_ERROR 0x80090304 #define SEC_E_SECPKG_NOT_FOUND 0x80090305 +#define SEC_E_NOT_OWNER 0x80090306 +#define SEC_E_CANNOT_INSTALL 0x80090307 +#define SEC_E_INVALID_TOKEN 0x80090308 +#define SEC_E_CANNOT_PACK 0x80090309 +#define SEC_E_QOP_NOT_SUPPORTED 0x8009030A +#define SEC_E_NO_IMPERSONATION 0x8009030B +#define SEC_E_LOGON_DENIED 0x8009030C +#define SEC_E_UNKNOWN_CREDENTIALS 0x8009030D +#define SEC_E_NO_CREDENTIALS 0x8009030E +#define SEC_E_MESSAGE_ALTERED 0x8009030F +#define SEC_E_OUT_OF_SEQUENCE 0x80090310 +#define SEC_E_NO_AUTHENTICATING_AUTHORITY 0x80090311 +#define SEC_E_BAD_PKGID 0x80090316 +#define SEC_E_CONTEXT_EXPIRED 0x80090317 +#define SEC_E_INCOMPLETE_MESSAGE 0x80090318 +#define SEC_E_INCOMPLETE_CREDENTIALS 0x80090320 +#define SEC_E_BUFFER_TOO_SMALL 0x80090321 +#define SEC_E_WRONG_PRINCIPAL 0x80090322 +#define SEC_E_TIME_SKEW 0x80090324 +#define SEC_E_UNTRUSTED_ROOT 0x80090325 +#define SEC_E_ILLEGAL_MESSAGE 0x80090326 +#define SEC_E_CERT_UNKNOWN 0x80090327 +#define SEC_E_CERT_EXPIRED 0x80090328 +#define SEC_E_ENCRYPT_FAILURE 0x80090329 +#define SEC_E_DECRYPT_FAILURE 0x80090330 +#define SEC_E_ALGORITHM_MISMATCH 0x80090331 +#define SEC_E_SECURITY_QOS_FAILED 0x80090332 +#define SEC_E_UNFINISHED_CONTEXT_DELETED 0x80090333 +#define SEC_E_NO_TGT_REPLY 0x80090334 +#define SEC_E_NO_IP_ADDRESSES 0x80090335 +#define SEC_E_WRONG_CREDENTIAL_HANDLE 0x80090336 +#define SEC_E_CRYPTO_SYSTEM_INVALID 0x80090337 +#define SEC_E_MAX_REFERRALS_EXCEEDED 0x80090338 +#define SEC_E_MUST_BE_KDC 0x80090339 +#define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED 0x8009033A +#define SEC_E_TOO_MANY_PRINCIPALS 0x8009033B +#define SEC_E_NO_PA_DATA 0x8009033C +#define SEC_E_PKINIT_NAME_MISMATCH 0x8009033D +#define SEC_E_SMARTCARD_LOGON_REQUIRED 0x8009033E +#define SEC_E_SHUTDOWN_IN_PROGRESS 0x8009033F +#define SEC_E_KDC_INVALID_REQUEST 0x80090340 +#define SEC_E_KDC_UNABLE_TO_REFER 0x80090341 +#define SEC_E_KDC_UNKNOWN_ETYPE 0x80090342 +#define SEC_E_UNSUPPORTED_PREAUTH 0x80090343 +#define SEC_E_DELEGATION_REQUIRED 0x80090345 +#define SEC_E_BAD_BINDINGS 0x80090346 +#define SEC_E_MULTIPLE_ACCOUNTS 0x80090347 +#define SEC_E_NO_KERB_KEY 0x80090348 +#define SEC_E_CERT_WRONG_USAGE 0x80090349 +#define SEC_E_DOWNGRADE_DETECTED 0x80090350 +#define SEC_E_SMARTCARD_CERT_REVOKED 0x80090351 +#define SEC_E_ISSUING_CA_UNTRUSTED 0x80090352 +#define SEC_E_REVOCATION_OFFLINE_C 0x80090353 +#define SEC_E_PKINIT_CLIENT_FAILURE 0x80090354 +#define SEC_E_SMARTCARD_CERT_EXPIRED 0x80090355 +#define SEC_E_NO_S4U_PROT_SUPPORT 0x80090356 +#define SEC_E_CROSSREALM_DELEGATION_FAILURE 0x80090357 +#define SEC_E_REVOCATION_OFFLINE_KDC 0x80090358 +#define SEC_E_ISSUING_CA_UNTRUSTED_KDC 0x80090359 +#define SEC_E_KDC_CERT_EXPIRED 0x8009035A +#define SEC_E_KDC_CERT_REVOKED 0x8009035B +#define SEC_E_INVALID_PARAMETER 0x8009035D +#define SEC_E_DELEGATION_POLICY 0x8009035E +#define SEC_E_POLICY_NLTM_ONLY 0x8009035F +#define SEC_E_NO_CONTEXT 0x80090361 +#define SEC_E_PKU2U_CERT_FAILURE 0x80090362 +#define SEC_E_MUTUAL_AUTH_FAILED 0x80090363 + +#define SEC_I_CONTINUE_NEEDED 0x00090312 +#define SEC_I_COMPLETE_NEEDED 0x00090313 +#define SEC_I_COMPLETE_AND_CONTINUE 0x00090314 +#define SEC_I_LOCAL_LOGON 0x00090315 +#define SEC_I_CONTEXT_EXPIRED 0x00090317 +#define SEC_I_INCOMPLETE_CREDENTIALS 0x00090320 +#define SEC_I_RENEGOTIATE 0x00090321 +#define SEC_I_NO_LSA_CONTEXT 0x00090323 +#define SEC_I_SIGNATURE_NEEDED 0x0009035C +#define SEC_I_NO_RENEGOTIATION 0x00090360 + +#define SECPKG_CRED_INBOUND 0x00000001 +#define SECPKG_CRED_OUTBOUND 0x00000002 +#define SECPKG_CRED_BOTH 0x00000003 +#define SECPKG_CRED_AUTOLOGON_RESTRICTED 0x00000010 +#define SECPKG_CRED_PROCESS_POLICY_ONLY 0x00000020 struct _SEC_PKG_INFO { @@ -66,6 +153,21 @@ struct _SEC_PKG_INFO }; typedef struct _SEC_PKG_INFO SEC_PKG_INFO; +#define SEC_AUTH_IDENTITY_ANSI 0x1 +#define SEC_AUTH_IDENTITY_UNICODE 0x2 + +struct _SEC_AUTH_IDENTITY +{ + uint16* User; + uint32 UserLength; + uint16* Domain; + uint32 DomainLength; + uint16* Password; + uint32 PasswordLength; + uint32 Flags; +}; +typedef struct _SEC_AUTH_IDENTITY SEC_AUTH_IDENTITY; + struct _SEC_HANDLE { uint32* dwLower; @@ -190,48 +292,48 @@ typedef struct _SECURITY_FUNCTION_TABLE SECURITY_FUNCTION_TABLE; /* Package Management */ -SECURITY_STATUS EnumerateSecurityPackages(uint32* pcPackages, SEC_PKG_INFO** ppPackageInfo); -SECURITY_FUNCTION_TABLE* InitSecurityInterface(void); -SECURITY_STATUS QuerySecurityPackageInfo(char* pszPackageName, SEC_PKG_INFO** ppPackageInfo); +FREERDP_API SECURITY_STATUS EnumerateSecurityPackages(uint32* pcPackages, SEC_PKG_INFO** ppPackageInfo); +FREERDP_API SECURITY_FUNCTION_TABLE* InitSecurityInterface(void); +FREERDP_API SECURITY_STATUS QuerySecurityPackageInfo(char* pszPackageName, SEC_PKG_INFO** ppPackageInfo); /* Credential Management */ -SECURITY_STATUS AcquireCredentialsHandle(char* pszPrincipal, char* pszPackage, +FREERDP_API SECURITY_STATUS AcquireCredentialsHandle(char* pszPrincipal, char* pszPackage, uint32 fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn, void* pvGetKeyArgument, CRED_HANDLE* phCredential, SEC_TIMESTAMP* ptsExpiry); -SECURITY_STATUS ExportSecurityContext(CTXT_HANDLE* phContext, uint32 fFlags, SEC_BUFFER* pPackedContext, void* pToken); -SECURITY_STATUS FreeCredentialsHandle(CRED_HANDLE* phCredential); -SECURITY_STATUS ImportSecurityContext(char* pszPackage, SEC_BUFFER* pPackedContext, void* pToken, CTXT_HANDLE* phContext); -SECURITY_STATUS QueryCredentialsAttributes(CRED_HANDLE* phCredential, uint32 ulAttribute, void* pBuffer); +FREERDP_API SECURITY_STATUS ExportSecurityContext(CTXT_HANDLE* phContext, uint32 fFlags, SEC_BUFFER* pPackedContext, void* pToken); +FREERDP_API SECURITY_STATUS FreeCredentialsHandle(CRED_HANDLE* phCredential); +FREERDP_API SECURITY_STATUS ImportSecurityContext(char* pszPackage, SEC_BUFFER* pPackedContext, void* pToken, CTXT_HANDLE* phContext); +FREERDP_API SECURITY_STATUS QueryCredentialsAttributes(CRED_HANDLE* phCredential, uint32 ulAttribute, void* pBuffer); /* Context Management */ -SECURITY_STATUS AcceptSecurityContext(CRED_HANDLE* phCredential, CTXT_HANDLE* phContext, +FREERDP_API SECURITY_STATUS AcceptSecurityContext(CRED_HANDLE* phCredential, CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pInput, uint32 fContextReq, uint32 TargetDataRep, CTXT_HANDLE* phNewContext, SEC_BUFFER_DESC* pOutput, uint32* pfContextAttr, SEC_TIMESTAMP* ptsTimeStamp); -SECURITY_STATUS ApplyControlToken(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pInput); -SECURITY_STATUS CompleteAuthToken(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pToken); -SECURITY_STATUS DeleteSecurityContext(CTXT_HANDLE* phContext); -SECURITY_STATUS FreeContextBuffer(void* pvContextBuffer); -SECURITY_STATUS ImpersonateSecurityContext(CTXT_HANDLE* phContext); +FREERDP_API SECURITY_STATUS ApplyControlToken(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pInput); +FREERDP_API SECURITY_STATUS CompleteAuthToken(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pToken); +FREERDP_API SECURITY_STATUS DeleteSecurityContext(CTXT_HANDLE* phContext); +FREERDP_API SECURITY_STATUS FreeContextBuffer(void* pvContextBuffer); +FREERDP_API SECURITY_STATUS ImpersonateSecurityContext(CTXT_HANDLE* phContext); -SECURITY_STATUS InitializeSecurityContext(CRED_HANDLE* phCredential, CTXT_HANDLE* phContext, +FREERDP_API SECURITY_STATUS InitializeSecurityContext(CRED_HANDLE* phCredential, CTXT_HANDLE* phContext, char* pszTargetName, uint32 fContextReq, uint32 Reserved1, uint32 TargetDataRep, SEC_BUFFER_DESC* pInput, uint32 Reserved2, CTXT_HANDLE* phNewContext, SEC_BUFFER_DESC* pOutput, uint32* pfContextAttr, SEC_TIMESTAMP* ptsExpiry); -SECURITY_STATUS QueryContextAttributes(CTXT_HANDLE* phContext, uint32 ulAttribute, void* pBuffer); -SECURITY_STATUS QuerySecurityContextToken(CTXT_HANDLE* phContext, void* phToken); -SECURITY_STATUS SetContextAttributes(CTXT_HANDLE* phContext, uint32 ulAttribute, void* pBuffer, uint32 cbBuffer); -SECURITY_STATUS RevertSecurityContext(CTXT_HANDLE* phContext); +FREERDP_API SECURITY_STATUS QueryContextAttributes(CTXT_HANDLE* phContext, uint32 ulAttribute, void* pBuffer); +FREERDP_API SECURITY_STATUS QuerySecurityContextToken(CTXT_HANDLE* phContext, void* phToken); +FREERDP_API SECURITY_STATUS SetContextAttributes(CTXT_HANDLE* phContext, uint32 ulAttribute, void* pBuffer, uint32 cbBuffer); +FREERDP_API SECURITY_STATUS RevertSecurityContext(CTXT_HANDLE* phContext); /* Message Support */ -SECURITY_STATUS DecryptMessage(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo, uint32* pfQOP); -SECURITY_STATUS EncryptMessage(CTXT_HANDLE* phContext, uint32 fQOP, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo); -SECURITY_STATUS MakeSignature(CTXT_HANDLE* phContext, uint32 fQOP, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo); -SECURITY_STATUS VerifySignature(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo, uint32* pfQOP); +FREERDP_API SECURITY_STATUS DecryptMessage(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo, uint32* pfQOP); +FREERDP_API SECURITY_STATUS EncryptMessage(CTXT_HANDLE* phContext, uint32 fQOP, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo); +FREERDP_API SECURITY_STATUS MakeSignature(CTXT_HANDLE* phContext, uint32 fQOP, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo); +FREERDP_API SECURITY_STATUS VerifySignature(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pMessage, uint32 MessageSeqNo, uint32* pfQOP); #endif /* FREERDP_AUTH_SSPI_H */ diff --git a/libfreerdp-auth/credssp.c b/libfreerdp-auth/credssp.c index 76e053469..c0c77aaa5 100644 --- a/libfreerdp-auth/credssp.c +++ b/libfreerdp-auth/credssp.c @@ -26,6 +26,7 @@ #include #include +#include #include /** @@ -719,3 +720,48 @@ void credssp_free(rdpCredssp* credssp) xfree(credssp); } } + +/* SSPI */ + +const SECURITY_FUNCTION_TABLE CREDSSP_SECURITY_FUNCTION_TABLE = +{ + 1, /* dwVersion */ + NULL, /* EnumerateSecurityPackages */ + NULL, /* Reserved1 */ + NULL, /* QueryCredentialsAttributes */ + NULL, /* AcquireCredentialsHandle */ + NULL, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + NULL, /* InitializeSecurityContext */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + NULL, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + NULL, /* QueryContextAttributes */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + NULL, /* MakeSignature */ + NULL, /* VerifySignature */ + NULL, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + NULL, /* EncryptMessage */ + NULL, /* DecryptMessage */ + NULL, /* SetContextAttributes */ +}; + +const SEC_PKG_INFO CREDSSP_SEC_PKG_INFO = +{ + 0x000110733, /* fCapabilities */ + 1, /* wVersion */ + 0xFFFF, /* wRPCID */ + 0x000090A8, /* cbMaxToken */ + "CREDSSP", /* Name */ + "Microsoft CredSSP Security Provider" /* Comment */ +}; diff --git a/libfreerdp-auth/ntlmssp.c b/libfreerdp-auth/ntlmssp.c index f6cff97d4..8e89e599d 100644 --- a/libfreerdp-auth/ntlmssp.c +++ b/libfreerdp-auth/ntlmssp.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -2223,3 +2224,60 @@ void ntlmssp_free(NTLMSSP* ntlmssp) crypto_rc4_free(ntlmssp->recv_rc4_seal); xfree(ntlmssp); } + +/* SSPI */ + +SECURITY_STATUS ntlm_AcquireCredentialsHandle(char* pszPrincipal, char* pszPackage, + uint32 fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn, + void* pvGetKeyArgument, CRED_HANDLE* phCredential, SEC_TIMESTAMP* ptsExpiry) +{ + if (fCredentialUse == SECPKG_CRED_OUTBOUND) + { + + } + + return SEC_E_OK; +} + +const SEC_PKG_INFO NTLM_SEC_PKG_INFO = +{ + 0x00082B37, /* fCapabilities */ + 1, /* wVersion */ + 0x000A, /* wRPCID */ + 0x00000B48, /* cbMaxToken */ + "NTLM", /* Name */ + "NTLM Security Package" /* Comment */ +}; + +const SECURITY_FUNCTION_TABLE NTLM_SECURITY_FUNCTION_TABLE = +{ + 1, /* dwVersion */ + NULL, /* EnumerateSecurityPackages */ + NULL, /* Reserved1 */ + NULL, /* QueryCredentialsAttributes */ + ntlm_AcquireCredentialsHandle, /* AcquireCredentialsHandle */ + NULL, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + NULL, /* InitializeSecurityContext */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + NULL, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + NULL, /* QueryContextAttributes */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + NULL, /* MakeSignature */ + NULL, /* VerifySignature */ + NULL, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + NULL, /* EncryptMessage */ + NULL, /* DecryptMessage */ + NULL, /* SetContextAttributes */ +}; diff --git a/libfreerdp-auth/sspi.c b/libfreerdp-auth/sspi.c index 70ed0a01e..ef02e58bb 100644 --- a/libfreerdp-auth/sspi.c +++ b/libfreerdp-auth/sspi.c @@ -23,6 +23,53 @@ /* Authentication Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731/ */ +extern const SEC_PKG_INFO NTLM_SEC_PKG_INFO; +extern const SEC_PKG_INFO CREDSSP_SEC_PKG_INFO; + +const SECURITY_FUNCTION_TABLE SSPI_SECURITY_FUNCTION_TABLE; +extern const SECURITY_FUNCTION_TABLE NTLM_SECURITY_FUNCTION_TABLE; +extern const SECURITY_FUNCTION_TABLE CREDSSP_SECURITY_FUNCTION_TABLE; + +const SEC_PKG_INFO* SEC_PKG_INFO_LIST[] = +{ + &NTLM_SEC_PKG_INFO, + &CREDSSP_SEC_PKG_INFO +}; + +struct _SECURITY_FUNCTION_TABLE_NAME +{ + char* Name; + const SECURITY_FUNCTION_TABLE* security_function_table; +}; +typedef struct _SECURITY_FUNCTION_TABLE_NAME SECURITY_FUNCTION_TABLE_NAME; + +const SECURITY_FUNCTION_TABLE_NAME SECURITY_FUNCTION_TABLE_NAME_LIST[] = +{ + { "NTLM", &NTLM_SECURITY_FUNCTION_TABLE }, + { "CREDSSP", &CREDSSP_SECURITY_FUNCTION_TABLE } +}; + +#define SEC_HANDLE_LOWER_MAX 0xFFFFFFFF +#define SEC_HANDLE_UPPER_MAX 0xFFFFFFFE + +SECURITY_FUNCTION_TABLE* sspi_GetSecurityFunctionTableByName(const char* Name) +{ + int index; + uint32 cPackages; + + cPackages = sizeof(SEC_PKG_INFO_LIST) / sizeof(SEC_PKG_INFO*); + + for (index = 0; index < cPackages; index++) + { + if (strcmp(Name, SECURITY_FUNCTION_TABLE_NAME_LIST[index].Name) == 0) + { + return (SECURITY_FUNCTION_TABLE*) SECURITY_FUNCTION_TABLE_NAME_LIST[index].security_function_table; + } + } + + return NULL; +} + /* Package Management */ SECURITY_STATUS EnumerateSecurityPackages(uint32* pcPackages, SEC_PKG_INFO** ppPackageInfo) @@ -90,6 +137,26 @@ SECURITY_STATUS EnumerateSecurityPackages(uint32* pcPackages, SEC_PKG_INFO** ppP * cbMaxToken: 0x000090A8 */ + int index; + uint32 cPackages; + SEC_PKG_INFO* pPackageInfo; + + cPackages = sizeof(SEC_PKG_INFO_LIST) / sizeof(SEC_PKG_INFO*); + pPackageInfo = (SEC_PKG_INFO*) xmalloc(sizeof(SEC_PKG_INFO) * cPackages); + + for (index = 0; index < cPackages; index++) + { + pPackageInfo[index].fCapabilities = SEC_PKG_INFO_LIST[index]->fCapabilities; + pPackageInfo[index].wVersion = SEC_PKG_INFO_LIST[index]->wVersion; + pPackageInfo[index].wRPCID = SEC_PKG_INFO_LIST[index]->wRPCID; + pPackageInfo[index].cbMaxToken = SEC_PKG_INFO_LIST[index]->cbMaxToken; + pPackageInfo[index].Name = xstrdup(SEC_PKG_INFO_LIST[index]->Name); + pPackageInfo[index].Comment = xstrdup(SEC_PKG_INFO_LIST[index]->Comment); + } + + *(pcPackages) = cPackages; + *(ppPackageInfo) = pPackageInfo; + return SEC_E_OK; } @@ -97,12 +164,40 @@ SECURITY_FUNCTION_TABLE* InitSecurityInterface(void) { SECURITY_FUNCTION_TABLE* security_function_table; security_function_table = xnew(SECURITY_FUNCTION_TABLE); + memcpy((void*) security_function_table, (void*) &SSPI_SECURITY_FUNCTION_TABLE, sizeof(SECURITY_FUNCTION_TABLE)); return security_function_table; } SECURITY_STATUS QuerySecurityPackageInfo(char* pszPackageName, SEC_PKG_INFO** ppPackageInfo) { - return SEC_E_OK; + int index; + uint32 cPackages; + SEC_PKG_INFO* pPackageInfo; + + cPackages = sizeof(SEC_PKG_INFO_LIST) / sizeof(SEC_PKG_INFO*); + + for (index = 0; index < cPackages; index++) + { + if (strcmp(pszPackageName, SEC_PKG_INFO_LIST[index]->Name) == 0) + { + pPackageInfo = (SEC_PKG_INFO*) xmalloc(sizeof(SEC_PKG_INFO)); + + pPackageInfo->fCapabilities = SEC_PKG_INFO_LIST[index]->fCapabilities; + pPackageInfo->wVersion = SEC_PKG_INFO_LIST[index]->wVersion; + pPackageInfo->wRPCID = SEC_PKG_INFO_LIST[index]->wRPCID; + pPackageInfo->cbMaxToken = SEC_PKG_INFO_LIST[index]->cbMaxToken; + pPackageInfo->Name = xstrdup(SEC_PKG_INFO_LIST[index]->Name); + pPackageInfo->Comment = xstrdup(SEC_PKG_INFO_LIST[index]->Comment); + + *(ppPackageInfo) = pPackageInfo; + + return SEC_E_OK; + } + } + + *(ppPackageInfo) = NULL; + + return SEC_E_SECPKG_NOT_FOUND; } /* Credential Management */ @@ -111,7 +206,19 @@ SECURITY_STATUS AcquireCredentialsHandle(char* pszPrincipal, char* pszPackage, uint32 fCredentialUse, void* pvLogonID, void* pAuthData, void* pGetKeyFn, void* pvGetKeyArgument, CRED_HANDLE* phCredential, SEC_TIMESTAMP* ptsExpiry) { - return SEC_E_OK; + SECURITY_STATUS status; + SECURITY_FUNCTION_TABLE* table = sspi_GetSecurityFunctionTableByName(pszPackage); + + if (!table) + return SEC_E_SECPKG_NOT_FOUND; + + if (!(table->AcquireCredentialsHandle)) + return SEC_E_UNSUPPORTED_FUNCTION; + + status = table->AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, + pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); + + return status; } SECURITY_STATUS ExportSecurityContext(CTXT_HANDLE* phContext, uint32 fFlags, SEC_BUFFER* pPackedContext, void* pToken) @@ -220,3 +327,36 @@ SECURITY_STATUS VerifySignature(CTXT_HANDLE* phContext, SEC_BUFFER_DESC* pMessag { return SEC_E_OK; } + +const SECURITY_FUNCTION_TABLE SSPI_SECURITY_FUNCTION_TABLE = +{ + 1, /* dwVersion */ + EnumerateSecurityPackages, /* EnumerateSecurityPackages */ + NULL, /* Reserved1 */ + QueryCredentialsAttributes, /* QueryCredentialsAttributes */ + AcquireCredentialsHandle, /* AcquireCredentialsHandle */ + FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + InitializeSecurityContext, /* InitializeSecurityContext */ + AcceptSecurityContext, /* AcceptSecurityContext */ + CompleteAuthToken, /* CompleteAuthToken */ + DeleteSecurityContext, /* DeleteSecurityContext */ + ApplyControlToken, /* ApplyControlToken */ + QueryContextAttributes, /* QueryContextAttributes */ + ImpersonateSecurityContext, /* ImpersonateSecurityContext */ + RevertSecurityContext, /* RevertSecurityContext */ + MakeSignature, /* MakeSignature */ + VerifySignature, /* VerifySignature */ + FreeContextBuffer, /* FreeContextBuffer */ + QuerySecurityPackageInfo, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + ExportSecurityContext, /* ExportSecurityContext */ + ImportSecurityContext, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + QuerySecurityContextToken, /* QuerySecurityContextToken */ + EncryptMessage, /* EncryptMessage */ + DecryptMessage, /* DecryptMessage */ + SetContextAttributes, /* SetContextAttributes */ +};