Added support for SCRAM-SHA-1, SCRAM-SHA-256 and SCRAM-SHA-512

This commit is contained in:
Patrick Okraku
2023-11-01 19:12:32 +01:00
committed by Patrick Griffis
parent 6420fd6117
commit 9b76b557ec
12 changed files with 534 additions and 6 deletions

View File

@@ -1648,7 +1648,10 @@ inbound_identified (server *serv) /* 'MODE +e MYSELF' on freenode */
static const char *sasl_mechanisms[] =
{
"PLAIN",
"EXTERNAL"
"EXTERNAL",
"SCRAM-SHA-1",
"SCRAM-SHA-256",
"SCRAM-SHA-512"
};
static void
@@ -1689,6 +1692,12 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable)
#ifdef USE_OPENSSL
if (serv->loginmethod == LOGIN_SASLEXTERNAL)
serv->sasl_mech = MECH_EXTERNAL;
else if (serv->loginmethod == LOGIN_SASL_SCRAM_SHA_1)
serv->sasl_mech = MECH_SCRAM_SHA_1;
else if (serv->loginmethod == LOGIN_SASL_SCRAM_SHA_256)
serv->sasl_mech = MECH_SCRAM_SHA_256;
else if (serv->loginmethod == LOGIN_SASL_SCRAM_SHA_512)
serv->sasl_mech = MECH_SCRAM_SHA_512;
#endif
/* Mechanism either defaulted to PLAIN or server gave us list */
tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[serv->sasl_mech]);
@@ -1766,6 +1775,30 @@ get_supported_mech (server *serv, const char *list)
break;
}
}
else if (serv->loginmethod == LOGIN_SASL_SCRAM_SHA_1)
{
if (!strcmp(mechs[i], "SCRAM-SHA-1"))
{
ret = MECH_SCRAM_SHA_1;
break;
}
}
else if (serv->loginmethod == LOGIN_SASL_SCRAM_SHA_256)
{
if (!strcmp(mechs[i], "SCRAM-SHA-256"))
{
ret = MECH_SCRAM_SHA_256;
break;
}
}
else if (serv->loginmethod == LOGIN_SASL_SCRAM_SHA_512)
{
if (!strcmp(mechs[i], "SCRAM-SHA-512"))
{
ret = MECH_SCRAM_SHA_512;
break;
}
}
else
#endif
if (!strcmp (mechs[i], "PLAIN"))
@@ -1821,7 +1854,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
|| serv->loginmethod == LOGIN_SASL_SCRAM_SHA_1
|| serv->loginmethod == LOGIN_SASL_SCRAM_SHA_256
|| serv->loginmethod == LOGIN_SASL_SCRAM_SHA_512)
&& strlen (serv->password) != 0)
|| serv->loginmethod == LOGIN_SASLEXTERNAL))
{
if (value)
@@ -1902,7 +1939,7 @@ inbound_cap_list (server *serv, char *nick, char *extensions,
}
static void
plain_authenticate(server *serv, char *user, char *password)
plain_authenticate (server *serv, char *user, char *password)
{
char *pass = encode_sasl_pass_plain (user, password);
@@ -1933,11 +1970,71 @@ plain_authenticate(server *serv, char *user, char *password)
tcp_sendf (serv, "AUTHENTICATE +\r\n");
}
#ifdef USE_OPENSSL
/*
* Sends AUTHENTICATE messages to log in via SCRAM.
*/
static void
scram_authenticate (server *serv, const char *data, const char *digest,
const char *user, const char *password)
{
char *encoded, *decoded, *output;
scram_status status;
size_t output_len;
gsize decoded_len;
if (serv->scram_session == NULL)
{
serv->scram_session = scram_create_session (digest, user, password);
if (serv->scram_session == NULL)
{
PrintTextf (serv->server_session, _("Could not create SCRAM session with digest %s"), digest);
g_warning ("Could not create SCRAM session with digest %s", digest);
tcp_sendf (serv, "AUTHENTICATE *\r\n");
return;
}
}
decoded = g_base64_decode (data, &decoded_len);
status = scram_process (serv->scram_session, decoded, &output, &output_len);
g_free (decoded);
if (status == SCRAM_IN_PROGRESS)
{
// Authentication is still in progress
encoded = g_base64_encode ((guchar *) output, output_len);
tcp_sendf (serv, "AUTHENTICATE %s\r\n", encoded);
g_free (encoded);
g_free (output);
}
else if (status == SCRAM_SUCCESS)
{
// Authentication succeeded
tcp_sendf (serv, "AUTHENTICATE +\r\n");
g_clear_pointer (&serv->scram_session, scram_free_session);
}
else if (status == SCRAM_ERROR)
{
// Authentication failed
tcp_sendf (serv, "AUTHENTICATE *\r\n");
if (serv->scram_session->error != NULL)
{
PrintTextf (serv->server_session, _("SASL SCRAM authentication failed: %s"), serv->scram_session->error);
g_info ("SASL SCRAM authentication failed: %s", serv->scram_session->error);
}
g_clear_pointer (&serv->scram_session, scram_free_session);
}
}
#endif
void
inbound_sasl_authenticate (server *serv, char *data)
{
ircnet *net = (ircnet*)serv->network;
char *user, *pass = NULL;
char *user;
const char *mech = sasl_mechanisms[serv->sasl_mech];
/* Got a list of supported mechanisms from outdated inspircd
@@ -1959,6 +2056,15 @@ inbound_sasl_authenticate (server *serv, char *data)
case MECH_EXTERNAL:
tcp_sendf (serv, "AUTHENTICATE +\r\n");
break;
case MECH_SCRAM_SHA_1:
scram_authenticate(serv, data, "SHA1", user, serv->password);
return;
case MECH_SCRAM_SHA_256:
scram_authenticate(serv, data, "SHA256", user, serv->password);
return;
case MECH_SCRAM_SHA_512:
scram_authenticate(serv, data, "SHA512", user, serv->password);
return;
#endif
}
@@ -1969,6 +2075,9 @@ inbound_sasl_authenticate (server *serv, char *data)
void
inbound_sasl_error (server *serv)
{
#ifdef USE_OPENSSL
g_clear_pointer (&serv->scram_session, scram_free_session);
#endif
/* Just abort, not much we can do */
tcp_sendf (serv, "AUTHENTICATE *\r\n");
}