comparison libfaim/aim_login.c @ 741:58a6e6e26695

[gaim-migrate @ 751] oscar logins work better (?), aliases in convo windows. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 22 Aug 2000 23:38:47 +0000
parents 58106806ac2b
children 72e556f6b99d
comparison
equal deleted inserted replaced
740:01d3c96867e2 741:58a6e6e26695
5 * 5 *
6 */ 6 */
7 7
8 #include <faim/aim.h> 8 #include <faim/aim.h>
9 9
10 #include "md5.h"
11
12 static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest);
10 13
11 /* 14 /*
12 * FIXME: Reimplement the TIS stuff. 15 * FIXME: Reimplement the TIS stuff.
13 */ 16 */
14 #ifdef TIS_TELNET_PROXY 17 #ifdef TIS_TELNET_PROXY
32 35
33 newpacket->lock = 0; 36 newpacket->lock = 0;
34 return aim_tx_enqueue(sess, newpacket); 37 return aim_tx_enqueue(sess, newpacket);
35 } 38 }
36 39
37 #ifdef SNACLOGIN
38 /* 40 /*
39 * In AIM 3.5 protocol, the first stage of login is to request 41 * In AIM 3.5 protocol, the first stage of login is to request
40 * login from the Authorizer, passing it the screen name 42 * login from the Authorizer, passing it the screen name
41 * for verification. If the name is invalid, a 0017/0003 43 * for verification. If the name is invalid, a 0017/0003
42 * is spit back, with the standard error contents. If valid, 44 * is spit back, with the standard error contents. If valid,
60 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); 62 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
61 63
62 newpacket->lock = 0; 64 newpacket->lock = 0;
63 return aim_tx_enqueue(sess, newpacket); 65 return aim_tx_enqueue(sess, newpacket);
64 } 66 }
65 #endif /* SNACLOGIN */
66 67
67 /* 68 /*
68 * send_login(int socket, char *sn, char *password) 69 * send_login(int socket, char *sn, char *password)
69 * 70 *
70 * This is the initial login request packet. 71 * This is the initial login request packet.
74 * stupid method of doing it. 75 * stupid method of doing it.
75 * 76 *
76 */ 77 */
77 int aim_send_login (struct aim_session_t *sess, 78 int aim_send_login (struct aim_session_t *sess,
78 struct aim_conn_t *conn, 79 struct aim_conn_t *conn,
79 char *sn, char *password, struct client_info_s *clientinfo) 80 char *sn, char *password, struct client_info_s *clientinfo,
80 { 81 char *key)
81 u_char *password_encoded = NULL; /* to store encoded password */ 82 {
82 int curbyte=0; 83 int curbyte=0;
83 int icqmode = 0; 84 md5_byte_t digest[16];
84 85
85 struct command_tx_struct *newpacket; 86 struct command_tx_struct *newpacket;
86 87
87 if (!clientinfo || !sn || !password) 88 if (!clientinfo || !sn || !password)
88 return -1; 89 return -1;
89 90
90 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152))) 91 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152)))
91 return -1; 92 return -1;
92 93
93 /*
94 * For ICQ logins, the client version must be at
95 * least as high as ICQ2000a.
96 */
97 if ((sn[0] >= '0') && (sn[0] <= '9')) {
98 icqmode = 1; /* needs a different password encoding */
99 if (clientinfo && (clientinfo->major < 4)) {
100 printf("faim: icq: version must be at least 4.30.3141 for ICQ OSCAR login\n");
101 }
102 if (strlen(password) > 8) {
103 printf("faim: icq: password too long (8 char max)\n");
104 }
105 }
106
107 #ifdef SNACLOGIN
108 newpacket->commandlen = 10;
109 newpacket->commandlen += 2 + 2 + strlen(sn);
110 newpacket->commandlen += 2 + 2 + strlen(password);
111 newpacket->commandlen += 2 + 2 + strlen(clientinfo->clientstring);
112 newpacket->commandlen += 56;
113
114 newpacket->lock = 1; 94 newpacket->lock = 1;
115 95
96 newpacket->hdr.oscar.type = 0x02;
97
116 curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000); 98 curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000);
99
117 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); 100 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
118 password_encoded = (u_char *) malloc(strlen(password)); 101
119 aim_encode_password(password, password_encoded); 102 aim_encode_password_md5(password, key, digest);
120 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); 103 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, digest);
121 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0003,
122 strlen(clientinfo->clientstring),
123 clientinfo->clientstring);
124 /* XXX: should use clientinfo provided version info */
125 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x0004);
126 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0003);
127 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x0005);
128 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0000);
129 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0686);
130 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, 0x0002, clientinfo->country);
131 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, 0x0002, clientinfo->lang);
132 curbyte+= aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x0000002a);
133 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015);
134 #else
135
136 newpacket->lock = 1;
137 newpacket->hdr.oscar.type = 0x01;
138
139 /*
140 * These four bytes are actually the FLAP version information.
141 * They're sent here for convenience. I suppose they could
142 * be seperated out into a seperate FLAP, but this is where
143 * everyone else sends them.
144 */
145 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
146 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
147
148 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
149
150 password_encoded = (char *) malloc(strlen(password));
151 aim_encode_password(password, password_encoded);
152 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded);
153 free(password_encoded);
154 104
155 /* XXX is clientstring required by oscar? */ 105 /* XXX is clientstring required by oscar? */
156 if (strlen(clientinfo->clientstring)) 106 if (strlen(clientinfo->clientstring))
157 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); 107 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring);
158 108
159 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, clientinfo->major2); 109 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, clientinfo->major2);
160 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, clientinfo->major); 110 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, clientinfo->major);
161 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, clientinfo->minor); 111 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, clientinfo->minor);
162 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, clientinfo->minor2); 112 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, clientinfo->minor2);
163 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, clientinfo->build); 113 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, clientinfo->build);
164 114
165 curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); 115 curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown);
116 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015);
166 117
167 if (strlen(clientinfo->country)) 118 if (strlen(clientinfo->country))
168 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); 119 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country);
169 else 120 else
170 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, 2, "us"); 121 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, 2, "us");
173 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang); 124 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang);
174 else 125 else
175 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, 2, "en"); 126 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, 2, "en");
176 127
177 newpacket->commandlen = curbyte; 128 newpacket->commandlen = curbyte;
178 #endif
179 129
180 newpacket->lock = 0; 130 newpacket->lock = 0;
181 return aim_tx_enqueue(sess, newpacket); 131 return aim_tx_enqueue(sess, newpacket);
132 }
133
134 static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest)
135 {
136 md5_state_t state;
137
138 md5_init(&state);
139 md5_append(&state, (const md5_byte_t *)key, strlen(key));
140 md5_append(&state, (const md5_byte_t *)password, strlen(password));
141 md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
142 md5_finish(&state, (md5_byte_t *)digest);
143
144 return 0;
182 } 145 }
183 146
184 /* 147 /*
185 * int encode_password( 148 * int encode_password(
186 * const char *password, 149 * const char *password,
194 * the null. The encoded password buffer IS NOT NULL TERMINATED. 157 * the null. The encoded password buffer IS NOT NULL TERMINATED.
195 * 158 *
196 * The encoding_table seems to be a fixed set of values. We'll 159 * The encoding_table seems to be a fixed set of values. We'll
197 * hope it doesn't change over time! 160 * hope it doesn't change over time!
198 * 161 *
199 */ 162 * NOTE: This is no longer used. Its here for historical reference.
200 int aim_encode_password(const char *password, u_char *encoded) 163 *
164 */
165 #if 0
166 static int aim_encode_password(const char *password, unsigned char *encoded)
201 { 167 {
202 u_char encoding_table[] = { 168 u_char encoding_table[] = {
203 #if 0 /* old v1 table */ 169 #if 0 /* old v1 table */
204 0xf3, 0xb3, 0x6c, 0x99, 170 0xf3, 0xb3, 0x6c, 0x99,
205 0x95, 0x3f, 0xac, 0xb6, 171 0x95, 0x3f, 0xac, 0xb6,
218 for (i = 0; i < strlen(password); i++) 184 for (i = 0; i < strlen(password); i++)
219 encoded[i] = (password[i] ^ encoding_table[i]); 185 encoded[i] = (password[i] ^ encoding_table[i]);
220 186
221 return 0; 187 return 0;
222 } 188 }
189 #endif
223 190
224 /* 191 /*
225 * This is sent back as a general response to the login command. 192 * This is sent back as a general response to the login command.
226 * It can be either an error or a success, depending on the 193 * It can be either an error or a success, depending on the
227 * precense of certain TLVs. 194 * precense of certain TLVs.
241 memset(&sess->logininfo, 0x00, sizeof(sess->logininfo)); 208 memset(&sess->logininfo, 0x00, sizeof(sess->logininfo));
242 209
243 /* 210 /*
244 * Read block of TLVs. All further data is derived 211 * Read block of TLVs. All further data is derived
245 * from what is parsed here. 212 * from what is parsed here.
213 *
214 * For SNAC login, there's a 17/3 SNAC header in front.
215 *
246 */ 216 */
247 #ifdef SNACLOGIN
248 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10); 217 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
249 #else 218
250 tlvlist = aim_readtlvchain(command->data, command->commandlen);
251 #endif
252 /* 219 /*
253 * No matter what, we should have a screen name. 220 * No matter what, we should have a screen name.
254 */ 221 */
255 sn = aim_gettlv_str(tlvlist, 0x0001, 1); 222 sn = aim_gettlv_str(tlvlist, 0x0001, 1);
256 strncpy(sess->logininfo.screen_name, sn, strlen(sn)); 223 strncpy(sess->logininfo.screen_name, sn, strlen(sn));
299 if ((tmptlv = aim_gettlv(tlvlist, 0x0013, 1))) 266 if ((tmptlv = aim_gettlv(tlvlist, 0x0013, 1)))
300 sess->logininfo.regstatus = aimutil_get16(tmptlv->value); 267 sess->logininfo.regstatus = aimutil_get16(tmptlv->value);
301 268
302 } 269 }
303 270
304 #ifdef SNACLOGIN
305 userfunc = aim_callhandler(command->conn, 0x0017, 0x0003); 271 userfunc = aim_callhandler(command->conn, 0x0017, 0x0003);
306 #else 272
307 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS);
308 #endif
309 if (userfunc) 273 if (userfunc)
310 ret = userfunc(sess, command); 274 ret = userfunc(sess, command);
311 275
312 aim_freetlvchain(&tlvlist); 276 aim_freetlvchain(&tlvlist);
313 277
321 } 285 }
322 if (sess->logininfo.errorurl) { 286 if (sess->logininfo.errorurl) {
323 free(sess->logininfo.errorurl); 287 free(sess->logininfo.errorurl);
324 sess->logininfo.errorurl = NULL; 288 sess->logininfo.errorurl = NULL;
325 } 289 }
290
291 return ret;
292 }
293
294 /*
295 * Middle handler for 0017/0007 SNACs. Contains the auth key prefixed
296 * by only its length in a two byte word.
297 *
298 * Calls the client, which should then use the value to call aim_send_login.
299 *
300 */
301 int aim_authkeyparse(struct aim_session_t *sess, struct command_rx_struct *command)
302 {
303 unsigned char *key;
304 int keylen;
305 int ret = 1;
306 rxcallback_t userfunc;
307
308 keylen = aimutil_get16(command->data+10);
309 key = malloc(keylen+1);
310 memcpy(key, command->data+12, keylen);
311 key[keylen] = '\0';
312
313 if ((userfunc = aim_callhandler(command->conn, 0x0017, 0x0007)))
314 ret = userfunc(sess, command, key);
315
316 free(key);
326 317
327 return ret; 318 return ret;
328 } 319 }
329 320
330 /* 321 /*