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 = NULL;
170 SEC_WCHAR* pszPackageW = NULL;
172 pszPrincipalW = ConvertUtf8ToWCharAlloc(pszPrincipal, NULL);
174 pszPackageW = ConvertUtf8ToWCharAlloc(pszPackage, NULL);
176 status = schannel_AcquireCredentialsHandleW(pszPrincipalW, pszPackageW, fCredentialUse,
177 pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument,
178 phCredential, ptsExpiry);
184static SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(
PCredHandle phCredential)
189 return SEC_E_INVALID_HANDLE;
194 return SEC_E_INVALID_HANDLE;
196 schannel_CredentialsFree(credentials);
200static SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(
202 WINPR_ATTR_UNUSED ULONG fContextReq, WINPR_ATTR_UNUSED ULONG Reserved1,
203 WINPR_ATTR_UNUSED ULONG TargetDataRep,
PSecBufferDesc pInput, WINPR_ATTR_UNUSED ULONG Reserved2,
207 SECURITY_STATUS status = 0;
212 if (phContext && !phContext->dwLower && !phContext->dwUpper)
213 return SEC_E_INVALID_HANDLE;
215 context = sspi_SecureHandleGetLowerPointer(phContext);
219 context = schannel_ContextNew();
222 return SEC_E_INSUFFICIENT_MEMORY;
225 context->server = FALSE;
226 CopyMemory(&context->cred, &credentials->cred,
sizeof(
SCHANNEL_CRED));
227 sspi_SecureHandleSetLowerPointer(phNewContext, context);
228 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)SCHANNEL_PACKAGE_NAME);
229 schannel_openssl_client_init(context->openssl);
232 status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput);
236static SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(
238 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
241 SECURITY_STATUS status = 0;
242 SEC_WCHAR* pszTargetNameW = NULL;
244 if (pszTargetName != NULL)
246 pszTargetNameW = ConvertUtf8ToWCharAlloc(pszTargetName, NULL);
248 return SEC_E_INSUFFICIENT_MEMORY;
251 status = schannel_InitializeSecurityContextW(
252 phCredential, phContext, pszTargetNameW, fContextReq, Reserved1, TargetDataRep, pInput,
253 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
254 free(pszTargetNameW);
258static SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(
260 WINPR_ATTR_UNUSED ULONG fContextReq, WINPR_ATTR_UNUSED ULONG TargetDataRep,
264 SECURITY_STATUS status = 0;
268 if (phContext && !phContext->dwLower && !phContext->dwUpper)
269 return SEC_E_INVALID_HANDLE;
275 context = schannel_ContextNew();
278 return SEC_E_INSUFFICIENT_MEMORY;
280 context->server = TRUE;
281 sspi_SecureHandleSetLowerPointer(phNewContext, context);
282 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)SCHANNEL_PACKAGE_NAME);
283 schannel_openssl_server_init(context->openssl);
286 status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput);
290static SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(
PCtxtHandle phContext)
296 return SEC_E_INVALID_HANDLE;
298 schannel_ContextFree(context);
302static SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(
PCtxtHandle phContext,
303 ULONG ulAttribute,
void* pBuffer)
306 return SEC_E_INVALID_HANDLE;
309 return SEC_E_INSUFFICIENT_MEMORY;
311 if (ulAttribute == SECPKG_ATTR_SIZES)
314 Sizes->cbMaxToken = 0x6000;
315 Sizes->cbMaxSignature = 16;
316 Sizes->cbBlockSize = 0;
317 Sizes->cbSecurityTrailer = 16;
320 else if (ulAttribute == SECPKG_ATTR_STREAM_SIZES)
323 StreamSizes->cbHeader = 5;
324 StreamSizes->cbTrailer = 36;
325 StreamSizes->cbMaximumMessage = 0x4000;
326 StreamSizes->cBuffers = 4;
327 StreamSizes->cbBlockSize = 16;
331 WLog_ERR(TAG,
"TODO: Implement ulAttribute=%08" PRIx32, ulAttribute);
332 return SEC_E_UNSUPPORTED_FUNCTION;
335static SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(WINPR_ATTR_UNUSED
PCtxtHandle phContext,
336 WINPR_ATTR_UNUSED ULONG fQOP,
338 WINPR_ATTR_UNUSED ULONG MessageSeqNo)
343static SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(WINPR_ATTR_UNUSED
PCtxtHandle phContext,
345 WINPR_ATTR_UNUSED ULONG MessageSeqNo,
346 WINPR_ATTR_UNUSED ULONG* pfQOP)
351static SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(WINPR_ATTR_UNUSED
PCtxtHandle phContext,
352 WINPR_ATTR_UNUSED ULONG fQOP,
354 WINPR_ATTR_UNUSED ULONG MessageSeqNo)
356 SECURITY_STATUS status = 0;
361 return SEC_E_INVALID_HANDLE;
363 status = schannel_openssl_encrypt_message(context->openssl, pMessage);
367static SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(
PCtxtHandle phContext,
369 WINPR_ATTR_UNUSED ULONG MessageSeqNo,
370 WINPR_ATTR_UNUSED ULONG* pfQOP)
372 SECURITY_STATUS status = 0;
377 return SEC_E_INVALID_HANDLE;
379 status = schannel_openssl_decrypt_message(context->openssl, pMessage);
386 schannel_QueryCredentialsAttributesA,
387 schannel_AcquireCredentialsHandleA,
388 schannel_FreeCredentialsHandle,
390 schannel_InitializeSecurityContextA,
391 schannel_AcceptSecurityContext,
393 schannel_DeleteSecurityContext,
395 schannel_QueryContextAttributes,
398 schannel_MakeSignature,
399 schannel_VerifySignature,
409 schannel_EncryptMessage,
410 schannel_DecryptMessage,
418 schannel_QueryCredentialsAttributesW,
419 schannel_AcquireCredentialsHandleW,
420 schannel_FreeCredentialsHandle,
422 schannel_InitializeSecurityContextW,
423 schannel_AcceptSecurityContext,
425 schannel_DeleteSecurityContext,
427 schannel_QueryContextAttributes,
430 schannel_MakeSignature,
431 schannel_VerifySignature,
441 schannel_EncryptMessage,
442 schannel_DecryptMessage,
451 SCHANNEL_CB_MAX_TOKEN,
453 "Schannel Security Package"
456static WCHAR SCHANNEL_SecPkgInfoW_NameBuffer[32] = { 0 };
457static WCHAR SCHANNEL_SecPkgInfoW_CommentBuffer[32] = { 0 };
463 SCHANNEL_CB_MAX_TOKEN,
464 SCHANNEL_SecPkgInfoW_NameBuffer,
465 SCHANNEL_SecPkgInfoW_CommentBuffer
468BOOL SCHANNEL_init(
void)
470 InitializeConstWCharFromUtf8(SCHANNEL_SecPkgInfoA.Name, SCHANNEL_SecPkgInfoW_NameBuffer,
471 ARRAYSIZE(SCHANNEL_SecPkgInfoW_NameBuffer));
472 InitializeConstWCharFromUtf8(SCHANNEL_SecPkgInfoA.Comment, SCHANNEL_SecPkgInfoW_CommentBuffer,
473 ARRAYSIZE(SCHANNEL_SecPkgInfoW_CommentBuffer));