/* * Inverse of aim_info_extract() */ int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info) { GSList *tlvlist = NULL; if (!bs || !info) return -EINVAL; byte_stream_put8(bs, strlen(info->bn)); byte_stream_putstr(bs, info->bn); byte_stream_put16(bs, info->warnlevel); if (info->present & AIM_USERINFO_PRESENT_FLAGS) aim_tlvlist_add_16(&tlvlist, 0x0001, info->flags); if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE) aim_tlvlist_add_32(&tlvlist, 0x0002, info->membersince); if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) aim_tlvlist_add_32(&tlvlist, 0x0003, info->onlinesince); if (info->present & AIM_USERINFO_PRESENT_IDLE) aim_tlvlist_add_16(&tlvlist, 0x0004, info->idletime); /* XXX - So, ICQ_OSCAR_SUPPORT is never defined anywhere... */ #ifdef ICQ_OSCAR_SUPPORT if (atoi(info->bn) != 0) { if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) aim_tlvlist_add_16(&tlvlist, 0x0006, info->icqinfo.status); if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR) aim_tlvlist_add_32(&tlvlist, 0x000a, info->icqinfo.ipaddr); } #endif if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES) aim_tlvlist_add_caps(&tlvlist, 0x000d, info->capabilities); if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) aim_tlvlist_add_32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen); byte_stream_put16(bs, aim_tlvlist_count(tlvlist)); aim_tlvlist_write(bs, &tlvlist); aim_tlvlist_free(tlvlist); return 0; }
/* * Part two of the ICQ hack. Note the ignoring of the key. */ static int goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci) { FlapFrame *frame; GSList *tlvlist = NULL; int passwdlen; guint8 *password_encoded; guint32 distrib; passwdlen = strlen(password); password_encoded = (guint8 *)g_malloc(passwdlen+1); if (passwdlen > MAXICQPASSLEN) passwdlen = MAXICQPASSLEN; frame = flap_frame_new(od, 0x01, 1152); aim_encode_password(password, password_encoded); distrib = oscar_get_ui_info_int( od->icq ? "prpl-icq-distid" : "prpl-aim-distid", ci->distrib); byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */ aim_tlvlist_add_str(&tlvlist, 0x0001, sn); aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded); if (ci->clientstring != NULL) aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring); else { gchar *clientstring = oscar_get_clientstring(); aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring); g_free(clientstring); } aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid); aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major); aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor); aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point); aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build); aim_tlvlist_add_32(&tlvlist, 0x0014, distrib); /* distribution chan */ aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang); aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country); aim_tlvlist_write(&frame->data, &tlvlist); g_free(password_encoded); aim_tlvlist_free(tlvlist); flap_connection_send(conn, frame); return 0; }
/* * Subtype 0x0002 * * This is the initial login request packet. * * NOTE!! If you want/need to make use of the aim_sendmemblock() function, * then the client information you send here must exactly match the * executable that you're pulling the data from. * * Java AIM 1.1.19: * clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001" * clientid = 0x0001 * major = 0x0001 * minor = 0x0001 * point = (not sent) * build = 0x0013 * unknown= (not sent) * * AIM for Linux 1.1.112: * clientstring = "AOL Instant Messenger (SM)" * clientid = 0x1d09 * major = 0x0001 * minor = 0x0001 * point = 0x0001 * build = 0x0070 * unknown= 0x0000008b * serverstore = 0x01 * * @param truncate_pass Truncate the password to 8 characters. This * usually happens for AOL accounts. We are told that we * should truncate it if the 0x0017/0x0007 SNAC contains * a TLV of type 0x0026 with data 0x0000. * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM * server will prompt the user when multiple logins occur. If * FALSE, existing connections (on other clients) will be * disconnected automatically as we connect. */ int aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins) { FlapFrame *frame; GSList *tlvlist = NULL; guint8 digest[16]; aim_snacid_t snacid; size_t password_len; guint32 distrib; if (!ci || !sn || !password) return -EINVAL; #ifdef USE_XOR_FOR_ICQ /* If we're signing on an ICQ account then use the older, XOR login method */ if (aim_snvalid_icq(sn)) return goddamnicq2(od, conn, sn, password, ci); #endif frame = flap_frame_new(od, 0x02, 1152); snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0); aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, 0x0000, snacid); aim_tlvlist_add_str(&tlvlist, 0x0001, sn); /* Truncate ICQ and AOL passwords, if necessary */ password_len = strlen(password); if (oscar_util_valid_name_icq(sn) && (password_len > MAXICQPASSLEN)) password_len = MAXICQPASSLEN; else if (truncate_pass && password_len > 8) password_len = 8; aim_encode_password_md5(password, password_len, key, digest); distrib = oscar_get_ui_info_int( od->icq ? "prpl-icq-distid" : "prpl-aim-distid", ci->distrib); aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest); #ifndef USE_OLD_MD5 aim_tlvlist_add_noval(&tlvlist, 0x004c); #endif if (ci->clientstring != NULL) aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring); else { gchar *clientstring = oscar_get_clientstring(); aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring); g_free(clientstring); } aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid); aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major); aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor); aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point); aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build); aim_tlvlist_add_32(&tlvlist, 0x0014, distrib); aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang); aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country); /* * If set, old-fashioned buddy lists will not work. You will need * to use SSI. */ aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03)); aim_tlvlist_write(&frame->data, &tlvlist); aim_tlvlist_free(tlvlist); flap_connection_send(conn, frame); return 0; }