Implement BLOWFISh, AES, and EXTERNAL SASL mechanisms

Closes #657
This commit is contained in:
TingPing
2013-09-02 14:24:37 -04:00
parent 731fd33be2
commit a903f16c68
11 changed files with 376 additions and 29 deletions

View File

@@ -1566,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);
@@ -1603,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
}
}
@@ -1687,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;
@@ -1710,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);
}
}
@@ -1717,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);
}
@@ -1727,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;
}