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