1 /* Copyright (c) 2007 by Errata Security */
\r
4 #include "netframe.h"
\r
11 FROM SERVER commands
\r
13 Response from a PNG (ping) command that says how many seconds remain
\r
14 before the server expects another ping.
\r
19 This example is a response to a ping where the server acknowledges the ping,
\r
20 and indicates that it wants another ping within 42 seconds.
\r
24 /* FROM CLIENT commands
\r
27 The client notifies the server of which protocol it is using.
\r
29 The major versions are MSNP8, MSNP9, and MSNP10
\r
36 This command sends a message
\r
39 #define CMD(str) ( (str[0]<<24) | (str[1]<<16) | (str[2]<<8) | (str[3]<<0) )
\r
41 static void skip_whitespace(const unsigned char *px, unsigned length, unsigned *r_offset)
\r
43 while (*r_offset < length && px[*r_offset] != '\n' && isspace(px[*r_offset]))
\r
46 static unsigned get_parm(const unsigned char *px, unsigned length, unsigned *r_offset)
\r
49 while ((*r_offset) < length && px[*r_offset] != '\n' && !isspace(px[*r_offset])) {
\r
53 skip_whitespace(px, length, r_offset);
\r
56 static unsigned is_number(const unsigned char *px, unsigned length)
\r
59 for (i=0; i<length; i++)
\r
60 if (!isdigit(px[i]))
\r
66 static unsigned equals(const unsigned char *px, unsigned length, const char *sz)
\r
70 for (i=0; i<length && sz[i]; i++)
\r
73 if (i != length || sz[i] != '\0')
\r
77 void process_simple_msnms_server_response(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
\r
80 unsigned char cmd[16] = "";
\r
84 /*Find out length of the command line */
\r
85 for (eol=0; eol<length && px[eol] != '\n'; eol++)
\r
88 skip_whitespace(px, length, &offset);
\r
92 while (offset < length && px[offset] != '\n' && !isspace(px[offset])) {
\r
93 if (i<sizeof(cmd)-1) {
\r
94 cmd[i++] = px[offset];
\r
99 skip_whitespace(px, length, &offset);
\r
101 SAMPLE("MSN-MSGR", "command", REC_SZ, cmd, -1);
\r
103 switch (CMD(cmd)) {
\r
104 case 0x56455200: /* "VER" */
\r
105 while (offset < eol) {
\r
106 unsigned parm = offset;
\r
107 unsigned parm_length = get_parm(px, length, &offset);
\r
109 if (is_number(px+parm, parm_length))
\r
112 if (equals(px+parm, parm_length, "CVR0"))
\r
117 * VER <TrID> <protocol> <protocol> ....
\r
119 * Indicates a list of protocols supported
\r
123 * VER 0 MSNP8 MYPROTOCOL CVR0
\r
125 process_record(seap,
\r
126 "ID-IP", REC_FRAMESRC, frame, -1,
\r
127 "app", REC_SZ, "MSN-MSGR", -1,
\r
128 "ver", REC_PRINTABLE, px+parm, parm_length,
\r
133 case 0x4e4c4e00: /* "NLN" */
\r
135 unsigned state, state_length;
\r
136 unsigned handle, handle_length;
\r
137 unsigned friendly, friendly_length;
\r
140 state_length = get_parm(px, length, &offset);
\r
143 handle_length = get_parm(px, length, &offset);
\r
146 friendly_length = get_parm(px, length, &offset);
\r
148 process_record(seap,
\r
149 "proto", REC_SZ, "MSN-MSGR", -1,
\r
150 "ip", REC_FRAMEDST, frame, -1,
\r
151 "friend", REC_PRINTABLE, px+handle, handle_length,
\r
152 "name", REC_PRINTABLE, px+friendly, friendly_length,
\r
153 "state", REC_PRINTABLE, px+state, state_length,
\r
157 case 0x514e4700: /* "QNG" */
\r
158 process_record(seap,
\r
159 "proto", REC_SZ, "MSN-MSGR", -1,
\r
160 "ip", REC_FRAMEDST, frame, -1,
\r
163 case 0x43565200: /* "CVR" */
\r
165 case 0x55535200: /* "USR" */
\r
167 case 0x4d534700: /* "MSG" */
\r
168 case 0x58465200: /* "XFR" */
\r
170 FRAMERR(frame, "msn-ms: unknown commanded from client: %.*s\n", length, px);
\r
176 void process_simple_msnms_client_request(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
\r
179 unsigned char cmd[16] = "";
\r
183 /*Find out length of the command line */
\r
184 for (eol=0; eol<length && px[eol] != '\n'; eol++)
\r
187 skip_whitespace(px, length, &offset);
\r
191 while (offset < length && px[offset] != '\n' && !isspace(px[offset])) {
\r
192 if (i<sizeof(cmd)-1) {
\r
193 cmd[i++] = px[offset];
\r
198 skip_whitespace(px, length, &offset);
\r
200 SAMPLE("MSN-MSGR", "command", REC_SZ, cmd, -1);
\r
202 switch (CMD(cmd)) {
\r
203 case 0x56455200: /* "VER" */
\r
204 while (offset < eol) {
\r
205 unsigned parm = offset;
\r
206 unsigned parm_length = get_parm(px, length, &offset);
\r
208 if (is_number(px+parm, parm_length))
\r
211 if (equals(px+parm, parm_length, "CVR0"))
\r
216 * VER <TrID> <protocol> <protocol> ....
\r
218 * Indicates a list of protocols supported
\r
222 * VER 0 MSNP8 MYPROTOCOL CVR0
\r
224 process_record(seap,
\r
225 "ID-IP", REC_FRAMESRC, frame, -1,
\r
226 "app", REC_SZ, "MSN-MSGR", -1,
\r
227 "ver", REC_PRINTABLE, px+parm, parm_length,
\r
232 case 0x4e4c4e00: /* "NLN" */
\r
234 case 0x514e4700: /* "QNG" */
\r
236 case 0x43565200: /* "CVR" */
\r
238 * The first parameter is hexadecimal number specifying your locale ID (e.g. "0x0409" For U.S. English).
\r
239 * The second parameter is your OS type (e.g. "win" for Windows).
\r
240 * The third parameter is your OS version (e.g. "4.10" for Windows 98).
\r
241 * The fourth parameter is the architecture of your computer (e.g. "i386" for Intel-comaptible PCs of type 386 or above).
\r
242 * The fifth parameter is your client name (e.g. "MSMSGR" for the official MSN Messenger client).
\r
243 * The sixth parameter is your client version (e.g. "6.0.0602").
\r
244 * The seventh parameter is always "MSMSGS" in the official client. Your guess about what this means is as good as mine.
\r
245 * The eighth parameter is your passport.
\r
248 unsigned trid, trid_length;
\r
249 unsigned localid, localid_length;
\r
250 unsigned ostype, ostype_length;
\r
251 unsigned osver, osver_length;
\r
252 unsigned arch, arch_length;
\r
253 unsigned clientname, clientname_length;
\r
254 unsigned clientver, clientver_length;
\r
255 unsigned msmsgs, msmsgs_length;
\r
256 unsigned passport, passport_length;
\r
259 trid_length = get_parm(px, length, &offset);
\r
262 localid_length = get_parm(px, length, &offset);
\r
265 ostype_length = get_parm(px, length, &offset);
\r
268 osver_length = get_parm(px, length, &offset);
\r
271 arch_length = get_parm(px, length, &offset);
\r
274 clientname_length = get_parm(px, length, &offset);
\r
277 clientver_length = get_parm(px, length, &offset);
\r
280 msmsgs_length = get_parm(px, length, &offset);
\r
283 passport_length = get_parm(px, length, &offset);
\r
285 process_record(seap,
\r
286 "ID-IP", REC_FRAMESRC, frame, -1,
\r
287 "Passport", REC_PRINTABLE, px+passport, passport_length,
\r
290 process_record(seap,
\r
291 "proto", REC_SZ, "MSN-MSGR", -1,
\r
292 "ip", REC_FRAMESRC, frame, -1,
\r
293 "localid", REC_PRINTABLE, px+localid, localid_length,
\r
295 process_record(seap,
\r
296 "proto", REC_SZ, "MSN-MSGR", -1,
\r
297 "ip", REC_FRAMESRC, frame, -1,
\r
298 "ostype", REC_PRINTABLE, px+ostype, ostype_length,
\r
300 process_record(seap,
\r
301 "proto", REC_SZ, "MSN-MSGR", -1,
\r
302 "ip", REC_FRAMESRC, frame, -1,
\r
303 "osver", REC_PRINTABLE , px+osver, osver_length,
\r
305 process_record(seap,
\r
306 "proto", REC_SZ, "MSN-MSGR", -1,
\r
307 "ip", REC_FRAMESRC, frame, -1,
\r
308 "arch", REC_PRINTABLE , px+arch, arch_length,
\r
310 process_record(seap,
\r
311 "proto", REC_SZ, "MSN-MSGR", -1,
\r
312 "ip", REC_FRAMESRC, frame, -1,
\r
313 "clientname", REC_PRINTABLE, px+clientname, clientname_length,
\r
315 process_record(seap,
\r
316 "proto", REC_SZ, "MSN-MSGR", -1,
\r
317 "ip", REC_FRAMESRC, frame, -1,
\r
318 "clientver",REC_PRINTABLE, px+clientver, clientver_length,
\r
320 process_record(seap,
\r
321 "proto", REC_SZ, "MSN-MSGR", -1,
\r
322 "ip", REC_FRAMESRC, frame, -1,
\r
323 "msmsgs", REC_PRINTABLE, px+msmsgs, msmsgs_length,
\r
325 process_record(seap,
\r
326 "proto", REC_SZ, "MSN-MSGR", -1,
\r
327 "ip", REC_FRAMESRC, frame, -1,
\r
328 "passport", REC_PRINTABLE, px+passport, passport_length,
\r
333 case 0x55535200: /* "USR" */
\r
334 /*After receiving the response to CVR, you must send the USR command. It has a TrID.
\r
335 * The first parameter is the authentication system (always TWN).
\r
336 * The second parameter is always the letter I (standing for initiating authentication).
\r
337 * The third parameter is the account name that you want to log on with.
\r
340 unsigned trid, trid_length;
\r
341 unsigned twn, twn_length;
\r
342 unsigned ii, ii_length;
\r
343 unsigned username, username_length;
\r
346 trid_length = get_parm(px, length, &offset);
\r
349 twn_length = get_parm(px, length, &offset);
\r
352 ii_length = get_parm(px, length, &offset);
\r
355 username_length = get_parm(px, length, &offset);
\r
357 process_record(seap,
\r
358 "proto", REC_SZ, "MSN-MSGR", -1,
\r
359 "ip", REC_FRAMESRC, frame, -1,
\r
360 "username", REC_PRINTABLE, px+username, username_length,
\r
362 process_record(seap,
\r
363 "ID-IP", REC_FRAMESRC, frame, -1,
\r
364 "MSN-username", REC_PRINTABLE, px+username, username_length,
\r
368 case 0x4d534700: /* "MSG" */
\r
369 case 0x58465200: /* "XFR" */
\r
371 FRAMERR(frame, "msn-ms: unknown commanded from client: %.*s\n", length, px);
\r