Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

Added SNI support (OpenSSL) #309

Open
wants to merge 1 commit into
base: release/3.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions doc/ircd.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -557,3 +557,17 @@ modules {
path = "modules";
path = "modules/autoload";
};

/*
vhost "selfsigned.hades.arpa" {
ssl_private_key = "etc/selfssl.key";
ssl_cert = "etc/selfssl.pem";
};

vhost "oldca.hades.arpa" {
ssl_private_key = "etc/oldssl.key";
ssl_cert = "etc/oldssl2.pem";
ssl_dh_params = "etc/olddh.pem";
ssl_cipher_list = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";;
};
*/
14 changes: 14 additions & 0 deletions doc/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1360,3 +1360,17 @@ modules {
/* module: the name of a module to load on startup/rehash */
#module = "some_module.so";
};

/*
vhost "selfsigned.hades.arpa" {
ssl_private_key = "etc/selfssl.key";
ssl_cert = "etc/selfssl.pem";
};

vhost "oldca.hades.arpa" {
ssl_private_key = "etc/oldssl.key";
ssl_cert = "etc/oldssl2.pem";
ssl_dh_params = "etc/olddh.pem";
ssl_cipher_list = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
};
*/
14 changes: 13 additions & 1 deletion include/s_newconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ extern rb_dlink_list xline_conf_list;
extern rb_dlink_list resv_conf_list;
extern rb_dlink_list nd_list;
extern rb_dlink_list tgchange_list;
extern rb_dlink_list vhost_conf_list;

extern struct _rb_patricia_tree_t *tgchange_tree;

Expand Down Expand Up @@ -245,5 +246,16 @@ extern void add_nd_entry(const char *name);
extern void free_nd_entry(struct nd_entry *);
extern unsigned long get_nd_count(void);

#endif
struct vhost_conf
{
char *hostname;
char *ssl_private_key;
char *ssl_cert;
char *ssl_dh_params;
char *ssl_cipher_list;
rb_dlink_node node;
};
extern struct vhost_conf *make_vhost_conf(void);
extern void free_vhost_conf(struct vhost_conf *);

#endif
4 changes: 2 additions & 2 deletions include/sslproc.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
void start_zlib_session(void *data);
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list, const int method);
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list, const int method, const char *hostname);
void send_remove_ssl_vhost(const char *hostname);
void ssld_decrement_clicount(ssl_ctl_t *ctl);
int get_ssld_count(void);
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status), void *data);

#endif

2 changes: 1 addition & 1 deletion libratbox/include/commio-ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#ifndef _COMMIO_SSL_H
#define _COMMIO_SSL_H

int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list);
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname);
int rb_init_ssl(void);

int rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept);
Expand Down
3 changes: 2 additions & 1 deletion libratbox/include/rb_commio.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,10 @@ ssize_t rb_writev(rb_fde_t *, struct rb_iovec *vector, int count);
ssize_t rb_read(rb_fde_t *, void *buf, int count);
int rb_pipe(rb_fde_t **, rb_fde_t **, const char *desc);

int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list);
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname);
int rb_ssl_listen(rb_fde_t *, int backlog, int defer_accept);
int rb_listen(rb_fde_t *, int backlog, int defer_accept);
int rb_remove_ssl_vserver(const char *hostname);

const char *rb_inet_ntop(int af, const void *src, char *dst, unsigned int size);
int rb_inet_pton(int af, const char *src, void *dst);
Expand Down
1 change: 1 addition & 0 deletions libratbox/src/export-syms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ rb_setselect
rb_settimeout
rb_setup_fd
rb_setup_ssl_server
rb_remove_ssl_vserver
rb_socket
rb_socketpair
rb_ssl_listen
Expand Down
9 changes: 8 additions & 1 deletion libratbox/src/gnutls.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,16 @@ rb_init_ssl(void)
return 1;
}

int
rb_remove_ssl_vserver(const char *hostname)
{
errno = ENOSYS;
return -1;
}

int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *cipherlist)
const char *const dhfile, const char *cipherlist, const char *hostname)
{
if(certfile == NULL)
{
Expand Down
9 changes: 8 additions & 1 deletion libratbox/src/mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,16 @@ rb_init_ssl(void)
return 1;
}

int
rb_remove_ssl_vserver(const char *hostname)
{
errno = ENOSYS;
return -1;
}

int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *const cipherlist)
const char *const dhfile, const char *const cipherlist, const char *hostname)
{
if(certfile == NULL)
{
Expand Down
9 changes: 8 additions & 1 deletion libratbox/src/nossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include <commio-ssl.h>

int
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list)
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname)
{
errno = ENOSYS;
return 0;
Expand All @@ -48,6 +48,13 @@ rb_init_ssl(void)

}

int
rb_remove_ssl_vserver(const char *hostname)
{
errno = ENOSYS;
return -1;
}

int
rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
{
Expand Down
110 changes: 104 additions & 6 deletions libratbox/src/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,31 @@ typedef enum

#define SSL_P(x) ((SSL *)((x)->ssl))


typedef struct ssl_vhost_s
{
char *hostname;
SSL_CTX *ctx;
rb_dlink_node node;
} ssl_vhost;

static SSL_CTX *ssl_ctx = NULL;
rb_dlink_list ssl_vhosts;

rb_dlink_node *
find_ssl_vhost(const char *hostname)
{
ssl_vhost *vhost_p;
rb_dlink_node *ptr;

RB_DLINK_FOREACH(ptr, ssl_vhosts.head)
{
vhost_p = ptr->data;

if(!strcmp(hostname,vhost_p->hostname))
return ptr;
}
return NULL;
}

struct ssl_connect
{
Expand Down Expand Up @@ -337,9 +359,65 @@ rb_init_ssl(void)
return 1;
}

static int rb_ssl_servername_cb(SSL *s, int *ad, void *arg)
{
ssl_vhost *vhost_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;

const char * servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);

rb_lib_log("Hostname in TLS extension?");
if (servername)
{
rb_lib_log("Hostname in TLS extension %s", servername);

RB_DLINK_FOREACH_SAFE(ptr, next_ptr, ssl_vhosts.head)
{
vhost_p = ptr->data;

if (strcmp(servername, vhost_p->hostname) != 0)
continue;

if (vhost_p->ctx)
{
rb_lib_log("Switching server context %s", servername);
SSL_set_SSL_CTX(s,vhost_p->ctx);
}
}
}
return SSL_TLSEXT_ERR_OK;
}

void
free_ssl_vhost(ssl_vhost *vhost_p)
{
if(vhost_p == NULL)
return;

rb_free(vhost_p->hostname);

SSL_CTX_free(vhost_p->ctx);
rb_free(vhost_p);
}

int
rb_remove_ssl_vserver(const char *hostname)
{
rb_dlink_node *ptr = find_ssl_vhost(hostname);
if(ptr != NULL && ptr) {
rb_dlinkDelete(ptr, &ssl_vhosts);
free_ssl_vhost(ptr->data);
return 1;
}

return 0;
}

int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *cipherlist)
const char *const dhfile, const char *cipherlist,
const char *hostname)
{
if(certfile == NULL)
{
Expand Down Expand Up @@ -419,6 +497,7 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile,
SSL_CTX_free(ssl_ctx_new);
return 0;
}
SSL_CTX_set_tlsext_servername_callback(ssl_ctx_new, rb_ssl_servername_cb);

SSL_CTX_set_session_cache_mode(ssl_ctx_new, SSL_SESS_CACHE_OFF);
SSL_CTX_set_verify(ssl_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
Expand Down Expand Up @@ -472,14 +551,33 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile,
# endif
#endif

rb_lib_log("%s: TLS configuration successful", __func__);
if(hostname == NULL) {
if(ssl_ctx)
SSL_CTX_free(ssl_ctx);

if(ssl_ctx)
SSL_CTX_free(ssl_ctx);
ssl_ctx = ssl_ctx_new;
} else {
ssl_vhost *vhost_p = NULL;

ssl_ctx = ssl_ctx_new;
rb_lib_log("rb_setup_ssl_server: SETUP [%s]", hostname);
rb_dlink_node *ptr = find_ssl_vhost(hostname);
if(ptr != NULL && ptr)
vhost_p = ptr->data;

if(vhost_p == NULL) {
vhost_p = rb_malloc(sizeof(ssl_vhost));
vhost_p->hostname = rb_strdup(hostname);

rb_dlinkAdd(vhost_p, &vhost_p->node, &ssl_vhosts);
}

if(vhost_p->ctx)
SSL_CTX_free(vhost_p->ctx);

vhost_p->ctx = ssl_ctx_new;
}

rb_lib_log("%s: TLS configuration successful", __func__);
return 1;
}

Expand Down
20 changes: 18 additions & 2 deletions src/ircd.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,11 @@ int
main(int argc, char *argv[])
{
int fd;

#ifdef HAVE_LIBCRYPTO
struct vhost_conf *vhost_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
#endif
/* Check to see if the user is running us as root, which is a nono */
if(geteuid() == 0)
{
Expand Down Expand Up @@ -676,13 +680,25 @@ main(int argc, char *argv[])
if(ServerInfo.ssl_cert != NULL && ServerInfo.ssl_private_key != NULL)
{
/* just do the rb_setup_ssl_server to validate the config */
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list))
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list, NULL))
{
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
ircd_ssl_ok = 0;
}
else
ircd_ssl_ok = 1;
#ifdef HAVE_LIBCRYPTO
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, vhost_conf_list.head)
{
vhost_p = ptr->data;
if(rb_setup_ssl_server(vhost_p->ssl_cert, vhost_p->ssl_private_key,
vhost_p->ssl_dh_params ? vhost_p->ssl_dh_params : ServerInfo.ssl_dh_params,
vhost_p->ssl_cipher_list ? vhost_p->ssl_cipher_list : ServerInfo.ssl_cipher_list, vhost_p->hostname))
{
ircd_ssl_ok = 1;
}
}
#endif
}

if (testing_conf)
Expand Down
Loading