Merge infrastructure for SASL authentication support from flashback.
This includes all of the underlying support, but doesn't hook it up to the /SERVER command yet, so it's not useable at this point. git-svn-id: svn://svn.code.sf.net/p/bitchx/code/trunk@216 13b04d17-f746-0410-82c6-800466cd88b0
This commit is contained in:
@@ -887,6 +887,75 @@ static void p_error(char *from, char **ArgList)
|
||||
say("%s", ArgList[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This only handles negotiating the SASL capability with the PLAIN method. It would
|
||||
* be good to add DH-BLOWFISH, and later, full capability support.
|
||||
*/
|
||||
static void p_cap(char *from, char **ArgList)
|
||||
{
|
||||
char *caps, *p;
|
||||
|
||||
if (!strcmp(ArgList[1], "ACK"))
|
||||
{
|
||||
caps = LOCAL_COPY(ArgList[2]);
|
||||
while ((p = next_arg(caps, &caps)) != NULL)
|
||||
{
|
||||
/* Only AUTHENTICATE before registration */
|
||||
if (!strcmp(p, "sasl") && !is_server_connected(from_server))
|
||||
{
|
||||
my_send_to_server(from_server, "AUTHENTICATE PLAIN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp(ArgList[1], "NAK"))
|
||||
{
|
||||
caps = LOCAL_COPY(ArgList[2]);
|
||||
while ((p = next_arg(caps, &caps)) != NULL)
|
||||
{
|
||||
/* End capability negotiation to continue registration */
|
||||
if (!strcmp(p, "sasl") && !is_server_connected(from_server))
|
||||
{
|
||||
my_send_to_server(from_server, "CAP END");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void p_authenticate(char *from, char **ArgList)
|
||||
{
|
||||
/* "AUTHENTICATE command MUST be used before registration is complete" */
|
||||
if (is_server_connected(from_server))
|
||||
return;
|
||||
|
||||
if (!strcmp(ArgList[0], "+"))
|
||||
{
|
||||
/* Message is BASE64(nick\0nick\0pass) */
|
||||
char buf[IRCD_BUFFER_SIZE];
|
||||
char *output = NULL;
|
||||
char *nick = get_server_sasl_nick(from_server);
|
||||
char *pass = get_server_sasl_pass(from_server);
|
||||
size_t nick_len = nick ? strlen(nick) + 1 : 0; /* nick_len includes \0 */
|
||||
size_t pass_len = pass ? strlen(pass) : 0;
|
||||
|
||||
/* "The client can abort an authentication by sending an asterisk as the data" */
|
||||
if (!nick || !pass || nick_len * 2 + pass_len > sizeof buf)
|
||||
{
|
||||
my_send_to_server(from_server, "AUTHENTICATE *");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(buf, nick, nick_len);
|
||||
memcpy(buf + nick_len, nick, nick_len);
|
||||
memcpy(buf + nick_len * 2, pass, pass_len);
|
||||
|
||||
output = base64_encode(buf, nick_len * 2 + pass_len);
|
||||
my_send_to_server(from_server, "AUTHENTICATE %s", output);
|
||||
new_free(&output);
|
||||
}
|
||||
}
|
||||
|
||||
void add_user_who (WhoEntry *w, char *from, char **ArgList)
|
||||
{
|
||||
char *userhost;
|
||||
@@ -1758,7 +1827,9 @@ static void p_rpong (char *from, char **ArgList)
|
||||
|
||||
protocol_command rfc1459[] = {
|
||||
{ "ADMIN", NULL, NULL, 0, 0, 0},
|
||||
{ "AUTHENTICATE", p_authenticate, NULL, 0, 0, 0},
|
||||
{ "AWAY", NULL, NULL, 0, 0, 0},
|
||||
{ "CAP", p_cap, NULL, 0, 0, 0},
|
||||
{ "CONNECT", NULL, NULL, 0, 0, 0},
|
||||
{ "ERROR", p_error, NULL, 0, 0, 0},
|
||||
{ "ERROR:", p_error, NULL, 0, 0, 0},
|
||||
|
||||
Reference in New Issue
Block a user