From 390240ac622ab1d81704bad694ba6187738ae9b8 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Fri, 28 May 2021 00:26:37 -0300 Subject: Initial TLS-SRP support --- src/common/hexchat.h | 3 +++ src/common/inbound.c | 18 +++++++++++++++--- src/common/server.c | 38 +++++++++++++++++++++++++++++++++++++- src/common/servlist.h | 2 ++ src/fe-gtk/servlistgui.c | 8 ++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/common/hexchat.h b/src/common/hexchat.h index d8effa1f..7ea25f71 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -584,6 +584,9 @@ typedef struct server #ifdef USE_OPENSSL unsigned int use_ssl:1; /* is server SSL capable? */ unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */ +#ifndef OPENSSL_NO_SRP + unsigned int use_pake:1;/* ignore lack of cert */ +#endif #endif } server; diff --git a/src/common/inbound.c b/src/common/inbound.c index 7175b2ae..d6155001 100644 --- a/src/common/inbound.c +++ b/src/common/inbound.c @@ -1679,7 +1679,11 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable) if (enable) { #ifdef USE_OPENSSL - if (serv->loginmethod == LOGIN_SASLEXTERNAL) + if (serv->loginmethod == LOGIN_SASLEXTERNAL +#ifndef OPENSSL_NO_SRP + || serv->loginmethod == LOGIN_SASLPAKE +#endif + ) serv->sasl_mech = MECH_EXTERNAL; #endif /* Mechanism either defaulted to PLAIN or server gave us list */ @@ -1748,7 +1752,11 @@ get_supported_mech (server *serv, const char *list) for (i = 0; mechs[i]; ++i) { #ifdef USE_OPENSSL - if (serv->loginmethod == LOGIN_SASLEXTERNAL) + if (serv->loginmethod == LOGIN_SASLEXTERNAL +#ifndef OPENSSL_NO_SRP + || serv->loginmethod == LOGIN_SASLPAKE +#endif + ) { if (!strcmp (mechs[i], "EXTERNAL")) { @@ -1811,7 +1819,11 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str, /* if the SASL password is set AND auth mode is set to SASL, request SASL auth */ if (!g_strcmp0 (extension, "sasl") && - ((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0) + (((serv->loginmethod == LOGIN_SASL +#ifndef OPENSSL_NO_SRP + || serv->loginmethod == LOGIN_SASLPAKE +#endif + ) && strlen (serv->password) != 0) || serv->loginmethod == LOGIN_SASLEXTERNAL)) { if (value) diff --git a/src/common/server.c b/src/common/server.c index 5c645eb5..3dd92be3 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -596,6 +596,9 @@ ssl_do_connect (server * serv) EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); } else +#ifndef OPENSSL_NO_SRP + if (!serv->use_pake) +#endif { g_snprintf (buf, sizeof (buf), "No Certificate"); goto conn_fail; @@ -618,7 +621,8 @@ ssl_do_connect (server * serv) { X509 *cert = SSL_get_peer_certificate (serv->ssl); int hostname_err; - if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0) + /* cert may be NULL due to pake */ + if (cert && (hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0) { g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s", hostname_err, serv->accept_invalid_cert ? " -- Ignored" : ""); @@ -1601,6 +1605,38 @@ server_connect (server *serv, char *hostname, int port, int no_login) } } g_free (cert_file); + +#ifndef OPENSSL_NO_SRP + /* also setup PAKE/SRP */ + if (serv->password[0] && (serv->loginmethod == LOGIN_SASLPAKE || serv->loginmethod == LOGIN_PAKE)) { + char *username; + char *password; + ircnet *net = (ircnet*)serv->network; + + if (net->user && !(net->flags & FLAG_USE_GLOBAL)) + username = net->user; + else + username = prefs.hex_irc_user_name; + password = serv->password; + + if (strlen(username) < 255) { + if (SSL_CTX_set_srp_username(serv->ctx, username) && + SSL_CTX_set_srp_password(serv->ctx, password)) { + serv->use_pake = TRUE; + } else { + goto pakefail; + } + } else { + goto pakefail; + } + } else { +pakefail: + /* clear PAKE just in case */ + SSL_CTX_set_srp_username(serv->ctx, NULL); + SSL_CTX_set_srp_password(serv->ctx, NULL); + serv->use_pake = FALSE; + } +#endif } #endif diff --git a/src/common/servlist.h b/src/common/servlist.h index ec885fef..bb8eac7f 100644 --- a/src/common/servlist.h +++ b/src/common/servlist.h @@ -79,6 +79,8 @@ extern GSList *network_list; #define LOGIN_CHALLENGEAUTH 8 #define LOGIN_CUSTOM 9 #define LOGIN_SASLEXTERNAL 10 +#define LOGIN_SASLPAKE 11 +#define LOGIN_PAKE 12 #define CHALLENGEAUTH_ALGO "HMAC-SHA-256" #define CHALLENGEAUTH_NICK "Q@CServe.quakenet.org" diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c index b22330ac..12a33de4 100644 --- a/src/fe-gtk/servlistgui.c +++ b/src/fe-gtk/servlistgui.c @@ -128,6 +128,10 @@ static int login_types_conf[] = LOGIN_NICKSERV, #ifdef USE_OPENSSL LOGIN_CHALLENGEAUTH, +#ifndef OPENSSL_NO_SRP + LOGIN_PAKE, + LOGIN_SASLPAKE, +#endif #endif LOGIN_CUSTOM #if 0 @@ -149,6 +153,10 @@ static const char *login_types[]= "NickServ (/NICKSERV + password)", #ifdef USE_OPENSSL "Challenge Auth (username + password)", +#ifndef OPENSSL_NO_SRP + "PAKE (username + password)", + "SASL EXTERNAL+PAKE (username + password)", +#endif #endif "Custom... (connect commands)", #if 0 -- cgit 1.4.1