Changes in irc_commands.c [9076a1c:c4e61db]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
irc_commands.c
r9076a1c rc4e61db 28 28 #include "help.h" 29 29 #include "ipc.h" 30 #include "base64.h" 30 31 31 32 static void irc_cmd_pass(irc_t *irc, char **cmd) … … 55 56 irc_setpass(irc, cmd[1]); 56 57 irc_check_login(irc); 58 } 59 } 60 61 static gboolean irc_sasl_plain_parse(char *input, char **user, char **pass) 62 { 63 int i, part, len; 64 guint8 *decoded; 65 char *parts[3]; 66 67 /* bitlbee's base64_decode wrapper adds an extra null terminator at the end */ 68 len = base64_decode(input, &decoded); 69 70 /* this loop splits the decoded string into the parts array, like this: 71 "username\0username\0password" -> {"username", "username", "password"} */ 72 73 for (i = 0, part = 0; i < len && part < 3; part++) { 74 /* set each of parts[] to point to the beginning of a string */ 75 parts[part] = (char *) decoded + i; 76 77 /* move the cursor forward to the next null terminator*/ 78 i += strlen(parts[part]) + 1; 79 } 80 81 /* sanity checks */ 82 if (part != 3 || i != (len + 1) || (parts[0][0] && strcmp(parts[0], parts[1]) != 0)) { 83 g_free(decoded); 84 return FALSE; 85 } else { 86 *user = g_strdup(parts[1]); 87 *pass = g_strdup(parts[2]); 88 g_free(decoded); 89 return TRUE; 90 } 91 } 92 93 static gboolean irc_sasl_check_pass(irc_t *irc, char *user, char *pass) 94 { 95 storage_status_t status; 96 97 /* just check the password here to be able to reply with useful numerics 98 * the actual identification will be handled later */ 99 status = storage_check_pass(user, pass); 100 101 if (status == STORAGE_OK) { 102 if (!irc->user->nick) { 103 /* set the nick here so we have it for the following numeric */ 104 irc->user->nick = g_strdup(user); 105 } 106 irc_send_num(irc, 903, ":Password accepted"); 107 return TRUE; 108 109 } else if (status == STORAGE_INVALID_PASSWORD) { 110 irc_send_num(irc, 904, ":Incorrect password"); 111 } else if (status == STORAGE_NO_SUCH_USER) { 112 irc_send_num(irc, 904, ":The nick is (probably) not registered"); 113 } else { 114 irc_send_num(irc, 904, ":Unknown SASL authentication error"); 115 } 116 117 return FALSE; 118 } 119 120 static void irc_cmd_authenticate(irc_t *irc, char **cmd) 121 { 122 /* require the CAP to be enabled, and don't allow authentication before server password */ 123 if (!(irc->caps & CAP_SASL) || 124 (global.conf->authmode == AUTHMODE_CLOSED && !(irc->status & USTATUS_AUTHORIZED))) { 125 return; 126 } 127 128 if (irc->status & USTATUS_SASL_PLAIN_PENDING) { 129 char *user, *pass; 130 131 irc->status &= ~USTATUS_SASL_PLAIN_PENDING; 132 133 if (!irc_sasl_plain_parse(cmd[1], &user, &pass)) { 134 irc_send_num(irc, 904, ":SASL authentication failed"); 135 return; 136 } 137 138 /* let's not support the nick != user case 139 * if NICK is received after SASL, it will just fail after registration */ 140 if (user && irc->user->nick && strcmp(user, irc->user->nick) != 0) { 141 irc_send_num(irc, 902, ":Your SASL username does not match your nickname"); 142 143 } else if (irc_sasl_check_pass(irc, user, pass)) { 144 /* and here we do the same thing as the PASS command*/ 145 if (irc->status & USTATUS_LOGGED_IN) { 146 char *send_cmd[] = { "identify", pass, NULL }; 147 root_command(irc, send_cmd); 148 } else { 149 /* no check_login here - wait for CAP END */ 150 irc_setpass(irc, pass); 151 } 152 } 153 154 g_free(user); 155 g_free(pass); 156 157 } else if (irc->status & USTATUS_IDENTIFIED) { 158 irc_send_num(irc, 907, ":You have already authenticated"); 159 160 } else if (strcmp(cmd[1], "*") == 0) { 161 irc_send_num(irc, 906, ":SASL authentication aborted"); 162 irc->status &= ~USTATUS_SASL_PLAIN_PENDING; 163 164 } else if (g_strcasecmp(cmd[1], "PLAIN") == 0) { 165 irc_write(irc, "AUTHENTICATE +"); 166 irc->status |= USTATUS_SASL_PLAIN_PENDING; 167 168 } else { 169 irc_send_num(irc, 908, "PLAIN :is the available SASL mechanism"); 170 irc_send_num(irc, 904, ":SASL authentication failed"); 171 irc->status &= ~USTATUS_SASL_PLAIN_PENDING; 57 172 } 58 173 } … … 83 198 irc->status &= ~USTATUS_IDENTIFIED; 84 199 irc_umode_set(irc, "-R", 1); 200 201 if (irc->caps & CAP_SASL) { 202 irc_send_num(irc, 901, "%s!%s@%s :You are now logged out", 203 irc->user->nick, irc->user->user, irc->user->host); 204 } 205 85 206 irc_rootmsg(irc, "Changing nicks resets your identify status. " 86 207 "Re-identify or register a new account if you want " … … 166 287 showed an error message, or is doing some work 167 288 before the join should be confirmed. (In the 168 latter case, the calle eshould take care of that289 latter case, the caller should take care of that 169 290 confirmation.) TRUE means all's good, let the 170 291 user join the channel right away. */ … … 685 806 686 807 static const command_t irc_commands[] = { 808 { "cap", 1, irc_cmd_cap, 0 }, 687 809 { "pass", 1, irc_cmd_pass, 0 }, 688 810 { "user", 4, irc_cmd_user, IRC_CMD_PRE_LOGIN }, … … 721 843 { "restart", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 722 844 { "kill", 2, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, 845 { "authenticate", 1, irc_cmd_authenticate, 0 }, 723 846 { NULL } 724 847 };
Note: See TracChangeset
for help on using the changeset viewer.