diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/hexchat.h | 3 | ||||
-rw-r--r-- | src/common/plugin.c | 2 | ||||
-rw-r--r-- | src/common/proto-irc.c | 45 | ||||
-rw-r--r-- | src/common/servlist.c | 29 | ||||
-rw-r--r-- | src/common/servlist.h | 1 | ||||
-rw-r--r-- | src/common/util.c | 24 | ||||
-rw-r--r-- | src/common/util.h | 1 |
7 files changed, 94 insertions, 11 deletions
diff --git a/src/common/hexchat.h b/src/common/hexchat.h index ff7a8bf9..9b5ebf04 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -485,6 +485,8 @@ typedef struct server char hostname[128]; /* real ip number */ char servername[128]; /* what the server says is its name */ char password[86]; + char sasluser[30]; /* this is just a buffer for network->user */ + char saslpassword[86]; /* we could reuse password but then we couldn't guarantee NickServ doesn't register first */ char nick[NICKLEN]; char linebuf[2048]; /* RFC says 512 chars including \r\n */ char *last_away_reason; @@ -547,6 +549,7 @@ typedef struct server unsigned int have_whox:1; /* have undernet's WHOX features */ unsigned int have_capab:1; /* supports CAPAB (005 tells us) */ unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */ + unsigned int have_sasl:1; /* SASL capability */ unsigned int have_except:1; /* ban exemptions +e */ unsigned int using_cp1255:1; /* encoding is CP1255/WINDOWS-1255? */ unsigned int using_irc:1; /* encoding is "IRC" (CP1252/UTF-8 hybrid)? */ diff --git a/src/common/plugin.c b/src/common/plugin.c index cc626659..ac1bce45 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -479,7 +479,7 @@ plugin_auto_load (session *sess) for_files ("./plugins", "hcmpcinfo.dll", plugin_auto_load_cb); for_files ("./plugins", "hcperl.dll", plugin_auto_load_cb); for_files ("./plugins", "hcpython.dll", plugin_auto_load_cb); - for_files ("./plugins", "hcsasl.dll", plugin_auto_load_cb); + /* for_files ("./plugins", "hcsasl.dll", plugin_auto_load_cb); we have this built-in */ for_files ("./plugins", "hctcl.dll", plugin_auto_load_cb); for_files ("./plugins", "hcupd.dll", plugin_auto_load_cb); for_files ("./plugins", "hcwinamp.dll", plugin_auto_load_cb); diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index 342ad221..b8899855 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -47,11 +47,12 @@ static void irc_login (server *serv, char *user, char *realname) { + tcp_sendf (serv, "CAP LS\r\n"); /* start with CAP LS as Charybdis sasl.txt suggests */ + if (serv->password[0]) + { tcp_sendf (serv, "PASS %s\r\n", serv->password); -#if 0 /* breaks the SASL plugin */ - tcp_sendf (serv, "CAP LS\r\n"); -#endif + } tcp_sendf (serv, "NICK %s\r\n" @@ -880,6 +881,15 @@ process_numeric (session * sess, int n, notify_set_online (serv, word[4]); break; + case 903: /* successful SASL auth */ + case 904: /* aborted SASL auth */ + case 905: /* failed SASL auth */ + case 906: /* registration completes before SASL auth */ + case 907: /* attempting to re-auth after a successful auth */ + tcp_send_len (serv, "CAP END\r\n", 9); + PrintTextf (sess, "%s\n", ++word_eol[4]); + break; + default: if (serv->inside_whois && word[4][0]) @@ -1117,10 +1127,10 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) } } -#if 0 /* breaks the SASL plugin */ else if (len == 3) { guint32 t; + char *pass; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); switch (t) @@ -1131,28 +1141,45 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) if (strncasecmp (word[5][0]==':' ? word[5] + 1 : word[5], "identify-msg", 12) == 0) { serv->have_idmsg = TRUE; - tcp_send_len (serv, "CAP END\r\n", 9); + } + if (strncasecmp (word[5][0]==':' ? word[5] + 1 : word[5], "sasl", 12) == 0) + { + serv->have_sasl = TRUE; + PrintTextf (sess, "Authenticating via SASL as %s\n", sess->server->sasluser); + tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20); + + pass = encode_sasl_pass (sess->server->sasluser, sess->server->saslpassword); + tcp_sendf (sess->server, "AUTHENTICATE %s\r\n", pass); + free (pass); } } else if (strncasecmp (word[4], "LS", 2) == 0) { + PrintTextf (sess, "Capabilities supported by the server: %s\n", ++word_eol[5]); if (strstr (word_eol[5], "identify-msg") != 0) { tcp_send_len (serv, "CAP REQ :identify-msg\r\n", 23); } + + /* if the SASL password is set, request SASL auth */ + if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0) + { + tcp_send_len (serv, "CAP REQ :sasl\r\n", 23); + } else { + /* if we use SASL, CAP END is dealt via raw numerics */ tcp_send_len (serv, "CAP END\r\n", 9); } } - else if (strncasecmp (word[4], "NAK",3) == 0) + else if (strncasecmp (word[4], "NAK", 3) == 0) { tcp_send_len (serv, "CAP END\r\n", 9); } + return; } } -#endif garbage: /* unknown message */ @@ -1184,6 +1211,10 @@ process_named_servermsg (session *sess, char *buf, char *rawname, char *word_eol EMIT_SIGNAL (XP_TE_SERVNOTICE, sess, buf, sess->server->servername, NULL, NULL, 0); return; } + if (!strncmp (buf, "AUTHENTICATE +", 14)) /* omit SASL "empty" responses */ + { + return; + } EMIT_SIGNAL (XP_TE_SERVTEXT, sess, buf, sess->server->servername, rawname, NULL, 0); } diff --git a/src/common/servlist.c b/src/common/servlist.c index 86a78ebf..6529b162 100644 --- a/src/common/servlist.c +++ b/src/common/servlist.c @@ -608,13 +608,33 @@ servlist_connect (session *sess, ircnet *net, gboolean join) } serv->password[0] = 0; + serv->sasluser[0] = 0; + serv->saslpassword[0] = 0; + if (net->pass) + { safe_strcpy (serv->password, net->pass, sizeof (serv->password)); + } + + if (net->flags & FLAG_USE_GLOBAL) + { + strcpy (serv->sasluser, prefs.hex_irc_user_name); + } + else if (net->user != NULL) + { + safe_strcpy (serv->sasluser, net->user, sizeof (serv->sasluser)); + } + + if (net->saslpass) + { + safe_strcpy (serv->saslpassword, net->saslpass, sizeof (serv->saslpassword)); + } if (net->flags & FLAG_USE_GLOBAL) { strcpy (serv->nick, prefs.hex_irc_nick1); - } else + } + else { if (net->nick) strcpy (serv->nick, net->nick); @@ -901,6 +921,7 @@ servlist_cleanup (void) { net = list->data; free_and_clear (net->pass); + free_and_clear (net->saslpass); free_and_clear (net->nickserv); } } @@ -923,6 +944,7 @@ servlist_net_remove (ircnet *net) if (net->real) free (net->real); free_and_clear (net->pass); + free_and_clear (net->saslpass); if (net->autojoin) free (net->autojoin); if (net->command) @@ -1035,6 +1057,9 @@ servlist_load (void) case 'P': net->pass = strdup (buf + 2); break; + case 'A': + net->saslpass = strdup (buf + 2); + break; case 'J': net->autojoin = strdup (buf + 2); break; @@ -1166,6 +1191,8 @@ servlist_save (void) fprintf (fp, "R=%s\n", net->real); if (net->pass) fprintf (fp, "P=%s\n", net->pass); + if (net->saslpass) + fprintf (fp, "A=%s\n", net->saslpass); if (net->autojoin) fprintf (fp, "J=%s\n", net->autojoin); if (net->nickserv) diff --git a/src/common/servlist.h b/src/common/servlist.h index e78f94b1..dc8095f4 100644 --- a/src/common/servlist.h +++ b/src/common/servlist.h @@ -14,6 +14,7 @@ typedef struct ircnet char *user; char *real; char *pass; + char *saslpass; char *autojoin; char *command; char *nickserv; diff --git a/src/common/util.c b/src/common/util.c index 5120c25a..0881c708 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -681,7 +681,7 @@ get_cpu_str (void) double mhz; osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - GetVersionEx (&osvi); + GetVersionEx ((OSVERSIONINFO*) &osvi); switch (osvi.dwMajorVersion) { @@ -740,7 +740,7 @@ get_cpu_str (void) } else { - strcpy (winver, "8 Server"); + strcpy (winver, "Server 2012"); } break; } @@ -1966,3 +1966,23 @@ get_subdirs (const char *path) return dirlist; } + +char * +encode_sasl_pass (char *user, char *pass) +{ + int passlen; + char *buffer; + char *encoded; + + /* passphrase generation, nicely copy-pasted from the CAP-SASL plugin */ + passlen = strlen (user) * 2 + 2 + strlen (pass); + buffer = (char*) malloc (passlen + 1); + strcpy (buffer, user); + strcpy (buffer + strlen (user) + 1, user); + strcpy (buffer + strlen (user) * 2 + 2, pass); + encoded = g_base64_encode ((unsigned char*) buffer, passlen); + + free (buffer); + + return encoded; +} diff --git a/src/common/util.h b/src/common/util.h index 484cd617..d2e8e84e 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -61,5 +61,6 @@ void canonalize_key (char *key); int portable_mode (); int hextray_mode (); GSList *get_subdirs (const char *path); +char *encode_sasl_pass (char *user, char *pass); #endif |