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