]> jfr.im git - solanum.git/blame - librb/src/openssl.c
openssl: change how we load DH parameters
[solanum.git] / librb / src / openssl.c
CommitLineData
db137867 1/*
fe037171 2 * librb: a library used by ircd-ratbox and other things
db137867
AC
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.
55abcbb2 17 *
db137867
AC
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 *
db137867
AC
23 */
24
fe037171
EM
25#include <librb_config.h>
26#include <rb_lib.h>
db137867
AC
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>
d3806d05 35#include <openssl/evp.h>
db137867 36#include <openssl/rand.h>
3ae24413
AJ
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
db137867 50
b1f05493
AJ
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
cf12678b
AJ
63static SSL_CTX *ssl_server_ctx = NULL;
64static SSL_CTX *ssl_client_ctx = NULL;
fe037171 65static int librb_index = -1;
db137867 66
3202e249
VY
67static unsigned long
68get_last_err(void)
db137867
AC
69{
70 unsigned long t_err, err = 0;
71 err = ERR_get_error();
72 if(err == 0)
73 return 0;
3202e249 74
db137867
AC
75 while((t_err = ERR_get_error()) > 0)
76 err = t_err;
77
78 return err;
79}
80
81void
3202e249 82rb_ssl_shutdown(rb_fde_t *F)
db137867
AC
83{
84 int i;
85 if(F == NULL || F->ssl == NULL)
86 return;
87 SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN);
88
3202e249 89 for(i = 0; i < 4; i++)
db137867
AC
90 {
91 if(SSL_shutdown((SSL *) F->ssl))
92 break;
93 }
94 get_last_err();
95 SSL_free((SSL *) F->ssl);
96}
97
c2ac22cc
VY
98unsigned int
99rb_ssl_handshake_count(rb_fde_t *F)
100{
101 return F->handshake_count;
102}
103
104void
105rb_ssl_clear_handshake_count(rb_fde_t *F)
106{
107 F->handshake_count = 0;
108}
109
db137867 110static void
3202e249 111rb_ssl_timeout(rb_fde_t *F, void *notused)
db137867 112{
73d6283c
VY
113 lrb_assert(F->accept != NULL);
114 F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
db137867
AC
115}
116
117
3202e249
VY
118static void
119rb_ssl_info_callback(SSL * ssl, int where, int ret)
c2ac22cc
VY
120{
121 if(where & SSL_CB_HANDSHAKE_START)
122 {
fe037171 123 rb_fde_t *F = SSL_get_ex_data(ssl, librb_index);
c2ac22cc
VY
124 if(F == NULL)
125 return;
126 F->handshake_count++;
3202e249 127 }
c2ac22cc
VY
128}
129
130static void
131rb_setup_ssl_cb(rb_fde_t *F)
132{
fe037171 133 SSL_set_ex_data(F->ssl, librb_index, (char *)F);
3202e249 134 SSL_set_info_callback((SSL *) F->ssl, (void (*)(const SSL *,int,int))rb_ssl_info_callback);
c2ac22cc
VY
135}
136
db137867 137static void
3202e249 138rb_ssl_tryaccept(rb_fde_t *F, void *data)
db137867
AC
139{
140 int ssl_err;
141 lrb_assert(F->accept != NULL);
73d6283c 142 int flags;
2142f691 143 struct acceptdata *ad;
db137867
AC
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 {
db137867
AC
151 case SSL_ERROR_WANT_READ:
152 case SSL_ERROR_WANT_WRITE:
73d6283c
VY
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;
db137867
AC
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);
3202e249 173
2142f691 174 ad = F->accept;
db137867 175 F->accept = NULL;
3202e249 176 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
2142f691 177 rb_free(ad);
db137867
AC
178
179}
180
c2ac22cc
VY
181
182static void
183rb_ssl_accept_common(rb_fde_t *new_F)
db137867
AC
184{
185 int ssl_err;
db137867
AC
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
c2ac22cc 212void
3202e249 213rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
c2ac22cc
VY
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
db137867
AC
229
230
231
232void
3202e249 233rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
db137867 234{
db137867
AC
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
a9fb3ed0 245 SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
c2ac22cc
VY
246 rb_setup_ssl_cb(new_F);
247 rb_ssl_accept_common(new_F);
db137867
AC
248}
249
250static ssize_t
3202e249 251rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count)
db137867
AC
252{
253 ssize_t ret;
254 unsigned long err;
255 SSL *ssl = F->ssl;
256
257 if(r_or_w == 0)
3202e249 258 ret = (ssize_t) SSL_read(ssl, rbuf, (int)count);
db137867 259 else
3202e249 260 ret = (ssize_t) SSL_write(ssl, wbuf, (int)count);
db137867
AC
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
297ssize_t
3202e249 298rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
db137867
AC
299{
300 return rb_ssl_read_or_write(0, F, buf, NULL, count);
301}
302
303ssize_t
3202e249 304rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
db137867
AC
305{
306 return rb_ssl_read_or_write(1, F, NULL, buf, count);
307}
308
7247337a
JT
309static int
310verify_accept_all_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
311{
312 return 1;
313}
314
918d73d5
JT
315static const char *
316get_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
db137867
AC
324int
325rb_init_ssl(void)
326{
fe037171 327 char librb_data[] = "librb data";
cf12678b
AJ
328
329#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
330 /*
331 * OpenSSL 1.1.0 and above automatically initialises itself with sane defaults
332 */
db137867 333 SSL_library_init();
cf12678b
AJ
334 SSL_load_error_strings();
335#endif
336
fe037171 337 librb_index = SSL_get_ex_new_index(0, librb_data, NULL, NULL, NULL);
a4c8c827 338
cf12678b
AJ
339 return 1;
340}
341
342int
0fe9dd41 343rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list)
cf12678b
AJ
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
0fe9dd41 351 if(certfile == NULL)
cf12678b
AJ
352 {
353 rb_lib_log("rb_setup_ssl_server: No certificate file");
354 return 0;
355 }
356
357 if(keyfile == NULL)
0fe9dd41 358 keyfile = certfile;
cf12678b 359
92404a1a
AJ
360 if(cipher_list == NULL)
361 cipher_list = librb_ciphers;
362
cf12678b
AJ
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
a4c8c827 370 ssl_server_ctx = SSL_CTX_new(TLS_server_method());
92404a1a 371 ssl_client_ctx = SSL_CTX_new(TLS_client_method());
cf12678b
AJ
372 #else
373 ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
92404a1a 374 ssl_client_ctx = SSL_CTX_new(SSLv23_client_method());
cf12678b 375 #endif
a4c8c827 376
db137867
AC
377 if(ssl_server_ctx == NULL)
378 {
379 rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
918d73d5 380 get_ssl_error(ERR_get_error()));
92404a1a 381 return 0;
db137867 382 }
a4c8c827 383
92404a1a
AJ
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 }
a4c8c827 390
92404a1a
AJ
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
a4c8c827 395
92404a1a
AJ
396 #ifdef SSL_OP_SINGLE_DH_USE
397 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_DH_USE);
398 #endif
a4c8c827 399
92404a1a
AJ
400 #ifdef SSL_OP_SINGLE_ECDH_USE
401 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE);
402 #endif
b6e799f5 403
92404a1a
AJ
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
b1f05493 408
92404a1a
AJ
409 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
410 SSL_CTX_set_options(ssl_server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
411 #endif
b1f05493 412
92404a1a
AJ
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);
cf12678b 415
92404a1a
AJ
416 #ifdef LRB_HAVE_TLS_SET_CURVES
417 SSL_CTX_set1_curves_list(ssl_server_ctx, librb_curves);
cf12678b 418 #endif
db137867 419
92404a1a
AJ
420 #ifdef LRB_HAVE_TLS_ECDH_AUTO
421 SSL_CTX_set_ecdh_auto(ssl_server_ctx, 1);
422 #endif
6b6a5799 423
92404a1a
AJ
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);
cf12678b 432 }
92404a1a 433 #endif
db137867 434
cf12678b
AJ
435 SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list);
436 SSL_CTX_set_cipher_list(ssl_client_ctx, cipher_list);
db137867 437
0fe9dd41 438 if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, certfile) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, certfile))
db137867 439 {
0fe9dd41 440 rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", certfile,
cf12678b 441 get_ssl_error(ERR_get_error()));
db137867
AC
442 return 0;
443 }
444
07e14084 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))
db137867 446 {
db137867 447 rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
cf12678b 448 get_ssl_error(ERR_get_error()));
db137867
AC
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 */
3057f91d
AJ
455 FILE *fp = fopen(dhfile, "r");
456 DH *dh = NULL;
457
458 if(fp == NULL)
db137867 459 {
3057f91d
AJ
460 rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
461 dhfile, strerror(errno));
3202e249 462 }
3057f91d 463 else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL)
3202e249 464 {
3202e249 465 rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
3057f91d
AJ
466 dhfile, get_ssl_error(ERR_get_error()));
467 fclose(fp);
468 }
469 else
470 {
471 SSL_CTX_set_tmp_dh(ssl_server_ctx, dh);
472 DH_free(dh);
473 fclose(fp);
db137867
AC
474 }
475 }
c1725bda 476
db137867
AC
477 return 1;
478}
479
480int
aa4737a0 481rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
db137867 482{
aa4737a0
AC
483 int result;
484
485 result = rb_listen(F, backlog, defer_accept);
db137867 486 F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
aa4737a0
AC
487
488 return result;
db137867
AC
489}
490
491struct ssl_connect
492{
493 CNCB *callback;
494 void *data;
495 int timeout;
496};
497
498static void
3202e249 499rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn)
db137867
AC
500{
501 F->connect->callback = sconn->callback;
502 F->connect->data = sconn->data;
503 rb_free(sconn);
504 rb_connect_callback(F, status);
505}
506
507static void
3202e249 508rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data)
db137867
AC
509{
510 rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
511}
512
513static void
3202e249 514rb_ssl_tryconn_cb(rb_fde_t *F, void *data)
db137867
AC
515{
516 struct ssl_connect *sconn = data;
517 int ssl_err;
518 if(!SSL_is_init_finished((SSL *) F->ssl))
519 {
520 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
521 {
522 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
523 {
524 case SSL_ERROR_SYSCALL:
525 if(rb_ignore_errno(errno))
526 case SSL_ERROR_WANT_READ:
527 case SSL_ERROR_WANT_WRITE:
528 {
529 F->ssl_errno = get_last_err();
530 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
531 rb_ssl_tryconn_cb, sconn);
532 return;
533 }
534 default:
535 F->ssl_errno = get_last_err();
536 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
537 return;
538 }
539 }
540 else
541 {
542 rb_ssl_connect_realcb(F, RB_OK, sconn);
543 }
544 }
545}
546
547static void
3202e249 548rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
db137867
AC
549{
550 struct ssl_connect *sconn = data;
551 int ssl_err;
552 if(status != RB_OK)
553 {
554 rb_ssl_connect_realcb(F, status, sconn);
555 return;
556 }
557
558 F->type |= RB_FD_SSL;
559 F->ssl = SSL_new(ssl_client_ctx);
560 SSL_set_fd((SSL *) F->ssl, F->fd);
c2ac22cc 561 rb_setup_ssl_cb(F);
db137867
AC
562 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
563 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
564 {
565 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
566 {
567 case SSL_ERROR_SYSCALL:
568 if(rb_ignore_errno(errno))
569 case SSL_ERROR_WANT_READ:
570 case SSL_ERROR_WANT_WRITE:
571 {
572 F->ssl_errno = get_last_err();
573 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
574 rb_ssl_tryconn_cb, sconn);
575 return;
576 }
577 default:
578 F->ssl_errno = get_last_err();
579 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
580 return;
581 }
582 }
583 else
584 {
585 rb_ssl_connect_realcb(F, RB_OK, sconn);
586 }
587}
588
589void
3202e249 590rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
5ad62c80 591 struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
db137867
AC
592{
593 struct ssl_connect *sconn;
594 if(F == NULL)
595 return;
596
597 sconn = rb_malloc(sizeof(struct ssl_connect));
598 sconn->data = data;
599 sconn->callback = callback;
600 sconn->timeout = timeout;
5ad62c80 601 rb_connect_tcp(F, dest, clocal, rb_ssl_tryconn, sconn, timeout);
db137867
AC
602}
603
604void
3202e249 605rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
db137867
AC
606{
607 struct ssl_connect *sconn;
608 int ssl_err;
609 if(F == NULL)
610 return;
611
612 sconn = rb_malloc(sizeof(struct ssl_connect));
613 sconn->data = data;
614 sconn->callback = callback;
615 sconn->timeout = timeout;
616 F->connect = rb_malloc(sizeof(struct conndata));
617 F->connect->callback = callback;
618 F->connect->data = data;
619 F->type |= RB_FD_SSL;
620 F->ssl = SSL_new(ssl_client_ctx);
3202e249 621
db137867 622 SSL_set_fd((SSL *) F->ssl, F->fd);
c2ac22cc 623 rb_setup_ssl_cb(F);
db137867
AC
624 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
625 if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
626 {
627 switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
628 {
629 case SSL_ERROR_SYSCALL:
630 if(rb_ignore_errno(errno))
631 case SSL_ERROR_WANT_READ:
632 case SSL_ERROR_WANT_WRITE:
633 {
634 F->ssl_errno = get_last_err();
635 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
636 rb_ssl_tryconn_cb, sconn);
637 return;
638 }
639 default:
640 F->ssl_errno = get_last_err();
641 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
642 return;
643 }
644 }
645 else
646 {
647 rb_ssl_connect_realcb(F, RB_OK, sconn);
648 }
649}
650
651int
652rb_init_prng(const char *path, prng_seed_t seed_type)
653{
654 if(seed_type == RB_PRNG_DEFAULT)
655 {
3202e249 656#ifdef _WIN32
db137867
AC
657 RAND_screen();
658#endif
659 return RAND_status();
660 }
661 if(path == NULL)
662 return RAND_status();
663
664 switch (seed_type)
665 {
db137867
AC
666 case RB_PRNG_FILE:
667 if(RAND_load_file(path, -1) == -1)
668 return -1;
669 break;
3202e249 670#ifdef _WIN32
db137867
AC
671 case RB_PRNGWIN32:
672 RAND_screen();
673 break;
674#endif
675 default:
676 return -1;
677 }
678
679 return RAND_status();
680}
681
682int
683rb_get_random(void *buf, size_t length)
684{
a9fb3ed0 685 int ret;
3202e249 686
a9fb3ed0 687 if((ret = RAND_bytes(buf, length)) == 0)
db137867 688 {
a9fb3ed0 689 /* remove the error from the queue */
3202e249 690 ERR_get_error();
db137867 691 }
a9fb3ed0 692 return ret;
db137867
AC
693}
694
db137867 695const char *
3202e249 696rb_get_ssl_strerror(rb_fde_t *F)
db137867 697{
918d73d5 698 return get_ssl_error(F->ssl_errno);
db137867
AC
699}
700
e3760ba7 701static int
03469187
SA
702make_certfp(X509 *cert, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
703{
704 const ASN1_ITEM *it;
705 const EVP_MD *evp;
706 void *data;
b28c26d9 707 unsigned int len;
03469187
SA
708
709 switch(method)
710 {
711 case RB_SSL_CERTFP_METH_CERT_SHA1:
712 it = ASN1_ITEM_rptr(X509);
713 evp = EVP_sha1();
714 data = cert;
715 len = RB_SSL_CERTFP_LEN_SHA1;
716 break;
717 case RB_SSL_CERTFP_METH_CERT_SHA256:
718 it = ASN1_ITEM_rptr(X509);
719 evp = EVP_sha256();
720 data = cert;
721 len = RB_SSL_CERTFP_LEN_SHA256;
722 break;
723 case RB_SSL_CERTFP_METH_CERT_SHA512:
724 it = ASN1_ITEM_rptr(X509);
725 evp = EVP_sha512();
726 data = cert;
727 len = RB_SSL_CERTFP_LEN_SHA512;
728 break;
729 case RB_SSL_CERTFP_METH_SPKI_SHA256:
730 it = ASN1_ITEM_rptr(X509_PUBKEY);
731 evp = EVP_sha256();
732 data = X509_get_X509_PUBKEY(cert);
733 len = RB_SSL_CERTFP_LEN_SHA256;
734 break;
735 case RB_SSL_CERTFP_METH_SPKI_SHA512:
736 it = ASN1_ITEM_rptr(X509_PUBKEY);
737 evp = EVP_sha512();
738 data = X509_get_X509_PUBKEY(cert);
739 len = RB_SSL_CERTFP_LEN_SHA512;
740 break;
741 default:
742 return 0;
743 }
744
745 if (ASN1_item_digest(it, evp, data, certfp, &len) != 1)
746 len = 0;
b28c26d9 747 return (int) len;
03469187
SA
748}
749
7247337a 750int
e6bbb410 751rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
7247337a 752{
e3760ba7 753 int len = 0;
7247337a
JT
754 X509 *cert;
755 int res;
756
757 if (F->ssl == NULL)
758 return 0;
759
760 cert = SSL_get_peer_certificate((SSL *) F->ssl);
e3760ba7
AJ
761 if(cert == NULL)
762 return 0;
763
764 res = SSL_get_verify_result((SSL *) F->ssl);
765 switch(res)
7247337a 766 {
e3760ba7
AJ
767 case X509_V_OK:
768 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
769 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
770 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
771 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
772 case X509_V_ERR_CERT_UNTRUSTED:
773 len = make_certfp(cert, certfp, method);
774
775 default: /* to silence code inspectors */
776 break;
7247337a
JT
777 }
778
e3760ba7
AJ
779 X509_free(cert);
780 return len;
7247337a
JT
781}
782
03469187
SA
783int
784rb_get_ssl_certfp_file(const char *filename, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
785{
786 X509 *cert;
787 FILE *f = fopen(filename, "r");
788
789 if (!f)
790 return -1;
791
792 cert = PEM_read_X509(f, NULL, NULL, NULL);
793 fclose(f);
794
795 if (cert) {
796 unsigned int len = make_certfp(cert, certfp, method);
797 X509_free(cert);
798 return len;
799 }
800 return 0;
801}
802
db137867
AC
803int
804rb_supports_ssl(void)
805{
806 return 1;
807}
808
030272f3
VY
809void
810rb_get_ssl_info(char *buf, size_t len)
811{
c40eede1
AJ
812#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
813 if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER)
814 snprintf(buf, len, "OpenSSL: 0x%lx, %s",
815 OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT);
816 else
817 snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
818 OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
819 OpenSSL_version_num(), OpenSSL_version(OPENSSL_VERSION));
820#else
821 if (SSLeay() == SSLEAY_VERSION_NUMBER)
822 snprintf(buf, len, "OpenSSL: 0x%lx, %s",
823 SSLeay(), SSLeay_version(SSLEAY_VERSION));
824 else
825 snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
826 SSLEAY_VERSION_NUMBER, "???",
827 SSLeay(), SSLeay_version(SSLEAY_VERSION));
828#endif
030272f3
VY
829}
830
833b2f9c
AC
831const char *
832rb_ssl_get_cipher(rb_fde_t *F)
833{
834 const SSL_CIPHER *sslciph;
835
836 if(F == NULL || F->ssl == NULL)
837 return NULL;
838
839 if((sslciph = SSL_get_current_cipher(F->ssl)) == NULL)
840 return NULL;
841
842 return SSL_CIPHER_get_name(sslciph);
843}
030272f3 844
b1f05493 845#endif /* HAVE_OPENSSL */