20 #include <winpr/config.h>
22 #include <winpr/crt.h>
23 #include <winpr/sspi.h>
28 #include "../../log.h"
30 static 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);
74 static ALG_ID schannel_SupportedAlgs[] = { CALG_AES_128,
86 (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_RESERVED7 |
91 static SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesW(
PCredHandle phCredential,
95 if (ulAttribute == SECPKG_ATTR_SUPPORTED_ALGS)
98 SupportedAlgs->cSupportedAlgs =
sizeof(schannel_SupportedAlgs) /
sizeof(ALG_ID);
99 SupportedAlgs->palgSupportedAlgs = (ALG_ID*)schannel_SupportedAlgs;
102 else if (ulAttribute == SECPKG_ATTR_CIPHER_STRENGTHS)
105 CipherStrengths->dwMinimumCipherStrength = 40;
106 CipherStrengths->dwMaximumCipherStrength = 256;
109 else if (ulAttribute == SECPKG_ATTR_SUPPORTED_PROTOCOLS)
113 SupportedProtocols->grbitProtocol = (SP_PROT_CLIENTS | SP_PROT_SERVERS);
117 WLog_ERR(TAG,
"TODO: Implement ulAttribute=%08" PRIx32, ulAttribute);
118 return SEC_E_UNSUPPORTED_FUNCTION;
121 static SECURITY_STATUS SEC_ENTRY schannel_QueryCredentialsAttributesA(
PCredHandle phCredential,
125 return schannel_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
128 static SECURITY_STATUS SEC_ENTRY schannel_AcquireCredentialsHandleW(
129 SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse,
void* pvLogonID,
130 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument,
PCredHandle phCredential,
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);
163 static 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);
184 static SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(
PCredHandle phCredential)
189 return SEC_E_INVALID_HANDLE;
194 return SEC_E_INVALID_HANDLE;
196 schannel_CredentialsFree(credentials);
200 static SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextW(
202 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
205 SECURITY_STATUS status = 0;
210 if (phContext && !phContext->dwLower && !phContext->dwUpper)
211 return SEC_E_INVALID_HANDLE;
213 context = sspi_SecureHandleGetLowerPointer(phContext);
217 context = schannel_ContextNew();
220 return SEC_E_INSUFFICIENT_MEMORY;
223 context->server = FALSE;
224 CopyMemory(&context->cred, &credentials->cred,
sizeof(
SCHANNEL_CRED));
225 sspi_SecureHandleSetLowerPointer(phNewContext, context);
226 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)SCHANNEL_PACKAGE_NAME);
227 schannel_openssl_client_init(context->openssl);
230 status = schannel_openssl_client_process_tokens(context->openssl, pInput, pOutput);
234 static SECURITY_STATUS SEC_ENTRY schannel_InitializeSecurityContextA(
236 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
239 SECURITY_STATUS status = 0;
240 SEC_WCHAR* pszTargetNameW = NULL;
242 if (pszTargetName != NULL)
244 pszTargetNameW = ConvertUtf8ToWCharAlloc(pszTargetName, NULL);
246 return SEC_E_INSUFFICIENT_MEMORY;
249 status = schannel_InitializeSecurityContextW(
250 phCredential, phContext, pszTargetNameW, fContextReq, Reserved1, TargetDataRep, pInput,
251 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
252 free(pszTargetNameW);
256 static SECURITY_STATUS SEC_ENTRY schannel_AcceptSecurityContext(
261 SECURITY_STATUS status = 0;
265 if (phContext && !phContext->dwLower && !phContext->dwUpper)
266 return SEC_E_INVALID_HANDLE;
272 context = schannel_ContextNew();
275 return SEC_E_INSUFFICIENT_MEMORY;
277 context->server = TRUE;
278 sspi_SecureHandleSetLowerPointer(phNewContext, context);
279 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)SCHANNEL_PACKAGE_NAME);
280 schannel_openssl_server_init(context->openssl);
283 status = schannel_openssl_server_process_tokens(context->openssl, pInput, pOutput);
287 static SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(
PCtxtHandle phContext)
293 return SEC_E_INVALID_HANDLE;
295 schannel_ContextFree(context);
299 static SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(
PCtxtHandle phContext,
300 ULONG ulAttribute,
void* pBuffer)
303 return SEC_E_INVALID_HANDLE;
306 return SEC_E_INSUFFICIENT_MEMORY;
308 if (ulAttribute == SECPKG_ATTR_SIZES)
311 Sizes->cbMaxToken = 0x6000;
312 Sizes->cbMaxSignature = 16;
313 Sizes->cbBlockSize = 0;
314 Sizes->cbSecurityTrailer = 16;
317 else if (ulAttribute == SECPKG_ATTR_STREAM_SIZES)
320 StreamSizes->cbHeader = 5;
321 StreamSizes->cbTrailer = 36;
322 StreamSizes->cbMaximumMessage = 0x4000;
323 StreamSizes->cBuffers = 4;
324 StreamSizes->cbBlockSize = 16;
328 WLog_ERR(TAG,
"TODO: Implement ulAttribute=%08" PRIx32, ulAttribute);
329 return SEC_E_UNSUPPORTED_FUNCTION;
332 static SECURITY_STATUS SEC_ENTRY schannel_MakeSignature(
PCtxtHandle phContext, ULONG fQOP,
338 static SECURITY_STATUS SEC_ENTRY schannel_VerifySignature(
PCtxtHandle phContext,
340 ULONG MessageSeqNo, ULONG* pfQOP)
345 static SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(
PCtxtHandle phContext, ULONG fQOP,
349 SECURITY_STATUS status = 0;
354 return SEC_E_INVALID_HANDLE;
356 status = schannel_openssl_encrypt_message(context->openssl, pMessage);
360 static SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(
PCtxtHandle phContext,
362 ULONG MessageSeqNo, ULONG* pfQOP)
364 SECURITY_STATUS status = 0;
369 return SEC_E_INVALID_HANDLE;
371 status = schannel_openssl_decrypt_message(context->openssl, pMessage);
378 schannel_QueryCredentialsAttributesA,
379 schannel_AcquireCredentialsHandleA,
380 schannel_FreeCredentialsHandle,
382 schannel_InitializeSecurityContextA,
383 schannel_AcceptSecurityContext,
385 schannel_DeleteSecurityContext,
387 schannel_QueryContextAttributes,
390 schannel_MakeSignature,
391 schannel_VerifySignature,
401 schannel_EncryptMessage,
402 schannel_DecryptMessage,
410 schannel_QueryCredentialsAttributesW,
411 schannel_AcquireCredentialsHandleW,
412 schannel_FreeCredentialsHandle,
414 schannel_InitializeSecurityContextW,
415 schannel_AcceptSecurityContext,
417 schannel_DeleteSecurityContext,
419 schannel_QueryContextAttributes,
422 schannel_MakeSignature,
423 schannel_VerifySignature,
433 schannel_EncryptMessage,
434 schannel_DecryptMessage,
443 SCHANNEL_CB_MAX_TOKEN,
445 "Schannel Security Package"
448 static WCHAR SCHANNEL_SecPkgInfoW_NameBuffer[32] = { 0 };
449 static WCHAR SCHANNEL_SecPkgInfoW_CommentBuffer[32] = { 0 };
455 SCHANNEL_CB_MAX_TOKEN,
456 SCHANNEL_SecPkgInfoW_NameBuffer,
457 SCHANNEL_SecPkgInfoW_CommentBuffer
460 BOOL SCHANNEL_init(
void)
462 InitializeConstWCharFromUtf8(SCHANNEL_SecPkgInfoA.Name, SCHANNEL_SecPkgInfoW_NameBuffer,
463 ARRAYSIZE(SCHANNEL_SecPkgInfoW_NameBuffer));
464 InitializeConstWCharFromUtf8(SCHANNEL_SecPkgInfoA.Comment, SCHANNEL_SecPkgInfoW_CommentBuffer,
465 ARRAYSIZE(SCHANNEL_SecPkgInfoW_CommentBuffer));