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