]> jfr.im git - solanum.git/blob - libratbox/src/openssl.c
Use X509_digest() instead of memcpy() to obtain cert fingerprint
[solanum.git] / libratbox / src / openssl.c
1 /*
2 * libratbox: 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 * $Id: commio.c 24808 2008-01-02 08:17:05Z androsyn $
24 */
25
26 #include <libratbox_config.h>
27 #include <ratbox_lib.h>
28
29 #ifdef HAVE_OPENSSL
30
31 #include <commio-int.h>
32 #include <commio-ssl.h>
33 #include <openssl/ssl.h>
34 #include <openssl/dh.h>
35 #include <openssl/err.h>
36 #include <openssl/evp.h>
37 #include <openssl/rand.h>
38
39 static SSL_CTX *ssl_server_ctx;
40 static SSL_CTX *ssl_client_ctx;
41 static int libratbox_index = -1;
42
43 static unsigned long
44 get_last_err(void)
45 {
46 unsigned long t_err, err = 0;
47 err = ERR_get_error();
48 if(err == 0)
49 return 0;
50
51 while((t_err = ERR_get_error()) > 0)
52 err = t_err;
53
54 return err;
55 }
56
57 void
58 rb_ssl_shutdown(rb_fde_t *F)
59 {
60 int i;
61 if(F == NULL || F->ssl == NULL)
62 return;
63 SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN);
64
65 for(i = 0; i < 4; i++)
66 {
67 if(SSL_shutdown((SSL *) F->ssl))
68 break;
69 }
70 get_last_err();
71 SSL_free((SSL *) F->ssl);
72 }
73
74 unsigned int
75 rb_ssl_handshake_count(rb_fde_t *F)
76 {
77 return F->handshake_count;
78 }
79
80 void
81 rb_ssl_clear_handshake_count(rb_fde_t *F)
82 {
83 F->handshake_count = 0;
84 }
85
86 static void
87 rb_ssl_timeout(rb_fde_t *F, void *notused)
88 {
89 lrb_assert(F->accept != NULL);
90 F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
91 }
92
93
94 static void
95 rb_ssl_info_callback(SSL * ssl, int where, int ret)
96 {
97 if(where & SSL_CB_HANDSHAKE_START)
98 {
99 rb_fde_t *F = SSL_get_ex_data(ssl, libratbox_index);
100 if(F == NULL)
101 return;
102 F->handshake_count++;
103 }
104 }
105
106 static void
107 rb_setup_ssl_cb(rb_fde_t *F)
108 {
109 SSL_set_ex_data(F->ssl, libratbox_index, (char *)F);
110 SSL_set_info_callback((SSL *) F->ssl, (void (*)(const SSL *,int,int))rb_ssl_info_callback);
111 }
112
113 static void
114 rb_ssl_tryaccept(rb_fde_t *F, void *data)
115 {
116 int ssl_err;
117 lrb_assert(F->accept != NULL);
118 int flags;
119 struct acceptdata *ad;
120
121 if(!SSL_is_init_finished((SSL *) F->ssl))
122 {
123 if((ssl_err = SSL_accept((SSL *) F->ssl)) <= 0)
124 {
125 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
126 {
127 case SSL_ERROR_WANT_READ:
128 case SSL_ERROR_WANT_WRITE:
129 if(ssl_err == SSL_ERROR_WANT_WRITE)
130 flags = RB_SELECT_WRITE;
131 else
132 flags = RB_SELECT_READ;
133 F->ssl_errno = get_last_err();
134 rb_setselect(F, flags, rb_ssl_tryaccept, NULL);
135 break;
136 case SSL_ERROR_SYSCALL:
137 F->accept->callback(F, RB_ERROR, NULL, 0, F->accept->data);
138 break;
139 default:
140 F->ssl_errno = get_last_err();
141 F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data);
142 break;
143 }
144 return;
145 }
146 }
147 rb_settimeout(F, 0, NULL, NULL);
148 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
149
150 ad = F->accept;
151 F->accept = NULL;
152 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
153 rb_free(ad);
154
155 }
156
157
158 static void
159 rb_ssl_accept_common(rb_fde_t *new_F)
160 {
161 int ssl_err;
162 if((ssl_err = SSL_accept((SSL *) new_F->ssl)) <= 0)
163 {
164 switch (ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err))
165 {
166 case SSL_ERROR_SYSCALL:
167 if(rb_ignore_errno(errno))
168 case SSL_ERROR_WANT_READ:
169 case SSL_ERROR_WANT_WRITE:
170 {
171 new_F->ssl_errno = get_last_err();
172 rb_setselect(new_F, RB_SELECT_READ | RB_SELECT_WRITE,
173 rb_ssl_tryaccept, NULL);
174 return;
175 }
176 default:
177 new_F->ssl_errno = get_last_err();
178 new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data);
179 return;
180 }
181 }
182 else
183 {
184 rb_ssl_tryaccept(new_F, NULL);
185 }
186 }
187
188 void
189 rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
190 {
191 new_F->type |= RB_FD_SSL;
192 new_F->ssl = SSL_new(ssl_server_ctx);
193 new_F->accept = rb_malloc(sizeof(struct acceptdata));
194
195 new_F->accept->callback = cb;
196 new_F->accept->data = data;
197 rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL);
198
199 new_F->accept->addrlen = 0;
200 SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
201 rb_setup_ssl_cb(new_F);
202 rb_ssl_accept_common(new_F);
203 }
204
205
206
207
208 void
209 rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
210 {
211 new_F->type |= RB_FD_SSL;
212 new_F->ssl = SSL_new(ssl_server_ctx);
213 new_F->accept = rb_malloc(sizeof(struct acceptdata));
214
215 new_F->accept->callback = F->accept->callback;
216 new_F->accept->data = F->accept->data;
217 rb_settimeout(new_F, 10, rb_ssl_timeout, NULL);
218 memcpy(&new_F->accept->S, st, addrlen);
219 new_F->accept->addrlen = addrlen;
220
221 SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
222 rb_setup_ssl_cb(new_F);
223 rb_ssl_accept_common(new_F);
224 }
225
226 static ssize_t
227 rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count)
228 {
229 ssize_t ret;
230 unsigned long err;
231 SSL *ssl = F->ssl;
232
233 if(r_or_w == 0)
234 ret = (ssize_t) SSL_read(ssl, rbuf, (int)count);
235 else
236 ret = (ssize_t) SSL_write(ssl, wbuf, (int)count);
237
238 if(ret < 0)
239 {
240 switch (SSL_get_error(ssl, ret))
241 {
242 case SSL_ERROR_WANT_READ:
243 errno = EAGAIN;
244 return RB_RW_SSL_NEED_READ;
245 case SSL_ERROR_WANT_WRITE:
246 errno = EAGAIN;
247 return RB_RW_SSL_NEED_WRITE;
248 case SSL_ERROR_ZERO_RETURN:
249 return 0;
250 case SSL_ERROR_SYSCALL:
251 err = get_last_err();
252 if(err == 0)
253 {
254 F->ssl_errno = 0;
255 return RB_RW_IO_ERROR;
256 }
257 break;
258 default:
259 err = get_last_err();
260 break;
261 }
262 F->ssl_errno = err;
263 if(err > 0)
264 {
265 errno = EIO; /* not great but... */
266 return RB_RW_SSL_ERROR;
267 }
268 return RB_RW_IO_ERROR;
269 }
270 return ret;
271 }
272
273 ssize_t
274 rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
275 {
276 return rb_ssl_read_or_write(0, F, buf, NULL, count);
277 }
278
279 ssize_t
280 rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
281 {
282 return rb_ssl_read_or_write(1, F, NULL, buf, count);
283 }
284
285 static int
286 verify_accept_all_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
287 {
288 return 1;
289 }
290
291 static const char *
292 get_ssl_error(unsigned long err)
293 {
294 static char buf[512];
295
296 ERR_error_string_n(err, buf, sizeof buf);
297 return buf;
298 }
299
300 int
301 rb_init_ssl(void)
302 {
303 int ret = 1;
304 char libratbox_data[] = "libratbox data";
305 SSL_load_error_strings();
306 SSL_library_init();
307 libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL);
308 ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
309 if(ssl_server_ctx == NULL)
310 {
311 rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
312 get_ssl_error(ERR_get_error()));
313 ret = 0;
314 }
315 /* Disable SSLv2, make the client use our settings */
316 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_CIPHER_SERVER_PREFERENCE
317 #ifdef SSL_OP_SINGLE_DH_USE
318 | SSL_OP_SINGLE_DH_USE
319 #endif
320 #ifdef SSL_OP_NO_TICKET
321 | SSL_OP_NO_TICKET
322 #endif
323 );
324 SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
325 SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF);
326 SSL_CTX_set_cipher_list(ssl_server_ctx, "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL");
327
328 /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks
329 and bastardise their OpenSSL for stupid reasons... */
330 #if (OPENSSL_VERSION_NUMBER >= 0x10000000) && defined(NID_secp384r1)
331 EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
332 if (key) {
333 SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
334 EC_KEY_free(key);
335 }
336 #ifdef SSL_OP_SINGLE_ECDH_USE
337 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE);
338 #endif
339 #endif
340
341 ssl_client_ctx = SSL_CTX_new(TLSv1_client_method());
342
343 if(ssl_client_ctx == NULL)
344 {
345 rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
346 get_ssl_error(ERR_get_error()));
347 ret = 0;
348 }
349
350 #ifdef SSL_OP_NO_TICKET
351 SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET);
352 #endif
353
354 return ret;
355 }
356
357
358 int
359 rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile)
360 {
361 DH *dh;
362 unsigned long err;
363 if(cert == NULL)
364 {
365 rb_lib_log("rb_setup_ssl_server: No certificate file");
366 return 0;
367 }
368 if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, cert) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, cert))
369 {
370 err = ERR_get_error();
371 rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert,
372 get_ssl_error(err));
373 return 0;
374 }
375
376 if(keyfile == NULL)
377 {
378 rb_lib_log("rb_setup_ssl_server: No key file");
379 return 0;
380 }
381
382
383 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))
384 {
385 err = ERR_get_error();
386 rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
387 get_ssl_error(err));
388 return 0;
389 }
390
391 if(dhfile != NULL)
392 {
393 /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
394 BIO *bio = BIO_new_file(dhfile, "r");
395 if(bio != NULL)
396 {
397 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
398 if(dh == NULL)
399 {
400 err = ERR_get_error();
401 rb_lib_log
402 ("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
403 dhfile, get_ssl_error(err));
404 BIO_free(bio);
405 return 0;
406 }
407 BIO_free(bio);
408 SSL_CTX_set_tmp_dh(ssl_server_ctx, dh);
409 }
410 else
411 {
412 err = ERR_get_error();
413 rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
414 dhfile, get_ssl_error(err));
415 }
416 }
417 return 1;
418 }
419
420 int
421 rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
422 {
423 int result;
424
425 result = rb_listen(F, backlog, defer_accept);
426 F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
427
428 return result;
429 }
430
431 struct ssl_connect
432 {
433 CNCB *callback;
434 void *data;
435 int timeout;
436 };
437
438 static void
439 rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn)
440 {
441 F->connect->callback = sconn->callback;
442 F->connect->data = sconn->data;
443 rb_free(sconn);
444 rb_connect_callback(F, status);
445 }
446
447 static void
448 rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data)
449 {
450 rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
451 }
452
453 static void
454 rb_ssl_tryconn_cb(rb_fde_t *F, void *data)
455 {
456 struct ssl_connect *sconn = data;
457 int ssl_err;
458 if(!SSL_is_init_finished((SSL *) F->ssl))
459 {
460 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
461 {
462 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
463 {
464 case SSL_ERROR_SYSCALL:
465 if(rb_ignore_errno(errno))
466 case SSL_ERROR_WANT_READ:
467 case SSL_ERROR_WANT_WRITE:
468 {
469 F->ssl_errno = get_last_err();
470 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
471 rb_ssl_tryconn_cb, sconn);
472 return;
473 }
474 default:
475 F->ssl_errno = get_last_err();
476 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
477 return;
478 }
479 }
480 else
481 {
482 rb_ssl_connect_realcb(F, RB_OK, sconn);
483 }
484 }
485 }
486
487 static void
488 rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
489 {
490 struct ssl_connect *sconn = data;
491 int ssl_err;
492 if(status != RB_OK)
493 {
494 rb_ssl_connect_realcb(F, status, sconn);
495 return;
496 }
497
498 F->type |= RB_FD_SSL;
499 F->ssl = SSL_new(ssl_client_ctx);
500 SSL_set_fd((SSL *) F->ssl, F->fd);
501 rb_setup_ssl_cb(F);
502 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
503 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
504 {
505 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
506 {
507 case SSL_ERROR_SYSCALL:
508 if(rb_ignore_errno(errno))
509 case SSL_ERROR_WANT_READ:
510 case SSL_ERROR_WANT_WRITE:
511 {
512 F->ssl_errno = get_last_err();
513 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
514 rb_ssl_tryconn_cb, sconn);
515 return;
516 }
517 default:
518 F->ssl_errno = get_last_err();
519 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
520 return;
521 }
522 }
523 else
524 {
525 rb_ssl_connect_realcb(F, RB_OK, sconn);
526 }
527 }
528
529 void
530 rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
531 struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
532 {
533 struct ssl_connect *sconn;
534 if(F == NULL)
535 return;
536
537 sconn = rb_malloc(sizeof(struct ssl_connect));
538 sconn->data = data;
539 sconn->callback = callback;
540 sconn->timeout = timeout;
541 rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
542
543 }
544
545 void
546 rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
547 {
548 struct ssl_connect *sconn;
549 int ssl_err;
550 if(F == NULL)
551 return;
552
553 sconn = rb_malloc(sizeof(struct ssl_connect));
554 sconn->data = data;
555 sconn->callback = callback;
556 sconn->timeout = timeout;
557 F->connect = rb_malloc(sizeof(struct conndata));
558 F->connect->callback = callback;
559 F->connect->data = data;
560 F->type |= RB_FD_SSL;
561 F->ssl = SSL_new(ssl_client_ctx);
562
563 SSL_set_fd((SSL *) F->ssl, F->fd);
564 rb_setup_ssl_cb(F);
565 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
566 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
567 {
568 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
569 {
570 case SSL_ERROR_SYSCALL:
571 if(rb_ignore_errno(errno))
572 case SSL_ERROR_WANT_READ:
573 case SSL_ERROR_WANT_WRITE:
574 {
575 F->ssl_errno = get_last_err();
576 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
577 rb_ssl_tryconn_cb, sconn);
578 return;
579 }
580 default:
581 F->ssl_errno = get_last_err();
582 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
583 return;
584 }
585 }
586 else
587 {
588 rb_ssl_connect_realcb(F, RB_OK, sconn);
589 }
590 }
591
592 int
593 rb_init_prng(const char *path, prng_seed_t seed_type)
594 {
595 if(seed_type == RB_PRNG_DEFAULT)
596 {
597 #ifdef _WIN32
598 RAND_screen();
599 #endif
600 return RAND_status();
601 }
602 if(path == NULL)
603 return RAND_status();
604
605 switch (seed_type)
606 {
607 case RB_PRNG_FILE:
608 if(RAND_load_file(path, -1) == -1)
609 return -1;
610 break;
611 #ifdef _WIN32
612 case RB_PRNGWIN32:
613 RAND_screen();
614 break;
615 #endif
616 default:
617 return -1;
618 }
619
620 return RAND_status();
621 }
622
623 int
624 rb_get_random(void *buf, size_t length)
625 {
626 int ret;
627
628 if((ret = RAND_bytes(buf, length)) == 0)
629 {
630 /* remove the error from the queue */
631 ERR_get_error();
632 }
633 return ret;
634 }
635
636 int
637 rb_get_pseudo_random(void *buf, size_t length)
638 {
639 int ret;
640 ret = RAND_pseudo_bytes(buf, length);
641 if(ret < 0)
642 return 0;
643 return 1;
644 }
645
646 const char *
647 rb_get_ssl_strerror(rb_fde_t *F)
648 {
649 return get_ssl_error(F->ssl_errno);
650 }
651
652 int
653 rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
654 {
655 X509 *cert;
656 int res;
657
658 if (F->ssl == NULL)
659 return 0;
660
661 cert = SSL_get_peer_certificate((SSL *) F->ssl);
662 if(cert != NULL)
663 {
664 res = SSL_get_verify_result((SSL *) F->ssl);
665 if(res == X509_V_OK ||
666 res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
667 res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE ||
668 res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
669 {
670 unsigned int certfp_length = RB_SSL_CERTFP_LEN;
671 X509_digest(cert, EVP_sha1(), certfp, &certfp_length);
672 X509_free(cert);
673 return 1;
674 }
675 X509_free(cert);
676 }
677
678 return 0;
679 }
680
681 int
682 rb_supports_ssl(void)
683 {
684 return 1;
685 }
686
687 void
688 rb_get_ssl_info(char *buf, size_t len)
689 {
690 rb_snprintf(buf, len, "Using SSL: %s compiled: 0x%lx, library 0x%lx",
691 SSLeay_version(SSLEAY_VERSION),
692 (long)OPENSSL_VERSION_NUMBER, SSLeay());
693 }
694
695
696 #endif /* HAVE_OPESSL */