On Windows, put Ethereal configuration files under the "Application
[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.22 2001/09/03 10:33:05 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  *
26  * This was derived from the dante socks implementation source code. 
27  * Most of the information came from common.h and msproxy_clientprotocol.c
28  *
29  * See http://www.inet.no/dante for more information 
30  *
31  */
32
33 /************************************************************************
34  *                                                                      *
35  *  Notes: These are possible command values. User input is welcome     *
36  *                                                                      *
37  *  Command = 0x040a - Remote host closed connection (maybe ?? )        *
38  *  Command = 0x0411 - Remote host closed connection                    *
39  *  Command = 0x0413 - Local host closed connection or SYN worked       *
40  *                                                                      *
41  ************************************************************************/
42
43
44
45
46 #ifdef HAVE_CONFIG_H
47 # include "config.h"
48 #endif
49
50 #ifdef HAVE_SYS_TYPES_H
51 # include <sys/types.h>
52 #endif
53
54 #ifdef HAVE_NETINET_IN_H
55 # include <netinet/in.h>
56 #endif
57
58 #include <stdio.h>
59 #include <string.h>
60 #include <glib.h>
61
62 #ifdef NEED_SNPRINTF_H
63 # include "snprintf.h"
64 #endif
65
66 #include "packet.h"
67 #include "resolv.h"
68 #include "alignment.h"
69 #include "conversation.h"
70
71 #include "packet-tcp.h"
72 #include "packet-udp.h"
73
74 extern void udp_hash_add(guint16 proto,
75         void (*dissect)(const u_char *, int, frame_data *, proto_tree *));
76
77
78 static int proto_msproxy = -1;
79
80 static int ett_msproxy = -1;
81 static int ett_msproxy_name = -1;
82
83 static int hf_msproxy_cmd = -1;
84 static int hf_msproxy_clntport = -1;
85
86 static int hf_msproxy_dstaddr = -1;
87
88 static int hf_msproxy_srcport = -1;
89 static int hf_msproxy_dstport = -1;
90 static int hf_msproxy_serverport = -1;
91 static int hf_msproxy_serveraddr = -1;
92 static int hf_msproxy_bindport = -1;
93 static int hf_msproxy_bindaddr = -1;
94 static int hf_msproxy_boundport = -1;
95 static int hf_msproxy_bind_id = -1;
96 static int hf_msproxy_resolvaddr = -1;
97
98 static int hf_msproxy_server_int_addr = -1;
99 static int hf_msproxy_server_int_port = -1;
100 static int hf_msproxy_server_ext_addr = -1;
101 static int hf_msproxy_server_ext_port = -1;
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 socks 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->fd, COL_PROTOCOL))
228                 col_set_str(pinfo->fd, COL_PROTOCOL, "MS Proxy");
229
230         if (check_col(pinfo->fd, COL_INFO))
231                 col_set_str(pinfo->fd, 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_dissector);
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         packet_info *pinfo, 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, packet_info *pinfo,
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         packet_info *pinfo, proto_tree *tree) {
418
419 /* decode the request _1 structure  */
420
421
422         offset += 182;
423
424         dissect_user_info_2( tvb, offset, pinfo, tree);
425
426 }
427
428
429
430 static void dissect_bind(tvbuff_t *tvb, int offset, packet_info *pinfo,
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, pinfo, tree);
461         }
462 }
463
464
465
466 static void dissect_auth(tvbuff_t *tvb, int offset,
467         packet_info *pinfo, 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         packet_info *pinfo, 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, pinfo, tree);
504         }
505 }
506
507
508 static void dissect_request_connect(tvbuff_t *tvb, int offset,
509         packet_info *pinfo, 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, pinfo, tree);
541         }
542 }
543
544
545 static void dissect_bind_info_ack(tvbuff_t *tvb, int offset, packet_info *pinfo,
546         proto_tree *tree, hash_entry_t *conv_info) {
547
548 /* decode the client bind info ack  */
549
550
551         if ( tree){
552                 offset += 6;
553
554                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
555                         FALSE);
556                 offset += 14;
557
558                 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
559                         FALSE);
560                 offset += 2;
561
562                 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
563                         FALSE);
564                 offset += 12;
565
566                 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
567                         offset, 2, FALSE);
568                 offset += 4;
569
570                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
571                         offset, 2, FALSE);
572                 offset += 2;
573
574                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
575                         offset, 4, FALSE);
576
577                 offset += 78;
578                 display_application_name( tvb, offset, pinfo, tree);
579         }
580 }
581
582
583 static void dissect_request_resolve(tvbuff_t *tvb, int offset,
584         packet_info *pinfo, proto_tree *tree) {
585
586 /* dissect the request resolve structure */
587 /* display a string with a length, characters encoding */
588 /* they are displayed under a tree with the name in Label variable */
589 /* return the length of the string and the length byte */
590
591         proto_tree      *name_tree;
592         proto_item      *ti;
593
594         int length = tvb_get_guint8( tvb, offset);
595
596         if ( tree){
597                 ti = proto_tree_add_text(tree, tvb, offset, length + 1,
598                         "Host Name: %.*s", length,
599                         tvb_get_ptr( tvb, offset + 18, length));
600
601                 name_tree = proto_item_add_subtree(ti, ett_msproxy_name);
602
603                 proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %d",
604                         length);
605
606                 ++offset;
607                 offset += 17;
608
609                 proto_tree_add_text( name_tree, tvb, offset, length, "String: %s",
610                         tvb_get_ptr( tvb, offset, length));
611         }
612 }       
613
614
615
616 static void dissect_udp_bind(tvbuff_t *tvb, int offset,
617         packet_info *pinfo, proto_tree *tree, hash_entry_t *conv_info) {
618
619 /* Dissect the udp bind request.  Load the protocol id (PT_UDP) and the */
620 /* remote address so bind_info can use it to create conversation        */
621 /* dissector.                                                           */
622
623         conv_info->proto = PT_UDP;
624
625
626         offset += 8;
627
628         if ( tree)
629                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
630                         FALSE);
631         offset += 12;
632
633
634         if ( tree)
635                 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
636                         FALSE);
637         offset += 2;
638
639         if ( tree) 
640                 proto_tree_add_ipv4( tree, hf_msproxy_dstaddr, tvb, offset, 4,
641                         FALSE);
642
643         offset += 96;
644         
645         if ( tree)
646                 display_application_name( tvb, offset, pinfo, tree);
647 }       
648  
649
650 static void dissect_udp_assoc(tvbuff_t *tvb, int offset,
651         packet_info *pinfo, proto_tree *tree, hash_entry_t *conv_info) {
652
653 /* dissect the udp associate request. And load client port into         */
654 /* conversation data structure for later.                               */
655
656
657         offset += 28;
658
659         if ( tree) 
660                 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
661                         FALSE);
662
663         conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
664
665         offset += 90;
666
667         if ( tree) 
668                 display_application_name( tvb, offset, pinfo, tree);
669 }       
670  
671
672 static void dissect_msproxy_request(tvbuff_t *tvb, packet_info *pinfo,
673         proto_tree *tree, hash_entry_t *conv_info) {
674
675         int offset = 0;
676         int cmd;
677
678         if ( tree) {
679                 proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x", 
680                         tvb_get_letohl( tvb, offset));
681                 offset += 4;
682         
683                 proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x", 
684                         tvb_get_letohl( tvb, offset));
685                 offset += 4;
686
687                 proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%0x", 
688                         tvb_get_letohl( tvb, offset));
689                 offset += 4;
690
691                 proto_tree_add_text( tree, tvb, offset, 1, "Server ack: %u", 
692                         tvb_get_guint8( tvb, offset));
693                 offset += 4;
694
695                 proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: %u", 
696                         tvb_get_guint8( tvb, offset));
697                 offset += 8;
698
699                 proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
700                         tvb_get_ptr( tvb, offset, 4));
701                 offset += 12;
702         } 
703         else                    /* no tree */
704                 offset += 36;
705
706         cmd = tvb_get_ntohs( tvb, offset);
707
708         if ( tree)
709                 proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
710                         cmd, "Command: 0x%02x (%s)", cmd, 
711                         get_msproxy_cmd_name( cmd, FROM_CLIENT));
712
713         offset += 2;
714
715         switch (cmd){ 
716                 case MSPROXY_AUTH:
717                         dissect_auth( tvb, offset, pinfo, tree);
718                         break;
719                         
720                 case MSPROXY_BIND:
721                         dissect_bind( tvb, offset, pinfo, tree, conv_info);
722                         break;
723
724                 case MSPROXY_UDP_BIND_REQ:
725                         dissect_udp_bind( tvb, offset, pinfo, tree, conv_info);
726                         break;
727         
728                 case MSPROXY_AUTH_2:    /*$$ this is probably wrong place for this */
729                 case MSPROXY_TCP_BIND:
730                         dissect_tcp_bind( tvb, offset, pinfo, tree, conv_info);
731                         break;
732         
733                 case MSPROXY_RESOLVE:
734                         dissect_request_resolve( tvb, offset, pinfo, tree);
735                         break;
736         
737                 case MSPROXY_CONNECT:
738                 case MSPROXY_LISTEN:
739                         dissect_request_connect( tvb, offset, pinfo, tree,
740                                 conv_info);
741                         break;
742         
743                 case MSPROXY_BINDINFO_ACK:
744                         dissect_bind_info_ack( tvb, offset, pinfo, tree,
745                                 conv_info);
746                         break;
747
748                 case MSPROXY_HELLO:
749                 case MSPROXY_HELLO_2:
750                         dissect_msproxy_request_1( tvb, offset, pinfo, tree);
751                         break;
752
753                 case  MSPROXY_UDPASSOCIATE:
754                         dissect_udp_assoc( tvb, offset, pinfo, tree, conv_info);
755                         break;
756                 default:
757                         if ( tree)
758                                 proto_tree_add_text( tree, tvb, offset, 0,
759                                         "Unhandled request command (report this, please)");
760         }
761 }
762
763
764
765 static void dissect_hello_ack(tvbuff_t *tvb, int offset, packet_info *pinfo,
766         proto_tree *tree, hash_entry_t *conv_info) {
767
768 /* decode the hello acknowledge packet  */
769
770         offset += 60;
771
772         if ( tree) {
773                 proto_tree_add_item( tree, hf_msproxy_serverport, tvb, offset, 2,
774                          FALSE);
775                 offset += 2;
776         
777                 proto_tree_add_item( tree, hf_msproxy_serveraddr, tvb, offset, 4,
778                         FALSE);
779                 offset += 4;
780         }
781 }
782
783
784
785 static void dissect_user_info_ack(tvbuff_t *tvb, int offset,
786         packet_info *pinfo, proto_tree *tree) {
787
788 /* decode the  response _2 structure  */
789
790         offset += 18;
791
792         offset += 2;
793
794 }
795
796
797
798 static void dissect_udpassociate_ack(tvbuff_t *tvb, int offset, 
799         packet_info *pinfo, proto_tree *tree) {
800
801         offset += 6;
802
803         if ( tree) {
804                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
805                         FALSE);
806                 offset += 14;
807
808                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
809                         offset, 2, FALSE);
810                 offset += 2;
811
812                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
813                         offset, 4, FALSE);
814
815                 offset += 96;
816                 display_application_name( tvb, offset, pinfo, tree);
817         }
818 }
819
820
821
822 static void dissect_auth_1_ack(tvbuff_t *tvb, int offset, packet_info *pinfo,
823         proto_tree *tree) {
824
825         offset += 134;
826         if ( tree) {
827                 proto_tree_add_text( tree, tvb, offset, 7, "NTLMSSP signature: %.7s",
828                         tvb_get_ptr( tvb, offset, 7));
829                 offset += 48;
830
831                 /* XXX - always 255? */
832                 proto_tree_add_text( tree, tvb, offset, 255, "NT domain: %.255s",
833                         tvb_get_ptr( tvb, offset, 255));
834         }
835 }
836
837
838
839 static void dissect_msproxy_response_4( tvbuff_t *tvb, int offset,
840         packet_info *pinfo, proto_tree *tree) {
841
842 /* decode the response _4 structure  */
843
844         offset += 134;
845 }
846
847
848
849 static void dissect_connect_ack( tvbuff_t *tvb, int offset, packet_info *pinfo,
850         proto_tree *tree, hash_entry_t *conv_info) {
851
852 /* decode the connect ack packet  */
853         offset += 20;
854
855         if ( tree)
856                 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
857                         offset, 2, FALSE);
858
859
860         conv_info->proto = PT_TCP;
861         conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
862         offset += 2;
863         
864         if ( tree){
865                 proto_tree_add_item( tree, hf_msproxy_server_int_addr, tvb,
866                         offset, 4, FALSE);
867                 offset += 14;
868
869                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
870                         offset, 2, FALSE);
871                 offset += 2;
872
873                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
874                         offset, 4, FALSE);
875                 offset += 80;
876
877                 display_application_name( tvb, offset, pinfo, tree);
878         }
879
880         add_msproxy_conversation( pinfo, conv_info);
881 }
882
883
884
885 static void dissect_tcp_bind_ack( tvbuff_t *tvb, int offset, packet_info *pinfo,
886         proto_tree *tree) {
887
888 /* decode the tcp bind */
889
890         if ( tree) {
891                 offset += 6;
892
893                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
894                         FALSE);
895                 offset += 16;
896
897                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
898                         offset, 2, FALSE);
899                 offset += 6;
900
901                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
902                         offset, 2, FALSE);
903                 offset += 2;
904
905                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
906                         offset, 4, FALSE);
907
908                 offset += 88;
909
910                 display_application_name( tvb, offset, pinfo, tree);
911         }
912 }
913
914
915
916 static void dissect_bind_info( tvbuff_t *tvb, int offset, packet_info *pinfo,
917         proto_tree *tree, hash_entry_t *conv_info) {
918
919 /* decode the Bind info response from server */
920
921         offset += 6;
922
923         if ( tree) 
924                 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
925                         FALSE);
926         offset += 14;
927
928
929         conv_info->dst_port = tvb_get_ntohs( tvb, offset);
930         if ( tree) 
931                 proto_tree_add_uint( tree, hf_msproxy_dstport, tvb, offset, 2,
932                         conv_info->dst_port);
933         offset += 2;
934
935         tvb_memcpy( tvb, (guint8 *)&conv_info->dst_addr, offset, sizeof( guint32));
936         if ( tree)
937                 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
938                         FALSE);
939         offset += 12;
940
941         conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
942         if ( tree) 
943                 proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
944                         offset, 2, conv_info->server_int_port);
945         offset += 4;
946         
947         if ( tree) {
948                 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
949                         offset, 2, FALSE);
950                 offset += 2;
951
952                 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
953                         offset, 4, FALSE);
954
955                 offset += 78;
956                 display_application_name( tvb, offset, pinfo, tree);
957                 
958         }
959         
960         add_msproxy_conversation( pinfo, conv_info);
961 }
962
963
964
965 static void dissect_resolve(tvbuff_t *tvb, int offset, packet_info *pinfo,
966         proto_tree *tree) {
967
968 /* dissect the  response resolve structure */
969 /* display a string with a length, characters encoding */
970 /* they are displayed under a tree with the name in Label variable */
971 /* return the length of the string and the length byte */
972
973         if ( tree) {
974                 int addr_offset;
975
976                 addr_offset = tvb_get_guint8( tvb, offset); 
977         
978                 proto_tree_add_text( tree, tvb, offset, 1, "Address offset: %d",
979                         addr_offset);
980
981                 ++offset;
982         
983                 offset += 13;
984
985                 offset += addr_offset; 
986
987                 proto_tree_add_item( tree, hf_msproxy_resolvaddr, tvb, offset, 4,
988                         FALSE);
989         }
990 }       
991
992
993
994 static void dissect_msproxy_response(tvbuff_t *tvb, packet_info *pinfo,
995                 proto_tree *tree, hash_entry_t *conv_info) {
996
997         int offset = 0;
998         int cmd;
999
1000         if ( tree) {
1001                 proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x", 
1002                         tvb_get_letohl( tvb, offset));
1003                 offset += 4;
1004
1005                 proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x", 
1006                         tvb_get_letohl( tvb, offset));
1007                 offset += 4;
1008
1009                 proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%04x", 
1010                         tvb_get_letohl( tvb, offset));
1011                 offset += 4;
1012
1013                 proto_tree_add_text( tree, tvb, offset, 1, "Client ack: 0x%02x", 
1014                         tvb_get_guint8( tvb, offset));
1015                 offset += 4;
1016
1017                 proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: 0x%02x", 
1018                         tvb_get_guint8( tvb, offset));
1019         
1020                 offset += 8;
1021
1022                 proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
1023                         tvb_get_ptr( tvb, offset, 4));
1024
1025                 offset += 12;
1026         }
1027         else
1028                 offset += 36;
1029
1030         cmd = tvb_get_ntohs( tvb, offset);
1031         
1032         if ( tree)
1033                 proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
1034                         cmd, "Command: 0x%02x (%s)", cmd, 
1035                         get_msproxy_cmd_name( cmd, FROM_SERVER));
1036         offset += 2;
1037         
1038         switch (cmd) {
1039                 case MSPROXY_HELLO_ACK:
1040                         dissect_hello_ack( tvb, offset, pinfo, tree, conv_info);
1041                         break;
1042         
1043                 case MSPROXY_USERINFO_ACK:
1044                         dissect_user_info_ack( tvb, offset, pinfo, tree);
1045                         break;
1046                         
1047                 case MSPROXY_AUTH_1_ACK:
1048                         dissect_auth_1_ack( tvb, offset, pinfo, tree);
1049                         break;
1050
1051 /* this also handle the MSPROXY_BIND_ACK ??? check this */
1052
1053                 case MSPROXY_UDPASSOCIATE_ACK:                  
1054                         dissect_udpassociate_ack( tvb, offset, pinfo, tree);
1055                         break;
1056                 
1057                 case MSPROXY_AUTH_2_ACK:
1058                 case MSPROXY_AUTH_2_ACK2:
1059                         dissect_msproxy_response_4( tvb, offset, pinfo, tree);
1060                         break;
1061
1062                 case MSPROXY_TCP_BIND_ACK:
1063                         dissect_tcp_bind_ack( tvb, offset, pinfo, tree);
1064                         break;
1065
1066                 case MSPROXY_CONNECT_ACK:
1067                         dissect_connect_ack( tvb, offset, pinfo, tree,
1068                                 conv_info);
1069                         break;
1070
1071                 case MSPROXY_BINDINFO:
1072                         dissect_bind_info( tvb, offset, pinfo, tree, conv_info);
1073                         break;
1074         
1075                 case MSPROXY_RESOLVE_ACK:
1076                         dissect_resolve( tvb, offset, pinfo, tree);
1077                         break;
1078                 
1079                 case MSPROXY_CONNECT_AUTHFAILED:
1080                 case MSPROXY_BIND_AUTHFAILED:
1081                         proto_tree_add_text( tree, tvb, offset, 0, "No know information (help wanted)");
1082                         break;
1083
1084                 default:
1085
1086                         if (tree &&
1087                            (((cmd >> 8) ==  MSPROXY_CONNREFUSED) ||
1088                             ((cmd >> 12) ==  MSPROXY_CONNREFUSED)))
1089                                 proto_tree_add_text( tree, tvb, offset, 0,
1090                                         "No know information (help wanted)");
1091         
1092                         else if ( tree)
1093                                 proto_tree_add_text( tree, tvb, offset, 0,
1094                                         "Unhandled response command (report this, please)");
1095         }
1096         
1097         
1098 }
1099
1100
1101
1102 static void dissect_msproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1103
1104
1105         proto_tree      *msproxy_tree = NULL;
1106         proto_item      *ti;
1107         unsigned int    cmd;
1108
1109
1110         hash_entry_t *hash_info;
1111         conversation_t *conversation;
1112         
1113         if (check_col(pinfo->fd, COL_PROTOCOL))
1114                 col_set_str(pinfo->fd, COL_PROTOCOL, "MSproxy");
1115         if (check_col(pinfo->fd, COL_INFO))
1116                 col_clear(pinfo->fd, COL_INFO);
1117
1118         conversation = find_conversation( &pinfo->src, &pinfo->dst,
1119                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1120
1121         if ( !conversation) {
1122                 conversation = conversation_new( &pinfo->src, &pinfo->dst,
1123                         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1124         }
1125         hash_info = conversation_get_proto_data(conversation, proto_msproxy);
1126         if ( !hash_info) {
1127                 hash_info = g_mem_chunk_alloc(vals);
1128                 conversation_add_proto_data(conversation, proto_msproxy,
1129                         hash_info);
1130         }
1131
1132         if (check_col(pinfo->fd, COL_INFO)){
1133         
1134                 cmd = tvb_get_ntohs( tvb, 36);
1135                 
1136                 if ( pinfo->srcport == UDP_PORT_MSPROXY)
1137                         col_add_fstr( pinfo->fd, COL_INFO, "Server message: %s",
1138                                 get_msproxy_cmd_name( cmd, FROM_SERVER));
1139                 else
1140                         col_add_fstr(pinfo->fd, COL_INFO, "Client message: %s",
1141                                 get_msproxy_cmd_name( cmd, FROM_CLIENT));
1142                 
1143         }
1144
1145         if (tree) {                             /* if proto tree, decode data */
1146                 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0,
1147                                 tvb_length(tvb), FALSE );
1148
1149                 msproxy_tree = proto_item_add_subtree(ti, ett_msproxy);
1150         }
1151
1152         if ( pinfo->srcport == UDP_PORT_MSPROXY)
1153                 dissect_msproxy_response( tvb, pinfo, msproxy_tree, hash_info);
1154         else
1155                 dissect_msproxy_request( tvb, pinfo, msproxy_tree, hash_info);
1156 }
1157
1158
1159
1160 static void msproxy_reinit( void){
1161
1162 /* Do the cleanup work when a new pass through the packet list is       */
1163 /* performed. Reset the highest row seen counter and re-initialize the  */
1164 /* conversation memory chunks.                                          */
1165
1166         last_row = 0;                   
1167         
1168         if (vals)
1169                 g_mem_chunk_destroy(vals);
1170
1171         vals = g_mem_chunk_new("msproxy_vals", hash_val_length,
1172                 hash_init_count * hash_val_length,
1173                 G_ALLOC_AND_FREE);
1174                 
1175         if (redirect_vals)
1176                 g_mem_chunk_destroy(redirect_vals);
1177
1178         redirect_vals = g_mem_chunk_new("msproxy_redirect_vals", redirect_val_length,
1179                 redirect_init_count * redirect_val_length,
1180                 G_ALLOC_AND_FREE);
1181 }
1182
1183
1184
1185 void
1186 proto_register_msproxy( void){
1187
1188 /* Prep the msproxy protocol, for now, just register it */
1189
1190         static gint *ett[] = {
1191                 &ett_msproxy,
1192                 &ett_msproxy_name
1193         };
1194         static hf_register_info hf[] = {
1195     
1196                 { &hf_msproxy_cmd,
1197                         { "Command", "msproxy.command", FT_UINT16, BASE_DEC,
1198                                  NULL, 0x0, "", HFILL
1199                         }
1200                 },
1201                 
1202                 { &hf_msproxy_dstaddr,
1203                         { "Destination Address", "msproxy.dstaddr", FT_IPv4, BASE_NONE, NULL,
1204                                 0x0, "", HFILL
1205                         }
1206                 },
1207
1208                 { &hf_msproxy_srcport,
1209                         { "Source Port", "msproxy.srcport", FT_UINT16,
1210                                 BASE_DEC, NULL, 0x0, "", HFILL
1211                         }
1212                 },
1213                 { &hf_msproxy_dstport,
1214                         { "Destination Port", "msproxy.dstport", FT_UINT16,
1215                                 BASE_DEC, NULL, 0x0, "", HFILL
1216                         }
1217                 },
1218                 { &hf_msproxy_clntport,
1219                         { "Client Port",        "msproxy.clntport", FT_UINT16,
1220                                 BASE_DEC, NULL, 0x0, "", HFILL
1221                         }
1222                 },
1223                 { &hf_msproxy_server_ext_addr,
1224                         { "Server External Address", "msproxy.server_ext_addr", FT_IPv4, BASE_NONE, NULL,
1225                                 0x0, "", HFILL
1226                         }
1227                 },
1228                 
1229                 { &hf_msproxy_server_ext_port,
1230                         { "Server External Port",       "msproxy.server_ext_port", FT_UINT16,
1231                                 BASE_DEC, NULL, 0x0, "", HFILL
1232                         }
1233                 },
1234
1235                 { &hf_msproxy_server_int_addr,
1236                         { "Server Internal Address", "msproxy.server_int_addr", FT_IPv4, BASE_NONE, NULL,
1237                                 0x0, "", HFILL
1238                         }
1239                 },
1240                 
1241                 { &hf_msproxy_server_int_port,
1242                         { "Server Internal Port",       "msproxy.server_int_port", FT_UINT16,
1243                                 BASE_DEC, NULL, 0x0, "", HFILL
1244                         }
1245                 },
1246                 { &hf_msproxy_serverport,
1247                         { "Server Port",        "msproxy.serverport", FT_UINT16,
1248                                 BASE_DEC, NULL, 0x0, "", HFILL
1249                         }
1250                 },
1251                 { &hf_msproxy_bindport,
1252                         { "Bind Port",  "msproxy.bindport", FT_UINT16,
1253                                 BASE_DEC, NULL, 0x0, "", HFILL
1254                         }
1255                 },
1256                 { &hf_msproxy_boundport,
1257                         { "Bound Port", "msproxy.boundport", FT_UINT16,
1258                                 BASE_DEC, NULL, 0x0, "", HFILL
1259                         }
1260                 },
1261                 { &hf_msproxy_serveraddr,
1262                         { "Server Address", "msproxy.serveraddr", FT_IPv4, BASE_NONE, NULL,
1263                                 0x0, "", HFILL
1264                         }
1265                 },
1266                 { &hf_msproxy_bindaddr,
1267                         { "Destination", "msproxy.bindaddr", FT_IPv4, BASE_NONE, NULL,
1268                                 0x0, "", HFILL
1269                         }
1270                 },
1271                 { &hf_msproxy_bind_id,
1272                         { "Bound Port Id",      "msproxy.bindid", FT_UINT32,
1273                                 BASE_HEX, NULL, 0x0, "", HFILL
1274                         }
1275                 },
1276                 { &hf_msproxy_resolvaddr,
1277                         { "Address", "msproxy.resolvaddr", FT_IPv4, BASE_NONE, NULL,
1278                                 0x0, "", HFILL
1279                         }
1280                 }
1281
1282         };
1283
1284         proto_msproxy = proto_register_protocol( "MS Proxy Protocol",
1285             "MS Proxy", "msproxy");
1286
1287         proto_register_field_array(proto_msproxy, hf, array_length(hf));
1288         proto_register_subtree_array(ett, array_length(ett));  
1289
1290         register_init_routine( &msproxy_reinit);        /* register re-init routine */
1291 }
1292
1293
1294 void
1295 proto_reg_handoff_msproxy(void) {
1296
1297         /* dissector install routine */ 
1298  
1299         dissector_add("udp.port", UDP_PORT_MSPROXY, dissect_msproxy,
1300             proto_msproxy);
1301 }