FreeRDP
schannel_openssl.c
1 
20 #include <winpr/config.h>
21 
22 #include "schannel_openssl.h"
23 
24 #ifdef WITH_OPENSSL
25 
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>
31 
32 #include <openssl/ssl.h>
33 #include <openssl/err.h>
34 #include <openssl/bio.h>
35 
36 #define LIMIT_INTMAX(a) ((a) > INT32_MAX) ? INT32_MAX : (int)(a)
37 
38 struct S_SCHANNEL_OPENSSL
39 {
40  SSL* ssl;
41  SSL_CTX* ctx;
42  BOOL connected;
43  BIO* bioRead;
44  BIO* bioWrite;
45  BYTE* ReadBuffer;
46  BYTE* WriteBuffer;
47 };
48 
49 #include "../../log.h"
50 #define TAG WINPR_TAG("sspi.schannel")
51 
52 static char* openssl_get_ssl_error_string(int ssl_error)
53 {
54  switch (ssl_error)
55  {
56  case SSL_ERROR_ZERO_RETURN:
57  return "SSL_ERROR_ZERO_RETURN";
58 
59  case SSL_ERROR_WANT_READ:
60  return "SSL_ERROR_WANT_READ";
61 
62  case SSL_ERROR_WANT_WRITE:
63  return "SSL_ERROR_WANT_WRITE";
64 
65  case SSL_ERROR_SYSCALL:
66  return "SSL_ERROR_SYSCALL";
67 
68  case SSL_ERROR_SSL:
69  return "SSL_ERROR_SSL";
70  default:
71  break;
72  }
73 
74  return "SSL_ERROR_UNKNOWN";
75 }
76 
77 static void schannel_context_cleanup(SCHANNEL_OPENSSL* context)
78 {
79  WINPR_ASSERT(context);
80 
81  free(context->ReadBuffer);
82  context->ReadBuffer = NULL;
83 
84  if (context->bioWrite)
85  BIO_free_all(context->bioWrite);
86  context->bioWrite = NULL;
87 
88  if (context->bioRead)
89  BIO_free_all(context->bioRead);
90  context->bioRead = NULL;
91 
92  if (context->ssl)
93  SSL_free(context->ssl);
94  context->ssl = NULL;
95 
96  if (context->ctx)
97  SSL_CTX_free(context->ctx);
98  context->ctx = NULL;
99 }
100 
101 static const SSL_METHOD* get_method(BOOL server)
102 {
103  if (server)
104  {
105 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
106  return SSLv23_server_method();
107 #else
108  return TLS_server_method();
109 #endif
110  }
111  else
112  {
113 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
114  return SSLv23_client_method();
115 #else
116  return TLS_client_method();
117 #endif
118  }
119 }
120 int schannel_openssl_client_init(SCHANNEL_OPENSSL* context)
121 {
122  int status = 0;
123  long options = 0;
124  context->ctx = SSL_CTX_new(get_method(FALSE));
125 
126  if (!context->ctx)
127  {
128  WLog_ERR(TAG, "SSL_CTX_new failed");
129  return -1;
130  }
131 
141 #ifdef SSL_OP_NO_COMPRESSION
142  options |= SSL_OP_NO_COMPRESSION;
143 #endif
150  options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
157  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
158  SSL_CTX_set_options(context->ctx, WINPR_ASSERTING_INT_CAST(uint64_t, options));
159  context->ssl = SSL_new(context->ctx);
160 
161  if (!context->ssl)
162  {
163  WLog_ERR(TAG, "SSL_new failed");
164  goto fail;
165  }
166 
167  context->bioRead = BIO_new(BIO_s_mem());
168 
169  if (!context->bioRead)
170  {
171  WLog_ERR(TAG, "BIO_new failed");
172  goto fail;
173  }
174 
175  status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN);
176 
177  if (status != 1)
178  {
179  WLog_ERR(TAG, "BIO_set_write_buf_size on bioRead failed");
180  goto fail;
181  }
182 
183  context->bioWrite = BIO_new(BIO_s_mem());
184 
185  if (!context->bioWrite)
186  {
187  WLog_ERR(TAG, "BIO_new failed");
188  goto fail;
189  }
190 
191  status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN);
192 
193  if (status != 1)
194  {
195  WLog_ERR(TAG, "BIO_set_write_buf_size on bioWrite failed");
196  goto fail;
197  }
198 
199  status = BIO_make_bio_pair(context->bioRead, context->bioWrite);
200 
201  if (status != 1)
202  {
203  WLog_ERR(TAG, "BIO_make_bio_pair failed");
204  goto fail;
205  }
206 
207  SSL_set_bio(context->ssl, context->bioRead, context->bioWrite);
208  context->ReadBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
209 
210  if (!context->ReadBuffer)
211  {
212  WLog_ERR(TAG, "Failed to allocate ReadBuffer");
213  goto fail;
214  }
215 
216  context->WriteBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
217 
218  if (!context->WriteBuffer)
219  {
220  WLog_ERR(TAG, "Failed to allocate ReadBuffer");
221  goto fail;
222  }
223 
224  return 0;
225 fail:
226  schannel_context_cleanup(context);
227  return -1;
228 }
229 
230 int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
231 {
232  int status = 0;
233  unsigned long options = 0;
234 
235  context->ctx = SSL_CTX_new(get_method(TRUE));
236 
237  if (!context->ctx)
238  {
239  WLog_ERR(TAG, "SSL_CTX_new failed");
240  return -1;
241  }
242 
243  /*
244  * SSL_OP_NO_SSLv2:
245  *
246  * We only want SSLv3 and TLSv1, so disable SSLv2.
247  * SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
248  */
249  options |= SSL_OP_NO_SSLv2;
259 #ifdef SSL_OP_NO_COMPRESSION
260  options |= SSL_OP_NO_COMPRESSION;
261 #endif
268  options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
275  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
276  SSL_CTX_set_options(context->ctx, options);
277 
278 #if defined(WITH_DEBUG_SCHANNEL)
279  if (SSL_CTX_use_RSAPrivateKey_file(context->ctx, "/tmp/localhost.key", SSL_FILETYPE_PEM) <= 0)
280  {
281  WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed");
282  goto fail;
283  }
284 #endif
285 
286  context->ssl = SSL_new(context->ctx);
287 
288  if (!context->ssl)
289  {
290  WLog_ERR(TAG, "SSL_new failed");
291  goto fail;
292  }
293 
294  if (SSL_use_certificate_file(context->ssl, "/tmp/localhost.crt", SSL_FILETYPE_PEM) <= 0)
295  {
296  WLog_ERR(TAG, "SSL_use_certificate_file failed");
297  goto fail;
298  }
299 
300  context->bioRead = BIO_new(BIO_s_mem());
301 
302  if (!context->bioRead)
303  {
304  WLog_ERR(TAG, "BIO_new failed");
305  goto fail;
306  }
307 
308  status = BIO_set_write_buf_size(context->bioRead, SCHANNEL_CB_MAX_TOKEN);
309 
310  if (status != 1)
311  {
312  WLog_ERR(TAG, "BIO_set_write_buf_size failed for bioRead");
313  goto fail;
314  }
315 
316  context->bioWrite = BIO_new(BIO_s_mem());
317 
318  if (!context->bioWrite)
319  {
320  WLog_ERR(TAG, "BIO_new failed");
321  goto fail;
322  }
323 
324  status = BIO_set_write_buf_size(context->bioWrite, SCHANNEL_CB_MAX_TOKEN);
325 
326  if (status != 1)
327  {
328  WLog_ERR(TAG, "BIO_set_write_buf_size failed for bioWrite");
329  goto fail;
330  }
331 
332  status = BIO_make_bio_pair(context->bioRead, context->bioWrite);
333 
334  if (status != 1)
335  {
336  WLog_ERR(TAG, "BIO_make_bio_pair failed");
337  goto fail;
338  }
339 
340  SSL_set_bio(context->ssl, context->bioRead, context->bioWrite);
341  context->ReadBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
342 
343  if (!context->ReadBuffer)
344  {
345  WLog_ERR(TAG, "Failed to allocate memory for ReadBuffer");
346  goto fail;
347  }
348 
349  context->WriteBuffer = (BYTE*)malloc(SCHANNEL_CB_MAX_TOKEN);
350 
351  if (!context->WriteBuffer)
352  {
353  WLog_ERR(TAG, "Failed to allocate memory for WriteBuffer");
354  goto fail;
355  }
356 
357  return 0;
358 fail:
359  schannel_context_cleanup(context);
360  return -1;
361 }
362 
363 SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context,
364  PSecBufferDesc pInput,
365  PSecBufferDesc pOutput)
366 {
367  int status = 0;
368  int ssl_error = 0;
369  PSecBuffer pBuffer = NULL;
370 
371  if (!context->connected)
372  {
373  if (pInput)
374  {
375  if (pInput->cBuffers < 1)
376  return SEC_E_INVALID_TOKEN;
377 
378  pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
379 
380  if (!pBuffer)
381  return SEC_E_INVALID_TOKEN;
382 
383  ERR_clear_error();
384  status =
385  BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
386  if (status < 0)
387  return SEC_E_INVALID_TOKEN;
388  }
389 
390  status = SSL_connect(context->ssl);
391 
392  if (status < 0)
393  {
394  ssl_error = SSL_get_error(context->ssl, status);
395  WLog_ERR(TAG, "SSL_connect error: %s", openssl_get_ssl_error_string(ssl_error));
396  }
397 
398  if (status == 1)
399  context->connected = TRUE;
400 
401  ERR_clear_error();
402  status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
403 
404  if (pOutput->cBuffers < 1)
405  return SEC_E_INVALID_TOKEN;
406 
407  pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
408 
409  if (!pBuffer)
410  return SEC_E_INVALID_TOKEN;
411 
412  if (status > 0)
413  {
414  if (pBuffer->cbBuffer < WINPR_ASSERTING_INT_CAST(uint32_t, status))
415  return SEC_E_INSUFFICIENT_MEMORY;
416 
417  CopyMemory(pBuffer->pvBuffer, context->ReadBuffer,
418  WINPR_ASSERTING_INT_CAST(uint32_t, status));
419  pBuffer->cbBuffer = WINPR_ASSERTING_INT_CAST(uint32_t, status);
420  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
421  }
422  else
423  {
424  pBuffer->cbBuffer = 0;
425  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
426  }
427  }
428 
429  return SEC_E_OK;
430 }
431 
432 SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context,
433  PSecBufferDesc pInput,
434  PSecBufferDesc pOutput)
435 {
436  int status = 0;
437  int ssl_error = 0;
438  PSecBuffer pBuffer = NULL;
439 
440  if (!context->connected)
441  {
442  if (pInput->cBuffers < 1)
443  return SEC_E_INVALID_TOKEN;
444 
445  pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
446 
447  if (!pBuffer)
448  return SEC_E_INVALID_TOKEN;
449 
450  ERR_clear_error();
451  status = BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
452  if (status >= 0)
453  status = SSL_accept(context->ssl);
454 
455  if (status < 0)
456  {
457  ssl_error = SSL_get_error(context->ssl, status);
458  WLog_ERR(TAG, "SSL_accept error: %s", openssl_get_ssl_error_string(ssl_error));
459  return SEC_E_INVALID_TOKEN;
460  }
461 
462  if (status == 1)
463  context->connected = TRUE;
464 
465  ERR_clear_error();
466  status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
467  if (status < 0)
468  {
469  ssl_error = SSL_get_error(context->ssl, status);
470  WLog_ERR(TAG, "BIO_read: %s", openssl_get_ssl_error_string(ssl_error));
471  return SEC_E_INVALID_TOKEN;
472  }
473 
474  if (pOutput->cBuffers < 1)
475  return SEC_E_INVALID_TOKEN;
476 
477  pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
478 
479  if (!pBuffer)
480  return SEC_E_INVALID_TOKEN;
481 
482  if (status > 0)
483  {
484  if (pBuffer->cbBuffer < WINPR_ASSERTING_INT_CAST(uint32_t, status))
485  return SEC_E_INSUFFICIENT_MEMORY;
486 
487  CopyMemory(pBuffer->pvBuffer, context->ReadBuffer,
488  WINPR_ASSERTING_INT_CAST(uint32_t, status));
489  pBuffer->cbBuffer = WINPR_ASSERTING_INT_CAST(uint32_t, status);
490  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
491  }
492  else
493  {
494  pBuffer->cbBuffer = 0;
495  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
496  }
497  }
498 
499  return SEC_E_OK;
500 }
501 
502 SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
503 {
504  int status = 0;
505  int ssl_error = 0;
506  PSecBuffer pStreamBodyBuffer = NULL;
507  PSecBuffer pStreamHeaderBuffer = NULL;
508  PSecBuffer pStreamTrailerBuffer = NULL;
509  pStreamHeaderBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_HEADER);
510  pStreamBodyBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
511  pStreamTrailerBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_TRAILER);
512 
513  if ((!pStreamHeaderBuffer) || (!pStreamBodyBuffer) || (!pStreamTrailerBuffer))
514  return SEC_E_INVALID_TOKEN;
515 
516  status = SSL_write(context->ssl, pStreamBodyBuffer->pvBuffer,
517  LIMIT_INTMAX(pStreamBodyBuffer->cbBuffer));
518 
519  if (status < 0)
520  {
521  ssl_error = SSL_get_error(context->ssl, status);
522  WLog_ERR(TAG, "SSL_write: %s", openssl_get_ssl_error_string(ssl_error));
523  }
524 
525  ERR_clear_error();
526  status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
527 
528  if (status > 0)
529  {
530  size_t ustatus = (size_t)status;
531  size_t length = 0;
532  size_t offset = 0;
533 
534  length =
535  (pStreamHeaderBuffer->cbBuffer > ustatus) ? ustatus : pStreamHeaderBuffer->cbBuffer;
536  CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length);
537  ustatus -= length;
538  offset += length;
539  length = (pStreamBodyBuffer->cbBuffer > ustatus) ? ustatus : pStreamBodyBuffer->cbBuffer;
540  CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length);
541  ustatus -= length;
542  offset += length;
543  length =
544  (pStreamTrailerBuffer->cbBuffer > ustatus) ? ustatus : pStreamTrailerBuffer->cbBuffer;
545  CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length);
546  }
547 
548  return SEC_E_OK;
549 }
550 
551 SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
552 {
553  int status = 0;
554  int length = 0;
555  BYTE* buffer = NULL;
556  int ssl_error = 0;
557  PSecBuffer pBuffer = NULL;
558  pBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
559 
560  if (!pBuffer)
561  return SEC_E_INVALID_TOKEN;
562 
563  ERR_clear_error();
564  status = BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
565  if (status > 0)
566  status = SSL_read(context->ssl, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
567 
568  if (status < 0)
569  {
570  ssl_error = SSL_get_error(context->ssl, status);
571  WLog_ERR(TAG, "SSL_read: %s", openssl_get_ssl_error_string(ssl_error));
572  }
573 
574  length = status;
575  buffer = pBuffer->pvBuffer;
576  pMessage->pBuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
577  pMessage->pBuffers[0].cbBuffer = 5;
578  pMessage->pBuffers[1].BufferType = SECBUFFER_DATA;
579  pMessage->pBuffers[1].pvBuffer = buffer;
580  pMessage->pBuffers[1].cbBuffer = WINPR_ASSERTING_INT_CAST(uint32_t, length);
581  pMessage->pBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
582  pMessage->pBuffers[2].cbBuffer = 36;
583  pMessage->pBuffers[3].BufferType = SECBUFFER_EMPTY;
584  pMessage->pBuffers[3].cbBuffer = 0;
585  return SEC_E_OK;
586 }
587 
588 SCHANNEL_OPENSSL* schannel_openssl_new(void)
589 {
590  SCHANNEL_OPENSSL* context = NULL;
591  context = (SCHANNEL_OPENSSL*)calloc(1, sizeof(SCHANNEL_OPENSSL));
592 
593  if (context != NULL)
594  {
595  winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
596  context->connected = FALSE;
597  }
598 
599  return context;
600 }
601 
602 void schannel_openssl_free(SCHANNEL_OPENSSL* context)
603 {
604  if (context)
605  {
606  free(context->ReadBuffer);
607  free(context->WriteBuffer);
608  free(context);
609  }
610 }
611 
612 #else
613 
614 int schannel_openssl_client_init(SCHANNEL_OPENSSL* context)
615 {
616  return 0;
617 }
618 
619 int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
620 {
621  return 0;
622 }
623 
624 SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context,
625  PSecBufferDesc pInput,
626  PSecBufferDesc pOutput)
627 {
628  return SEC_E_OK;
629 }
630 
631 SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context,
632  PSecBufferDesc pInput,
633  PSecBufferDesc pOutput)
634 {
635  return SEC_E_OK;
636 }
637 
638 SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
639 {
640  return SEC_E_OK;
641 }
642 
643 SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
644 {
645  return SEC_E_OK;
646 }
647 
648 SCHANNEL_OPENSSL* schannel_openssl_new(void)
649 {
650  return NULL;
651 }
652 
653 void schannel_openssl_free(SCHANNEL_OPENSSL* context)
654 {
655 }
656 
657 #endif