📄 family_oservice.c
字号:
/* * Send only the versions that the server cares about (that it * marked as supporting in the server ready SNAC). */ for (cur = conn->groups; cur != NULL; cur = cur->next) { aim_module_t *mod; if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data)))) { byte_stream_put16(&frame->data, mod->family); byte_stream_put16(&frame->data, mod->version); } } flap_connection_send(conn, frame);}/* Subtype 0x0018 - Host versions */static inthostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int vercount; guint8 *versions; /* This is frivolous. (Thank you SmarterChild.) */ vercount = byte_stream_empty(bs)/4; versions = byte_stream_getraw(bs, byte_stream_empty(bs)); g_free(versions); /* * Now request rates. */ aim_srv_reqrates(od, conn); return 1;}/** * Subtype 0x001e - Extended Status/Extra Info. * * These settings are transient, not server-stored (i.e. they only * apply to this session, and must be re-set the next time you sign * on). * * You can set your ICQ status (available, away, do not disturb, * etc.), or whether your IP address should be hidden or not, or * if your status is visible on ICQ web sites, and you can set * your IP address info and what not. * * You can also set your "available" message. This is currently * only supported by iChat, Purple and other 3rd party clients. * * These are the same TLVs seen in user info. You can * also set 0x0008 and 0x000c. */intaim_srv_setextrainfo(OscarData *od, gboolean seticqstatus, guint32 icqstatus, gboolean setavailmsg, const char *availmsg, const char *itmsurl){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; GSList *tlvlist = NULL; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM))) return -EINVAL; if (seticqstatus) { aim_tlvlist_add_32(&tlvlist, 0x0006, icqstatus | AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH); }#if 0 if (other_stuff_that_isnt_implemented) { aim_tlvlist_add_raw(&tlvlist, 0x000c, 0x0025, chunk_of_x25_bytes_with_ip_address_etc); aim_tlvlist_add_raw(&tlvlist, 0x0011, 0x0005, unknown 0x01 61 10 f6 41); aim_tlvlist_add_16(&tlvlist, 0x0012, unknown 0x00 00); }#endif if (setavailmsg) { int availmsglen, itmsurllen; ByteStream tmpbs; availmsglen = (availmsg != NULL) ? strlen(availmsg) : 0; itmsurllen = (itmsurl != NULL) ? strlen(itmsurl) : 0; byte_stream_new(&tmpbs, availmsglen + 8 + itmsurllen + 8); byte_stream_put16(&tmpbs, 0x0002); byte_stream_put8(&tmpbs, 0x04); /* Flags */ byte_stream_put8(&tmpbs, availmsglen + 4); byte_stream_put16(&tmpbs, availmsglen); if (availmsglen > 0) byte_stream_putstr(&tmpbs, availmsg); byte_stream_put16(&tmpbs, 0x0000); byte_stream_put16(&tmpbs, 0x0009); byte_stream_put8(&tmpbs, 0x04); /* Flags */ byte_stream_put8(&tmpbs, itmsurllen + 4); byte_stream_put16(&tmpbs, itmsurllen); if (itmsurllen > 0) byte_stream_putstr(&tmpbs, itmsurl); byte_stream_put16(&tmpbs, 0x0000); aim_tlvlist_add_raw(&tlvlist, 0x001d, byte_stream_curpos(&tmpbs), tmpbs.data); g_free(tmpbs.data); } frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist)); snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid); aim_tlvlist_write(&frame->data, &tlvlist); aim_tlvlist_free(tlvlist); flap_connection_send(conn, frame); return 0;}/** * Starting this past week (26 Mar 2001, say), AOL has started sending * this nice little extra SNAC. AFAIK, it has never been used until now. * * The request contains eight bytes. The first four are an offset, the * second four are a length. * * The offset is an offset into aim.exe when it is mapped during execution * on Win32. So far, AOL has only been requesting bytes in static regions * of memory. (I won't put it past them to start requesting data in * less static regions -- regions that are initialized at run time, but still * before the client receives this request.) * * When the client receives the request, it adds it to the current ds * (0x00400000) and dereferences it, copying the data into a buffer which * it then runs directly through the MD5 hasher. The 16 byte output of * the hash is then sent back to the server. * * If the client does not send any data back, or the data does not match * the data that the specific client should have, the client will get the * following message from "AOL Instant Messenger": * "You have been disconnected from the AOL Instant Message Service (SM) * for accessing the AOL network using unauthorized software. You can * download a FREE, fully featured, and authorized client, here * http://www.aol.com/aim/download2.html" * The connection is then closed, receiving disconnect code 1, URL * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html. * * Note, however, that numerous inconsistencies can cause the above error, * not just sending back a bad hash. Do not immediatly suspect this code * if you get disconnected. AOL and the open/free software community have * played this game for a couple years now, generating the above message * on numerous ocassions. * * Anyway, neener. We win again. * *//* Subtype 0x001f - Client verification */static intmemrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; guint32 offset, len; GSList *tlvlist; char *modname; offset = byte_stream_get32(bs); len = byte_stream_get32(bs); tlvlist = aim_tlvlist_read(bs); modname = aim_tlv_getstr(tlvlist, 0x0001, 1); purple_debug_info("oscar", "Got memory request for data at 0x%08lx (%d bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe"); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, offset, len, modname); g_free(modname); aim_tlvlist_free(tlvlist); return ret;}/* Subtype 0x0020 - Client verification reply */intaim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag){ FlapFrame *frame; aim_snacid_t snacid; if (!od || !conn) return -EINVAL; frame = flap_frame_new(od, 0x02, 10+2+16); snacid = aim_cachesnac(od, 0x0001, 0x0020, 0x0000, NULL, 0); aim_putsnac(&frame->data, 0x0001, 0x0020, 0x0000, snacid); byte_stream_put16(&frame->data, 0x0010); /* md5 is always 16 bytes */ if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ byte_stream_putraw(&frame->data, buf, 0x10); } else if (buf && (len > 0)) { /* use input buffer */ PurpleCipher *cipher; PurpleCipherContext *context; guchar digest[16]; cipher = purple_ciphers_find_cipher("md5"); context = purple_cipher_context_new(cipher, NULL); purple_cipher_context_append(context, buf, len); purple_cipher_context_digest(context, 16, digest, NULL); purple_cipher_context_destroy(context); byte_stream_putraw(&frame->data, digest, 0x10); } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ PurpleCipher *cipher; PurpleCipherContext *context; guchar digest[16]; guint8 nil = '\0'; /* * I'm not sure if we really need the empty append with the * new MD5 functions, so I'll leave it in, just in case. */ cipher = purple_ciphers_find_cipher("md5"); context = purple_cipher_context_new(cipher, NULL); purple_cipher_context_append(context, &nil, 0); purple_cipher_context_digest(context, 16, digest, NULL); purple_cipher_context_destroy(context); byte_stream_putraw(&frame->data, digest, 0x10); } else { /* * This data is correct for AIM 3.5.1670. * * Using these blocks is as close to "legal" as you can get * without using an AIM binary. * */ if ((offset == 0x03ffffff) && (len == 0x03ffffff)) {#if 1 /* with "AnrbnrAqhfzcd" */ byte_stream_put32(&frame->data, 0x44a95d26); byte_stream_put32(&frame->data, 0xd2490423); byte_stream_put32(&frame->data, 0x93b8821f); byte_stream_put32(&frame->data, 0x51c54b01);#else /* no filename */ byte_stream_put32(&frame->data, 0x1df8cbae); byte_stream_put32(&frame->data, 0x5523b839); byte_stream_put32(&frame->data, 0xa0e10db3); byte_stream_put32(&frame->data, 0xa46d3b39);#endif } else purple_debug_warning("oscar", "sendmemblock: unknown hash request\n"); } flap_connection_send(conn, frame); return 0;}/* * Subtype 0x0021 - Receive our extended status * * This is used for iChat's "available" messages, and maybe ICQ extended * status messages? It's also used to tell the client whether or not it * needs to upload an SSI buddy icon... who engineers this stuff, anyway? */static intaim_parse_extstatus(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; guint16 type; guint8 flags, length; type = byte_stream_get16(bs); flags = byte_stream_get8(bs); length = byte_stream_get8(bs); /* * A flag of 0x01 could mean "this is the checksum we have for you" * A flag of 0x40 could mean "I don't have your icon, upload it" */ if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { switch (type) { case 0x0000: case 0x0001: { /* buddy icon checksum */ /* not sure what the difference between 1 and 0 is */ guint8 *md5 = byte_stream_getraw(bs, length); ret = userfunc(od, conn, frame, type, flags, length, md5); g_free(md5); } break; case 0x0002: { /* available message */ /* there is a second length that is just for the message */ char *msg = byte_stream_getstr(bs, byte_stream_get16(bs)); ret = userfunc(od, conn, frame, msg); g_free(msg); } break; } } return ret;}static intsnachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ if (snac->subtype == 0x0003) return hostonline(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0005) return redirect(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0007) return rateresp(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000a) return ratechange(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000b) return serverpause(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000d) return serverresume(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000f) return selfinfo(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0010) return evilnotify(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0012) return migrate(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0013) return motd(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0018) return hostversions(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x001f) return memrequest(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0021) return aim_parse_extstatus(od, conn, mod, frame, snac, bs); return 0;}int service_modfirst(OscarData *od, aim_module_t *mod){ mod->family = 0x0001; mod->version = 0x0003; mod->toolid = 0x0110; mod->toolversion = 0x0629; mod->flags = 0; strncpy(mod->name, "oservice", sizeof(mod->name)); mod->snachandler = snachandler; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -