1 /*
2 * decode_aim.c
3 *
4 * AOL Instant Messenger (and ICQ2000).
5 *
6 * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
7 *
8 * $Id: decode_aim.c,v 1.5 2001/03/15 08:32:59 dugsong Exp $
9 */
10
11 #include "config.h"
12
13 #include <sys/types.h>
14 #include <arpa/inet.h> /* for ntohl() */
15
16 #include <stdio.h>
17 #include <string.h>
18
19 #include "hex.h"
20 #include "buf.h"
21 #include "decode.h"
22
23 struct flap {
24 u_char start;
25 u_char channel;
26 u_short seqnum;
27 u_short datalen;
28 };
29
30 static char *aim_xor1 = "Tic/Toc";
31
32 static u_char aim_xor2[] = {
33 0xf3, 0x26, 0x81, 0xc4, 0x39, 0x86, 0xdb, 0x92,
34 0x71, 0xa3, 0xb9, 0xe6, 0x53, 0x7a, 0x95, 0x7c
35 };
36
37 int
decode_aim(u_char * buf,int len,u_char * obuf,int olen)38 decode_aim(u_char *buf, int len, u_char *obuf, int olen)
39 {
40 struct buf *msg, inbuf, outbuf;
41 struct flap *flap;
42 u_char c, *p;
43 int i, j;
44
45 buf_init(&inbuf, buf, len);
46 buf_init(&outbuf, obuf, olen);
47
48 if (buf_cmp(&inbuf, "FLAPON\r\n\r\n", 10) == 0)
49 buf_skip(&inbuf, 10);
50
51 while (buf_len(&inbuf) > sizeof(*flap)) {
52 flap = (struct flap *)buf_ptr(&inbuf);
53 flap->datalen = ntohs(flap->datalen);
54
55 i = sizeof(*flap) + flap->datalen;
56
57 if ((msg = buf_tok(&inbuf, NULL, i)) == NULL)
58 break;
59
60 buf_skip(msg, sizeof(*flap));
61
62 if (buf_cmp(msg, "toc_signon ", 11) == 0) {
63 msg->base[msg->end - 1] = '\0';
64 p = buf_ptr(msg);
65
66 for (i = 0; i < 4; i++) {
67 if ((j = strcspn(p, " ")) > 0)
68 p += (j + 1);
69 }
70 if (strtok(p, " ") == NULL)
71 continue;
72
73 buf_putf(&outbuf, "%s ", buf_ptr(msg));
74
75 i = strlen(p);
76 j = hex_decode(p, i, p, i);
77
78 for (i = 0; i < j; i++)
79 p[i] = p[i] ^ aim_xor1[i % 7];
80 p[i] = '\0';
81
82 buf_putf(&outbuf, "[%s]\n", p);
83 }
84 else if (flap->start == 0x2a && flap->channel == 0x01 &&
85 buf_cmp(msg, "\x00\x00\x00\x01", 4) == 0) {
86 buf_skip(msg, 7);
87
88 buf_get(msg, &c, 1);
89 p = buf_ptr(msg);
90
91 if (c == 0 || buf_skip(msg, c + 3) < 0)
92 continue;
93
94 p[c] = '\0';
95
96 buf_get(msg, &c, 1);
97
98 if (buf_len(msg) < c + 1)
99 continue;
100
101 buf_putf(&outbuf, "%s\n", p);
102
103 p = buf_ptr(msg);
104
105 for (i = 0; i < c; i++) {
106 p[i] = p[i] ^ aim_xor2[i % sizeof(aim_xor2)];
107 }
108 p[i] = '\0';
109
110 buf_putf(&outbuf, "%s\n", p);
111
112 break;
113 }
114 }
115 buf_end(&outbuf);
116
117 return (buf_len(&outbuf));
118 }
119