]> jfr.im git - solanum.git/blob - librb/src/openssl.c
[mbedtls] Various fixes and improvements
[solanum.git] / librb / src / openssl.c
1 /*
2 * librb: a library used by ircd-ratbox and other things
3 * openssl.c: openssl related code
4 *
5 * Copyright (C) 2007-2008 ircd-ratbox development team
6 * Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 *
23 */
24
25 #include <librb_config.h>
26 #include <rb_lib.h>
27
28 #ifdef HAVE_OPENSSL
29
30 #include <commio-int.h>
31 #include <commio-ssl.h>
32 #include <openssl/ssl.h>
33 #include <openssl/dh.h>
34 #include <openssl/err.h>
35 #include <openssl/evp.h>
36 #include <openssl/rand.h>
37 #include <openssl/opensslv.h>
38
39 /*
40 * This is a mess but what can you do when the library authors
41 * refuse to play ball with established conventions?
42 */
43 #if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20020002L)
44 # define LRB_HAVE_TLS_METHOD_API 1
45 #else
46 # if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
47 # define LRB_HAVE_TLS_METHOD_API 1
48 # endif
49 #endif
50
51 /*
52 * Use SSL_CTX_set_ecdh_auto() in OpenSSL 1.0.2 only
53 * Use SSL_CTX_set1_curves_list() in OpenSSL 1.0.2 and above
54 * TODO: Merge this into the block above if LibreSSL implements them
55 */
56 #if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002000L)
57 # define LRB_HAVE_TLS_SET_CURVES 1
58 # if (OPENSSL_VERSION_NUMBER < 0x10100000L)
59 # define LRB_HAVE_TLS_ECDH_AUTO 1
60 # endif
61 #endif
62
63 static SSL_CTX *ssl_server_ctx = NULL;
64 static SSL_CTX *ssl_client_ctx = NULL;
65 static int librb_index = -1;
66
67 static unsigned long
68 get_last_err(void)
69 {
70 unsigned long t_err, err = 0;
71 err = ERR_get_error();
72 if(err == 0)
73 return 0;
74
75 while((t_err = ERR_get_error()) > 0)
76 err = t_err;
77
78 return err;
79 }
80
81 void
82 rb_ssl_shutdown(rb_fde_t *F)
83 {
84 int i;
85 if(F == NULL || F->ssl == NULL)
86 return;
87 SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN);
88
89 for(i = 0; i < 4; i++)
90 {
91 if(SSL_shutdown((SSL *) F->ssl))
92 break;
93 }
94 get_last_err();
95 SSL_free((SSL *) F->ssl);
96 }
97
98 unsigned int
99 rb_ssl_handshake_count(rb_fde_t *F)
100 {
101 return F->handshake_count;
102 }
103
104 void
105 rb_ssl_clear_handshake_count(rb_fde_t *F)
106 {
107 F->handshake_count = 0;
108 }
109
110 static void
111 rb_ssl_timeout(rb_fde_t *F, void *notused)
112 {
113 lrb_assert(F->accept != NULL);
114 F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
115 }
116
117
118 static void
119 rb_ssl_info_callback(SSL * ssl, int where, int ret)
120 {
121 if(where & SSL_CB_HANDSHAKE_START)
122 {
123 rb_fde_t *F = SSL_get_ex_data(ssl, librb_index);
124 if(F == NULL)
125 return;
126 F->handshake_count++;
127 }
128 }
129
130 static void
131 rb_setup_ssl_cb(rb_fde_t *F)
132 {
133 SSL_set_ex_data(F->ssl, librb_index, (char *)F);
134 SSL_set_info_callback((SSL *) F->ssl, (void (*)(const SSL *,int,int))rb_ssl_info_callback);
135 }
136
137 static void
138 rb_ssl_tryaccept(rb_fde_t *F, void *data)
139 {
140 int ssl_err;
141 lrb_assert(F->accept != NULL);
142 int flags;
143 struct acceptdata *ad;
144
145 if(!SSL_is_init_finished((SSL *) F->ssl))
146 {
147 if((ssl_err = SSL_accept((SSL *) F->ssl)) <= 0)
148 {
149 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
150 {
151 case SSL_ERROR_WANT_READ:
152 case SSL_ERROR_WANT_WRITE:
153 if(ssl_err == SSL_ERROR_WANT_WRITE)
154 flags = RB_SELECT_WRITE;
155 else
156 flags = RB_SELECT_READ;
157 F->ssl_errno = get_last_err();
158 rb_setselect(F, flags, rb_ssl_tryaccept, NULL);
159 break;
160 case SSL_ERROR_SYSCALL:
161 F->accept->callback(F, RB_ERROR, NULL, 0, F->accept->data);
162 break;
163 default:
164 F->ssl_errno = get_last_err();
165 F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data);
166 break;
167 }
168 return;
169 }
170 }
171 rb_settimeout(F, 0, NULL, NULL);
172 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
173
174 ad = F->accept;
175 F->accept = NULL;
176 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
177 rb_free(ad);
178
179 }
180
181
182 static void
183 rb_ssl_accept_common(rb_fde_t *new_F)
184 {
185 int ssl_err;
186 if((ssl_err = SSL_accept((SSL *) new_F->ssl)) <= 0)
187 {
188 switch (ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err))
189 {
190 case SSL_ERROR_SYSCALL:
191 if(rb_ignore_errno(errno))
192 case SSL_ERROR_WANT_READ:
193 case SSL_ERROR_WANT_WRITE:
194 {
195 new_F->ssl_errno = get_last_err();
196 rb_setselect(new_F, RB_SELECT_READ | RB_SELECT_WRITE,
197 rb_ssl_tryaccept, NULL);
198 return;
199 }
200 default:
201 new_F->ssl_errno = get_last_err();
202 new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data);
203 return;
204 }
205 }
206 else
207 {
208 rb_ssl_tryaccept(new_F, NULL);
209 }
210 }
211
212 void
213 rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
214 {
215 new_F->type |= RB_FD_SSL;
216 new_F->ssl = SSL_new(ssl_server_ctx);
217 new_F->accept = rb_malloc(sizeof(struct acceptdata));
218
219 new_F->accept->callback = cb;
220 new_F->accept->data = data;
221 rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL);
222
223 new_F->accept->addrlen = 0;
224 SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
225 rb_setup_ssl_cb(new_F);
226 rb_ssl_accept_common(new_F);
227 }
228
229
230
231
232 void
233 rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
234 {
235 new_F->type |= RB_FD_SSL;
236 new_F->ssl = SSL_new(ssl_server_ctx);
237 new_F->accept = rb_malloc(sizeof(struct acceptdata));
238
239 new_F->accept->callback = F->accept->callback;
240 new_F->accept->data = F->accept->data;
241 rb_settimeout(new_F, 10, rb_ssl_timeout, NULL);
242 memcpy(&new_F->accept->S, st, addrlen);
243 new_F->accept->addrlen = addrlen;
244
245 SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
246 rb_setup_ssl_cb(new_F);
247 rb_ssl_accept_common(new_F);
248 }
249
250 static ssize_t
251 rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count)
252 {
253 ssize_t ret;
254 unsigned long err;
255 SSL *ssl = F->ssl;
256
257 if(r_or_w == 0)
258 ret = (ssize_t) SSL_read(ssl, rbuf, (int)count);
259 else
260 ret = (ssize_t) SSL_write(ssl, wbuf, (int)count);
261
262 if(ret < 0)
263 {
264 switch (SSL_get_error(ssl, ret))
265 {
266 case SSL_ERROR_WANT_READ:
267 errno = EAGAIN;
268 return RB_RW_SSL_NEED_READ;
269 case SSL_ERROR_WANT_WRITE:
270 errno = EAGAIN;
271 return RB_RW_SSL_NEED_WRITE;
272 case SSL_ERROR_ZERO_RETURN:
273 return 0;
274 case SSL_ERROR_SYSCALL:
275 err = get_last_err();
276 if(err == 0)
277 {
278 F->ssl_errno = 0;
279 return RB_RW_IO_ERROR;
280 }
281 break;
282 default:
283 err = get_last_err();
284 break;
285 }
286 F->ssl_errno = err;
287 if(err > 0)
288 {
289 errno = EIO; /* not great but... */
290 return RB_RW_SSL_ERROR;
291 }
292 return RB_RW_IO_ERROR;
293 }
294 return ret;
295 }
296
297 ssize_t
298 rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
299 {
300 return rb_ssl_read_or_write(0, F, buf, NULL, count);
301 }
302
303 ssize_t
304 rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
305 {
306 return rb_ssl_read_or_write(1, F, NULL, buf, count);
307 }
308
309 static int
310 verify_accept_all_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
311 {
312 return 1;
313 }
314
315 static const char *
316 get_ssl_error(unsigned long err)
317 {
318 static char buf[512];
319
320 ERR_error_string_n(err, buf, sizeof buf);
321 return buf;
322 }
323
324 int
325 rb_init_ssl(void)
326 {
327 char librb_data[] = "librb data";
328
329 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
330 /*
331 * OpenSSL 1.1.0 and above automatically initialises itself with sane defaults
332 */
333 SSL_library_init();
334 SSL_load_error_strings();
335 #endif
336
337 librb_index = SSL_get_ex_new_index(0, librb_data, NULL, NULL, NULL);
338
339 return 1;
340 }
341
342 int
343 rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list)
344 {
345 const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!aNULL";
346
347 #ifdef LRB_HAVE_TLS_SET_CURVES
348 const char librb_curves[] = "P-521:P-384:P-256";
349 #endif
350
351 if(certfile == NULL)
352 {
353 rb_lib_log("rb_setup_ssl_server: No certificate file");
354 return 0;
355 }
356
357 if(keyfile == NULL)
358 keyfile = certfile;
359
360 if(cipher_list == NULL)
361 cipher_list = librb_ciphers;
362
363 if (ssl_server_ctx)
364 SSL_CTX_free(ssl_server_ctx);
365
366 if (ssl_client_ctx)
367 SSL_CTX_free(ssl_client_ctx);
368
369 #ifdef LRB_HAVE_TLS_METHOD_API
370 ssl_server_ctx = SSL_CTX_new(TLS_server_method());
371 ssl_client_ctx = SSL_CTX_new(TLS_client_method());
372 #else
373 ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
374 ssl_client_ctx = SSL_CTX_new(SSLv23_client_method());
375 #endif
376
377 if(ssl_server_ctx == NULL)
378 {
379 rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
380 get_ssl_error(ERR_get_error()));
381 return 0;
382 }
383
384 if(ssl_client_ctx == NULL)
385 {
386 rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
387 get_ssl_error(ERR_get_error()));
388 return 0;
389 }
390
391 #ifndef LRB_HAVE_TLS_METHOD_API
392 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
393 SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
394 #endif
395
396 #ifdef SSL_OP_SINGLE_DH_USE
397 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_DH_USE);
398 #endif
399
400 #ifdef SSL_OP_SINGLE_ECDH_USE
401 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE);
402 #endif
403
404 #ifdef SSL_OP_NO_TICKET
405 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_TICKET);
406 SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET);
407 #endif
408
409 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
410 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
411 #endif
412
413 SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
414 SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF);
415
416 #ifdef LRB_HAVE_TLS_SET_CURVES
417 SSL_CTX_set1_curves_list(ssl_server_ctx, librb_curves);
418 #endif
419
420 #ifdef LRB_HAVE_TLS_ECDH_AUTO
421 SSL_CTX_set_ecdh_auto(ssl_server_ctx, 1);
422 #endif
423
424 /*
425 * Set manual ECDHE curve on OpenSSL 1.0.0 & 1.0.1, but make sure it's actually available
426 */
427 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH)
428 EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
429 if (key) {
430 SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
431 EC_KEY_free(key);
432 }
433 #endif
434
435 SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list);
436 SSL_CTX_set_cipher_list(ssl_client_ctx, cipher_list);
437
438 if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, certfile) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, certfile))
439 {
440 rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", certfile,
441 get_ssl_error(ERR_get_error()));
442 return 0;
443 }
444
445 if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM))
446 {
447 rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
448 get_ssl_error(ERR_get_error()));
449 return 0;
450 }
451
452 if(dhfile != NULL)
453 {
454 /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
455 BIO *bio = BIO_new_file(dhfile, "r");
456 if(bio != NULL)
457 {
458 DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
459 if(dh == NULL)
460 {
461 rb_lib_log
462 ("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
463 dhfile, get_ssl_error(ERR_get_error()));
464 BIO_free(bio);
465 return 0;
466 }
467 BIO_free(bio);
468 SSL_CTX_set_tmp_dh(ssl_server_ctx, dh);
469 DH_free(dh);
470 }
471 else
472 {
473 rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
474 dhfile, get_ssl_error(ERR_get_error()));
475 }
476 }
477
478 return 1;
479 }
480
481 int
482 rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
483 {
484 int result;
485
486 result = rb_listen(F, backlog, defer_accept);
487 F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
488
489 return result;
490 }
491
492 struct ssl_connect
493 {
494 CNCB *callback;
495 void *data;
496 int timeout;
497 };
498
499 static void
500 rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn)
501 {
502 F->connect->callback = sconn->callback;
503 F->connect->data = sconn->data;
504 rb_free(sconn);
505 rb_connect_callback(F, status);
506 }
507
508 static void
509 rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data)
510 {
511 rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
512 }
513
514 static void
515 rb_ssl_tryconn_cb(rb_fde_t *F, void *data)
516 {
517 struct ssl_connect *sconn = data;
518 int ssl_err;
519 if(!SSL_is_init_finished((SSL *) F->ssl))
520 {
521 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
522 {
523 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
524 {
525 case SSL_ERROR_SYSCALL:
526 if(rb_ignore_errno(errno))
527 case SSL_ERROR_WANT_READ:
528 case SSL_ERROR_WANT_WRITE:
529 {
530 F->ssl_errno = get_last_err();
531 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
532 rb_ssl_tryconn_cb, sconn);
533 return;
534 }
535 default:
536 F->ssl_errno = get_last_err();
537 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
538 return;
539 }
540 }
541 else
542 {
543 rb_ssl_connect_realcb(F, RB_OK, sconn);
544 }
545 }
546 }
547
548 static void
549 rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
550 {
551 struct ssl_connect *sconn = data;
552 int ssl_err;
553 if(status != RB_OK)
554 {
555 rb_ssl_connect_realcb(F, status, sconn);
556 return;
557 }
558
559 F->type |= RB_FD_SSL;
560 F->ssl = SSL_new(ssl_client_ctx);
561 SSL_set_fd((SSL *) F->ssl, F->fd);
562 rb_setup_ssl_cb(F);
563 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
564 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
565 {
566 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
567 {
568 case SSL_ERROR_SYSCALL:
569 if(rb_ignore_errno(errno))
570 case SSL_ERROR_WANT_READ:
571 case SSL_ERROR_WANT_WRITE:
572 {
573 F->ssl_errno = get_last_err();
574 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
575 rb_ssl_tryconn_cb, sconn);
576 return;
577 }
578 default:
579 F->ssl_errno = get_last_err();
580 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
581 return;
582 }
583 }
584 else
585 {
586 rb_ssl_connect_realcb(F, RB_OK, sconn);
587 }
588 }
589
590 void
591 rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
592 struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
593 {
594 struct ssl_connect *sconn;
595 if(F == NULL)
596 return;
597
598 sconn = rb_malloc(sizeof(struct ssl_connect));
599 sconn->data = data;
600 sconn->callback = callback;
601 sconn->timeout = timeout;
602 rb_connect_tcp(F, dest, clocal, rb_ssl_tryconn, sconn, timeout);
603 }
604
605 void
606 rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
607 {
608 struct ssl_connect *sconn;
609 int ssl_err;
610 if(F == NULL)
611 return;
612
613 sconn = rb_malloc(sizeof(struct ssl_connect));
614 sconn->data = data;
615 sconn->callback = callback;
616 sconn->timeout = timeout;
617 F->connect = rb_malloc(sizeof(struct conndata));
618 F->connect->callback = callback;
619 F->connect->data = data;
620 F->type |= RB_FD_SSL;
621 F->ssl = SSL_new(ssl_client_ctx);
622
623 SSL_set_fd((SSL *) F->ssl, F->fd);
624 rb_setup_ssl_cb(F);
625 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
626 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
627 {
628 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
629 {
630 case SSL_ERROR_SYSCALL:
631 if(rb_ignore_errno(errno))
632 case SSL_ERROR_WANT_READ:
633 case SSL_ERROR_WANT_WRITE:
634 {
635 F->ssl_errno = get_last_err();
636 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
637 rb_ssl_tryconn_cb, sconn);
638 return;
639 }
640 default:
641 F->ssl_errno = get_last_err();
642 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
643 return;
644 }
645 }
646 else
647 {
648 rb_ssl_connect_realcb(F, RB_OK, sconn);
649 }
650 }
651
652 int
653 rb_init_prng(const char *path, prng_seed_t seed_type)
654 {
655 if(seed_type == RB_PRNG_DEFAULT)
656 {
657 #ifdef _WIN32
658 RAND_screen();
659 #endif
660 return RAND_status();
661 }
662 if(path == NULL)
663 return RAND_status();
664
665 switch (seed_type)
666 {
667 case RB_PRNG_FILE:
668 if(RAND_load_file(path, -1) == -1)
669 return -1;
670 break;
671 #ifdef _WIN32
672 case RB_PRNGWIN32:
673 RAND_screen();
674 break;
675 #endif
676 default:
677 return -1;
678 }
679
680 return RAND_status();
681 }
682
683 int
684 rb_get_random(void *buf, size_t length)
685 {
686 int ret;
687
688 if((ret = RAND_bytes(buf, length)) == 0)
689 {
690 /* remove the error from the queue */
691 ERR_get_error();
692 }
693 return ret;
694 }
695
696 const char *
697 rb_get_ssl_strerror(rb_fde_t *F)
698 {
699 return get_ssl_error(F->ssl_errno);
700 }
701
702 static int
703 make_certfp(X509 *cert, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
704 {
705 const ASN1_ITEM *it;
706 const EVP_MD *evp;
707 void *data;
708 unsigned int len;
709
710 switch(method)
711 {
712 case RB_SSL_CERTFP_METH_CERT_SHA1:
713 it = ASN1_ITEM_rptr(X509);
714 evp = EVP_sha1();
715 data = cert;
716 len = RB_SSL_CERTFP_LEN_SHA1;
717 break;
718 case RB_SSL_CERTFP_METH_CERT_SHA256:
719 it = ASN1_ITEM_rptr(X509);
720 evp = EVP_sha256();
721 data = cert;
722 len = RB_SSL_CERTFP_LEN_SHA256;
723 break;
724 case RB_SSL_CERTFP_METH_CERT_SHA512:
725 it = ASN1_ITEM_rptr(X509);
726 evp = EVP_sha512();
727 data = cert;
728 len = RB_SSL_CERTFP_LEN_SHA512;
729 break;
730 case RB_SSL_CERTFP_METH_SPKI_SHA256:
731 it = ASN1_ITEM_rptr(X509_PUBKEY);
732 evp = EVP_sha256();
733 data = X509_get_X509_PUBKEY(cert);
734 len = RB_SSL_CERTFP_LEN_SHA256;
735 break;
736 case RB_SSL_CERTFP_METH_SPKI_SHA512:
737 it = ASN1_ITEM_rptr(X509_PUBKEY);
738 evp = EVP_sha512();
739 data = X509_get_X509_PUBKEY(cert);
740 len = RB_SSL_CERTFP_LEN_SHA512;
741 break;
742 default:
743 return 0;
744 }
745
746 if (ASN1_item_digest(it, evp, data, certfp, &len) != 1)
747 len = 0;
748 return (int) len;
749 }
750
751 int
752 rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
753 {
754 int len = 0;
755 X509 *cert;
756 int res;
757
758 if (F->ssl == NULL)
759 return 0;
760
761 cert = SSL_get_peer_certificate((SSL *) F->ssl);
762 if(cert == NULL)
763 return 0;
764
765 res = SSL_get_verify_result((SSL *) F->ssl);
766 switch(res)
767 {
768 case X509_V_OK:
769 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
770 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
771 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
772 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
773 case X509_V_ERR_CERT_UNTRUSTED:
774 len = make_certfp(cert, certfp, method);
775
776 default: /* to silence code inspectors */
777 break;
778 }
779
780 X509_free(cert);
781 return len;
782 }
783
784 int
785 rb_get_ssl_certfp_file(const char *filename, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
786 {
787 X509 *cert;
788 FILE *f = fopen(filename, "r");
789
790 if (!f)
791 return -1;
792
793 cert = PEM_read_X509(f, NULL, NULL, NULL);
794 fclose(f);
795
796 if (cert) {
797 unsigned int len = make_certfp(cert, certfp, method);
798 X509_free(cert);
799 return len;
800 }
801 return 0;
802 }
803
804 int
805 rb_supports_ssl(void)
806 {
807 return 1;
808 }
809
810 void
811 rb_get_ssl_info(char *buf, size_t len)
812 {
813 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
814 if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER)
815 snprintf(buf, len, "OpenSSL: 0x%lx, %s",
816 OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT);
817 else
818 snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
819 OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
820 OpenSSL_version_num(), OpenSSL_version(OPENSSL_VERSION));
821 #else
822 if (SSLeay() == SSLEAY_VERSION_NUMBER)
823 snprintf(buf, len, "OpenSSL: 0x%lx, %s",
824 SSLeay(), SSLeay_version(SSLEAY_VERSION));
825 else
826 snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
827 SSLEAY_VERSION_NUMBER, "???",
828 SSLeay(), SSLeay_version(SSLEAY_VERSION));
829 #endif
830 }
831
832 const char *
833 rb_ssl_get_cipher(rb_fde_t *F)
834 {
835 const SSL_CIPHER *sslciph;
836
837 if(F == NULL || F->ssl == NULL)
838 return NULL;
839
840 if((sslciph = SSL_get_current_cipher(F->ssl)) == NULL)
841 return NULL;
842
843 return SSL_CIPHER_get_name(sslciph);
844 }
845
846 #endif /* HAVE_OPENSSL */