2 * IRC - Internet Relay Chat, ircd/ssl.c
3 * Written by David Herrmann.
8 * This SSL module is created to be as generic as possible.
9 * That is, it is easy to add new backends. We currently support
12 * The module is built up to encrypt all kinds of network connections.
13 * You have to create your socket yourself and accept() or connect() it.
14 * The new connected socket has to be passed to this module which then
15 * initiates a secure connection. While initiating this connection the
16 * socket is kept in a separate queue inside this module. When the
17 * connection has been fully established, the client is passed back to
18 * the add_connection() function which then passes the client to the
19 * authentication module. You can handle the client equally to a normal
20 * unencrypted connection, however, the send()/recv() functions have
21 * to be changed to the functions provided by this module.
23 * The first part of this file defines the backend functions. Only one
24 * backend can be enabled at one time. Please add your own backends there.
32 #include "ircd_defs.h"
33 #include "ircd_events.h"
34 #include "ircd_snprintf.h"
35 #include "ircd_osdep.h"
36 #include "ircd_alloc.h"
54 /* Backend declarations.
55 * Please add your backend here. I recommend to leave GnuTLS as the first choice
56 * because it is tested most and works perfectly. You can change the backend with
57 * the configure script at compile time.
59 * Each backend has to declare the following functions:
60 * - ssl_be_init(): This is called when the SSL library should be initialized.
61 * - ssl_be_deinit(): This is called when the SSL library should be deinitialized.
62 * - ssl_be_cred_new(): This should create a new credentials structure.
63 * - ssl_be_cred_free(): This should free a previously allocated credentials structure.
64 * - ssl_be_session_new(): This should create a new session.
65 * - ssl_be_session_connect(): This connects a session with an FD.
66 * - ssl_be_session_shutdown(): This should shutdown the Write-Endpoint of a session.
67 * - ssl_be_session_free(): This should free a session.
68 * - ssl_be_handshake(): This should start/continue the protocol handshake.
69 * - ssl_be_send(): This should send data over the connection.
70 * - ssl_be_recv(): This should receive data from the connection.
71 * - ssl_be_cipherstr(): This should return a string representing the used cipher.
72 * - ssl_be_fingerprint(): Validates the peer's socket and returns the fingerprint on success.
74 * You should declare the backend specific functions at the end of this files. At this
75 * point, every backend has to define the ssl_be_cred_t and ssl_be_session_t structures which
76 * represent the credentials and session values used by the backend.
78 * Please use the namespace "ssl_be_" in your backend only! All other names may collide
80 * Furthermore look into the dummy to see which checks are already done by the main module
81 * and what you do not have to do in your backend.
85 #if defined(HAVE_GNUTLS)
87 * GnuTLS is licensed under the LGPL and developed by the GNU project.
88 * This backend is recommended and tested by the developers of this module.
90 #include <gnutls/gnutls.h>
92 gnutls_certificate_credentials_t cred;
93 gnutls_dh_params_t dhparams;
94 gnutls_priority_t prio;
96 typedef gnutls_session_t ssl_be_session_t;
97 #elif defined(HAVE_OPENSSL)
99 * OpenSSL is developed by independant people and a de-facto standard in the
100 * industry. However, the source is *bad* and it has had many bugs in the
101 * past. We do not recommend this module!
103 /* On some systems, these headers also include the OpenSSL md5 header
104 * which itself defines MD5_CTX. This is already defined in ircd_md5.h,
105 * hence, we prevent this inclusion here.
106 * This fix is really *BAD* but since OpenSSL does not use "namespaces"/
107 * "prefixes" there is currently no other solution.
110 #include <openssl/ssl.h>
111 #include <openssl/err.h>
112 #include <openssl/rand.h>
113 typedef SSL_CTX* ssl_be_cred_t;
114 typedef SSL* ssl_be_session_t;
115 static signed int ssl_be_verify(signed int preverify_ok, X509_STORE_CTX *ctx);
118 * No backend available. We simply declare fake structures here and handle
119 * the connections unencrypted.
121 typedef void* ssl_be_cred_t;
122 typedef void* ssl_be_session_t;
126 /* SSL credentials (cred).
127 * An SSL credential is a specific certificate which can be used in many SSL
128 * sessions. However, we want to allow to change the certificate at runtime,
129 * therefore, we allow several credentials at one time. A new credential is
130 * created on /rehash when the certificate changed and then the old creds are
131 * marked for removal. New clients are connected with the new credential so we
132 * can remove the old creds when there are no more connected clients with this
134 * A cred can either be for accepting clients or for connecting yourself as
135 * client. We support both, that is, server<->server encryption is also supported.
136 * The global creds are stored separated in two single linked lists. If the lists
137 * are empty, then no credential has been loaded yet and a new one will be created
138 * when a client connects.
139 * Thus, only the first credential in this list should be used for new connections,
140 * all other credentials are marked for removal.
144 struct ssl_cred_t *next;
149 struct ssl_cred_t *ssl_cli_credlist = NULL;
150 struct ssl_cred_t *ssl_srv_credlist = NULL;
154 * A session contains all data that is needed by the SSL backend. We also link
155 * the session to the used credentials to be able to modify the cred when we
156 * modify the session.
157 * \fingerprint is NULL when the peer's certificate is not trusted. If it is
158 * trusted, then \fingerprint points to a string containing the fingerprint of
159 * the peer's certificate.
161 struct ssl_session_t;
162 struct ssl_session_t {
163 struct ssl_cred_t *cred;
169 /* Represents an SSL connection whose handshake is currently pending.
170 * If a client connects, it is accepted and then put into the handshake queue.
171 * If the handshake timeouts he is rejected, otherwise he is put into the
172 * usual user-queue and the auth module continues.
173 * This structure is only used in the handshake-queue of accepted SSL clients.
175 * ssl_conn_t is the pending outgoing connection. The handshake is performed
176 * in this state and then returned to the main module when done. This is handled
177 * separately to the client connections.
179 struct ssl_pending_t {
180 ssl_session_t *session;
181 struct Socket socket;
182 struct Timer timeout;
184 struct Listener *listener;
187 ssl_session_t *session;
188 struct Timer timeout;
194 /* Backend functions.
195 * See the comment near the top of this file for information on these functions.
197 unsigned int ssl_be_init();
198 void ssl_be_deinit();
199 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred);
200 void ssl_be_cred_free(ssl_be_cred_t *cred);
201 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session);
202 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd);
203 void ssl_be_session_shutdown(ssl_be_session_t *session);
204 void ssl_be_session_free(ssl_be_session_t *session);
205 #define SSL_NEED_WR 0
206 #define SSL_NEED_RD 1
207 #define SSL_NEED_RDWR 2
208 #define SSL_FAILURE 3
209 #define SSL_SUCCESS 4
210 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session);
211 const char *ssl_be_cipherstr(ssl_be_session_t *session);
212 const char *ssl_be_fingerprint(ssl_be_session_t *session);
213 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out);
214 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out);
217 /* Path to the certificate to use. */
218 char *ssl_cert = NULL;
219 char **ssl_trusts = NULL;
220 void ssl_setcert(const char *cert) {
222 ssl_cert = strdup(cert);
224 void ssl_clearcert() {
228 void ssl_addtrust(const char *trust) {
233 while(ssl_trusts[i]) ++i;
234 tmp = MyMalloc(sizeof(char*) * (i + 2));
236 while(ssl_trusts[i]) {
237 tmp[i] = ssl_trusts[i];
240 tmp[i] = strdup(trust);
246 tmp = MyMalloc(sizeof(char*) * 2);
247 tmp[0] = strdup(trust);
252 void ssl_cleartrusts() {
256 while(ssl_trusts[i]) {
257 MyFree(ssl_trusts[i]);
266 /* This handles SSL messages.
267 * It writes the message to the logfile and prints it on the screen if debugmode is
273 static void ssl_msg(unsigned int type, const char *msg, ...) {
278 #define SSL_DEBUGMSG(x, y, z) vdebug((x), (y), (z))
280 #define SSL_DEBUGMSG(x, y, z)
284 log_vwrite(LS_SYSTEM, L_NOTICE, 0, msg, list);
285 SSL_DEBUGMSG(DEBUG_NOTICE, msg, list);
288 log_vwrite(LS_SYSTEM, L_CRIT, 0, msg, list);
289 SSL_DEBUGMSG(DEBUG_FATAL, msg, list);
292 SSL_DEBUGMSG(DEBUG_DEBUG, msg, list);
299 /* Initializes or Deinitializes the SSL module. */
300 static unsigned int ssl_loaded = 0;
303 ssl_msg(SSL_ERROR, "SSL: ssl_init(): called twice");
308 ssl_msg(SSL_NOTICE, "SSL: ssl_init(): done");
310 else ssl_msg(SSL_ERROR, "SSL: ssl_be_deinit(): failed");
314 ssl_msg(SSL_ERROR, "SSL: ssl_deinit(): not initialized");
318 /* Check whether there are active SSL connections.
319 * That is, the credentials-list must either be empty or contain only
320 * one credential with ZERO references which then is deleted.
322 if((ssl_srv_credlist && (ssl_srv_credlist->next || ssl_srv_credlist->ref)) ||
323 (ssl_cli_credlist && (ssl_cli_credlist->next || ssl_cli_credlist->ref))) {
324 ssl_msg(SSL_ERROR, "SSL: ssl_deinit(): still active sessions");
327 if(ssl_srv_credlist) ssl_cred_free(ssl_srv_credlist);
328 if(ssl_cli_credlist) ssl_cred_free(ssl_cli_credlist);
334 ssl_msg(SSL_NOTICE, "SSL: ssl_deinit(): done");
339 /* Creates/Frees a credential. */
340 ssl_cred_t *ssl_cred_new(unsigned int mode, char *cert, char **trusts) {
343 cred = MyMalloc(sizeof(ssl_cred_t));
344 memset(cred, 0, sizeof(ssl_cred_t));
346 if(!ssl_be_cred_new(mode, cert, trusts, &cred->be)) {
347 ssl_msg(SSL_ERROR, "SSL: ssl_be_cred_new(): failed.");
352 if(mode == SSL_CLIENT) {
353 if(ssl_cli_credlist && ssl_cli_credlist->ref == 0) ssl_cred_free(ssl_cli_credlist);
354 cred->next = ssl_cli_credlist;
355 ssl_cli_credlist = cred;
358 if(ssl_srv_credlist && ssl_srv_credlist->ref == 0) ssl_cred_free(ssl_srv_credlist);
359 cred->next = ssl_srv_credlist;
360 ssl_srv_credlist = cred;
364 ssl_msg(SSL_NOTICE, "SSL: ssl_cred_new(%u, '%s'): done", mode, cert);
367 void ssl_cred_free(ssl_cred_t *cred) {
371 ssl_msg(SSL_ERROR, "SSL: ssl_cred_free(%u, %u): still active sessions", cred->mode, cred->ref);
375 if(cred->mode == SSL_CLIENT) {
376 iter = ssl_cli_credlist;
378 ssl_cli_credlist = iter->next;
382 if(iter->next == cred) {
383 iter->next = cred->next;
387 ssl_msg(SSL_ERROR, "SSL: ssl_cred_free(): invalid cred");
391 iter = ssl_srv_credlist;
393 ssl_srv_credlist = iter->next;
397 if(iter->next == cred) {
398 iter->next = cred->next;
402 ssl_msg(SSL_ERROR, "SSL: ssl_cred_free(): invalid cred");
407 ssl_be_cred_free(&cred->be);
408 ssl_msg(SSL_NOTICE, "SSL: ssl_cred_free(%u): done", cred->mode);
413 /* Manipulates an SSL session. */
414 ssl_session_t *ssl_session_new(unsigned int mode) {
416 char **trusts, *fallback[1] = { NULL };
418 /* If no SSL certificate is set, we stop.
419 * We also clear \ssl_cert when allocating the certificate fails.
420 * This prevents the ircd from reallocating the credentials everytime
421 * a client connects although the allocation is guaranteed to fail.
423 if(!ssl_cert) return NULL;
424 if(ssl_trusts) trusts = ssl_trusts;
425 else trusts = fallback;
427 ssl = MyMalloc(sizeof(ssl_session_t));
428 memset(ssl, 0, sizeof(ssl_session_t));
429 ssl->fingerprint = NULL;
431 if(mode == SSL_CLIENT) {
432 if(ssl_cli_credlist) ssl->cred = ssl_cli_credlist;
433 else if(!(ssl->cred = ssl_cred_new(SSL_CLIENT, ssl_cert, trusts))) {
437 ssl_msg(SSL_ERROR, "SSL: ssl_session_new(%u): failed", mode);
442 if(ssl_srv_credlist) ssl->cred = ssl_srv_credlist;
443 else if(!(ssl->cred = ssl_cred_new(SSL_SERVER, ssl_cert, trusts))) {
447 ssl_msg(SSL_ERROR, "SSL: ssl_session_new(%u): failed", mode);
452 if(!ssl_be_session_new(mode, &ssl->cred->be, &ssl->be)) {
453 /* Keep credentials. They may be used later. */
455 ssl_msg(SSL_ERROR, "SSL: ssl_session_new(%u): failed", mode);
460 ssl_msg(SSL_DEBUG, "SSL: ssl_session_new(%u): done", mode);
463 void ssl_session_shutdown(ssl_session_t *ssl) {
464 /* We do not care for the return value here. This might be implemented
465 * in future. This makes ssl_shutdown() totally useless but this is only
466 * a placeholder for future implementations.
468 ssl_be_session_shutdown(&ssl->be);
470 void ssl_session_free(ssl_session_t *ssl) {
471 ssl_be_session_free(&ssl->be);
473 /* Check whether to free the credentials. */
474 if(--ssl->cred->ref == 0) {
475 if(ssl_cli_credlist != ssl->cred && ssl_srv_credlist != ssl->cred) {
476 ssl_cred_free(ssl->cred);
480 ssl_msg(SSL_DEBUG, "SSL: ssl_session_free(%u): done", ssl->cred->mode);
481 MyFree(ssl->fingerprint);
486 /* This handles a new client connection. It puts the client into the SSL queue and
487 * performs the SSL handshake. It either disconnects the client or passes the client
488 * to add_connection() after the handshake has been performed.
490 * We use two callbacks. One for the timeout and one for the socket. To prevent that
491 * both callbacks remove the ssl_pending_t structure or that they remove it too early
492 * we remove the structure only when the socket has been set to -1. This security check
493 * is needed, you should *NEVER* remove it.
495 static void ssl_socket_callback(struct Event* ev) {
496 struct ssl_pending_t *pend;
499 pend = s_data(ev_socket(ev));
500 switch(ev_type(ev)) {
502 if(pend->fd == -1) MyFree(pend);
506 ssl_session_shutdown(pend->session);
508 ssl_session_free(pend->session);
509 socket_del(&pend->socket);
510 timer_del(&pend->timeout);
511 /* Set fd to -1 to make ET_DESTROY free "pend". */
516 /* Continue Handshake */
517 ret = ssl_be_handshake(pend->session->cred->mode, &pend->session->be);
518 if(ret == SSL_SUCCESS) {
519 pend->session->fingerprint = strdup(ssl_be_fingerprint(&pend->session->be));
520 timer_del(&pend->timeout);
521 socket_del(&pend->socket);
522 add_connection(pend->listener, pend->fd, pend->session);
523 /* Set fd to -1 to make ET_DESTROY free "pend". */
527 else if(ret == SSL_NEED_RD) {
528 socket_events(&pend->socket, SOCK_ACTION_SET | SOCK_EVENT_READABLE);
531 else if(ret == SSL_NEED_WR || ret == SSL_NEED_RDWR) {
532 socket_events(&pend->socket, SOCK_ACTION_SET | SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE);
535 else /* SSL_FAILURE */ {
536 ssl_session_shutdown(pend->session);
538 ssl_session_free(pend->session);
539 socket_del(&pend->socket);
540 timer_del(&pend->timeout);
541 /* Set fd to -1 to make ET_DESTROY free "pend". */
549 static void ssl_timer_callback(struct Event* ev) {
550 struct ssl_pending_t *pend;
552 pend = t_data(ev_timer(ev));
553 switch(ev_type(ev)) {
555 /* Decrease refcount here because this is guaranteed to be called when the
556 * connection gets destructed in any way.
558 --pend->listener->ref_count;
559 /* Destruct \pend if required. */
560 if(pend->fd == -1) MyFree(pend);
563 ssl_session_shutdown(pend->session);
565 ssl_session_free(pend->session);
566 socket_del(&pend->socket);
567 timer_del(&pend->timeout);
568 /* Set fd to -1 to make ET_DESTROY free "pend". */
575 void ssl_accept(struct Listener *listener, signed int fd) {
577 struct ssl_pending_t *pend;
579 if(!os_set_nonblocking(fd)) {
583 os_disable_options(fd);
585 pend = MyMalloc(sizeof(struct ssl_pending_t));
586 pend->listener = listener;
588 pend->session = ssl_session_new(SSL_SERVER);
593 ssl_msg(SSL_ERROR, "SSL: ssl_accept(%d): failed", fd);
597 if(!socket_add(&pend->socket, ssl_socket_callback, (void*)pend, SS_CONNECTED, SOCK_EVENT_READABLE, fd)) {
598 ssl_session_shutdown(pend->session);
600 ssl_session_free(pend->session);
602 ssl_msg(SSL_ERROR, "SSL: ssl_accept(%d): failed", fd);
606 if(!ssl_be_session_connect(&pend->session->be, fd)) {
607 socket_del(&pend->socket);
608 ssl_session_shutdown(pend->session);
610 ssl_session_free(pend->session);
612 ssl_msg(SSL_ERROR, "SSL: ssl_accept(%d): failed", fd);
616 ret = ssl_be_handshake(pend->session->cred->mode, &pend->session->be);
617 if(ret == SSL_SUCCESS) {
618 pend->session->fingerprint = strdup(ssl_be_fingerprint(&pend->session->be));
619 socket_del(&pend->socket);
620 add_connection(pend->listener, pend->fd, pend->session);
624 else if(ret == SSL_NEED_RD || ret == SSL_NEED_WR || ret == SSL_NEED_RDWR) {
625 if(ret != SSL_NEED_RD) {
626 socket_events(&pend->socket, SOCK_ACTION_SET | SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE);
628 timer_init(&pend->timeout);
629 timer_add(&pend->timeout, ssl_timer_callback, (void*)pend, TT_RELATIVE, 20);
630 ++listener->ref_count;
633 else /* SSL_FAILURE */ {
634 socket_del(&pend->socket);
635 ssl_session_shutdown(pend->session);
637 ssl_session_free(pend->session);
639 ssl_msg(SSL_DEBUG, "SSL: ssl_accept(%d): failed", fd);
643 static void ssl_csocket_callback(struct Event* ev) {
644 struct ssl_conn_t *conn;
647 conn = s_data(ev_socket(ev));
648 switch(ev_type(ev)) {
653 cli_socket(conn->cptr).s_header.gh_call = client_sock_callback;
654 s_data(&(cli_socket(conn->cptr))) = conn->olddata;
655 ssl_session_free(conn->session);
656 cli_socket(conn->cptr).ssl = NULL;
657 exit_client_msg(conn->cptr, conn->cptr, &me, "SSL connection timedout.");
658 sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: SSL timeout.", cli_name(conn->cptr));
660 timer_del(&conn->timeout);
664 /* Continue Handshake */
665 ret = ssl_be_handshake(conn->session->cred->mode, &conn->session->be);
666 if(ret == SSL_SUCCESS) {
667 cli_socket(conn->cptr).s_header.gh_call = client_sock_callback;
668 s_data(&(cli_socket(conn->cptr))) = conn->olddata;
669 conn->session->fingerprint = strdup(ssl_be_fingerprint(&conn->session->be));
670 if(completed_connection(conn->cptr) == 0) {
671 ssl_session_free(conn->session);
672 cli_socket(conn->cptr).ssl = NULL;
673 exit_client_msg(conn->cptr, conn->cptr, &me, "SSL handshake rejected.");
676 timer_del(&conn->timeout);
679 else if(ret == SSL_NEED_RD) {
680 socket_events(&cli_socket(conn->cptr), SOCK_ACTION_SET | SOCK_EVENT_READABLE);
683 else if(ret == SSL_NEED_WR || ret == SSL_NEED_RDWR) {
684 socket_events(&cli_socket(conn->cptr), SOCK_ACTION_SET | SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE);
687 else /* SSL_FAILURE */ {
688 cli_socket(conn->cptr).s_header.gh_call = client_sock_callback;
689 s_data(&(cli_socket(conn->cptr))) = conn->olddata;
690 ssl_session_free(conn->session);
691 cli_socket(conn->cptr).ssl = NULL;
692 exit_client_msg(conn->cptr, conn->cptr, &me, "SSL connection timedout.");
693 sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: SSL timeout.", cli_name(conn->cptr));
695 timer_del(&conn->timeout);
702 static void ssl_ctimer_callback(struct Event* ev) {
703 struct ssl_conn_t *conn;
705 conn = t_data(ev_timer(ev));
706 switch(ev_type(ev)) {
708 if(conn->cptr == NULL) MyFree(conn);
711 cli_socket(conn->cptr).s_header.gh_call = client_sock_callback;
712 s_data(&(cli_socket(conn->cptr))) = conn->olddata;
713 ssl_session_free(conn->session);
714 cli_socket(conn->cptr).ssl = NULL;
715 exit_client_msg(conn->cptr, conn->cptr, &me, "SSL connection timedout.");
716 sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: SSL timeout.", cli_name(conn->cptr));
718 timer_del(&conn->timeout);
724 signed int ssl_connect(struct Client *cptr) {
725 struct ssl_conn_t *conn;
729 conn = MyMalloc(sizeof(struct ssl_conn_t));
730 memset(conn, 0, sizeof(struct ssl_conn_t));
733 conn->session = ssl_session_new(SSL_CLIENT);
734 cli_socket(cptr).ssl = conn->session;
737 cli_socket(cptr).ssl = NULL;
739 ssl_msg(SSL_ERROR, "SSL: ssl_connect(): failed");
740 sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: SSL session-creation failed.", cli_name(cptr));
744 if(!ssl_be_session_connect(&conn->session->be, s_fd(&(cli_socket(cptr))))) {
745 cli_socket(cptr).ssl = NULL;
746 ssl_session_free(conn->session);
748 ssl_msg(SSL_ERROR, "SSL: ssl_connect(): failed");
749 sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: SSL fd-connect failed.", cli_name(cptr));
753 ret = ssl_be_handshake(conn->session->cred->mode, &conn->session->be);
754 if(ret == SSL_SUCCESS) {
755 conn->session->fingerprint = strdup(ssl_be_fingerprint(&conn->session->be));
756 tmp = completed_connection(cptr);
760 else if(ret == SSL_NEED_RD || ret == SSL_NEED_WR || ret == SSL_NEED_RDWR) {
761 if(ret == SSL_NEED_RD) {
762 socket_events(&cli_socket(cptr), SOCK_ACTION_SET | SOCK_EVENT_READABLE);
765 socket_events(&cli_socket(cptr), SOCK_ACTION_SET | SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE);
767 /* Change callback temporarily to avoid ET_DESTROY on the old callback.
768 * We will change this back before ET_DESTROY is called.
770 cli_socket(cptr).s_header.gh_call = ssl_csocket_callback;
771 conn->olddata = s_data(&(cli_socket(cptr)));
772 s_data(&(cli_socket(cptr))) = conn;
773 timer_init(&conn->timeout);
774 timer_add(&conn->timeout, ssl_ctimer_callback, (void*)conn, TT_RELATIVE, 20);
777 else /* SSL_FAILURE */ {
778 cli_socket(cptr).ssl = NULL;
779 ssl_session_free(conn->session);
781 ssl_msg(SSL_ERROR, "SSL: ssl_connect(): failed");
782 sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: SSL handshake failed.", cli_name(cptr));
789 /* Basic IO on SSL sockets. */
790 void ssl_close(signed int fd, ssl_session_t *ssl, const char *buf, unsigned int len) {
796 ssl_be_send(fd, &ssl->be, buf, &len);
797 ssl_session_shutdown(ssl);
799 ssl_session_free(ssl);
802 signed int ssl_send(signed int fd, ssl_session_t *ssl, const char *buf, unsigned int len) {
804 return write(fd, buf, len);
807 ssl_be_send(fd, &ssl->be, buf, &len);
811 IOResult ssl_recv(signed int fd, ssl_session_t *ssl, char *buf, unsigned int len, unsigned int *count_out) {
813 return os_recv_nonb(fd, buf, len, count_out);
816 return ssl_be_recv(fd, &ssl->be, buf, count_out);
818 IOResult ssl_sendv(signed int fd, ssl_session_t *ssl, struct MsgQ *buf, unsigned int *count_in, unsigned int *count_out) {
824 struct iovec iov[IOV_MAX];
825 IOResult ret = IO_BLOCKED, res;
828 return os_sendv_nonb(fd, buf, count_in, count_out);
833 count = msgq_mapiov(buf, iov, IOV_MAX, count_in);
835 for(k = 0; k < count; ++k) {
836 tmp = iov[k].iov_len;
837 res = ssl_be_send(fd, &ssl->be, iov[k].iov_base, &tmp);
838 if(res == IO_FAILURE) return IO_FAILURE;
839 else if(tmp == 0) return ret;
847 const char *ssl_cipherstr(ssl_session_t *ssl) {
848 return ssl_be_cipherstr(&ssl->be);
854 /*******************************************************************************/
855 /*******************************************************************************/
856 /*******************************************************************************/
857 /*******************************************************************************/
858 /*******************************************************************************/
859 /********************** GnuTLS backend *****************/
860 /*******************************************************************************/
861 /*******************************************************************************/
862 /*******************************************************************************/
863 /*******************************************************************************/
864 /*******************************************************************************/
869 #if defined(HAVE_GNUTLS)
871 unsigned int ssl_be_init() {
873 if((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS) {
874 ssl_msg(SSL_ERROR, "SSL: gnutls_global_init(): failed (%d)", ret);
879 void ssl_be_deinit() {
880 gnutls_global_deinit();
882 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred) {
885 if((ret = gnutls_dh_params_init(&cred->dhparams)) != GNUTLS_E_SUCCESS) {
886 ssl_msg(SSL_ERROR, "SSL: gnutls_dh_params_init(): failed (%d)", ret);
889 if((ret = gnutls_dh_params_generate2(cred->dhparams, SSL_DH_BITS)) != GNUTLS_E_SUCCESS) {
890 gnutls_dh_params_deinit(cred->dhparams);
891 ssl_msg(SSL_ERROR, "SSL: gnutls_dh_params_generate2(): failed (%d)", ret);
894 if((ret = gnutls_certificate_allocate_credentials(&cred->cred)) != GNUTLS_E_SUCCESS) {
895 gnutls_dh_params_deinit(cred->dhparams);
896 ssl_msg(SSL_ERROR, "SSL: gnutls_certificate_allocate_credentials(): failed (%d)", ret);
901 if((ret = gnutls_certificate_set_x509_trust_file(cred->cred, trusts[i], GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS) {
902 ssl_msg(SSL_NOTICE, "SSL: gnutls_certificate_set_x509_trust_file('%s'): failed (%d)", trusts[i], ret);
903 /* ignore errors here */
907 if((ret = gnutls_certificate_set_x509_key_file(cred->cred, cert, cert, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS) {
908 gnutls_certificate_free_credentials(cred->cred);
909 gnutls_dh_params_deinit(cred->dhparams);
910 ssl_msg(SSL_NOTICE, "SSL: gnutls_certificate_set_x509_key_file('%s'): failed (%d)", cert, ret);
913 gnutls_certificate_set_dh_params(cred->cred, cred->dhparams);
914 gnutls_priority_init(&cred->prio, "NORMAL", NULL);
917 void ssl_be_cred_free(ssl_be_cred_t *cred) {
918 gnutls_certificate_free_credentials(cred->cred);
919 gnutls_priority_deinit(cred->prio);
920 gnutls_dh_params_deinit(cred->dhparams);
922 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session) {
924 if(mode == SSL_CLIENT) {
925 if((ret = gnutls_init(session, GNUTLS_CLIENT)) != GNUTLS_E_SUCCESS) {
926 ssl_msg(SSL_ERROR, "SSL: gnutls_init(): failed (%d)", ret);
929 gnutls_priority_set(*session, cred->prio);
930 /*if((ret = gnutls_priority_set_direct(*session, "NORMAL", NULL)) != GNUTLS_E_SUCCESS) {
931 gnutls_deinit(*session);
932 ssl_msg(SSL_ERROR, "SSL: gnutls_priority_set_direct(): failed (%d)", ret);
935 if((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, cred->cred)) != GNUTLS_E_SUCCESS) {
936 gnutls_deinit(*session);
937 ssl_msg(SSL_ERROR, "SSL: gnutls_credentials_set(): failed (%d)", ret);
940 gnutls_dh_set_prime_bits(*session, SSL_DH_RBITS);
943 if((ret = gnutls_init(session, GNUTLS_SERVER)) != GNUTLS_E_SUCCESS) {
944 ssl_msg(SSL_ERROR, "SSL: gnutls_init(): failed (%d)", ret);
947 gnutls_priority_set(*session, cred->prio);
948 /*if((ret = gnutls_priority_set_direct(*session, "NORMAL", NULL)) != GNUTLS_E_SUCCESS) {
949 gnutls_deinit(*session);
950 ssl_msg(SSL_ERROR, "SSL: gnutls_priority_set_direct(): failed (%d)", ret);
953 if((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, cred->cred)) != GNUTLS_E_SUCCESS) {
954 gnutls_deinit(*session);
955 ssl_msg(SSL_ERROR, "SSL: gnutls_credentials_set(): failed (%d)", ret);
958 gnutls_certificate_server_set_request(*session, GNUTLS_CERT_REQUEST);
962 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd) {
963 gnutls_transport_set_ptr(*session, (gnutls_transport_ptr_t)fd);
966 void ssl_be_session_shutdown(ssl_be_session_t *session) {
967 gnutls_bye(*session, GNUTLS_SHUT_WR);
969 void ssl_be_session_free(ssl_be_session_t *session) {
970 gnutls_deinit(*session);
972 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session) {
974 ret = gnutls_handshake(*session);
976 if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
977 if(gnutls_record_get_direction(*session) == 0) return SSL_NEED_RD;
978 else return SSL_NEED_WR;
981 ssl_msg(SSL_DEBUG, "SSL: gnutls_handshake(): failed (%d)", ret);
985 else return SSL_SUCCESS;
987 const char *ssl_be_cipherstr(ssl_be_session_t *session) {
988 static char buf[401];
989 const char *kx_name, *cipher_name, *mac_name;
993 kx_name = gnutls_kx_get_name(gnutls_kx_get(*session));
994 cipher_name = gnutls_cipher_get_name(gnutls_cipher_get(*session));
995 mac_name = gnutls_mac_get_name(gnutls_mac_get(*session));
997 if(!kx_name || !cipher_name || !mac_name) {
998 ssl_msg(SSL_ERROR, "SSL: gnutls_[kx,cipher,mac]_get_name(): failed");
1002 len = strlen(kx_name) + strlen(cipher_name) + strlen(mac_name);
1004 ssl_msg(SSL_ERROR, "SSL: gnutls_[kx,cipher,mac]_get_name(): too long");
1010 while((*dest++ = kx_name[i++])) /* empty */ ;
1013 while((*dest++ = cipher_name[i++])) /* empty */ ;
1016 while((*dest++ = mac_name[i++])) /* empty */ ;
1020 const char *ssl_be_fingerprint(ssl_be_session_t *session) {
1023 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out) {
1025 res = gnutls_record_send(*ssl, buf, *count_out);
1028 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_send(): failed (IO_FAILURE)");
1032 if(res != GNUTLS_E_AGAIN && res != GNUTLS_E_INTERRUPTED) {
1033 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_send(): failed (IO_FAILURE)");
1036 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_send(): failed (IO_BLOCKED)");
1042 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_send(): successful (IO_SUCCESS)");
1046 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out) {
1048 res = gnutls_record_recv(*ssl, buf, *count_out);
1051 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_recv(): failed (IO_FAILURE)");
1055 if(res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) {
1056 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_recv(): failed (IO_BLOCKED)");
1059 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_recv(): failed (IO_FAILURE)");
1065 ssl_msg(SSL_DEBUG, "SSL: gnutls ssl_be_recv(): successful (IO_SUCCESS)");
1073 /*******************************************************************************/
1074 /*******************************************************************************/
1075 /*******************************************************************************/
1076 /*******************************************************************************/
1077 /*******************************************************************************/
1078 /********************** OpenSSL backend *****************/
1079 /*******************************************************************************/
1080 /*******************************************************************************/
1081 /*******************************************************************************/
1082 /*******************************************************************************/
1083 /*******************************************************************************/
1088 #elif defined(HAVE_OPENSSL)
1089 unsigned int ssl_be_init() {
1091 /* Load error strings; Returns void. */
1092 SSL_load_error_strings();
1093 /* Seed the random number generator. We do not care for errors here. */
1094 RAND_load_file("/dev/urandom", 4096);
1097 void ssl_be_deinit() {
1100 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred) {
1101 if(mode == SSL_CLIENT) {
1102 *cred = SSL_CTX_new(SSLv23_client_method());
1104 ssl_msg(SSL_ERROR, "SSL: SSL_CTX_new(): failed");
1108 if(*(trusts + 1)) ssl_msg(SSL_NOTICE, "SSL: (OpenSSL) skipping further CA files");
1109 if(!SSL_CTX_load_verify_locations(*cred, *trusts, NULL)) {
1110 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_load_verify_locations('%s'): failed", *trusts);
1111 /* ignore errors here */
1113 else SSL_CTX_set_client_CA_list(*cred, SSL_load_client_CA_file(*trusts));
1115 SSL_CTX_set_mode(*cred, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
1116 if(!SSL_CTX_use_certificate_file(*cred, cert, SSL_FILETYPE_PEM)) {
1117 SSL_CTX_free(*cred);
1118 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_use_certificate_file('%s'): failed", cert);
1121 if(!SSL_CTX_use_PrivateKey_file(*cred, cert, SSL_FILETYPE_PEM)) {
1122 SSL_CTX_free(*cred);
1123 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_use_PrivateKey_file('%s'): failed", cert);
1126 SSL_CTX_set_verify(*cred, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, ssl_be_verify);
1129 *cred = SSL_CTX_new(SSLv23_server_method());
1131 ssl_msg(SSL_ERROR, "SSL: SSL_CTX_new(): failed");
1134 SSL_CTX_set_mode(*cred, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
1135 if(!SSL_CTX_use_certificate_file(*cred, cert, SSL_FILETYPE_PEM)) {
1136 SSL_CTX_free(*cred);
1137 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_use_certificate_file('%s'): failed", cert);
1140 if(!SSL_CTX_use_PrivateKey_file(*cred, cert, SSL_FILETYPE_PEM)) {
1141 SSL_CTX_free(*cred);
1142 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_use_PrivateKey_file('%s'): failed", cert);
1148 void ssl_be_cred_free(ssl_be_cred_t *cred) {
1149 SSL_CTX_free(*cred);
1151 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session) {
1152 *session = SSL_new(*cred);
1154 ssl_msg(SSL_ERROR, "SSL: SSL_new(%u): failed", mode);
1159 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd) {
1160 SSL_set_fd(*session, fd);
1163 void ssl_be_session_shutdown(ssl_be_session_t *session) {
1164 SSL_shutdown(*session);
1166 void ssl_be_session_free(ssl_be_session_t *session) {
1169 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session) {
1171 if(mode == SSL_CLIENT) ret = SSL_connect(*session);
1172 else ret = SSL_accept(*session);
1174 ret = SSL_get_error(*session, ret);
1175 if(ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE) {
1176 if(ret == SSL_ERROR_WANT_READ) return SSL_NEED_RD;
1177 else return SSL_NEED_WR;
1180 ssl_msg(SSL_DEBUG, "SSL: gnutls_handshake(): failed (%d)", ret);
1184 else return SSL_SUCCESS;
1186 const char *ssl_be_cipherstr(ssl_be_session_t *session) {
1187 static char buf[400];
1193 strcpy(buf, SSL_get_version(*session));
1195 strcat(buf, SSL_get_cipher(*session));
1196 c = SSL_get_current_cipher(*session);
1197 SSL_CIPHER_get_bits(c, &bits);
1199 ircd_snprintf(0, buf2, sizeof(buf2), "%d", bits);
1201 strcat(buf, "bits");
1204 const char *ssl_be_fingerprint(ssl_be_session_t *session) {
1207 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out) {
1208 signed int res, merrno;
1210 #ifdef SSL_EAGAIN_DEBUG
1211 signed int back, back_c;
1215 res = SSL_write(*ssl, buf, *count_out);
1218 #ifdef SSL_EAGAIN_DEBUG
1219 back_c = *count_out;
1223 if(res == 0) return IO_FAILURE;
1225 #ifdef SSL_EAGAIN_DEBUG
1228 res = SSL_get_error(*ssl, res);
1230 * OpenSSL sucks! This hack still returns IO_BLOCKED on special SYSCALL failures.
1231 * The ircd system is built that the user will be killed automatically when this
1232 * happens too often so we can safely return this here, however, the OpenSSL devs
1233 * should *REALLY* fix this. They're already noticed.
1236 if(res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE && res != SSL_ERROR_WANT_X509_LOOKUP) {
1237 if(merrno == EAGAIN || merrno == EINTR || merrno == EWOULDBLOCK || merrno == EBUSY) {
1238 #ifdef SSL_EAGAIN_DEBUG
1239 snprintf(buffer, (back_c > 4096)?4096:back_c, "%s", buf);
1241 ssl_msg(SSL_NOTICE, "OpenSSL: EAGAIN debug information: fd (%d) err (%d) serr (%d) "
1242 "derr1 (%lu) derr2 (%lu) back (%d) len (%u) buf (%s)",
1243 fd, merrno, res, ERR_peek_error(), ERR_peek_last_error(), back, back_c, buffer);
1249 else return IO_BLOCKED;
1256 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out) {
1257 signed int res, merrno;
1258 res = SSL_read(*ssl, buf, *count_out);
1261 if(res == 0) return IO_FAILURE;
1263 res = SSL_get_error(*ssl, res);
1264 if(res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE || res == SSL_ERROR_WANT_X509_LOOKUP) return IO_BLOCKED;
1266 * OpenSSL sucks! This hack still returns IO_BLOCKED on special SYSCALL failures.
1267 * The ircd system is built that the user will be killed automatically when this
1268 * happens too often so we can safely return this here, however, the OpenSSL devs
1269 * should *REALLY* fix this. They're already noticed.
1272 else if(merrno == EAGAIN || merrno == EINTR || merrno == EWOULDBLOCK || merrno == EBUSY) return IO_BLOCKED;
1273 else return IO_FAILURE;
1280 static signed int ssl_be_verify(signed int preverify_ok, X509_STORE_CTX *ctx) {
1287 /*******************************************************************************/
1288 /*******************************************************************************/
1289 /*******************************************************************************/
1290 /*******************************************************************************/
1291 /*******************************************************************************/
1292 /********************** Dummy backend *****************/
1293 /*******************************************************************************/
1294 /*******************************************************************************/
1295 /*******************************************************************************/
1296 /*******************************************************************************/
1297 /*******************************************************************************/
1303 unsigned int ssl_be_init() {
1306 void ssl_be_deinit() {
1309 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred) {
1313 void ssl_be_cred_free(ssl_be_cred_t *cred) {
1316 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session) {
1320 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd) {
1323 void ssl_be_session_shutdown(ssl_be_session_t *session) {
1326 void ssl_be_session_free(ssl_be_session_t *session) {
1329 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session) {
1332 const char *ssl_be_cipherstr(ssl_be_session_t *session) {
1335 const char *ssl_be_fingerprint(ssl_be_session_t *session) {
1338 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out) {
1341 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out) {