From 0e02134c4010fe75df9a212cf72863b3fa9682ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 22 Dec 2012 02:23:58 -0500 Subject: [PATCH 01/24] libwinpr-crypto: started stubbing CryptoAPI --- winpr/include/winpr/crypto.h | 31 +++++ winpr/libwinpr/crypto/CMakeLists.txt | 42 ++++++ winpr/libwinpr/crypto/ModuleOptions.cmake | 9 ++ winpr/libwinpr/crypto/cert.c | 157 ++++++++++++++++++++++ winpr/libwinpr/crypto/crypto.c | 149 ++++++++++++++++++++ winpr/libwinpr/crypto/module.def | 3 + winpr/libwinpr/pool/CMakeLists.txt | 2 +- 7 files changed, 392 insertions(+), 1 deletion(-) create mode 100644 winpr/include/winpr/crypto.h create mode 100644 winpr/libwinpr/crypto/CMakeLists.txt create mode 100644 winpr/libwinpr/crypto/ModuleOptions.cmake create mode 100644 winpr/libwinpr/crypto/cert.c create mode 100644 winpr/libwinpr/crypto/crypto.c create mode 100644 winpr/libwinpr/crypto/module.def diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h new file mode 100644 index 000000000..a71067e9e --- /dev/null +++ b/winpr/include/winpr/crypto.h @@ -0,0 +1,31 @@ +/** + * WinPR: Windows Portable Runtime + * Cryptography API (CryptoAPI) + * + * 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. + */ + +#ifndef WINPR_CRYPTO_H +#define WINPR_CRYPTO_H + +#include +#include + +#ifndef _WIN32 + +#endif + +#endif /* WINPR_CRYPTO_H */ + diff --git a/winpr/libwinpr/crypto/CMakeLists.txt b/winpr/libwinpr/crypto/CMakeLists.txt new file mode 100644 index 000000000..a935afac1 --- /dev/null +++ b/winpr/libwinpr/crypto/CMakeLists.txt @@ -0,0 +1,42 @@ +# WinPR: Windows Portable Runtime +# libwinpr-crypto cmake build script +# +# 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. + +set(MODULE_NAME "winpr-crypto") +set(MODULE_PREFIX "WINPR_CRYPTO") + +set(${MODULE_PREFIX}_SRCS + crypto.c + cert.c) + +if(MSVC AND (NOT MONOLITHIC_BUILD)) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) +endif() + +add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" + MONOLITHIC ${MONOLITHIC_BUILD} + SOURCES ${${MODULE_PREFIX}_SRCS}) + +set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") + +if(MONOLITHIC_BUILD) + +else() + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") + diff --git a/winpr/libwinpr/crypto/ModuleOptions.cmake b/winpr/libwinpr/crypto/ModuleOptions.cmake new file mode 100644 index 000000000..39cbfe1e1 --- /dev/null +++ b/winpr/libwinpr/crypto/ModuleOptions.cmake @@ -0,0 +1,9 @@ + +set(MINWIN_LAYER "1") +set(MINWIN_GROUP "core") +set(MINWIN_MAJOR_VERSION "1") +set(MINWIN_MINOR_VERSION "0") +set(MINWIN_SHORT_NAME "crypto") +set(MINWIN_LONG_NAME "Cryptography API (CryptoAPI)") +set(MODULE_LIBRARY_NAME "crypt32") + diff --git a/winpr/libwinpr/crypto/cert.c b/winpr/libwinpr/crypto/cert.c new file mode 100644 index 000000000..5309c8161 --- /dev/null +++ b/winpr/libwinpr/crypto/cert.c @@ -0,0 +1,157 @@ +/** + * WinPR: Windows Portable Runtime + * Cryptography API (CryptoAPI) + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/** + * CertAddCertificateContextToStore + * CertAddCertificateLinkToStore + * CertAddCRLContextToStore + * CertAddCRLLinkToStore + * CertAddCTLContextToStore + * CertAddCTLLinkToStore + * CertAddEncodedCertificateToStore + * CertAddEncodedCertificateToSystemStoreA + * CertAddEncodedCertificateToSystemStoreW + * CertAddEncodedCRLToStore + * CertAddEncodedCTLToStore + * CertAddSerializedElementToStore + * CertAddStoreToCollection + * CertControlStore + * CertCloseStore + * CertDeleteCertificateFromStore + * CertDeleteCRLFromStore + * CertDeleteCTLFromStore + * CertDuplicateStore + * CertGetCRLFromStore + * CertEnumCertificatesInStore + * CertEnumCRLsInStore + * CertEnumCTLsInStore + * CertEnumPhysicalStore + * CertEnumSystemStore + * CertEnumSystemStoreLocation + * CertFindCertificateInStore + * CertFindChainInStore + * CertFindCRLInStore + * CertFindCTLInStore + * CertGetIssuerCertificateFromStore + * CertGetStoreProperty + * CertGetSubjectCertificateFromStore + * CertOpenStore + * CertOpenSystemStoreA + * CertOpenSystemStoreW + * CertRegisterPhysicalStore + * CertRegisterSystemStore + * CertRemoveStoreFromCollection + * CertSaveStore + * CertSerializeCertificateStoreElement + * CertSerializeCRLStoreElement + * CertSerializeCTLStoreElement + * CertSetStoreProperty + * CertUnregisterPhysicalStore + * CertUnregisterSystemStore + * + * CertAddEnhancedKeyUsageIdentifier + * CertAddRefServerOcspResponse + * CertAddRefServerOcspResponseContext + * CertAlgIdToOID + * CertCloseServerOcspResponse + * CertCompareCertificate + * CertCompareCertificateName + * CertCompareIntegerBlob + * CertComparePublicKeyInfo + * CertCreateCertificateChainEngine + * CertCreateCertificateContext + * CertCreateContext + * CertCreateCRLContext + * CertCreateCTLContext + * CertCreateCTLEntryFromCertificateContextProperties + * CertCreateSelfSignCertificate + * CertDuplicateCertificateChain + * CertDuplicateCertificateContext + * CertDuplicateCRLContext + * CertDuplicateCTLContext + * CertEnumCertificateContextProperties + * CertEnumCRLContextProperties + * CertEnumCTLContextProperties + * CertEnumSubjectInSortedCTL + * CertFindAttribute + * CertFindCertificateInCRL + * CertFindExtension + * CertFindRDNAttr + * CertFindSubjectInCTL + * CertFindSubjectInSortedCTL + * CertFreeCertificateChain + * CertFreeCertificateChainEngine + * CertFreeCertificateChainList + * CertFreeCertificateContext + * CertFreeCRLContext + * CertFreeCTLContext + * CertFreeServerOcspResponseContext + * CertGetCertificateChain + * CertGetCertificateContextProperty + * CertGetCRLContextProperty + * CertGetCTLContextProperty + * CertGetEnhancedKeyUsage + * CertGetIntendedKeyUsage + * CertGetNameStringA + * CertGetNameStringW + * CertGetPublicKeyLength + * CertGetServerOcspResponseContext + * CertGetValidUsages + * CertIsRDNAttrsInCertificateName + * CertIsStrongHashToSign + * CertIsValidCRLForCertificate + * CertNameToStrA + * CertNameToStrW + * CertOIDToAlgId + * CertOpenServerOcspResponse + * CertRDNValueToStrA + * CertRDNValueToStrW + * CertRemoveEnhancedKeyUsageIdentifier + * CertResyncCertificateChainEngine + * CertRetrieveLogoOrBiometricInfo + * CertSelectCertificateChains + * CertSetCertificateContextPropertiesFromCTLEntry + * CertSetCertificateContextProperty + * CertSetCRLContextProperty + * CertSetCTLContextProperty + * CertSetEnhancedKeyUsage + * CertStrToNameA + * CertStrToNameW + * CertVerifyCertificateChainPolicy + * CertVerifyCRLRevocation + * CertVerifyCRLTimeValidity + * CertVerifyCTLUsage + * CertVerifyRevocation + * CertVerifySubjectCertificateContext + * CertVerifyTimeValidity + * CertVerifyValidityNesting + */ + +#ifndef _WIN32 + + + +#endif + diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c new file mode 100644 index 000000000..5c6a1a6cd --- /dev/null +++ b/winpr/libwinpr/crypto/crypto.c @@ -0,0 +1,149 @@ +/** + * WinPR: Windows Portable Runtime + * Cryptography API (CryptoAPI) + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/** + * CryptAcquireCertificatePrivateKey + * CryptBinaryToStringA + * CryptBinaryToStringW + * CryptCloseAsyncHandle + * CryptCreateAsyncHandle + * CryptCreateKeyIdentifierFromCSP + * CryptDecodeMessage + * CryptDecodeObject + * CryptDecodeObjectEx + * CryptDecryptAndVerifyMessageSignature + * CryptDecryptMessage + * CryptEncodeObject + * CryptEncodeObjectEx + * CryptEncryptMessage + * CryptEnumKeyIdentifierProperties + * CryptEnumOIDFunction + * CryptEnumOIDInfo + * CryptExportPKCS8 + * CryptExportPublicKeyInfo + * CryptExportPublicKeyInfoEx + * CryptExportPublicKeyInfoFromBCryptKeyHandle + * CryptFindCertificateKeyProvInfo + * CryptFindLocalizedName + * CryptFindOIDInfo + * CryptFormatObject + * CryptFreeOIDFunctionAddress + * CryptGetAsyncParam + * CryptGetDefaultOIDDllList + * CryptGetDefaultOIDFunctionAddress + * CryptGetKeyIdentifierProperty + * CryptGetMessageCertificates + * CryptGetMessageSignerCount + * CryptGetOIDFunctionAddress + * CryptGetOIDFunctionValue + * CryptHashCertificate + * CryptHashCertificate2 + * CryptHashMessage + * CryptHashPublicKeyInfo + * CryptHashToBeSigned + * CryptImportPKCS8 + * CryptImportPublicKeyInfo + * CryptImportPublicKeyInfoEx + * CryptImportPublicKeyInfoEx2 + * CryptInitOIDFunctionSet + * CryptInstallDefaultContext + * CryptInstallOIDFunctionAddress + * CryptLoadSip + * CryptMemAlloc + * CryptMemFree + * CryptMemRealloc + * CryptMsgCalculateEncodedLength + * CryptMsgClose + * CryptMsgControl + * CryptMsgCountersign + * CryptMsgCountersignEncoded + * CryptMsgDuplicate + * CryptMsgEncodeAndSignCTL + * CryptMsgGetAndVerifySigner + * CryptMsgGetParam + * CryptMsgOpenToDecode + * CryptMsgOpenToEncode + * CryptMsgSignCTL + * CryptMsgUpdate + * CryptMsgVerifyCountersignatureEncoded + * CryptMsgVerifyCountersignatureEncodedEx + * CryptProtectData + * CryptProtectMemory + * CryptQueryObject + * CryptRegisterDefaultOIDFunction + * CryptRegisterOIDFunction + * CryptRegisterOIDInfo + * CryptRetrieveTimeStamp + * CryptSetAsyncParam + * CryptSetKeyIdentifierProperty + * CryptSetOIDFunctionValue + * CryptSignAndEncodeCertificate + * CryptSignAndEncryptMessage + * CryptSignCertificate + * CryptSignMessage + * CryptSignMessageWithKey + * CryptSIPAddProvider + * CryptSIPCreateIndirectData + * CryptSIPGetCaps + * CryptSIPGetSignedDataMsg + * CryptSIPLoad + * CryptSIPPutSignedDataMsg + * CryptSIPRemoveProvider + * CryptSIPRemoveSignedDataMsg + * CryptSIPRetrieveSubjectGuid + * CryptSIPRetrieveSubjectGuidForCatalogFile + * CryptSIPVerifyIndirectData + * CryptStringToBinaryA + * CryptStringToBinaryW + * CryptUninstallDefaultContext + * CryptUnprotectData + * CryptUnprotectMemory + * CryptUnregisterDefaultOIDFunction + * CryptUnregisterOIDFunction + * CryptUnregisterOIDInfo + * CryptUpdateProtectedState + * CryptVerifyCertificateSignature + * CryptVerifyCertificateSignatureEx + * CryptVerifyDetachedMessageHash + * CryptVerifyDetachedMessageSignature + * CryptVerifyMessageHash + * CryptVerifyMessageSignature + * CryptVerifyMessageSignatureWithKey + * CryptVerifyTimeStampSignature + * DbgInitOSS + * DbgPrintf + * PFXExportCertStore + * PFXExportCertStore2 + * PFXExportCertStoreEx + * PFXImportCertStore + * PFXIsPFXBlob + * PFXVerifyPassword + */ + +#ifndef _WIN32 + + + +#endif diff --git a/winpr/libwinpr/crypto/module.def b/winpr/libwinpr/crypto/module.def new file mode 100644 index 000000000..d21b12685 --- /dev/null +++ b/winpr/libwinpr/crypto/module.def @@ -0,0 +1,3 @@ +LIBRARY "libwinpr-crypto" +EXPORTS + diff --git a/winpr/libwinpr/pool/CMakeLists.txt b/winpr/libwinpr/pool/CMakeLists.txt index 7470c0a92..9841e4392 100644 --- a/winpr/libwinpr/pool/CMakeLists.txt +++ b/winpr/libwinpr/pool/CMakeLists.txt @@ -1,5 +1,5 @@ # WinPR: Windows Portable Runtime -# libwinpr-thread cmake build script +# libwinpr-pool cmake build script # # Copyright 2012 Marc-Andre Moreau # From f9ad678a51bb88de14473feb2669be1ba75622ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 22 Dec 2012 02:39:39 -0500 Subject: [PATCH 02/24] libfreerdp-client: fix /pcb and /pcid --- client/common/cmdline.c | 2 ++ winpr/libwinpr/crypto/cert.c | 35 +++++++++++++------------ winpr/libwinpr/sspi/Schannel/schannel.h | 1 + 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index a3a08a62f..8461068bb 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -96,6 +96,8 @@ COMMAND_LINE_ARGUMENT_A args[] = { "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" }, { "cert-name", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "certificate name" }, { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" }, + { "pcb", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Preconnection Blob" }, + { "pcid", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Preconnection Id" }, { "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "authentication (hack!)" }, { "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "encryption (hack!)" }, { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "grab keyboard" }, diff --git a/winpr/libwinpr/crypto/cert.c b/winpr/libwinpr/crypto/cert.c index 5309c8161..56f38f5da 100644 --- a/winpr/libwinpr/crypto/cert.c +++ b/winpr/libwinpr/crypto/cert.c @@ -24,6 +24,24 @@ #include /** + * CertOpenStore + * CertCloseStore + * CertControlStore + * CertDuplicateStore + * CertSaveStore + * CertRegisterPhysicalStore + * CertRegisterSystemStore + * CertAddStoreToCollection + * CertRemoveStoreFromCollection + * CertOpenSystemStoreA + * CertOpenSystemStoreW + * CertEnumPhysicalStore + * CertEnumSystemStore + * CertEnumSystemStoreLocation + * CertSetStoreProperty + * CertUnregisterPhysicalStore + * CertUnregisterSystemStore + * * CertAddCertificateContextToStore * CertAddCertificateLinkToStore * CertAddCRLContextToStore @@ -36,20 +54,13 @@ * CertAddEncodedCRLToStore * CertAddEncodedCTLToStore * CertAddSerializedElementToStore - * CertAddStoreToCollection - * CertControlStore - * CertCloseStore * CertDeleteCertificateFromStore * CertDeleteCRLFromStore * CertDeleteCTLFromStore - * CertDuplicateStore * CertGetCRLFromStore * CertEnumCertificatesInStore * CertEnumCRLsInStore * CertEnumCTLsInStore - * CertEnumPhysicalStore - * CertEnumSystemStore - * CertEnumSystemStoreLocation * CertFindCertificateInStore * CertFindChainInStore * CertFindCRLInStore @@ -57,19 +68,9 @@ * CertGetIssuerCertificateFromStore * CertGetStoreProperty * CertGetSubjectCertificateFromStore - * CertOpenStore - * CertOpenSystemStoreA - * CertOpenSystemStoreW - * CertRegisterPhysicalStore - * CertRegisterSystemStore - * CertRemoveStoreFromCollection - * CertSaveStore * CertSerializeCertificateStoreElement * CertSerializeCRLStoreElement * CertSerializeCTLStoreElement - * CertSetStoreProperty - * CertUnregisterPhysicalStore - * CertUnregisterSystemStore * * CertAddEnhancedKeyUsageIdentifier * CertAddRefServerOcspResponse diff --git a/winpr/libwinpr/sspi/Schannel/schannel.h b/winpr/libwinpr/sspi/Schannel/schannel.h index aeac6f675..956bba2ff 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.h +++ b/winpr/libwinpr/sspi/Schannel/schannel.h @@ -21,6 +21,7 @@ #define WINPR_SSPI_SCHANNEL_PRIVATE_H #include +#include #include "../sspi.h" From 093a0edd9c0ea9e4dea3e860d3934b291ad1e049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 22 Dec 2012 03:58:09 -0500 Subject: [PATCH 03/24] libwinpr-sspi: add schannel definitions --- winpr/include/winpr/crypto.h | 74 +++++++ winpr/include/winpr/schannel.h | 262 ++++++++++++++++++++++++ winpr/libwinpr/sspi/Schannel/schannel.c | 177 +++++++++------- winpr/libwinpr/sspi/Schannel/schannel.h | 2 +- 4 files changed, 439 insertions(+), 76 deletions(-) create mode 100644 winpr/include/winpr/schannel.h diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index a71067e9e..b9cc3fdc5 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -25,6 +25,80 @@ #ifndef _WIN32 +typedef struct _CRYPTOAPI_BLOB +{ + DWORD cbData; + BYTE* pbData; +} CRYPT_INTEGER_BLOB, *PCRYPT_INTEGER_BLOB, +CRYPT_UINT_BLOB, *PCRYPT_UINT_BLOB, +CRYPT_OBJID_BLOB, *PCRYPT_OBJID_BLOB, +CERT_NAME_BLOB, *PCERT_NAME_BLOB, +CERT_RDN_VALUE_BLOB, *PCERT_RDN_VALUE_BLOB, +CERT_BLOB, *PCERT_BLOB, +CRL_BLOB, *PCRL_BLOB, +DATA_BLOB, *PDATA_BLOB, +CRYPT_DATA_BLOB, *PCRYPT_DATA_BLOB, +CRYPT_HASH_BLOB, *PCRYPT_HASH_BLOB, +CRYPT_DIGEST_BLOB, *PCRYPT_DIGEST_BLOB, +CRYPT_DER_BLOB, *PCRYPT_DER_BLOB, +CRYPT_ATTR_BLOB, *PCRYPT_ATTR_BLOB; + +typedef struct _CRYPT_ALGORITHM_IDENTIFIER +{ + LPSTR pszObjId; + CRYPT_OBJID_BLOB Parameters; +} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER; + +typedef struct _CRYPT_BIT_BLOB +{ + DWORD cbData; + BYTE* pbData; + DWORD cUnusedBits; +} CRYPT_BIT_BLOB, *PCRYPT_BIT_BLOB; + +typedef struct _CERT_PUBLIC_KEY_INFO +{ + CRYPT_ALGORITHM_IDENTIFIER Algorithm; + CRYPT_BIT_BLOB PublicKey; +} CERT_PUBLIC_KEY_INFO, *PCERT_PUBLIC_KEY_INFO; + +typedef struct _CERT_EXTENSION +{ + LPSTR pszObjId; + BOOL fCritical; + CRYPT_OBJID_BLOB Value; +} CERT_EXTENSION, *PCERT_EXTENSION; +typedef const CERT_EXTENSION* PCCERT_EXTENSION; + +typedef struct _CERT_INFO +{ + DWORD dwVersion; + CRYPT_INTEGER_BLOB SerialNumber; + CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; + CERT_NAME_BLOB Issuer; + FILETIME NotBefore; + FILETIME NotAfter; + CERT_NAME_BLOB Subject; + CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo; + CRYPT_BIT_BLOB IssuerUniqueId; + CRYPT_BIT_BLOB SubjectUniqueId; + DWORD cExtension; + PCERT_EXTENSION rgExtension; +} CERT_INFO, *PCERT_INFO; + +typedef void *HCERTSTORE; +typedef ULONG_PTR HCRYPTPROV; + +typedef struct _CERT_CONTEXT +{ + DWORD dwCertEncodingType; + BYTE* pbCertEncoded; + DWORD cbCertEncoded; + PCERT_INFO pCertInfo; + HCERTSTORE hCertStore; +} CERT_CONTEXT, *PCERT_CONTEXT; +typedef const CERT_CONTEXT *PCCERT_CONTEXT; + #endif #endif /* WINPR_CRYPTO_H */ diff --git a/winpr/include/winpr/schannel.h b/winpr/include/winpr/schannel.h new file mode 100644 index 000000000..b0887463a --- /dev/null +++ b/winpr/include/winpr/schannel.h @@ -0,0 +1,262 @@ +/** + * WinPR: Windows Portable Runtime + * Schannel Security Package + * + * 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. + */ + +#ifndef WINPR_SSPI_SCHANNEL_H +#define WINPR_SSPI_SCHANNEL_H + +#include +#include + +#ifndef _WIN32 + +#define SCHANNEL_NAME_A "Schannel" +#define SCHANNEL_NAME_W L"Schannel" + +#ifdef _UNICODE +#define SCHANNEL_NAME SCHANNEL_NAME_W +#else +#define SCHANNEL_NAME SCHANNEL_NAME_A +#endif + +enum eTlsSignatureAlgorithm +{ + TlsSignatureAlgorithm_Anonymous = 0, + TlsSignatureAlgorithm_Rsa = 1, + TlsSignatureAlgorithm_Dsa = 2, + TlsSignatureAlgorithm_Ecdsa = 3 +}; + +enum eTlsHashAlgorithm +{ + TlsHashAlgorithm_None = 0, + TlsHashAlgorithm_Md5 = 1, + TlsHashAlgorithm_Sha1 = 2, + TlsHashAlgorithm_Sha224 = 3, + TlsHashAlgorithm_Sha256 = 4, + TlsHashAlgorithm_Sha384 = 5, + TlsHashAlgorithm_Sha512 = 6 +}; + +#define SCH_CRED_V1 0x00000001 +#define SCH_CRED_V2 0x00000002 +#define SCH_CRED_VERSION 0x00000002 +#define SCH_CRED_V3 0x00000003 +#define SCHANNEL_CRED_VERSION 0x00000004 + +struct _HMAPPER; + +typedef struct _SCHANNEL_CRED +{ + DWORD dwVersion; + DWORD cCreds; + PCCERT_CONTEXT* paCred; + HCERTSTORE hRootStore; + + DWORD cMappers; + struct _HMAPPER **aphMappers; + + DWORD cSupportedAlgs; + ALG_ID* palgSupportedAlgs; + + DWORD grbitEnabledProtocols; + DWORD dwMinimumCipherStrength; + DWORD dwMaximumCipherStrength; + DWORD dwSessionLifespan; + DWORD dwFlags; + DWORD dwCredFormat; +} SCHANNEL_CRED, *PSCHANNEL_CRED; + +#define SCH_CRED_FORMAT_CERT_CONTEXT 0x00000000 +#define SCH_CRED_FORMAT_CERT_HASH 0x00000001 +#define SCH_CRED_FORMAT_CERT_HASH_STORE 0x00000002 + +#define SCH_CRED_MAX_STORE_NAME_SIZE 128 +#define SCH_CRED_MAX_SUPPORTED_ALGS 256 +#define SCH_CRED_MAX_SUPPORTED_CERTS 100 + +typedef struct _SCHANNEL_CERT_HASH +{ + DWORD dwLength; + DWORD dwFlags; + HCRYPTPROV hProv; + BYTE ShaHash[20]; +} SCHANNEL_CERT_HASH, *PSCHANNEL_CERT_HASH; + +typedef struct _SCHANNEL_CERT_HASH_STORE +{ + DWORD dwLength; + DWORD dwFlags; + HCRYPTPROV hProv; + BYTE ShaHash[20]; + WCHAR pwszStoreName[SCH_CRED_MAX_STORE_NAME_SIZE]; +} SCHANNEL_CERT_HASH_STORE, *PSCHANNEL_CERT_HASH_STORE; + +#define SCH_MACHINE_CERT_HASH 0x00000001 + +#define SCH_CRED_NO_SYSTEM_MAPPER 0x00000002 +#define SCH_CRED_NO_SERVERNAME_CHECK 0x00000004 +#define SCH_CRED_MANUAL_CRED_VALIDATION 0x00000008 +#define SCH_CRED_NO_DEFAULT_CREDS 0x00000010 +#define SCH_CRED_AUTO_CRED_VALIDATION 0x00000020 +#define SCH_CRED_USE_DEFAULT_CREDS 0x00000040 +#define SCH_CRED_DISABLE_RECONNECTS 0x00000080 + +#define SCH_CRED_REVOCATION_CHECK_END_CERT 0x00000100 +#define SCH_CRED_REVOCATION_CHECK_CHAIN 0x00000200 +#define SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT 0x00000400 +#define SCH_CRED_IGNORE_NO_REVOCATION_CHECK 0x00000800 +#define SCH_CRED_IGNORE_REVOCATION_OFFLINE 0x00001000 + +#define SCH_CRED_RESTRICTED_ROOTS 0x00002000 +#define SCH_CRED_REVOCATION_CHECK_CACHE_ONLY 0x00004000 +#define SCH_CRED_CACHE_ONLY_URL_RETRIEVAL 0x00008000 + +#define SCH_CRED_MEMORY_STORE_CERT 0x00010000 + +#define SCH_CRED_CACHE_ONLY_URL_RETRIEVAL_ON_CREATE 0x00020000 + +#define SCH_SEND_ROOT_CERT 0x00040000 +#define SCH_CRED_SNI_CREDENTIAL 0x00080000 +#define SCH_CRED_SNI_ENABLE_OCSP 0x00100000 +#define SCH_SEND_AUX_RECORD 0x00200000 + +#define SCHANNEL_RENEGOTIATE 0 +#define SCHANNEL_SHUTDOWN 1 +#define SCHANNEL_ALERT 2 +#define SCHANNEL_SESSION 3 + +typedef struct _SCHANNEL_ALERT_TOKEN +{ + DWORD dwTokenType; + DWORD dwAlertType; + DWORD dwAlertNumber; +} SCHANNEL_ALERT_TOKEN; + +#define TLS1_ALERT_WARNING 1 +#define TLS1_ALERT_FATAL 2 + +#define TLS1_ALERT_CLOSE_NOTIFY 0 +#define TLS1_ALERT_UNEXPECTED_MESSAGE 10 +#define TLS1_ALERT_BAD_RECORD_MAC 20 +#define TLS1_ALERT_DECRYPTION_FAILED 21 +#define TLS1_ALERT_RECORD_OVERFLOW 22 +#define TLS1_ALERT_DECOMPRESSION_FAIL 30 +#define TLS1_ALERT_HANDSHAKE_FAILURE 40 +#define TLS1_ALERT_BAD_CERTIFICATE 42 +#define TLS1_ALERT_UNSUPPORTED_CERT 43 +#define TLS1_ALERT_CERTIFICATE_REVOKED 44 +#define TLS1_ALERT_CERTIFICATE_EXPIRED 45 +#define TLS1_ALERT_CERTIFICATE_UNKNOWN 46 +#define TLS1_ALERT_ILLEGAL_PARAMETER 47 +#define TLS1_ALERT_UNKNOWN_CA 48 +#define TLS1_ALERT_ACCESS_DENIED 49 +#define TLS1_ALERT_DECODE_ERROR 50 +#define TLS1_ALERT_DECRYPT_ERROR 51 +#define TLS1_ALERT_EXPORT_RESTRICTION 60 +#define TLS1_ALERT_PROTOCOL_VERSION 70 +#define TLS1_ALERT_INSUFFIENT_SECURITY 71 +#define TLS1_ALERT_INTERNAL_ERROR 80 +#define TLS1_ALERT_USER_CANCELED 90 +#define TLS1_ALERT_NO_RENEGOTIATION 100 +#define TLS1_ALERT_UNSUPPORTED_EXT 110 + +#define SSL_SESSION_ENABLE_RECONNECTS 1 +#define SSL_SESSION_DISABLE_RECONNECTS 2 + +typedef struct _SCHANNEL_SESSION_TOKEN +{ + DWORD dwTokenType; + DWORD dwFlags; +} SCHANNEL_SESSION_TOKEN; + +typedef struct _SCHANNEL_CLIENT_SIGNATURE +{ + DWORD cbLength; + ALG_ID aiHash; + DWORD cbHash; + BYTE HashValue[36]; + BYTE CertThumbprint[20]; +} SCHANNEL_CLIENT_SIGNATURE, *PSCHANNEL_CLIENT_SIGNATURE; + +#define SP_PROT_SSL3_SERVER 0x00000010 +#define SP_PROT_SSL3_CLIENT 0x00000020 +#define SP_PROT_SSL3 (SP_PROT_SSL3_SERVER | SP_PROT_SSL3_CLIENT) + +#define SP_PROT_TLS1_SERVER 0x00000040 +#define SP_PROT_TLS1_CLIENT 0x00000080 +#define SP_PROT_TLS1 (SP_PROT_TLS1_SERVER | SP_PROT_TLS1_CLIENT) + +#define SP_PROT_SSL3TLS1_CLIENTS (SP_PROT_TLS1_CLIENT | SP_PROT_SSL3_CLIENT) +#define SP_PROT_SSL3TLS1_SERVERS (SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER) +#define SP_PROT_SSL3TLS1 (SP_PROT_SSL3 | SP_PROT_TLS1) + +#define SP_PROT_UNI_SERVER 0x40000000 +#define SP_PROT_UNI_CLIENT 0x80000000 +#define SP_PROT_UNI (SP_PROT_UNI_SERVER | SP_PROT_UNI_CLIENT) + +#define SP_PROT_ALL 0xFFFFFFFF +#define SP_PROT_NONE 0 +#define SP_PROT_CLIENTS (SP_PROT_SSL3_CLIENT | SP_PROT_UNI_CLIENT | SP_PROT_TLS1_CLIENT) +#define SP_PROT_SERVERS (SP_PROT_SSL3_SERVER | SP_PROT_UNI_SERVER | SP_PROT_TLS1_SERVER) + +#define SP_PROT_TLS1_0_SERVER SP_PROT_TLS1_SERVER +#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT +#define SP_PROT_TLS1_0 (SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_0_CLIENT) + +#define SP_PROT_TLS1_1_SERVER 0x00000100 +#define SP_PROT_TLS1_1_CLIENT 0x00000200 +#define SP_PROT_TLS1_1 (SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT) + +#define SP_PROT_TLS1_2_SERVER 0x00000400 +#define SP_PROT_TLS1_2_CLIENT 0x00000800 +#define SP_PROT_TLS1_2 (SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_CLIENT) + +#define SP_PROT_DTLS_SERVER 0x00010000 +#define SP_PROT_DTLS_CLIENT 0x00020000 +#define SP_PROT_DTLS (SP_PROT_DTLS_SERVER | SP_PROT_DTLS_CLIENT) + +#define SP_PROT_DTLS1_0_SERVER SP_PROT_DTLS_SERVER +#define SP_PROT_DTLS1_0_CLIENT SP_PROT_DTLS_CLIENT +#define SP_PROT_DTLS1_0 (SP_PROT_DTLS1_0_SERVER | SP_PROT_DTLS1_0_CLIENT) + +#define SP_PROT_DTLS1_X_SERVER SP_PROT_DTLS1_0_SERVER + +#define SP_PROT_DTLS1_X_CLIENT SP_PROT_DTLS1_0_CLIENT + +#define SP_PROT_DTLS1_X (SP_PROT_DTLS1_X_SERVER | SP_PROT_DTLS1_X_CLIENT) + +#define SP_PROT_TLS1_1PLUS_SERVER (SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER) +#define SP_PROT_TLS1_1PLUS_CLIENT (SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT) + +#define SP_PROT_TLS1_1PLUS (SP_PROT_TLS1_1PLUS_SERVER | SP_PROT_TLS1_1PLUS_CLIENT) + +#define SP_PROT_TLS1_X_SERVER (SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER) +#define SP_PROT_TLS1_X_CLIENT (SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT) +#define SP_PROT_TLS1_X (SP_PROT_TLS1_X_SERVER | SP_PROT_TLS1_X_CLIENT) + +#define SP_PROT_SSL3TLS1_X_CLIENTS (SP_PROT_TLS1_X_CLIENT | SP_PROT_SSL3_CLIENT) +#define SP_PROT_SSL3TLS1_X_SERVERS (SP_PROT_TLS1_X_SERVER | SP_PROT_SSL3_SERVER) +#define SP_PROT_SSL3TLS1_X (SP_PROT_SSL3 | SP_PROT_TLS1_X) + +#define SP_PROT_X_CLIENTS (SP_PROT_CLIENTS | SP_PROT_TLS1_X_CLIENT | SP_PROT_DTLS1_X_CLIENT) +#define SP_PROT_X_SERVERS (SP_PROT_SERVERS | SP_PROT_TLS1_X_SERVER | SP_PROT_DTLS1_X_SERVER ) + +#endif + +#endif /* WINPR_SSPI_SCHANNEL_H */ diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index 4010bf2dd..ef8f0ece4 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -30,47 +30,15 @@ char* SCHANNEL_PACKAGE_NAME = "Schannel"; -SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) -{ - return SEC_E_OK; -} - -SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) -{ - SCHANNEL_CONTEXT* context; - CREDENTIALS* credentials; - - context = sspi_SecureHandleGetLowerPointer(phContext); - - if (!context) - { - context = schannel_ContextNew(); - - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - - sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); - } - - return SEC_E_OK; - -} - SCHANNEL_CONTEXT* schannel_ContextNew() { SCHANNEL_CONTEXT* context; - context = (SCHANNEL_CONTEXT*) calloc(1, sizeof(SCHANNEL_CONTEXT)); + context = (SCHANNEL_CONTEXT*) malloc(sizeof(SCHANNEL_CONTEXT)); if (context != NULL) { - + ZeroMemory(context, sizeof(SCHANNEL_CONTEXT)); } return context; @@ -84,14 +52,13 @@ void schannel_ContextFree(SCHANNEL_CONTEXT* context) free(context); } -SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) { - if (!phContext) - return SEC_E_INVALID_HANDLE; - - if (!pBuffer) - return SEC_E_INSUFFICIENT_MEMORY; + return SEC_E_UNSUPPORTED_FUNCTION; +} +SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +{ return SEC_E_UNSUPPORTED_FUNCTION; } @@ -99,6 +66,15 @@ SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(SEC_WCHAR* pszPrinc ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { + if (fCredentialUse == SECPKG_CRED_OUTBOUND) + { + return SEC_E_OK; + } + else if (fCredentialUse == SECPKG_CRED_INBOUND) + { + return SEC_E_OK; + } + return SEC_E_OK; } @@ -106,44 +82,22 @@ SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrinci ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { - CREDENTIALS* credentials; - SEC_WINNT_AUTH_IDENTITY* identity; + SECURITY_STATUS status; + SEC_WCHAR* pszPrincipalW = NULL; + SEC_WCHAR* pszPackageW = NULL; - if (fCredentialUse == SECPKG_CRED_OUTBOUND) - { - credentials = sspi_CredentialsNew(); - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; + ConvertToUnicode(CP_UTF8, 0, pszPrincipal, -1, &pszPrincipalW, 0); + ConvertToUnicode(CP_UTF8, 0, pszPackage, -1, &pszPackageW, 0); - //CopyMemory(&(credentials->identity), identity, sizeof(SEC_WINNT_AUTH_IDENTITY)); + status = schannel_AcquireCredentialsHandleW(pszPrincipalW, pszPackageW, fCredentialUse, pvLogonID, + pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); - sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME); - - return SEC_E_OK; - } + free(pszPrincipalW); + free(pszPackageW); return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) -{ - return SEC_E_OK; -} - -SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) -{ - if (ulAttribute == SECPKG_CRED_ATTR_NAMES) - { - CREDENTIALS* credentials; - - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - - return SEC_E_OK; - } - - return SEC_E_UNSUPPORTED_FUNCTION; -} - SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredential) { CREDENTIALS* credentials; @@ -161,16 +115,79 @@ SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredentia return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { + SCHANNEL_CONTEXT* context; + SCHANNEL_CRED* credentials; + + context = sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + { + context = schannel_ContextNew(); + + if (!context) + return SEC_E_INSUFFICIENT_MEMORY; + + credentials = (SCHANNEL_CRED*) sspi_SecureHandleGetLowerPointer(phCredential); + + sspi_SecureHandleSetLowerPointer(phNewContext, context); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); + } + return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { + SECURITY_STATUS status; + SEC_WCHAR* pszTargetNameW = NULL; + + if (pszTargetName != NULL) + { + ConvertToUnicode(CP_UTF8, 0, pszTargetName, -1, &pszTargetNameW, 0); + } + + status = schannel_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq, + Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); + + if (pszTargetNameW != NULL) + free(pszTargetNameW); + + return status; +} + +SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(PCtxtHandle phContext) +{ + SCHANNEL_CONTEXT* context; + + context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + schannel_ContextFree(context); + return SEC_E_OK; } +SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +{ + if (!phContext) + return SEC_E_INVALID_HANDLE; + + if (!pBuffer) + return SEC_E_INSUFFICIENT_MEMORY; + + return SEC_E_UNSUPPORTED_FUNCTION; +} + SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { return SEC_E_OK; @@ -181,6 +198,16 @@ SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(PCtxtHandle phContext, PSecBu return SEC_E_OK; } +SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +{ + return SEC_E_OK; +} + +SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +{ + return SEC_E_OK; +} + const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA = { 1, /* dwVersion */ @@ -192,7 +219,7 @@ const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA = schannel_InitializeSecurityContextA, /* InitializeSecurityContext */ NULL, /* AcceptSecurityContext */ NULL, /* CompleteAuthToken */ - NULL, /* DeleteSecurityContext */ + schannel_DeleteSecurityContext, /* DeleteSecurityContext */ NULL, /* ApplyControlToken */ schannel_QueryContextAttributes, /* QueryContextAttributes */ NULL, /* ImpersonateSecurityContext */ @@ -224,7 +251,7 @@ const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW = schannel_InitializeSecurityContextW, /* InitializeSecurityContext */ NULL, /* AcceptSecurityContext */ NULL, /* CompleteAuthToken */ - NULL, /* DeleteSecurityContext */ + schannel_DeleteSecurityContext, /* DeleteSecurityContext */ NULL, /* ApplyControlToken */ schannel_QueryContextAttributes, /* QueryContextAttributes */ NULL, /* ImpersonateSecurityContext */ diff --git a/winpr/libwinpr/sspi/Schannel/schannel.h b/winpr/libwinpr/sspi/Schannel/schannel.h index 956bba2ff..325b5111d 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.h +++ b/winpr/libwinpr/sspi/Schannel/schannel.h @@ -21,7 +21,7 @@ #define WINPR_SSPI_SCHANNEL_PRIVATE_H #include -#include +#include #include "../sspi.h" From af05962a8e075ac5e94e2f46ab14e2b13764b3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 22 Dec 2012 12:18:13 -0500 Subject: [PATCH 04/24] libwinpr-sspi: added more Schannel definitions --- winpr/include/winpr/crypto.h | 152 ++++++++++++++++++++++++ winpr/include/winpr/schannel.h | 21 ++++ winpr/libwinpr/sspi/Schannel/schannel.c | 130 ++++++++++++++++++-- winpr/libwinpr/sspi/Schannel/schannel.h | 8 ++ 4 files changed, 303 insertions(+), 8 deletions(-) diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index b9cc3fdc5..12ad53da3 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -25,6 +25,158 @@ #ifndef _WIN32 +#define GET_ALG_CLASS(x) (x & (7 << 13)) +#define GET_ALG_TYPE(x) (x & (15 << 9)) +#define GET_ALG_SID(x) (x & (511)) + +#define ALG_CLASS_ANY (0) +#define ALG_CLASS_SIGNATURE (1 << 13) +#define ALG_CLASS_MSG_ENCRYPT (2 << 13) +#define ALG_CLASS_DATA_ENCRYPT (3 << 13) +#define ALG_CLASS_HASH (4 << 13) +#define ALG_CLASS_KEY_EXCHANGE (5 << 13) +#define ALG_CLASS_ALL (7 << 13) + +#define ALG_TYPE_ANY (0) +#define ALG_TYPE_DSS (1 << 9) +#define ALG_TYPE_RSA (2 << 9) +#define ALG_TYPE_BLOCK (3 << 9) +#define ALG_TYPE_STREAM (4 << 9) +#define ALG_TYPE_DH (5 << 9) +#define ALG_TYPE_SECURECHANNEL (6 << 9) + +#define ALG_SID_ANY (0) + +#define ALG_SID_RSA_ANY 0 +#define ALG_SID_RSA_PKCS 1 +#define ALG_SID_RSA_MSATWORK 2 +#define ALG_SID_RSA_ENTRUST 3 +#define ALG_SID_RSA_PGP 4 + +#define ALG_SID_DSS_ANY 0 +#define ALG_SID_DSS_PKCS 1 +#define ALG_SID_DSS_DMS 2 + +#define ALG_SID_ECDSA 3 + +#define ALG_SID_DES 1 +#define ALG_SID_3DES 3 +#define ALG_SID_DESX 4 +#define ALG_SID_IDEA 5 +#define ALG_SID_CAST 6 +#define ALG_SID_SAFERSK64 7 +#define ALG_SID_SAFERSK128 8 +#define ALG_SID_3DES_112 9 +#define ALG_SID_CYLINK_MEK 12 +#define ALG_SID_RC5 13 + +#define ALG_SID_AES_128 14 +#define ALG_SID_AES_192 15 +#define ALG_SID_AES_256 16 +#define ALG_SID_AES 17 + +#define ALG_SID_SKIPJACK 10 +#define ALG_SID_TEK 11 + +#define CRYPT_MODE_CBCI 6 +#define CRYPT_MODE_CFBP 7 +#define CRYPT_MODE_OFBP 8 +#define CRYPT_MODE_CBCOFM 9 +#define CRYPT_MODE_CBCOFMI 10 + +#define ALG_SID_RC2 2 + +#define ALG_SID_RC4 1 +#define ALG_SID_SEAL 2 + +#define ALG_SID_DH_SANDF 1 +#define ALG_SID_DH_EPHEM 2 +#define ALG_SID_AGREED_KEY_ANY 3 +#define ALG_SID_KEA 4 + +#define ALG_SID_ECDH 5 + +#define ALG_SID_MD2 1 +#define ALG_SID_MD4 2 +#define ALG_SID_MD5 3 +#define ALG_SID_SHA 4 +#define ALG_SID_SHA1 4 +#define ALG_SID_MAC 5 +#define ALG_SID_RIPEMD 6 +#define ALG_SID_RIPEMD160 7 +#define ALG_SID_SSL3SHAMD5 8 +#define ALG_SID_HMAC 9 +#define ALG_SID_TLS1PRF 10 + +#define ALG_SID_HASH_REPLACE_OWF 11 + +#define ALG_SID_SHA_256 12 +#define ALG_SID_SHA_384 13 +#define ALG_SID_SHA_512 14 + +#define ALG_SID_SSL3_MASTER 1 +#define ALG_SID_SCHANNEL_MASTER_HASH 2 +#define ALG_SID_SCHANNEL_MAC_KEY 3 +#define ALG_SID_PCT1_MASTER 4 +#define ALG_SID_SSL2_MASTER 5 +#define ALG_SID_TLS1_MASTER 6 +#define ALG_SID_SCHANNEL_ENC_KEY 7 + +#define ALG_SID_ECMQV 1 + +#define CALG_MD2 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD2) +#define CALG_MD4 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4) +#define CALG_MD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5) +#define CALG_SHA (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA) +#define CALG_SHA1 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1) +#define CALG_MAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MAC) +#define CALG_RSA_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY) +#define CALG_DSS_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_DSS_ANY) + +#define CALG_NO_SIGN (ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | ALG_SID_ANY) + +#define CALG_RSA_KEYX (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RSA | ALG_SID_RSA_ANY) +#define CALG_DES (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DES) +#define CALG_3DES_112 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES_112) +#define CALG_3DES (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES) +#define CALG_DESX (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_DESX) +#define CALG_RC2 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC2) +#define CALG_RC4 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_RC4) +#define CALG_SEAL (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_STREAM | ALG_SID_SEAL) +#define CALG_DH_SF (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_SANDF) +#define CALG_DH_EPHEM (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_DH_EPHEM) +#define CALG_AGREEDKEY_ANY (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_AGREED_KEY_ANY) +#define CALG_KEA_KEYX (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_KEA) +#define CALG_HUGHES_MD5 (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_MD5) +#define CALG_SKIPJACK (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_SKIPJACK) +#define CALG_TEK (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_TEK) +#define CALG_CYLINK_MEK (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_CYLINK_MEK) +#define CALG_SSL3_SHAMD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5) +#define CALG_SSL3_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SSL3_MASTER) +#define CALG_SCHANNEL_MASTER_HASH (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_MASTER_HASH) +#define CALG_SCHANNEL_MAC_KEY (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_MAC_KEY) +#define CALG_SCHANNEL_ENC_KEY (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SCHANNEL_ENC_KEY) +#define CALG_PCT1_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_PCT1_MASTER) +#define CALG_SSL2_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_SSL2_MASTER) +#define CALG_TLS1_MASTER (ALG_CLASS_MSG_ENCRYPT | ALG_TYPE_SECURECHANNEL | ALG_SID_TLS1_MASTER) +#define CALG_RC5 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_RC5) +#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) +#define CALG_TLS1PRF (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_TLS1PRF) + +#define CALG_HASH_REPLACE_OWF (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HASH_REPLACE_OWF) +#define CALG_AES_128 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_128) +#define CALG_AES_192 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_192) +#define CALG_AES_256 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_256) +#define CALG_AES (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES) + +#define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) +#define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384) +#define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512) + +#define CALG_ECDH (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH) +#define CALG_ECMQV (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV) +#define CALG_ECDSA (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA) + typedef struct _CRYPTOAPI_BLOB { DWORD cbData; diff --git a/winpr/include/winpr/schannel.h b/winpr/include/winpr/schannel.h index b0887463a..46c61f2b6 100644 --- a/winpr/include/winpr/schannel.h +++ b/winpr/include/winpr/schannel.h @@ -34,6 +34,27 @@ #define SCHANNEL_NAME SCHANNEL_NAME_A #endif +#define SECPKG_ATTR_SUPPORTED_ALGS 86 +#define SECPKG_ATTR_CIPHER_STRENGTHS 87 +#define SECPKG_ATTR_SUPPORTED_PROTOCOLS 88 + +typedef struct _SecPkgCred_SupportedAlgs +{ + DWORD cSupportedAlgs; + ALG_ID* palgSupportedAlgs; +} SecPkgCred_SupportedAlgs, *PSecPkgCred_SupportedAlgs; + +typedef struct _SecPkgCred_CipherStrengths +{ + DWORD dwMinimumCipherStrength; + DWORD dwMaximumCipherStrength; +} SecPkgCred_CipherStrengths, *PSecPkgCred_CipherStrengths; + +typedef struct _SecPkgCred_SupportedProtocols +{ + DWORD grbitProtocol; +} SecPkgCred_SupportedProtocols, *PSecPkgCred_SupportedProtocols; + enum eTlsSignatureAlgorithm { TlsSignatureAlgorithm_Anonymous = 0, diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index ef8f0ece4..9cfb3d880 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -52,26 +52,98 @@ void schannel_ContextFree(SCHANNEL_CONTEXT* context) free(context); } +SCHANNEL_CREDENTIALS* schannel_CredentialsNew() +{ + SCHANNEL_CREDENTIALS* credentials; + + credentials = (SCHANNEL_CREDENTIALS*) malloc(sizeof(SCHANNEL_CREDENTIALS)); + + if (credentials != NULL) + { + ZeroMemory(credentials, sizeof(SCHANNEL_CREDENTIALS)); + } + + return credentials; +} + +void schannel_CredentialsFree(SCHANNEL_CREDENTIALS* credentials) +{ + if (!credentials) + return; + + free(credentials); +} + SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) { + if (ulAttribute == SECPKG_ATTR_SUPPORTED_ALGS) + { + PSecPkgCred_SupportedAlgs SupportedAlgs = (PSecPkgCred_SupportedAlgs) pBuffer; + + SupportedAlgs->cSupportedAlgs = 0; + SupportedAlgs->palgSupportedAlgs = NULL; + + return SEC_E_OK; + } + else if (ulAttribute == SECPKG_ATTR_CIPHER_STRENGTHS) + { + PSecPkgCred_CipherStrengths CipherStrengths = (PSecPkgCred_CipherStrengths) pBuffer; + + CipherStrengths->dwMinimumCipherStrength = 128; + CipherStrengths->dwMaximumCipherStrength = 256; + + return SEC_E_OK; + } + else if (ulAttribute == SECPKG_ATTR_SUPPORTED_PROTOCOLS) + { + PSecPkgCred_SupportedProtocols SupportedProtocols = (PSecPkgCred_SupportedProtocols) pBuffer; + + SupportedProtocols->grbitProtocol = (SP_PROT_CLIENTS | SP_PROT_SERVERS); + + return SEC_E_OK; + } + return SEC_E_UNSUPPORTED_FUNCTION; } SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) { - return SEC_E_UNSUPPORTED_FUNCTION; + return schannel_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer); } SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { + SCHANNEL_CREDENTIALS* credentials; + if (fCredentialUse == SECPKG_CRED_OUTBOUND) { + SCHANNEL_CRED* cred; + + credentials = schannel_CredentialsNew(); + credentials->fCredentialUse = fCredentialUse; + + cred = (SCHANNEL_CRED*) pAuthData; + + if (cred) + { + CopyMemory(&credentials->cred, cred, sizeof(SCHANNEL_CRED)); + } + + sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); + sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME); + return SEC_E_OK; } else if (fCredentialUse == SECPKG_CRED_INBOUND) { + credentials = schannel_CredentialsNew(); + credentials->fCredentialUse = fCredentialUse; + + sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); + sspi_SecureHandleSetUpperPointer(phCredential, (void*) SCHANNEL_PACKAGE_NAME); + return SEC_E_OK; } @@ -100,17 +172,17 @@ SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(SEC_CHAR* pszPrinci SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle phCredential) { - CREDENTIALS* credentials; + SCHANNEL_CREDENTIALS* credentials; if (!phCredential) return SEC_E_INVALID_HANDLE; - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); if (!credentials) return SEC_E_INVALID_HANDLE; - sspi_CredentialsFree(credentials); + schannel_CredentialsFree(credentials); return SEC_E_OK; } @@ -121,7 +193,7 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SCHANNEL_CONTEXT* context; - SCHANNEL_CRED* credentials; + SCHANNEL_CREDENTIALS* credentials; context = sspi_SecureHandleGetLowerPointer(phContext); @@ -132,7 +204,10 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred if (!context) return SEC_E_INSUFFICIENT_MEMORY; - credentials = (SCHANNEL_CRED*) sspi_SecureHandleGetLowerPointer(phCredential); + credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + + context->server = FALSE; + CopyMemory(&context->cred, &credentials->cred, sizeof(SCHANNEL_CRED)); sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); @@ -163,6 +238,33 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(PCredHandle phCred return status; } +SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) +{ + SCHANNEL_CONTEXT* context; + SCHANNEL_CREDENTIALS* credentials; + + context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + { + context = schannel_ContextNew(); + + if (!context) + return SEC_E_INSUFFICIENT_MEMORY; + + credentials = (SCHANNEL_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + + context->server = TRUE; + + sspi_SecureHandleSetLowerPointer(phNewContext, context); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); + } + + return SEC_E_OK; +} + SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(PCtxtHandle phContext) { SCHANNEL_CONTEXT* context; @@ -185,6 +287,18 @@ SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, if (!pBuffer) return SEC_E_INSUFFICIENT_MEMORY; + if (ulAttribute == SECPKG_ATTR_SIZES) + { + SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; + + ContextSizes->cbMaxToken = 0x6000; + ContextSizes->cbMaxSignature = 16; + ContextSizes->cbBlockSize = 0; + ContextSizes->cbSecurityTrailer = 16; + + return SEC_E_OK; + } + return SEC_E_UNSUPPORTED_FUNCTION; } @@ -217,7 +331,7 @@ const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA = schannel_FreeCredentialsHandle, /* FreeCredentialsHandle */ NULL, /* Reserved2 */ schannel_InitializeSecurityContextA, /* InitializeSecurityContext */ - NULL, /* AcceptSecurityContext */ + schannel_AcceptSecurityContext, /* AcceptSecurityContext */ NULL, /* CompleteAuthToken */ schannel_DeleteSecurityContext, /* DeleteSecurityContext */ NULL, /* ApplyControlToken */ @@ -249,7 +363,7 @@ const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW = schannel_FreeCredentialsHandle, /* FreeCredentialsHandle */ NULL, /* Reserved2 */ schannel_InitializeSecurityContextW, /* InitializeSecurityContext */ - NULL, /* AcceptSecurityContext */ + schannel_AcceptSecurityContext, /* AcceptSecurityContext */ NULL, /* CompleteAuthToken */ schannel_DeleteSecurityContext, /* DeleteSecurityContext */ NULL, /* ApplyControlToken */ diff --git a/winpr/libwinpr/sspi/Schannel/schannel.h b/winpr/libwinpr/sspi/Schannel/schannel.h index 325b5111d..3256aca68 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.h +++ b/winpr/libwinpr/sspi/Schannel/schannel.h @@ -25,9 +25,17 @@ #include "../sspi.h" +struct _SCHANNEL_CREDENTIALS +{ + SCHANNEL_CRED cred; + ULONG fCredentialUse; +}; +typedef struct _SCHANNEL_CREDENTIALS SCHANNEL_CREDENTIALS; + struct _SCHANNEL_CONTEXT { BOOL server; + SCHANNEL_CRED cred; }; typedef struct _SCHANNEL_CONTEXT SCHANNEL_CONTEXT; From 1c89b62f550789a56433bb94d899826c1538870e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 22 Dec 2012 20:23:44 -0500 Subject: [PATCH 05/24] libwinpr-sspi: added Schannel test --- winpr/libwinpr/sspi/sspi.c | 24 ++-- winpr/libwinpr/sspi/test/CMakeLists.txt | 5 +- winpr/libwinpr/sspi/test/TestSchannel.c | 158 ++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 9 deletions(-) create mode 100644 winpr/libwinpr/sspi/test/TestSchannel.c diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c index 9a10a03ae..fffa38d57 100644 --- a/winpr/libwinpr/sspi/sspi.c +++ b/winpr/libwinpr/sspi/sspi.c @@ -40,24 +40,31 @@ extern const SecPkgInfoA NTLM_SecPkgInfoA; extern const SecPkgInfoW NTLM_SecPkgInfoW; -extern const SecPkgInfoA CREDSSP_SecPkgInfoA; -extern const SecPkgInfoW CREDSSP_SecPkgInfoW; - extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA; extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW; + +extern const SecPkgInfoA CREDSSP_SecPkgInfoA; +extern const SecPkgInfoW CREDSSP_SecPkgInfoW; extern const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA; extern const SecurityFunctionTableW CREDSSP_SecurityFunctionTableW; +extern const SecPkgInfoA SCHANNEL_SecPkgInfoA; +extern const SecPkgInfoW SCHANNEL_SecPkgInfoW; +extern const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA; +extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW; + const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, - &CREDSSP_SecPkgInfoA + &CREDSSP_SecPkgInfoA, + &SCHANNEL_SecPkgInfoA }; const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, - &CREDSSP_SecPkgInfoW + &CREDSSP_SecPkgInfoW, + &SCHANNEL_SecPkgInfoW }; SecurityFunctionTableA SSPI_SecurityFunctionTableA; @@ -80,16 +87,19 @@ typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME; const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = { { "NTLM", &NTLM_SecurityFunctionTableA }, - { "CREDSSP", &CREDSSP_SecurityFunctionTableA } + { "CREDSSP", &CREDSSP_SecurityFunctionTableA }, + { "Schannel", &SCHANNEL_SecurityFunctionTableA } }; WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' }; WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' }; +WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l','\0' }; const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = { { NTLM_NAME_W, &NTLM_SecurityFunctionTableW }, - { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW } + { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW }, + { SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW } }; #endif diff --git a/winpr/libwinpr/sspi/test/CMakeLists.txt b/winpr/libwinpr/sspi/test/CMakeLists.txt index dddaa9917..dba3e7564 100644 --- a/winpr/libwinpr/sspi/test/CMakeLists.txt +++ b/winpr/libwinpr/sspi/test/CMakeLists.txt @@ -8,7 +8,8 @@ set(${MODULE_PREFIX}_TESTS TestQuerySecurityPackageInfo.c TestEnumerateSecurityPackages.c TestInitializeSecurityContext.c - TestAcquireCredentialsHandle.c) + TestAcquireCredentialsHandle.c + TestSchannel.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} @@ -23,7 +24,7 @@ endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-sspi) + MODULES winpr-sspi winpr-thread) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c new file mode 100644 index 000000000..15bf1e609 --- /dev/null +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -0,0 +1,158 @@ + +#include +#include +#include +#include + +static void* schannel_test_server_thread(void* arg) +{ + UINT32 cbMaxToken; + SCHANNEL_CRED cred; + CredHandle credentials; + SECURITY_STATUS status; + PSecPkgInfo pPackageInfo; + PSecurityFunctionTable table; + + table = InitSecurityInterface(); + + status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); + + if (status != SEC_E_OK) + { + printf("QuerySecurityPackageInfo failure: 0x%08X\n", status); + return -1; + } + + cbMaxToken = pPackageInfo->cbMaxToken; + + ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); + cred.dwVersion = SCHANNEL_CRED_VERSION; + cred.cSupportedAlgs = 0; + cred.palgSupportedAlgs = NULL; + + status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, + SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); + + if (status != SEC_E_OK) + { + printf("AcquireCredentialsHandle failure: 0x%08X\n", status); + return -1; + } + + return NULL; +} + +int TestSchannel(int argc, char* argv[]) +{ + HANDLE ServerThread; + UINT32 cbMaxToken; + SCHANNEL_CRED cred; + UINT32 fContextReq; + ULONG fContextAttr; + CtxtHandle context; + CredHandle credentials; + SECURITY_STATUS status; + PSecPkgInfo pPackageInfo; + SecBuffer SecBuffer_in[2]; + SecBuffer SecBuffer_out[1]; + SecBufferDesc SecBufferDesc_in; + SecBufferDesc SecBufferDesc_out; + PSecurityFunctionTable table; + SecPkgCred_SupportedAlgs SupportedAlgs; + SecPkgCred_CipherStrengths CipherStrengths; + SecPkgCred_SupportedProtocols SupportedProtocols; + + sspi_GlobalInit(); + + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) schannel_test_server_thread, NULL, 0, NULL); + + table = InitSecurityInterface(); + + status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); + + if (status != SEC_E_OK) + { + printf("QuerySecurityPackageInfo failure: 0x%08X\n", status); + return -1; + } + + cbMaxToken = pPackageInfo->cbMaxToken; + + ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); + cred.dwVersion = SCHANNEL_CRED_VERSION; + cred.cSupportedAlgs = 0; + cred.palgSupportedAlgs = NULL; + + status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, + SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); + + if (status != SEC_E_OK) + { + printf("AcquireCredentialsHandle failure: 0x%08X\n", status); + return -1; + } + + ZeroMemory(&SupportedAlgs, sizeof(SecPkgCred_SupportedAlgs)); + status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_ALGS, &SupportedAlgs); + + if (status != SEC_E_OK) + { + printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_ALGS failure: 0x%08X\n", status); + return -1; + } + + ZeroMemory(&CipherStrengths, sizeof(SecPkgCred_CipherStrengths)); + status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS, &CipherStrengths); + + if (status != SEC_E_OK) + { + printf("QueryCredentialsAttributes SECPKG_ATTR_CIPHER_STRENGTHS failure: 0x%08X\n", status); + return -1; + } + + ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols)); + status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &SupportedProtocols); + + if (status != SEC_E_OK) + { + printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_PROTOCOLS failure: 0x%08X\n", status); + return -1; + } + + fContextReq = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | + ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY; + + ZeroMemory(&SecBuffer_in, sizeof(SecBuffer_in)); + ZeroMemory(&SecBuffer_out, sizeof(SecBuffer_out)); + ZeroMemory(&SecBufferDesc_in, sizeof(SecBufferDesc)); + ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc)); + + SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_in[0].pvBuffer = malloc(cbMaxToken); + SecBuffer_in[0].cbBuffer = cbMaxToken; + + SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; + + SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_in.cBuffers = 2; + SecBufferDesc_in.pBuffers = SecBuffer_in; + + SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; + + SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_out.cBuffers = 1; + SecBufferDesc_out.pBuffers = SecBuffer_out; + + status = table->InitializeSecurityContext(&credentials, NULL, _T("localhost"), + fContextReq, 0, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, NULL); + + if (status != SEC_I_CONTINUE_NEEDED) + { + printf("InitializeSecurityContext unexpected status: 0x%08X\n", status); + return -1; + } + + sspi_GlobalFinish(); + + return 0; +} From d4e580834f24e0f0e402317b44e5c716b564895a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 23 Dec 2012 13:21:57 -0500 Subject: [PATCH 06/24] libwinpr-sspi: fix build on Windows --- winpr/include/winpr/schannel.h | 6 +++++- winpr/libwinpr/sspi/test/TestSchannel.c | 28 +++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/winpr/include/winpr/schannel.h b/winpr/include/winpr/schannel.h index 46c61f2b6..b1afab8a0 100644 --- a/winpr/include/winpr/schannel.h +++ b/winpr/include/winpr/schannel.h @@ -23,7 +23,11 @@ #include #include -#ifndef _WIN32 +#ifdef _WIN32 + +#include + +#else #define SCHANNEL_NAME_A "Schannel" #define SCHANNEL_NAME_W L"Schannel" diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 15bf1e609..3681c6d86 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -20,7 +20,7 @@ static void* schannel_test_server_thread(void* arg) if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo failure: 0x%08X\n", status); - return -1; + return NULL; } cbMaxToken = pPackageInfo->cbMaxToken; @@ -36,7 +36,7 @@ static void* schannel_test_server_thread(void* arg) if (status != SEC_E_OK) { printf("AcquireCredentialsHandle failure: 0x%08X\n", status); - return -1; + return NULL; } return NULL; @@ -44,6 +44,7 @@ static void* schannel_test_server_thread(void* arg) int TestSchannel(int argc, char* argv[]) { + int index; HANDLE ServerThread; UINT32 cbMaxToken; SCHANNEL_CRED cred; @@ -101,6 +102,20 @@ int TestSchannel(int argc, char* argv[]) return -1; } + /** + * SupportedAlgs: 15 + * 0x660E 0x6610 0x6801 0x6603 0x6601 0x8003 0x8004 + * 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203 + */ + + printf("SupportedAlgs: %d\n", SupportedAlgs.cSupportedAlgs); + + for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++) + { + printf(" 0x%04X", SupportedAlgs.palgSupportedAlgs[index]); + } + printf("\n"); + ZeroMemory(&CipherStrengths, sizeof(SecPkgCred_CipherStrengths)); status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS, &CipherStrengths); @@ -110,6 +125,11 @@ int TestSchannel(int argc, char* argv[]) return -1; } + /* CipherStrengths: Minimum: 40 Maximum: 256 */ + + printf("CipherStrengths: Minimum: %d Maximum: %d\n", + CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength); + ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols)); status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &SupportedProtocols); @@ -119,6 +139,10 @@ int TestSchannel(int argc, char* argv[]) return -1; } + /* SupportedProtocols: 0x208A0 */ + + printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol); + fContextReq = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY; From 85690a3ec740d7f26c4e5a59b8e8ec8efed8faa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 23 Dec 2012 14:38:58 -0500 Subject: [PATCH 07/24] libwinpr-sspi: improve Schannel QueryCredentialsAttributes stubs --- winpr/include/winpr/crypto.h | 1 + winpr/libwinpr/sspi/Schannel/schannel.c | 16 +++++++++++++--- winpr/libwinpr/sspi/test/TestSchannel.c | 9 ++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 12ad53da3..6210a541c 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -44,6 +44,7 @@ #define ALG_TYPE_STREAM (4 << 9) #define ALG_TYPE_DH (5 << 9) #define ALG_TYPE_SECURECHANNEL (6 << 9) +#define ALG_TYPE_RESERVED7 (7 << 9) #define ALG_SID_ANY (0) diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index 9cfb3d880..720fbd38e 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -74,14 +74,23 @@ void schannel_CredentialsFree(SCHANNEL_CREDENTIALS* credentials) free(credentials); } +static ALG_ID schannel_SupportedAlgs[] = +{ + CALG_AES_128, CALG_AES_256, CALG_RC4, CALG_DES, CALG_3DES, + CALG_MD5, CALG_SHA1, CALG_SHA_256, CALG_SHA_384, CALG_SHA_512, + CALG_RSA_SIGN, CALG_DH_EPHEM, + (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RESERVED7 | 6), /* what is this? */ + CALG_DSS_SIGN, CALG_ECDSA +}; + SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) { if (ulAttribute == SECPKG_ATTR_SUPPORTED_ALGS) { PSecPkgCred_SupportedAlgs SupportedAlgs = (PSecPkgCred_SupportedAlgs) pBuffer; - SupportedAlgs->cSupportedAlgs = 0; - SupportedAlgs->palgSupportedAlgs = NULL; + SupportedAlgs->cSupportedAlgs = sizeof(schannel_SupportedAlgs) / sizeof(ALG_ID); + SupportedAlgs->palgSupportedAlgs = (ALG_ID*) schannel_SupportedAlgs; return SEC_E_OK; } @@ -89,7 +98,7 @@ SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCre { PSecPkgCred_CipherStrengths CipherStrengths = (PSecPkgCred_CipherStrengths) pBuffer; - CipherStrengths->dwMinimumCipherStrength = 128; + CipherStrengths->dwMinimumCipherStrength = 40; CipherStrengths->dwMaximumCipherStrength = 256; return SEC_E_OK; @@ -98,6 +107,7 @@ SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(PCredHandle phCre { PSecPkgCred_SupportedProtocols SupportedProtocols = (PSecPkgCred_SupportedProtocols) pBuffer; + /* Observed SupportedProtocols: 0x208A0 */ SupportedProtocols->grbitProtocol = (SP_PROT_CLIENTS | SP_PROT_SERVERS); return SEC_E_OK; diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 3681c6d86..716da893c 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -45,7 +45,8 @@ static void* schannel_test_server_thread(void* arg) int TestSchannel(int argc, char* argv[]) { int index; - HANDLE ServerThread; + ALG_ID algId; + HANDLE thread; UINT32 cbMaxToken; SCHANNEL_CRED cred; UINT32 fContextReq; @@ -65,7 +66,7 @@ int TestSchannel(int argc, char* argv[]) sspi_GlobalInit(); - CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) schannel_test_server_thread, NULL, 0, NULL); + thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) schannel_test_server_thread, NULL, 0, NULL); table = InitSecurityInterface(); @@ -112,7 +113,9 @@ int TestSchannel(int argc, char* argv[]) for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++) { - printf(" 0x%04X", SupportedAlgs.palgSupportedAlgs[index]); + algId = SupportedAlgs.palgSupportedAlgs[index]; + printf("\t0x%04X CLASS: %d TYPE: %d SID: %d\n", algId, + ((GET_ALG_CLASS(algId)) >> 13), ((GET_ALG_TYPE(algId)) >> 9), GET_ALG_SID(algId)); } printf("\n"); From a5aa8fc2cc01d7ac68334e15f517993e71a6d71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 23 Dec 2012 18:41:02 -0500 Subject: [PATCH 08/24] libwinpr-sspi: improved Schannel test with fake client-server communication --- winpr/libwinpr/sspi/test/TestSchannel.c | 128 +++++++++++++++++++++++- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 716da893c..5b3328964 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -1,18 +1,40 @@ #include #include +#include #include #include +HANDLE g_ClientReadPipe = NULL; +HANDLE g_ClientWritePipe = NULL; +HANDLE g_ServerReadPipe = NULL; +HANDLE g_ServerWritePipe = NULL; + static void* schannel_test_server_thread(void* arg) { + BYTE* lpTokenIn; + BYTE* lpTokenOut; UINT32 cbMaxToken; + UINT32 fContextReq; + ULONG fContextAttr; SCHANNEL_CRED cred; + CtxtHandle context; CredHandle credentials; + PSecBuffer pSecBuffer; + SecBuffer SecBuffer_in[2]; + SecBuffer SecBuffer_out[2]; + SecBufferDesc SecBufferDesc_in; + SecBufferDesc SecBufferDesc_out; + DWORD NumberOfBytesRead; SECURITY_STATUS status; PSecPkgInfo pPackageInfo; PSecurityFunctionTable table; + printf("Starting Server\n"); + + SecInvalidateHandle(&context); + SecInvalidateHandle(&credentials); + table = InitSecurityInterface(); status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); @@ -39,6 +61,53 @@ static void* schannel_test_server_thread(void* arg) return NULL; } + lpTokenIn = (BYTE*) malloc(cbMaxToken); + lpTokenOut = (BYTE*) malloc(cbMaxToken); + + if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) + { + printf("Failed to read from server pipe\n"); + return NULL; + } + + printf("Server Received:\n"); + winpr_HexDump(lpTokenIn, NumberOfBytesRead); + + fContextReq = ASC_REQ_STREAM; + + SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_in[0].pvBuffer = lpTokenIn; + SecBuffer_in[0].cbBuffer = NumberOfBytesRead; + + SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; + SecBuffer_in[1].pvBuffer = NULL; + SecBuffer_in[1].cbBuffer = 0; + + SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_in.cBuffers = 2; + SecBufferDesc_in.pBuffers = SecBuffer_in; + + SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_out[0].pvBuffer = lpTokenOut; + SecBuffer_out[0].cbBuffer = NumberOfBytesRead; + + SecBuffer_out[1].BufferType = SECBUFFER_EMPTY; + SecBuffer_out[1].pvBuffer = NULL; + SecBuffer_out[1].cbBuffer = 0; + + SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_out.cBuffers = 2; + SecBufferDesc_out.pBuffers = SecBuffer_out; + + status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, + &SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, NULL); + + if (status != SEC_I_CONTINUE_NEEDED) + { + printf("AcceptSecurityContext unexpected status: 0x%08X\n", status); + return NULL; + } + return NULL; } @@ -47,6 +116,8 @@ int TestSchannel(int argc, char* argv[]) int index; ALG_ID algId; HANDLE thread; + BYTE* lpTokenIn; + BYTE* lpTokenOut; UINT32 cbMaxToken; SCHANNEL_CRED cred; UINT32 fContextReq; @@ -55,17 +126,34 @@ int TestSchannel(int argc, char* argv[]) CredHandle credentials; SECURITY_STATUS status; PSecPkgInfo pPackageInfo; + PSecBuffer pSecBuffer; SecBuffer SecBuffer_in[2]; SecBuffer SecBuffer_out[1]; SecBufferDesc SecBufferDesc_in; SecBufferDesc SecBufferDesc_out; PSecurityFunctionTable table; + DWORD NumberOfBytesWritten; SecPkgCred_SupportedAlgs SupportedAlgs; SecPkgCred_CipherStrengths CipherStrengths; SecPkgCred_SupportedProtocols SupportedProtocols; sspi_GlobalInit(); + SecInvalidateHandle(&context); + SecInvalidateHandle(&credentials); + + if (!CreatePipe(&g_ClientReadPipe, &g_ClientWritePipe, NULL, 0)) + { + printf("Failed to create client pipe\n"); + return -1; + } + + if (!CreatePipe(&g_ServerReadPipe, &g_ServerWritePipe, NULL, 0)) + { + printf("Failed to create server pipe\n"); + return -1; + } + thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) schannel_test_server_thread, NULL, 0, NULL); table = InitSecurityInterface(); @@ -146,8 +234,10 @@ int TestSchannel(int argc, char* argv[]) printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol); - fContextReq = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | - ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY; + fContextReq = ISC_REQ_STREAM; + + lpTokenIn = (BYTE*) malloc(cbMaxToken); + lpTokenOut = (BYTE*) malloc(cbMaxToken); ZeroMemory(&SecBuffer_in, sizeof(SecBuffer_in)); ZeroMemory(&SecBuffer_out, sizeof(SecBuffer_out)); @@ -155,7 +245,7 @@ int TestSchannel(int argc, char* argv[]) ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc)); SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; - SecBuffer_in[0].pvBuffer = malloc(cbMaxToken); + SecBuffer_in[0].pvBuffer = lpTokenIn; SecBuffer_in[0].cbBuffer = cbMaxToken; SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; @@ -165,12 +255,14 @@ int TestSchannel(int argc, char* argv[]) SecBufferDesc_in.pBuffers = SecBuffer_in; SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_out[0].pvBuffer = lpTokenOut; + SecBuffer_out[0].cbBuffer = cbMaxToken; SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; SecBufferDesc_out.cBuffers = 1; SecBufferDesc_out.pBuffers = SecBuffer_out; - status = table->InitializeSecurityContext(&credentials, NULL, _T("localhost"), + status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"), fContextReq, 0, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, NULL); if (status != SEC_I_CONTINUE_NEEDED) @@ -179,6 +271,34 @@ int TestSchannel(int argc, char* argv[]) return -1; } + printf("SecBufferDesc_out.cBuffers: %d\n", SecBufferDesc_out.cBuffers); + + pSecBuffer = &SecBufferDesc_out.pBuffers[0]; + winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); + + /** + * 0000 16 03 03 00 96 01 00 00 92 03 03 50 d7 7e 56 dd ...........P.~V. + * 0010 c9 01 59 01 49 d3 2f 99 ef da 77 01 a0 97 06 e7 ..Y.I./...w..... + * 0020 a4 fe 2d 71 46 55 fc 42 dd 2e 58 00 00 2a 00 3c ..-qFU.B..X..*.< + * 0030 00 2f 00 3d 00 35 00 05 00 0a c0 27 c0 13 c0 14 ./.=.5.....'.... + * 0040 c0 2b c0 23 c0 2c c0 24 c0 09 c0 0a 00 40 00 32 .+.#.,.$.....@.2 + * 0050 00 6a 00 38 00 13 00 04 01 00 00 3f ff 01 00 01 .j.8.......?.... + * 0060 00 00 00 00 0e 00 0c 00 00 09 6c 6f 63 61 6c 68 ..........localh + * 0070 6f 73 74 00 0a 00 06 00 04 00 17 00 18 00 0b 00 ost............. + * 0080 02 01 00 00 0d 00 10 00 0e 04 01 05 01 02 01 04 ................ + * 0090 03 05 03 02 03 02 02 00 23 00 00 ........#.. + */ + + if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) + { + printf("failed to write to server pipe\n"); + return -1; + } + + printf("Client wrote %d bytes\n", NumberOfBytesWritten); + + WaitForSingleObject(thread, INFINITE); + sspi_GlobalFinish(); return 0; From 52408231248ba5680dd0a1b32a0d8d5f9d82be62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 23 Dec 2012 18:59:59 -0500 Subject: [PATCH 09/24] libwinpr-sspi: fix build on Linux --- winpr/include/winpr/sspi.h | 8 ++++++++ winpr/libwinpr/sspi/test/CMakeLists.txt | 2 +- winpr/libwinpr/sspi/test/TestSchannel.c | 5 ++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/winpr/include/winpr/sspi.h b/winpr/include/winpr/sspi.h index f74e448ff..d486540b4 100644 --- a/winpr/include/winpr/sspi.h +++ b/winpr/include/winpr/sspi.h @@ -635,12 +635,20 @@ struct _SecHandle ULONG_PTR dwUpper; }; typedef struct _SecHandle SecHandle; +typedef SecHandle* PSecHandle; typedef SecHandle CredHandle; typedef CredHandle* PCredHandle; typedef SecHandle CtxtHandle; typedef CtxtHandle* PCtxtHandle; +#define SecInvalidateHandle(x) \ + ((PSecHandle)(x))->dwLower = ((PSecHandle)(x))->dwUpper = ((ULONG_PTR)((INT_PTR) - 1)); + +#define SecIsValidHandle(x) \ + ((((PSecHandle)(x))->dwLower != ((ULONG_PTR)((INT_PTR) - 1))) && \ + (((PSecHandle) (x))->dwUpper != ((ULONG_PTR)((INT_PTR) - 1)))) + #endif #define SECBUFFER_VERSION 0 diff --git a/winpr/libwinpr/sspi/test/CMakeLists.txt b/winpr/libwinpr/sspi/test/CMakeLists.txt index dba3e7564..af8bcc8b6 100644 --- a/winpr/libwinpr/sspi/test/CMakeLists.txt +++ b/winpr/libwinpr/sspi/test/CMakeLists.txt @@ -24,7 +24,7 @@ endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-sspi winpr-thread) + MODULES winpr-sspi winpr-thread winpr-pipe winpr-file winpr-utils) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 5b3328964..1784fb818 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -1,7 +1,10 @@ #include #include +#include +#include #include +#include #include #include @@ -20,7 +23,7 @@ static void* schannel_test_server_thread(void* arg) SCHANNEL_CRED cred; CtxtHandle context; CredHandle credentials; - PSecBuffer pSecBuffer; + //PSecBuffer pSecBuffer; SecBuffer SecBuffer_in[2]; SecBuffer SecBuffer_out[2]; SecBufferDesc SecBufferDesc_in; From 45ad6e9ac920c89afa951ffdfdc8b15881d82710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 23 Dec 2012 20:20:41 -0500 Subject: [PATCH 10/24] libwinpr-sspi: started OpenSSL-based Schannel implementation --- winpr/libwinpr/sspi/CMakeLists.txt | 2 + winpr/libwinpr/sspi/Schannel/schannel.c | 10 +- winpr/libwinpr/sspi/Schannel/schannel.h | 3 + .../libwinpr/sspi/Schannel/schannel_openssl.c | 179 ++++++++++++++++++ .../libwinpr/sspi/Schannel/schannel_openssl.h | 48 +++++ winpr/libwinpr/sspi/sspi.h | 2 + 6 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 winpr/libwinpr/sspi/Schannel/schannel_openssl.c create mode 100644 winpr/libwinpr/sspi/Schannel/schannel_openssl.h diff --git a/winpr/libwinpr/sspi/CMakeLists.txt b/winpr/libwinpr/sspi/CMakeLists.txt index f969e0e48..d6c6568ea 100644 --- a/winpr/libwinpr/sspi/CMakeLists.txt +++ b/winpr/libwinpr/sspi/CMakeLists.txt @@ -33,6 +33,8 @@ set(${MODULE_PREFIX}_NEGOTIATE_SRCS Negotiate/negotiate.h) set(${MODULE_PREFIX}_SCHANNEL_SRCS + Schannel/schannel_openssl.c + Schannel/schannel_openssl.h Schannel/schannel.c Schannel/schannel.h) diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index 720fbd38e..3757e2663 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -39,6 +39,8 @@ SCHANNEL_CONTEXT* schannel_ContextNew() if (context != NULL) { ZeroMemory(context, sizeof(SCHANNEL_CONTEXT)); + + context->openssl = schannel_openssl_new(); } return context; @@ -49,6 +51,8 @@ void schannel_ContextFree(SCHANNEL_CONTEXT* context) if (!context) return; + schannel_openssl_free(context->openssl); + free(context); } @@ -221,6 +225,8 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); + + schannel_openssl_client_init(context->openssl); } return SEC_E_OK; @@ -401,7 +407,7 @@ const SecPkgInfoA SCHANNEL_SecPkgInfoA = 0x000107B3, /* fCapabilities */ 1, /* wVersion */ 0x000E, /* wRPCID */ - 0x00006000, /* cbMaxToken */ + SCHANNEL_CB_MAX_TOKEN, /* cbMaxToken */ "Schannel", /* Name */ "Schannel Security Package" /* Comment */ }; @@ -420,7 +426,7 @@ const SecPkgInfoW SCHANNEL_SecPkgInfoW = 0x000107B3, /* fCapabilities */ 1, /* wVersion */ 0x000E, /* wRPCID */ - 0x00006000, /* cbMaxToken */ + SCHANNEL_CB_MAX_TOKEN, /* cbMaxToken */ SCHANNEL_SecPkgInfoW_Name, /* Name */ SCHANNEL_SecPkgInfoW_Comment /* Comment */ }; diff --git a/winpr/libwinpr/sspi/Schannel/schannel.h b/winpr/libwinpr/sspi/Schannel/schannel.h index 3256aca68..0ec9a833c 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.h +++ b/winpr/libwinpr/sspi/Schannel/schannel.h @@ -25,6 +25,8 @@ #include "../sspi.h" +#include "schannel_openssl.h" + struct _SCHANNEL_CREDENTIALS { SCHANNEL_CRED cred; @@ -36,6 +38,7 @@ struct _SCHANNEL_CONTEXT { BOOL server; SCHANNEL_CRED cred; + SCHANNEL_OPENSSL* openssl; }; typedef struct _SCHANNEL_CONTEXT SCHANNEL_CONTEXT; diff --git a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c new file mode 100644 index 000000000..b8a380558 --- /dev/null +++ b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c @@ -0,0 +1,179 @@ +/** + * WinPR: Windows Portable Runtime + * Schannel Security Package (OpenSSL) + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "schannel_openssl.h" + +char* openssl_get_ssl_error_string(int ssl_error) +{ + switch (ssl_error) + { + case SSL_ERROR_ZERO_RETURN: + return "SSL_ERROR_ZERO_RETURN"; + + case SSL_ERROR_WANT_READ: + return "SSL_ERROR_WANT_READ"; + + case SSL_ERROR_WANT_WRITE: + return "SSL_ERROR_WANT_WRITE"; + + case SSL_ERROR_SYSCALL: + return "SSL_ERROR_SYSCALL"; + + case SSL_ERROR_SSL: + return "SSL_ERROR_SSL"; + } + + return "SSL_ERROR_UNKNOWN"; +} + +int schannel_openssl_client_init(SCHANNEL_OPENSSL* context) +{ + int status; + int ssl_error; + BYTE* ReadBuffer; + BYTE* WriteBuffer; + long options = 0; + + context->ctx = SSL_CTX_new(TLSv1_client_method()); + + if (!context->ctx) + { + printf("SSL_CTX_new failed\n"); + return -1; + } + + /** + * SSL_OP_NO_COMPRESSION: + * + * The Microsoft RDP server does not advertise support + * for TLS compression, but alternative servers may support it. + * This was observed between early versions of the FreeRDP server + * and the FreeRDP client, and caused major performance issues, + * which is why we're disabling it. + */ +#ifdef SSL_OP_NO_COMPRESSION + options |= SSL_OP_NO_COMPRESSION; +#endif + + /** + * SSL_OP_TLS_BLOCK_PADDING_BUG: + * + * The Microsoft RDP server does *not* support TLS padding. + * It absolutely needs to be disabled otherwise it won't work. + */ + options |= SSL_OP_TLS_BLOCK_PADDING_BUG; + + /** + * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: + * + * Just like TLS padding, the Microsoft RDP server does not + * support empty fragments. This needs to be disabled. + */ + options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + + SSL_CTX_set_options(context->ctx, options); + + context->ssl = SSL_new(context->ctx); + + if (!context->ssl) + { + printf("SSL_new failed\n"); + return -1; + } + + context->bioRead = BIO_new(BIO_s_mem()); + + if (!context->bioRead) + { + printf("BIO_new failed\n"); + return -1; + } + + status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN); + + context->bioWrite = BIO_new(BIO_s_mem()); + + if (!context->bioWrite) + { + printf("BIO_new failed\n"); + return -1; + } + + status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN); + + status = BIO_make_bio_pair(context->bioRead, context->bioWrite); + + SSL_set_bio(context->ssl, context->bioRead, context->bioWrite); + + status = SSL_connect(context->ssl); + + if (status < 0) + { + ssl_error = SSL_get_error(context->ssl, status); + printf("SSL_connect error: %s\n", openssl_get_ssl_error_string(ssl_error)); + } + + ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); + WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); + + status = BIO_read(context->bioWrite, ReadBuffer, SCHANNEL_CB_MAX_TOKEN); + + if (status >= 0) + { + winpr_HexDump(ReadBuffer, status); + } + + free(ReadBuffer); + free(WriteBuffer); + + return 0; +} + +SCHANNEL_OPENSSL* schannel_openssl_new() +{ + SCHANNEL_OPENSSL* context; + + context = (SCHANNEL_OPENSSL*) malloc(sizeof(SCHANNEL_OPENSSL)); + + if (context != NULL) + { + ZeroMemory(context, sizeof(SCHANNEL_OPENSSL)); + + SSL_load_error_strings(); + SSL_library_init(); + } + + return context; +} + +void schannel_openssl_free(SCHANNEL_OPENSSL* context) +{ + if (!context) + return; + + free(context); +} diff --git a/winpr/libwinpr/sspi/Schannel/schannel_openssl.h b/winpr/libwinpr/sspi/Schannel/schannel_openssl.h new file mode 100644 index 000000000..a023b7918 --- /dev/null +++ b/winpr/libwinpr/sspi/Schannel/schannel_openssl.h @@ -0,0 +1,48 @@ +/** + * WinPR: Windows Portable Runtime + * Schannel Security Package (OpenSSL) + * + * 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. + */ + +#ifndef WINPR_SSPI_SCHANNEL_OPENSSL_H +#define WINPR_SSPI_SCHANNEL_OPENSSL_H + +#include + +#include "../sspi.h" + +/* OpenSSL includes windows.h */ +#include + +#include +#include +#include + +struct _SCHANNEL_OPENSSL +{ + SSL* ssl; + SSL_CTX* ctx; + BIO* bioRead; + BIO* bioWrite; +}; +typedef struct _SCHANNEL_OPENSSL SCHANNEL_OPENSSL; + +int schannel_openssl_client_init(SCHANNEL_OPENSSL* context); + +SCHANNEL_OPENSSL* schannel_openssl_new(); +void schannel_openssl_free(SCHANNEL_OPENSSL* context); + +#endif /* WINPR_SSPI_SCHANNEL_OPENSSL_H */ diff --git a/winpr/libwinpr/sspi/sspi.h b/winpr/libwinpr/sspi/sspi.h index b51f72398..0144c83de 100644 --- a/winpr/libwinpr/sspi/sspi.h +++ b/winpr/libwinpr/sspi/sspi.h @@ -22,6 +22,8 @@ #include +#define SCHANNEL_CB_MAX_TOKEN 0x00006000 + struct _CREDENTIALS { SEC_WINNT_AUTH_IDENTITY identity; From 436a7dfc9f940222fca522abb2186001983296b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 28 Dec 2012 11:53:17 -0500 Subject: [PATCH 11/24] libwinpr-sspi: enable extended protection by default to restore TSG connectivity with most servers --- winpr/libwinpr/sspi/NTLM/ntlm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 6f8a16ecc..41c537898 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -133,7 +133,7 @@ NTLM_CONTEXT* ntlm_ContextNew() * Extended Protection is enabled by default in Windows 7, * but enabling it in WinPR breaks TS Gateway at this point */ - context->SuppressExtendedProtection = TRUE; + context->SuppressExtendedProtection = FALSE; status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\LSA"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); From 27084c46421f56323b0425615d0f928472ff2702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 3 Jan 2013 11:13:13 -0500 Subject: [PATCH 12/24] libwinpr-sspi: improve SSPI Schannel test --- server/Windows/wf_rdpsnd.c | 5 +- winpr/libwinpr/crypto/CMakeLists.txt | 4 + winpr/libwinpr/sspi/CMakeLists.txt | 2 +- winpr/libwinpr/sspi/test/CMakeLists.txt | 4 +- winpr/libwinpr/sspi/test/TestSchannel.c | 117 ++++++++++++++++-------- 5 files changed, 91 insertions(+), 41 deletions(-) diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 8ef5b2775..f3b104841 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -24,7 +24,8 @@ #include #include -#include +#include + #define CINTERFACE #include #include @@ -38,7 +39,7 @@ * Here are some temp things that shall be moved * */ -IDirectSoundCapture8 * cap; +IDirectSoundCapture8* cap; IDirectSoundCaptureBuffer8* capBuf; DSCBUFFERDESC dscbd; DWORD capturePos; diff --git a/winpr/libwinpr/crypto/CMakeLists.txt b/winpr/libwinpr/crypto/CMakeLists.txt index a935afac1..00809dad5 100644 --- a/winpr/libwinpr/crypto/CMakeLists.txt +++ b/winpr/libwinpr/crypto/CMakeLists.txt @@ -32,6 +32,10 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") +if(WIN32) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} crypt32) +endif() + if(MONOLITHIC_BUILD) else() diff --git a/winpr/libwinpr/sspi/CMakeLists.txt b/winpr/libwinpr/sspi/CMakeLists.txt index d6c6568ea..2811b57fd 100644 --- a/winpr/libwinpr/sspi/CMakeLists.txt +++ b/winpr/libwinpr/sspi/CMakeLists.txt @@ -81,7 +81,7 @@ endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL MODULE winpr - MODULES winpr-crt winpr-sysinfo winpr-registry winpr-utils) + MODULES winpr-crt winpr-sysinfo winpr-registry winpr-crypto winpr-utils) if(MONOLITHIC_BUILD) set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/winpr/libwinpr/sspi/test/CMakeLists.txt b/winpr/libwinpr/sspi/test/CMakeLists.txt index af8bcc8b6..e1e660e94 100644 --- a/winpr/libwinpr/sspi/test/CMakeLists.txt +++ b/winpr/libwinpr/sspi/test/CMakeLists.txt @@ -18,13 +18,13 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) if(WIN32) - set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32) endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-sspi winpr-thread winpr-pipe winpr-file winpr-utils) + MODULES winpr-sspi winpr-thread winpr-pipe winpr-file winpr-crypto winpr-utils) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 1784fb818..84589b164 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -13,17 +13,26 @@ HANDLE g_ClientWritePipe = NULL; HANDLE g_ServerReadPipe = NULL; HANDLE g_ServerWritePipe = NULL; +#ifndef _WIN32 +#define SCHANNEL_PKG_NAME SCHANNEL_NAME +#else +#define SCHANNEL_PKG_NAME UNISP_NAME +#endif + static void* schannel_test_server_thread(void* arg) { BYTE* lpTokenIn; BYTE* lpTokenOut; + TimeStamp expiry; UINT32 cbMaxToken; UINT32 fContextReq; ULONG fContextAttr; SCHANNEL_CRED cred; CtxtHandle context; CredHandle credentials; - //PSecBuffer pSecBuffer; + HCERTSTORE hCertStore; + PCCERT_CONTEXT pCertContext; + PSecBuffer pSecBuffer; SecBuffer SecBuffer_in[2]; SecBuffer SecBuffer_out[2]; SecBufferDesc SecBufferDesc_in; @@ -32,6 +41,7 @@ static void* schannel_test_server_thread(void* arg) SECURITY_STATUS status; PSecPkgInfo pPackageInfo; PSecurityFunctionTable table; + DWORD NumberOfBytesWritten; printf("Starting Server\n"); @@ -40,7 +50,7 @@ static void* schannel_test_server_thread(void* arg) table = InitSecurityInterface(); - status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(SCHANNEL_PKG_NAME, &pPackageInfo); if (status != SEC_E_OK) { @@ -50,12 +60,36 @@ static void* schannel_test_server_thread(void* arg) cbMaxToken = pPackageInfo->cbMaxToken; + hCertStore = CertOpenSystemStore(0, _T("MY")); + + if (!hCertStore) + { + printf("Error opening system store\n"); + //return NULL; + } + + pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); + + if (!pCertContext) + { + printf("Error finding certificate in store\n"); + //return NULL; + } + ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); cred.dwVersion = SCHANNEL_CRED_VERSION; + + cred.cCreds = 1; + cred.paCred = &pCertContext; + cred.cSupportedAlgs = 0; cred.palgSupportedAlgs = NULL; - status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, + cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER; + + cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER; + + status = table->AcquireCredentialsHandle(NULL, SCHANNEL_PKG_NAME, SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); if (status != SEC_E_OK) @@ -76,34 +110,28 @@ static void* schannel_test_server_thread(void* arg) printf("Server Received:\n"); winpr_HexDump(lpTokenIn, NumberOfBytesRead); - fContextReq = ASC_REQ_STREAM; + fContextReq = ASC_REQ_STREAM | + ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | + ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR; SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; SecBuffer_in[0].pvBuffer = lpTokenIn; SecBuffer_in[0].cbBuffer = NumberOfBytesRead; - SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; - SecBuffer_in[1].pvBuffer = NULL; - SecBuffer_in[1].cbBuffer = 0; - SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_in.cBuffers = 2; + SecBufferDesc_in.cBuffers = 1; SecBufferDesc_in.pBuffers = SecBuffer_in; SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; SecBuffer_out[0].pvBuffer = lpTokenOut; - SecBuffer_out[0].cbBuffer = NumberOfBytesRead; - - SecBuffer_out[1].BufferType = SECBUFFER_EMPTY; - SecBuffer_out[1].pvBuffer = NULL; - SecBuffer_out[1].cbBuffer = 0; + SecBuffer_out[0].cbBuffer = cbMaxToken; SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_out.cBuffers = 2; + SecBufferDesc_out.cBuffers = 1; SecBufferDesc_out.pBuffers = SecBuffer_out; status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, - &SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, NULL); + &SecBufferDesc_in, fContextReq, SECURITY_NATIVE_DREP, &context, &SecBufferDesc_out, &fContextAttr, &expiry); if (status != SEC_I_CONTINUE_NEEDED) { @@ -111,6 +139,17 @@ static void* schannel_test_server_thread(void* arg) return NULL; } + printf("SecBufferDesc_out.cBuffers: %d\n", SecBufferDesc_out.cBuffers); + + pSecBuffer = &SecBufferDesc_out.pBuffers[0]; + winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); + + if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) + { + printf("failed to write to client pipe\n"); + return NULL; + } + return NULL; } @@ -121,6 +160,7 @@ int TestSchannel(int argc, char* argv[]) HANDLE thread; BYTE* lpTokenIn; BYTE* lpTokenOut; + TimeStamp expiry; UINT32 cbMaxToken; SCHANNEL_CRED cred; UINT32 fContextReq; @@ -135,6 +175,7 @@ int TestSchannel(int argc, char* argv[]) SecBufferDesc SecBufferDesc_in; SecBufferDesc SecBufferDesc_out; PSecurityFunctionTable table; + DWORD NumberOfBytesRead; DWORD NumberOfBytesWritten; SecPkgCred_SupportedAlgs SupportedAlgs; SecPkgCred_CipherStrengths CipherStrengths; @@ -161,7 +202,7 @@ int TestSchannel(int argc, char* argv[]) table = InitSecurityInterface(); - status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(SCHANNEL_PKG_NAME, &pPackageInfo); if (status != SEC_E_OK) { @@ -173,10 +214,20 @@ int TestSchannel(int argc, char* argv[]) ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); cred.dwVersion = SCHANNEL_CRED_VERSION; + + cred.cCreds = 0; + cred.paCred = NULL; + cred.cSupportedAlgs = 0; cred.palgSupportedAlgs = NULL; - status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, + cred.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS; + + cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS; + cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + + status = table->AcquireCredentialsHandle(NULL, SCHANNEL_PKG_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); if (status != SEC_E_OK) @@ -237,7 +288,10 @@ int TestSchannel(int argc, char* argv[]) printf("SupportedProtocols: 0x%04X\n", SupportedProtocols.grbitProtocol); - fContextReq = ISC_REQ_STREAM; + fContextReq = ISC_REQ_STREAM | + ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | + ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | + ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY; lpTokenIn = (BYTE*) malloc(cbMaxToken); lpTokenOut = (BYTE*) malloc(cbMaxToken); @@ -251,10 +305,8 @@ int TestSchannel(int argc, char* argv[]) SecBuffer_in[0].pvBuffer = lpTokenIn; SecBuffer_in[0].cbBuffer = cbMaxToken; - SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; - SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_in.cBuffers = 2; + SecBufferDesc_in.cBuffers = 1; SecBufferDesc_in.pBuffers = SecBuffer_in; SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; @@ -266,7 +318,7 @@ int TestSchannel(int argc, char* argv[]) SecBufferDesc_out.pBuffers = SecBuffer_out; status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"), - fContextReq, 0, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, NULL); + fContextReq, SECURITY_NATIVE_DREP, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); if (status != SEC_I_CONTINUE_NEEDED) { @@ -279,19 +331,6 @@ int TestSchannel(int argc, char* argv[]) pSecBuffer = &SecBufferDesc_out.pBuffers[0]; winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); - /** - * 0000 16 03 03 00 96 01 00 00 92 03 03 50 d7 7e 56 dd ...........P.~V. - * 0010 c9 01 59 01 49 d3 2f 99 ef da 77 01 a0 97 06 e7 ..Y.I./...w..... - * 0020 a4 fe 2d 71 46 55 fc 42 dd 2e 58 00 00 2a 00 3c ..-qFU.B..X..*.< - * 0030 00 2f 00 3d 00 35 00 05 00 0a c0 27 c0 13 c0 14 ./.=.5.....'.... - * 0040 c0 2b c0 23 c0 2c c0 24 c0 09 c0 0a 00 40 00 32 .+.#.,.$.....@.2 - * 0050 00 6a 00 38 00 13 00 04 01 00 00 3f ff 01 00 01 .j.8.......?.... - * 0060 00 00 00 00 0e 00 0c 00 00 09 6c 6f 63 61 6c 68 ..........localh - * 0070 6f 73 74 00 0a 00 06 00 04 00 17 00 18 00 0b 00 ost............. - * 0080 02 01 00 00 0d 00 10 00 0e 04 01 05 01 02 01 04 ................ - * 0090 03 05 03 02 03 02 02 00 23 00 00 ........#.. - */ - if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) { printf("failed to write to server pipe\n"); @@ -300,6 +339,12 @@ int TestSchannel(int argc, char* argv[]) printf("Client wrote %d bytes\n", NumberOfBytesWritten); + if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) + { + printf("failed to read from server pipe\n"); + return -1; + } + WaitForSingleObject(thread, INFINITE); sspi_GlobalFinish(); From 80daf6fb5cdd021a34ca7ae3888fa8ab5564b9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 3 Jan 2013 11:35:08 -0500 Subject: [PATCH 13/24] libwinpr-sspi: fix build on Linux --- winpr/include/winpr/crypto.h | 96 +++++++++++++++++++++++++ winpr/libwinpr/crypto/cert.c | 14 ++++ winpr/libwinpr/sspi/test/TestSchannel.c | 1 + 3 files changed, 111 insertions(+) diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 6210a541c..334b6c690 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -241,6 +241,7 @@ typedef struct _CERT_INFO typedef void *HCERTSTORE; typedef ULONG_PTR HCRYPTPROV; +typedef ULONG_PTR HCRYPTPROV_LEGACY; typedef struct _CERT_CONTEXT { @@ -252,6 +253,101 @@ typedef struct _CERT_CONTEXT } CERT_CONTEXT, *PCERT_CONTEXT; typedef const CERT_CONTEXT *PCCERT_CONTEXT; +#define CERT_ENCODING_TYPE_MASK 0x0000FFFF +#define CMSG_ENCODING_TYPE_MASK 0xFFFF0000 +#define GET_CERT_ENCODING_TYPE(x) (x & CERT_ENCODING_TYPE_MASK) +#define GET_CMSG_ENCODING_TYPE(x) (x & CMSG_ENCODING_TYPE_MASK) + +#define CRYPT_ASN_ENCODING 0x00000001 +#define CRYPT_NDR_ENCODING 0x00000002 +#define X509_ASN_ENCODING 0x00000001 +#define X509_NDR_ENCODING 0x00000002 +#define PKCS_7_ASN_ENCODING 0x00010000 +#define PKCS_7_NDR_ENCODING 0x00020000 + +#define CERT_COMPARE_MASK 0xFFFF +#define CERT_COMPARE_SHIFT 16 +#define CERT_COMPARE_ANY 0 +#define CERT_COMPARE_SHA1_HASH 1 +#define CERT_COMPARE_NAME 2 +#define CERT_COMPARE_ATTR 3 +#define CERT_COMPARE_MD5_HASH 4 +#define CERT_COMPARE_PROPERTY 5 +#define CERT_COMPARE_PUBLIC_KEY 6 +#define CERT_COMPARE_HASH CERT_COMPARE_SHA1_HASH +#define CERT_COMPARE_NAME_STR_A 7 +#define CERT_COMPARE_NAME_STR_W 8 +#define CERT_COMPARE_KEY_SPEC 9 +#define CERT_COMPARE_ENHKEY_USAGE 10 +#define CERT_COMPARE_CTL_USAGE CERT_COMPARE_ENHKEY_USAGE +#define CERT_COMPARE_SUBJECT_CERT 11 +#define CERT_COMPARE_ISSUER_OF 12 +#define CERT_COMPARE_EXISTING 13 +#define CERT_COMPARE_SIGNATURE_HASH 14 +#define CERT_COMPARE_KEY_IDENTIFIER 15 +#define CERT_COMPARE_CERT_ID 16 +#define CERT_COMPARE_CROSS_CERT_DIST_POINTS 17 +#define CERT_COMPARE_PUBKEY_MD5_HASH 18 +#define CERT_COMPARE_SUBJECT_INFO_ACCESS 19 +#define CERT_COMPARE_HASH_STR 20 +#define CERT_COMPARE_HAS_PRIVATE_KEY 21 + +#define CERT_FIND_ANY (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT) +#define CERT_FIND_SHA1_HASH (CERT_COMPARE_SHA1_HASH << CERT_COMPARE_SHIFT) +#define CERT_FIND_MD5_HASH (CERT_COMPARE_MD5_HASH << CERT_COMPARE_SHIFT) +#define CERT_FIND_SIGNATURE_HASH (CERT_COMPARE_SIGNATURE_HASH << CERT_COMPARE_SHIFT) +#define CERT_FIND_KEY_IDENTIFIER (CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT) +#define CERT_FIND_HASH CERT_FIND_SHA1_HASH +#define CERT_FIND_PROPERTY (CERT_COMPARE_PROPERTY << CERT_COMPARE_SHIFT) +#define CERT_FIND_PUBLIC_KEY (CERT_COMPARE_PUBLIC_KEY << CERT_COMPARE_SHIFT) +#define CERT_FIND_SUBJECT_NAME (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG) +#define CERT_FIND_SUBJECT_ATTR (CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG) +#define CERT_FIND_ISSUER_NAME (CERT_COMPARE_NAME << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG) +#define CERT_FIND_ISSUER_ATTR (CERT_COMPARE_ATTR << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG) +#define CERT_FIND_SUBJECT_STR_A (CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG) +#define CERT_FIND_SUBJECT_STR_W (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG) +#define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W +#define CERT_FIND_ISSUER_STR_A (CERT_COMPARE_NAME_STR_A << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG) +#define CERT_FIND_ISSUER_STR_W (CERT_COMPARE_NAME_STR_W << CERT_COMPARE_SHIFT | CERT_INFO_ISSUER_FLAG) +#define CERT_FIND_ISSUER_STR CERT_FIND_ISSUER_STR_W +#define CERT_FIND_KEY_SPEC (CERT_COMPARE_KEY_SPEC << CERT_COMPARE_SHIFT) +#define CERT_FIND_ENHKEY_USAGE (CERT_COMPARE_ENHKEY_USAGE << CERT_COMPARE_SHIFT) +#define CERT_FIND_CTL_USAGE CERT_FIND_ENHKEY_USAGE +#define CERT_FIND_SUBJECT_CERT (CERT_COMPARE_SUBJECT_CERT << CERT_COMPARE_SHIFT) +#define CERT_FIND_ISSUER_OF (CERT_COMPARE_ISSUER_OF << CERT_COMPARE_SHIFT) +#define CERT_FIND_EXISTING (CERT_COMPARE_EXISTING << CERT_COMPARE_SHIFT) +#define CERT_FIND_CERT_ID (CERT_COMPARE_CERT_ID << CERT_COMPARE_SHIFT) +#define CERT_FIND_CROSS_CERT_DIST_POINTS (CERT_COMPARE_CROSS_CERT_DIST_POINTS << CERT_COMPARE_SHIFT) +#define CERT_FIND_PUBKEY_MD5_HASH (CERT_COMPARE_PUBKEY_MD5_HASH << CERT_COMPARE_SHIFT) +#define CERT_FIND_SUBJECT_INFO_ACCESS (CERT_COMPARE_SUBJECT_INFO_ACCESS << CERT_COMPARE_SHIFT) +#define CERT_FIND_HASH_STR (CERT_COMPARE_HASH_STR << CERT_COMPARE_SHIFT) +#define CERT_FIND_HAS_PRIVATE_KEY (CERT_COMPARE_HAS_PRIVATE_KEY << CERT_COMPARE_SHIFT) + +#define CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG 0x1 +#define CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG 0x2 +#define CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG 0x4 +#define CERT_FIND_NO_ENHKEY_USAGE_FLAG 0x8 +#define CERT_FIND_OR_ENHKEY_USAGE_FLAG 0x10 +#define CERT_FIND_VALID_ENHKEY_USAGE_FLAG 0x20 +#define CERT_FIND_OPTIONAL_CTL_USAGE_FLAG CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG +#define CERT_FIND_EXT_ONLY_CTL_USAGE_FLAG CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG +#define CERT_FIND_PROP_ONLY_CTL_USAGE_FLAG CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG +#define CERT_FIND_NO_CTL_USAGE_FLAG CERT_FIND_NO_ENHKEY_USAGE_FLAG +#define CERT_FIND_OR_CTL_USAGE_FLAG CERT_FIND_OR_ENHKEY_USAGE_FLAG +#define CERT_FIND_VALID_CTL_USAGE_FLAG CERT_FIND_VALID_ENHKEY_USAGE_FLAG + +WINPR_API HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubsystemProtocol); +WINPR_API HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProtocol); + +#ifdef UNICODE +#define CertOpenSystemStore CertOpenSystemStoreW +#else +#define CertOpenSystemStore CertOpenSystemStoreA +#endif + +WINPR_API PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, + DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext); + #endif #endif /* WINPR_CRYPTO_H */ diff --git a/winpr/libwinpr/crypto/cert.c b/winpr/libwinpr/crypto/cert.c index 56f38f5da..bc989a631 100644 --- a/winpr/libwinpr/crypto/cert.c +++ b/winpr/libwinpr/crypto/cert.c @@ -152,7 +152,21 @@ #ifndef _WIN32 +HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubsystemProtocol) +{ + return (HCERTSTORE) 1; +} +HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProtocol) +{ + return CertOpenSystemStoreW(hProv, NULL); +} + +PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, + DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext) +{ + return (PCCERT_CONTEXT) 1; +} #endif diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 84589b164..477f05534 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -6,6 +6,7 @@ #include #include #include +#include #include HANDLE g_ClientReadPipe = NULL; From 985721d035bc2cf3518579199c09cb4021a77ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 3 Jan 2013 13:36:19 -0500 Subject: [PATCH 14/24] libwinpr-sspi: start implementing ISC and ASC for Schannel --- winpr/libwinpr/sspi/Schannel/schannel.c | 12 + .../libwinpr/sspi/Schannel/schannel_openssl.c | 249 ++++++++++++++++-- .../libwinpr/sspi/Schannel/schannel_openssl.h | 7 + 3 files changed, 242 insertions(+), 26 deletions(-) diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index 3757e2663..d6b5501d9 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -206,6 +206,7 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { + SECURITY_STATUS status; SCHANNEL_CONTEXT* context; SCHANNEL_CREDENTIALS* credentials; @@ -227,6 +228,10 @@ SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(PCredHandle phCred sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); schannel_openssl_client_init(context->openssl); + + status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput); + + return status; } return SEC_E_OK; @@ -258,6 +263,7 @@ SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredentia PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) { + SECURITY_STATUS status; SCHANNEL_CONTEXT* context; SCHANNEL_CREDENTIALS* credentials; @@ -276,6 +282,12 @@ SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(PCredHandle phCredentia sspi_SecureHandleSetLowerPointer(phNewContext, context); sspi_SecureHandleSetUpperPointer(phNewContext, (void*) SCHANNEL_PACKAGE_NAME); + + schannel_openssl_server_init(context->openssl); + + status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput); + + return status; } return SEC_E_OK; diff --git a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c index b8a380558..c33e33ac7 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c +++ b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c @@ -53,9 +53,6 @@ char* openssl_get_ssl_error_string(int ssl_error) int schannel_openssl_client_init(SCHANNEL_OPENSSL* context) { int status; - int ssl_error; - BYTE* ReadBuffer; - BYTE* WriteBuffer; long options = 0; context->ctx = SSL_CTX_new(TLSv1_client_method()); @@ -129,30 +126,225 @@ int schannel_openssl_client_init(SCHANNEL_OPENSSL* context) SSL_set_bio(context->ssl, context->bioRead, context->bioWrite); - status = SSL_connect(context->ssl); - - if (status < 0) - { - ssl_error = SSL_get_error(context->ssl, status); - printf("SSL_connect error: %s\n", openssl_get_ssl_error_string(ssl_error)); - } - - ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); - WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); - - status = BIO_read(context->bioWrite, ReadBuffer, SCHANNEL_CB_MAX_TOKEN); - - if (status >= 0) - { - winpr_HexDump(ReadBuffer, status); - } - - free(ReadBuffer); - free(WriteBuffer); + context->ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); + context->WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); return 0; } +int schannel_openssl_server_init(SCHANNEL_OPENSSL* context) +{ + int status; + long options = 0; + + context->ctx = SSL_CTX_new(SSLv23_server_method()); + + if (!context->ctx) + { + printf("SSL_CTX_new failed\n"); + return -1; + } + + /* + * SSL_OP_NO_SSLv2: + * + * We only want SSLv3 and TLSv1, so disable SSLv2. + * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. + */ + options |= SSL_OP_NO_SSLv2; + + /** + * SSL_OP_NO_COMPRESSION: + * + * The Microsoft RDP server does not advertise support + * for TLS compression, but alternative servers may support it. + * This was observed between early versions of the FreeRDP server + * and the FreeRDP client, and caused major performance issues, + * which is why we're disabling it. + */ +#ifdef SSL_OP_NO_COMPRESSION + options |= SSL_OP_NO_COMPRESSION; +#endif + + /** + * SSL_OP_TLS_BLOCK_PADDING_BUG: + * + * The Microsoft RDP server does *not* support TLS padding. + * It absolutely needs to be disabled otherwise it won't work. + */ + options |= SSL_OP_TLS_BLOCK_PADDING_BUG; + + /** + * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: + * + * Just like TLS padding, the Microsoft RDP server does not + * support empty fragments. This needs to be disabled. + */ + options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + + SSL_CTX_set_options(context->ctx, options); + + context->ssl = SSL_new(context->ctx); + + if (!context->ssl) + { + printf("SSL_new failed\n"); + return -1; + } + +#if 0 + if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) + { + printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); + return -1; + } + + if (SSL_use_certificate_file(context->ssl, certificate_file, SSL_FILETYPE_PEM) <= 0) + { + printf("SSL_use_certificate_file failed\n"); + return -1; + } +#endif + + context->bioRead = BIO_new(BIO_s_mem()); + + if (!context->bioRead) + { + printf("BIO_new failed\n"); + return -1; + } + + status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN); + + context->bioWrite = BIO_new(BIO_s_mem()); + + if (!context->bioWrite) + { + printf("BIO_new failed\n"); + return -1; + } + + status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN); + + status = BIO_make_bio_pair(context->bioRead, context->bioWrite); + + SSL_set_bio(context->ssl, context->bioRead, context->bioWrite); + + context->ReadBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); + context->WriteBuffer = (BYTE*) malloc(SCHANNEL_CB_MAX_TOKEN); + + return 0; +} + +SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput) +{ + int status; + int ssl_error; + PSecBuffer pBuffer; + + if (!context->connected) + { + if (pInput) + { + if (pInput->cBuffers < 1) + return SEC_E_INVALID_TOKEN; + + pBuffer = &pInput->pBuffers[0]; + + if (pBuffer->BufferType != SECBUFFER_TOKEN) + return SEC_E_INVALID_TOKEN; + + status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer); + } + + status = SSL_connect(context->ssl); + + if (status < 0) + { + ssl_error = SSL_get_error(context->ssl, status); + printf("SSL_connect error: %s\n", openssl_get_ssl_error_string(ssl_error)); + } + + status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN); + + if (status >= 0) + { + winpr_HexDump(context->ReadBuffer, status); + } + + if (pOutput->cBuffers < 1) + return SEC_E_INVALID_TOKEN; + + pBuffer = &pOutput->pBuffers[0]; + + if (pBuffer->BufferType != SECBUFFER_TOKEN) + return SEC_E_INVALID_TOKEN; + + if (pBuffer->cbBuffer < status) + return SEC_E_INSUFFICIENT_MEMORY; + + CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status); + pBuffer->cbBuffer = status; + + return SEC_I_CONTINUE_NEEDED; + } + + return SEC_E_OK; +} + +SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput) +{ + int status; + int ssl_error; + PSecBuffer pBuffer; + + if (!context->connected) + { + if (pInput->cBuffers < 1) + return SEC_E_INVALID_TOKEN; + + pBuffer = &pInput->pBuffers[0]; + + if (pBuffer->BufferType != SECBUFFER_TOKEN) + return SEC_E_INVALID_TOKEN; + + status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer); + + status = SSL_accept(context->ssl); + + if (status < 0) + { + ssl_error = SSL_get_error(context->ssl, status); + printf("SSL_accept error: %s\n", openssl_get_ssl_error_string(ssl_error)); + } + + status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN); + + if (status >= 0) + { + winpr_HexDump(context->ReadBuffer, status); + } + + if (pOutput->cBuffers < 1) + return SEC_E_INVALID_TOKEN; + + pBuffer = &pOutput->pBuffers[0]; + + if (pBuffer->BufferType != SECBUFFER_TOKEN) + return SEC_E_INVALID_TOKEN; + + if (pBuffer->cbBuffer < status) + return SEC_E_INSUFFICIENT_MEMORY; + + CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status); + pBuffer->cbBuffer = status; + + return SEC_I_CONTINUE_NEEDED; + } + + return SEC_E_OK; +} + SCHANNEL_OPENSSL* schannel_openssl_new() { SCHANNEL_OPENSSL* context; @@ -165,6 +357,8 @@ SCHANNEL_OPENSSL* schannel_openssl_new() SSL_load_error_strings(); SSL_library_init(); + + context->connected = FALSE; } return context; @@ -172,8 +366,11 @@ SCHANNEL_OPENSSL* schannel_openssl_new() void schannel_openssl_free(SCHANNEL_OPENSSL* context) { - if (!context) - return; + if (context) + { + free(context->ReadBuffer); + free(context->WriteBuffer); - free(context); + free(context); + } } diff --git a/winpr/libwinpr/sspi/Schannel/schannel_openssl.h b/winpr/libwinpr/sspi/Schannel/schannel_openssl.h index a023b7918..9d6624c84 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel_openssl.h +++ b/winpr/libwinpr/sspi/Schannel/schannel_openssl.h @@ -35,12 +35,19 @@ struct _SCHANNEL_OPENSSL { SSL* ssl; SSL_CTX* ctx; + BOOL connected; BIO* bioRead; BIO* bioWrite; + BYTE* ReadBuffer; + BYTE* WriteBuffer; }; typedef struct _SCHANNEL_OPENSSL SCHANNEL_OPENSSL; int schannel_openssl_client_init(SCHANNEL_OPENSSL* context); +int schannel_openssl_server_init(SCHANNEL_OPENSSL* context); + +SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput); +SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context, PSecBufferDesc pInput, PSecBufferDesc pOutput); SCHANNEL_OPENSSL* schannel_openssl_new(); void schannel_openssl_free(SCHANNEL_OPENSSL* context); From f8b364d6967ed85304de1cd613a0e9e432679070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 4 Jan 2013 12:16:55 -0500 Subject: [PATCH 15/24] libwinpr-sspi: add more Schannel tests --- winpr/include/winpr/crypto.h | 6 +- winpr/libwinpr/crypto/CMakeLists.txt | 3 + winpr/libwinpr/crypto/test/.gitignore | 3 + winpr/libwinpr/crypto/test/CMakeLists.txt | 35 +++ .../test/TestCertEnumCertificatesInStore.c | 66 ++++ winpr/libwinpr/sspi/test/TestSchannel.c | 282 ++++++++++++------ 6 files changed, 301 insertions(+), 94 deletions(-) create mode 100644 winpr/libwinpr/crypto/test/.gitignore create mode 100644 winpr/libwinpr/crypto/test/CMakeLists.txt create mode 100644 winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 334b6c690..ded2480c0 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -23,7 +23,11 @@ #include #include -#ifndef _WIN32 +#ifdef _WIN32 + +#include + +#else #define GET_ALG_CLASS(x) (x & (7 << 13)) #define GET_ALG_TYPE(x) (x & (15 << 9)) diff --git a/winpr/libwinpr/crypto/CMakeLists.txt b/winpr/libwinpr/crypto/CMakeLists.txt index 00809dad5..05605a1c3 100644 --- a/winpr/libwinpr/crypto/CMakeLists.txt +++ b/winpr/libwinpr/crypto/CMakeLists.txt @@ -44,3 +44,6 @@ endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR") +if(BUILD_TESTING) + add_subdirectory(test) +endif() diff --git a/winpr/libwinpr/crypto/test/.gitignore b/winpr/libwinpr/crypto/test/.gitignore new file mode 100644 index 000000000..2c4826250 --- /dev/null +++ b/winpr/libwinpr/crypto/test/.gitignore @@ -0,0 +1,3 @@ +TestCrypto +TestCrypto.c + diff --git a/winpr/libwinpr/crypto/test/CMakeLists.txt b/winpr/libwinpr/crypto/test/CMakeLists.txt new file mode 100644 index 000000000..398cb9c8e --- /dev/null +++ b/winpr/libwinpr/crypto/test/CMakeLists.txt @@ -0,0 +1,35 @@ + +set(MODULE_NAME "TestCrypto") +set(MODULE_PREFIX "TEST_CRYPTO") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestCertEnumCertificatesInStore.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +if(WIN32) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32 cryptui) +endif() + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-crt winpr-crypto winpr-utils) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") + diff --git a/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c b/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c new file mode 100644 index 000000000..5f81415a4 --- /dev/null +++ b/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c @@ -0,0 +1,66 @@ + + +#include +#include +#include + +#ifdef _WIN32 +//#define WITH_CRYPTUI 1 +#endif + +#ifdef WITH_CRYPTUI +#include +#endif + +int TestCertEnumCertificatesInStore(int argc, char* argv[]) +{ + int index; + DWORD status; + LPTSTR pszNameString; + HCERTSTORE hCertStore = NULL; + PCCERT_CONTEXT pCertContext = NULL; + + /** + * System Store Locations: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136/ + */ + + /** + * Requires elevated rights: + * hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, _T("Remote Desktop")); + */ + + hCertStore = CertOpenSystemStore((HCRYPTPROV_LEGACY) NULL, _T("MY")); + // hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_CURRENT_USER, _T("MY")); + + if (!hCertStore) + { + printf("Failed to open system store\n"); + return -1; + } + + index = 0; + + while (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) + { + status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); + + pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR)); + status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, status); + + _tprintf(_T("Certificate #%d: %s\n"), index++, pszNameString); + +#ifdef WITH_CRYPTUI + CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, NULL, NULL, 0, NULL); +#endif + } + + if (!CertCloseStore(hCertStore, 0)) + { + printf("Failed to close system store\n"); + return -1; + } + + return 0; +} + diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 477f05534..a5b66b63c 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -9,17 +9,16 @@ #include #include +HANDLE g_ClientEvent = NULL; +HANDLE g_ServerEvent = NULL; +BOOL g_ClientWait = FALSE; +BOOL g_ServerWait = FALSE; + HANDLE g_ClientReadPipe = NULL; HANDLE g_ClientWritePipe = NULL; HANDLE g_ServerReadPipe = NULL; HANDLE g_ServerWritePipe = NULL; -#ifndef _WIN32 -#define SCHANNEL_PKG_NAME SCHANNEL_NAME -#else -#define SCHANNEL_PKG_NAME UNISP_NAME -#endif - static void* schannel_test_server_thread(void* arg) { BYTE* lpTokenIn; @@ -31,6 +30,8 @@ static void* schannel_test_server_thread(void* arg) SCHANNEL_CRED cred; CtxtHandle context; CredHandle credentials; + DWORD cchNameString; + LPTSTR pszNameString; HCERTSTORE hCertStore; PCCERT_CONTEXT pCertContext; PSecBuffer pSecBuffer; @@ -51,7 +52,7 @@ static void* schannel_test_server_thread(void* arg) table = InitSecurityInterface(); - status = QuerySecurityPackageInfo(SCHANNEL_PKG_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); if (status != SEC_E_OK) { @@ -69,7 +70,7 @@ static void* schannel_test_server_thread(void* arg) //return NULL; } - pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); + pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL); if (!pCertContext) { @@ -77,6 +78,13 @@ static void* schannel_test_server_thread(void* arg) //return NULL; } + cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); + + pszNameString = (LPTSTR) malloc(status * sizeof(TCHAR)); + cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString); + + _tprintf(_T("Certificate Name: %s\n"), pszNameString); + ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); cred.dwVersion = SCHANNEL_CRED_VERSION; @@ -90,7 +98,7 @@ static void* schannel_test_server_thread(void* arg) cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER; - status = table->AcquireCredentialsHandle(NULL, SCHANNEL_PKG_NAME, + status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); if (status != SEC_E_OK) @@ -102,54 +110,95 @@ static void* schannel_test_server_thread(void* arg) lpTokenIn = (BYTE*) malloc(cbMaxToken); lpTokenOut = (BYTE*) malloc(cbMaxToken); - if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) - { - printf("Failed to read from server pipe\n"); - return NULL; - } - - printf("Server Received:\n"); - winpr_HexDump(lpTokenIn, NumberOfBytesRead); - fContextReq = ASC_REQ_STREAM | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR; - SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; - SecBuffer_in[0].pvBuffer = lpTokenIn; - SecBuffer_in[0].cbBuffer = NumberOfBytesRead; - - SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_in.cBuffers = 1; - SecBufferDesc_in.pBuffers = SecBuffer_in; - - SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; - SecBuffer_out[0].pvBuffer = lpTokenOut; - SecBuffer_out[0].cbBuffer = cbMaxToken; - - SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_out.cBuffers = 1; - SecBufferDesc_out.pBuffers = SecBuffer_out; - - status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, - &SecBufferDesc_in, fContextReq, SECURITY_NATIVE_DREP, &context, &SecBufferDesc_out, &fContextAttr, &expiry); - - if (status != SEC_I_CONTINUE_NEEDED) + do { - printf("AcceptSecurityContext unexpected status: 0x%08X\n", status); - return NULL; - } - - printf("SecBufferDesc_out.cBuffers: %d\n", SecBufferDesc_out.cBuffers); - - pSecBuffer = &SecBufferDesc_out.pBuffers[0]; - winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); - - if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) - { - printf("failed to write to client pipe\n"); - return NULL; + WaitForSingleObject(g_ServerEvent, INFINITE); + ResetEvent(g_ServerEvent); + + if (g_ServerWait) + { + if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) + { + printf("Failed to read from server pipe\n"); + return NULL; + } + } + else + { + NumberOfBytesRead = 0; + } + + printf("Server Received %d bytes:\n", NumberOfBytesRead); + winpr_HexDump(lpTokenIn, NumberOfBytesRead); + + SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_in[0].pvBuffer = lpTokenIn; + SecBuffer_in[0].cbBuffer = NumberOfBytesRead; + + SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; + SecBuffer_in[1].pvBuffer = NULL; + SecBuffer_in[1].cbBuffer = 0; + + SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_in.cBuffers = 2; + SecBufferDesc_in.pBuffers = SecBuffer_in; + + SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_out[0].pvBuffer = lpTokenOut; + SecBuffer_out[0].cbBuffer = cbMaxToken; + + SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_out.cBuffers = 1; + SecBufferDesc_out.pBuffers = SecBuffer_out; + + status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, + &SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); + + if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE)) + { + printf("AcceptSecurityContext unexpected status: 0x%08X\n", status); + return NULL; + } + + NumberOfBytesWritten = 0; + + if (status == SEC_I_CONTINUE_NEEDED) + printf("AcceptSecurityContext status: SEC_I_CONTINUE_NEEDED\n"); + else if (status == SEC_E_INCOMPLETE_MESSAGE) + printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n"); + + printf("Server cBuffers: %d pBuffers[0]: %d type: %d\n", + SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); + printf("Server Input cBuffers: %d pBuffers[1]: %d type: %d\n", + SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); + + if (status != SEC_E_INCOMPLETE_MESSAGE) + { + pSecBuffer = &SecBufferDesc_out.pBuffers[0]; + winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); + + g_ClientWait = TRUE; + SetEvent(g_ClientEvent); + + if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) + { + printf("failed to write to client pipe\n"); + return NULL; + } + } + else + { + g_ClientWait = FALSE; + SetEvent(g_ClientEvent); + } + + printf("Server wrote %d bytes\n", NumberOfBytesWritten); } + while (1); return NULL; } @@ -184,6 +233,9 @@ int TestSchannel(int argc, char* argv[]) sspi_GlobalInit(); + g_ClientEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + g_ServerEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + SecInvalidateHandle(&context); SecInvalidateHandle(&credentials); @@ -203,7 +255,7 @@ int TestSchannel(int argc, char* argv[]) table = InitSecurityInterface(); - status = QuerySecurityPackageInfo(SCHANNEL_PKG_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); if (status != SEC_E_OK) { @@ -228,7 +280,7 @@ int TestSchannel(int argc, char* argv[]) cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - status = table->AcquireCredentialsHandle(NULL, SCHANNEL_PKG_NAME, + status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); if (status != SEC_E_OK) @@ -302,49 +354,93 @@ int TestSchannel(int argc, char* argv[]) ZeroMemory(&SecBufferDesc_in, sizeof(SecBufferDesc)); ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc)); - SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; - SecBuffer_in[0].pvBuffer = lpTokenIn; - SecBuffer_in[0].cbBuffer = cbMaxToken; + g_ClientWait = FALSE; + SetEvent(g_ClientEvent); - SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_in.cBuffers = 1; - SecBufferDesc_in.pBuffers = SecBuffer_in; - - SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; - SecBuffer_out[0].pvBuffer = lpTokenOut; - SecBuffer_out[0].cbBuffer = cbMaxToken; - - SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; - SecBufferDesc_out.cBuffers = 1; - SecBufferDesc_out.pBuffers = SecBuffer_out; - - status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"), - fContextReq, SECURITY_NATIVE_DREP, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); - - if (status != SEC_I_CONTINUE_NEEDED) + do { - printf("InitializeSecurityContext unexpected status: 0x%08X\n", status); - return -1; - } - - printf("SecBufferDesc_out.cBuffers: %d\n", SecBufferDesc_out.cBuffers); - - pSecBuffer = &SecBufferDesc_out.pBuffers[0]; - winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); - - if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) - { - printf("failed to write to server pipe\n"); - return -1; - } - - printf("Client wrote %d bytes\n", NumberOfBytesWritten); - - if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) - { - printf("failed to read from server pipe\n"); - return -1; + WaitForSingleObject(g_ClientEvent, INFINITE); + ResetEvent(g_ClientEvent); + + if (g_ClientWait) + { + if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) + { + printf("failed to read from server pipe\n"); + return -1; + } + } + else + { + NumberOfBytesRead = 0; + } + + printf("NumberOfBytesRead: %d\n", NumberOfBytesRead); + + SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_in[0].pvBuffer = lpTokenIn; + SecBuffer_in[0].cbBuffer = NumberOfBytesRead; + + SecBuffer_in[1].pvBuffer = NULL; + SecBuffer_in[1].cbBuffer = 0; + SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; + + SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_in.cBuffers = 2; + SecBufferDesc_in.pBuffers = SecBuffer_in; + + SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; + SecBuffer_out[0].pvBuffer = lpTokenOut; + SecBuffer_out[0].cbBuffer = cbMaxToken; + + SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; + SecBufferDesc_out.cBuffers = 1; + SecBufferDesc_out.pBuffers = SecBuffer_out; + + status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"), + fContextReq, 0, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); + + if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE)) + { + printf("InitializeSecurityContext unexpected status: 0x%08X\n", status); + return -1; + } + + NumberOfBytesWritten = 0; + + if (status == SEC_I_CONTINUE_NEEDED) + printf("InitializeSecurityContext status: SEC_I_CONTINUE_NEEDED\n"); + else if (status == SEC_E_INCOMPLETE_MESSAGE) + printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n"); + + printf("Client Output cBuffers: %d pBuffers[0]: %d type: %d\n", + SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); + printf("Client Input cBuffers: %d pBuffers[1]: %d type: %d\n", + SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); + + if (status != SEC_E_INCOMPLETE_MESSAGE) + { + pSecBuffer = &SecBufferDesc_out.pBuffers[0]; + winpr_HexDump((BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); + + g_ServerWait = TRUE; + SetEvent(g_ServerEvent); + + if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) + { + printf("failed to write to server pipe\n"); + return -1; + } + } + else + { + g_ServerWait = FALSE; + SetEvent(g_ServerEvent); + } + + printf("Client wrote %d bytes\n", NumberOfBytesWritten); } + while(1); WaitForSingleObject(thread, INFINITE); From 05ef57bb015a66afea54856385353ba08fa39eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 4 Jan 2013 13:43:44 -0500 Subject: [PATCH 16/24] libwinpr-sspi: complete Schannel TLS handshake test --- winpr/libwinpr/sspi/test/TestSchannel.c | 45 ++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index a5b66b63c..0c4432589 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -21,6 +21,7 @@ HANDLE g_ServerWritePipe = NULL; static void* schannel_test_server_thread(void* arg) { + BOOL extraData; BYTE* lpTokenIn; BYTE* lpTokenOut; TimeStamp expiry; @@ -107,6 +108,7 @@ static void* schannel_test_server_thread(void* arg) return NULL; } + extraData = FALSE; lpTokenIn = (BYTE*) malloc(cbMaxToken); lpTokenOut = (BYTE*) malloc(cbMaxToken); @@ -116,21 +118,25 @@ static void* schannel_test_server_thread(void* arg) do { - WaitForSingleObject(g_ServerEvent, INFINITE); - ResetEvent(g_ServerEvent); - - if (g_ServerWait) + if (!extraData) { - if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) + WaitForSingleObject(g_ServerEvent, INFINITE); + ResetEvent(g_ServerEvent); + + if (g_ServerWait) { - printf("Failed to read from server pipe\n"); - return NULL; + if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) + { + printf("Failed to read from server pipe\n"); + return NULL; + } + } + else + { + NumberOfBytesRead = 0; } } - else - { - NumberOfBytesRead = 0; - } + extraData = FALSE; printf("Server Received %d bytes:\n", NumberOfBytesRead); winpr_HexDump(lpTokenIn, NumberOfBytesRead); @@ -158,6 +164,12 @@ static void* schannel_test_server_thread(void* arg) status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, &SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); + if (status == SEC_E_OK) + { + printf("AcceptSecurityContext SEC_E_OK, TLS connection complete\n"); + break; + } + if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE)) { printf("AcceptSecurityContext unexpected status: 0x%08X\n", status); @@ -176,6 +188,15 @@ static void* schannel_test_server_thread(void* arg) printf("Server Input cBuffers: %d pBuffers[1]: %d type: %d\n", SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); + if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA) + { + printf("AcceptSecurityContext SECBUFFER_EXTRA\n"); + pSecBuffer = &SecBufferDesc_in.pBuffers[1]; + CopyMemory(lpTokenIn, &lpTokenIn[NumberOfBytesRead - pSecBuffer->cbBuffer], pSecBuffer->cbBuffer); + NumberOfBytesRead = pSecBuffer->cbBuffer; + continue; + } + if (status != SEC_E_INCOMPLETE_MESSAGE) { pSecBuffer = &SecBufferDesc_out.pBuffers[0]; @@ -398,7 +419,7 @@ int TestSchannel(int argc, char* argv[]) SecBufferDesc_out.pBuffers = SecBuffer_out; status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"), - fContextReq, 0, 0, NULL, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); + fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); if ((status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE)) { From 609459f8a6733701f41a1cfbfc0db563f9621c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 5 Jan 2013 12:35:24 -0500 Subject: [PATCH 17/24] libwinpr-sspi: fix build on Linux --- winpr/include/winpr/crypto.h | 29 +++++++++++++++++++ winpr/libwinpr/crypto/cert.c | 22 ++++++++++++++ .../libwinpr/sspi/Schannel/schannel_openssl.c | 8 ++--- winpr/libwinpr/sspi/test/TestSchannel.c | 1 + 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index ded2480c0..56fd6d981 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -340,9 +340,25 @@ typedef const CERT_CONTEXT *PCCERT_CONTEXT; #define CERT_FIND_OR_CTL_USAGE_FLAG CERT_FIND_OR_ENHKEY_USAGE_FLAG #define CERT_FIND_VALID_CTL_USAGE_FLAG CERT_FIND_VALID_ENHKEY_USAGE_FLAG +#define CERT_NAME_EMAIL_TYPE 1 +#define CERT_NAME_RDN_TYPE 2 +#define CERT_NAME_ATTR_TYPE 3 +#define CERT_NAME_SIMPLE_DISPLAY_TYPE 4 +#define CERT_NAME_FRIENDLY_DISPLAY_TYPE 5 +#define CERT_NAME_DNS_TYPE 6 +#define CERT_NAME_URL_TYPE 7 +#define CERT_NAME_UPN_TYPE 8 + +#define CERT_NAME_ISSUER_FLAG 0x1 +#define CERT_NAME_DISABLE_IE4_UTF8_FLAG 0x00010000 + +#define CERT_NAME_SEARCH_ALL_NAMES_FLAG 0x2 + WINPR_API HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubsystemProtocol); WINPR_API HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProtocol); +WINPR_API BOOL CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags); + #ifdef UNICODE #define CertOpenSystemStore CertOpenSystemStoreW #else @@ -352,6 +368,19 @@ WINPR_API HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubs WINPR_API PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext); +WINPR_API PCCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext); + +DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, + DWORD dwFlags, void* pvTypePara, LPWSTR pszNameString, DWORD cchNameString); +DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, + DWORD dwFlags, void* pvTypePara, LPSTR pszNameString, DWORD cchNameString); + +#ifdef UNICODE +#define CertGetNameString CertGetNameStringW +#else +#define CertGetNameString CertGetNameStringA +#endif + #endif #endif /* WINPR_CRYPTO_H */ diff --git a/winpr/libwinpr/crypto/cert.c b/winpr/libwinpr/crypto/cert.c index bc989a631..7dc256221 100644 --- a/winpr/libwinpr/crypto/cert.c +++ b/winpr/libwinpr/crypto/cert.c @@ -162,11 +162,33 @@ HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, LPCSTR szSubsystemProto return CertOpenSystemStoreW(hProv, NULL); } +BOOL CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) +{ + return TRUE; +} + PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext) { return (PCCERT_CONTEXT) 1; } +PCCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext) +{ + return (PCCERT_CONTEXT) NULL; +} + +DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, + DWORD dwFlags, void* pvTypePara, LPWSTR pszNameString, DWORD cchNameString) +{ + return 0; +} + +DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, + DWORD dwFlags, void* pvTypePara, LPSTR pszNameString, DWORD cchNameString) +{ + return 0; +} + #endif diff --git a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c index c33e33ac7..3b767311c 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c +++ b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c @@ -44,6 +44,7 @@ char* openssl_get_ssl_error_string(int ssl_error) return "SSL_ERROR_SYSCALL"; case SSL_ERROR_SSL: + ERR_print_errors_fp(stdout); return "SSL_ERROR_SSL"; } @@ -192,19 +193,17 @@ int schannel_openssl_server_init(SCHANNEL_OPENSSL* context) return -1; } -#if 0 - if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) + if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, "/tmp/localhost.key", SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return -1; } - if (SSL_use_certificate_file(context->ssl, certificate_file, SSL_FILETYPE_PEM) <= 0) + if (SSL_use_certificate_file(context->ssl, "/tmp/localhost.crt", SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return -1; } -#endif context->bioRead = BIO_new(BIO_s_mem()); @@ -308,6 +307,7 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context if (pBuffer->BufferType != SECBUFFER_TOKEN) return SEC_E_INVALID_TOKEN; + printf("Server input: %d\n", pBuffer->cbBuffer); status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer); status = SSL_accept(context->ssl); diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 0c4432589..3fccbb1c0 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include From 3b71138442eb3e595bc74c884c70cf61652f9728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 5 Jan 2013 14:58:47 -0500 Subject: [PATCH 18/24] wfreerdp-server: fix build on Windows 7 --- server/Windows/CMakeLists.txt | 1 - server/Windows/wf_rdpsnd.c | 4 ++++ winpr/libwinpr/sspi/test/TestSchannel.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt index 2382a152b..bdabe1329 100644 --- a/server/Windows/CMakeLists.txt +++ b/server/Windows/CMakeLists.txt @@ -54,7 +54,6 @@ if(WITH_WIN8) endif() set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} dsound) - set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-server) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index f3b104841..ec90e911a 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -26,6 +26,10 @@ #include +#define INITGUID +#include +#include + #define CINTERFACE #include #include diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 3fccbb1c0..646445d79 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -72,7 +72,7 @@ static void* schannel_test_server_thread(void* arg) //return NULL; } - pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL); + pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); if (!pCertContext) { From 4cf0dc1004abca3376536c0114e6a7f64b51632a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 6 Jan 2013 16:05:20 -0500 Subject: [PATCH 19/24] libwinpr-sspi: improve attempted channel binding token computation --- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 49 +++++++++++++++++++++++- winpr/libwinpr/sspi/test/CMakeLists.txt | 3 +- winpr/libwinpr/sspi/test/TestNTLM.c | 9 +++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 winpr/libwinpr/sspi/test/TestNTLM.c diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index e2ee412bf..5315ea367 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -303,10 +303,29 @@ int test_CertificateHashLength = 32; char TlsServerEndPointPrefix[] = "tls-server-end-point:"; +void ntlm_uint32_to_big_endian(UINT32 num, BYTE be32[4]) +{ + be32[0] = (num >> 0) & 0xFF; + be32[1] = (num >> 8) & 0xFF; + be32[2] = (num >> 16) & 0xFF; + be32[3] = (num >> 24) & 0xFF; +} + +/* +typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; +} *gss_channel_bindings_t; + */ + void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) { #if 0 MD5_CTX md5; + BYTE be32[4]; int HashLength; int PrefixLength; BYTE* pChannelBindingToken; @@ -340,11 +359,39 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) winpr_HexDump((BYTE*) ChannelBindings, context->EndpointBindings.BindingsLength); MD5_Init(&md5); - MD5_Update(&md5, (void*) context->EndpointBindings.Bindings, context->EndpointBindings.BindingsLength); + + ntlm_uint32_to_big_endian(ChannelBindings->dwInitiatorAddrType, be32); + MD5_Update(&md5, be32, 4); + + ntlm_uint32_to_big_endian(ChannelBindings->cbInitiatorLength, be32); + MD5_Update(&md5, be32, 4); + + //ntlm_uint32_to_big_endian(ChannelBindings->dwInitiatorOffset, be32); + //MD5_Update(&md5, be32, 4); + + ntlm_uint32_to_big_endian(ChannelBindings->dwAcceptorAddrType, be32); + MD5_Update(&md5, be32, 4); + + ntlm_uint32_to_big_endian(ChannelBindings->cbAcceptorLength, be32); + MD5_Update(&md5, be32, 4); + + //ntlm_uint32_to_big_endian(ChannelBindings->dwAcceptorOffset, be32); + //MD5_Update(&md5, be32, 4); + + ntlm_uint32_to_big_endian(ChannelBindings->cbApplicationDataLength, be32); + MD5_Update(&md5, be32, 4); + + //ntlm_uint32_to_big_endian(ChannelBindings->dwApplicationDataOffset, be32); + //MD5_Update(&md5, be32, 4); + + MD5_Update(&md5, (void*) pChannelBindingToken, ChannelBindingTokenLength); + MD5_Final(context->ChannelBindingsHash, &md5); printf("ChannelBindingsHash:\n"); winpr_HexDump(context->ChannelBindingsHash, 16); + + printf("\n\n"); #endif } diff --git a/winpr/libwinpr/sspi/test/CMakeLists.txt b/winpr/libwinpr/sspi/test/CMakeLists.txt index e1e660e94..694ae997f 100644 --- a/winpr/libwinpr/sspi/test/CMakeLists.txt +++ b/winpr/libwinpr/sspi/test/CMakeLists.txt @@ -9,7 +9,8 @@ set(${MODULE_PREFIX}_TESTS TestEnumerateSecurityPackages.c TestInitializeSecurityContext.c TestAcquireCredentialsHandle.c - TestSchannel.c) + TestSchannel.c + TestNTLM.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c new file mode 100644 index 000000000..f7cf4ad77 --- /dev/null +++ b/winpr/libwinpr/sspi/test/TestNTLM.c @@ -0,0 +1,9 @@ + +#include +#include + +int TestNTLM(int argc, char* argv[]) +{ + return 0; +} + From 811ff4472016bb20b35ce4a9004eb7914d8d6319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 6 Jan 2013 17:24:08 -0500 Subject: [PATCH 20/24] libfreerdp-core: change ReceiveCallback return values --- libfreerdp/core/fastpath.c | 8 ++-- libfreerdp/core/nego.c | 10 ++--- libfreerdp/core/nego.h | 2 +- libfreerdp/core/peer.c | 44 +++++++++---------- libfreerdp/core/rdp.c | 18 ++++---- libfreerdp/core/transport.c | 16 ++++++- .../test/TestCertEnumCertificatesInStore.c | 2 +- 7 files changed, 56 insertions(+), 44 deletions(-) diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 7a43c6c6a..b6c012401 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -506,7 +506,7 @@ static BOOL fastpath_recv_input_event(rdpFastPath* fastpath, STREAM* s) return TRUE; } -BOOL fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) +int fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) { BYTE i; @@ -518,7 +518,7 @@ BOOL fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) */ if (stream_get_left(s) < 1) - return FALSE; + return -1; stream_read_BYTE(s, fastpath->numberEvents); /* eventHeader (1 byte) */ } @@ -526,10 +526,10 @@ BOOL fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) for (i = 0; i < fastpath->numberEvents; i++) { if (!fastpath_recv_input_event(fastpath, s)) - return FALSE; + return -1; } - return TRUE; + return 0; } static UINT32 fastpath_get_sec_bytes(rdpRdp* rdp) diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 07c6ea035..770c6da8c 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -465,9 +465,9 @@ BOOL nego_recv_response(rdpNego* nego) STREAM* s = transport_recv_stream_init(nego->transport, 1024); if (transport_read(nego->transport, s) < 0) - return FALSE; + return -1; - return nego_recv(nego->transport, s, nego); + return ((nego_recv(nego->transport, s, nego) < 0) ? FALSE : TRUE); } /** @@ -478,7 +478,7 @@ BOOL nego_recv_response(rdpNego* nego) * @param extra nego pointer */ -BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra) +int nego_recv(rdpTransport* transport, STREAM* s, void* extra) { BYTE li; BYTE type; @@ -488,7 +488,7 @@ BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra) length = tpkt_read_header(s); if (length == 0) - return FALSE; + return -1; li = tpdu_read_connection_confirm(s); @@ -546,7 +546,7 @@ BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra) nego->state = NEGO_STATE_FAIL; } - return TRUE; + return 0; } /** diff --git a/libfreerdp/core/nego.h b/libfreerdp/core/nego.h index 5b9c31079..622f8f33b 100644 --- a/libfreerdp/core/nego.h +++ b/libfreerdp/core/nego.h @@ -117,7 +117,7 @@ void nego_attempt_tls(rdpNego* nego); void nego_attempt_rdp(rdpNego* nego); void nego_send(rdpNego* nego); -BOOL nego_recv(rdpTransport* transport, STREAM* s, void* extra); +int nego_recv(rdpTransport* transport, STREAM* s, void* extra); BOOL nego_recv_response(rdpNego* nego); BOOL nego_read_request(rdpNego* nego, STREAM* s); diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 059de8cf9..215bcb9c3 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -156,7 +156,7 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, STREAM* s) return TRUE; } -static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) +static int peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) { rdpRdp* rdp; UINT16 length; @@ -171,7 +171,7 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) if (!rdp_read_header(rdp, s, &length, &channelId)) { printf("Incorrect RDP header.\n"); - return FALSE; + return -1; } if (rdp->settings->DisableEncryption) @@ -183,7 +183,7 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); - return FALSE; + return -1; } } } @@ -195,7 +195,7 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) else { if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource)) - return FALSE; + return -1; client->settings->PduSource = pduSource; @@ -203,19 +203,19 @@ static BOOL peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s) { case PDU_TYPE_DATA: if (!peer_recv_data_pdu(client, s)) - return FALSE; + return -1; break; default: printf("Client sent pduType %d\n", pduType); - return FALSE; + return -1; } } - return TRUE; + return 0; } -static BOOL peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s) +static int peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s) { rdpRdp* rdp; UINT16 length; @@ -225,10 +225,10 @@ static BOOL peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s) fastpath = rdp->fastpath; length = fastpath_read_header_rdp(fastpath, s); - if (length == 0 || length > stream_get_left(s)) + if ((length == 0) || (length > stream_get_left(s))) { printf("incorrect FastPath PDU header length %d\n", length); - return FALSE; + return -1; } if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) @@ -239,7 +239,7 @@ static BOOL peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s) return fastpath_recv_inputs(fastpath, s); } -static BOOL peer_recv_pdu(freerdp_peer* client, STREAM* s) +static int peer_recv_pdu(freerdp_peer* client, STREAM* s) { if (tpkt_verify_header(s)) return peer_recv_tpkt_pdu(client, s); @@ -256,7 +256,7 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { case CONNECTION_STATE_INITIAL: if (!rdp_server_accept_nego(rdp, s)) - return FALSE; + return -1; if (rdp->nego->selected_protocol & PROTOCOL_NLA) { @@ -273,29 +273,29 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) case CONNECTION_STATE_NEGO: if (!rdp_server_accept_mcs_connect_initial(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_MCS_CONNECT: if (!rdp_server_accept_mcs_erect_domain_request(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_MCS_ERECT_DOMAIN: if (!rdp_server_accept_mcs_attach_user_request(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_MCS_ATTACH_USER: if (!rdp_server_accept_mcs_channel_join_request(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: if (rdp->settings->DisableEncryption) { if (!rdp_server_accept_client_keys(rdp, s)) - return FALSE; + return -1; break; } rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; @@ -303,12 +303,12 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) case CONNECTION_STATE_ESTABLISH_KEYS: if (!rdp_server_accept_client_info(rdp, s)) - return FALSE; + return -1; IFCALL(client->Capabilities, client); if (!rdp_send_demand_active(rdp)) - return FALSE; + return -1; break; case CONNECTION_STATE_LICENSE: @@ -325,15 +325,15 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) case CONNECTION_STATE_ACTIVE: if (!peer_recv_pdu(client, s)) - return FALSE; + return -1; break; default: printf("Invalid state %d\n", rdp->state); - return FALSE; + return -1; } - return TRUE; + return 0; } static BOOL freerdp_peer_close(freerdp_peer* client) diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 999e7b567..2c10b1b61 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -850,50 +850,50 @@ static BOOL rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { case CONNECTION_STATE_NEGO: if (!rdp_client_connect_mcs_connect_response(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_MCS_ATTACH_USER: if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_LICENSE: if (!rdp_client_connect_license(rdp, s)) - return FALSE; + return -1; break; case CONNECTION_STATE_CAPABILITY: if (!rdp_client_connect_demand_active(rdp, s)) { printf("rdp_client_connect_demand_active failed\n"); - return FALSE; + return -1; } break; case CONNECTION_STATE_FINALIZATION: if (!rdp_recv_pdu(rdp, s)) - return FALSE; + return -1; if (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE) rdp->state = CONNECTION_STATE_ACTIVE; break; case CONNECTION_STATE_ACTIVE: if (!rdp_recv_pdu(rdp, s)) - return FALSE; + return -1; break; default: printf("Invalid state %d\n", rdp->state); - return FALSE; + return -1; } - return TRUE; + return 0; } int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size) diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 75287059d..fc2be7b3a 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -589,6 +589,7 @@ int transport_check_fds(rdpTransport** ptransport) int pos; int status; UINT16 length; + int recv_status; STREAM* received; rdpTransport* transport = *ptransport; @@ -684,10 +685,21 @@ int transport_check_fds(rdpTransport** ptransport) stream_seal(received); stream_set_pos(received, 0); - if (transport->ReceiveCallback(transport, received, transport->ReceiveExtra) == FALSE) + /** + * ReceiveCallback return values: + * + * -1: synchronous failure + * 0: synchronous success + * 1: asynchronous return + */ + + recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); + + if (recv_status < 0) status = -1; - transport_receive_pool_return(transport, received); + if (recv_status == 0) + transport_receive_pool_return(transport, received); if (status < 0) return status; diff --git a/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c b/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c index 5f81415a4..d4a909e5a 100644 --- a/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c +++ b/winpr/libwinpr/crypto/test/TestCertEnumCertificatesInStore.c @@ -41,7 +41,7 @@ int TestCertEnumCertificatesInStore(int argc, char* argv[]) index = 0; - while (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) + while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext))) { status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); From 45d001ef8b757d50e4a29021b34b452fd0de3e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 8 Jan 2013 17:18:10 -0500 Subject: [PATCH 21/24] libfreerdp-core: change return values for PDU processing --- include/freerdp/update.h | 8 ++++++ libfreerdp/core/fastpath.c | 9 ++---- libfreerdp/core/rdp.c | 58 +++++++++++++++++++------------------- libfreerdp/core/surface.c | 7 +++-- libfreerdp/core/surface.h | 2 +- libfreerdp/core/update.c | 23 ++++++++++++++- 6 files changed, 67 insertions(+), 40 deletions(-) diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 71cd47189..526f22f0d 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -22,6 +22,11 @@ typedef struct rdp_update rdpUpdate; +#include +#include +#include +#include + #include #include #include @@ -191,6 +196,9 @@ struct rdp_update SURFACE_BITS_COMMAND surface_bits_command; SURFACE_FRAME_MARKER surface_frame_marker; + + HANDLE thread; + wQueue* queue; }; #endif /* FREERDP_UPDATE_H */ diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index b6c012401..848bfd6ed 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -340,7 +340,7 @@ static BOOL fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s) return TRUE; } -BOOL fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s) +int fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s) { rdpUpdate* update = fastpath->rdp->update; @@ -349,15 +349,12 @@ BOOL fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s) while (stream_get_left(s) >= 3) { if (!fastpath_recv_update_data(fastpath, s)) - { - /* XXX: Do we need to call EndPaint? */ - return FALSE; - } + return -1; } IFCALL(update->EndPaint, update->context); - return TRUE; + return 0; } static BOOL fastpath_read_input_event_header(STREAM* s, BYTE* eventFlags, BYTE* eventCode) diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 2c10b1b61..1b068b509 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -480,7 +480,7 @@ void rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, STREAM* s) rdp_print_errinfo(rdp->errorInfo); } -BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) +int rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) { BYTE type; UINT16 length; @@ -507,7 +507,7 @@ BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) else { printf("decompress_rdp() failed\n"); - return FALSE; + return -1; } stream_seek(s, compressed_len - 18); } @@ -522,7 +522,7 @@ BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) { case DATA_PDU_TYPE_UPDATE: if (!update_recv(rdp->update, comp_stream)) - return FALSE; + return -1; break; case DATA_PDU_TYPE_CONTROL: @@ -611,7 +611,7 @@ BOOL rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) stream_free(comp_stream); } - return TRUE; + return 0; } BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s) @@ -624,7 +624,7 @@ BOOL rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s) if (type == PDU_TYPE_DATA) { - return rdp_recv_data_pdu(rdp, s); + return (rdp_recv_data_pdu(rdp, s) < 0) ? FALSE : TRUE; } else if (type == PDU_TYPE_SERVER_REDIRECTION) { @@ -712,7 +712,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, STREAM* s, int length, UINT16 securityFlags) * @param s stream */ -static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) +static int rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) { UINT16 length; UINT16 pduType; @@ -725,7 +725,7 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) if (!rdp_read_header(rdp, s, &length, &channelId)) { printf("Incorrect RDP header.\n"); - return FALSE; + return -1; } if (rdp->settings->DisableEncryption) @@ -737,7 +737,7 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); - return FALSE; + return -1; } } @@ -749,7 +749,7 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) */ s->p -= 2; rdp_recv_enhanced_security_redirection_packet(rdp, s); - return TRUE; + return -1; } } @@ -770,16 +770,16 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) switch (pduType) { case PDU_TYPE_DATA: - if (!rdp_recv_data_pdu(rdp, s)) + if (rdp_recv_data_pdu(rdp, s) < 0) { printf("rdp_recv_data_pdu failed\n"); - return FALSE; + return -1; } break; case PDU_TYPE_DEACTIVATE_ALL: if (!rdp_recv_deactivate_all(rdp, s)) - return FALSE; + return -1; break; case PDU_TYPE_SERVER_REDIRECTION: @@ -794,10 +794,10 @@ static BOOL rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) } } - return TRUE; + return 0; } -static BOOL rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) +static int rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) { UINT16 length; rdpFastPath* fastpath; @@ -808,7 +808,7 @@ static BOOL rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) if ((length == 0) || (length > stream_get_left(s))) { printf("incorrect FastPath PDU header length %d\n", length); - return FALSE; + return -1; } if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) @@ -819,7 +819,7 @@ static BOOL rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) return fastpath_recv_updates(rdp->fastpath, s); } -static BOOL rdp_recv_pdu(rdpRdp* rdp, STREAM* s) +static int rdp_recv_pdu(rdpRdp* rdp, STREAM* s) { if (tpkt_verify_header(s)) return rdp_recv_tpkt_pdu(rdp, s); @@ -842,58 +842,58 @@ void rdp_recv(rdpRdp* rdp) rdp_recv_pdu(rdp, s); } -static BOOL rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra) +static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { + int status = 0; rdpRdp* rdp = (rdpRdp*) extra; switch (rdp->state) { case CONNECTION_STATE_NEGO: if (!rdp_client_connect_mcs_connect_response(rdp, s)) - return -1; + status = -1; break; case CONNECTION_STATE_MCS_ATTACH_USER: if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s)) - return -1; + status = -1; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s)) - return -1; + status = -1; break; case CONNECTION_STATE_LICENSE: if (!rdp_client_connect_license(rdp, s)) - return -1; + status = -1; break; case CONNECTION_STATE_CAPABILITY: if (!rdp_client_connect_demand_active(rdp, s)) { printf("rdp_client_connect_demand_active failed\n"); - return -1; + status = -1; } break; case CONNECTION_STATE_FINALIZATION: - if (!rdp_recv_pdu(rdp, s)) - return -1; - if (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE) + status = rdp_recv_pdu(rdp, s); + if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE)) rdp->state = CONNECTION_STATE_ACTIVE; break; case CONNECTION_STATE_ACTIVE: - if (!rdp_recv_pdu(rdp, s)) - return -1; + status = rdp_recv_pdu(rdp, s); break; default: printf("Invalid state %d\n", rdp->state); - return -1; + status = -1; + break; } - return 0; + return status; } int rdp_send_channel_data(rdpRdp* rdp, int channel_id, BYTE* data, int size) diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c index 9c1574295..e55050323 100644 --- a/libfreerdp/core/surface.c +++ b/libfreerdp/core/surface.c @@ -76,7 +76,7 @@ static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s) return 6; } -BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s) +int update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s) { BYTE* mark; UINT16 cmdType; @@ -102,7 +102,7 @@ BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s) default: DEBUG_WARN("unknown cmdType 0x%X", cmdType); - return FALSE; + return -1; } size -= cmdLength; @@ -113,7 +113,8 @@ BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s) pcap_flush(update->pcap_rfx); } } - return TRUE; + + return 0; } void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd) diff --git a/libfreerdp/core/surface.h b/libfreerdp/core/surface.h index 82dda2491..38ebbe12d 100644 --- a/libfreerdp/core/surface.h +++ b/libfreerdp/core/surface.h @@ -33,7 +33,7 @@ enum SURFCMD_CMDTYPE CMDTYPE_STREAM_SURFACE_BITS = 0x0006 }; -BOOL update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s); +int update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s); void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd); void update_write_surfcmd_frame_marker(STREAM* s, UINT16 frameAction, UINT32 frameId); diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 7f747c641..9baea0e8e 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -22,6 +22,7 @@ #endif #include +#include #include "update.h" #include "surface.h" @@ -620,6 +621,20 @@ void update_register_client_callbacks(rdpUpdate* update) update->SuppressOutput = update_send_suppress_output; } +static void* update_thread(void* arg) +{ + rdpUpdate* update; + + update = (rdpUpdate*) arg; + + while (WaitForSingleObject(Queue_Event(update->queue), INFINITE) == WAIT_OBJECT_0) + { + + } + + return NULL; +} + rdpUpdate* update_new(rdpRdp* rdp) { rdpUpdate* update; @@ -657,6 +672,10 @@ rdpUpdate* update_new(rdpRdp* rdp) deleteList->cIndices = 0; update->SuppressOutput = update_send_suppress_output; + + update->queue = Queue_New(TRUE, -1, -1); + + update->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) update_thread, update, 0, NULL); } return update; @@ -679,7 +698,9 @@ void update_free(rdpUpdate* update) free(update->secondary); free(update->altsec); free(update->window); + + CloseHandle(update->thread); + free(update); } } - From b274133b8617ca81590f1169536f92a5e4c43a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 8 Jan 2013 17:18:34 -0500 Subject: [PATCH 22/24] libfreerdp-client: add /vmconnect option for hyper-v --- client/common/cmdline.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 8461068bb..9c4c064ad 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -98,6 +98,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" }, { "pcb", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Preconnection Blob" }, { "pcid", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Preconnection Id" }, + { "vmconnect", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, NULL, -1, NULL, "Hyper-V console (use port 2179, disable negotiation)" }, { "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "authentication (hack!)" }, { "encryption", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "encryption (hack!)" }, { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "grab keyboard" }, @@ -191,6 +192,7 @@ int freerdp_client_print_command_line_help(int argc, char** argv) printf(" xfreerdp connection.rdp /p:Pwd123! /f\n"); printf(" xfreerdp /u:CONTOSO\\JohnDoe /p:Pwd123! /v:rdp.contoso.com\n"); printf(" xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192.168.1.100:4489\n"); + printf(" xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:192.168.1.100\n"); printf("\n"); printf("Clipboard Redirection: +clipboard\n"); @@ -834,6 +836,17 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin settings->ServerHostname = _strdup(arg->Value); } } + CommandLineSwitchCase(arg, "vmconnect") + { + settings->ServerPort = 2179; + settings->NegotiateSecurityLayer = FALSE; + + if (arg->Flags & COMMAND_LINE_VALUE_PRESENT) + { + settings->SendPreconnectionPdu = TRUE; + settings->PreconnectionBlob = _strdup(arg->Value); + } + } CommandLineSwitchCase(arg, "port") { settings->ServerPort = atoi(arg->Value); @@ -1163,16 +1176,16 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin { settings->NegotiateSecurityLayer = arg->Value ? TRUE : FALSE; } - CommandLineSwitchCase(arg, "pcid") - { - settings->SendPreconnectionPdu = TRUE; - settings->PreconnectionId = atoi(arg->Value); - } CommandLineSwitchCase(arg, "pcb") { settings->SendPreconnectionPdu = TRUE; settings->PreconnectionBlob = _strdup(arg->Value); } + CommandLineSwitchCase(arg, "pcid") + { + settings->SendPreconnectionPdu = TRUE; + settings->PreconnectionId = atoi(arg->Value); + } CommandLineSwitchCase(arg, "sec") { if (strcmp("rdp", arg->Value) == 0) /* Standard RDP */ From d8949f5d8f18d321409830683c3bb0c98ca03963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 8 Jan 2013 21:56:28 -0500 Subject: [PATCH 23/24] libfreerdp-core: fix computing of test channel binding token --- winpr/libwinpr/sspi/NTLM/ntlm.h | 1 + winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 140 ++++++++++------------- winpr/libwinpr/sspi/test/TestNTLM.c | 52 ++++++++- 3 files changed, 113 insertions(+), 80 deletions(-) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index 3fee06246..f0146b7d6 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index 5315ea367..8f08d11a7 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -228,72 +228,49 @@ void ntlm_free_unicode_string(PUNICODE_STRING string) * https://raw.github.com/mozilla/mozilla-central/master/extensions/auth/nsAuthSSPI.cpp */ -/* Certificate (TBSCertificate) */ +/* Certificate */ -BYTE test_Certificate[] = - "\x30\x82\x02\xfa\xa0\x03\x02\x01\x02\x02\x10\x33\x1d\x91\x3b\x2b" - "\x0a\xc8\x90\x4a\x19\x35\xed\x79\x65\xb8\xe3\x30\x09\x06\x05\x2b" - "\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04" - "\x03\x13\x0b\x4c\x41\x42\x33\x2d\x57\x32\x4b\x38\x52\x32\x30\x1e" - "\x17\x0d\x31\x32\x31\x32\x31\x37\x31\x37\x33\x33\x31\x32\x5a\x17" - "\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x16" - "\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x4c\x41\x42\x33\x2d" - "\x57\x32\x4b\x38\x52\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86" - "\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82" - "\x02\x0a\x02\x82\x02\x01\x00\xbf\x99\x68\x59\x41\x06\x5a\xd0\x3a" - "\x38\x7a\xca\x7a\x1e\x85\xee\x21\x7e\xa3\x01\xca\xf5\xdd\x2f\xbc" - "\xf7\x05\x87\x12\x89\x22\xd7\x37\xc1\xe1\x5d\x41\x02\xd8\x60\xc5" - "\x07\xec\x26\x6f\x13\x48\xe1\xf3\xc3\x42\x1e\x71\x5d\x31\x8e\x83" - "\x74\xac\x23\x84\x88\x02\xf4\xa2\x0a\xa8\x41\xfd\x16\x27\x31\x9c" - "\xb6\x78\x08\x84\xfe\x5f\xa1\x9f\x9b\x5c\xe4\x41\xf0\x7f\xb2\x41" - "\xe8\xd7\xf1\xcc\xb5\xd4\x38\x38\x5c\x0b\x64\x4b\x10\x6a\x62\x55" - "\xc1\x4f\xa3\x22\x58\x01\x92\x1c\x09\x68\xec\xe4\xf1\x01\xda\xe3" - "\x6d\x4b\xec\xc2\x9e\xc4\x8e\xc0\x00\x0f\x6e\x07\x7b\xec\x87\x0e" - "\x17\x46\xc7\x84\x78\x78\xd0\x9b\xeb\x86\xca\xd4\x30\x09\xe4\xd5" - "\xb7\x54\xab\xc0\x86\x2c\x7f\x0e\x8f\x00\xda\xd9\xdf\xb3\x56\xbe" - "\xce\xd5\x65\x1b\xe0\xe2\x55\x5a\xd1\xef\xfc\xe6\x20\x3f\x22\xc0" - "\xa6\x88\x63\x00\xa7\x0a\xcb\x73\xf1\x0d\x73\xba\x79\x39\x45\x8d" - "\xa8\x1f\x32\x58\xb1\xb5\x23\xe7\x68\x7d\xc4\x3a\x8f\x44\xa8\x36" - "\xc1\x5d\x0d\xcf\x4a\x21\x0f\x33\x8c\xb4\x57\x9a\x9f\xcb\xc6\xcb" - "\x04\x25\x74\x3a\x91\xaf\xd6\xb5\x35\x94\xa5\xe3\xe1\xa4\x92\x87" - "\xb5\xc7\xd9\x23\x07\xe2\x37\xf3\xb9\x6d\x01\x55\xa2\x39\x65\x8e" - "\xee\xcc\x53\x29\xcb\x1f\x1c\x7e\x7d\x4e\xd6\xfc\xe7\x02\x0a\xba" - "\xdb\xa9\x2d\x74\x9a\xeb\xe0\x95\x50\x23\xcd\xff\xe7\xc4\x47\xc2" - "\x55\x08\xdb\x1b\x0f\xb8\xd4\x4d\x4f\xd7\xd7\x13\x4c\x66\xed\x0f" - "\x78\x7d\x9a\xd5\xb5\xc0\x9e\xf3\xff\xe6\xef\xb7\xea\xd1\xff\xd4" - "\xf7\x09\x92\x15\x3e\x44\xb4\x3e\x01\x29\x06\xf1\x73\xa3\x61\xe8" - "\x84\x7b\x3e\x0d\x12\x44\x73\x4a\x29\x4b\x82\xe3\xac\x64\x81\xa5" - "\xa5\x1d\xa6\xb5\xd6\xc2\xe5\x6f\x98\x3b\x7c\x70\x82\xda\xf9\xf1" - "\xde\x46\x7b\xe8\x9e\x03\xbf\xc7\xb2\xe6\x26\x24\x21\x6c\xb3\x67" - "\xde\xe0\x8c\x17\x93\xf2\x32\xe5\xae\x5e\xfd\x4f\x77\x40\x3e\x25" - "\xfe\xfe\xc0\xd5\xc9\xcd\xff\x8b\xa2\x4e\xae\x89\x12\x0f\x05\xdb" - "\xc5\xba\xc2\x02\x6f\x60\xf8\x91\x23\x99\x29\xb4\x22\x5e\x62\x43" - "\x5e\xde\xb3\x56\x02\x3c\xa2\xf8\x2a\xbf\x82\xf7\x7a\xcc\x2c\x26" - "\x96\x88\x0e\x8d\x65\xb6\x7f\xda\x3c\x52\x6a\x25\xc1\xb2\x89\x5e" - "\x3d\x30\x39\x5f\x11\x74\x3c\x00\xa2\xef\x2c\xff\x3e\xaa\x04\x34" - "\x93\xbd\x55\xc2\x8b\x98\x5b\x66\x9c\x53\x8b\x27\x7c\x4c\x87\x0b" - "\x5b\x24\x72\x08\x06\xf9\x11\x02\x03\x01\x00\x01\xa3\x60\x30\x5e" +BYTE test_Certificate[525] = + "\x30\x82\x02\x09\x30\x82\x01\x76\xa0\x03\x02\x01\x02\x02\x10\xcb" + "\x69\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30" + "\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12" + "\x06\x03\x55\x04\x03\x13\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38" + "\x52\x32\x30\x1e\x17\x0d\x31\x32\x31\x31\x31\x37\x30\x30\x35\x39" + "\x32\x31\x5a\x17\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35" + "\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x44" + "\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x30\x81\x9f\x30\x0d\x06" + "\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00" + "\x30\x81\x89\x02\x81\x81\x00\x9b\x00\xf8\x1a\x2d\x37\xc6\x8d\xa1" + "\x39\x91\x46\xf3\x6a\x1b\xf9\x60\x6c\xb3\x6c\xa0\xac\xed\x85\xe0" + "\x3f\xdc\x92\x86\x36\xbd\x64\xbf\x36\x51\xdb\x57\x3a\x8a\x82\x6b" + "\xd8\x94\x17\x7b\xd3\x91\x11\x98\xef\x19\x06\x52\x30\x03\x73\x67" + "\xc8\xed\x8e\xfa\x0b\x3d\x4c\xc9\x10\x63\x9f\xcf\xb4\xcf\x39\xd8" + "\xfe\x99\xeb\x5b\x11\xf2\xfc\xfa\x86\x24\xd9\xff\xd9\x19\xf5\x69" + "\xb4\xdf\x5a\x5a\xc4\x94\xb4\xb0\x07\x25\x97\x13\xad\x7e\x38\x14" + "\xfb\xd6\x33\x65\x6f\xe6\xf7\x48\x4b\x2d\xb3\x51\x2e\x6d\xc7\xea" + "\x11\x76\x9a\x2b\xf0\x00\x4d\x02\x03\x01\x00\x01\xa3\x60\x30\x5e" "\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01" "\x05\x05\x07\x03\x01\x30\x47\x06\x03\x55\x1d\x01\x04\x40\x30\x3e" - "\x80\x10\x8c\x90\xe6\x16\x1e\x1e\xa9\xf3\xbf\x03\x93\x22\xe1\x0c" - "\x3b\xfe\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13" - "\x0b\x4c\x41\x42\x33\x2d\x57\x32\x4b\x38\x52\x32\x82\x10\x33\x1d" - "\x91\x3b\x2b\x0a\xc8\x90\x4a\x19\x35\xed\x79\x65\xb8\xe3"; + "\x80\x10\xeb\x65\x26\x03\x95\x4b\xd6\xc0\x54\x75\x78\x7c\xb6\x2a" + "\xa1\xbb\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13" + "\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x82\x10\xcb\x69" + "\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30\x09" + "\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x81\x81\x00\x7b\xfa\xfe" + "\xee\x74\x05\xac\xbb\x79\xe9\xda\xca\x00\x44\x96\x94\x71\x92\xb1" + "\xdb\xc9\x9b\x71\x29\xc0\xe4\x28\x5e\x6a\x50\x99\xcd\xa8\x17\xe4" + "\x56\xb9\xef\x7f\x02\x7d\x96\xa3\x48\x14\x72\x75\x2f\xb0\xb5\x87" + "\xee\x55\xe9\x6a\x6d\x28\x3c\xc1\xfd\x00\xe4\x76\xe3\x80\x88\x78" + "\x26\x0d\x6c\x8c\xb8\x64\x61\x63\xb7\x13\x3a\xab\xc7\xdd\x1d\x0a" + "\xd7\x15\x45\xa1\xd6\xd9\x34\xc7\x21\x48\xfb\x43\x87\x38\xda\x1f" + "\x50\x47\xb1\xa5\x5c\x47\xed\x04\x44\x97\xd3\xac\x74\x2d\xeb\x09" + "\x77\x59\xbf\xa3\x54\x5b\xde\x42\xd5\x23\x5a\x71\x9f"; -/* 544D5750776A7533334736516B4D76694762777548516B41 (MD5 hash of SEC_CHANNEL_BINDINGS) */ -BYTE test_ChannelBindingsHash[] = "\x54\x4D\x57\x50\x77\x6A\x75\x33\x33\x47\x36\x51\x6B\x4D\x76\x69\x47\x62\x77\x75\x48\x51\x6B\x41"; +BYTE test_CertificateHash_SHA256[] = + "\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53" + "\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95"; -/* 63d3533695bf1bd0de203fee9691a2515e2e7bfe75bb8ab09da08911e157847c (SHA-256 hash of Certificate, length = 32) */ -BYTE test_CertificateHash_SHA256[] = "\x63\xd3\x53\x36\x95\xbf\x1b\xd0\xde\x20\x3f\xee\x96\x91\xa2\x51\x5e\x2e\x7b\xfe\x75\xbb\x8a\xb0\x9d\xa0\x89\x11\xe1\x57\x84\x7c"; - -/* c0ef35911b5ba641c4b67f4b32c7efc4c1d82e2b (SHA1 hash of Certificate, length = 20) */ -BYTE test_CertificateHash_SHA1[] = "\xc0\xef\x35\x91\x1b\x5b\xa6\x41\xc4\xb6\x7f\x4b\x32\xc7\xef\xc4\xc1\xd8\x2e\x2b"; - -/* d2b4df88a54faf95590cd336987a97a5 (MD5 hash of Certificate, length = 16) */ -BYTE test_CertificateHash_MD5[] = "\xd2\xb4\xdf\x88\xa5\x4f\xaf\x95\x59\x0c\xd3\x36\x98\x7a\x97\xa5"; - -BYTE* test_CertificateHash = test_CertificateHash_SHA256; -int test_CertificateHashLength = 32; +BYTE test_ChannelBindingsHash[] = + "\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10"; /* * Channel Bindings Data: @@ -313,11 +290,11 @@ void ntlm_uint32_to_big_endian(UINT32 num, BYTE be32[4]) /* typedef struct gss_channel_bindings_struct { - OM_uint32 initiator_addrtype; - gss_buffer_desc initiator_address; - OM_uint32 acceptor_addrtype; - gss_buffer_desc acceptor_address; - gss_buffer_desc application_data; + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; } *gss_channel_bindings_t; */ @@ -326,20 +303,32 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) #if 0 MD5_CTX md5; BYTE be32[4]; - int HashLength; int PrefixLength; + SHA256_CTX sha256; + BYTE* CertificateHash; + int CertificateHashLength; BYTE* pChannelBindingToken; int ChannelBindingTokenLength; SEC_CHANNEL_BINDINGS* ChannelBindings; ZeroMemory(context->ChannelBindingsHash, 16); - HashLength = test_CertificateHashLength; + CertificateHashLength = 32; + CertificateHash = (BYTE*) malloc(CertificateHashLength); + ZeroMemory(CertificateHash, CertificateHashLength); + + SHA256_Init(&sha256); + SHA256_Update(&sha256, test_Certificate, sizeof(test_Certificate)); + SHA256_Final(CertificateHash, &sha256); + + printf("Certificate SHA256 Hash:\n"); + winpr_HexDump(CertificateHash, CertificateHashLength); + PrefixLength = strlen(TlsServerEndPointPrefix); - ChannelBindingTokenLength = PrefixLength + HashLength; + ChannelBindingTokenLength = PrefixLength + CertificateHashLength; context->ChannelBindingToken = (BYTE*) malloc(ChannelBindingTokenLength + 1); strcpy((char*) context->ChannelBindingToken, TlsServerEndPointPrefix); - CopyMemory(&context->ChannelBindingToken[PrefixLength], test_CertificateHash, HashLength); + CopyMemory(&context->ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength); printf("ChannelBindingToken:\n"); winpr_HexDump(context->ChannelBindingToken, ChannelBindingTokenLength); @@ -366,24 +355,15 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) ntlm_uint32_to_big_endian(ChannelBindings->cbInitiatorLength, be32); MD5_Update(&md5, be32, 4); - //ntlm_uint32_to_big_endian(ChannelBindings->dwInitiatorOffset, be32); - //MD5_Update(&md5, be32, 4); - ntlm_uint32_to_big_endian(ChannelBindings->dwAcceptorAddrType, be32); MD5_Update(&md5, be32, 4); ntlm_uint32_to_big_endian(ChannelBindings->cbAcceptorLength, be32); MD5_Update(&md5, be32, 4); - //ntlm_uint32_to_big_endian(ChannelBindings->dwAcceptorOffset, be32); - //MD5_Update(&md5, be32, 4); - ntlm_uint32_to_big_endian(ChannelBindings->cbApplicationDataLength, be32); MD5_Update(&md5, be32, 4); - //ntlm_uint32_to_big_endian(ChannelBindings->dwApplicationDataOffset, be32); - //MD5_Update(&md5, be32, 4); - MD5_Update(&md5, (void*) pChannelBindingToken, ChannelBindingTokenLength); MD5_Final(context->ChannelBindingsHash, &md5); @@ -391,6 +371,8 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) printf("ChannelBindingsHash:\n"); winpr_HexDump(context->ChannelBindingsHash, 16); + free(CertificateHash); + printf("\n\n"); #endif } diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c index f7cf4ad77..8d4afa859 100644 --- a/winpr/libwinpr/sspi/test/TestNTLM.c +++ b/winpr/libwinpr/sspi/test/TestNTLM.c @@ -2,8 +2,58 @@ #include #include -int TestNTLM(int argc, char* argv[]) +BYTE test_Certificate[] = + "\x30\x82\x02\x09\x30\x82\x01\x76\xa0\x03\x02\x01\x02\x02\x10\xcb" + "\x69\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30" + "\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12" + "\x06\x03\x55\x04\x03\x13\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38" + "\x52\x32\x30\x1e\x17\x0d\x31\x32\x31\x31\x31\x37\x30\x30\x35\x39" + "\x32\x31\x5a\x17\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35" + "\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x44" + "\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x30\x81\x9f\x30\x0d\x06" + "\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00" + "\x30\x81\x89\x02\x81\x81\x00\x9b\x00\xf8\x1a\x2d\x37\xc6\x8d\xa1" + "\x39\x91\x46\xf3\x6a\x1b\xf9\x60\x6c\xb3\x6c\xa0\xac\xed\x85\xe0" + "\x3f\xdc\x92\x86\x36\xbd\x64\xbf\x36\x51\xdb\x57\x3a\x8a\x82\x6b" + "\xd8\x94\x17\x7b\xd3\x91\x11\x98\xef\x19\x06\x52\x30\x03\x73\x67" + "\xc8\xed\x8e\xfa\x0b\x3d\x4c\xc9\x10\x63\x9f\xcf\xb4\xcf\x39\xd8" + "\xfe\x99\xeb\x5b\x11\xf2\xfc\xfa\x86\x24\xd9\xff\xd9\x19\xf5\x69" + "\xb4\xdf\x5a\x5a\xc4\x94\xb4\xb0\x07\x25\x97\x13\xad\x7e\x38\x14" + "\xfb\xd6\x33\x65\x6f\xe6\xf7\x48\x4b\x2d\xb3\x51\x2e\x6d\xc7\xea" + "\x11\x76\x9a\x2b\xf0\x00\x4d\x02\x03\x01\x00\x01\xa3\x60\x30\x5e" + "\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01" + "\x05\x05\x07\x03\x01\x30\x47\x06\x03\x55\x1d\x01\x04\x40\x30\x3e" + "\x80\x10\xeb\x65\x26\x03\x95\x4b\xd6\xc0\x54\x75\x78\x7c\xb6\x2a" + "\xa1\xbb\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13" + "\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x82\x10\xcb\x69" + "\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30\x09" + "\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x81\x81\x00\x7b\xfa\xfe" + "\xee\x74\x05\xac\xbb\x79\xe9\xda\xca\x00\x44\x96\x94\x71\x92\xb1" + "\xdb\xc9\x9b\x71\x29\xc0\xe4\x28\x5e\x6a\x50\x99\xcd\xa8\x17\xe4" + "\x56\xb9\xef\x7f\x02\x7d\x96\xa3\x48\x14\x72\x75\x2f\xb0\xb5\x87" + "\xee\x55\xe9\x6a\x6d\x28\x3c\xc1\xfd\x00\xe4\x76\xe3\x80\x88\x78" + "\x26\x0d\x6c\x8c\xb8\x64\x61\x63\xb7\x13\x3a\xab\xc7\xdd\x1d\x0a" + "\xd7\x15\x45\xa1\xd6\xd9\x34\xc7\x21\x48\xfb\x43\x87\x38\xda\x1f" + "\x50\x47\xb1\xa5\x5c\x47\xed\x04\x44\x97\xd3\xac\x74\x2d\xeb\x09" + "\x77\x59\xbf\xa3\x54\x5b\xde\x42\xd5\x23\x5a\x71\x9f"; + +BYTE test_Certificate_SHA256Hash[] = + "\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53" + "\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95"; + +BYTE test_ChannelBindings_MD5Hash[] = + "\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10"; + +int test_ntlm_channel_binding_token() { + return 0; } +int TestNTLM(int argc, char* argv[]) +{ + if (test_ntlm_channel_binding_token() < 0) + return -1; + + return 0; +} From 1d893ed268b39a277ba4688b3236f27f2271e4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 9 Jan 2013 00:20:08 -0500 Subject: [PATCH 24/24] libwinpr-sspi: add support for NTLMv2 Channel Binding Token (CBT) --- include/freerdp/crypto/tls.h | 4 + libfreerdp/core/gateway/ncacn_http.c | 15 +-- libfreerdp/core/gateway/ntlm.c | 35 ++++-- libfreerdp/core/gateway/ntlm.h | 9 +- libfreerdp/core/gateway/rpc_bind.c | 16 +-- libfreerdp/crypto/tls.c | 83 +++++++++++++ winpr/libwinpr/sspi/NTLM/ntlm.c | 17 ++- winpr/libwinpr/sspi/NTLM/ntlm.h | 2 +- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 148 ++++------------------- 9 files changed, 173 insertions(+), 156 deletions(-) diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h index 9ac7223bb..527f69ba0 100644 --- a/include/freerdp/crypto/tls.h +++ b/include/freerdp/crypto/tls.h @@ -23,6 +23,9 @@ #include "crypto.h" #include "certificate.h" +#include +#include + #include #include @@ -40,6 +43,7 @@ struct rdp_tls BYTE* PublicKey; DWORD PublicKeyLength; rdpSettings* settings; + SecPkgContext_Bindings* Bindings; rdpCertificateStore* certificate_store; }; diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index 4020a844f..4e3489d81 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -80,7 +80,7 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc) content_length = (continue_needed) ? 0 : 0x40000000; - s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, content_length, TSG_CHANNEL_IN); + s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], content_length, TSG_CHANNEL_IN); DEBUG_RPC("\n%s", Stream_Buffer(s)); rpc_in_write(rpc, Stream_Buffer(s), Stream_Length(s)); @@ -102,8 +102,8 @@ int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc) crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam), &ntlm_token_data, &ntlm_token_length); - ntlm->inputBuffer.pvBuffer = ntlm_token_data; - ntlm->inputBuffer.cbBuffer = ntlm_token_length; + ntlm->inputBuffer[0].pvBuffer = ntlm_token_data; + ntlm->inputBuffer[0].cbBuffer = ntlm_token_length; http_response_free(http_response); @@ -123,7 +123,8 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel) ntlm = rpc->NtlmHttpOut->ntlm; ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, - settings->GatewayDomain, settings->GatewayPassword); + settings->GatewayDomain, settings->GatewayPassword, + rpc->TlsIn->Bindings); //ntlm_client_make_spn(ntlm, NULL, settings->GatewayHostname); ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname); @@ -168,7 +169,7 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc) content_length = (continue_needed) ? 0 : 76; - s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, content_length, TSG_CHANNEL_OUT); + s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], content_length, TSG_CHANNEL_OUT); DEBUG_RPC("\n%s", Stream_Buffer(s)); rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s)); @@ -190,8 +191,8 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam), &ntlm_token_data, &ntlm_token_length); - ntlm->inputBuffer.pvBuffer = ntlm_token_data; - ntlm->inputBuffer.cbBuffer = ntlm_token_length; + ntlm->inputBuffer[0].pvBuffer = ntlm_token_data; + ntlm->inputBuffer[0].cbBuffer = ntlm_token_length; http_response_free(http_response); diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index 656a89230..75ba9bcf1 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -37,12 +37,15 @@ #include "ntlm.h" -BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password) +BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password, SecPkgContext_Bindings* Bindings) { SECURITY_STATUS status; sspi_GlobalInit(); + ntlm->http = http; + ntlm->Bindings = Bindings; + #ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; @@ -91,7 +94,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* ntlm->fContextReq = 0; - if (http) + if (ntlm->http) { /* flags for HTTP authentication */ ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY; @@ -195,25 +198,33 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm) { SECURITY_STATUS status; - if (ntlm->outputBuffer.pvBuffer) + if (ntlm->outputBuffer[0].pvBuffer) { - free(ntlm->outputBuffer.pvBuffer); - ntlm->outputBuffer.pvBuffer = NULL; + free(ntlm->outputBuffer[0].pvBuffer); + ntlm->outputBuffer[0].pvBuffer = NULL; } ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION; ntlm->outputBufferDesc.cBuffers = 1; - ntlm->outputBufferDesc.pBuffers = &ntlm->outputBuffer; - ntlm->outputBuffer.BufferType = SECBUFFER_TOKEN; - ntlm->outputBuffer.cbBuffer = ntlm->cbMaxToken; - ntlm->outputBuffer.pvBuffer = malloc(ntlm->outputBuffer.cbBuffer); + ntlm->outputBufferDesc.pBuffers = ntlm->outputBuffer; + ntlm->outputBuffer[0].BufferType = SECBUFFER_TOKEN; + ntlm->outputBuffer[0].cbBuffer = ntlm->cbMaxToken; + ntlm->outputBuffer[0].pvBuffer = malloc(ntlm->outputBuffer[0].cbBuffer); if (ntlm->haveInputBuffer) { ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION; ntlm->inputBufferDesc.cBuffers = 1; - ntlm->inputBufferDesc.pBuffers = &ntlm->inputBuffer; - ntlm->inputBuffer.BufferType = SECBUFFER_TOKEN; + ntlm->inputBufferDesc.pBuffers = ntlm->inputBuffer; + ntlm->inputBuffer[0].BufferType = SECBUFFER_TOKEN; + + if (ntlm->Bindings) + { + ntlm->inputBufferDesc.cBuffers++; + ntlm->inputBuffer[1].BufferType = SECBUFFER_CHANNEL_BINDINGS; + ntlm->inputBuffer[1].cbBuffer = ntlm->Bindings->BindingsLength; + ntlm->inputBuffer[1].pvBuffer = (void*) ntlm->Bindings->Bindings; + } } status = ntlm->table->InitializeSecurityContext(&ntlm->credentials, @@ -243,7 +254,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm) if (ntlm->haveInputBuffer) { - free(ntlm->inputBuffer.pvBuffer); + free(ntlm->inputBuffer[0].pvBuffer); } ntlm->haveInputBuffer = TRUE; diff --git a/libfreerdp/core/gateway/ntlm.h b/libfreerdp/core/gateway/ntlm.h index 1d2b2d38e..845e0ad68 100644 --- a/libfreerdp/core/gateway/ntlm.h +++ b/libfreerdp/core/gateway/ntlm.h @@ -43,14 +43,15 @@ typedef struct rdp_ntlm_http rdpNtlmHttp; struct rdp_ntlm { + BOOL http; CtxtHandle context; ULONG cbMaxToken; ULONG fContextReq; ULONG pfContextAttr; TimeStamp expiration; PSecBuffer pBuffer; - SecBuffer inputBuffer; - SecBuffer outputBuffer; + SecBuffer inputBuffer[2]; + SecBuffer outputBuffer[2]; BOOL haveContext; BOOL haveInputBuffer; LPTSTR ServicePrincipalName; @@ -62,6 +63,7 @@ struct rdp_ntlm SecurityFunctionTable* table; SEC_WINNT_AUTH_IDENTITY identity; SecPkgContext_Sizes ContextSizes; + SecPkgContext_Bindings* Bindings; }; struct rdp_ntlm_http @@ -72,7 +74,8 @@ struct rdp_ntlm_http BOOL ntlm_authenticate(rdpNtlm* ntlm); -BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality, char* user, char* domain, char* password); +BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality, char* user, + char* domain, char* password, SecPkgContext_Bindings* Bindings); void ntlm_client_uninit(rdpNtlm* ntlm); BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname); diff --git a/libfreerdp/core/gateway/rpc_bind.c b/libfreerdp/core/gateway/rpc_bind.c index 9c01eb4c8..d524ff0d5 100644 --- a/libfreerdp/core/gateway/rpc_bind.c +++ b/libfreerdp/core/gateway/rpc_bind.c @@ -102,7 +102,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc) rpc->ntlm = ntlm_new(); - ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword); + ntlm_client_init(rpc->ntlm, FALSE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, NULL); ntlm_client_make_spn(rpc->ntlm, NULL, settings->GatewayHostname); ntlm_authenticate(rpc->ntlm); @@ -112,8 +112,8 @@ int rpc_send_bind_pdu(rdpRpc* rpc) rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) bind_pdu); - bind_pdu->auth_length = rpc->ntlm->outputBuffer.cbBuffer; - bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer.pvBuffer; + bind_pdu->auth_length = rpc->ntlm->outputBuffer[0].cbBuffer; + bind_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; bind_pdu->ptype = PTYPE_BIND; bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX; @@ -228,11 +228,11 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) rpc->max_recv_frag = header->bind_ack.max_xmit_frag; rpc->max_xmit_frag = header->bind_ack.max_recv_frag; - rpc->ntlm->inputBuffer.cbBuffer = header->common.auth_length; - rpc->ntlm->inputBuffer.pvBuffer = malloc(header->common.auth_length); + rpc->ntlm->inputBuffer[0].cbBuffer = header->common.auth_length; + rpc->ntlm->inputBuffer[0].pvBuffer = malloc(header->common.auth_length); auth_data = buffer + (header->common.frag_length - header->common.auth_length); - CopyMemory(rpc->ntlm->inputBuffer.pvBuffer, auth_data, header->common.auth_length); + CopyMemory(rpc->ntlm->inputBuffer[0].pvBuffer, auth_data, header->common.auth_length); ntlm_authenticate(rpc->ntlm); @@ -261,8 +261,8 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) rpc_pdu_header_init(rpc, (rpcconn_hdr_t*) auth_3_pdu); - auth_3_pdu->auth_length = rpc->ntlm->outputBuffer.cbBuffer; - auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer.pvBuffer; + auth_3_pdu->auth_length = rpc->ntlm->outputBuffer[0].cbBuffer; + auth_3_pdu->auth_verifier.auth_value = rpc->ntlm->outputBuffer[0].pvBuffer; auth_3_pdu->ptype = PTYPE_RPC_AUTH_3; auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 6b265fb27..7269304fa 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -58,6 +59,86 @@ static void tls_free_certificate(CryptoCert cert) free(cert); } +static void tls_md5_update_uint32_be(MD5_CTX* md5, UINT32 num) +{ + BYTE be32[4]; + + be32[0] = (num >> 0) & 0xFF; + be32[1] = (num >> 8) & 0xFF; + be32[2] = (num >> 16) & 0xFF; + be32[3] = (num >> 24) & 0xFF; + + MD5_Update(md5, be32, 4); +} + +BYTE* tls_get_channel_bindings_hash(SecPkgContext_Bindings* Bindings) +{ + MD5_CTX md5; + BYTE* ChannelBindingToken; + UINT32 ChannelBindingTokenLength; + BYTE* ChannelBindingsHash; + UINT32 ChannelBindingsHashLength; + SEC_CHANNEL_BINDINGS* ChannelBindings; + + ChannelBindings = Bindings->Bindings; + ChannelBindingTokenLength = Bindings->BindingsLength - sizeof(SEC_CHANNEL_BINDINGS); + ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset]; + + ChannelBindingsHashLength = 16; + ChannelBindingsHash = (BYTE*) malloc(ChannelBindingsHashLength); + ZeroMemory(ChannelBindingsHash, ChannelBindingsHashLength); + + MD5_Init(&md5); + + tls_md5_update_uint32_be(&md5, ChannelBindings->dwInitiatorAddrType); + tls_md5_update_uint32_be(&md5, ChannelBindings->cbInitiatorLength); + tls_md5_update_uint32_be(&md5, ChannelBindings->dwAcceptorAddrType); + tls_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength); + tls_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength); + + MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength); + + MD5_Final(ChannelBindingsHash, &md5); + + return ChannelBindingsHash; +} + +#define TLS_SERVER_END_POINT "tls-server-end-point:" + +SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert) +{ + int PrefixLength; + BYTE CertificateHash[32]; + UINT32 CertificateHashLength; + BYTE* ChannelBindingToken; + UINT32 ChannelBindingTokenLength; + SEC_CHANNEL_BINDINGS* ChannelBindings; + SecPkgContext_Bindings* ContextBindings; + + ZeroMemory(CertificateHash, sizeof(CertificateHash)); + X509_digest(cert, EVP_sha256(), CertificateHash, &CertificateHashLength); + + PrefixLength = strlen(TLS_SERVER_END_POINT); + ChannelBindingTokenLength = PrefixLength + CertificateHashLength; + + ContextBindings = (SecPkgContext_Bindings*) malloc(sizeof(SecPkgContext_Bindings)); + ZeroMemory(ContextBindings, sizeof(SecPkgContext_Bindings)); + + ContextBindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength; + ChannelBindings = (SEC_CHANNEL_BINDINGS*) malloc(ContextBindings->BindingsLength); + ZeroMemory(ChannelBindings, ContextBindings->BindingsLength); + ContextBindings->Bindings = ChannelBindings; + + ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength; + ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS); + ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset]; + + strcpy((char*) ChannelBindingToken, TLS_SERVER_END_POINT); + CopyMemory(&ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength); + + return ContextBindings; +} + BOOL tls_connect(rdpTls* tls) { CryptoCert cert; @@ -135,6 +216,8 @@ BOOL tls_connect(rdpTls* tls) return FALSE; } + tls->Bindings = tls_get_channel_bindings(cert->px509); + if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 41c537898..5ffff741b 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -416,8 +416,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti NTLM_CONTEXT* context; SECURITY_STATUS status; CREDENTIALS* credentials; - PSecBuffer input_buffer; - PSecBuffer output_buffer; + PSecBuffer input_buffer = NULL; + PSecBuffer output_buffer = NULL; + PSecBuffer channel_bindings = NULL; context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); @@ -478,6 +479,18 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredenti if (input_buffer->cbBuffer < 1) return SEC_E_INVALID_TOKEN; + if (pInput->cBuffers > 1) + { + if (pInput->pBuffers[1].BufferType == SECBUFFER_CHANNEL_BINDINGS) + channel_bindings = &pInput->pBuffers[1]; + } + + if (channel_bindings) + { + context->Bindings.BindingsLength = channel_bindings->cbBuffer; + context->Bindings.Bindings = (SEC_CHANNEL_BINDINGS*) channel_bindings->pvBuffer; + } + if (context->state == NTLM_STATE_CHALLENGE) { status = ntlm_read_ChallengeMessage(context, input_buffer); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index f0146b7d6..1c8ad520b 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -243,7 +243,7 @@ struct _NTLM_CONTEXT SEC_WINNT_AUTH_IDENTITY identity; BYTE* ChannelBindingToken; BYTE ChannelBindingsHash[16]; - SecPkgContext_Bindings EndpointBindings; + SecPkgContext_Bindings Bindings; SecBuffer NegotiateMessage; SecBuffer ChallengeMessage; SecBuffer AuthenticateMessage; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index 8f08d11a7..bfa2d91c8 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -228,66 +228,6 @@ void ntlm_free_unicode_string(PUNICODE_STRING string) * https://raw.github.com/mozilla/mozilla-central/master/extensions/auth/nsAuthSSPI.cpp */ -/* Certificate */ - -BYTE test_Certificate[525] = - "\x30\x82\x02\x09\x30\x82\x01\x76\xa0\x03\x02\x01\x02\x02\x10\xcb" - "\x69\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30" - "\x09\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x30\x16\x31\x14\x30\x12" - "\x06\x03\x55\x04\x03\x13\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38" - "\x52\x32\x30\x1e\x17\x0d\x31\x32\x31\x31\x31\x37\x30\x30\x35\x39" - "\x32\x31\x5a\x17\x0d\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35" - "\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x44" - "\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x30\x81\x9f\x30\x0d\x06" - "\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00" - "\x30\x81\x89\x02\x81\x81\x00\x9b\x00\xf8\x1a\x2d\x37\xc6\x8d\xa1" - "\x39\x91\x46\xf3\x6a\x1b\xf9\x60\x6c\xb3\x6c\xa0\xac\xed\x85\xe0" - "\x3f\xdc\x92\x86\x36\xbd\x64\xbf\x36\x51\xdb\x57\x3a\x8a\x82\x6b" - "\xd8\x94\x17\x7b\xd3\x91\x11\x98\xef\x19\x06\x52\x30\x03\x73\x67" - "\xc8\xed\x8e\xfa\x0b\x3d\x4c\xc9\x10\x63\x9f\xcf\xb4\xcf\x39\xd8" - "\xfe\x99\xeb\x5b\x11\xf2\xfc\xfa\x86\x24\xd9\xff\xd9\x19\xf5\x69" - "\xb4\xdf\x5a\x5a\xc4\x94\xb4\xb0\x07\x25\x97\x13\xad\x7e\x38\x14" - "\xfb\xd6\x33\x65\x6f\xe6\xf7\x48\x4b\x2d\xb3\x51\x2e\x6d\xc7\xea" - "\x11\x76\x9a\x2b\xf0\x00\x4d\x02\x03\x01\x00\x01\xa3\x60\x30\x5e" - "\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01" - "\x05\x05\x07\x03\x01\x30\x47\x06\x03\x55\x1d\x01\x04\x40\x30\x3e" - "\x80\x10\xeb\x65\x26\x03\x95\x4b\xd6\xc0\x54\x75\x78\x7c\xb6\x2a" - "\xa1\xbb\xa1\x18\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13" - "\x0b\x44\x43\x2d\x57\x53\x32\x30\x30\x38\x52\x32\x82\x10\xcb\x69" - "\x79\xcd\x51\x75\xc5\xb7\x4b\x67\x30\x83\x6c\x78\x44\x27\x30\x09" - "\x06\x05\x2b\x0e\x03\x02\x1d\x05\x00\x03\x81\x81\x00\x7b\xfa\xfe" - "\xee\x74\x05\xac\xbb\x79\xe9\xda\xca\x00\x44\x96\x94\x71\x92\xb1" - "\xdb\xc9\x9b\x71\x29\xc0\xe4\x28\x5e\x6a\x50\x99\xcd\xa8\x17\xe4" - "\x56\xb9\xef\x7f\x02\x7d\x96\xa3\x48\x14\x72\x75\x2f\xb0\xb5\x87" - "\xee\x55\xe9\x6a\x6d\x28\x3c\xc1\xfd\x00\xe4\x76\xe3\x80\x88\x78" - "\x26\x0d\x6c\x8c\xb8\x64\x61\x63\xb7\x13\x3a\xab\xc7\xdd\x1d\x0a" - "\xd7\x15\x45\xa1\xd6\xd9\x34\xc7\x21\x48\xfb\x43\x87\x38\xda\x1f" - "\x50\x47\xb1\xa5\x5c\x47\xed\x04\x44\x97\xd3\xac\x74\x2d\xeb\x09" - "\x77\x59\xbf\xa3\x54\x5b\xde\x42\xd5\x23\x5a\x71\x9f"; - -BYTE test_CertificateHash_SHA256[] = - "\xea\x05\xfe\xfe\xcc\x6b\x0b\xd5\x71\xdb\xbc\x5b\xaa\x3e\xd4\x53" - "\x86\xd0\x44\x68\x35\xf7\xb7\x4c\x85\x62\x1b\x99\x83\x47\x5f\x95"; - -BYTE test_ChannelBindingsHash[] = - "\x65\x86\xE9\x9D\x81\xC2\xFC\x98\x4E\x47\x17\x2F\xD4\xDD\x03\x10"; - -/* - * Channel Bindings Data: - * - * tls-server-end-point: - */ - -char TlsServerEndPointPrefix[] = "tls-server-end-point:"; - -void ntlm_uint32_to_big_endian(UINT32 num, BYTE be32[4]) -{ - be32[0] = (num >> 0) & 0xFF; - be32[1] = (num >> 8) & 0xFF; - be32[2] = (num >> 16) & 0xFF; - be32[3] = (num >> 24) & 0xFF; -} - /* typedef struct gss_channel_bindings_struct { OM_uint32 initiator_addrtype; @@ -298,83 +238,45 @@ typedef struct gss_channel_bindings_struct { } *gss_channel_bindings_t; */ +static void ntlm_md5_update_uint32_be(MD5_CTX* md5, UINT32 num) +{ + BYTE be32[4]; + + be32[0] = (num >> 0) & 0xFF; + be32[1] = (num >> 8) & 0xFF; + be32[2] = (num >> 16) & 0xFF; + be32[3] = (num >> 24) & 0xFF; + + MD5_Update(md5, be32, 4); +} + void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) { -#if 0 MD5_CTX md5; - BYTE be32[4]; - int PrefixLength; - SHA256_CTX sha256; - BYTE* CertificateHash; - int CertificateHashLength; - BYTE* pChannelBindingToken; - int ChannelBindingTokenLength; + BYTE* ChannelBindingToken; + UINT32 ChannelBindingTokenLength; SEC_CHANNEL_BINDINGS* ChannelBindings; ZeroMemory(context->ChannelBindingsHash, 16); + ChannelBindings = context->Bindings.Bindings; - CertificateHashLength = 32; - CertificateHash = (BYTE*) malloc(CertificateHashLength); - ZeroMemory(CertificateHash, CertificateHashLength); + if (!ChannelBindings) + return; - SHA256_Init(&sha256); - SHA256_Update(&sha256, test_Certificate, sizeof(test_Certificate)); - SHA256_Final(CertificateHash, &sha256); - - printf("Certificate SHA256 Hash:\n"); - winpr_HexDump(CertificateHash, CertificateHashLength); - - PrefixLength = strlen(TlsServerEndPointPrefix); - ChannelBindingTokenLength = PrefixLength + CertificateHashLength; - context->ChannelBindingToken = (BYTE*) malloc(ChannelBindingTokenLength + 1); - strcpy((char*) context->ChannelBindingToken, TlsServerEndPointPrefix); - CopyMemory(&context->ChannelBindingToken[PrefixLength], CertificateHash, CertificateHashLength); - - printf("ChannelBindingToken:\n"); - winpr_HexDump(context->ChannelBindingToken, ChannelBindingTokenLength); - - context->EndpointBindings.BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + ChannelBindingTokenLength; - context->EndpointBindings.Bindings = (SEC_CHANNEL_BINDINGS*) malloc(context->EndpointBindings.BindingsLength); - ZeroMemory(context->EndpointBindings.Bindings, context->EndpointBindings.BindingsLength); - - ChannelBindings = context->EndpointBindings.Bindings; - ChannelBindings->cbApplicationDataLength = ChannelBindingTokenLength; - ChannelBindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS); - - pChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset]; - CopyMemory(pChannelBindingToken, context->ChannelBindingToken, ChannelBindingTokenLength); - - printf("ChannelBindings\n"); - winpr_HexDump((BYTE*) ChannelBindings, context->EndpointBindings.BindingsLength); + ChannelBindingTokenLength = context->Bindings.BindingsLength - sizeof(SEC_CHANNEL_BINDINGS); + ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset]; MD5_Init(&md5); - ntlm_uint32_to_big_endian(ChannelBindings->dwInitiatorAddrType, be32); - MD5_Update(&md5, be32, 4); + ntlm_md5_update_uint32_be(&md5, ChannelBindings->dwInitiatorAddrType); + ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbInitiatorLength); + ntlm_md5_update_uint32_be(&md5, ChannelBindings->dwAcceptorAddrType); + ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength); + ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength); - ntlm_uint32_to_big_endian(ChannelBindings->cbInitiatorLength, be32); - MD5_Update(&md5, be32, 4); - - ntlm_uint32_to_big_endian(ChannelBindings->dwAcceptorAddrType, be32); - MD5_Update(&md5, be32, 4); - - ntlm_uint32_to_big_endian(ChannelBindings->cbAcceptorLength, be32); - MD5_Update(&md5, be32, 4); - - ntlm_uint32_to_big_endian(ChannelBindings->cbApplicationDataLength, be32); - MD5_Update(&md5, be32, 4); - - MD5_Update(&md5, (void*) pChannelBindingToken, ChannelBindingTokenLength); + MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength); MD5_Final(context->ChannelBindingsHash, &md5); - - printf("ChannelBindingsHash:\n"); - winpr_HexDump(context->ChannelBindingsHash, 16); - - free(CertificateHash); - - printf("\n\n"); -#endif } void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)