summary refs log tree commit diff stats
path: root/src/common/inbound.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/inbound.c')
-rw-r--r--src/common/inbound.c114
1 files changed, 97 insertions, 17 deletions
diff --git a/src/common/inbound.c b/src/common/inbound.c
index f57207d1..fca5f071 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -392,6 +392,8 @@ inbound_action (session *sess, char *chan, char *from, char *ip, char *text,
 		user->lasttalk = time (0);
 		if (user->account)
 			id = TRUE;
+		if (user->me)
+			fromme = TRUE;
 	}
 
 	inbound_make_idtext (serv, idtext, sizeof (idtext), id);
@@ -459,6 +461,8 @@ inbound_chanmsg (server *serv, session *sess, char *chan, char *from,
 			id = TRUE;
 		nickchar[0] = user->prefix[0];
 		user->lasttalk = time (0);
+		if (user->me)
+			fromme = TRUE;
 	}
 
 	if (fromme)
@@ -1450,7 +1454,12 @@ nowindow:
 static int
 inbound_exec_eom_cmd (char *str, void *sess)
 {
-	handle_command (sess, (str[0] == '/') ? str + 1 : str, TRUE);
+	char *cmd;
+
+	cmd = command_insert_vars ((session*)sess, (str[0] == '/') ? str + 1 : str);
+	handle_command ((session*)sess, cmd, TRUE);
+	g_free (cmd);
+
 	return 1;
 }
 
@@ -1557,8 +1566,6 @@ void
 inbound_cap_ack (server *serv, char *nick, char *extensions,
 					  const message_tags_data *tags_data)
 {
-	char *pass; /* buffer for SASL password */
-
 	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPACK, serv->server_session, nick, extensions,
 								  NULL, NULL, 0, tags_data->timestamp);
 
@@ -1594,20 +1601,25 @@ inbound_cap_ack (server *serv, char *nick, char *extensions,
 
 	if (strstr (extensions, "sasl") != NULL)
 	{
-		char *user;
-
 		serv->have_sasl = TRUE;
+		serv->sent_saslauth = FALSE;
 
-		user = (((ircnet *)serv->network)->user) 
-			? (((ircnet *)serv->network)->user) : prefs.hex_irc_user_name;
-
-		EMIT_SIGNAL_TIMESTAMP (XP_TE_SASLAUTH, serv->server_session, user, NULL,
-									  NULL,	NULL,	0,	tags_data->timestamp);
+#ifdef USE_OPENSSL
+		if (serv->loginmethod == LOGIN_SASLEXTERNAL)
+		{
+			serv->sasl_mech = MECH_EXTERNAL;
+			tcp_send_len (serv, "AUTHENTICATE EXTERNAL\r\n", 23);
+		}
+		else
+		{
+			/* default to most secure, it will fallback if not supported */
+			serv->sasl_mech = MECH_AES;
+			tcp_send_len (serv, "AUTHENTICATE DH-AES\r\n", 21);
+		}
+#else
+		serv->sasl_mech = MECH_PLAIN;
 		tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20);
-
-		pass = encode_sasl_pass (user, serv->password);
-		tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass);
-		free (pass);
+#endif
 	}
 }
 
@@ -1678,9 +1690,9 @@ 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 (serv->loginmethod == LOGIN_SASL
-			 && strcmp (extension, "sasl") == 0
-			 && strlen (serv->password) != 0)
+		if (!strcmp (extension, "sasl")
+			&& ((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
+			|| (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert)))
 		{
 			strcat (buffer, "sasl ");
 			want_cap = 1;
@@ -1701,6 +1713,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 	if (!want_sasl)
 	{
 		/* if we use SASL, CAP END is dealt via raw numerics */
+		serv->sent_capend = TRUE;
 		tcp_send_len (serv, "CAP END\r\n", 9);
 	}
 }
@@ -1708,6 +1721,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 void
 inbound_cap_nak (server *serv, const message_tags_data *tags_data)
 {
+	serv->sent_capend = TRUE;
 	tcp_send_len (serv, "CAP END\r\n", 9);
 }
 
@@ -1718,3 +1732,69 @@ inbound_cap_list (server *serv, char *nick, char *extensions,
 	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPACK, serv->server_session, nick, extensions,
 								  NULL, NULL, 0, tags_data->timestamp);
 }
+
+static const char *sasl_mechanisms[] =
+{
+	"PLAIN",
+	"DH-BLOWFISH",
+	"DH-AES",
+	"EXTERNAL"
+};
+
+void
+inbound_sasl_authenticate (server *serv, char *data)
+{
+		char *user, *pass = NULL;
+		const char *mech = sasl_mechanisms[serv->sasl_mech];
+
+		user = (((ircnet*)serv->network)->user)
+				? (((ircnet*)serv->network)->user) : prefs.hex_irc_user_name;
+
+		switch (serv->sasl_mech)
+		{
+		case MECH_PLAIN:
+			pass = encode_sasl_pass_plain (user, serv->password);
+			break;
+#ifdef USE_OPENSSL
+		case MECH_BLOWFISH:
+			pass = encode_sasl_pass_blowfish (user, serv->password, data);
+			break;
+		case MECH_AES:
+			pass = encode_sasl_pass_aes (user, serv->password, data);
+			break;
+		case MECH_EXTERNAL:
+			pass = g_strdup ("+");
+			break;
+#endif
+		}
+
+		if (pass == NULL)
+		{
+			/* something went wrong abort */
+			serv->sent_saslauth = TRUE; /* prevent trying PLAIN */
+			tcp_sendf (serv, "AUTHENTICATE *\r\n");
+			return;
+		}
+
+		serv->sent_saslauth = TRUE;
+		tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass);
+		g_free (pass);
+
+		
+		EMIT_SIGNAL_TIMESTAMP (XP_TE_SASLAUTH, serv->server_session, user, (char*)mech,
+								NULL,	NULL,	0,	0);
+}
+
+int
+inbound_sasl_error (server *serv)
+{
+	/* If server sent 904 before we sent password,
+		* mech not support so fallback to next mech */
+	if (!serv->sent_saslauth && serv->sasl_mech != MECH_EXTERNAL && serv->sasl_mech != MECH_PLAIN)
+	{
+		serv->sasl_mech -= 1;
+		tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[serv->sasl_mech]);
+		return 1;
+	}
+	return 0;
+}