Add support for QuakeNet /CHALLENGEAUTH, remove legacy /AUTH

This commit is contained in:
Berke Viktor 2013-05-17 01:39:28 +02:00
parent 096d0660e2
commit a1a94ed319
7 changed files with 115 additions and 28 deletions

View File

@ -1380,7 +1380,10 @@ inbound_nickserv_login (server *serv)
case LOGIN_NICKSERV: case LOGIN_NICKSERV:
case LOGIN_NS: case LOGIN_NS:
case LOGIN_MSG_NS: case LOGIN_MSG_NS:
case LOGIN_CHALLENGEAUTH:
#if 0
case LOGIN_AUTH: case LOGIN_AUTH:
#endif
return 1; return 1;
default: default:
return 0; return 0;

View File

@ -73,29 +73,35 @@ irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3)
case LOGIN_NICKSERV: case LOGIN_NICKSERV:
tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break; break;
case LOGIN_MSG_NS:
tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
#if 0 #if 0
case LOGIN_NS: case LOGIN_NS:
tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3); tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break; break;
#endif
case LOGIN_MSG_NS:
tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
case LOGIN_AUTH: case LOGIN_AUTH:
/* why couldn't QuakeNet implement one of the existing ones? */ /* why couldn't QuakeNet implement one of the existing ones? */
tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2); tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2);
break;
#endif
} }
} }
static void static void
irc_ns_identify (server *serv, char *pass) irc_ns_identify (server *serv, char *pass)
{ {
if (serv->loginmethod == LOGIN_AUTH) /* QuakeNet needs to do everything in its own ways... */ switch (serv->loginmethod)
{ {
case LOGIN_CHALLENGEAUTH:
tcp_sendf (serv, "PRIVMSG %s :CHALLENGE\r\n", CHALLENGEAUTH_NICK); /* request a challenge from Q */
break;
#if 0
case LOGIN_AUTH:
irc_nickserv (serv, "", serv->nick, pass, ""); irc_nickserv (serv, "", serv->nick, pass, "");
} break;
else #endif
{ default:
irc_nickserv (serv, "IDENTIFY", pass, "", ""); irc_nickserv (serv, "IDENTIFY", pass, "", "");
} }
} }
@ -103,7 +109,7 @@ irc_ns_identify (server *serv, char *pass)
static void static void
irc_ns_ghost (server *serv, char *usname, char *pass) irc_ns_ghost (server *serv, char *usname, char *pass)
{ {
if (serv->loginmethod != LOGIN_AUTH) if (serv->loginmethod != LOGIN_AUTH && serv->loginmethod != LOGIN_CHALLENGEAUTH)
{ {
irc_nickserv (serv, "GHOST", usname, " ", pass); irc_nickserv (serv, "GHOST", usname, " ", pass);
} }
@ -1081,10 +1087,20 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
case WORDL('N','O','T','I'): case WORDL('N','O','T','I'):
{ {
int id = FALSE; /* identified */ int id = FALSE; /* identified */
char *response;
text = word_eol[4]; text = word_eol[4];
if (*text == ':') if (*text == ':')
{
text++; text++;
}
if (!strncmp (text, "CHALLENGE ", 10)) /* QuakeNet CHALLENGEAUTH upon our request */
{
response = challengeauth_response (((ircnet *)serv->network)->user, serv->password, word[5]);
tcp_sendf (serv, "PRIVMSG %s :CHALLENGEAUTH %s %s %s\r\n", CHALLENGEAUTH_NICK, ((ircnet *)serv->network)->user, response, CHALLENGEAUTH_ALGO);
g_free (response);
}
if (serv->have_idmsg) if (serv->have_idmsg)
{ {

View File

@ -426,7 +426,7 @@ static const struct defaultserver def[] =
{0, "nfsi.ptnet.org"}, {0, "nfsi.ptnet.org"},
{0, "fctunl.ptnet.org"}, {0, "fctunl.ptnet.org"},
{"QuakeNet", 0, 0, 0, LOGIN_AUTH}, {"QuakeNet", 0, 0, 0, LOGIN_CHALLENGEAUTH},
{0, "irc.quakenet.org"}, {0, "irc.quakenet.org"},
{0, "irc.se.quakenet.org"}, {0, "irc.se.quakenet.org"},
{0, "irc.dk.quakenet.org"}, {0, "irc.dk.quakenet.org"},

View File

@ -75,6 +75,10 @@ extern GSList *network_list;
#define LOGIN_AUTH 5 #define LOGIN_AUTH 5
#define LOGIN_SASL 6 #define LOGIN_SASL 6
#define LOGIN_PASS 7 #define LOGIN_PASS 7
#define LOGIN_CHALLENGEAUTH 8
#define CHALLENGEAUTH_ALGO "HMAC-SHA-256"
#define CHALLENGEAUTH_NICK "Q@CServe.quakenet.org"
/* DEFAULT_CHARSET is already defined in wingdi.h */ /* DEFAULT_CHARSET is already defined in wingdi.h */
#define IRC_DEFAULT_CHARSET "UTF-8 (Unicode)" #define IRC_DEFAULT_CHARSET "UTF-8 (Unicode)"

View File

@ -1978,3 +1978,64 @@ find_font (const char *fontname)
return 0; return 0;
} }
#endif #endif
static char *
str_sha256hash (char *string)
{
int i;
unsigned char hash[SHA256_DIGEST_LENGTH];
char buf[SHA256_DIGEST_LENGTH * 2 + 1]; /* 64 digit hash + '\0' */
SHA256_CTX sha256;
SHA256_Init (&sha256);
SHA256_Update (&sha256, string, strlen (string));
SHA256_Final (hash, &sha256);
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf (buf + (i * 2), "%02x", hash[i]);
}
buf[SHA256_DIGEST_LENGTH * 2] = 0;
return g_strdup (buf);
}
char *
challengeauth_response (char *username, char *password, char *challenge)
{
int i;
char *user;
char *pass;
char *passhash;
char *key;
char *keyhash;
unsigned char *digest;
GString *buf = g_string_new_len (NULL, SHA256_DIGEST_LENGTH * 2);
user = g_strdup (username);
*user = rfc_tolower (*username); /* convert username to lowercase as per the RFC*/
pass = g_strndup (password, 10); /* truncate to 10 characters */
passhash = str_sha256hash (pass);
g_free (pass);
key = g_strdup_printf ("%s:%s", user, passhash);
g_free (user);
g_free (passhash);
keyhash = str_sha256hash (key);
g_free (key);
digest = HMAC (EVP_sha256 (), keyhash, strlen (keyhash), (unsigned char *) challenge, strlen (challenge), NULL, NULL);
g_free (keyhash);
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
g_string_append_printf (buf, "%02x", (unsigned int) digest[i]);
}
digest = (unsigned char *) g_string_free (buf, FALSE);
return (char *) digest;
}

View File

@ -80,5 +80,6 @@ int portable_mode ();
int unity_mode (); int unity_mode ();
GSList *get_subdirs (const char *path); GSList *get_subdirs (const char *path);
char *encode_sasl_pass (char *user, char *pass); char *encode_sasl_pass (char *user, char *pass);
char *challengeauth_response (char *username, char *password, char *challenge);
#endif #endif

View File

@ -121,11 +121,12 @@ static int login_types_conf[] =
LOGIN_PASS, LOGIN_PASS,
LOGIN_MSG_NICKSERV, LOGIN_MSG_NICKSERV,
LOGIN_NICKSERV, LOGIN_NICKSERV,
LOGIN_MSG_NS,
LOGIN_CHALLENGEAUTH
#if 0 #if 0
LOGIN_NS, LOGIN_NS,
#endif
LOGIN_MSG_NS,
LOGIN_AUTH, LOGIN_AUTH,
#endif
}; };
static const char *login_types[]= static const char *login_types[]=
@ -135,11 +136,12 @@ static const char *login_types[]=
"Server Password (/PASS password)", "Server Password (/PASS password)",
"NickServ (/MSG NickServ + password)", "NickServ (/MSG NickServ + password)",
"NickServ (/NICKSERV + password)", "NickServ (/NICKSERV + password)",
"NickServ (/MSG NS + password)",
"Challenge Auth (username + password)",
#if 0 #if 0
"NickServ (/NS + password)", "NickServ (/NS + password)",
#endif
"NickServ (/MSG NS + password)",
"AUTH (/AUTH nickname password)", "AUTH (/AUTH nickname password)",
#endif
NULL NULL
}; };