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