diff --git a/include/msg.h b/include/msg.h index dfcea34c..113bcc7c 100644 --- a/include/msg.h +++ b/include/msg.h @@ -109,6 +109,7 @@ #define MSG_SGLINE "SGLINE" /* sgline */ #define MSG_UNSGLINE "UNSGLINE" /* unsgline */ #define MSG_DKEY "DKEY" /* diffie-hellman negotiation */ +#define MSG_TLS "TLS" /* TLS negotiation */ #define MSG_NS "NS" /* NickServ commands */ #define MSG_CS "CS" /* ChanServ commands */ #define MSG_MS "MS" /* MemoServ commands */ @@ -217,6 +218,7 @@ extern int m_dccallow(aClient *, aClient *, int, char **); extern int m_sgline(aClient *, aClient *, int, char **); extern int m_unsgline(aClient *, aClient *, int, char **); extern int m_dkey(aClient *, aClient *, int, char **); +extern int m_tls(aClient *, aClient *, int, char **); extern int m_resynch(aClient *, aClient *, int, char **); extern int m_luserslock(aClient *, aClient *, int, char **); extern int m_linkscontrol(aClient *, aClient *, int, char **); @@ -350,6 +352,7 @@ struct Message msgtab[] = {MSG_SGLINE, m_sgline, MAXPARA, 0, 0}, {MSG_UNSGLINE, m_unsgline, MAXPARA, 0, 0}, {MSG_DKEY, m_dkey, MAXPARA, MF_UNREG, 0}, + {MSG_TLS, m_tls, MAXPARA, MF_UNREG, 0}, {MSG_NS, m_aliased, 1, MF_ALIAS, AII_NS}, {MSG_CS, m_aliased, 1, MF_ALIAS, AII_CS}, {MSG_MS, m_aliased, 1, MF_ALIAS, AII_MS}, diff --git a/src/m_server.c b/src/m_server.c index b077c41f..41c5b3e1 100644 --- a/src/m_server.c +++ b/src/m_server.c @@ -527,7 +527,9 @@ m_server_estab(aClient *cptr) } else { - return do_server_estab(cptr); + SetNegoServer(cptr); /* Now we need to negotiate TLS */ + sendto_one(cptr, "TLS START"); + // return do_server_estab(cptr); } #endif #else @@ -836,6 +838,76 @@ int m_server(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; } +/* m_tls + * code to validate TLS connection + * validation is basically: + * CN specified by peer's certificate + * compared against name sent by peer + * compared against name specified in connect block + * all must match + */ + +int m_tls(aClient *cptr, aClient *sptr, int parc, char *parv[]) +{ + if (!(IsNegoServer(sptr) && parc > 1)) + { + if (IsPerson(sptr)) + return 0; + return exit_client(sptr, sptr, sptr, "Not negotiating now"); + } + + #ifdef USE_SSL + if (mycmp(parv[1], "START") == 0) + { + if (parc != 2) + return exit_client(sptr, sptr, sptr, "TLS START failure"); + + sendto_one(sptr, "TLS VALIDATE %s", me.name); + + sendto_realops("Initiating TLS validation with %s", sptr->name); + return 0; + } + + if (mycmp(parv[1], "VALIDATE") == 0) + { + if (parc < 3) + return exit_client(sptr, sptr, sptr, "TLS VALIDATE failure"); + + X509 *cert = NULL; + X509_NAME *certname = NULL; + char subject[NAME_MAX+1]; + + cert = SSL_get_peer_certificate(sptr->ssl); + + if (cert == NULL) + return exit_client(sptr, sptr, sptr, "Could not get peer certificate"); + + certname = X509_NAME_new(); + certname = X509_get_subject_name(cert); + + X509_NAME_online(certname, subject, NAME_MAX); + sendto_ops_lev(DEBUG_LEV, "Subject name %s [server %s]", + subject, sptr->name); + + sendto_one(sptr, "TLS DONE"); + return 0; + } + + if (mycmp(parv[1], "DONE") == 0) + { + sendto_realops("TLS validation with %s complete", sptr->name); + sendto_one(sptr, "TLS EXIT"); + return 0; + } + + if (mycmp(parv[1], "EXIT") == 0) + { + ClearNegoServer(sptr); + return do_server_estab(sptr); + } + #endif + return 0; +} /* m_dkey * lucas's code, i assume. * moved here from s_serv.c due to its integration in the encrypted diff --git a/src/s_bsd.c b/src/s_bsd.c index 6527591a..d2ae4e78 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -1976,28 +1976,6 @@ int connect_server(aConnect *aconn, aClient * by, struct hostent *hp) free_client(cptr); return -1; } - - /* - * Now that we've connected, let's validate cert DN against aconn->name - */ - X509 *cert = NULL; - X509_NAME *certname = NULL; - - cert = SSL_get_peer_certificate(cptr->ssl); - if (cert == NULL) - { - sendto_realops_lev(DEBUG_LEV, "Could not get SSL peer certificate " - " [server %s]", aconn->name); - } else - { - certname = X509_NAME_new(); - certname = X509_get_subject_name(cert); - char cert_name[NAME_MAX+1]; - X509_NAME_oneline(certname, cert_name, NAME_MAX); - - sendto_realops_lev(DEBUG_LEV, "Got certificate name %s [server %s]", - cert_name, aconn->name); - } } #endif