Remove unneeded #include <stdio.h>
[obnox/wireshark/wip.git] / epan / dissectors / packet-msproxy.c
1 /* packet-msproxy.c
2  * Routines for Microsoft Proxy packet dissection
3  * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * This was derived from the dante socks implementation source code.
26  * Most of the information came from common.h and msproxy_clientprotocol.c
27  *
28  * See http://www.inet.no/dante for more information
29  */
30
31 /************************************************************************
32  *                                                                      *
33  *  Notes: These are possible command values. User input is welcome     *
34  *                                                                      *
35  *  Command = 0x040a - Remote host closed connection (maybe ?? )        *
36  *  Command = 0x0411 - Remote host closed connection                    *
37  *  Command = 0x0413 - Local host closed connection or SYN worked       *
38  *                                                                      *
39  ************************************************************************/
40
41
42
43
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif
47
48 #include <string.h>
49 #include <glib.h>
50
51 #include <epan/packet.h>
52 #include <epan/addr_resolv.h>
53 #include <epan/conversation.h>
54 #include <epan/emem.h>
55
56 #include "packet-tcp.h"
57 #include "packet-udp.h"
58
59 extern void udp_hash_add(guint16 proto,
60         void (*dissect)(const guchar *, int, frame_data *, proto_tree *));
61
62
63 static int proto_msproxy = -1;
64
65 static int ett_msproxy = -1;
66 static int ett_msproxy_name = -1;
67
68 static int hf_msproxy_cmd = -1;
69 static int hf_msproxy_clntport = -1;
70
71 static int hf_msproxy_dstaddr = -1;
72
73 static int hf_msproxy_srcport = -1;
74 static int hf_msproxy_dstport = -1;
75 static int hf_msproxy_serverport = -1;
76 static int hf_msproxy_serveraddr = -1;
77 static int hf_msproxy_bindport = -1;
78 static int hf_msproxy_bindaddr = -1;
79 static int hf_msproxy_boundport = -1;
80 static int hf_msproxy_bind_id = -1;
81 static int hf_msproxy_resolvaddr = -1;
82
83 static int hf_msproxy_server_int_addr = -1;
84 static int hf_msproxy_server_int_port = -1;
85 static int hf_msproxy_server_ext_addr = -1;
86 static int hf_msproxy_server_ext_port = -1;
87
88 static dissector_handle_t msproxy_sub_handle;
89
90
91 #define UDP_PORT_MSPROXY 1745
92
93 #define N_MSPROXY_HELLO                 0x05    /* packet 1 from client */
94 #define N_MSPROXY_ACK                   0x10    /* packet 1 from server */
95 #define N_MSPROXY_USERINFO_ACK          0x04    /* packet 2 from server */
96 #define N_MSPROXY_AUTH                  0x47    /* packet 3 from client */
97 #define N_MSPROXY_RESOLVE               0x07    /* Resolve request      */
98
99
100 /*$$$ 0x0500 was dante value, I see 0x05ff and 0x0500 */
101
102 #define MSPROXY_HELLO                   0x0500
103 #define MSPROXY_HELLO_2                 0x05ff
104
105 #define MSPROXY_HELLO_ACK               0x1000
106
107 #define MSPROXY_USERINFO                0x1000
108 #define MSPROXY_USERINFO_ACK            0x0400
109
110 #define MSPROXY_AUTH                    0x4700
111 #define MSPROXY_AUTH_1_ACK              0x4714
112 #define MSPROXY_AUTH_2                  0x4701
113 #define MSPROXY_AUTH_2_ACK              0x4715
114 #define MSPROXY_AUTH_2_ACK2             0x4716
115
116 #define MSPROXY_RESOLVE                 0x070d
117 #define MSPROXY_RESOLVE_ACK             0x070f
118
119 #define MSPROXY_BIND                    0x0704
120 #define MSPROXY_BIND_ACK                0x0706
121
122 #define MSPROXY_TCP_BIND                0x0707
123 #define MSPROXY_TCP_BIND_ACK            0x0708
124
125 #define MSPROXY_LISTEN                  0x0406
126
127 #define MSPROXY_BINDINFO                0x0709
128
129 #define MSPROXY_BINDINFO_ACK            0x070a
130
131 #define MSPROXY_CONNECT                 0x071e
132 #define MSPROXY_CONNECT_ACK             0x0703
133
134 #define MSPROXY_UDPASSOCIATE            0x0705
135 #define MSPROXY_UDPASSOCIATE_ACK        0x0706
136
137 #define MSPROXY_UDP_BIND_REQ            0x070b
138
139 #define MSPROXY_CONNECTED               0x042c
140 #define MSPROXY_SESSIONEND              0x251e
141
142 #define MSPROXY_BIND_AUTHFAILED         0x0804
143 #define MSPROXY_CONNECT_AUTHFAILED      0x081e
144 #define MSPROXY_CONNREFUSED             0x4             /* low 12 bits seem to vary.    */
145
146 #define FROM_SERVER 1                   /* direction of packet data for get_msproxy_cmd_name */
147 #define FROM_CLIENT 0
148
149
150
151
152 /*$$$ should this be the same as redirect_entry_t ?? */
153 /*  then the add_conversation could just copy the structure */
154 /* using the same allocation (instance  for you object guys)    */
155 /* wouldn't work because there may be multiple child conversations */
156 /* from the same MSProxy conversation */
157
158 typedef struct {
159         guint32 dst_addr;
160         guint32 clnt_port;
161         guint32 dst_port;
162         guint32 server_int_port;
163         int     proto;
164 }hash_entry_t;
165
166
167 /************** conversation hash stuff ***************/
168
169 typedef struct {
170         guint32 remote_addr;
171         guint32 clnt_port;
172         guint32 server_int_port;
173         guint32 remote_port;
174         int     proto;
175 }redirect_entry_t;
176
177
178 /************** negotiated conversation hash stuff ***************/
179
180
181 static guint32 last_row= 0;     /* used to see if packet is new */
182
183 static void msproxy_sub_dissector( tvbuff_t *tvb, packet_info *pinfo,
184                 proto_tree *tree) {
185
186 /* Conversation dissector called from TCP or UDP dissector. Decode and  */
187 /* display the msproxy header, the pass the rest of the data to the tcp */
188 /* or udp port decode routine to  handle the payload.                   */
189
190         guint32 *ptr;
191         redirect_entry_t *redirect_info;
192         conversation_t *conversation;
193         proto_tree      *msp_tree;
194         proto_item      *ti;
195
196         conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst,
197                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
198
199         DISSECTOR_ASSERT( conversation);        /* should always find a conversation */
200
201         redirect_info = conversation_get_proto_data(conversation,
202                 proto_msproxy);
203
204         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS Proxy");
205
206         if (check_col(pinfo->cinfo, COL_INFO))
207                 col_set_str(pinfo->cinfo, COL_INFO,
208                         (( redirect_info->proto == PT_TCP) ? "TCP stream" :
209                          "UDP packets"));
210
211         if ( tree) {
212                 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, 0,
213                         FALSE );
214
215                 msp_tree = proto_item_add_subtree(ti, ett_msproxy);
216
217                 proto_tree_add_uint( msp_tree, hf_msproxy_dstport, tvb, 0, 0,
218                         redirect_info->remote_port);
219
220                 proto_tree_add_ipv4( msp_tree, hf_msproxy_dstaddr, tvb, 0, 0,
221                         redirect_info->remote_addr);
222
223         }
224
225 /* set pinfo->{src/dst port} and call the UDP sub-dissector lookup */
226
227         if ( pinfo->srcport == redirect_info->clnt_port)
228                 ptr = &pinfo->destport;
229         else
230                 ptr = &pinfo->srcport;
231
232         *ptr = redirect_info->remote_port;
233
234         if ( redirect_info->proto == PT_TCP)
235                 decode_tcp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
236                         pinfo->destport, NULL);
237         else
238                 decode_udp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
239                         pinfo->destport, -1);
240
241         *ptr = redirect_info->server_int_port;
242 }
243
244
245
246 static void add_msproxy_conversation( packet_info *pinfo,
247         hash_entry_t *hash_info){
248
249 /* check to see if a conversation already exists, if it does assume     */
250 /* it's our conversation and quit. Otherwise create a new conversation. */
251 /* Load the conversation dissector to our  dissector and load the       */
252 /* conversation data structure with the info needed to call the TCP or  */
253 /* UDP port decoder.                                                    */
254
255 /* NOTE: Currently this assume that the conversation will be created    */
256 /*      during a packet from the server.  If that changes, pinfo->src   */
257 /*      and pinfo->dst will not be correct and this routine will have   */
258 /*      to change.                                                      */
259
260         conversation_t *conversation;
261         redirect_entry_t *new_conv_info;
262
263         if (pinfo->fd->flags.visited) {
264                 /*
265                  * We've already processed this frame once, so we
266                  * should already have done this.
267                  */
268                 return;
269         }
270
271         conversation = find_conversation( pinfo->fd->num, &pinfo->src,
272                 &pinfo->dst, hash_info->proto, hash_info->server_int_port,
273                 hash_info->clnt_port, 0);
274
275         if ( !conversation) {
276                 conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst,
277                         hash_info->proto, hash_info->server_int_port,
278                         hash_info->clnt_port, 0);
279         }
280         conversation_set_dissector(conversation, msproxy_sub_handle);
281
282         new_conv_info = se_alloc(sizeof(redirect_entry_t));
283
284         new_conv_info->remote_addr = hash_info->dst_addr;
285         new_conv_info->clnt_port = hash_info->clnt_port;
286         new_conv_info->remote_port = hash_info->dst_port;
287         new_conv_info->server_int_port = hash_info->server_int_port;
288         new_conv_info->proto = hash_info->proto;
289
290         conversation_add_proto_data(conversation, proto_msproxy,
291                 new_conv_info);
292 }
293
294
295
296 static int display_application_name(tvbuff_t *tvb, int offset,
297         proto_tree *tree) {
298
299 /* display the application name in the proto tree.                      */
300
301 /* NOTE: this routine assumes that the tree pointer is valid (not NULL) */
302
303         int length;
304
305         length = tvb_strnlen( tvb, offset, 255);
306         proto_tree_add_text( tree, tvb, offset, length, "Application: %.*s",
307                 length, tvb_get_ptr( tvb, offset, length));
308
309         return length;
310 }
311
312
313 static const char *get_msproxy_cmd_name( int cmd, int direction) {
314
315 /* return the command name string for cmd */
316
317         switch (cmd){
318                 case MSPROXY_HELLO_2:
319                 case MSPROXY_HELLO:             return "Hello";
320
321 /* MSPROXY_HELLO_ACK & MSPROXY_USERINFO have the same value (0x1000).   */
322 /* So use the direction flag to determine which to use.                 */
323
324                 case MSPROXY_USERINFO:
325                         if ( direction == FROM_SERVER)
326                                 return "Hello Acknowledge";
327                         else
328                                 return "User Info";
329                 case MSPROXY_USERINFO_ACK:      return "User Info Acknowledge";
330                 case MSPROXY_AUTH:              return "Authentication";
331                 case MSPROXY_AUTH_1_ACK:        return "Authentication Acknowledge";
332                 case MSPROXY_AUTH_2:            return "Authentication 2";
333                 case MSPROXY_AUTH_2_ACK:        return "Authentication 2 Acknowledge";
334                 case MSPROXY_RESOLVE:           return "Resolve";
335                 case MSPROXY_RESOLVE_ACK:       return "Resolve Acknowledge";
336                 case MSPROXY_BIND:              return "Bind";
337                 case MSPROXY_TCP_BIND:          return "TCP Bind";
338                 case MSPROXY_TCP_BIND_ACK:      return "TCP Bind Acknowledge";
339                 case MSPROXY_LISTEN:            return "Listen";
340                 case MSPROXY_BINDINFO:          return "Bind Info";
341                 case MSPROXY_BINDINFO_ACK:      return "Bind Info Acknowledge";
342                 case MSPROXY_CONNECT:           return "Connect";
343                 case MSPROXY_CONNECT_ACK:       return "Connect Acknowledge";
344                 case MSPROXY_UDPASSOCIATE:      return "UDP Associate";
345                 case MSPROXY_UDP_BIND_REQ:      return "UDP Bind";
346                 case MSPROXY_UDPASSOCIATE_ACK:  return "Bind or Associate Acknowledge";
347                 case MSPROXY_CONNECTED:         return "Connected";
348                 case MSPROXY_SESSIONEND:        return "Session End";
349
350                 default:                        return "Unknown";
351         }
352 }
353
354
355
356 static void dissect_user_info_2(tvbuff_t *tvb, int offset,
357         proto_tree *tree) {
358
359 /* decode the user, application, computer name  */
360
361
362         int length;
363
364         if ( tree) {
365                 length = tvb_strnlen( tvb, offset, 255);
366                 if (length == -1)
367                         return;
368                 proto_tree_add_text( tree, tvb, offset, length + 1,
369                         "User name: %.*s", length,
370                         tvb_get_ptr( tvb, offset, length));
371                 offset += length + 2;
372
373                 length = tvb_strnlen( tvb, offset, 255);
374                 if (length == -1)
375                         return;
376                 proto_tree_add_text( tree, tvb, offset, length + 1,
377                         "Application name: %.*s", length,
378                         tvb_get_ptr( tvb, offset, length));
379                 offset += length + 1;
380
381                 length = tvb_strnlen( tvb, offset, 255);
382                 if (length == -1)
383                         return;
384                 proto_tree_add_text( tree, tvb, offset, length + 1,
385                         "Client computer name: %.*s", length,
386                         tvb_get_ptr( tvb, offset, length));
387         }
388 }
389
390
391
392 static void dissect_msproxy_request_1(tvbuff_t *tvb, int offset,
393         proto_tree *tree) {
394
395 /* decode the request _1 structure  */
396
397
398         offset += 182;
399
400         dissect_user_info_2( tvb, offset, tree);
401
402 }
403
404
405
406 static void dissect_bind(tvbuff_t *tvb, int offset,
407          proto_tree *tree, hash_entry_t *conv_info) {
408
409 /* decode the bind request   */
410
411         offset += 18;
412
413         if ( tree)
414                 proto_tree_add_item( tree, hf_msproxy_bindaddr, tvb, offset, 4,
415                         FALSE);
416         offset += 4;
417
418         if ( tree)
419                 proto_tree_add_item( tree, hf_msproxy_bindport, tvb, offset, 2,
420                          FALSE);
421         offset += 6;
422
423         if ( tree)
424                 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
425                          FALSE);
426         offset += 2;
427
428         conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
429         offset += 6;
430
431         if ( tree){
432                 proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
433                         FALSE);
434
435                 offset += 82;
436                 display_application_name( tvb, offset, tree);
437         }
438 }
439
440
441
442 static void dissect_auth(tvbuff_t *tvb, int offset,
443         proto_tree *tree) {
444
445 /* decode the authorization request  */
446
447         if ( tree) {
448                 offset += 134;
449
450                 proto_tree_add_text( tree, tvb, offset, 7, "NTLMSSP signature: %.7s",
451                         tvb_get_ptr( tvb, offset, 7));
452                 offset += 7;
453         }
454 }
455
456
457
458 static void dissect_tcp_bind(tvbuff_t *tvb, int offset,
459         proto_tree *tree, hash_entry_t *conv_info) {
460
461 /* decode the bind packet. Set the protocol type in the conversation    */
462 /* information so the bind_info can use it to create the payload        */
463 /* dissector.                                                           */
464
465
466         conv_info->proto = PT_TCP;
467
468         if ( tree) {
469                 offset += 6;
470
471                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
472                         FALSE);
473                 offset += 16;
474
475                 proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
476                         FALSE);
477
478                 offset += 96;
479                 display_application_name( tvb, offset, tree);
480         }
481 }
482
483
484 static void dissect_request_connect(tvbuff_t *tvb, int offset,
485         proto_tree *tree, hash_entry_t *conv_info) {
486
487 /* decode the connect request, display  */
488
489         conv_info->proto = PT_TCP;
490
491         offset += 20;
492
493         if ( tree)
494                 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
495                         FALSE);
496
497         conv_info->dst_port = tvb_get_ntohs( tvb, offset);
498         offset += 2;
499
500         if ( tree)
501                 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
502                         FALSE);
503
504         conv_info->dst_addr = tvb_get_ipv4( tvb, offset);
505
506         offset += 12;
507
508         conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
509
510         if ( tree){
511                 proto_tree_add_uint( tree, hf_msproxy_clntport, tvb, offset, 2,
512                         conv_info->clnt_port);
513
514                 offset += 84;
515
516                 display_application_name( tvb, offset, tree);
517         }
518 }
519
520
521 static void dissect_bind_info_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
522
523 /* decode the client bind info ack  */
524
525
526         if ( tree){
527                 offset += 6;
528
529                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
530                         FALSE);
531                 offset += 14;
532
533                 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
534                         FALSE);
535                 offset += 2;
536
537                 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
538                         FALSE);
539                 offset += 12;
540
541                 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
542                         offset, 2, FALSE);
543                 offset += 4;
544
545                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
546                         offset, 2, FALSE);
547                 offset += 2;
548
549                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
550                         offset, 4, FALSE);
551
552                 offset += 78;
553                 display_application_name( tvb, offset, tree);
554         }
555 }
556
557
558 static void dissect_request_resolve(tvbuff_t *tvb, int offset,
559         proto_tree *tree) {
560
561 /* dissect the request resolve structure */
562 /* display a string with a length, characters encoding */
563 /* they are displayed under a tree with the name in Label variable */
564 /* return the length of the string and the length byte */
565
566         proto_tree      *name_tree;
567         proto_item      *ti;
568
569         int length = tvb_get_guint8( tvb, offset);
570
571         if ( tree){
572                 ti = proto_tree_add_text(tree, tvb, offset, length + 1,
573                         "Host Name: %.*s", length,
574                         tvb_get_ptr( tvb, offset + 18, length));
575
576                 name_tree = proto_item_add_subtree(ti, ett_msproxy_name);
577
578                 proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %d",
579                         length);
580
581                 ++offset;
582                 offset += 17;
583
584                 proto_tree_add_text( name_tree, tvb, offset, length, "String: %s",
585                         tvb_get_ptr( tvb, offset, length));
586         }
587 }
588
589
590
591 static void dissect_udp_bind(tvbuff_t *tvb, int offset,
592         proto_tree *tree, hash_entry_t *conv_info) {
593
594 /* Dissect the udp bind request.  Load the protocol id (PT_UDP) and the */
595 /* remote address so bind_info can use it to create conversation        */
596 /* dissector.                                                           */
597
598         conv_info->proto = PT_UDP;
599
600
601         offset += 8;
602
603         if ( tree)
604                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
605                         FALSE);
606         offset += 12;
607
608
609         if ( tree)
610                 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
611                         FALSE);
612         offset += 2;
613
614         if ( tree)
615                 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
616                         FALSE);
617
618         offset += 96;
619
620         if ( tree)
621                 display_application_name( tvb, offset, tree);
622 }
623
624
625 static void dissect_udp_assoc(tvbuff_t *tvb, int offset,
626         proto_tree *tree, hash_entry_t *conv_info) {
627
628 /* dissect the udp associate request. And load client port into         */
629 /* conversation data structure for later.                               */
630
631
632         offset += 28;
633
634         if ( tree)
635                 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
636                         FALSE);
637
638         conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
639
640         offset += 90;
641
642         if ( tree)
643                 display_application_name( tvb, offset, tree);
644 }
645
646
647 static void dissect_msproxy_request(tvbuff_t *tvb,
648         proto_tree *tree, hash_entry_t *conv_info) {
649
650         int offset = 0;
651         int cmd;
652
653         if ( tree) {
654                 proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x",
655                         tvb_get_letohl( tvb, offset));
656                 offset += 4;
657
658                 proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x",
659                         tvb_get_letohl( tvb, offset));
660                 offset += 4;
661
662                 proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%0x",
663                         tvb_get_letohl( tvb, offset));
664                 offset += 4;
665
666                 proto_tree_add_text( tree, tvb, offset, 1, "Server ack: %u",
667                         tvb_get_guint8( tvb, offset));
668                 offset += 4;
669
670                 proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: %u",
671                         tvb_get_guint8( tvb, offset));
672                 offset += 8;
673
674                 proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
675                         tvb_get_ptr( tvb, offset, 4));
676                 offset += 12;
677         }
678         else                    /* no tree */
679                 offset += 36;
680
681         cmd = tvb_get_ntohs( tvb, offset);
682
683         if ( tree)
684                 proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
685                         cmd, "Command: 0x%02x (%s)", cmd,
686                         get_msproxy_cmd_name( cmd, FROM_CLIENT));
687
688         offset += 2;
689
690         switch (cmd){
691                 case MSPROXY_AUTH:
692                         dissect_auth( tvb, offset, tree);
693                         break;
694
695                 case MSPROXY_BIND:
696                         dissect_bind( tvb, offset, tree, conv_info);
697                         break;
698
699                 case MSPROXY_UDP_BIND_REQ:
700                         dissect_udp_bind( tvb, offset, tree, conv_info);
701                         break;
702
703                 case MSPROXY_AUTH_2:    /*$$ this is probably wrong place for this */
704                 case MSPROXY_TCP_BIND:
705                         dissect_tcp_bind( tvb, offset, tree, conv_info);
706                         break;
707
708                 case MSPROXY_RESOLVE:
709                         dissect_request_resolve( tvb, offset, tree);
710                         break;
711
712                 case MSPROXY_CONNECT:
713                 case MSPROXY_LISTEN:
714                         dissect_request_connect( tvb, offset, tree,
715                                 conv_info);
716                         break;
717
718                 case MSPROXY_BINDINFO_ACK:
719                         dissect_bind_info_ack( tvb, offset, tree);
720                         break;
721
722                 case MSPROXY_HELLO:
723                 case MSPROXY_HELLO_2:
724                         dissect_msproxy_request_1( tvb, offset, tree);
725                         break;
726
727                 case  MSPROXY_UDPASSOCIATE:
728                         dissect_udp_assoc( tvb, offset, tree, conv_info);
729                         break;
730                 default:
731                         if ( tree)
732                                 proto_tree_add_text( tree, tvb, offset, 0,
733                                         "Unhandled request command (report this, please)");
734         }
735 }
736
737
738
739 static void dissect_hello_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
740
741 /* decode the hello acknowledge packet  */
742
743         offset += 60;
744
745         if ( tree) {
746                 proto_tree_add_item( tree, hf_msproxy_serverport, tvb, offset, 2,
747                          FALSE);
748                 offset += 2;
749
750                 proto_tree_add_item( tree, hf_msproxy_serveraddr, tvb, offset, 4,
751                         FALSE);
752                 offset += 4;
753         }
754 }
755
756
757
758 /* XXX - implement me */
759 static void dissect_user_info_ack(tvbuff_t *tvb _U_, int offset,
760         proto_tree *tree _U_) {
761
762 /* decode the  response _2 structure  */
763
764         offset += 18;
765
766         offset += 2;
767
768 }
769
770
771
772 static void dissect_udpassociate_ack(tvbuff_t *tvb, int offset,
773         proto_tree *tree) {
774
775         offset += 6;
776
777         if ( tree) {
778                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
779                         FALSE);
780                 offset += 14;
781
782                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
783                         offset, 2, FALSE);
784                 offset += 2;
785
786                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
787                         offset, 4, FALSE);
788
789                 offset += 96;
790                 display_application_name( tvb, offset, tree);
791         }
792 }
793
794
795
796 static void dissect_auth_1_ack(tvbuff_t *tvb, int offset,
797         proto_tree *tree) {
798
799         offset += 134;
800         if ( tree) {
801                 proto_tree_add_text( tree, tvb, offset, 7, "NTLMSSP signature: %.7s",
802                         tvb_get_ptr( tvb, offset, 7));
803                 offset += 48;
804
805                 /* XXX - always 255? */
806                 proto_tree_add_text( tree, tvb, offset, 255, "NT domain: %.255s",
807                         tvb_get_ptr( tvb, offset, 255));
808         }
809 }
810
811
812
813 /* XXX - implement me */
814 static void dissect_msproxy_response_4( tvbuff_t *tvb _U_, int offset,
815         proto_tree *tree _U_) {
816
817 /* decode the response _4 structure  */
818
819         offset += 134;
820 }
821
822
823
824 static void dissect_connect_ack( tvbuff_t *tvb, int offset, packet_info *pinfo,
825         proto_tree *tree, hash_entry_t *conv_info) {
826
827 /* decode the connect ack packet  */
828         offset += 20;
829
830         if ( tree)
831                 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
832                         offset, 2, FALSE);
833
834
835         conv_info->proto = PT_TCP;
836         conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
837         offset += 2;
838
839         if ( tree){
840                 proto_tree_add_item( tree, hf_msproxy_server_int_addr, tvb,
841                         offset, 4, FALSE);
842                 offset += 14;
843
844                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
845                         offset, 2, FALSE);
846                 offset += 2;
847
848                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
849                         offset, 4, FALSE);
850                 offset += 80;
851
852                 display_application_name( tvb, offset, tree);
853         }
854
855         add_msproxy_conversation( pinfo, conv_info);
856 }
857
858
859
860 static void dissect_tcp_bind_ack( tvbuff_t *tvb, int offset, proto_tree *tree) {
861
862 /* decode the tcp bind */
863
864         if ( tree) {
865                 offset += 6;
866
867                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
868                         FALSE);
869                 offset += 16;
870
871                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
872                         offset, 2, FALSE);
873                 offset += 6;
874
875                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
876                         offset, 2, FALSE);
877                 offset += 2;
878
879                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
880                         offset, 4, FALSE);
881
882                 offset += 88;
883
884                 display_application_name( tvb, offset, tree);
885         }
886 }
887
888
889
890 static void dissect_bind_info( tvbuff_t *tvb, int offset, packet_info *pinfo,
891         proto_tree *tree, hash_entry_t *conv_info) {
892
893 /* decode the Bind info response from server */
894
895         offset += 6;
896
897         if ( tree)
898                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
899                         FALSE);
900         offset += 14;
901
902
903         conv_info->dst_port = tvb_get_ntohs( tvb, offset);
904         if ( tree)
905                 proto_tree_add_uint( tree, hf_msproxy_dstport, tvb, offset, 2,
906                         conv_info->dst_port);
907         offset += 2;
908
909         conv_info->dst_addr = tvb_get_ipv4( tvb, offset);
910         if ( tree)
911                 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
912                         FALSE);
913         offset += 12;
914
915         conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
916         if ( tree)
917                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
918                         offset, 2, conv_info->server_int_port);
919         offset += 4;
920
921         if ( tree) {
922                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
923                         offset, 2, FALSE);
924                 offset += 2;
925
926                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
927                         offset, 4, FALSE);
928
929                 offset += 78;
930                 display_application_name( tvb, offset, tree);
931
932         }
933
934         add_msproxy_conversation( pinfo, conv_info);
935 }
936
937
938
939 static void dissect_resolve(tvbuff_t *tvb, int offset, proto_tree *tree) {
940
941 /* dissect the  response resolve structure */
942 /* display a string with a length, characters encoding */
943 /* they are displayed under a tree with the name in Label variable */
944 /* return the length of the string and the length byte */
945
946         if ( tree) {
947                 int addr_offset;
948
949                 addr_offset = tvb_get_guint8( tvb, offset);
950
951                 proto_tree_add_text( tree, tvb, offset, 1, "Address offset: %d",
952                         addr_offset);
953
954                 ++offset;
955
956                 offset += 13;
957
958                 offset += addr_offset;
959
960                 proto_tree_add_item( tree, hf_msproxy_resolvaddr, tvb, offset, 4,
961                         FALSE);
962         }
963 }
964
965
966
967 static void dissect_msproxy_response(tvbuff_t *tvb, packet_info *pinfo,
968                 proto_tree *tree, hash_entry_t *conv_info) {
969
970         int offset = 0;
971         int cmd;
972
973         if ( tree) {
974                 proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x",
975                         tvb_get_letohl( tvb, offset));
976                 offset += 4;
977
978                 proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x",
979                         tvb_get_letohl( tvb, offset));
980                 offset += 4;
981
982                 proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%04x",
983                         tvb_get_letohl( tvb, offset));
984                 offset += 4;
985
986                 proto_tree_add_text( tree, tvb, offset, 1, "Client ack: 0x%02x",
987                         tvb_get_guint8( tvb, offset));
988                 offset += 4;
989
990                 proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: 0x%02x",
991                         tvb_get_guint8( tvb, offset));
992
993                 offset += 8;
994
995                 proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
996                         tvb_get_ptr( tvb, offset, 4));
997
998                 offset += 12;
999         }
1000         else
1001                 offset += 36;
1002
1003         cmd = tvb_get_ntohs( tvb, offset);
1004
1005         if ( tree)
1006                 proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
1007                         cmd, "Command: 0x%02x (%s)", cmd,
1008                         get_msproxy_cmd_name( cmd, FROM_SERVER));
1009         offset += 2;
1010
1011         switch (cmd) {
1012                 case MSPROXY_HELLO_ACK:
1013                         dissect_hello_ack( tvb, offset, tree);
1014                         break;
1015
1016                 case MSPROXY_USERINFO_ACK:
1017                         dissect_user_info_ack( tvb, offset, tree);
1018                         break;
1019
1020                 case MSPROXY_AUTH_1_ACK:
1021                         dissect_auth_1_ack( tvb, offset, tree);
1022                         break;
1023
1024 /* this also handle the MSPROXY_BIND_ACK ??? check this */
1025
1026                 case MSPROXY_UDPASSOCIATE_ACK:
1027                         dissect_udpassociate_ack( tvb, offset, tree);
1028                         break;
1029
1030                 case MSPROXY_AUTH_2_ACK:
1031                 case MSPROXY_AUTH_2_ACK2:
1032                         dissect_msproxy_response_4( tvb, offset, tree);
1033                         break;
1034
1035                 case MSPROXY_TCP_BIND_ACK:
1036                         dissect_tcp_bind_ack( tvb, offset, tree);
1037                         break;
1038
1039                 case MSPROXY_CONNECT_ACK:
1040                         dissect_connect_ack( tvb, offset, pinfo, tree,
1041                                 conv_info);
1042                         break;
1043
1044                 case MSPROXY_BINDINFO:
1045                         dissect_bind_info( tvb, offset, pinfo, tree, conv_info);
1046                         break;
1047
1048                 case MSPROXY_RESOLVE_ACK:
1049                         dissect_resolve( tvb, offset, tree);
1050                         break;
1051
1052                 case MSPROXY_CONNECT_AUTHFAILED:
1053                 case MSPROXY_BIND_AUTHFAILED:
1054                         proto_tree_add_text( tree, tvb, offset, 0, "No know information (help wanted)");
1055                         break;
1056
1057                 default:
1058
1059                         if (tree &&
1060                            (((cmd >> 8) ==  MSPROXY_CONNREFUSED) ||
1061                             ((cmd >> 12) ==  MSPROXY_CONNREFUSED)))
1062                                 proto_tree_add_text( tree, tvb, offset, 0,
1063                                         "No know information (help wanted)");
1064
1065                         else if ( tree)
1066                                 proto_tree_add_text( tree, tvb, offset, 0,
1067                                         "Unhandled response command (report this, please)");
1068         }
1069
1070
1071 }
1072
1073
1074
1075 static void dissect_msproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1076
1077
1078         proto_tree      *msproxy_tree = NULL;
1079         proto_item      *ti;
1080         unsigned int    cmd;
1081
1082
1083         hash_entry_t *hash_info;
1084         conversation_t *conversation;
1085
1086         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSproxy");
1087         col_clear(pinfo->cinfo, COL_INFO);
1088
1089         conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst,
1090                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1091
1092         if ( !conversation) {
1093                 conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst,
1094                         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1095         }
1096         hash_info = conversation_get_proto_data(conversation, proto_msproxy);
1097         if ( !hash_info) {
1098                 hash_info = se_alloc(sizeof(hash_entry_t));
1099                 conversation_add_proto_data(conversation, proto_msproxy,
1100                         hash_info);
1101         }
1102
1103         if (check_col(pinfo->cinfo, COL_INFO)){
1104
1105                 cmd = tvb_get_ntohs( tvb, 36);
1106
1107                 if ( pinfo->srcport == UDP_PORT_MSPROXY)
1108                         col_add_fstr( pinfo->cinfo, COL_INFO, "Server message: %s",
1109                                 get_msproxy_cmd_name( cmd, FROM_SERVER));
1110                 else
1111                         col_add_fstr(pinfo->cinfo, COL_INFO, "Client message: %s",
1112                                 get_msproxy_cmd_name( cmd, FROM_CLIENT));
1113
1114         }
1115
1116         if (tree) {                             /* if proto tree, decode data */
1117                 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, -1,
1118                                 FALSE );
1119
1120                 msproxy_tree = proto_item_add_subtree(ti, ett_msproxy);
1121         }
1122
1123         if ( pinfo->srcport == UDP_PORT_MSPROXY)
1124                 dissect_msproxy_response( tvb, pinfo, msproxy_tree, hash_info);
1125         else
1126                 dissect_msproxy_request( tvb, msproxy_tree, hash_info);
1127 }
1128
1129
1130
1131 static void msproxy_reinit( void){
1132
1133 /* Do the cleanup work when a new pass through the packet list is       */
1134 /* performed. Reset the highest row seen counter                        */
1135
1136         last_row = 0;
1137 }
1138
1139
1140
1141 void
1142 proto_register_msproxy( void){
1143
1144 /* Prep the msproxy protocol, for now, just register it */
1145
1146         static gint *ett[] = {
1147                 &ett_msproxy,
1148                 &ett_msproxy_name
1149         };
1150         static hf_register_info hf[] = {
1151
1152                 { &hf_msproxy_cmd,
1153                         { "Command", "msproxy.command", FT_UINT16, BASE_DEC,
1154                                  NULL, 0x0, NULL, HFILL
1155                         }
1156                 },
1157
1158                 { &hf_msproxy_dstaddr,
1159                         { "Destination Address", "msproxy.dstaddr", FT_IPv4, BASE_NONE, NULL,
1160                                 0x0, NULL, HFILL
1161                         }
1162                 },
1163
1164                 { &hf_msproxy_srcport,
1165                         { "Source Port", "msproxy.srcport", FT_UINT16,
1166                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1167                         }
1168                 },
1169                 { &hf_msproxy_dstport,
1170                         { "Destination Port", "msproxy.dstport", FT_UINT16,
1171                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1172                         }
1173                 },
1174                 { &hf_msproxy_clntport,
1175                         { "Client Port",        "msproxy.clntport", FT_UINT16,
1176                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1177                         }
1178                 },
1179                 { &hf_msproxy_server_ext_addr,
1180                         { "Server External Address", "msproxy.server_ext_addr", FT_IPv4, BASE_NONE, NULL,
1181                                 0x0, NULL, HFILL
1182                         }
1183                 },
1184
1185                 { &hf_msproxy_server_ext_port,
1186                         { "Server External Port",       "msproxy.server_ext_port", FT_UINT16,
1187                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1188                         }
1189                 },
1190
1191                 { &hf_msproxy_server_int_addr,
1192                         { "Server Internal Address", "msproxy.server_int_addr", FT_IPv4, BASE_NONE, NULL,
1193                                 0x0, NULL, HFILL
1194                         }
1195                 },
1196
1197                 { &hf_msproxy_server_int_port,
1198                         { "Server Internal Port",       "msproxy.server_int_port", FT_UINT16,
1199                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1200                         }
1201                 },
1202                 { &hf_msproxy_serverport,
1203                         { "Server Port",        "msproxy.serverport", FT_UINT16,
1204                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1205                         }
1206                 },
1207                 { &hf_msproxy_bindport,
1208                         { "Bind Port",  "msproxy.bindport", FT_UINT16,
1209                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1210                         }
1211                 },
1212                 { &hf_msproxy_boundport,
1213                         { "Bound Port", "msproxy.boundport", FT_UINT16,
1214                                 BASE_DEC, NULL, 0x0, NULL, HFILL
1215                         }
1216                 },
1217                 { &hf_msproxy_serveraddr,
1218                         { "Server Address", "msproxy.serveraddr", FT_IPv4, BASE_NONE, NULL,
1219                                 0x0, NULL, HFILL
1220                         }
1221                 },
1222                 { &hf_msproxy_bindaddr,
1223                         { "Destination", "msproxy.bindaddr", FT_IPv4, BASE_NONE, NULL,
1224                                 0x0, NULL, HFILL
1225                         }
1226                 },
1227                 { &hf_msproxy_bind_id,
1228                         { "Bound Port Id",      "msproxy.bindid", FT_UINT32,
1229                                 BASE_HEX, NULL, 0x0, NULL, HFILL
1230                         }
1231                 },
1232                 { &hf_msproxy_resolvaddr,
1233                         { "Address", "msproxy.resolvaddr", FT_IPv4, BASE_NONE, NULL,
1234                                 0x0, NULL, HFILL
1235                         }
1236                 }
1237
1238         };
1239
1240         proto_msproxy = proto_register_protocol( "MS Proxy Protocol",
1241             "MS Proxy", "msproxy");
1242
1243         proto_register_field_array(proto_msproxy, hf, array_length(hf));
1244         proto_register_subtree_array(ett, array_length(ett));
1245
1246         register_init_routine( &msproxy_reinit);        /* register re-init routine */
1247
1248         msproxy_sub_handle = create_dissector_handle(msproxy_sub_dissector,
1249             proto_msproxy);
1250 }
1251
1252
1253 void
1254 proto_reg_handoff_msproxy(void) {
1255
1256         /* dissector install routine */
1257
1258         dissector_handle_t msproxy_handle;
1259
1260         msproxy_handle = create_dissector_handle(dissect_msproxy,
1261             proto_msproxy);
1262         dissector_add("udp.port", UDP_PORT_MSPROXY, msproxy_handle);
1263 }