summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/hexchat.h3
-rw-r--r--src/common/inbound.c18
-rw-r--r--src/common/server.c38
-rw-r--r--src/common/servlist.h2
-rw-r--r--src/fe-gtk/servlistgui.c8
5 files changed, 65 insertions, 4 deletions
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