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