Changeset 3fbce97 for irc_commands.c
- Timestamp:
- 2016-09-24T20:14:34Z (8 years ago)
- Children:
- ba52ac5
- Parents:
- 63cad66 (diff), 82cb190 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
irc_commands.c
r63cad66 r3fbce97 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 " … … 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.