- }
- break;
- case 0x000d: /* ChatNav */
- {
- struct aim_conn_t *tstconn = NULL;
- tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
- if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
- dprintf("faimtest: unable to connect to chatnav server\n");
- if (tstconn) aim_conn_kill(sess, &tstconn);
- return 1;
- }
-#if 0
- aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, faimtest_parse_unknown, 0);
- aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, faimtest_parse_unknown, 0);
-#endif
- aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
- aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
- aim_auth_sendcookie(sess, tstconn, cookie);
- dprintf("\achatnav: connected\n");
- }
- break;
- case 0x000e: /* Chat */
- {
- char *roomname = NULL;
- int exchange;
- struct aim_conn_t *tstconn = NULL;
-
- roomname = va_arg(ap, char *);
- exchange = va_arg(ap, int);
-
- tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
- if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR))
- {
- dprintf("faimtest: unable to connect to chat server\n");
- if (tstconn) aim_conn_kill(sess, &tstconn);
- return 1;
- }
- dvprintf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
-
- /*
- * We must do this to attach the stored name to the connection!
- */
- aim_chat_attachname(tstconn, roomname);
-
- aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
- aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
- aim_auth_sendcookie(sess, tstconn, cookie);
- }
- break;
- default:
- dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
- /* dunno */
+ roomname = va_arg(ap, char *);
+ exchange = va_arg(ap, int);
+
+ tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
+ if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
+ dprintf("faimtest: unable to connect to chat server\n");
+ if (tstconn) aim_conn_kill(sess, &tstconn);
+ return 1;
+ }
+ dvprintf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
+
+ /*
+ * We must do this to attach the stored name to the connection!
+ */
+ aim_chat_attachname(tstconn, roomname);
+
+ aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
+ aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
+ aim_auth_sendcookie(sess, tstconn, cookie);
+
+ break;
+ }
+ default:
+ dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
+ /* dunno */
+ }
+
+ va_end(ap);
+
+ return 1;
+}
+
+/*
+ * This is a little more complicated than it looks. The module
+ * name (proto, boscore, etc) may or may not be given. If it is
+ * not given, then use aim.exe. If it is given, put ".ocm" on the
+ * end of it.
+ *
+ * Now, if the offset or length requested would cause a read past
+ * the end of the file, then the request is considered invalid. Invalid
+ * requests are processed specially. The value hashed is the
+ * the request, put into little-endian (eight bytes: offset followed
+ * by length).
+ *
+ * Additionally, if the request is valid, the length is mod 4096. It is
+ * important that the length is checked for validity first before doing
+ * the mod.
+ *
+ * Note to Bosco's Brigade: if you'd like to break this, put the
+ * module name on an invalid request.
+ *
+ */
+static int getaimdata(unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
+{
+ FILE *f;
+ static const char defaultmod[] = "aim.exe";
+ char *filename = NULL;
+ struct stat st;
+ unsigned char *buf;
+ int invalid = 0;
+
+ if (!bufret || !buflenret)
+ return -1;
+
+ if (modname) {
+
+ if (!(filename = malloc(strlen(aimbinarypath)+1+strlen(modname)+4+1))) {
+ dperror("memrequest: malloc");
+ return -1;
+ }
+
+ sprintf(filename, "%s/%s.ocm", aimbinarypath, modname);
+
+ } else {
+
+ if (!(filename = malloc(strlen(aimbinarypath)+1+strlen(defaultmod)+1))) {
+ dperror("memrequest: malloc");
+ return -1;
+ }
+
+ sprintf(filename, "%s/%s", aimbinarypath, defaultmod);
+
+ }
+
+ 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;