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 /*******************************************************************************/
870 unsigned int ssl_be_init() {
872 if((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS) {
873 ssl_msg(SSL_ERROR, "SSL: gnutls_global_init(): failed (%d)", ret);
878 void ssl_be_deinit() {
879 gnutls_global_deinit();
881 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred) {
884 if((ret = gnutls_dh_params_init(&cred->dhparams)) != GNUTLS_E_SUCCESS) {
885 ssl_msg(SSL_ERROR, "SSL: gnutls_dh_params_init(): failed (%d)", ret);
888 if((ret = gnutls_dh_params_generate2(cred->dhparams, SSL_DH_BITS)) != GNUTLS_E_SUCCESS) {
889 gnutls_dh_params_deinit(cred->dhparams);
890 ssl_msg(SSL_ERROR, "SSL: gnutls_dh_params_generate2(): failed (%d)", ret);
893 if((ret = gnutls_certificate_allocate_credentials(&cred->cred)) != GNUTLS_E_SUCCESS) {
894 gnutls_dh_params_deinit(cred->dhparams);
895 ssl_msg(SSL_ERROR, "SSL: gnutls_certificate_allocate_credentials(): failed (%d)", ret);
900 if((ret = gnutls_certificate_set_x509_trust_file(cred->cred, trusts[i], GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS) {
901 ssl_msg(SSL_NOTICE, "SSL: gnutls_certificate_set_x509_trust_file('%s'): failed (%d)", trusts[i], ret);
902 /* ignore errors here */
906 if((ret = gnutls_certificate_set_x509_key_file(cred->cred, cert, cert, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS) {
907 gnutls_certificate_free_credentials(cred->cred);
908 gnutls_dh_params_deinit(cred->dhparams);
909 ssl_msg(SSL_NOTICE, "SSL: gnutls_certificate_set_x509_key_file('%s'): failed (%d)", cert, ret);
912 gnutls_certificate_set_dh_params(cred->cred, cred->dhparams);
913 gnutls_priority_init(&cred->prio, "NORMAL", NULL);
916 void ssl_be_cred_free(ssl_be_cred_t *cred) {
917 gnutls_certificate_free_credentials(cred->cred);
918 gnutls_priority_deinit(cred->prio);
919 gnutls_dh_params_deinit(cred->dhparams);
921 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session) {
923 if(mode == SSL_CLIENT) {
924 if((ret = gnutls_init(session, GNUTLS_CLIENT)) != GNUTLS_E_SUCCESS) {
925 ssl_msg(SSL_ERROR, "SSL: gnutls_init(): failed (%d)", ret);
928 gnutls_priority_set(*session, cred->prio);
929 /*if((ret = gnutls_priority_set_direct(*session, "NORMAL", NULL)) != GNUTLS_E_SUCCESS) {
930 gnutls_deinit(*session);
931 ssl_msg(SSL_ERROR, "SSL: gnutls_priority_set_direct(): failed (%d)", ret);
934 if((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, cred->cred)) != GNUTLS_E_SUCCESS) {
935 gnutls_deinit(*session);
936 ssl_msg(SSL_ERROR, "SSL: gnutls_credentials_set(): failed (%d)", ret);
939 gnutls_dh_set_prime_bits(*session, SSL_DH_RBITS);
942 if((ret = gnutls_init(session, GNUTLS_SERVER)) != GNUTLS_E_SUCCESS) {
943 ssl_msg(SSL_ERROR, "SSL: gnutls_init(): failed (%d)", ret);
946 gnutls_priority_set(*session, cred->prio);
947 /*if((ret = gnutls_priority_set_direct(*session, "NORMAL", NULL)) != GNUTLS_E_SUCCESS) {
948 gnutls_deinit(*session);
949 ssl_msg(SSL_ERROR, "SSL: gnutls_priority_set_direct(): failed (%d)", ret);
952 if((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, cred->cred)) != GNUTLS_E_SUCCESS) {
953 gnutls_deinit(*session);
954 ssl_msg(SSL_ERROR, "SSL: gnutls_credentials_set(): failed (%d)", ret);
957 gnutls_certificate_server_set_request(*session, GNUTLS_CERT_REQUEST);
961 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd) {
962 gnutls_transport_set_ptr(*session, (gnutls_transport_ptr_t)fd);
965 void ssl_be_session_shutdown(ssl_be_session_t *session) {
966 gnutls_bye(*session, GNUTLS_SHUT_WR);
968 void ssl_be_session_free(ssl_be_session_t *session) {
969 gnutls_deinit(*session);
971 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session) {
973 ret = gnutls_handshake(*session);
975 if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
976 if(gnutls_record_get_direction(*session) == 0) return SSL_NEED_RD;
977 else return SSL_NEED_WR;
980 ssl_msg(SSL_DEBUG, "SSL: gnutls_handshake(): failed (%d)", ret);
984 else return SSL_SUCCESS;
986 const char *ssl_be_cipherstr(ssl_be_session_t *session) {
987 static char buf[401];
988 const char *kx_name, *cipher_name, *mac_name;
992 kx_name = gnutls_kx_get_name(gnutls_kx_get(*session));
993 cipher_name = gnutls_cipher_get_name(gnutls_cipher_get(*session));
994 mac_name = gnutls_mac_get_name(gnutls_mac_get(*session));
996 if(!kx_name || !cipher_name || !mac_name) {
997 ssl_msg(SSL_ERROR, "SSL: gnutls_[kx,cipher,mac]_get_name(): failed");
1001 len = strlen(kx_name) + strlen(cipher_name) + strlen(mac_name);
1003 ssl_msg(SSL_ERROR, "SSL: gnutls_[kx,cipher,mac]_get_name(): too long");
1009 while((*dest++ = kx_name[i++])) /* empty */ ;
1012 while((*dest++ = cipher_name[i++])) /* empty */ ;
1015 while((*dest++ = mac_name[i++])) /* empty */ ;
1019 const char *ssl_be_fingerprint(ssl_be_session_t *session) {
1022 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out) {
1024 res = gnutls_record_send(*ssl, buf, *count_out);
1026 if(res == 0) return IO_FAILURE;
1028 if(res != GNUTLS_E_AGAIN && res != GNUTLS_E_INTERRUPTED) return IO_FAILURE;
1029 else return IO_BLOCKED;
1036 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out) {
1038 res = gnutls_record_recv(*ssl, buf, *count_out);
1040 if(res == 0) return IO_FAILURE;
1042 if(res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) return IO_BLOCKED;
1043 else return IO_FAILURE;
1054 /*******************************************************************************/
1055 /*******************************************************************************/
1056 /*******************************************************************************/
1057 /*******************************************************************************/
1058 /*******************************************************************************/
1059 /********************** OpenSSL backend *****************/
1060 /*******************************************************************************/
1061 /*******************************************************************************/
1062 /*******************************************************************************/
1063 /*******************************************************************************/
1064 /*******************************************************************************/
1069 #elif defined(HAVE_OPENSSL)
1070 unsigned int ssl_be_init() {
1072 /* Load error strings; Returns void. */
1073 SSL_load_error_strings();
1074 /* Seed the random number generator. We do not care for errors here. */
1075 RAND_load_file("/dev/urandom", 4096);
1078 void ssl_be_deinit() {
1081 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred) {
1082 if(mode == SSL_CLIENT) {
1083 *cred = SSL_CTX_new(SSLv23_client_method());
1085 ssl_msg(SSL_ERROR, "SSL: SSL_CTX_new(): failed");
1089 if(*(trusts + 1)) ssl_msg(SSL_NOTICE, "SSL: (OpenSSL) skipping further CA files");
1090 if(!SSL_CTX_load_verify_locations(*cred, *trusts, NULL)) {
1091 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_load_verify_locations('%s'): failed", *trusts);
1092 /* ignore errors here */
1094 else SSL_CTX_set_client_CA_list(*cred, SSL_load_client_CA_file(*trusts));
1096 SSL_CTX_set_mode(*cred, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
1097 if(!SSL_CTX_use_certificate_file(*cred, cert, SSL_FILETYPE_PEM)) {
1098 SSL_CTX_free(*cred);
1099 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_use_certificate_file('%s'): failed", cert);
1102 if(!SSL_CTX_use_PrivateKey_file(*cred, cert, SSL_FILETYPE_PEM)) {
1103 SSL_CTX_free(*cred);
1104 ssl_msg(SSL_NOTICE, "SSL: SSL_CTX_use_PrivateKey_file('%s'): failed", cert);
1107 SSL_CTX_set_verify(*cred, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, ssl_be_verify);
1110 *cred = SSL_CTX_new(SSLv23_server_method());
1112 ssl_msg(SSL_ERROR, "SSL: SSL_CTX_new(): failed");
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);
1129 void ssl_be_cred_free(ssl_be_cred_t *cred) {
1130 SSL_CTX_free(*cred);
1132 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session) {
1133 *session = SSL_new(*cred);
1135 ssl_msg(SSL_ERROR, "SSL: SSL_new(%u): failed", mode);
1140 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd) {
1141 SSL_set_fd(*session, fd);
1144 void ssl_be_session_shutdown(ssl_be_session_t *session) {
1145 SSL_shutdown(*session);
1147 void ssl_be_session_free(ssl_be_session_t *session) {
1150 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session) {
1152 if(mode == SSL_CLIENT) ret = SSL_connect(*session);
1153 else ret = SSL_accept(*session);
1155 ret = SSL_get_error(*session, ret);
1156 if(ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE) {
1157 if(ret == SSL_ERROR_WANT_READ) return SSL_NEED_RD;
1158 else return SSL_NEED_WR;
1161 ssl_msg(SSL_DEBUG, "SSL: gnutls_handshake(): failed (%d)", ret);
1165 else return SSL_SUCCESS;
1167 const char *ssl_be_cipherstr(ssl_be_session_t *session) {
1168 static char buf[400];
1174 strcpy(buf, SSL_get_version(*session));
1176 strcat(buf, SSL_get_cipher(*session));
1177 c = SSL_get_current_cipher(*session);
1178 SSL_CIPHER_get_bits(c, &bits);
1180 ircd_snprintf(0, buf2, sizeof(buf2), "%d", bits);
1182 strcat(buf, "bits");
1185 const char *ssl_be_fingerprint(ssl_be_session_t *session) {
1188 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out) {
1189 signed int res, merrno;
1191 #ifdef SSL_EAGAIN_DEBUG
1192 signed int back, back_c;
1196 res = SSL_write(*ssl, buf, *count_out);
1199 #ifdef SSL_EAGAIN_DEBUG
1200 back_c = *count_out;
1204 if(res == 0) return IO_FAILURE;
1206 #ifdef SSL_EAGAIN_DEBUG
1209 res = SSL_get_error(*ssl, res);
1211 * OpenSSL sucks! This hack still returns IO_BLOCKED on special SYSCALL failures.
1212 * The ircd system is built that the user will be killed automatically when this
1213 * happens too often so we can safely return this here, however, the OpenSSL devs
1214 * should *REALLY* fix this. They're already noticed.
1217 if(res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE && res != SSL_ERROR_WANT_X509_LOOKUP) {
1218 if(merrno == EAGAIN || merrno == EINTR || merrno == EWOULDBLOCK || merrno == EBUSY) {
1219 #ifdef SSL_EAGAIN_DEBUG
1220 snprintf(buffer, (back_c > 4096)?4096:back_c, "%s", buf);
1222 ssl_msg(SSL_NOTICE, "OpenSSL: EAGAIN debug information: fd (%d) err (%d) serr (%d) "
1223 "derr1 (%lu) derr2 (%lu) back (%d) len (%u) buf (%s)",
1224 fd, merrno, res, ERR_peek_error(), ERR_peek_last_error(), back, back_c, buffer);
1230 else return IO_BLOCKED;
1237 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out) {
1238 signed int res, merrno;
1239 res = SSL_read(*ssl, buf, *count_out);
1242 if(res == 0) return IO_FAILURE;
1244 res = SSL_get_error(*ssl, res);
1245 if(res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE || res == SSL_ERROR_WANT_X509_LOOKUP) return IO_BLOCKED;
1247 * OpenSSL sucks! This hack still returns IO_BLOCKED on special SYSCALL failures.
1248 * The ircd system is built that the user will be killed automatically when this
1249 * happens too often so we can safely return this here, however, the OpenSSL devs
1250 * should *REALLY* fix this. They're already noticed.
1253 else if(merrno == EAGAIN || merrno == EINTR || merrno == EWOULDBLOCK || merrno == EBUSY) return IO_BLOCKED;
1254 else return IO_FAILURE;
1261 static signed int ssl_be_verify(signed int preverify_ok, X509_STORE_CTX *ctx) {
1268 /*******************************************************************************/
1269 /*******************************************************************************/
1270 /*******************************************************************************/
1271 /*******************************************************************************/
1272 /*******************************************************************************/
1273 /********************** Dummy backend *****************/
1274 /*******************************************************************************/
1275 /*******************************************************************************/
1276 /*******************************************************************************/
1277 /*******************************************************************************/
1278 /*******************************************************************************/
1284 unsigned int ssl_be_init() {
1287 void ssl_be_deinit() {
1290 unsigned int ssl_be_cred_new(unsigned int mode, char *cert, char **trusts, ssl_be_cred_t *cred) {
1294 void ssl_be_cred_free(ssl_be_cred_t *cred) {
1297 unsigned int ssl_be_session_new(unsigned int mode, ssl_be_cred_t *cred, ssl_be_session_t *session) {
1301 unsigned int ssl_be_session_connect(ssl_be_session_t *session, signed int fd) {
1304 void ssl_be_session_shutdown(ssl_be_session_t *session) {
1307 void ssl_be_session_free(ssl_be_session_t *session) {
1310 unsigned int ssl_be_handshake(unsigned int mode, ssl_be_session_t *session) {
1313 const char *ssl_be_cipherstr(ssl_be_session_t *session) {
1316 const char *ssl_be_fingerprint(ssl_be_session_t *session) {
1319 IOResult ssl_be_send(signed int fd, ssl_be_session_t *ssl, const char *buf, unsigned int *count_out) {
1322 IOResult ssl_be_recv(signed int fd, ssl_be_session_t *ssl, char *buf, unsigned int *count_out) {