20#include <winpr/config.h>
23#include <winpr/sspi.h>
30static char* SCHANNEL_PACKAGE_NAME =
"Schannel";
32#define TAG WINPR_TAG("sspi.Schannel")
42 context->openssl = schannel_openssl_new();
44 if (!context->openssl)
58 schannel_openssl_free(context->openssl);
74static ALG_ID schannel_SupportedAlgs[] = { CALG_AES_128,
86 (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RESERVED7 |
91static SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(
92 WINPR_ATTR_UNUSED
PCredHandle phCredential, ULONG ulAttribute,
void* pBuffer)
94 if (ulAttribute == SECPKG_ATTR_SUPPORTED_ALGS)
97 SupportedAlgs->cSupportedAlgs =
sizeof(schannel_SupportedAlgs) /
sizeof(ALG_ID);
98 SupportedAlgs->palgSupportedAlgs = (ALG_ID*)schannel_SupportedAlgs;
101 else if (ulAttribute == SECPKG_ATTR_CIPHER_STRENGTHS)
104 CipherStrengths->dwMinimumCipherStrength = 40;
105 CipherStrengths->dwMaximumCipherStrength = 256;
108 else if (ulAttribute == SECPKG_ATTR_SUPPORTED_PROTOCOLS)
112 SupportedProtocols->grbitProtocol = (SP_PROT_CLIENTS | SP_PROT_SERVERS);
116 WLog_ERR(TAG,
"TODO: Implement ulAttribute=%08" PRIx32, ulAttribute);
117 return SEC_E_UNSUPPORTED_FUNCTION;
120static SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(
PCredHandle phCredential,
124 return schannel_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
127static SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(
128 WINPR_ATTR_UNUSED SEC_WCHAR* pszPrincipal, WINPR_ATTR_UNUSED SEC_WCHAR* pszPackage,
129 ULONG fCredentialUse, WINPR_ATTR_UNUSED
void* pvLogonID,
void* pAuthData,
130 WINPR_ATTR_UNUSED SEC_GET_KEY_FN pGetKeyFn, WINPR_ATTR_UNUSED
void* pvGetKeyArgument,
135 if (fCredentialUse == SECPKG_CRED_OUTBOUND)
138 credentials = schannel_CredentialsNew();
139 credentials->fCredentialUse = fCredentialUse;
147 sspi_SecureHandleSetLowerPointer(phCredential, (
void*)credentials);
148 sspi_SecureHandleSetUpperPointer(phCredential, (
void*)SCHANNEL_PACKAGE_NAME);
151 else if (fCredentialUse == SECPKG_CRED_INBOUND)
153 credentials = schannel_CredentialsNew();
154 credentials->fCredentialUse = fCredentialUse;
155 sspi_SecureHandleSetLowerPointer(phCredential, (
void*)credentials);
156 sspi_SecureHandleSetUpperPointer(phCredential, (
void*)SCHANNEL_PACKAGE_NAME);
163static SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleA(
164 SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse,
void* pvLogonID,
165 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument,
PCredHandle phCredential,
168 SECURITY_STATUS status = 0;
169 SEC_WCHAR* pszPrincipalW =
nullptr;
170 SEC_WCHAR* pszPackageW =
nullptr;
172 pszPrincipalW = ConvertUtf8ToWCharAlloc(pszPrincipal,
nullptr);
174 pszPackageW = ConvertUtf8ToWCharAlloc(pszPackage,
nullptr);
176 status = schannel_AcquireCredentialsHandleW(pszPrincipalW, pszPackageW, fCredentialUse,
177 pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument,
178 phCredential, ptsExpiry);
184static SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(
PCredHandle phCredential)
187 return SEC_E_INVALID_HANDLE;
191 sspi_SecureHandleInvalidate(phCredential);
193 return SEC_E_INVALID_HANDLE;
195 schannel_CredentialsFree(credentials);
199static SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(
201 WINPR_ATTR_UNUSED ULONG fContextReq, WINPR_ATTR_UNUSED ULONG Reserved1,
202 WINPR_ATTR_UNUSED ULONG TargetDataRep,
PSecBufferDesc pInput, WINPR_ATTR_UNUSED ULONG Reserved2,
206 SECURITY_STATUS status = 0;
211 if (phContext && !phContext->dwLower && !phContext->dwUpper)
212 return SEC_E_INVALID_HANDLE;
214 context = sspi_SecureHandleGetLowerPointer(phContext);
218 context = schannel_ContextNew();
221 return SEC_E_INSUFFICIENT_MEMORY;
224 context->server = FALSE;
225 CopyMemory(&context->cred, &credentials->cred,
sizeof(
SCHANNEL_CRED));
226 sspi_SecureHandleSetLowerPointer(phNewContext, context);
227 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)SCHANNEL_PACKAGE_NAME);
228 schannel_openssl_client_init(context->openssl);
231 status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput);
235static SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(
237 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
240 SECURITY_STATUS status = 0;
241 SEC_WCHAR* pszTargetNameW =
nullptr;
243 if (pszTargetName !=
nullptr)
245 pszTargetNameW = ConvertUtf8ToWCharAlloc(pszTargetName,
nullptr);
247 return SEC_E_INSUFFICIENT_MEMORY;
250 status = schannel_InitializeSecurityContextW(
251 phCredential, phContext, pszTargetNameW, fContextReq, Reserved1, TargetDataRep, pInput,
252 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
253 free(pszTargetNameW);
257static SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(
259 WINPR_ATTR_UNUSED ULONG fContextReq, WINPR_ATTR_UNUSED ULONG TargetDataRep,
263 SECURITY_STATUS status = 0;
267 if (phContext && !phContext->dwLower && !phContext->dwUpper)
268 return SEC_E_INVALID_HANDLE;
274 context = schannel_ContextNew();
277 return SEC_E_INSUFFICIENT_MEMORY;
279 context->server = TRUE;
280 sspi_SecureHandleSetLowerPointer(phNewContext, context);
281 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)SCHANNEL_PACKAGE_NAME);
282 schannel_openssl_server_init(context->openssl);
285 status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput);
289static SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(
PCtxtHandle phContext)
292 sspi_SecureHandleInvalidate(phContext);
295 return SEC_E_INVALID_HANDLE;
297 schannel_ContextFree(context);
301static SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(
PCtxtHandle phContext,
302 ULONG ulAttribute,
void* pBuffer)
305 return SEC_E_INVALID_HANDLE;
308 return SEC_E_INSUFFICIENT_MEMORY;
310 if (ulAttribute == SECPKG_ATTR_SIZES)
313 Sizes->cbMaxToken = 0x6000;
314 Sizes->cbMaxSignature = 16;
315 Sizes->cbBlockSize = 0;
316 Sizes->cbSecurityTrailer = 16;
319 else if (ulAttribute == SECPKG_ATTR_STREAM_SIZES)
322 StreamSizes->cbHeader = 5;
323 StreamSizes->cbTrailer = 36;
324 StreamSizes->cbMaximumMessage = 0x4000;
325 StreamSizes->cBuffers = 4;
326 StreamSizes->cbBlockSize = 16;
330 WLog_ERR(TAG,
"TODO: Implement ulAttribute=%08" PRIx32, ulAttribute);
331 return SEC_E_UNSUPPORTED_FUNCTION;
334static SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(WINPR_ATTR_UNUSED
PCtxtHandle phContext,
335 WINPR_ATTR_UNUSED ULONG fQOP,
337 WINPR_ATTR_UNUSED ULONG MessageSeqNo)
342static SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(WINPR_ATTR_UNUSED
PCtxtHandle phContext,
344 WINPR_ATTR_UNUSED ULONG MessageSeqNo,
345 WINPR_ATTR_UNUSED ULONG* pfQOP)
350static SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(WINPR_ATTR_UNUSED
PCtxtHandle phContext,
351 WINPR_ATTR_UNUSED ULONG fQOP,
353 WINPR_ATTR_UNUSED ULONG MessageSeqNo)
355 SECURITY_STATUS status = 0;
360 return SEC_E_INVALID_HANDLE;
362 status = schannel_openssl_encrypt_message(context->openssl, pMessage);
366static SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(
PCtxtHandle phContext,
368 WINPR_ATTR_UNUSED ULONG MessageSeqNo,
369 WINPR_ATTR_UNUSED ULONG* pfQOP)
371 SECURITY_STATUS status = 0;
376 return SEC_E_INVALID_HANDLE;
378 status = schannel_openssl_decrypt_message(context->openssl, pMessage);
385 schannel_QueryCredentialsAttributesA,
386 schannel_AcquireCredentialsHandleA,
387 schannel_FreeCredentialsHandle,
389 schannel_InitializeSecurityContextA,
390 schannel_AcceptSecurityContext,
392 schannel_DeleteSecurityContext,
394 schannel_QueryContextAttributes,
397 schannel_MakeSignature,
398 schannel_VerifySignature,
408 schannel_EncryptMessage,
409 schannel_DecryptMessage,
417 schannel_QueryCredentialsAttributesW,
418 schannel_AcquireCredentialsHandleW,
419 schannel_FreeCredentialsHandle,
421 schannel_InitializeSecurityContextW,
422 schannel_AcceptSecurityContext,
424 schannel_DeleteSecurityContext,
426 schannel_QueryContextAttributes,
429 schannel_MakeSignature,
430 schannel_VerifySignature,
440 schannel_EncryptMessage,
441 schannel_DecryptMessage,
450 SCHANNEL_CB_MAX_TOKEN,
452 "Schannel Security Package"
455static WCHAR SCHANNEL_SecPkgInfoW_NameBuffer[32] = WINPR_C_ARRAY_INIT;
456static WCHAR SCHANNEL_SecPkgInfoW_CommentBuffer[32] = WINPR_C_ARRAY_INIT;
462 SCHANNEL_CB_MAX_TOKEN,
463 SCHANNEL_SecPkgInfoW_NameBuffer,
464 SCHANNEL_SecPkgInfoW_CommentBuffer
467BOOL SCHANNEL_init(
void)
469 InitializeConstWCharFromUtf8(SCHANNEL_SecPkgInfoA.Name, SCHANNEL_SecPkgInfoW_NameBuffer,
470 ARRAYSIZE(SCHANNEL_SecPkgInfoW_NameBuffer));
471 InitializeConstWCharFromUtf8(SCHANNEL_SecPkgInfoA.Comment, SCHANNEL_SecPkgInfoW_CommentBuffer,
472 ARRAYSIZE(SCHANNEL_SecPkgInfoW_CommentBuffer));