Changeset cf02dd6 for libfaim/auth.c


Ignore:
Timestamp:
Dec 10, 2003, 3:20:45 PM (17 years ago)
Author:
James M. Kretchmar <kretch@mit.edu>
Branches:
master, barnowl_perlaim, debian, owl, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
b1fe407
Parents:
8c46404
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfaim/auth.c

    re374dee rcf02dd6  
    1212#include "md5.h"
    1313
    14 static int aim_encode_password(const char *password, fu8_t *encoded);
    15 
    16 /*
     14#include <ctype.h>
     15
     16/**
     17 * Encode a password using old XOR method
     18 *
     19 * This takes a const pointer to a (null terminated) string
     20 * containing the unencoded password.  It also gets passed
     21 * an already allocated buffer to store the encoded password.
     22 * This buffer should be the exact length of the password without
     23 * the null.  The encoded password buffer /is not %NULL terminated/.
     24 *
     25 * The encoding_table seems to be a fixed set of values.  We'll
     26 * hope it doesn't change over time! 
     27 *
     28 * This is only used for the XOR method, not the better MD5 method.
     29 *
     30 * @param password Incoming password.
     31 * @param encoded Buffer to put encoded password.
     32 */
     33static int aim_encode_password(const char *password, fu8_t *encoded)
     34{
     35        fu8_t encoding_table[] = {
     36#if 0 /* old v1 table */
     37                0xf3, 0xb3, 0x6c, 0x99,
     38                0x95, 0x3f, 0xac, 0xb6,
     39                0xc5, 0xfa, 0x6b, 0x63,
     40                0x69, 0x6c, 0xc3, 0x9f
     41#else /* v2.1 table, also works for ICQ */
     42                0xf3, 0x26, 0x81, 0xc4,
     43                0x39, 0x86, 0xdb, 0x92,
     44                0x71, 0xa3, 0xb9, 0xe6,
     45                0x53, 0x7a, 0x95, 0x7c
     46#endif
     47        };
     48        int i;
     49
     50        for (i = 0; i < strlen(password); i++)
     51                encoded[i] = (password[i] ^ encoding_table[i]);
     52
     53        return 0;
     54}
     55
     56#ifdef USE_OLD_MD5
     57static int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
     58{
     59        md5_state_t state;
     60
     61        md5_init(&state);       
     62        md5_append(&state, (const md5_byte_t *)key, strlen(key));
     63        md5_append(&state, (const md5_byte_t *)password, strlen(password));
     64        md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
     65        md5_finish(&state, (md5_byte_t *)digest);
     66
     67        return 0;
     68}
     69#else
     70static int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
     71{
     72        md5_state_t state;
     73        fu8_t passdigest[16];
     74
     75        md5_init(&state);
     76        md5_append(&state, (const md5_byte_t *)password, strlen(password));
     77        md5_finish(&state, (md5_byte_t *)&passdigest);
     78
     79        md5_init(&state);       
     80        md5_append(&state, (const md5_byte_t *)key, strlen(key));
     81        md5_append(&state, (const md5_byte_t *)&passdigest, 16);
     82        md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
     83        md5_finish(&state, (md5_byte_t *)digest);
     84
     85        return 0;
     86}
     87#endif
     88
     89/*
     90 * The FLAP version is sent by itself at the beginning of authorization
     91 * connections.  The FLAP version is also sent before the cookie when connecting
     92 * for other services (BOS, chatnav, chat, etc.).
     93 */
     94faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn)
     95{
     96        aim_frame_t *fr;
     97
     98        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4)))
     99                return -ENOMEM;
     100
     101        aimbs_put32(&fr->data, 0x00000001);
     102
     103        aim_tx_enqueue(sess, fr);
     104
     105        return 0;
     106}
     107
     108/*
    17109 * This just pushes the passed cookie onto the passed connection, without
    18110 * the SNAC header or any of that.
     
    31123
    32124        aimbs_put32(&fr->data, 0x00000001);
    33         aim_addtlvtochain_raw(&tl, 0x0006, length, chipsahoy);
    34         aim_writetlvchain(&fr->data, &tl);
    35         aim_freetlvchain(&tl);
    36 
    37         aim_tx_enqueue(sess, fr);
    38 
    39         return 0;
    40 }
    41 
    42 /*
    43  * Normally the FLAP version is sent as the first few bytes of the cookie,
    44  * meaning you generally never call this.
    45  *
    46  * But there are times when something might want it seperate. Specifically,
    47  * libfaim sends this internally when doing SNAC login.
    48  *
    49  */
    50 faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn)
    51 {
    52         aim_frame_t *fr;
    53 
    54         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4)))
    55                 return -ENOMEM;
    56 
    57         aimbs_put32(&fr->data, 0x00000001);
    58 
    59         aim_tx_enqueue(sess, fr);
    60 
    61         return 0;
    62 }
    63 
    64 /*
    65  * This is a bit confusing.
    66  *
    67  * Normal SNAC login goes like this:
    68  *   - connect
    69  *   - server sends flap version
    70  *   - client sends flap version
    71  *   - client sends screen name (17/6)
    72  *   - server sends hash key (17/7)
    73  *   - client sends auth request (17/2 -- aim_send_login)
    74  *   - server yells
    75  *
    76  * XOR login (for ICQ) goes like this:
    77  *   - connect
    78  *   - server sends flap version
    79  *   - client sends auth request which contains flap version (aim_send_login)
    80  *   - server yells
    81  *
    82  * For the client API, we make them implement the most complicated version,
    83  * and for the simpler version, we fake it and make it look like the more
    84  * complicated process.
    85  *
    86  * This is done by giving the client a faked key, just so we can convince
    87  * them to call aim_send_login right away, which will detect the session
    88  * flag that says this is XOR login and ignore the key, sending an ICQ
    89  * login request instead of the normal SNAC one.
    90  *
    91  * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
    92  *
    93  * XXX This may cause problems if the client relies on callbacks only
    94  * being called from the context of aim_rxdispatch()...
    95  *
    96  */
    97 static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    98 {
    99         aim_frame_t fr;
    100         aim_rxcallback_t userfunc;
    101        
    102         sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN;
    103         sess->flags |= AIM_SESS_FLAGS_XORLOGIN;
    104 
    105         fr.conn = conn;
    106        
    107         if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007)))
    108                 userfunc(sess, &fr, "");
    109 
    110         return 0;
    111 }
    112 
    113 /*
    114  * In AIM 3.5 protocol, the first stage of login is to request login from the
    115  * Authorizer, passing it the screen name for verification.  If the name is
    116  * invalid, a 0017/0003 is spit back, with the standard error contents.  If
    117  * valid, a 0017/0007 comes back, which is the signal to send it the main
    118  * login command (0017/0002).
    119  *
    120  */
    121 faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
    122 {
    123         aim_frame_t *fr;
    124         aim_snacid_t snacid;
    125         aim_tlvlist_t *tl = NULL;
    126        
    127         if (!sess || !conn || !sn)
    128                 return -EINVAL;
    129 
    130         if ((sn[0] >= '0') && (sn[0] <= '9'))
    131                 return goddamnicq(sess, conn, sn);
    132 
    133         sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
    134 
    135         aim_sendflapver(sess, conn);
    136 
    137         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn))))
    138                 return -ENOMEM;
    139 
    140         snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
    141         aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);
    142 
    143         aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn);
    144         aim_writetlvchain(&fr->data, &tl);
    145         aim_freetlvchain(&tl);
     125        aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy);
     126        aim_tlvlist_write(&fr->data, &tl);
     127        aim_tlvlist_free(&tl);
    146128
    147129        aim_tx_enqueue(sess, fr);
     
    174156
    175157        aimbs_put32(&fr->data, 0x00000001); /* FLAP Version */
    176         aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn);
    177         aim_addtlvtochain_raw(&tl, 0x0002, passwdlen, password_encoded);
     158        aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
     159        aim_tlvlist_add_raw(&tl, 0x0002, passwdlen, password_encoded);
    178160
    179161        if (ci->clientstring)
    180                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
    181         aim_addtlvtochain16(&tl, 0x0016, (fu16_t)ci->clientid);
    182         aim_addtlvtochain16(&tl, 0x0017, (fu16_t)ci->major);
    183         aim_addtlvtochain16(&tl, 0x0018, (fu16_t)ci->minor);
    184         aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point);
    185         aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build);
    186         aim_addtlvtochain32(&tl, 0x0014, (fu32_t)ci->distrib); /* distribution chan */
    187         aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
    188         aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country);
    189 
    190         aim_writetlvchain(&fr->data, &tl);
     162                aim_tlvlist_add_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
     163        aim_tlvlist_add_16(&tl, 0x0016, (fu16_t)ci->clientid);
     164        aim_tlvlist_add_16(&tl, 0x0017, (fu16_t)ci->major);
     165        aim_tlvlist_add_16(&tl, 0x0018, (fu16_t)ci->minor);
     166        aim_tlvlist_add_16(&tl, 0x0019, (fu16_t)ci->point);
     167        aim_tlvlist_add_16(&tl, 0x001a, (fu16_t)ci->build);
     168        aim_tlvlist_add_32(&tl, 0x0014, (fu32_t)ci->distrib); /* distribution chan */
     169        aim_tlvlist_add_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
     170        aim_tlvlist_add_raw(&tl, 0x000e, strlen(ci->country), ci->country);
     171
     172        aim_tlvlist_write(&fr->data, &tl);
    191173
    192174        free(password_encoded);
    193         aim_freetlvchain(&tl);
     175        aim_tlvlist_free(&tl);
    194176
    195177        aim_tx_enqueue(sess, fr);
     
    199181
    200182/*
    201  * send_login(int socket, char *sn, char *password)
    202  * 
     183 * Subtype 0x0002
     184 *
    203185 * This is the initial login request packet.
    204186 *
     
    237219                return -EINVAL;
    238220
    239         /*
    240          * What the XORLOGIN flag _really_ means is that its an ICQ login,
    241          * which is really stupid and painful, so its not done here.
    242          *
    243          */
    244         if (sess->flags & AIM_SESS_FLAGS_XORLOGIN)
     221        /* If we're signing on an ICQ account then use the older, XOR login method */
     222        if (isdigit(sn[0]))
    245223                return goddamnicq2(sess, conn, sn, password, ci);
    246 
    247224
    248225        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
     
    252229        aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid);
    253230
    254         aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn);
     231        aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
    255232
    256233        aim_encode_password_md5(password, key, digest);
    257         aim_addtlvtochain_raw(&tl, 0x0025, 16, digest);
    258 
    259         /*
    260          * Newer versions of winaim have an empty type x004c TLV here.
    261          */
     234        aim_tlvlist_add_raw(&tl, 0x0025, 16, digest);
     235
     236#ifndef USE_OLD_MD5
     237        aim_tlvlist_add_noval(&tl, 0x004c);
     238#endif
    262239
    263240        if (ci->clientstring)
    264                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
    265         aim_addtlvtochain16(&tl, 0x0016, (fu16_t)ci->clientid);
    266         aim_addtlvtochain16(&tl, 0x0017, (fu16_t)ci->major);
    267         aim_addtlvtochain16(&tl, 0x0018, (fu16_t)ci->minor);
    268         aim_addtlvtochain16(&tl, 0x0019, (fu16_t)ci->point);
    269         aim_addtlvtochain16(&tl, 0x001a, (fu16_t)ci->build);
    270         aim_addtlvtochain32(&tl, 0x0014, (fu32_t)ci->distrib);
    271         aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), ci->country);
    272         aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
     241                aim_tlvlist_add_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
     242        aim_tlvlist_add_16(&tl, 0x0016, (fu16_t)ci->clientid);
     243        aim_tlvlist_add_16(&tl, 0x0017, (fu16_t)ci->major);
     244        aim_tlvlist_add_16(&tl, 0x0018, (fu16_t)ci->minor);
     245        aim_tlvlist_add_16(&tl, 0x0019, (fu16_t)ci->point);
     246        aim_tlvlist_add_16(&tl, 0x001a, (fu16_t)ci->build);
     247        aim_tlvlist_add_32(&tl, 0x0014, (fu32_t)ci->distrib);
     248        aim_tlvlist_add_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
     249        aim_tlvlist_add_raw(&tl, 0x000e, strlen(ci->country), ci->country);
    273250
    274251#ifndef NOSSI
     
    277254         * to use SSI.
    278255         */
    279         aim_addtlvtochain8(&tl, 0x004a, 0x01);
     256        aim_tlvlist_add_8(&tl, 0x004a, 0x01);
    280257#endif
    281258
    282         aim_writetlvchain(&fr->data, &tl);
    283 
    284         aim_freetlvchain(&tl);
     259        aim_tlvlist_write(&fr->data, &tl);
     260
     261        aim_tlvlist_free(&tl);
    285262       
    286263        aim_tx_enqueue(sess, fr);
    287 
    288         return 0;
    289 }
    290 
    291 faim_export int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
    292 {
    293         md5_state_t state;
    294 
    295         md5_init(&state);       
    296         md5_append(&state, (const md5_byte_t *)key, strlen(key));
    297         md5_append(&state, (const md5_byte_t *)password, strlen(password));
    298         md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
    299         md5_finish(&state, (md5_byte_t *)digest);
    300 
    301         return 0;
    302 }
    303 
    304 /**
    305  * aim_encode_password - Encode a password using old XOR method
    306  * @password: incoming password
    307  * @encoded: buffer to put encoded password
    308  *
    309  * This takes a const pointer to a (null terminated) string
    310  * containing the unencoded password.  It also gets passed
    311  * an already allocated buffer to store the encoded password.
    312  * This buffer should be the exact length of the password without
    313  * the null.  The encoded password buffer /is not %NULL terminated/.
    314  *
    315  * The encoding_table seems to be a fixed set of values.  We'll
    316  * hope it doesn't change over time! 
    317  *
    318  * This is only used for the XOR method, not the better MD5 method.
    319  *
    320  */
    321 static int aim_encode_password(const char *password, fu8_t *encoded)
    322 {
    323         fu8_t encoding_table[] = {
    324 #if 0 /* old v1 table */
    325                 0xf3, 0xb3, 0x6c, 0x99,
    326                 0x95, 0x3f, 0xac, 0xb6,
    327                 0xc5, 0xfa, 0x6b, 0x63,
    328                 0x69, 0x6c, 0xc3, 0x9f
    329 #else /* v2.1 table, also works for ICQ */
    330                 0xf3, 0x26, 0x81, 0xc4,
    331                 0x39, 0x86, 0xdb, 0x92,
    332                 0x71, 0xa3, 0xb9, 0xe6,
    333                 0x53, 0x7a, 0x95, 0x7c
    334 #endif
    335         };
    336         int i;
    337 
    338         for (i = 0; i < strlen(password); i++)
    339                 encoded[i] = (password[i] ^ encoding_table[i]);
    340264
    341265        return 0;
     
    349273 * The client should check the value passed as errorcode. If
    350274 * its nonzero, there was an error.
    351  *
    352275 */
    353276static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
     
    365288         * from what is parsed here.
    366289         */
    367         tlvlist = aim_readtlvchain(bs);
     290        tlvlist = aim_tlvlist_read(bs);
    368291
    369292        /*
     
    371294         */
    372295        memset(sess->sn, 0, sizeof(sess->sn));
    373         if (aim_gettlv(tlvlist, 0x0001, 1)) {
    374                 info->sn = aim_gettlv_str(tlvlist, 0x0001, 1);
     296        if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) {
     297                info->sn = aim_tlv_getstr(tlvlist, 0x0001, 1);
    375298                strncpy(sess->sn, info->sn, sizeof(sess->sn));
    376299        }
     
    380303         * have an error url.
    381304         */
    382         if (aim_gettlv(tlvlist, 0x0008, 1))
    383                 info->errorcode = aim_gettlv16(tlvlist, 0x0008, 1);
    384         if (aim_gettlv(tlvlist, 0x0004, 1))
    385                 info->errorurl = aim_gettlv_str(tlvlist, 0x0004, 1);
     305        if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
     306                info->errorcode = aim_tlv_get16(tlvlist, 0x0008, 1);
     307        if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
     308                info->errorurl = aim_tlv_getstr(tlvlist, 0x0004, 1);
    386309
    387310        /*
    388311         * BOS server address.
    389312         */
    390         if (aim_gettlv(tlvlist, 0x0005, 1))
    391                 info->bosip = aim_gettlv_str(tlvlist, 0x0005, 1);
     313        if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
     314                info->bosip = aim_tlv_getstr(tlvlist, 0x0005, 1);
    392315
    393316        /*
    394317         * Authorization cookie.
    395318         */
    396         if (aim_gettlv(tlvlist, 0x0006, 1)) {
     319        if (aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
    397320                aim_tlv_t *tmptlv;
    398321
    399                 tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
     322                tmptlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
    400323
    401324                info->cookielen = tmptlv->length;
     
    410333         * XXX - Not really true!
    411334         */
    412         if (aim_gettlv(tlvlist, 0x0011, 1))
    413                 info->email = aim_gettlv_str(tlvlist, 0x0011, 1);
     335        if (aim_tlv_gettlv(tlvlist, 0x0011, 1))
     336                info->email = aim_tlv_getstr(tlvlist, 0x0011, 1);
    414337
    415338        /*
     
    427350         *
    428351         */
    429         if (aim_gettlv(tlvlist, 0x0013, 1))
    430                 info->regstatus = aim_gettlv16(tlvlist, 0x0013, 1);
    431 
    432         if (aim_gettlv(tlvlist, 0x0040, 1))
    433                 info->latestbeta.build = aim_gettlv32(tlvlist, 0x0040, 1);
    434         if (aim_gettlv(tlvlist, 0x0041, 1))
    435                 info->latestbeta.url = aim_gettlv_str(tlvlist, 0x0041, 1);
    436         if (aim_gettlv(tlvlist, 0x0042, 1))
    437                 info->latestbeta.info = aim_gettlv_str(tlvlist, 0x0042, 1);
    438         if (aim_gettlv(tlvlist, 0x0043, 1))
    439                 info->latestbeta.name = aim_gettlv_str(tlvlist, 0x0043, 1);
    440         if (aim_gettlv(tlvlist, 0x0048, 1))
    441                 ; /* no idea what this is */
    442 
    443         if (aim_gettlv(tlvlist, 0x0044, 1))
    444                 info->latestrelease.build = aim_gettlv32(tlvlist, 0x0044, 1);
    445         if (aim_gettlv(tlvlist, 0x0045, 1))
    446                 info->latestrelease.url = aim_gettlv_str(tlvlist, 0x0045, 1);
    447         if (aim_gettlv(tlvlist, 0x0046, 1))
    448                 info->latestrelease.info = aim_gettlv_str(tlvlist, 0x0046, 1);
    449         if (aim_gettlv(tlvlist, 0x0047, 1))
    450                 info->latestrelease.name = aim_gettlv_str(tlvlist, 0x0047, 1);
    451         if (aim_gettlv(tlvlist, 0x0049, 1))
    452                 ; /* no idea what this is */
     352        if (aim_tlv_gettlv(tlvlist, 0x0013, 1))
     353                info->regstatus = aim_tlv_get16(tlvlist, 0x0013, 1);
     354
     355        if (aim_tlv_gettlv(tlvlist, 0x0040, 1))
     356                info->latestbeta.build = aim_tlv_get32(tlvlist, 0x0040, 1);
     357        if (aim_tlv_gettlv(tlvlist, 0x0041, 1))
     358                info->latestbeta.url = aim_tlv_getstr(tlvlist, 0x0041, 1);
     359        if (aim_tlv_gettlv(tlvlist, 0x0042, 1))
     360                info->latestbeta.info = aim_tlv_getstr(tlvlist, 0x0042, 1);
     361        if (aim_tlv_gettlv(tlvlist, 0x0043, 1))
     362                info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1);
     363        if (aim_tlv_gettlv(tlvlist, 0x0048, 1))
     364                ; /* beta serial */
     365
     366        if (aim_tlv_gettlv(tlvlist, 0x0044, 1))
     367                info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1);
     368        if (aim_tlv_gettlv(tlvlist, 0x0045, 1))
     369                info->latestrelease.url = aim_tlv_getstr(tlvlist, 0x0045, 1);
     370        if (aim_tlv_gettlv(tlvlist, 0x0046, 1))
     371                info->latestrelease.info = aim_tlv_getstr(tlvlist, 0x0046, 1);
     372        if (aim_tlv_gettlv(tlvlist, 0x0047, 1))
     373                info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1);
     374        if (aim_tlv_gettlv(tlvlist, 0x0049, 1))
     375                ; /* lastest release serial */
    453376
    454377        /*
    455378         * URL to change password.
    456379         */
    457         if (aim_gettlv(tlvlist, 0x0054, 1))
    458                 info->chpassurl = aim_gettlv_str(tlvlist, 0x0054, 1);
     380        if (aim_tlv_gettlv(tlvlist, 0x0054, 1))
     381                info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1);
    459382
    460383        /*
    461384         * Unknown.  Seen on an @mac.com screen name with value of 0x003f
    462385         */
    463         if (aim_gettlv(tlvlist, 0x0055, 1))
     386        if (aim_tlv_gettlv(tlvlist, 0x0055, 1))
    464387                ;
    465388
     
    469392                ret = userfunc(sess, rx, info);
    470393
    471         aim_freetlvchain(&tlvlist);
     394        aim_tlvlist_free(&tlvlist);
    472395
    473396        return ret;
     
    475398
    476399/*
     400 * Subtype 0x0007 (kind of) - Send a fake type 0x0007 SNAC to the client
     401 *
     402 * This is a bit confusing.
     403 *
     404 * Normal SNAC login goes like this:
     405 *   - connect
     406 *   - server sends flap version
     407 *   - client sends flap version
     408 *   - client sends screen name (17/6)
     409 *   - server sends hash key (17/7)
     410 *   - client sends auth request (17/2 -- aim_send_login)
     411 *   - server yells
     412 *
     413 * XOR login (for ICQ) goes like this:
     414 *   - connect
     415 *   - server sends flap version
     416 *   - client sends auth request which contains flap version (aim_send_login)
     417 *   - server yells
     418 *
     419 * For the client API, we make them implement the most complicated version,
     420 * and for the simpler version, we fake it and make it look like the more
     421 * complicated process.
     422 *
     423 * This is done by giving the client a faked key, just so we can convince
     424 * them to call aim_send_login right away, which will detect the session
     425 * flag that says this is XOR login and ignore the key, sending an ICQ
     426 * login request instead of the normal SNAC one.
     427 *
     428 * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
     429 *
     430 * XXX This may cause problems if the client relies on callbacks only
     431 * being called from the context of aim_rxdispatch()...
     432 *
     433 */
     434static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     435{
     436        aim_frame_t fr;
     437        aim_rxcallback_t userfunc;
     438       
     439        fr.conn = conn;
     440       
     441        if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007)))
     442                userfunc(sess, &fr, "");
     443
     444        return 0;
     445}
     446
     447/*
     448 * Subtype 0x0006
     449 *
     450 * In AIM 3.5 protocol, the first stage of login is to request login from the
     451 * Authorizer, passing it the screen name for verification.  If the name is
     452 * invalid, a 0017/0003 is spit back, with the standard error contents.  If
     453 * valid, a 0017/0007 comes back, which is the signal to send it the main
     454 * login command (0017/0002).
     455 *
     456 */
     457faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
     458{
     459        aim_frame_t *fr;
     460        aim_snacid_t snacid;
     461        aim_tlvlist_t *tl = NULL;
     462       
     463        if (!sess || !conn || !sn)
     464                return -EINVAL;
     465
     466        if (isdigit(sn[0]))
     467                return goddamnicq(sess, conn, sn);
     468
     469        aim_sendflapver(sess, conn);
     470
     471        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn) /*+8*/ )))
     472                return -ENOMEM;
     473
     474        snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
     475        aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);
     476
     477        aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
     478/*      aim_tlvlist_add_noval(&tl, 0x004b);
     479        aim_tlvlist_add_noval(&tl, 0x005a); */
     480        aim_tlvlist_write(&fr->data, &tl);
     481        aim_tlvlist_free(&tl);
     482
     483        aim_tx_enqueue(sess, fr);
     484
     485        return 0;
     486}
     487
     488/*
     489 * Subtype 0x0007
     490 *
    477491 * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
    478492 * by only its length in a two byte word.
Note: See TracChangeset for help on using the changeset viewer.