diff --git a/include/client.h b/include/client.h index af8ccfa43..417627730 100644 --- a/include/client.h +++ b/include/client.h @@ -291,6 +291,8 @@ struct LocalUser unsigned int sasl_messages; unsigned int sasl_failures; time_t sasl_next_retry; + + char *sni; }; #define AUTHC_F_DEFERRED 0x01 diff --git a/ircd/sslproc.c b/ircd/sslproc.c index ffea6e89b..ebabd0a80 100644 --- a/ircd/sslproc.c +++ b/ircd/sslproc.c @@ -535,6 +535,28 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) client_p->certfp = certfp_string; } + +static void +ssl_process_sni(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) +{ + struct Client *client_p; + int32_t fd; + char *sni_string; + int i; + + if(ctl_buf->buflen > 5 + RB_SSL_SNI_LEN) + return; + + fd = buf_to_uint32(&ctl_buf->buf[1]); + client_p = find_cli_connid_hash(fd); + if(client_p == NULL) + return; + rb_free(client_p->localClient->sni); + sni_string = rb_malloc(ctl_buf->buflen - 4); + rb_strlcpy(sni_string, &ctl_buf->buf[5], ctl_buf->buflen - 0); + client_p->localClient->sni = sni_string; +} + static void ssl_process_cmd_recv(ssl_ctl_t * ctl) { @@ -590,6 +612,9 @@ ssl_process_cmd_recv(ssl_ctl_t * ctl) case 'z': ircd_zlib_ok = 0; break; + case 'n': + ssl_process_sni(ctl, ctl_buf); + break; default: ilog(L_MAIN, "Received invalid command from ssld: %s", ctl_buf->buf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Received invalid command from ssld"); diff --git a/librb/include/rb_commio.h b/librb/include/rb_commio.h index b7a37db8d..abda2d4dd 100644 --- a/librb/include/rb_commio.h +++ b/librb/include/rb_commio.h @@ -117,6 +117,8 @@ void rb_note(rb_fde_t *, const char *); #define RB_SSL_CERTFP_LEN_SHA256 32 #define RB_SSL_CERTFP_LEN_SHA512 64 +#define RB_SSL_SNI_LEN 250 + int rb_set_nb(rb_fde_t *); int rb_set_buffers(rb_fde_t *, int); @@ -165,6 +167,7 @@ rb_platform_fd_t rb_get_fd(rb_fde_t *F); const char *rb_get_ssl_strerror(rb_fde_t *F); int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method); int rb_get_ssl_certfp_file(const char *filename, uint8_t certfp[RB_SSL_CERTFP_LEN], int method); +int rb_get_ssl_sni(rb_fde_t *F, uint8_t sni[static RB_SSL_SNI_LEN]); rb_fde_t *rb_get_fde(rb_platform_fd_t fd); diff --git a/librb/src/export-syms.txt b/librb/src/export-syms.txt index 0c479b6db..d77f91a98 100644 --- a/librb/src/export-syms.txt +++ b/librb/src/export-syms.txt @@ -62,6 +62,7 @@ rb_get_random rb_get_sockerr rb_get_ssl_certfp rb_get_ssl_certfp_file +rb_get_ssl_sni rb_get_ssl_strerror rb_get_type rb_getmaxconnect diff --git a/librb/src/openssl.c b/librb/src/openssl.c index b2f179a17..91582eb93 100644 --- a/librb/src/openssl.c +++ b/librb/src/openssl.c @@ -521,6 +521,27 @@ rb_get_ssl_strerror(rb_fde_t *const F) return rb_ssl_strerror(F->ssl_errno); } +int +rb_get_ssl_sni(rb_fde_t *F, uint8_t sni[static RB_SSL_SNI_LEN]) +{ + const char *openssl_sni; + size_t n; + + if (F == NULL || F->ssl == NULL) + return 0; + + openssl_sni = SSL_get_servername(F->ssl, TLSEXT_NAMETYPE_host_name); + if (openssl_sni == NULL) + return 0; + + n = snprintf((char *)sni, RB_SSL_SNI_LEN, "%s", openssl_sni); + + if (n == 0 || n > RB_SSL_SNI_LEN || n > INT_MAX) + return 0; + + return (int)n; +} + int rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method) { diff --git a/modules/m_whois.c b/modules/m_whois.c index 0fc0f4f7f..7c84003ba 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -344,6 +344,13 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) sendto_one_numeric(source_p, RPL_WHOISCERTFP, form_str(RPL_WHOISCERTFP), target_p->name, target_p->certfp); + + if((source_p == target_p || IsOper(source_p)) && + target_p->localClient != NULL && + target_p->localClient->sni != NULL) + sendto_one_numeric(source_p, RPL_WHOISCERTFP, + "%s %s :Connected to hostname", + target_p->name, target_p->localClient->sni); } if(MyClient(target_p)) diff --git a/ssld/ssld.c b/ssld/ssld.c index db33486be..a9c905b12 100644 --- a/ssld/ssld.c +++ b/ssld/ssld.c @@ -695,6 +695,21 @@ ssl_send_certfp(conn_t *conn) mod_cmd_write_queue(conn->ctl, buf, 13 + len); } +static void +ssl_send_sni(conn_t *conn) +{ + uint8_t buf[5 + RB_SSL_SNI_LEN]; + + int len = rb_get_ssl_sni(conn->mod_fd, &buf[5]); + if (len == 0) + return; + + lrb_assert(len <= RB_SSL_SNI_LEN); + buf[0] = 'n'; + uint32_to_buf(&buf[1], conn->id); + mod_cmd_write_queue(conn->ctl, buf, 5 + len); +} + static void ssl_send_open(conn_t *conn) { @@ -714,6 +729,7 @@ ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen { ssl_send_cipher(conn); ssl_send_certfp(conn); + ssl_send_sni(conn); ssl_send_open(conn); conn_mod_read_cb(conn->mod_fd, conn); conn_plain_read_cb(conn->plain_fd, conn);