Mercurial > pidgin
comparison src/protocols/oscar/login.c @ 2246:933346315b9b
[gaim-migrate @ 2256]
heh.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Sun, 09 Sep 2001 10:07:14 +0000 |
parents | edf8c5a70e5b |
children | d82efea341ef |
comparison
equal
deleted
inserted
replaced
2245:31157c54fe6e | 2246:933346315b9b |
---|---|
10 | 10 |
11 #include "md5.h" | 11 #include "md5.h" |
12 | 12 |
13 static int aim_encode_password(const char *password, unsigned char *encoded); | 13 static int aim_encode_password(const char *password, unsigned char *encoded); |
14 | 14 |
15 faim_export int aim_sendflapver(struct aim_session_t *sess, struct aim_conn_t *conn) | 15 faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn) |
16 { | 16 { |
17 int curbyte=0; | 17 aim_frame_t *fr; |
18 | 18 |
19 struct command_tx_struct *newpacket; | 19 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4))) |
20 | |
21 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0001, 4))) | |
22 return -ENOMEM; | 20 return -ENOMEM; |
23 | 21 |
24 newpacket->lock = 1; | 22 aimbs_put32(&fr->data, 0x00000001); |
25 | 23 |
26 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000); | 24 aim_tx_enqueue(sess, fr); |
27 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); | 25 |
28 | 26 return 0; |
29 newpacket->lock = 0; | 27 } |
30 | 28 |
31 return aim_tx_enqueue(sess, newpacket); | 29 /* |
32 } | 30 * This is a bit confusing. |
33 | 31 * |
34 /* | 32 * Normal SNAC login goes like this: |
35 * In AIM 3.5 protocol, the first stage of login is to request | 33 * - connect |
36 * login from the Authorizer, passing it the screen name | 34 * - server sends flap version |
37 * for verification. If the name is invalid, a 0017/0003 | 35 * - client sends flap version |
38 * is spit back, with the standard error contents. If valid, | 36 * - client sends screen name (17/6) |
39 * a 0017/0007 comes back, which is the signal to send | 37 * - server sends hash key (17/7) |
40 * it the main login command (0017/0002). | 38 * - client sends auth request (17/2 -- aim_send_login) |
41 */ | 39 * - server yells |
42 faim_export int aim_request_login(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn) | 40 * |
43 { | 41 * XOR login (for ICQ) goes like this: |
44 int curbyte; | 42 * - connect |
45 struct command_tx_struct *newpacket; | 43 * - server sends flap version |
46 | 44 * - client sends auth request which contains flap version (aim_send_login) |
45 * - server yells | |
46 * | |
47 * For the client API, we make them implement the most complicated version, | |
48 * and for the simpler version, we fake it and make it look like the more | |
49 * complicated process. | |
50 * | |
51 * This is done by giving the client a faked key, just so we can convince | |
52 * them to call aim_send_login right away, which will detect the session | |
53 * flag that says this is XOR login and ignore the key, sending an ICQ | |
54 * login request instead of the normal SNAC one. | |
55 * | |
56 * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/. | |
57 * | |
58 * XXX This may cause problems if the client relies on callbacks only | |
59 * being called from the context of aim_rxdispatch()... | |
60 * | |
61 */ | |
62 static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn) | |
63 { | |
64 aim_frame_t fr; | |
65 aim_rxcallback_t userfunc; | |
66 | |
67 sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; | |
68 sess->flags |= AIM_SESS_FLAGS_XORLOGIN; | |
69 | |
70 fr.conn = conn; | |
71 | |
72 if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007))) | |
73 userfunc(sess, &fr, ""); | |
74 | |
75 return 0; | |
76 } | |
77 | |
78 /* | |
79 * In AIM 3.5 protocol, the first stage of login is to request login from the | |
80 * Authorizer, passing it the screen name for verification. If the name is | |
81 * invalid, a 0017/0003 is spit back, with the standard error contents. If | |
82 * valid, a 0017/0007 comes back, which is the signal to send it the main | |
83 * login command (0017/0002). | |
84 * | |
85 * XXX make ICQ logins work again. | |
86 */ | |
87 faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn) | |
88 { | |
89 aim_frame_t *fr; | |
90 aim_snacid_t snacid; | |
91 aim_tlvlist_t *tl = NULL; | |
92 | |
47 if (!sess || !conn || !sn) | 93 if (!sess || !conn || !sn) |
48 return -EINVAL; | 94 return -EINVAL; |
49 | 95 |
50 /* | 96 if ((sn[0] >= '0') || (sn[0] <= '9')) |
51 * For ICQ, we enable the ancient horrible login and stuff | 97 return goddamnicq(sess, conn, sn); |
52 * a key packet into the queue to make it look like we got | |
53 * a reply back. This is so the client doesn't know we're | |
54 * really not doing MD5 login. | |
55 * | |
56 * This may sound stupid, but I'm not in the best of moods and | |
57 * I don't plan to keep support for this crap around much longer. | |
58 * Its all AOL's fault anyway, really. I hate AOL. Really. They | |
59 * always seem to be able to piss me off by doing the dumbest little | |
60 * things. Like disabling MD5 logins for ICQ UINs, or adding | |
61 * purposefully wrong TLV lengths, or adding superfluous information | |
62 * to host strings, or... I'll stop. | |
63 * | |
64 */ | |
65 if ((sn[0] >= '0') && (sn[0] <= '9')) { | |
66 struct command_rx_struct *newrx; | |
67 int i; | |
68 | |
69 /* XXX Uhm why doesn't this use aim_tx_new? */ | |
70 if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) | |
71 return -ENOMEM; | |
72 | |
73 memset(newrx, 0x00, sizeof(struct command_rx_struct)); | |
74 newrx->lock = 1; | |
75 newrx->hdrtype = AIM_FRAMETYPE_OSCAR; | |
76 newrx->hdr.oscar.type = 0x02; | |
77 newrx->hdr.oscar.seqnum = 0; | |
78 newrx->commandlen = 10+2+1; | |
79 newrx->nofree = 0; | |
80 | |
81 if (!(newrx->data = malloc(newrx->commandlen))) { | |
82 free(newrx); | |
83 return -ENOMEM; | |
84 } | |
85 | |
86 i = aim_putsnac(newrx->data, 0x0017, 0x0007, 0x0000, 0x0000); | |
87 i += aimutil_put16(newrx->data+i, 0x01); | |
88 i += aimutil_putstr(newrx->data+i, "0", 1); | |
89 | |
90 newrx->conn = conn; | |
91 | |
92 newrx->next = sess->queue_incoming; | |
93 sess->queue_incoming = newrx; | |
94 | |
95 newrx->lock = 0; | |
96 | |
97 sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; | |
98 | |
99 return 0; | |
100 } | |
101 | 98 |
102 sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; | 99 sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; |
103 | 100 |
104 aim_sendflapver(sess, conn); | 101 aim_sendflapver(sess, conn); |
105 | 102 |
106 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(sn)))) | 103 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn)))) |
107 return -ENOMEM; | 104 return -ENOMEM; |
108 | 105 |
109 newpacket->lock = 1; | 106 snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0); |
110 | 107 aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid); |
111 curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0006, 0x0000, 0x00010000); | 108 |
112 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); | 109 aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn); |
113 | 110 aim_writetlvchain(&fr->data, &tl); |
114 newpacket->commandlen = curbyte; | 111 aim_freetlvchain(&tl); |
115 newpacket->lock = 0; | 112 |
116 | 113 aim_tx_enqueue(sess, fr); |
117 return aim_tx_enqueue(sess, newpacket); | 114 |
115 return 0; | |
116 } | |
117 | |
118 /* | |
119 * Part two of the ICQ hack. Note the ignoring of the key and clientinfo. | |
120 */ | |
121 static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password) | |
122 { | |
123 static const char clientstr[] = {"ICQ Inc. - Product of ICQ (TM) 2000b.4.65.1.3281.85"}; | |
124 static const char lang[] = {"en"}; | |
125 static const char country[] = {"us"}; | |
126 aim_frame_t *fr; | |
127 aim_tlvlist_t *tl = NULL; | |
128 char *password_encoded; | |
129 | |
130 if (!(password_encoded = (char *) malloc(strlen(password)))) | |
131 return -ENOMEM; | |
132 | |
133 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 1152))) { | |
134 free(password_encoded); | |
135 return -ENOMEM; | |
136 } | |
137 | |
138 aim_encode_password(password, password_encoded); | |
139 | |
140 aimbs_put32(&fr->data, 0x00000001); | |
141 aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn); | |
142 aim_addtlvtochain_raw(&tl, 0x0002, strlen(password), password_encoded); | |
143 aim_addtlvtochain_raw(&tl, 0x0003, strlen(clientstr), clientstr); | |
144 aim_addtlvtochain16(&tl, 0x0016, 0x010a); | |
145 aim_addtlvtochain16(&tl, 0x0017, 0x0004); | |
146 aim_addtlvtochain16(&tl, 0x0018, 0x0041); | |
147 aim_addtlvtochain16(&tl, 0x0019, 0x0001); | |
148 aim_addtlvtochain16(&tl, 0x001a, 0x0cd1); | |
149 aim_addtlvtochain32(&tl, 0x0014, 0x00000055); | |
150 aim_addtlvtochain_raw(&tl, 0x000f, strlen(lang), lang); | |
151 aim_addtlvtochain_raw(&tl, 0x000e, strlen(country), country); | |
152 | |
153 aim_writetlvchain(&fr->data, &tl); | |
154 | |
155 free(password_encoded); | |
156 aim_freetlvchain(&tl); | |
157 | |
158 aim_tx_enqueue(sess, fr); | |
159 | |
160 return 0; | |
118 } | 161 } |
119 | 162 |
120 /* | 163 /* |
121 * send_login(int socket, char *sn, char *password) | 164 * send_login(int socket, char *sn, char *password) |
122 * | 165 * |
174 * build = 0x0070 | 217 * build = 0x0070 |
175 * unknown= 0x0000008b | 218 * unknown= 0x0000008b |
176 * serverstore = 0x01 | 219 * serverstore = 0x01 |
177 * | 220 * |
178 */ | 221 */ |
179 faim_export int aim_send_login (struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, char *password, struct client_info_s *clientinfo, char *key) | 222 faim_export int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password, struct client_info_s *clientinfo, const char *key) |
180 { | 223 { |
181 int curbyte=0; | 224 aim_frame_t *fr; |
182 struct command_tx_struct *newpacket; | 225 aim_tlvlist_t *tl = NULL; |
226 fu8_t digest[16]; | |
227 aim_snacid_t snacid; | |
183 | 228 |
184 if (!clientinfo || !sn || !password) | 229 if (!clientinfo || !sn || !password) |
185 return -EINVAL; | 230 return -EINVAL; |
186 | 231 |
187 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152))) | 232 if (sess->flags & AIM_SESS_FLAGS_XORLOGIN) |
233 return goddamnicq2(sess, conn, sn, password); | |
234 | |
235 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) | |
188 return -ENOMEM; | 236 return -ENOMEM; |
189 | 237 |
190 newpacket->lock = 1; | 238 if (sess->flags & AIM_SESS_FLAGS_XORLOGIN) { |
191 | 239 fr->hdr.flap.type = 0x01; |
192 newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01; | 240 |
193 | 241 /* Use very specific version numbers to further indicate hack */ |
194 if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) | 242 clientinfo->major2 = 0x010a; |
195 curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000); | 243 clientinfo->major = 0x0004; |
196 else { | 244 clientinfo->minor = 0x003c; |
197 curbyte = aimutil_put16(newpacket->data, 0x0000); | 245 clientinfo->minor2 = 0x0001; |
198 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001); | 246 clientinfo->build = 0x0cce; |
247 clientinfo->unknown = 0x00000055; | |
199 } | 248 } |
200 | 249 |
201 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn); | 250 snacid = aim_cachesnac(sess, 0x0017, 0x0002, 0x0000, NULL, 0); |
202 | 251 aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid); |
203 if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { | 252 |
204 unsigned char digest[16]; | 253 aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), sn); |
205 | 254 |
206 aim_encode_password_md5(password, key, digest); | 255 aim_encode_password_md5(password, key, digest); |
207 curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest); | 256 aim_addtlvtochain_raw(&tl, 0x0025, 16, digest); |
208 } else { | 257 |
209 char *password_encoded; | 258 aim_addtlvtochain_raw(&tl, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); |
210 | 259 aim_addtlvtochain16(&tl, 0x0016, (fu16_t)clientinfo->major2); |
211 password_encoded = (char *) malloc(strlen(password)); | 260 aim_addtlvtochain16(&tl, 0x0017, (fu16_t)clientinfo->major); |
212 aim_encode_password(password, password_encoded); | 261 aim_addtlvtochain16(&tl, 0x0018, (fu16_t)clientinfo->minor); |
213 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded); | 262 aim_addtlvtochain16(&tl, 0x0019, (fu16_t)clientinfo->minor2); |
214 free(password_encoded); | 263 aim_addtlvtochain16(&tl, 0x001a, (fu16_t)clientinfo->build); |
215 } | 264 aim_addtlvtochain_raw(&tl, 0x000e, strlen(clientinfo->country), clientinfo->country); |
216 | 265 aim_addtlvtochain_raw(&tl, 0x000f, strlen(clientinfo->lang), clientinfo->lang); |
217 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring); | 266 aim_addtlvtochain16(&tl, 0x0009, 0x0015); |
218 | 267 |
219 if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { | 268 aim_writetlvchain(&fr->data, &tl); |
220 | 269 |
221 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2); | 270 aim_freetlvchain(&tl); |
222 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major); | 271 |
223 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor); | 272 aim_tx_enqueue(sess, fr); |
224 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2); | 273 |
225 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build); | 274 return 0; |
226 | 275 } |
227 } else { | 276 |
228 /* Use very specific version numbers, to further indicate the hack. */ | 277 faim_export int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest) |
229 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x010a); | |
230 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0004); | |
231 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x003c); | |
232 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0001); | |
233 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0cce); | |
234 curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x00000055); | |
235 } | |
236 | |
237 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country); | |
238 curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang); | |
239 | |
240 if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) { | |
241 curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown); | |
242 curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015); | |
243 } | |
244 | |
245 newpacket->commandlen = curbyte; | |
246 newpacket->lock = 0; | |
247 | |
248 return aim_tx_enqueue(sess, newpacket); | |
249 } | |
250 | |
251 faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest) | |
252 { | 278 { |
253 md5_state_t state; | 279 md5_state_t state; |
254 | 280 |
255 md5_init(&state); | 281 md5_init(&state); |
256 md5_append(&state, (const md5_byte_t *)key, strlen(key)); | 282 md5_append(&state, (const md5_byte_t *)key, strlen(key)); |
276 * hope it doesn't change over time! | 302 * hope it doesn't change over time! |
277 * | 303 * |
278 * This is only used for the XOR method, not the better MD5 method. | 304 * This is only used for the XOR method, not the better MD5 method. |
279 * | 305 * |
280 */ | 306 */ |
281 static int aim_encode_password(const char *password, unsigned char *encoded) | 307 static int aim_encode_password(const char *password, fu8_t *encoded) |
282 { | 308 { |
283 unsigned char encoding_table[] = { | 309 fu8_t encoding_table[] = { |
284 #if 0 /* old v1 table */ | 310 #if 0 /* old v1 table */ |
285 0xf3, 0xb3, 0x6c, 0x99, | 311 0xf3, 0xb3, 0x6c, 0x99, |
286 0x95, 0x3f, 0xac, 0xb6, | 312 0x95, 0x3f, 0xac, 0xb6, |
287 0xc5, 0xfa, 0x6b, 0x63, | 313 0xc5, 0xfa, 0x6b, 0x63, |
288 0x69, 0x6c, 0xc3, 0x9f | 314 0x69, 0x6c, 0xc3, 0x9f |
302 } | 328 } |
303 | 329 |
304 /* | 330 /* |
305 * Generate an authorization response. | 331 * Generate an authorization response. |
306 * | 332 * |
307 * You probably don't want this unless you're writing an AIM server. | 333 * You probably don't want this unless you're writing an AIM server. Which |
308 * | 334 * I hope you're not doing. Because it's far more difficult than it looks. |
309 */ | 335 * |
310 faim_export unsigned long aim_sendauthresp(struct aim_session_t *sess, | 336 */ |
311 struct aim_conn_t *conn, | 337 faim_export int aim_sendauthresp(aim_session_t *sess, aim_conn_t *conn, const char *sn, int errorcode, const char *errorurl, const char *bosip, const char *cookie, const char *email, int regstatus) |
312 char *sn, int errorcode, | |
313 char *errorurl, char *bosip, | |
314 char *cookie, char *email, | |
315 int regstatus) | |
316 { | 338 { |
317 struct command_tx_struct *tx; | 339 aim_tlvlist_t *tlvlist = NULL; |
318 struct aim_tlvlist_t *tlvlist = NULL; | 340 aim_frame_t *fr; |
319 | 341 |
320 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0004, 1152))) | 342 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x04, 1152))) |
321 return -ENOMEM; | 343 return -ENOMEM; |
322 | 344 |
323 tx->lock = 1; | |
324 | |
325 if (sn) | 345 if (sn) |
326 aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn)); | 346 aim_addtlvtochain_raw(&tlvlist, 0x0001, strlen(sn), sn); |
327 else | 347 else |
328 aim_addtlvtochain_str(&tlvlist, 0x0001, sess->sn, strlen(sess->sn)); | 348 aim_addtlvtochain_raw(&tlvlist, 0x0001, strlen(sess->sn), sess->sn); |
329 | 349 |
330 if (errorcode) { | 350 if (errorcode) { |
331 aim_addtlvtochain16(&tlvlist, 0x0008, errorcode); | 351 aim_addtlvtochain16(&tlvlist, 0x0008, errorcode); |
332 aim_addtlvtochain_str(&tlvlist, 0x0004, errorurl, strlen(errorurl)); | 352 aim_addtlvtochain_raw(&tlvlist, 0x0004, strlen(errorurl), errorurl); |
333 } else { | 353 } else { |
334 aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip)); | 354 aim_addtlvtochain_raw(&tlvlist, 0x0005, strlen(bosip), bosip); |
335 aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN); | 355 aim_addtlvtochain_raw(&tlvlist, 0x0006, AIM_COOKIELEN, cookie); |
336 aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email)); | 356 aim_addtlvtochain_raw(&tlvlist, 0x0011, strlen(email), email); |
337 aim_addtlvtochain16(&tlvlist, 0x0013, (unsigned short)regstatus); | 357 aim_addtlvtochain16(&tlvlist, 0x0013, (fu16_t)regstatus); |
338 } | 358 } |
339 | 359 |
340 tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist); | 360 aim_writetlvchain(&fr->data, &tlvlist); |
341 tx->lock = 0; | 361 aim_freetlvchain(&tlvlist); |
342 | 362 |
343 return aim_tx_enqueue(sess, tx); | 363 aim_tx_enqueue(sess, fr); |
364 | |
365 return 0; | |
344 } | 366 } |
345 | 367 |
346 /* | 368 /* |
347 * Generate a random cookie. (Non-client use only) | 369 * Generate a random cookie. (Non-client use only) |
348 */ | 370 */ |
349 faim_export int aim_gencookie(unsigned char *buf) | 371 faim_export int aim_gencookie(fu8_t *buf) |
350 { | 372 { |
351 int i; | 373 int i; |
352 | 374 |
353 srand(time(NULL)); | 375 srand(time(NULL)); |
354 | 376 |
355 for (i=0; i < AIM_COOKIELEN; i++) | 377 for (i = 0; i < AIM_COOKIELEN; i++) |
356 buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0)); | 378 buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0)); |
357 | 379 |
358 return i; | 380 return i; |
359 } | 381 } |
360 | 382 |
361 /* | 383 /* |
362 * Send Server Ready. (Non-client) | 384 * Send Server Ready. (Non-client) |
363 */ | 385 */ |
364 faim_export int aim_sendserverready(struct aim_session_t *sess, struct aim_conn_t *conn) | 386 faim_export int aim_sendserverready(aim_session_t *sess, aim_conn_t *conn) |
365 { | 387 { |
366 struct command_tx_struct *tx; | 388 aim_frame_t *fr; |
367 int i; | 389 aim_snacid_t snacid; |
368 | 390 |
369 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+0x22))) | 391 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+0x22))) |
370 return -ENOMEM; | 392 return -ENOMEM; |
371 | 393 |
372 tx->lock = 1; | 394 snacid = aim_cachesnac(sess, 0x0001, 0x0003, 0x0000, NULL, 0); |
373 | 395 |
374 i = aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++); | 396 aim_putsnac(&fr->data, 0x0001, 0x0003, 0x0000, snacid); |
375 | 397 aimbs_put16(&fr->data, 0x0001); |
376 i += aimutil_put16(tx->data+i, 0x0001); | 398 aimbs_put16(&fr->data, 0x0002); |
377 i += aimutil_put16(tx->data+i, 0x0002); | 399 aimbs_put16(&fr->data, 0x0003); |
378 i += aimutil_put16(tx->data+i, 0x0003); | 400 aimbs_put16(&fr->data, 0x0004); |
379 i += aimutil_put16(tx->data+i, 0x0004); | 401 aimbs_put16(&fr->data, 0x0006); |
380 i += aimutil_put16(tx->data+i, 0x0006); | 402 aimbs_put16(&fr->data, 0x0008); |
381 i += aimutil_put16(tx->data+i, 0x0008); | 403 aimbs_put16(&fr->data, 0x0009); |
382 i += aimutil_put16(tx->data+i, 0x0009); | 404 aimbs_put16(&fr->data, 0x000a); |
383 i += aimutil_put16(tx->data+i, 0x000a); | 405 aimbs_put16(&fr->data, 0x000b); |
384 i += aimutil_put16(tx->data+i, 0x000b); | 406 aimbs_put16(&fr->data, 0x000c); |
385 i += aimutil_put16(tx->data+i, 0x000c); | 407 aimbs_put16(&fr->data, 0x0013); |
386 i += aimutil_put16(tx->data+i, 0x0013); | 408 aimbs_put16(&fr->data, 0x0015); |
387 i += aimutil_put16(tx->data+i, 0x0015); | 409 |
388 | 410 aim_tx_enqueue(sess, fr); |
389 tx->commandlen = i; | 411 |
390 tx->lock = 0; | 412 return 0; |
391 | |
392 return aim_tx_enqueue(sess, tx); | |
393 } | 413 } |
394 | 414 |
395 | 415 |
396 /* | 416 /* |
397 * Send service redirect. (Non-Client) | 417 * Send service redirect. (Non-Client) |
398 */ | 418 */ |
399 faim_export unsigned long aim_sendredirect(struct aim_session_t *sess, struct aim_conn_t *conn, unsigned short servid, char *ip, char *cookie) | 419 faim_export int aim_sendredirect(aim_session_t *sess, aim_conn_t *conn, fu16_t servid, const char *ip, const char *cookie) |
400 { | 420 { |
401 struct command_tx_struct *tx; | 421 aim_tlvlist_t *tlvlist = NULL; |
402 struct aim_tlvlist_t *tlvlist = NULL; | 422 aim_frame_t *fr; |
403 int i; | 423 aim_snacid_t snacid; |
404 | 424 |
405 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152))) | 425 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) |
406 return -ENOMEM; | 426 return -ENOMEM; |
407 | 427 |
408 tx->lock = 1; | 428 snacid = aim_cachesnac(sess, 0x0001, 0x0005, 0x0000, NULL, 0); |
409 | 429 aim_putsnac(&fr->data, 0x0001, 0x0005, 0x0000, snacid); |
410 i = aim_putsnac(tx->data, 0x0001, 0x0005, 0x0000, 0x00000000); | |
411 | 430 |
412 aim_addtlvtochain16(&tlvlist, 0x000d, servid); | 431 aim_addtlvtochain16(&tlvlist, 0x000d, servid); |
413 aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip)); | 432 aim_addtlvtochain_raw(&tlvlist, 0x0005, strlen(ip), ip); |
414 aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN); | 433 aim_addtlvtochain_raw(&tlvlist, 0x0006, AIM_COOKIELEN, cookie); |
415 | 434 |
416 tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i; | 435 aim_writetlvchain(&fr->data, &tlvlist); |
417 aim_freetlvchain(&tlvlist); | 436 aim_freetlvchain(&tlvlist); |
418 | 437 |
419 tx->lock = 0; | 438 aim_tx_enqueue(sess, fr); |
420 | 439 |
421 return aim_tx_enqueue(sess, tx); | 440 return 0; |
422 } | 441 } |
423 | 442 |
424 | 443 |
425 static int hostonline(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 444 static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
426 { | 445 { |
427 aim_rxcallback_t userfunc; | 446 aim_rxcallback_t userfunc; |
428 int ret = 0; | 447 int ret = 0; |
429 unsigned short *families; | 448 fu16_t *families; |
430 int famcount, i; | 449 int famcount; |
431 | 450 |
432 famcount = datalen/2; | 451 if (!(families = malloc(aim_bstream_empty(bs)))) |
433 | |
434 if (!(families = malloc(datalen))) | |
435 return 0; | 452 return 0; |
436 | 453 |
437 for (i = 0; i < famcount; i++) | 454 for (famcount = 0; aim_bstream_empty(bs); famcount++) |
438 families[i] = aimutil_get16(data+(i*2)); | 455 families[famcount] = aimbs_get16(bs); |
439 | 456 |
440 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 457 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
441 ret = userfunc(sess, rx, famcount, families); | 458 ret = userfunc(sess, rx, famcount, families); |
442 | 459 |
443 free(families); | 460 free(families); |
444 | 461 |
445 return ret; | 462 return ret; |
446 } | 463 } |
447 | 464 |
448 static int redirect(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 465 static int redirect(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
449 { | 466 { |
450 int serviceid; | 467 int serviceid; |
451 unsigned char *cookie; | 468 fu8_t *cookie; |
452 char *ip; | 469 char *ip; |
453 aim_rxcallback_t userfunc; | 470 aim_rxcallback_t userfunc; |
454 struct aim_tlvlist_t *tlvlist; | 471 aim_tlvlist_t *tlvlist; |
455 char *chathack = NULL; | 472 char *chathack = NULL; |
456 int chathackex = 0; | 473 int chathackex = 0; |
457 int ret = 0; | 474 int ret = 0; |
458 | 475 |
459 tlvlist = aim_readtlvchain(data, datalen); | 476 tlvlist = aim_readtlvchain(bs); |
460 | 477 |
461 if (!aim_gettlv(tlvlist, 0x000d, 1) || | 478 if (!aim_gettlv(tlvlist, 0x000d, 1) || |
462 !aim_gettlv(tlvlist, 0x0005, 1) || | 479 !aim_gettlv(tlvlist, 0x0005, 1) || |
463 !aim_gettlv(tlvlist, 0x0006, 1)) { | 480 !aim_gettlv(tlvlist, 0x0006, 1)) { |
464 aim_freetlvchain(&tlvlist); | 481 aim_freetlvchain(&tlvlist); |
540 * seems to be a big mystery. | 557 * seems to be a big mystery. |
541 * | 558 * |
542 */ | 559 */ |
543 | 560 |
544 /* XXX parse this */ | 561 /* XXX parse this */ |
545 static int rateresp(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 562 static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
546 { | 563 { |
547 aim_rxcallback_t userfunc; | 564 aim_rxcallback_t userfunc; |
548 | 565 |
549 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 566 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
550 return userfunc(sess, rx); | 567 return userfunc(sess, rx); |
551 | 568 |
552 return 0; | 569 return 0; |
553 } | 570 } |
554 | 571 |
555 static int ratechange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 572 static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
556 { | 573 { |
557 aim_rxcallback_t userfunc; | 574 aim_rxcallback_t userfunc; |
558 int i = 0, code; | 575 fu16_t code, rateclass; |
559 unsigned long currentavg, maxavg; | 576 fu32_t currentavg, maxavg, windowsize, clear, alert, limit, disconnect; |
560 unsigned long rateclass, windowsize, clear, alert, limit, disconnect; | 577 |
561 | 578 code = aimbs_get16(bs); |
562 code = aimutil_get16(data+i); | 579 rateclass = aimbs_get16(bs); |
563 i += 2; | 580 |
564 | 581 windowsize = aimbs_get32(bs); |
565 rateclass = aimutil_get16(data+i); | 582 clear = aimbs_get32(bs); |
566 i += 2; | 583 alert = aimbs_get32(bs); |
567 | 584 limit = aimbs_get32(bs); |
568 windowsize = aimutil_get32(data+i); | 585 disconnect = aimbs_get32(bs); |
569 i += 4; | 586 currentavg = aimbs_get32(bs); |
570 clear = aimutil_get32(data+i); | 587 maxavg = aimbs_get32(bs); |
571 i += 4; | |
572 alert = aimutil_get32(data+i); | |
573 i += 4; | |
574 limit = aimutil_get32(data+i); | |
575 i += 4; | |
576 disconnect = aimutil_get32(data+i); | |
577 i += 4; | |
578 currentavg = aimutil_get32(data+i); | |
579 i += 4; | |
580 maxavg = aimutil_get32(data+i); | |
581 i += 4; | |
582 | 588 |
583 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 589 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
584 return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); | 590 return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); |
585 | 591 |
586 return 0; | 592 return 0; |
587 } | 593 } |
588 | 594 |
589 /* XXX parse this */ | 595 /* XXX parse this */ |
590 static int selfinfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 596 static int selfinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
591 { | 597 { |
592 aim_rxcallback_t userfunc; | 598 aim_rxcallback_t userfunc; |
593 | 599 |
594 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 600 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
595 return userfunc(sess, rx); | 601 return userfunc(sess, rx); |
596 | 602 |
597 return 0; | 603 return 0; |
598 } | 604 } |
599 | 605 |
600 static int evilnotify(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 606 static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
601 { | 607 { |
602 aim_rxcallback_t userfunc = NULL; | 608 aim_rxcallback_t userfunc; |
603 int i = 0; | 609 fu16_t newevil; |
604 unsigned short newevil; | |
605 struct aim_userinfo_s userinfo; | 610 struct aim_userinfo_s userinfo; |
606 | 611 |
607 newevil = aimutil_get16(data); | |
608 i += 2; | |
609 | |
610 memset(&userinfo, 0, sizeof(struct aim_userinfo_s)); | 612 memset(&userinfo, 0, sizeof(struct aim_userinfo_s)); |
611 | 613 |
612 if (datalen-i) | 614 newevil = aimbs_get16(bs); |
613 i += aim_extractuserinfo(sess, data+i, &userinfo); | 615 |
616 if (aim_bstream_empty(bs)) | |
617 aim_extractuserinfo(sess, bs, &userinfo); | |
614 | 618 |
615 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 619 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
616 return userfunc(sess, rx, newevil, &userinfo); | 620 return userfunc(sess, rx, newevil, &userinfo); |
617 | 621 |
618 return 0; | 622 return 0; |
619 } | 623 } |
620 | 624 |
621 static int motd(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 625 static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
622 { | 626 { |
623 aim_rxcallback_t userfunc; | 627 aim_rxcallback_t userfunc; |
624 char *msg = NULL; | 628 char *msg = NULL; |
625 int ret = 0; | 629 int ret = 0; |
626 struct aim_tlvlist_t *tlvlist; | 630 aim_tlvlist_t *tlvlist; |
627 unsigned short id; | 631 fu16_t id; |
628 | 632 |
629 /* | 633 /* |
630 * Code. | 634 * Code. |
631 * | 635 * |
632 * Valid values: | 636 * Valid values: |
634 * 2 Advisory upgrade | 638 * 2 Advisory upgrade |
635 * 3 System bulletin | 639 * 3 System bulletin |
636 * 4 Nothing's wrong ("top o the world" -- normal) | 640 * 4 Nothing's wrong ("top o the world" -- normal) |
637 * | 641 * |
638 */ | 642 */ |
639 id = aimutil_get16(data); | 643 id = aimbs_get16(bs); |
640 | 644 |
641 /* | 645 /* |
642 * TLVs follow | 646 * TLVs follow |
643 */ | 647 */ |
644 if ((tlvlist = aim_readtlvchain(data+2, datalen-2))) | 648 tlvlist = aim_readtlvchain(bs); |
645 msg = aim_gettlv_str(tlvlist, 0x000b, 1); | 649 |
650 msg = aim_gettlv_str(tlvlist, 0x000b, 1); | |
646 | 651 |
647 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 652 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
648 ret = userfunc(sess, rx, id, msg); | 653 ret = userfunc(sess, rx, id, msg); |
649 | 654 |
650 free(msg); | 655 free(msg); |
652 aim_freetlvchain(&tlvlist); | 657 aim_freetlvchain(&tlvlist); |
653 | 658 |
654 return ret; | 659 return ret; |
655 } | 660 } |
656 | 661 |
657 static int hostversions(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 662 static int hostversions(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
658 { | 663 { |
659 aim_rxcallback_t userfunc; | 664 aim_rxcallback_t userfunc; |
660 int vercount; | 665 int vercount; |
661 | 666 fu8_t *versions; |
662 vercount = datalen/4; | 667 |
668 vercount = aim_bstream_empty(bs)/4; | |
669 versions = aimbs_getraw(bs, aim_bstream_empty(bs)); | |
663 | 670 |
664 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 671 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
665 return userfunc(sess, rx, vercount, data); | 672 return userfunc(sess, rx, vercount, versions); |
673 | |
674 free(versions); | |
666 | 675 |
667 return 0; | 676 return 0; |
668 } | 677 } |
669 | 678 |
670 /* | 679 /* |
702 * on numerous ocassions. | 711 * on numerous ocassions. |
703 * | 712 * |
704 * Anyway, neener. We win again. | 713 * Anyway, neener. We win again. |
705 * | 714 * |
706 */ | 715 */ |
707 static int memrequest(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | 716 static int memrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
708 { | 717 { |
709 aim_rxcallback_t userfunc; | 718 aim_rxcallback_t userfunc; |
710 unsigned long offset, len; | 719 fu32_t offset, len; |
711 int i = 0; | 720 aim_tlvlist_t *list; |
712 struct aim_tlvlist_t *list; | 721 char *modname; |
713 char *modname = NULL; | 722 |
714 | 723 offset = aimbs_get32(bs); |
715 offset = aimutil_get32(data); | 724 len = aimbs_get32(bs); |
716 i += 4; | 725 list = aim_readtlvchain(bs); |
717 | 726 |
718 len = aimutil_get32(data+4); | 727 modname = aim_gettlv_str(list, 0x0001, 1); |
719 i += 4; | |
720 | |
721 list = aim_readtlvchain(data+i, datalen-i); | |
722 | |
723 if (aim_gettlv(list, 0x0001, 1)) | |
724 modname = aim_gettlv_str(list, 0x0001, 1); | |
725 | 728 |
726 faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname ? modname : "aim.exe"); | 729 faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname ? modname : "aim.exe"); |
727 | 730 |
728 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 731 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
729 return userfunc(sess, rx, offset, len, modname); | 732 return userfunc(sess, rx, offset, len, modname); |
732 aim_freetlvchain(&list); | 735 aim_freetlvchain(&list); |
733 | 736 |
734 return 0; | 737 return 0; |
735 } | 738 } |
736 | 739 |
737 static void dumpbox(struct aim_session_t *sess, unsigned char *buf, int len) | 740 #if 0 |
741 static void dumpbox(aim_session_t *sess, unsigned char *buf, int len) | |
738 { | 742 { |
739 int i; | 743 int i; |
740 | 744 |
741 if (!sess || !buf || !len) | 745 if (!sess || !buf || !len) |
742 return; | 746 return; |
752 | 756 |
753 faimdprintf(sess, 1, "\n\n"); | 757 faimdprintf(sess, 1, "\n\n"); |
754 | 758 |
755 return; | 759 return; |
756 } | 760 } |
757 | 761 #endif |
758 faim_export int aim_sendmemblock(struct aim_session_t *sess, struct aim_conn_t *conn, unsigned long offset, unsigned long len, const unsigned char *buf, unsigned char flag) | 762 |
759 { | 763 faim_export int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, fu32_t offset, fu32_t len, const fu8_t *buf, fu8_t flag) |
760 struct command_tx_struct *tx; | 764 { |
761 int i = 0; | 765 aim_frame_t *fr; |
766 aim_snacid_t snacid; | |
762 | 767 |
763 if (!sess || !conn) | 768 if (!sess || !conn) |
764 return -EINVAL; | 769 return -EINVAL; |
765 | 770 |
766 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+16))) | 771 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16))) |
767 return -ENOMEM; | 772 return -ENOMEM; |
768 | 773 |
769 tx->lock = 1; | 774 snacid = aim_cachesnac(sess, 0x0001, 0x0020, 0x0000, NULL, 0); |
770 | 775 |
771 i = aim_putsnac(tx->data, 0x0001, 0x0020, 0x0000, sess->snac_nextid++); | 776 aim_putsnac(&fr->data, 0x0001, 0x0020, 0x0000, snacid); |
772 i += aimutil_put16(tx->data+i, 0x0010); /* md5 is always 16 bytes */ | 777 aimbs_put16(&fr->data, 0x0010); /* md5 is always 16 bytes */ |
773 | 778 |
774 if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ | 779 if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ |
775 | 780 |
776 memcpy(tx->data+i, buf, 0x10); | 781 aimbs_putraw(&fr->data, buf, 0x10); |
777 i += 0x10; | |
778 | 782 |
779 } else if (buf && (len > 0)) { /* use input buffer */ | 783 } else if (buf && (len > 0)) { /* use input buffer */ |
780 md5_state_t state; | 784 md5_state_t state; |
785 md5_byte_t digest[0x10]; | |
781 | 786 |
782 md5_init(&state); | 787 md5_init(&state); |
783 md5_append(&state, (const md5_byte_t *)buf, len); | 788 md5_append(&state, (const md5_byte_t *)buf, len); |
784 md5_finish(&state, (md5_byte_t *)(tx->data+i)); | 789 md5_finish(&state, digest); |
785 i += 0x10; | 790 |
791 aimbs_putraw(&fr->data, (fu8_t *)digest, 0x10); | |
786 | 792 |
787 } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ | 793 } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ |
788 md5_state_t state; | 794 md5_state_t state; |
789 unsigned char nil = '\0'; | 795 fu8_t nil = '\0'; |
796 md5_byte_t digest[0x10]; | |
790 | 797 |
791 /* | 798 /* |
792 * These MD5 routines are stupid in that you have to have | 799 * These MD5 routines are stupid in that you have to have |
793 * at least one append. So thats why this doesn't look | 800 * at least one append. So thats why this doesn't look |
794 * real logical. | 801 * real logical. |
795 */ | 802 */ |
796 md5_init(&state); | 803 md5_init(&state); |
797 md5_append(&state, (const md5_byte_t *)&nil, 0); | 804 md5_append(&state, (const md5_byte_t *)&nil, 0); |
798 md5_finish(&state, (md5_byte_t *)(tx->data+i)); | 805 md5_finish(&state, digest); |
799 i += 0x10; | 806 |
807 aimbs_putraw(&fr->data, (fu8_t *)digest, 0x10); | |
800 | 808 |
801 } else { | 809 } else { |
802 | 810 |
803 /* | 811 /* |
804 * This data is correct for AIM 3.5.1670. | 812 * This data is correct for AIM 3.5.1670. |
808 * | 816 * |
809 */ | 817 */ |
810 if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { | 818 if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { |
811 | 819 |
812 #if 1 /* with "AnrbnrAqhfzcd" */ | 820 #if 1 /* with "AnrbnrAqhfzcd" */ |
813 i += aimutil_put32(tx->data+i, 0x44a95d26); | 821 aimbs_put32(&fr->data, 0x44a95d26); |
814 i += aimutil_put32(tx->data+i, 0xd2490423); | 822 aimbs_put32(&fr->data, 0xd2490423); |
815 i += aimutil_put32(tx->data+i, 0x93b8821f); | 823 aimbs_put32(&fr->data, 0x93b8821f); |
816 i += aimutil_put32(tx->data+i, 0x51c54b01); | 824 aimbs_put32(&fr->data, 0x51c54b01); |
817 #else /* no filename */ | 825 #else /* no filename */ |
818 i += aimutil_put32(tx->data+i, 0x1df8cbae); | 826 aimbs_put32(&fr->data, 0x1df8cbae); |
819 i += aimutil_put32(tx->data+i, 0x5523b839); | 827 aimbs_put32(&fr->data, 0x5523b839); |
820 i += aimutil_put32(tx->data+i, 0xa0e10db3); | 828 aimbs_put32(&fr->data, 0xa0e10db3); |
821 i += aimutil_put32(tx->data+i, 0xa46d3b39); | 829 aimbs_put32(&fr->data, 0xa46d3b39); |
822 #endif | 830 #endif |
823 | 831 |
824 } else if ((offset == 0x00001000) && (len == 0x00000000)) { | 832 } else if ((offset == 0x00001000) && (len == 0x00000000)) { |
825 | 833 |
826 i += aimutil_put32(tx->data+i, 0xd41d8cd9); | 834 aimbs_put32(&fr->data, 0xd41d8cd9); |
827 i += aimutil_put32(tx->data+i, 0x8f00b204); | 835 aimbs_put32(&fr->data, 0x8f00b204); |
828 i += aimutil_put32(tx->data+i, 0xe9800998); | 836 aimbs_put32(&fr->data, 0xe9800998); |
829 i += aimutil_put32(tx->data+i, 0xecf8427e); | 837 aimbs_put32(&fr->data, 0xecf8427e); |
830 | 838 |
831 } else | 839 } else |
832 faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n"); | 840 faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n"); |
833 | 841 |
834 } | 842 } |
835 | 843 |
836 tx->commandlen = i; | 844 aim_tx_enqueue(sess, fr); |
837 tx->lock = 0; | 845 |
838 aim_tx_enqueue(sess, tx); | 846 return 0; |
839 | 847 } |
840 return 0; | 848 |
841 } | 849 static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
842 | |
843 static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen) | |
844 { | 850 { |
845 | 851 |
846 if (snac->subtype == 0x0003) | 852 if (snac->subtype == 0x0003) |
847 return hostonline(sess, mod, rx, snac, data, datalen); | 853 return hostonline(sess, mod, rx, snac, bs); |
848 else if (snac->subtype == 0x0005) | 854 else if (snac->subtype == 0x0005) |
849 return redirect(sess, mod, rx, snac, data, datalen); | 855 return redirect(sess, mod, rx, snac, bs); |
850 else if (snac->subtype == 0x0007) | 856 else if (snac->subtype == 0x0007) |
851 return rateresp(sess, mod, rx, snac, data, datalen); | 857 return rateresp(sess, mod, rx, snac, bs); |
852 else if (snac->subtype == 0x000a) | 858 else if (snac->subtype == 0x000a) |
853 return ratechange(sess, mod, rx, snac, data, datalen); | 859 return ratechange(sess, mod, rx, snac, bs); |
854 else if (snac->subtype == 0x000f) | 860 else if (snac->subtype == 0x000f) |
855 return selfinfo(sess, mod, rx, snac, data, datalen); | 861 return selfinfo(sess, mod, rx, snac, bs); |
856 else if (snac->subtype == 0x0010) | 862 else if (snac->subtype == 0x0010) |
857 return evilnotify(sess, mod, rx, snac, data, datalen); | 863 return evilnotify(sess, mod, rx, snac, bs); |
858 else if (snac->subtype == 0x0013) | 864 else if (snac->subtype == 0x0013) |
859 return motd(sess, mod, rx, snac, data, datalen); | 865 return motd(sess, mod, rx, snac, bs); |
860 else if (snac->subtype == 0x0018) | 866 else if (snac->subtype == 0x0018) |
861 return hostversions(sess, mod, rx, snac, data, datalen); | 867 return hostversions(sess, mod, rx, snac, bs); |
862 else if (snac->subtype == 0x001f) | 868 else if (snac->subtype == 0x001f) |
863 return memrequest(sess, mod, rx, snac, data, datalen); | 869 return memrequest(sess, mod, rx, snac, bs); |
864 | 870 |
865 return 0; | 871 return 0; |
866 } | 872 } |
867 | 873 |
868 faim_internal int general_modfirst(struct aim_session_t *sess, aim_module_t *mod) | 874 faim_internal int general_modfirst(aim_session_t *sess, aim_module_t *mod) |
869 { | 875 { |
870 | 876 |
871 mod->family = 0x0001; | 877 mod->family = 0x0001; |
872 mod->version = 0x0000; | 878 mod->version = 0x0000; |
873 mod->flags = 0; | 879 mod->flags = 0; |