]> andersk Git - libfaim.git/blob - aim_login.c
Random Changes.
[libfaim.git] / aim_login.c
1 /*
2  *  aim_login.c
3  *
4  *  This contains all the functions needed to actually login.
5  *
6  */
7
8 #include <faim/aim.h>
9
10
11 /*
12  * FIXME: Reimplement the TIS stuff.
13  */
14 #ifdef TIS_TELNET_PROXY
15 #include "tis_telnet_proxy.h"
16 #endif
17
18 int aim_sendconnack(struct aim_session_t *sess,
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)
69  *  
70  * This is the initial login request packet.
71  *
72  * The password is encoded before transmition, as per
73  * encode_password().  See that function for their
74  * stupid method of doing it.
75  *
76  */
77 int aim_send_login (struct aim_session_t *sess,
78                     struct aim_conn_t *conn, 
79                     char *sn, char *password, struct client_info_s *clientinfo)
80 {
81   u_char *password_encoded = NULL;  /* to store encoded password */
82   int curbyte=0;
83
84   struct command_tx_struct *newpacket;
85
86   if (!clientinfo || !sn || !password)
87     return -1;
88
89   if (!(newpacket = aim_tx_new(0x0002, conn, 1152)))
90     return -1;
91
92 #ifdef SNACLOGIN 
93   newpacket->commandlen = 10;
94   newpacket->commandlen += 2 + 2 + strlen(sn);
95   newpacket->commandlen += 2 + 2 + strlen(password);
96   newpacket->commandlen += 2 + 2 + strlen(clientinfo->clientstring);
97   newpacket->commandlen += 56;
98   
99   newpacket->lock = 1;
100
101   curbyte = aim_putsnac(newpacket->data+curbyte, 0x0017, 0x0002, 0x0000, 0x00010000);
102   curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
103   password_encoded = (u_char *) malloc(strlen(password));
104   aim_encode_password(password, password_encoded);
105   curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded);
106   curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0003, 
107                            strlen(clientinfo->clientstring), 
108                            clientinfo->clientstring);
109   /* XXX: should use clientinfo provided version info */
110   curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x0004);
111   curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0003);
112   curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x0005);
113   curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0000);
114   curbyte+= aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0686);
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));
145   password_encoded = (char *) malloc(strlen(password));
146   aim_encode_password(password, password_encoded);
147   curbyte += aimutil_putstr(newpacket->data+curbyte, password_encoded, strlen(password));
148   free(password_encoded);
149   
150   curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x0004);
151   
152   if (clientinfo) {
153     if (strlen(clientinfo->clientstring)) {
154       curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
155       curbyte += aimutil_put16(newpacket->data+curbyte, strlen(clientinfo->clientstring));
156       curbyte += aimutil_putstr(newpacket->data+curbyte, clientinfo->clientstring, strlen(clientinfo->clientstring));
157     }
158     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, clientinfo->major /*0x0001*/);
159     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, clientinfo->minor /*0x0001*/);
160     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0000);
161     curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, clientinfo->build /*0x0013*/);
162     if (strlen(clientinfo->country)) {
163       curbyte += aimutil_put16(newpacket->data+curbyte, 0x000e);
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);
179 }
180
181 /*
182  *  int encode_password(
183  *                      const char *password,
184  *                      char *encoded
185  *                      ); 
186  *
187  * This takes a const pointer to a (null terminated) string
188  * containing the unencoded password.  It also gets passed
189  * an already allocated buffer to store the encoded password.
190  * This buffer should be the exact length of the password without
191  * the null.  The encoded password buffer IS NOT NULL TERMINATED.
192  *
193  * The encoding_table seems to be a fixed set of values.  We'll
194  * hope it doesn't change over time!  
195  *
196  */
197 int aim_encode_password(const char *password, u_char *encoded)
198 {
199   u_char encoding_table[] = {
200     0xf3, 0xb3, 0x6c, 0x99,
201     0x95, 0x3f, 0xac, 0xb6,
202     0xc5, 0xfa, 0x6b, 0x63,
203     0x69, 0x6c, 0xc3, 0x9f
204   };
205
206   int i;
207   
208   for (i = 0; i < strlen(password); i++)
209       encoded[i] = (password[i] ^ encoding_table[i]);
210
211   return 0;
212 }
213
214 /*
215  * This is sent back as a general response to the login command.
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(0x0004, 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+0x22)))
374     return -1;
375
376   tx->lock = 1;
377
378   i += aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++);
379   
380   i += aimutil_put16(tx->data+i, 0x0001);  
381   i += aimutil_put16(tx->data+i, 0x0002);
382   i += aimutil_put16(tx->data+i, 0x0003);
383   i += aimutil_put16(tx->data+i, 0x0004);
384   i += aimutil_put16(tx->data+i, 0x0006);
385   i += aimutil_put16(tx->data+i, 0x0008);
386   i += aimutil_put16(tx->data+i, 0x0009);
387   i += aimutil_put16(tx->data+i, 0x000a);
388   i += aimutil_put16(tx->data+i, 0x000b);
389   i += aimutil_put16(tx->data+i, 0x000c);
390   i += aimutil_put16(tx->data+i, 0x0013);
391   i += aimutil_put16(tx->data+i, 0x0015);
392
393   tx->commandlen = i;
394   tx->lock = 0;
395   return aim_tx_enqueue(sess, tx);
396 }
397
398
399 /* 
400  * Send service redirect.  (Non-Client)
401  */
402 unsigned long aim_sendredirect(struct aim_session_t *sess, 
403                                struct aim_conn_t *conn, 
404                                unsigned short servid, 
405                                char *ip,
406                                char *cookie)
407 {       
408   struct command_tx_struct *tx;
409   struct aim_tlvlist_t *tlvlist = NULL;
410   int i = 0;
411
412   if (!(tx = aim_tx_new(0x0002, conn, 1152)))
413     return -1;
414
415   tx->lock = 1;
416
417   i += aimutil_put16(tx->data+i, 0x0001);
418   i += aimutil_put16(tx->data+i, 0x0005);
419   i += aimutil_put16(tx->data+i, 0x0000);
420   i += aimutil_put16(tx->data+i, 0x0000);
421   i += aimutil_put16(tx->data+i, 0x0000);
422   
423   aim_addtlvtochain16(&tlvlist, 0x000d, servid);
424   aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip));
425   aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
426
427   tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i;
428   aim_freetlvchain(&tlvlist);
429
430   tx->lock = 0;
431   return aim_tx_enqueue(sess, tx);
432 }
This page took 0.628701 seconds and 5 git commands to generate.