+ if (stat(filename, &st) == -1) {
+ if (!modname) {
+ dperror("memrequest: stat");
+ free(filename);
+ return -1;
+ }
+ invalid = 1;
+ }
+
+ if (!invalid) {
+ if ((offset > st.st_size) || (len > st.st_size))
+ invalid = 1;
+ else if ((st.st_size - offset) < len)
+ len = st.st_size - offset;
+ else if ((st.st_size - len) < len)
+ len = st.st_size - len;
+ }
+
+ if (!invalid && len)
+ len %= 4096;
+
+ if (invalid) {
+ int i;
+
+ free(filename); /* not needed */
+
+ dvprintf("memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
+
+ i = 8;
+ if (modname)
+ i += strlen(modname);
+
+ if (!(buf = malloc(i)))
+ return -1;
+
+ i = 0;
+
+ if (modname) {
+ memcpy(buf, modname, strlen(modname));
+ i += strlen(modname);
+ }
+
+ /* Damn endianness. This must be little (LSB first) endian. */
+ buf[i++] = offset & 0xff;
+ buf[i++] = (offset >> 8) & 0xff;
+ buf[i++] = (offset >> 16) & 0xff;
+ buf[i++] = (offset >> 24) & 0xff;
+ buf[i++] = len & 0xff;
+ buf[i++] = (len >> 8) & 0xff;
+ buf[i++] = (len >> 16) & 0xff;
+ buf[i++] = (len >> 24) & 0xff;
+
+ *bufret = buf;
+ *buflenret = i;
+
+ } else {
+
+ if (!(buf = malloc(len))) {
+ free(filename);
+ return -1;
+ }
+
+ dvprintf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename);
+
+ if (!(f = fopen(filename, "r"))) {
+ dperror("memrequest: fopen");
+ free(filename);
+ free(buf);
+ return -1;
+ }
+
+ free(filename);
+
+ if (fseek(f, offset, SEEK_SET) == -1) {
+ dperror("memrequest: fseek");
+ fclose(f);
+ free(buf);
+ return -1;
+ }
+
+ if (fread(buf, len, 1, f) != 1) {
+ dperror("memrequest: fread");
+ fclose(f);
+ free(buf);
+ return -1;
+ }
+
+ fclose(f);
+
+ *bufret = buf;
+ *buflenret = len;
+
+ }
+
+ return 0; /* success! */
+}
+
+/*
+ * This will get an offset and a length. The client should read this
+ * data out of whatever AIM.EXE binary the user has provided (hopefully
+ * it matches the client information thats sent at login) and pass a
+ * buffer back to libfaim so it can hash the data and send it to AOL for
+ * inspection by the client police.
+ */
+static int faimtest_memrequest(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ unsigned long offset, len;
+ char *modname;
+ unsigned char *buf;
+ int buflen;
+
+ va_start(ap, command);
+ offset = va_arg(ap, unsigned long);
+ len = va_arg(ap, unsigned long);
+ modname = va_arg(ap, char *);
+ va_end(ap);
+
+ if (aimbinarypath && (getaimdata(&buf, &buflen, offset, len, modname) == 0)) {
+
+ aim_sendmemblock(sess, command->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
+
+ free(buf);
+
+ } else {
+
+ dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", aimbinarypath, modname);
+
+ aim_sendmemblock(sess, command->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
+
+ }
+
+ return 1;
+}
+
+static int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_conn_t *bosconn = NULL;
+ char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
+ unsigned char *cookie = NULL;
+ int errorcode = 0, regstatus = 0;
+ int latestbuild = 0, latestbetabuild = 0;
+ char *latestrelease = NULL, *latestbeta = NULL;
+ char *latestreleaseurl = NULL, *latestbetaurl = NULL;
+ char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
+
+ va_start(ap, command);
+ sn = va_arg(ap, char *);
+ errorcode = va_arg(ap, int);
+ errurl = va_arg(ap, char *);
+ regstatus = va_arg(ap, int);
+ email = va_arg(ap, char *);
+ bosip = va_arg(ap, char *);
+ cookie = va_arg(ap, unsigned char *);
+
+ latestrelease = va_arg(ap, char *);
+ latestbuild = va_arg(ap, int);
+ latestreleaseurl = va_arg(ap, char *);
+ latestreleaseinfo = va_arg(ap, char *);
+
+ latestbeta = va_arg(ap, char *);
+ latestbetabuild = va_arg(ap, int);
+ latestbetaurl = va_arg(ap, char *);
+ latestbetainfo = va_arg(ap, char *);
+
+ va_end(ap);
+
+ dvprintf("Screen name: %s\n", sn);
+
+ /*
+ * Check for error.
+ */
+ if (errorcode || !bosip || !cookie) {
+ dvprintf("Login Error Code 0x%04x\n", errorcode);
+ dvprintf("Error URL: %s\n", errurl);
+ aim_conn_kill(sess, &command->conn);
+ return 1;
+ }
+
+ dvprintf("Reg status: %2d\n", regstatus);
+ dvprintf("Email: %s\n", email);
+ dvprintf("BOS IP: %s\n", bosip);
+
+ if (latestbeta)
+ dvprintf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
+
+ if (latestrelease)
+ dvprintf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
+
+ dprintf("Closing auth connection...\n");
+ aim_conn_kill(sess, &command->conn);
+ if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
+ dprintf("faimtest: could not connect to BOS: internal error\n");
+ return 1;
+ } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
+ dprintf("faimtest: could not connect to BOS\n");
+ aim_conn_kill(sess, &bosconn);
+ return 1;
+ }
+
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
+ aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
+ aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, faimtest_locrights, 0);
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
+
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
+
+ aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
+
+ aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
+ aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
+ aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
+
+ aim_auth_sendcookie(sess, bosconn, cookie);
+
+ return 1;
+}
+
+static void printuserflags(unsigned short flags)
+{
+ if (flags & AIM_FLAG_UNCONFIRMED)
+ dinlineprintf("UNCONFIRMED ");
+ if (flags & AIM_FLAG_ADMINISTRATOR)
+ dinlineprintf("ADMINISTRATOR ");
+ if (flags & AIM_FLAG_AOL)
+ dinlineprintf("AOL ");
+ if (flags & AIM_FLAG_OSCAR_PAY)
+ dinlineprintf("OSCAR_PAY ");
+ if (flags & AIM_FLAG_FREE)
+ dinlineprintf("FREE ");
+ if (flags & AIM_FLAG_AWAY)
+ dinlineprintf("AWAY ");
+ if (flags & AIM_FLAG_UNKNOWN40)
+ dinlineprintf("ICQ? ");
+ if (flags & AIM_FLAG_UNKNOWN80)
+ dinlineprintf("UNKNOWN80 ");
+ return;
+}
+
+int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ struct aim_userinfo_s *userinfo;