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, 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 < (unsigned long)status)
415  return SEC_E_INSUFFICIENT_MEMORY;
416 
417  CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
418  pBuffer->cbBuffer = status;
419  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
420  }
421  else
422  {
423  pBuffer->cbBuffer = 0;
424  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
425  }
426  }
427 
428  return SEC_E_OK;
429 }
430 
431 SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context,
432  PSecBufferDesc pInput,
433  PSecBufferDesc pOutput)
434 {
435  int status = 0;
436  int ssl_error = 0;
437  PSecBuffer pBuffer = NULL;
438 
439  if (!context->connected)
440  {
441  if (pInput->cBuffers < 1)
442  return SEC_E_INVALID_TOKEN;
443 
444  pBuffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
445 
446  if (!pBuffer)
447  return SEC_E_INVALID_TOKEN;
448 
449  ERR_clear_error();
450  status = BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
451  if (status >= 0)
452  status = SSL_accept(context->ssl);
453 
454  if (status < 0)
455  {
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;
459  }
460 
461  if (status == 1)
462  context->connected = TRUE;
463 
464  ERR_clear_error();
465  status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
466  if (status < 0)
467  {
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;
471  }
472 
473  if (pOutput->cBuffers < 1)
474  return SEC_E_INVALID_TOKEN;
475 
476  pBuffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
477 
478  if (!pBuffer)
479  return SEC_E_INVALID_TOKEN;
480 
481  if (status > 0)
482  {
483  if (pBuffer->cbBuffer < (unsigned long)status)
484  return SEC_E_INSUFFICIENT_MEMORY;
485 
486  CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status);
487  pBuffer->cbBuffer = status;
488  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
489  }
490  else
491  {
492  pBuffer->cbBuffer = 0;
493  return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED;
494  }
495  }
496 
497  return SEC_E_OK;
498 }
499 
500 SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
501 {
502  int status = 0;
503  int ssl_error = 0;
504  PSecBuffer pStreamBodyBuffer = NULL;
505  PSecBuffer pStreamHeaderBuffer = NULL;
506  PSecBuffer pStreamTrailerBuffer = NULL;
507  pStreamHeaderBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_HEADER);
508  pStreamBodyBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
509  pStreamTrailerBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_STREAM_TRAILER);
510 
511  if ((!pStreamHeaderBuffer) || (!pStreamBodyBuffer) || (!pStreamTrailerBuffer))
512  return SEC_E_INVALID_TOKEN;
513 
514  status = SSL_write(context->ssl, pStreamBodyBuffer->pvBuffer,
515  LIMIT_INTMAX(pStreamBodyBuffer->cbBuffer));
516 
517  if (status < 0)
518  {
519  ssl_error = SSL_get_error(context->ssl, status);
520  WLog_ERR(TAG, "SSL_write: %s", openssl_get_ssl_error_string(ssl_error));
521  }
522 
523  ERR_clear_error();
524  status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN);
525 
526  if (status > 0)
527  {
528  size_t ustatus = (size_t)status;
529  size_t length = 0;
530  size_t offset = 0;
531 
532  length =
533  (pStreamHeaderBuffer->cbBuffer > ustatus) ? ustatus : pStreamHeaderBuffer->cbBuffer;
534  CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length);
535  ustatus -= length;
536  offset += length;
537  length = (pStreamBodyBuffer->cbBuffer > ustatus) ? ustatus : pStreamBodyBuffer->cbBuffer;
538  CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length);
539  ustatus -= length;
540  offset += length;
541  length =
542  (pStreamTrailerBuffer->cbBuffer > ustatus) ? ustatus : pStreamTrailerBuffer->cbBuffer;
543  CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length);
544  }
545 
546  return SEC_E_OK;
547 }
548 
549 SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
550 {
551  int status = 0;
552  int length = 0;
553  BYTE* buffer = NULL;
554  int ssl_error = 0;
555  PSecBuffer pBuffer = NULL;
556  pBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);
557 
558  if (!pBuffer)
559  return SEC_E_INVALID_TOKEN;
560 
561  ERR_clear_error();
562  status = BIO_write(context->bioRead, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
563  if (status > 0)
564  status = SSL_read(context->ssl, pBuffer->pvBuffer, LIMIT_INTMAX(pBuffer->cbBuffer));
565 
566  if (status < 0)
567  {
568  ssl_error = SSL_get_error(context->ssl, status);
569  WLog_ERR(TAG, "SSL_read: %s", openssl_get_ssl_error_string(ssl_error));
570  }
571 
572  length = status;
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;
583  return SEC_E_OK;
584 }
585 
586 SCHANNEL_OPENSSL* schannel_openssl_new(void)
587 {
588  SCHANNEL_OPENSSL* context = NULL;
589  context = (SCHANNEL_OPENSSL*)calloc(1, sizeof(SCHANNEL_OPENSSL));
590 
591  if (context != NULL)
592  {
593  winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
594  context->connected = FALSE;
595  }
596 
597  return context;
598 }
599 
600 void schannel_openssl_free(SCHANNEL_OPENSSL* context)
601 {
602  if (context)
603  {
604  free(context->ReadBuffer);
605  free(context->WriteBuffer);
606  free(context);
607  }
608 }
609 
610 #else
611 
612 int schannel_openssl_client_init(SCHANNEL_OPENSSL* context)
613 {
614  return 0;
615 }
616 
617 int schannel_openssl_server_init(SCHANNEL_OPENSSL* context)
618 {
619  return 0;
620 }
621 
622 SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context,
623  PSecBufferDesc pInput,
624  PSecBufferDesc pOutput)
625 {
626  return SEC_E_OK;
627 }
628 
629 SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context,
630  PSecBufferDesc pInput,
631  PSecBufferDesc pOutput)
632 {
633  return SEC_E_OK;
634 }
635 
636 SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
637 {
638  return SEC_E_OK;
639 }
640 
641 SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage)
642 {
643  return SEC_E_OK;
644 }
645 
646 SCHANNEL_OPENSSL* schannel_openssl_new(void)
647 {
648  return NULL;
649 }
650 
651 void schannel_openssl_free(SCHANNEL_OPENSSL* context)
652 {
653 }
654 
655 #endif