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