20 #include <winpr/config.h>
22 #include "schannel_openssl.h"
26 #include <winpr/crt.h>
27 #include <winpr/sspi.h>
28 #include <winpr/ssl.h>
29 #include <winpr/print.h>
30 #include <winpr/crypto.h>
32 #include <openssl/ssl.h>
33 #include <openssl/err.h>
34 #include <openssl/bio.h>
36 #define LIMIT_INTMAX(a) ((a) > INT32_MAX) ? INT32_MAX : (int)(a)
38 struct S_SCHANNEL_OPENSSL
49 #include "../../log.h"
50 #define TAG WINPR_TAG("sspi.schannel")
52 static char* openssl_get_ssl_error_string(
int ssl_error)
56 case SSL_ERROR_ZERO_RETURN:
57 return "SSL_ERROR_ZERO_RETURN";
59 case SSL_ERROR_WANT_READ:
60 return "SSL_ERROR_WANT_READ";
62 case SSL_ERROR_WANT_WRITE:
63 return "SSL_ERROR_WANT_WRITE";
65 case SSL_ERROR_SYSCALL:
66 return "SSL_ERROR_SYSCALL";
69 return "SSL_ERROR_SSL";
74 return "SSL_ERROR_UNKNOWN";
77 static void schannel_context_cleanup(SCHANNEL_OPENSSL* context)
79 WINPR_ASSERT(context);
81 free(context->ReadBuffer);
82 context->ReadBuffer = NULL;
84 if (context->bioWrite)
85 BIO_free_all(context->bioWrite);
86 context->bioWrite = NULL;
89 BIO_free_all(context->bioRead);
90 context->bioRead = NULL;
93 SSL_free(context->ssl);
97 SSL_CTX_free(context->ctx);
101 static const SSL_METHOD* get_method(BOOL server)
105 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
106 return SSLv23_server_method();
108 return TLS_server_method();
113 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
114 return SSLv23_client_method();
116 return TLS_client_method();
120 int schannel_openssl_client_init(SCHANNEL_OPENSSL* context)
124 context->ctx = SSL_CTX_new(get_method(FALSE));
128 WLog_ERR(TAG,
"SSL_CTX_new failed");
141 #ifdef SSL_OP_NO_COMPRESSION
142 options |= SSL_OP_NO_COMPRESSION;
150 options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
157 options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
158 SSL_CTX_set_options(context->ctx, options);
159 context->ssl = SSL_new(context->ctx);
163 WLog_ERR(TAG,
"SSL_new failed");
167 context->bioRead = BIO_new(BIO_s_mem());
169 if (!context->bioRead)
171 WLog_ERR(TAG,
"BIO_new failed");
175 status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN);
179 WLog_ERR(TAG,
"BIO_set_write_buf_size on bioRead failed");
183 context->bioWrite = BIO_new(BIO_s_mem());
185 if (!context->bioWrite)
187 WLog_ERR(TAG,
"BIO_new failed");
191 status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN);
195 WLog_ERR(TAG,
"BIO_set_write_buf_size on bioWrite failed");
199 status = BIO_make_bio_pair(context->bioRead, context->bioWrite);
203 WLog_ERR(TAG,
"BIO_make_bio_pair failed");
207 SSL_set_bio(context->ssl, context->bioRead, context->bioWrite);
208 context->ReadBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
210 if (!context->ReadBuffer)
212 WLog_ERR(TAG,
"Failed to allocate ReadBuffer");
216 context->WriteBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
218 if (!context->WriteBuffer)
220 WLog_ERR(TAG,
"Failed to allocate ReadBuffer");
226 schannel_context_cleanup(context);
230 int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
233 unsigned long options = 0;
235 context->ctx = SSL_CTX_new(get_method(TRUE));
239 WLog_ERR(TAG,
"SSL_CTX_new failed");
249 options |= SSL_OP_NO_SSLv2;
259 #ifdef SSL_OP_NO_COMPRESSION
260 options |= SSL_OP_NO_COMPRESSION;
268 options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
275 options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
276 SSL_CTX_set_options(context->ctx, options);
278 #if defined(WITH_DEBUG_SCHANNEL)
279 if (SSL_CTX_use_RSAPrivateKey_file(context->ctx,
"/tmp/localhost.key", SSL_FILETYPE_PEM) <= 0)
281 WLog_ERR(TAG,
"SSL_CTX_use_RSAPrivateKey_file failed");
286 context->ssl = SSL_new(context->ctx);
290 WLog_ERR(TAG,
"SSL_new failed");
294 if (SSL_use_certificate_file(context->ssl,
"/tmp/localhost.crt", SSL_FILETYPE_PEM) <= 0)
296 WLog_ERR(TAG,
"SSL_use_certificate_file failed");
300 context->bioRead = BIO_new(BIO_s_mem());
302 if (!context->bioRead)
304 WLog_ERR(TAG,
"BIO_new failed");
308 status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN);
312 WLog_ERR(TAG,
"BIO_set_write_buf_size failed for bioRead");
316 context->bioWrite = BIO_new(BIO_s_mem());
318 if (!context->bioWrite)
320 WLog_ERR(TAG,
"BIO_new failed");
324 status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN);
328 WLog_ERR(TAG,
"BIO_set_write_buf_size failed for bioWrite");
332 status = BIO_make_bio_pair(context->bioRead, context->bioWrite);
336 WLog_ERR(TAG,
"BIO_make_bio_pair failed");
340 SSL_set_bio(context->ssl, context->bioRead, context->bioWrite);
341 context->ReadBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
343 if (!context->ReadBuffer)
345 WLog_ERR(TAG,
"Failed to allocate memory for ReadBuffer");
349 context->WriteBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
351 if (!context->WriteBuffer)
353 WLog_ERR(TAG,
"Failed to allocate memory for WriteBuffer");
359 schannel_context_cleanup(context);
363 SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context,
371 if (!context->connected)
375 if (pInput->cBuffers < 1)
376 return SEC_E_INVALID_TOKEN;
378 pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
381 return SEC_E_INVALID_TOKEN;
385 BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
387 return SEC_E_INVALID_TOKEN;
390 status = SSL_connect(context->ssl);
394 ssl_error = SSL_get_error(context->ssl, status);
395 WLog_ERR(TAG,
"SSL_connect error: %s", openssl_get_ssl_error_string(ssl_error));
399 context->connected = TRUE;
402 status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
404 if (pOutput->cBuffers < 1)
405 return SEC_E_INVALID_TOKEN;
407 pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
410 return SEC_E_INVALID_TOKEN;
414 if (pBuffer->cbBuffer < (
unsigned long)status)
415 return SEC_E_INSUFFICIENT_MEMORY;
417 CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
418 pBuffer->cbBuffer = status;
419 return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
423 pBuffer->cbBuffer = 0;
424 return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
431 SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context,
439 if (!context->connected)
441 if (pInput->cBuffers < 1)
442 return SEC_E_INVALID_TOKEN;
444 pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
447 return SEC_E_INVALID_TOKEN;
450 status = BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
452 status = SSL_accept(context->ssl);
456 ssl_error = SSL_get_error(context->ssl, status);
457 WLog_ERR(TAG,
"SSL_accept error: %s", openssl_get_ssl_error_string(ssl_error));
458 return SEC_E_INVALID_TOKEN;
462 context->connected = TRUE;
465 status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
468 ssl_error = SSL_get_error(context->ssl, status);
469 WLog_ERR(TAG,
"BIO_read: %s", openssl_get_ssl_error_string(ssl_error));
470 return SEC_E_INVALID_TOKEN;
473 if (pOutput->cBuffers < 1)
474 return SEC_E_INVALID_TOKEN;
476 pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
479 return SEC_E_INVALID_TOKEN;
483 if (pBuffer->cbBuffer < (
unsigned long)status)
484 return SEC_E_INSUFFICIENT_MEMORY;
486 CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
487 pBuffer->cbBuffer = status;
488 return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
492 pBuffer->cbBuffer = 0;
493 return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
500 SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context,
PSecBufferDesc pMessage)
507 pStreamHeaderBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_HEADER);
508 pStreamBodyBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
509 pStreamTrailerBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_TRAILER);
511 if ((!pStreamHeaderBuffer) || (!pStreamBodyBuffer) || (!pStreamTrailerBuffer))
512 return SEC_E_INVALID_TOKEN;
514 status = SSL_write(context->ssl, pStreamBodyBuffer->pvBuffer,
515 LIMIT_INTMAX(pStreamBodyBuffer->cbBuffer));
519 ssl_error = SSL_get_error(context->ssl, status);
520 WLog_ERR(TAG,
"SSL_write: %s", openssl_get_ssl_error_string(ssl_error));
524 status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
528 size_t ustatus = (size_t)status;
533 (pStreamHeaderBuffer->cbBuffer > ustatus) ? ustatus : pStreamHeaderBuffer->cbBuffer;
534 CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length);
537 length = (pStreamBodyBuffer->cbBuffer > ustatus) ? ustatus : pStreamBodyBuffer->cbBuffer;
538 CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length);
542 (pStreamTrailerBuffer->cbBuffer > ustatus) ? ustatus : pStreamTrailerBuffer->cbBuffer;
543 CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length);
549 SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context,
PSecBufferDesc pMessage)
556 pBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
559 return SEC_E_INVALID_TOKEN;
562 status = BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
564 status = SSL_read(context->ssl, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
568 ssl_error = SSL_get_error(context->ssl, status);
569 WLog_ERR(TAG,
"SSL_read: %s", openssl_get_ssl_error_string(ssl_error));
573 buffer = pBuffer->pvBuffer;
574 pMessage->pBuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
575 pMessage->pBuffers[0].cbBuffer = 5;
576 pMessage->pBuffers[1].BufferType = SECBUFFER_DATA;
577 pMessage->pBuffers[1].pvBuffer = buffer;
578 pMessage->pBuffers[1].cbBuffer = length;
579 pMessage->pBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
580 pMessage->pBuffers[2].cbBuffer = 36;
581 pMessage->pBuffers[3].BufferType = SECBUFFER_EMPTY;
582 pMessage->pBuffers[3].cbBuffer = 0;
586 SCHANNEL_OPENSSL* schannel_openssl_new(
void)
588 SCHANNEL_OPENSSL* context = NULL;
589 context = (SCHANNEL_OPENSSL*)calloc(1,
sizeof(SCHANNEL_OPENSSL));
593 winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
594 context->connected = FALSE;
600 void schannel_openssl_free(SCHANNEL_OPENSSL* context)
604 free(context->ReadBuffer);
605 free(context->WriteBuffer);
612 int schannel_openssl_client_init(SCHANNEL_OPENSSL* context)
617 int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
622 SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context,
629 SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context,
636 SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context,
PSecBufferDesc pMessage)
641 SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context,
PSecBufferDesc pMessage)
646 SCHANNEL_OPENSSL* schannel_openssl_new(
void)
651 void schannel_openssl_free(SCHANNEL_OPENSSL* context)