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