comparison libfaim/aim_login.c @ 237:6ced2f1c8b24

[gaim-migrate @ 247] How cool is this, libfaim is making a comeback. I completely redid everything, as was necessary because of the updates to libfaim since gaim 0.9.7. You can sign on and send/recv IMs, but there's a bad lag between display updates that I haven't figured out how to fix yet. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sat, 20 May 2000 00:30:53 +0000
parents 68b230f8da5f
children cfc73b8501a7
comparison
equal deleted inserted replaced
236:62d470738cc7 237:6ced2f1c8b24
3 * 3 *
4 * This contains all the functions needed to actually login. 4 * This contains all the functions needed to actually login.
5 * 5 *
6 */ 6 */
7 7
8 #include "aim.h" 8 #include <aim.h>
9 9
10 10
11 /* 11 /*
12 * FIXME: Reimplement the TIS stuff. 12 * FIXME: Reimplement the TIS stuff.
13 */ 13 */
14 #ifdef TIS_TELNET_PROXY 14 #ifdef TIS_TELNET_PROXY
15 #include "tis_telnet_proxy.h" 15 #include "tis_telnet_proxy.h"
16 #endif 16 #endif
17 17
18 /* 18 int aim_sendconnack(struct aim_session_t *sess,
19 * send_login(int socket, char *sn, char *password) 19 struct aim_conn_t *conn)
20 {
21 int curbyte=0;
22
23 struct command_tx_struct *newpacket;
24
25 if (!(newpacket = aim_tx_new(0x0001, conn, 4)))
26 return -1;
27
28 newpacket->lock = 1;
29
30 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
31 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
32
33 newpacket->lock = 0;
34 return aim_tx_enqueue(sess, newpacket);
35 }
36
37 #ifdef SNACLOGIN
38 /*
39 * In AIM 3.5 protocol, the first stage of login is to request
40 * login from the Authorizer, passing it the screen name
41 * for verification. If the name is invalid, a 0017/0003
42 * is spit back, with the standard error contents. If valid,
43 * a 0017/0007 comes back, which is the signal to send
44 * it the main login command (0017/0002).
45 */
46 int aim_request_login(struct aim_session_t *sess,
47 struct aim_conn_t *conn,
48 char *sn)
49 {
50 int curbyte=0;
51
52 struct command_tx_struct *newpacket;
53
54 if (!(newpacket = aim_tx_new(0x0002, conn, 10+2+2+strlen(sn))))
55 return -1;
56
57 newpacket->lock = 1;
58
59 curbyte += aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0006, 0x0000, 0x00010000);
60 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
61
62 newpacket->lock = 0;
63 return aim_tx_enqueue(sess, newpacket);
64 }
65 #endif /* SNACLOGIN */
66
67 /*
68 * send_login(int socket, char *sn, char *password)
20 * 69 *
21 * This is the initial login request packet. 70 * This is the initial login request packet.
22 * 71 *
23 * The password is encoded before transmition, as per 72 * The password is encoded before transmition, as per
24 * encode_password(). See that function for their 73 * encode_password(). See that function for their
25 * stupid method of doing it. 74 * stupid method of doing it.
26 * 75 *
27 * 76 */
28 * 77 int aim_send_login (struct aim_session_t *sess,
29 */ 78 struct aim_conn_t *conn,
30 int aim_send_login (struct aim_conn_t *conn, char *sn, char *password, struct client_info_s *clientinfo) 79 char *sn, char *password, struct client_info_s *clientinfo)
31 { 80 {
32 char *password_encoded = NULL; /* to store encoded password */ 81 u_char *password_encoded = NULL; /* to store encoded password */
33 int curbyte=0; 82 int curbyte=0;
34 83
35 struct command_tx_struct newpacket; 84 struct command_tx_struct *newpacket;
36 85
37 if (conn) 86 if (!clientinfo || !sn || !password)
38 newpacket.conn = conn; 87 return -1;
39 else 88
40 newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH); 89 if (!(newpacket = aim_tx_new(0x0002, conn, 1152)))
41 90 return -1;
42 newpacket.commandlen = 6+2+strlen(sn)+1+1+2+strlen(password)+6; 91
43 92 #ifdef SNACLOGIN
44 if (clientinfo) 93 newpacket->commandlen = 10;
45 { 94 newpacket->commandlen += 2 + 2 + strlen(sn);
46 if (strlen(clientinfo->clientstring)) 95 newpacket->commandlen += 2 + 2 + strlen(password);
47 newpacket.commandlen += strlen(clientinfo->clientstring)+4; 96 newpacket->commandlen += 2 + 2 + strlen(clientinfo->clientstring);
48 newpacket.commandlen += 6+6+6; 97 newpacket->commandlen += 56;
49 if (strlen(clientinfo->country)) 98
50 newpacket.commandlen += strlen(clientinfo->country)+4; 99 newpacket->lock = 1;
51 if (strlen(clientinfo->lang)) 100
52 newpacket.commandlen += strlen(clientinfo->lang)+4; 101 curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000);
53 } 102 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
54 103 password_encoded = (u_char *) malloc(strlen(password));
55 newpacket.data = (char *) calloc (1, newpacket.commandlen ); 104 aim_encode_password(password, password_encoded);
56 newpacket.lock = 1; 105 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded);
57 newpacket.type = 0x01; 106 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0003,
58 107 strlen(clientinfo->clientstring),
59 curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000); 108 clientinfo->clientstring);
60 curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); 109 /* XXX: should use clientinfo provided version info */
61 curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); 110 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x0004);
62 curbyte += aimutil_put16(newpacket.data+curbyte, strlen(sn)); 111 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0003);
63 curbyte += aimutil_putstr(newpacket.data+curbyte, sn, strlen(sn)); 112 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x0005);
64 113 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0000);
65 curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002); 114 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0686);
66 curbyte += aimutil_put16(newpacket.data+curbyte, strlen(password)); 115 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, 0x0002, clientinfo->country);
116 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, 0x0002, clientinfo->lang);
117 curbyte+= aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x0000002a);
118 curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015);
119 #else
120
121 newpacket->commandlen = 4 + 4+strlen(sn) + 4+strlen(password) + 6;
122
123 if (clientinfo) {
124 if (strlen(clientinfo->clientstring))
125 newpacket->commandlen += 4+strlen(clientinfo->clientstring);
126 newpacket->commandlen += 6+6+6+6;
127 if (strlen(clientinfo->country))
128 newpacket->commandlen += 4+strlen(clientinfo->country);
129 if (strlen(clientinfo->lang))
130 newpacket->commandlen += 4+strlen(clientinfo->lang);
131 }
132 newpacket->commandlen += 6;
133
134 newpacket->lock = 1;
135 newpacket->type = 0x01;
136
137 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
138 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
139 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
140 curbyte += aimutil_put16(newpacket->data+curbyte, strlen(sn));
141 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn));
142
143 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
144 curbyte += aimutil_put16(newpacket->data+curbyte, strlen(password));
67 password_encoded = (char *) malloc(strlen(password)); 145 password_encoded = (char *) malloc(strlen(password));
68 aim_encode_password(password, password_encoded); 146 aim_encode_password(password, password_encoded);
69 curbyte += aimutil_putstr(newpacket.data+curbyte, password_encoded, strlen(password)); 147 curbyte += aimutil_putstr(newpacket->data+curbyte, password_encoded, strlen(password));
70 free(password_encoded); 148 free(password_encoded);
71 149
72 curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0016, 0x0001); 150 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x0004);
73 151
74 if (clientinfo) 152 if (clientinfo) {
75 { 153 if (strlen(clientinfo->clientstring)) {
76 if (strlen(clientinfo->clientstring)) 154 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
77 { 155 curbyte += aimutil_put16(newpacket->data+curbyte, strlen(clientinfo->clientstring));
78 curbyte += aimutil_put16(newpacket.data+curbyte, 0x0003); 156 curbyte += aimutil_putstr(newpacket->data+curbyte, clientinfo->clientstring, strlen(clientinfo->clientstring));
79 curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->clientstring));
80 curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->clientstring, strlen(clientinfo->clientstring));
81 }
82 curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0017, 0x0001);
83 curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0018, 0x0001);
84 curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x001a, 0x0013);
85 if (strlen(clientinfo->country))
86 {
87 curbyte += aimutil_put16(newpacket.data+curbyte, 0x000e);
88 curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->country));
89 curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->country, strlen(clientinfo->country));
90 }
91 if (strlen(clientinfo->lang))
92 {
93 curbyte += aimutil_put16(newpacket.data+curbyte, 0x000f);
94 curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->lang));
95 curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->lang, strlen(clientinfo->lang));
96 }
97 } 157 }
98 158 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, clientinfo->major /*0x0001*/);
99 curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0009, 0x0015); 159 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, clientinfo->minor /*0x0001*/);
100 160 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0000);
101 newpacket.lock = 0; 161 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, clientinfo->build /*0x0013*/);
102 aim_tx_enqueue(&newpacket); 162 if (strlen(clientinfo->country)) {
103 163 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000e);
104 return 0; 164 curbyte += aimutil_put16(newpacket->data+curbyte, strlen(clientinfo->country));
165 curbyte += aimutil_putstr(newpacket->data+curbyte, clientinfo->country, strlen(clientinfo->country));
166 }
167 if (strlen(clientinfo->lang)) {
168 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f);
169 curbyte += aimutil_put16(newpacket->data+curbyte, strlen(clientinfo->lang));
170 curbyte += aimutil_putstr(newpacket->data+curbyte, clientinfo->lang, strlen(clientinfo->lang));
171 }
172 }
173
174 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015);
175 #endif
176
177 newpacket->lock = 0;
178 return aim_tx_enqueue(sess, newpacket);
105 } 179 }
106 180
107 /* 181 /*
108 * int encode_password( 182 * int encode_password(
109 * const char *password, 183 * const char *password,
118 * 192 *
119 * The encoding_table seems to be a fixed set of values. We'll 193 * The encoding_table seems to be a fixed set of values. We'll
120 * hope it doesn't change over time! 194 * hope it doesn't change over time!
121 * 195 *
122 */ 196 */
123 int aim_encode_password(const char *password, char *encoded) 197 int aim_encode_password(const char *password, u_char *encoded)
124 { 198 {
125 char encoding_table[] = { 199 u_char encoding_table[] = {
126 0xf3, 0xb3, 0x6c, 0x99, 200 0xf3, 0xb3, 0x6c, 0x99,
127 0x95, 0x3f, 0xac, 0xb6, 201 0x95, 0x3f, 0xac, 0xb6,
128 0xc5, 0xfa, 0x6b, 0x63, 202 0xc5, 0xfa, 0x6b, 0x63,
129 0x69, 0x6c, 0xc3, 0x9f 203 0x69, 0x6c, 0xc3, 0x9f
130 }; 204 };
135 encoded[i] = (password[i] ^ encoding_table[i]); 209 encoded[i] = (password[i] ^ encoding_table[i]);
136 210
137 return 0; 211 return 0;
138 } 212 }
139 213
140 214 /*
141 215 * This is sent back as a general response to the login command.
142 216 * It can be either an error or a success, depending on the
217 * precense of certain TLVs.
218 *
219 * The client should check the value of logininfo->errorcode. If
220 * its nonzero, there was an error.
221 *
222 */
223 int aim_authparse(struct aim_session_t *sess,
224 struct command_rx_struct *command)
225 {
226 struct aim_tlvlist_t *tlvlist;
227 int ret = 1;
228 char *sn;
229 rxcallback_t userfunc = NULL;
230
231 memset(&sess->logininfo, 0x00, sizeof(sess->logininfo));
232
233 /*
234 * Read block of TLVs. All further data is derived
235 * from what is parsed here.
236 */
237 #ifdef SNACLOGIN
238 tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
239 #else
240 tlvlist = aim_readtlvchain(command->data, command->commandlen);
241 #endif
242 /*
243 * No matter what, we should have a screen name.
244 */
245 sn = aim_gettlv_str(tlvlist, 0x0001, 1);
246 memcpy(sess->logininfo.screen_name, sn, strlen(sn));
247 sn[(strlen(sn))] = '\0';
248
249 /*
250 * Check for an error code. If so, we should also
251 * have an error url.
252 */
253 if (aim_gettlv(tlvlist, 0x0008, 1))
254 {
255 struct aim_tlv_t *errtlv;
256 errtlv = aim_gettlv(tlvlist, 0x0008, 1);
257 sess->logininfo.errorcode = aimutil_get16(errtlv->value);
258 sess->logininfo.errorurl = aim_gettlv_str(tlvlist, 0x0004, 1);
259 }
260 /*
261 * If we have both an IP number (0x0005) and a cookie (0x0006),
262 * then the login was successful.
263 */
264 else if (aim_gettlv(tlvlist, 0x0005, 1) && aim_gettlv(tlvlist, 0x0006, 1))
265 {
266 struct aim_tlv_t *tmptlv;
267
268 /*
269 * IP address of BOS server.
270 */
271 sess->logininfo.BOSIP = aim_gettlv_str(tlvlist, 0x0005, 1);
272
273 /*
274 * Authorization Cookie
275 */
276 tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
277 memcpy(sess->logininfo.cookie, tmptlv->value, AIM_COOKIELEN);
278
279 /*
280 * The email address attached to this account
281 */
282 sess->logininfo.email = aim_gettlv_str(tlvlist, 0x0011, 1);
283
284 /*
285 * The registration status. (Not real sure what it means.)
286 */
287 tmptlv = aim_gettlv(tlvlist, 0x0013, 1);
288 sess->logininfo.regstatus = aimutil_get16(tmptlv->value);
289
290 }
291
292 #ifdef SNACLOGIN
293 userfunc = aim_callhandler(command->conn, 0x0017, 0x0003);
294 #else
295 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS);
296 #endif
297 if (userfunc)
298 ret = userfunc(sess, command);
299
300 aim_freetlvchain(&tlvlist);
301
302 /* These have been clobbered by the freetlvchain */
303 sess->logininfo.BOSIP = NULL;
304 sess->logininfo.email = NULL;
305 sess->logininfo.errorurl = NULL;
306
307 return ret;
308 }
309
310 /*
311 * Generate an authorization response.
312 *
313 * You probably don't want this unless you're writing an AIM server.
314 *
315 */
316 unsigned long aim_sendauthresp(struct aim_session_t *sess,
317 struct aim_conn_t *conn,
318 char *sn, char *bosip,
319 char *cookie, char *email,
320 int regstatus)
321 {
322 struct command_tx_struct *tx;
323 struct aim_tlvlist_t *tlvlist = NULL;
324
325 if (!(tx = aim_tx_new(0x0001 /*right??*/, conn, 1152)))
326 return -1;
327
328 tx->lock = 1;
329
330 if (sn)
331 aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn));
332 else
333 aim_addtlvtochain_str(&tlvlist, 0x0001, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
334
335 if (sess->logininfo.errorcode) {
336 aim_addtlvtochain16(&tlvlist, 0x0008, sess->logininfo.errorcode);
337 aim_addtlvtochain_str(&tlvlist, 0x0004, sess->logininfo.errorurl, strlen(sess->logininfo.errorurl));
338 } else {
339 aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip));
340 aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
341 aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email));
342 aim_addtlvtochain16(&tlvlist, 0x0013, regstatus);
343 }
344
345 tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist);
346 tx->lock = 0;
347 return aim_tx_enqueue(sess, tx);
348 }
349
350 /*
351 * Generate a random cookie. (Non-client use only)
352 */
353 int aim_gencookie(unsigned char *buf)
354 {
355 int i;
356
357 srand(time(NULL));
358
359 for (i=0; i < AIM_COOKIELEN; i++)
360 buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0));
361
362 return i;
363 }
364
365 /*
366 * Send Server Ready. (Non-client)
367 */
368 int aim_sendserverready(struct aim_session_t *sess, struct aim_conn_t *conn)
369 {
370 struct command_tx_struct *tx;
371 int i = 0;
372
373 if (!(tx = aim_tx_new(0x0002, conn, 10+0x20)))
374 return -1;
375
376 tx->lock = 1;
377
378 i += aimutil_put16(tx->data+i, 0x0001);
379 i += aimutil_put16(tx->data+i, 0x0003);
380 i += aimutil_put16(tx->data+i, 0x0000);
381 i += aimutil_put16(tx->data+i, 0x0000);
382 i += aimutil_put16(tx->data+i, 0x0000);
383
384 i += aimutil_put16(tx->data+i, 0x0001);
385 i += aimutil_put16(tx->data+i, 0x0002);
386 i += aimutil_put16(tx->data+i, 0x0003);
387 i += aimutil_put16(tx->data+i, 0x0004);
388 i += aimutil_put16(tx->data+i, 0x0006);
389 i += aimutil_put16(tx->data+i, 0x0008);
390 i += aimutil_put16(tx->data+i, 0x0009);
391 i += aimutil_put16(tx->data+i, 0x000a);
392 i += aimutil_put16(tx->data+i, 0x000b);
393 i += aimutil_put16(tx->data+i, 0x000c);
394
395 tx->lock = 0;
396
397 return aim_tx_enqueue(sess, tx);
398 }
399
400
401 /*
402 * Send service redirect. (Non-Client)
403 */
404 unsigned long aim_sendredirect(struct aim_session_t *sess,
405 struct aim_conn_t *conn,
406 unsigned short servid,
407 char *ip,
408 char *cookie)
409 {
410 struct command_tx_struct *tx;
411 struct aim_tlvlist_t *tlvlist = NULL;
412 int i = 0;
413
414 if (!(tx = aim_tx_new(0x0002, conn, 1152)))
415 return -1;
416
417 tx->lock = 1;
418
419 i += aimutil_put16(tx->data+i, 0x0001);
420 i += aimutil_put16(tx->data+i, 0x0005);
421 i += aimutil_put16(tx->data+i, 0x0000);
422 i += aimutil_put16(tx->data+i, 0x0000);
423 i += aimutil_put16(tx->data+i, 0x0000);
424
425 aim_addtlvtochain16(&tlvlist, 0x000d, servid);
426 aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip));
427 aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
428
429 tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i;
430 aim_freetlvchain(&tlvlist);
431
432 tx->lock = 0;
433 return aim_tx_enqueue(sess, tx);
434 }