HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-msproxy.c
blob61d34b179d8ff82c41ff9a75bd23528d81df05fa
1 /* packet-msproxy.c
2 * Routines for Microsoft Proxy packet dissection
3 * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * This was derived from the dante socks implementation source code.
26 * Most of the information came from common.h and msproxy_clientprotocol.c
28 * See http://www.inet.no/dante for more information
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 ************************************************************************/
44 #include "config.h"
46 #include <string.h>
47 #include <glib.h>
49 #include <epan/packet.h>
50 #include <epan/addr_resolv.h>
51 #include <epan/conversation.h>
52 #include <epan/wmem/wmem.h>
53 #include <epan/expert.h>
55 #include "packet-tcp.h"
56 #include "packet-udp.h"
58 extern void udp_hash_add(guint16 proto,
59 void (*dissect)(const guchar *, int, frame_data *, proto_tree *));
62 static int proto_msproxy = -1;
64 static int ett_msproxy = -1;
65 static int ett_msproxy_name = -1;
67 static int hf_msproxy_cmd = -1;
68 static int hf_msproxy_clntport = -1;
70 static int hf_msproxy_dstaddr = -1;
72 /* static int hf_msproxy_srcport = -1; */
73 static int hf_msproxy_dstport = -1;
74 static int hf_msproxy_serverport = -1;
75 static int hf_msproxy_serveraddr = -1;
76 static int hf_msproxy_bindport = -1;
77 static int hf_msproxy_bindaddr = -1;
78 static int hf_msproxy_boundport = -1;
79 static int hf_msproxy_bind_id = -1;
80 static int hf_msproxy_resolvaddr = -1;
82 static int hf_msproxy_client_id = -1;
83 static int hf_msproxy_version = -1;
84 static int hf_msproxy_server_id = -1;
85 static int hf_msproxy_server_ack = -1;
86 static int hf_msproxy_client_ack = -1;
87 static int hf_msproxy_seq_num = -1;
88 static int hf_msproxy_rwsp_signature = -1;
89 static int hf_msproxy_ntlmssp_signature = -1;
91 static int hf_msproxy_server_int_addr = -1;
92 static int hf_msproxy_server_int_port = -1;
93 static int hf_msproxy_server_ext_addr = -1;
94 static int hf_msproxy_server_ext_port = -1;
96 static expert_field ei_msproxy_unknown = EI_INIT;
97 static expert_field ei_msproxy_unhandled = EI_INIT;
99 static dissector_handle_t msproxy_sub_handle;
102 #define UDP_PORT_MSPROXY 1745
104 #define N_MSPROXY_HELLO 0x05 /* packet 1 from client */
105 #define N_MSPROXY_ACK 0x10 /* packet 1 from server */
106 #define N_MSPROXY_USERINFO_ACK 0x04 /* packet 2 from server */
107 #define N_MSPROXY_AUTH 0x47 /* packet 3 from client */
108 #define N_MSPROXY_RESOLVE 0x07 /* Resolve request */
111 /*$$$ 0x0500 was dante value, I see 0x05ff and 0x0500 */
113 #define MSPROXY_HELLO 0x0500
114 #define MSPROXY_HELLO_2 0x05ff
116 #define MSPROXY_HELLO_ACK 0x1000
118 #define MSPROXY_USERINFO 0x1000
119 #define MSPROXY_USERINFO_ACK 0x0400
121 #define MSPROXY_AUTH 0x4700
122 #define MSPROXY_AUTH_1_ACK 0x4714
123 #define MSPROXY_AUTH_2 0x4701
124 #define MSPROXY_AUTH_2_ACK 0x4715
125 #define MSPROXY_AUTH_2_ACK2 0x4716
127 #define MSPROXY_RESOLVE 0x070d
128 #define MSPROXY_RESOLVE_ACK 0x070f
130 #define MSPROXY_BIND 0x0704
131 #define MSPROXY_BIND_ACK 0x0706
133 #define MSPROXY_TCP_BIND 0x0707
134 #define MSPROXY_TCP_BIND_ACK 0x0708
136 #define MSPROXY_LISTEN 0x0406
138 #define MSPROXY_BINDINFO 0x0709
140 #define MSPROXY_BINDINFO_ACK 0x070a
142 #define MSPROXY_CONNECT 0x071e
143 #define MSPROXY_CONNECT_ACK 0x0703
145 #define MSPROXY_UDPASSOCIATE 0x0705
146 #define MSPROXY_UDPASSOCIATE_ACK 0x0706
148 #define MSPROXY_UDP_BIND_REQ 0x070b
150 #define MSPROXY_CONNECTED 0x042c
151 #define MSPROXY_SESSIONEND 0x251e
153 #define MSPROXY_BIND_AUTHFAILED 0x0804
154 #define MSPROXY_CONNECT_AUTHFAILED 0x081e
155 #define MSPROXY_CONNREFUSED 0x4 /* low 12 bits seem to vary. */
157 #define FROM_SERVER 1 /* direction of packet data for get_msproxy_cmd_name */
158 #define FROM_CLIENT 0
163 /*$$$ should this be the same as redirect_entry_t ?? */
164 /* then the add_conversation could just copy the structure */
165 /* using the same allocation (instance for you object guys) */
166 /* wouldn't work because there may be multiple child conversations */
167 /* from the same MSProxy conversation */
169 typedef struct {
170 guint32 dst_addr;
171 guint32 clnt_port;
172 guint32 dst_port;
173 guint32 server_int_port;
174 int proto;
175 }hash_entry_t;
178 /************** conversation hash stuff ***************/
180 typedef struct {
181 guint32 remote_addr;
182 guint32 clnt_port;
183 guint32 server_int_port;
184 guint32 remote_port;
185 int proto;
186 }redirect_entry_t;
189 /************** negotiated conversation hash stuff ***************/
192 static guint32 last_row= 0; /* used to see if packet is new */
194 static void msproxy_sub_dissector( tvbuff_t *tvb, packet_info *pinfo,
195 proto_tree *tree) {
197 /* Conversation dissector called from TCP or UDP dissector. Decode and */
198 /* display the msproxy header, the pass the rest of the data to the tcp */
199 /* or udp port decode routine to handle the payload. */
201 guint32 *ptr;
202 redirect_entry_t *redirect_info;
203 conversation_t *conversation;
204 proto_tree *msp_tree;
205 proto_item *ti;
207 conversation = find_conversation( pinfo->fd->num, &pinfo->src, &pinfo->dst,
208 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
210 DISSECTOR_ASSERT( conversation); /* should always find a conversation */
212 redirect_info = (redirect_entry_t *)conversation_get_proto_data(conversation,
213 proto_msproxy);
215 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS Proxy");
217 col_set_str(pinfo->cinfo, COL_INFO,
218 (( redirect_info->proto == PT_TCP) ? "TCP stream" :
219 "UDP packets"));
221 if ( tree) {
222 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, 0,
223 ENC_NA );
225 msp_tree = proto_item_add_subtree(ti, ett_msproxy);
227 proto_tree_add_uint( msp_tree, hf_msproxy_dstport, tvb, 0, 0,
228 redirect_info->remote_port);
230 proto_tree_add_ipv4( msp_tree, hf_msproxy_dstaddr, tvb, 0, 0,
231 redirect_info->remote_addr);
235 /* set pinfo->{src/dst port} and call the TCP or UDP sub-dissector lookup */
237 if ( pinfo->srcport == redirect_info->clnt_port)
238 ptr = &pinfo->destport;
239 else
240 ptr = &pinfo->srcport;
242 *ptr = redirect_info->remote_port;
244 if ( redirect_info->proto == PT_TCP)
245 decode_tcp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
246 pinfo->destport, NULL, NULL);
247 else
248 decode_udp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
249 pinfo->destport, -1);
251 *ptr = redirect_info->server_int_port;
256 static void add_msproxy_conversation( packet_info *pinfo,
257 hash_entry_t *hash_info){
259 /* check to see if a conversation already exists, if it does assume */
260 /* it's our conversation and quit. Otherwise create a new conversation. */
261 /* Load the conversation dissector to our dissector and load the */
262 /* conversation data structure with the info needed to call the TCP or */
263 /* UDP port decoder. */
265 /* NOTE: Currently this assume that the conversation will be created */
266 /* during a packet from the server. If that changes, pinfo->src */
267 /* and pinfo->dst will not be correct and this routine will have */
268 /* to change. */
270 conversation_t *conversation;
271 redirect_entry_t *new_conv_info;
273 if (pinfo->fd->flags.visited) {
275 * We've already processed this frame once, so we
276 * should already have done this.
278 return;
281 conversation = find_conversation( pinfo->fd->num, &pinfo->src,
282 &pinfo->dst, (port_type)hash_info->proto, hash_info->server_int_port,
283 hash_info->clnt_port, 0);
285 if ( !conversation) {
286 conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst,
287 (port_type)hash_info->proto, hash_info->server_int_port,
288 hash_info->clnt_port, 0);
290 conversation_set_dissector(conversation, msproxy_sub_handle);
292 new_conv_info = wmem_new(wmem_file_scope(), redirect_entry_t);
294 new_conv_info->remote_addr = hash_info->dst_addr;
295 new_conv_info->clnt_port = hash_info->clnt_port;
296 new_conv_info->remote_port = hash_info->dst_port;
297 new_conv_info->server_int_port = hash_info->server_int_port;
298 new_conv_info->proto = hash_info->proto;
300 conversation_add_proto_data(conversation, proto_msproxy,
301 new_conv_info);
306 static int display_application_name(tvbuff_t *tvb, int offset,
307 proto_tree *tree) {
309 /* display the application name in the proto tree. */
311 /* NOTE: this routine assumes that the tree pointer is valid (not NULL) */
313 int length;
315 length = tvb_strnlen( tvb, offset, 255);
316 proto_tree_add_text( tree, tvb, offset, length, "Application: %.*s",
317 length, tvb_get_string( wmem_packet_scope(), tvb, offset, length));
319 return length;
323 static const char *get_msproxy_cmd_name( int cmd, int direction) {
325 /* return the command name string for cmd */
327 switch (cmd){
328 case MSPROXY_HELLO_2:
329 case MSPROXY_HELLO: return "Hello";
331 /* MSPROXY_HELLO_ACK & MSPROXY_USERINFO have the same value (0x1000). */
332 /* So use the direction flag to determine which to use. */
334 case MSPROXY_USERINFO:
335 if ( direction == FROM_SERVER)
336 return "Hello Acknowledge";
337 else
338 return "User Info";
339 case MSPROXY_USERINFO_ACK: return "User Info Acknowledge";
340 case MSPROXY_AUTH: return "Authentication";
341 case MSPROXY_AUTH_1_ACK: return "Authentication Acknowledge";
342 case MSPROXY_AUTH_2: return "Authentication 2";
343 case MSPROXY_AUTH_2_ACK: return "Authentication 2 Acknowledge";
344 case MSPROXY_RESOLVE: return "Resolve";
345 case MSPROXY_RESOLVE_ACK: return "Resolve Acknowledge";
346 case MSPROXY_BIND: return "Bind";
347 case MSPROXY_TCP_BIND: return "TCP Bind";
348 case MSPROXY_TCP_BIND_ACK: return "TCP Bind Acknowledge";
349 case MSPROXY_LISTEN: return "Listen";
350 case MSPROXY_BINDINFO: return "Bind Info";
351 case MSPROXY_BINDINFO_ACK: return "Bind Info Acknowledge";
352 case MSPROXY_CONNECT: return "Connect";
353 case MSPROXY_CONNECT_ACK: return "Connect Acknowledge";
354 case MSPROXY_UDPASSOCIATE: return "UDP Associate";
355 case MSPROXY_UDP_BIND_REQ: return "UDP Bind";
356 case MSPROXY_UDPASSOCIATE_ACK: return "Bind or Associate Acknowledge";
357 case MSPROXY_CONNECTED: return "Connected";
358 case MSPROXY_SESSIONEND: return "Session End";
360 default: return "Unknown";
366 static void dissect_user_info_2(tvbuff_t *tvb, int offset,
367 proto_tree *tree) {
369 /* decode the user, application, computer name */
372 int length;
374 if ( tree) {
375 length = tvb_strnlen( tvb, offset, 255);
376 if (length == -1)
377 return;
378 proto_tree_add_text( tree, tvb, offset, length + 1,
379 "User name: %.*s", length,
380 tvb_get_string( wmem_packet_scope(), tvb, offset, length));
381 offset += length + 2;
383 length = tvb_strnlen( tvb, offset, 255);
384 if (length == -1)
385 return;
386 proto_tree_add_text( tree, tvb, offset, length + 1,
387 "Application name: %.*s", length,
388 tvb_get_string( wmem_packet_scope(), tvb, offset, length));
389 offset += length + 1;
391 length = tvb_strnlen( tvb, offset, 255);
392 if (length == -1)
393 return;
394 proto_tree_add_text( tree, tvb, offset, length + 1,
395 "Client computer name: %.*s", length,
396 tvb_get_string( wmem_packet_scope(), tvb, offset, length));
402 static void dissect_msproxy_request_1(tvbuff_t *tvb, int offset,
403 proto_tree *tree) {
405 /* decode the request _1 structure */
408 offset += 182;
410 dissect_user_info_2( tvb, offset, tree);
416 static void dissect_bind(tvbuff_t *tvb, int offset,
417 proto_tree *tree, hash_entry_t *conv_info) {
419 /* decode the bind request */
421 offset += 18;
423 if ( tree)
424 proto_tree_add_item( tree, hf_msproxy_bindaddr, tvb, offset, 4,
425 ENC_BIG_ENDIAN);
426 offset += 4;
428 if ( tree)
429 proto_tree_add_item( tree, hf_msproxy_bindport, tvb, offset, 2,
430 ENC_BIG_ENDIAN);
431 offset += 6;
433 if ( tree)
434 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
435 ENC_BIG_ENDIAN);
436 offset += 2;
438 conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
439 offset += 6;
441 if ( tree){
442 proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
443 ENC_BIG_ENDIAN);
445 offset += 82;
446 display_application_name( tvb, offset, tree);
452 static int dissect_auth(tvbuff_t *tvb, int offset,
453 proto_tree *tree) {
455 /* decode the authorization request */
458 offset += 134;
459 if ( tree) {
460 proto_tree_add_item( tree, hf_msproxy_ntlmssp_signature, tvb, offset, 7, ENC_NA|ENC_ASCII);
462 offset += 7;
464 return offset;
469 static void dissect_tcp_bind(tvbuff_t *tvb, int offset,
470 proto_tree *tree, hash_entry_t *conv_info) {
472 /* decode the bind packet. Set the protocol type in the conversation */
473 /* information so the bind_info can use it to create the payload */
474 /* dissector. */
477 conv_info->proto = PT_TCP;
479 if ( tree) {
480 offset += 6;
482 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
483 ENC_BIG_ENDIAN);
484 offset += 16;
486 proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
487 ENC_BIG_ENDIAN);
489 offset += 96;
490 display_application_name( tvb, offset, tree);
495 static void dissect_request_connect(tvbuff_t *tvb, int offset,
496 proto_tree *tree, hash_entry_t *conv_info) {
498 /* decode the connect request, display */
500 conv_info->proto = PT_TCP;
502 offset += 20;
504 if ( tree)
505 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
506 ENC_BIG_ENDIAN);
508 conv_info->dst_port = tvb_get_ntohs( tvb, offset);
509 offset += 2;
511 if ( tree)
512 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
513 ENC_BIG_ENDIAN);
515 conv_info->dst_addr = tvb_get_ipv4( tvb, offset);
517 offset += 12;
519 conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
521 if ( tree){
522 proto_tree_add_uint( tree, hf_msproxy_clntport, tvb, offset, 2,
523 conv_info->clnt_port);
525 offset += 84;
527 display_application_name( tvb, offset, tree);
532 static void dissect_bind_info_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
534 /* decode the client bind info ack */
537 if ( tree){
538 offset += 6;
540 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
541 ENC_BIG_ENDIAN);
542 offset += 14;
544 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
545 ENC_BIG_ENDIAN);
546 offset += 2;
548 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
549 ENC_BIG_ENDIAN);
550 offset += 12;
552 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
553 offset, 2, ENC_BIG_ENDIAN);
554 offset += 4;
556 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
557 offset, 2, ENC_BIG_ENDIAN);
558 offset += 2;
560 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
561 offset, 4, ENC_BIG_ENDIAN);
563 offset += 78;
564 display_application_name( tvb, offset, tree);
569 static void dissect_request_resolve(tvbuff_t *tvb, int offset,
570 proto_tree *tree) {
572 /* dissect the request resolve structure */
573 /* display a string with a length, characters encoding */
574 /* they are displayed under a tree with the name in Label variable */
575 /* return the length of the string and the length byte */
577 proto_tree *name_tree;
578 proto_item *ti;
580 int length = tvb_get_guint8( tvb, offset);
582 if ( tree){
583 ti = proto_tree_add_text(tree, tvb, offset, length + 1,
584 "Host Name: %.*s", length,
585 tvb_get_string( wmem_packet_scope(), tvb, offset + 18, length));
587 name_tree = proto_item_add_subtree(ti, ett_msproxy_name);
589 proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %d",
590 length);
592 ++offset;
593 offset += 17;
595 proto_tree_add_text( name_tree, tvb, offset, length, "String: %s",
596 tvb_get_string( wmem_packet_scope(), tvb, offset, length));
602 static void dissect_udp_bind(tvbuff_t *tvb, int offset,
603 proto_tree *tree, hash_entry_t *conv_info) {
605 /* Dissect the udp bind request. Load the protocol id (PT_UDP) and the */
606 /* remote address so bind_info can use it to create conversation */
607 /* dissector. */
609 conv_info->proto = PT_UDP;
612 offset += 8;
614 if ( tree)
615 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
616 ENC_BIG_ENDIAN);
617 offset += 12;
620 if ( tree)
621 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
622 ENC_BIG_ENDIAN);
623 offset += 2;
625 if ( tree)
626 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
627 ENC_BIG_ENDIAN);
629 offset += 96;
631 if ( tree)
632 display_application_name( tvb, offset, tree);
636 static void dissect_udp_assoc(tvbuff_t *tvb, int offset,
637 proto_tree *tree, hash_entry_t *conv_info) {
639 /* dissect the udp associate request. And load client port into */
640 /* conversation data structure for later. */
643 offset += 28;
645 if ( tree)
646 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
647 ENC_BIG_ENDIAN);
649 conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
651 offset += 90;
653 if ( tree)
654 display_application_name( tvb, offset, tree);
658 static void dissect_msproxy_request(tvbuff_t *tvb,
659 proto_tree *tree, hash_entry_t *conv_info) {
661 int offset = 0;
662 int cmd;
664 if ( tree) {
665 proto_tree_add_item( tree, hf_msproxy_client_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
666 offset += 4;
668 proto_tree_add_item( tree, hf_msproxy_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
669 offset += 4;
671 proto_tree_add_item( tree, hf_msproxy_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
672 offset += 4;
674 proto_tree_add_item( tree, hf_msproxy_server_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
675 offset += 4;
677 proto_tree_add_item( tree, hf_msproxy_seq_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
678 offset += 8;
680 proto_tree_add_item( tree, hf_msproxy_rwsp_signature, tvb, offset, 4, ENC_NA|ENC_ASCII);
681 offset += 12;
683 else /* no tree */
684 offset += 36;
686 cmd = tvb_get_ntohs( tvb, offset);
688 if ( tree)
689 proto_tree_add_uint_format_value( tree, hf_msproxy_cmd, tvb, offset, 2,
690 cmd, "%s (0x%02x)",
691 get_msproxy_cmd_name( cmd, FROM_CLIENT),
692 cmd);
694 offset += 2;
696 switch (cmd){
697 case MSPROXY_AUTH:
698 dissect_auth( tvb, offset, tree);
699 break;
701 case MSPROXY_BIND:
702 dissect_bind( tvb, offset, tree, conv_info);
703 break;
705 case MSPROXY_UDP_BIND_REQ:
706 dissect_udp_bind( tvb, offset, tree, conv_info);
707 break;
709 case MSPROXY_AUTH_2: /*$$ this is probably wrong place for this */
710 case MSPROXY_TCP_BIND:
711 dissect_tcp_bind( tvb, offset, tree, conv_info);
712 break;
714 case MSPROXY_RESOLVE:
715 dissect_request_resolve( tvb, offset, tree);
716 break;
718 case MSPROXY_CONNECT:
719 case MSPROXY_LISTEN:
720 dissect_request_connect( tvb, offset, tree,
721 conv_info);
722 break;
724 case MSPROXY_BINDINFO_ACK:
725 dissect_bind_info_ack( tvb, offset, tree);
726 break;
728 case MSPROXY_HELLO:
729 case MSPROXY_HELLO_2:
730 dissect_msproxy_request_1( tvb, offset, tree);
731 break;
733 case MSPROXY_UDPASSOCIATE:
734 dissect_udp_assoc( tvb, offset, tree, conv_info);
735 break;
736 default:
737 if ( tree)
738 proto_tree_add_text( tree, tvb, offset, 0,
739 "Unhandled request command (report this, please)");
745 static int dissect_hello_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
747 /* decode the hello acknowledge packet */
749 offset += 60;
751 if ( tree) {
752 proto_tree_add_item( tree, hf_msproxy_serverport, tvb, offset, 2,
753 ENC_BIG_ENDIAN);
755 offset += 2;
756 if ( tree) {
757 proto_tree_add_item( tree, hf_msproxy_serveraddr, tvb, offset, 4,
758 ENC_BIG_ENDIAN);
760 offset += 4;
762 return offset;
767 /* XXX - implement me */
768 static int dissect_user_info_ack(tvbuff_t *tvb _U_, int offset,
769 proto_tree *tree _U_) {
771 /* decode the response _2 structure */
773 offset += 18;
775 offset += 2;
777 return offset;
782 static void dissect_udpassociate_ack(tvbuff_t *tvb, int offset,
783 proto_tree *tree) {
785 offset += 6;
787 if ( tree) {
788 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
789 ENC_BIG_ENDIAN);
790 offset += 14;
792 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
793 offset, 2, ENC_BIG_ENDIAN);
794 offset += 2;
796 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
797 offset, 4, ENC_BIG_ENDIAN);
799 offset += 96;
800 display_application_name( tvb, offset, tree);
806 static void dissect_auth_1_ack(tvbuff_t *tvb, int offset,
807 proto_tree *tree) {
809 offset += 134;
810 if ( tree) {
811 proto_tree_add_item( tree, hf_msproxy_ntlmssp_signature, tvb, offset, 7, ENC_NA|ENC_ASCII);
812 offset += 48;
814 /* XXX - always 255? */
815 proto_tree_add_text( tree, tvb, offset, 255, "NT domain: %.255s",
816 tvb_get_string( wmem_packet_scope(), tvb, offset, 255));
822 /* XXX - implement me */
823 static int dissect_msproxy_response_4( tvbuff_t *tvb _U_, int offset,
824 proto_tree *tree _U_) {
826 /* decode the response _4 structure */
828 offset += 134;
830 return offset;
835 static void dissect_connect_ack( tvbuff_t *tvb, int offset, packet_info *pinfo,
836 proto_tree *tree, hash_entry_t *conv_info) {
838 /* decode the connect ack packet */
839 offset += 20;
841 if ( tree)
842 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
843 offset, 2, ENC_BIG_ENDIAN);
846 conv_info->proto = PT_TCP;
847 conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
848 offset += 2;
850 if ( tree){
851 proto_tree_add_item( tree, hf_msproxy_server_int_addr, tvb,
852 offset, 4, ENC_BIG_ENDIAN);
853 offset += 14;
855 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
856 offset, 2, ENC_BIG_ENDIAN);
857 offset += 2;
859 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
860 offset, 4, ENC_BIG_ENDIAN);
861 offset += 80;
863 display_application_name( tvb, offset, tree);
866 add_msproxy_conversation( pinfo, conv_info);
871 static void dissect_tcp_bind_ack( tvbuff_t *tvb, int offset, proto_tree *tree) {
873 /* decode the tcp bind */
875 if ( tree) {
876 offset += 6;
878 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
879 ENC_BIG_ENDIAN);
880 offset += 16;
882 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
883 offset, 2, ENC_BIG_ENDIAN);
884 offset += 6;
886 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
887 offset, 2, ENC_BIG_ENDIAN);
888 offset += 2;
890 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
891 offset, 4, ENC_BIG_ENDIAN);
893 offset += 88;
895 display_application_name( tvb, offset, tree);
901 static void dissect_bind_info( tvbuff_t *tvb, int offset, packet_info *pinfo,
902 proto_tree *tree, hash_entry_t *conv_info) {
904 /* decode the Bind info response from server */
906 offset += 6;
908 if ( tree)
909 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
910 ENC_BIG_ENDIAN);
911 offset += 14;
914 conv_info->dst_port = tvb_get_ntohs( tvb, offset);
915 if ( tree)
916 proto_tree_add_uint( tree, hf_msproxy_dstport, tvb, offset, 2,
917 conv_info->dst_port);
918 offset += 2;
920 conv_info->dst_addr = tvb_get_ipv4( tvb, offset);
921 if ( tree)
922 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
923 ENC_BIG_ENDIAN);
924 offset += 12;
926 conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
927 if ( tree)
928 proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
929 offset, 2, conv_info->server_int_port);
930 offset += 4;
932 if ( tree) {
933 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
934 offset, 2, ENC_BIG_ENDIAN);
935 offset += 2;
937 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
938 offset, 4, ENC_BIG_ENDIAN);
940 offset += 78;
941 display_application_name( tvb, offset, tree);
945 add_msproxy_conversation( pinfo, conv_info);
950 static void dissect_resolve(tvbuff_t *tvb, int offset, proto_tree *tree) {
952 /* dissect the response resolve structure */
953 /* display a string with a length, characters encoding */
954 /* they are displayed under a tree with the name in Label variable */
955 /* return the length of the string and the length byte */
957 if ( tree) {
958 int addr_offset;
960 addr_offset = tvb_get_guint8( tvb, offset);
962 proto_tree_add_text( tree, tvb, offset, 1, "Address offset: %d",
963 addr_offset);
965 ++offset;
967 offset += 13;
969 offset += addr_offset;
971 proto_tree_add_item( tree, hf_msproxy_resolvaddr, tvb, offset, 4,
972 ENC_BIG_ENDIAN);
978 static void dissect_msproxy_response(tvbuff_t *tvb, packet_info *pinfo,
979 proto_tree *tree, hash_entry_t *conv_info) {
981 int offset = 0;
982 int cmd;
983 proto_item* ti;
985 if ( tree) {
986 proto_tree_add_item( tree, hf_msproxy_client_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
987 offset += 4;
989 proto_tree_add_item( tree, hf_msproxy_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
990 offset += 4;
992 proto_tree_add_item( tree, hf_msproxy_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
993 offset += 4;
995 proto_tree_add_item( tree, hf_msproxy_client_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
996 offset += 4;
998 proto_tree_add_item( tree, hf_msproxy_seq_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
999 offset += 8;
1001 proto_tree_add_item( tree, hf_msproxy_rwsp_signature, tvb, offset, 4, ENC_NA|ENC_ASCII);
1002 offset += 12;
1004 else
1005 offset += 36;
1007 cmd = tvb_get_ntohs( tvb, offset);
1009 ti = proto_tree_add_uint_format_value( tree, hf_msproxy_cmd, tvb, offset, 2,
1010 cmd, "0x%02x (%s)", cmd,
1011 get_msproxy_cmd_name( cmd, FROM_SERVER));
1012 offset += 2;
1014 switch (cmd) {
1015 case MSPROXY_HELLO_ACK:
1016 dissect_hello_ack( tvb, offset, tree);
1017 break;
1019 case MSPROXY_USERINFO_ACK:
1020 dissect_user_info_ack( tvb, offset, tree);
1021 break;
1023 case MSPROXY_AUTH_1_ACK:
1024 dissect_auth_1_ack( tvb, offset, tree);
1025 break;
1027 /* this also handle the MSPROXY_BIND_ACK ??? check this */
1029 case MSPROXY_UDPASSOCIATE_ACK:
1030 dissect_udpassociate_ack( tvb, offset, tree);
1031 break;
1033 case MSPROXY_AUTH_2_ACK:
1034 case MSPROXY_AUTH_2_ACK2:
1035 dissect_msproxy_response_4( tvb, offset, tree);
1036 break;
1038 case MSPROXY_TCP_BIND_ACK:
1039 dissect_tcp_bind_ack( tvb, offset, tree);
1040 break;
1042 case MSPROXY_CONNECT_ACK:
1043 dissect_connect_ack( tvb, offset, pinfo, tree,
1044 conv_info);
1045 break;
1047 case MSPROXY_BINDINFO:
1048 dissect_bind_info( tvb, offset, pinfo, tree, conv_info);
1049 break;
1051 case MSPROXY_RESOLVE_ACK:
1052 dissect_resolve( tvb, offset, tree);
1053 break;
1055 case MSPROXY_CONNECT_AUTHFAILED:
1056 case MSPROXY_BIND_AUTHFAILED:
1057 expert_add_info(pinfo, ti, &ei_msproxy_unknown);
1058 break;
1060 default:
1062 if ((((cmd >> 8) == MSPROXY_CONNREFUSED) ||
1063 ((cmd >> 12) == MSPROXY_CONNREFUSED)))
1064 expert_add_info(pinfo, ti, &ei_msproxy_unknown);
1065 else
1066 expert_add_info(pinfo, ti, &ei_msproxy_unhandled);
1074 static void dissect_msproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1077 proto_tree *msproxy_tree;
1078 proto_item *ti;
1079 unsigned int cmd;
1082 hash_entry_t *hash_info;
1083 conversation_t *conversation;
1085 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSproxy");
1086 col_clear(pinfo->cinfo, COL_INFO);
1088 conversation = find_or_create_conversation(pinfo);
1090 hash_info = (hash_entry_t *)conversation_get_proto_data(conversation, proto_msproxy);
1091 if ( !hash_info) {
1092 hash_info = wmem_new(wmem_file_scope(), hash_entry_t);
1093 conversation_add_proto_data(conversation, proto_msproxy,
1094 hash_info);
1097 cmd = tvb_get_ntohs( tvb, 36);
1099 if ( pinfo->srcport == UDP_PORT_MSPROXY)
1100 col_add_fstr( pinfo->cinfo, COL_INFO, "Server message: %s",
1101 get_msproxy_cmd_name( cmd, FROM_SERVER));
1102 else
1103 col_add_fstr(pinfo->cinfo, COL_INFO, "Client message: %s",
1104 get_msproxy_cmd_name( cmd, FROM_CLIENT));
1106 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, -1, ENC_NA );
1107 msproxy_tree = proto_item_add_subtree(ti, ett_msproxy);
1109 if ( pinfo->srcport == UDP_PORT_MSPROXY)
1110 dissect_msproxy_response( tvb, pinfo, msproxy_tree, hash_info);
1111 else
1112 dissect_msproxy_request( tvb, msproxy_tree, hash_info);
1117 static void msproxy_reinit( void){
1119 /* Do the cleanup work when a new pass through the packet list is */
1120 /* performed. Reset the highest row seen counter */
1122 last_row = 0;
1127 void
1128 proto_register_msproxy( void){
1130 /* Prep the msproxy protocol, for now, just register it */
1132 static gint *ett[] = {
1133 &ett_msproxy,
1134 &ett_msproxy_name
1136 static hf_register_info hf[] = {
1138 { &hf_msproxy_cmd,
1139 { "Command", "msproxy.command", FT_UINT16, BASE_DEC,
1140 NULL, 0x0, NULL, HFILL
1144 { &hf_msproxy_dstaddr,
1145 { "Destination Address", "msproxy.dstaddr", FT_IPv4, BASE_NONE, NULL,
1146 0x0, NULL, HFILL
1150 #if 0
1151 { &hf_msproxy_srcport,
1152 { "Source Port", "msproxy.srcport", FT_UINT16,
1153 BASE_DEC, NULL, 0x0, NULL, HFILL
1156 #endif
1157 { &hf_msproxy_dstport,
1158 { "Destination Port", "msproxy.dstport", FT_UINT16,
1159 BASE_DEC, NULL, 0x0, NULL, HFILL
1162 { &hf_msproxy_clntport,
1163 { "Client Port", "msproxy.clntport", FT_UINT16,
1164 BASE_DEC, NULL, 0x0, NULL, HFILL
1167 { &hf_msproxy_server_ext_addr,
1168 { "Server External Address", "msproxy.server_ext_addr", FT_IPv4, BASE_NONE, NULL,
1169 0x0, NULL, HFILL
1173 { &hf_msproxy_server_ext_port,
1174 { "Server External Port", "msproxy.server_ext_port", FT_UINT16,
1175 BASE_DEC, NULL, 0x0, NULL, HFILL
1179 { &hf_msproxy_server_int_addr,
1180 { "Server Internal Address", "msproxy.server_int_addr", FT_IPv4, BASE_NONE, NULL,
1181 0x0, NULL, HFILL
1185 { &hf_msproxy_server_int_port,
1186 { "Server Internal Port", "msproxy.server_int_port", FT_UINT16,
1187 BASE_DEC, NULL, 0x0, NULL, HFILL
1190 { &hf_msproxy_serverport,
1191 { "Server Port", "msproxy.serverport", FT_UINT16,
1192 BASE_DEC, NULL, 0x0, NULL, HFILL
1195 { &hf_msproxy_bindport,
1196 { "Bind Port", "msproxy.bindport", FT_UINT16,
1197 BASE_DEC, NULL, 0x0, NULL, HFILL
1200 { &hf_msproxy_boundport,
1201 { "Bound Port", "msproxy.boundport", FT_UINT16,
1202 BASE_DEC, NULL, 0x0, NULL, HFILL
1205 { &hf_msproxy_serveraddr,
1206 { "Server Address", "msproxy.serveraddr", FT_IPv4, BASE_NONE, NULL,
1207 0x0, NULL, HFILL
1210 { &hf_msproxy_bindaddr,
1211 { "Destination", "msproxy.bindaddr", FT_IPv4, BASE_NONE, NULL,
1212 0x0, NULL, HFILL
1215 { &hf_msproxy_bind_id,
1216 { "Bound Port Id", "msproxy.bindid", FT_UINT32,
1217 BASE_HEX, NULL, 0x0, NULL, HFILL
1220 { &hf_msproxy_resolvaddr,
1221 { "Address", "msproxy.resolvaddr", FT_IPv4, BASE_NONE, NULL,
1222 0x0, NULL, HFILL
1225 { &hf_msproxy_client_id,
1226 { "Client Id", "msproxy.client_id", FT_UINT32,
1227 BASE_HEX, NULL, 0x0, NULL, HFILL
1230 { &hf_msproxy_version,
1231 { "Version", "msproxy.version", FT_UINT32,
1232 BASE_HEX, NULL, 0x0, NULL, HFILL
1235 { &hf_msproxy_server_id,
1236 { "Server id", "msproxy.server_id", FT_UINT32,
1237 BASE_HEX, NULL, 0x0, NULL, HFILL
1240 { &hf_msproxy_server_ack,
1241 { "Server ack", "msproxy.server_ack", FT_UINT8,
1242 BASE_DEC, NULL, 0x0, NULL, HFILL
1245 { &hf_msproxy_client_ack,
1246 { "Client ack", "msproxy.client_ack", FT_UINT8,
1247 BASE_DEC, NULL, 0x0, NULL, HFILL
1250 { &hf_msproxy_seq_num,
1251 { "Sequence Number", "msproxy.seq_num", FT_UINT8,
1252 BASE_DEC, NULL, 0x0, NULL, HFILL
1255 { &hf_msproxy_rwsp_signature,
1256 { "RWSP signature", "msproxy.rwsp_signature", FT_STRING, BASE_NONE, NULL,
1257 0x0, NULL, HFILL
1260 { &hf_msproxy_ntlmssp_signature,
1261 { "NTLMSSP signature", "msproxy.ntlmssp_signature", FT_STRING, BASE_NONE, NULL,
1262 0x0, NULL, HFILL
1267 static ei_register_info ei[] = {
1268 { &ei_msproxy_unknown, { "msproxy.unknown", PI_UNDECODED, PI_WARN, "No know information (help wanted)", EXPFILL }},
1269 { &ei_msproxy_unhandled, { "msproxy.command.unhandled", PI_UNDECODED, PI_WARN, "Unhandled response command (report this, please)", EXPFILL }},
1272 expert_module_t* expert_msproxy;
1274 proto_msproxy = proto_register_protocol( "MS Proxy Protocol", "MS Proxy", "msproxy");
1276 proto_register_field_array(proto_msproxy, hf, array_length(hf));
1277 proto_register_subtree_array(ett, array_length(ett));
1278 expert_msproxy = expert_register_protocol(proto_msproxy);
1279 expert_register_field_array(expert_msproxy, ei, array_length(ei));
1281 register_init_routine( &msproxy_reinit); /* register re-init routine */
1283 msproxy_sub_handle = create_dissector_handle(msproxy_sub_dissector,
1284 proto_msproxy);
1288 void
1289 proto_reg_handoff_msproxy(void) {
1291 /* dissector install routine */
1293 dissector_handle_t msproxy_handle;
1295 msproxy_handle = create_dissector_handle(dissect_msproxy,
1296 proto_msproxy);
1297 dissector_add_uint("udp.port", UDP_PORT_MSPROXY, msproxy_handle);