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_NS:
case LOGIN_MSG_NS:
case LOGIN_CHALLENGEAUTH:
#if 0
case LOGIN_AUTH:
#endif
return 1;
default:
return 0;

View File

@ -73,29 +73,35 @@ irc_nickserv (server *serv, char *cmd, char *arg1, char *arg2, char *arg3)
case LOGIN_NICKSERV:
tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
case LOGIN_MSG_NS:
tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3);
break;
#if 0
case LOGIN_NS:
tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3);
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:
/* why couldn't QuakeNet implement one of the existing ones? */
tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2);
break;
#endif
}
}
static void
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, "");
}
else
{
break;
#endif
default:
irc_nickserv (serv, "IDENTIFY", pass, "", "");
}
}
@ -103,7 +109,7 @@ irc_ns_identify (server *serv, char *pass)
static void
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);
}
@ -1081,10 +1087,20 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
case WORDL('N','O','T','I'):
{
int id = FALSE; /* identified */
char *response;
text = word_eol[4];
if (*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)
{

View File

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

View File

@ -75,6 +75,10 @@ extern GSList *network_list;
#define LOGIN_AUTH 5
#define LOGIN_SASL 6
#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 */
#define IRC_DEFAULT_CHARSET "UTF-8 (Unicode)"

View File

@ -1978,3 +1978,64 @@ find_font (const char *fontname)
return 0;
}
#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 ();
GSList *get_subdirs (const char *path);
char *encode_sasl_pass (char *user, char *pass);
char *challengeauth_response (char *username, char *password, char *challenge);
#endif

View File

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