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