epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-msproxy.c
blobdaf1392d1e7c5bdd93ee9d21f3396739000dfe7b
1 /* packet-msproxy.c
2 * Routines for Microsoft Proxy packet dissection
3 * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 * This was derived from the dante socks implementation source code.
12 * Most of the information came from common.h and msproxy_clientprotocol.c
14 * See http://www.inet.no/dante for more information
17 /************************************************************************
18 * *
19 * Notes: These are possible command values. User input is welcome *
20 * *
21 * Command = 0x040a - Remote host closed connection (maybe ?? ) *
22 * Command = 0x0411 - Remote host closed connection *
23 * Command = 0x0413 - Local host closed connection or SYN worked *
24 * *
25 ************************************************************************/
30 #include "config.h"
32 #include <epan/packet.h>
33 #include <epan/expert.h>
35 #include "packet-tcp.h"
36 #include "packet-udp.h"
38 void proto_register_msproxy(void);
39 void proto_reg_handoff_msproxy(void);
42 static int proto_msproxy;
44 static int ett_msproxy;
45 static int ett_msproxy_name;
47 static int hf_msproxy_cmd;
48 static int hf_msproxy_clntport;
50 static int hf_msproxy_dstaddr;
52 /* static int hf_msproxy_srcport; */
53 static int hf_msproxy_dstport;
54 static int hf_msproxy_serverport;
55 static int hf_msproxy_serveraddr;
56 static int hf_msproxy_bindport;
57 static int hf_msproxy_bindaddr;
58 static int hf_msproxy_boundport;
59 static int hf_msproxy_bind_id;
60 static int hf_msproxy_resolvaddr;
62 static int hf_msproxy_client_id;
63 static int hf_msproxy_version;
64 static int hf_msproxy_server_id;
65 static int hf_msproxy_server_ack;
66 static int hf_msproxy_client_ack;
67 static int hf_msproxy_seq_num;
68 static int hf_msproxy_rwsp_signature;
69 static int hf_msproxy_ntlmssp_signature;
71 static int hf_msproxy_server_int_addr;
72 static int hf_msproxy_server_int_port;
73 static int hf_msproxy_server_ext_addr;
74 static int hf_msproxy_server_ext_port;
76 /* Generated from convert_proto_tree_add_text.pl */
77 static int hf_msproxy_host_name;
78 static int hf_msproxy_address_offset;
79 static int hf_msproxy_client_computer_name;
80 static int hf_msproxy_nt_domain;
81 static int hf_msproxy_req_resolve_length;
82 static int hf_msproxy_application_name;
83 static int hf_msproxy_user_name;
84 static int hf_msproxy_application;
86 static expert_field ei_msproxy_unknown;
87 static expert_field ei_msproxy_unhandled;
89 static dissector_handle_t msproxy_sub_handle;
92 #define UDP_PORT_MSPROXY 1745
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 */
101 /*$$$ 0x0500 was dante value, I see 0x05ff and 0x0500 */
103 #define MSPROXY_HELLO 0x0500
104 #define MSPROXY_HELLO_2 0x05ff
106 #define MSPROXY_HELLO_ACK 0x1000
108 #define MSPROXY_USERINFO 0x1000
109 #define MSPROXY_USERINFO_ACK 0x0400
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
117 #define MSPROXY_RESOLVE 0x070d
118 #define MSPROXY_RESOLVE_ACK 0x070f
120 #define MSPROXY_BIND 0x0704
121 #define MSPROXY_BIND_ACK 0x0706
123 #define MSPROXY_TCP_BIND 0x0707
124 #define MSPROXY_TCP_BIND_ACK 0x0708
126 #define MSPROXY_LISTEN 0x0406
128 #define MSPROXY_BINDINFO 0x0709
130 #define MSPROXY_BINDINFO_ACK 0x070a
132 #define MSPROXY_CONNECT 0x071e
133 #define MSPROXY_CONNECT_ACK 0x0703
135 #define MSPROXY_UDPASSOCIATE 0x0705
136 #define MSPROXY_UDPASSOCIATE_ACK 0x0706
138 #define MSPROXY_UDP_BIND_REQ 0x070b
140 #define MSPROXY_CONNECTED 0x042c
141 #define MSPROXY_SESSIONEND 0x251e
143 #define MSPROXY_BIND_AUTHFAILED 0x0804
144 #define MSPROXY_CONNECT_AUTHFAILED 0x081e
145 #define MSPROXY_CONNREFUSED 0x4 /* low 12 bits seem to vary. */
147 #define FROM_SERVER 1 /* direction of packet data for get_msproxy_cmd_name */
148 #define FROM_CLIENT 0
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 */
159 typedef struct {
160 uint32_t dst_addr;
161 uint32_t clnt_port;
162 uint32_t dst_port;
163 uint32_t server_int_port;
164 conversation_type ctype;
165 }hash_entry_t;
168 /************** conversation hash stuff ***************/
170 typedef struct {
171 uint32_t remote_addr;
172 uint32_t clnt_port;
173 uint32_t server_int_port;
174 uint32_t remote_port;
175 conversation_type ctype;
176 }redirect_entry_t;
179 /************** negotiated conversation hash stuff ***************/
182 static int msproxy_sub_dissector( tvbuff_t *tvb, packet_info *pinfo,
183 proto_tree *tree, void* data _U_) {
185 /* Conversation dissector called from TCP or UDP dissector. Decode and */
186 /* display the msproxy header, the pass the rest of the data to the tcp */
187 /* or udp port decode routine to handle the payload. */
189 uint32_t *ptr;
190 redirect_entry_t *redirect_info;
191 conversation_t *conversation;
192 proto_tree *msp_tree;
193 proto_item *ti;
195 conversation = find_conversation_pinfo(pinfo, 0);
197 DISSECTOR_ASSERT( conversation); /* should always find a conversation */
199 redirect_info = (redirect_entry_t *)conversation_get_proto_data(conversation,
200 proto_msproxy);
202 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS Proxy");
204 col_set_str(pinfo->cinfo, COL_INFO,
205 (( redirect_info->ctype == CONVERSATION_TCP) ? "TCP stream" :
206 "UDP packets"));
208 if ( tree) {
209 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, 0,
210 ENC_NA );
212 msp_tree = proto_item_add_subtree(ti, ett_msproxy);
214 proto_tree_add_uint( msp_tree, hf_msproxy_dstport, tvb, 0, 0,
215 redirect_info->remote_port);
217 proto_tree_add_ipv4( msp_tree, hf_msproxy_dstaddr, tvb, 0, 0,
218 redirect_info->remote_addr);
222 /* set pinfo->{src/dst port} and call the TCP or UDP sub-dissector lookup */
224 if ( pinfo->srcport == redirect_info->clnt_port)
225 ptr = &pinfo->destport;
226 else
227 ptr = &pinfo->srcport;
229 *ptr = redirect_info->remote_port;
231 if ( redirect_info->ctype == CONVERSATION_TCP)
232 decode_tcp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
233 pinfo->destport, NULL, NULL);
234 else
235 decode_udp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
236 pinfo->destport, -1);
238 *ptr = redirect_info->server_int_port;
239 return tvb_captured_length(tvb);
244 static void add_msproxy_conversation( packet_info *pinfo,
245 hash_entry_t *hash_info){
247 /* check to see if a conversation already exists, if it does assume */
248 /* it's our conversation and quit. Otherwise create a new conversation. */
249 /* Load the conversation dissector to our dissector and load the */
250 /* conversation data structure with the info needed to call the TCP or */
251 /* UDP port decoder. */
253 /* NOTE: Currently this assumes that the conversation will be created */
254 /* during a packet from the server. If that changes, pinfo->src */
255 /* and pinfo->dst will not be correct and this routine will have */
256 /* to change. */
258 conversation_t *conversation;
259 redirect_entry_t *new_conv_info;
261 if (pinfo->fd->visited) {
263 * We've already processed this frame once, so we
264 * should already have done this.
266 return;
269 conversation = find_conversation( pinfo->num, &pinfo->src,
270 &pinfo->dst, hash_info->ctype, hash_info->server_int_port,
271 hash_info->clnt_port, 0);
273 if ( !conversation) {
274 conversation = conversation_new( pinfo->num, &pinfo->src, &pinfo->dst,
275 hash_info->ctype, hash_info->server_int_port,
276 hash_info->clnt_port, 0);
278 conversation_set_dissector(conversation, msproxy_sub_handle);
280 new_conv_info = wmem_new(wmem_file_scope(), redirect_entry_t);
282 new_conv_info->remote_addr = hash_info->dst_addr;
283 new_conv_info->clnt_port = hash_info->clnt_port;
284 new_conv_info->remote_port = hash_info->dst_port;
285 new_conv_info->server_int_port = hash_info->server_int_port;
286 new_conv_info->ctype = hash_info->ctype;
288 conversation_add_proto_data(conversation, proto_msproxy,
289 new_conv_info);
294 static int display_application_name(tvbuff_t *tvb, int offset,
295 proto_tree *tree) {
297 /* display the application name in the proto tree. */
299 /* NOTE: this routine assumes that the tree pointer is valid (not NULL) */
301 int length;
303 length = tvb_strnlen( tvb, offset, 255);
304 proto_tree_add_item(tree, hf_msproxy_application, tvb, offset, length, ENC_ASCII);
306 return length;
310 static const char *get_msproxy_cmd_name( int cmd, int direction) {
312 /* return the command name string for cmd */
314 switch (cmd){
315 case MSPROXY_HELLO_2:
316 case MSPROXY_HELLO: return "Hello";
318 /* MSPROXY_HELLO_ACK & MSPROXY_USERINFO have the same value (0x1000). */
319 /* So use the direction flag to determine which to use. */
321 case MSPROXY_USERINFO:
322 if ( direction == FROM_SERVER)
323 return "Hello Acknowledge";
324 else
325 return "User Info";
326 case MSPROXY_USERINFO_ACK: return "User Info Acknowledge";
327 case MSPROXY_AUTH: return "Authentication";
328 case MSPROXY_AUTH_1_ACK: return "Authentication Acknowledge";
329 case MSPROXY_AUTH_2: return "Authentication 2";
330 case MSPROXY_AUTH_2_ACK: return "Authentication 2 Acknowledge";
331 case MSPROXY_RESOLVE: return "Resolve";
332 case MSPROXY_RESOLVE_ACK: return "Resolve Acknowledge";
333 case MSPROXY_BIND: return "Bind";
334 case MSPROXY_TCP_BIND: return "TCP Bind";
335 case MSPROXY_TCP_BIND_ACK: return "TCP Bind Acknowledge";
336 case MSPROXY_LISTEN: return "Listen";
337 case MSPROXY_BINDINFO: return "Bind Info";
338 case MSPROXY_BINDINFO_ACK: return "Bind Info Acknowledge";
339 case MSPROXY_CONNECT: return "Connect";
340 case MSPROXY_CONNECT_ACK: return "Connect Acknowledge";
341 case MSPROXY_UDPASSOCIATE: return "UDP Associate";
342 case MSPROXY_UDP_BIND_REQ: return "UDP Bind";
343 case MSPROXY_UDPASSOCIATE_ACK: return "Bind or Associate Acknowledge";
344 case MSPROXY_CONNECTED: return "Connected";
345 case MSPROXY_SESSIONEND: return "Session End";
347 default: return "Unknown";
353 static void dissect_user_info_2(tvbuff_t *tvb, int offset,
354 proto_tree *tree) {
356 /* decode the user, application, computer name */
359 int length;
361 if ( tree) {
362 length = tvb_strnlen( tvb, offset, 255);
363 if (length == -1)
364 return;
365 proto_tree_add_item(tree, hf_msproxy_user_name, tvb, offset, length + 1, ENC_ASCII);
366 offset += length + 2;
368 length = tvb_strnlen( tvb, offset, 255);
369 if (length == -1)
370 return;
371 proto_tree_add_item(tree, hf_msproxy_application_name, tvb, offset, length + 1, ENC_ASCII);
372 offset += length + 1;
374 length = tvb_strnlen( tvb, offset, 255);
375 if (length == -1)
376 return;
377 proto_tree_add_item(tree, hf_msproxy_client_computer_name, tvb, offset, length + 1, ENC_ASCII);
383 static void dissect_msproxy_request_1(tvbuff_t *tvb, int offset,
384 proto_tree *tree) {
386 /* decode the request _1 structure */
389 offset += 182;
391 dissect_user_info_2( tvb, offset, tree);
397 static void dissect_bind(tvbuff_t *tvb, int offset,
398 proto_tree *tree, hash_entry_t *conv_info) {
400 /* decode the bind request */
402 offset += 18;
404 if ( tree)
405 proto_tree_add_item( tree, hf_msproxy_bindaddr, tvb, offset, 4,
406 ENC_BIG_ENDIAN);
407 offset += 4;
409 if ( tree)
410 proto_tree_add_item( tree, hf_msproxy_bindport, tvb, offset, 2,
411 ENC_BIG_ENDIAN);
412 offset += 6;
414 if ( tree)
415 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
416 ENC_BIG_ENDIAN);
417 offset += 2;
419 conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
420 offset += 6;
422 if ( tree){
423 proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
424 ENC_BIG_ENDIAN);
426 offset += 82;
427 display_application_name( tvb, offset, tree);
433 static int dissect_auth(tvbuff_t *tvb, int offset,
434 proto_tree *tree) {
436 /* decode the authorization request */
439 offset += 134;
440 if ( tree) {
441 proto_tree_add_item( tree, hf_msproxy_ntlmssp_signature, tvb, offset, 7, ENC_NA|ENC_ASCII);
443 offset += 7;
445 return offset;
450 static void dissect_tcp_bind(tvbuff_t *tvb, int offset,
451 proto_tree *tree, hash_entry_t *conv_info) {
453 /* decode the bind packet. Set the protocol type in the conversation */
454 /* information so the bind_info can use it to create the payload */
455 /* dissector. */
458 conv_info->ctype = CONVERSATION_TCP;
460 if ( tree) {
461 offset += 6;
463 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
464 ENC_BIG_ENDIAN);
465 offset += 16;
467 proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
468 ENC_BIG_ENDIAN);
470 offset += 96;
471 display_application_name( tvb, offset, tree);
476 static void dissect_request_connect(tvbuff_t *tvb, int offset,
477 proto_tree *tree, hash_entry_t *conv_info) {
479 /* decode the connect request, display */
481 conv_info->ctype = CONVERSATION_TCP;
483 offset += 20;
485 if ( tree)
486 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
487 ENC_BIG_ENDIAN);
489 conv_info->dst_port = tvb_get_ntohs( tvb, offset);
490 offset += 2;
492 if ( tree)
493 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
494 ENC_BIG_ENDIAN);
496 conv_info->dst_addr = tvb_get_ipv4( tvb, offset);
498 offset += 12;
500 conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
502 if ( tree){
503 proto_tree_add_uint( tree, hf_msproxy_clntport, tvb, offset, 2,
504 conv_info->clnt_port);
506 offset += 84;
508 display_application_name( tvb, offset, tree);
513 static void dissect_bind_info_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
515 /* decode the client bind info ack */
518 if ( tree){
519 offset += 6;
521 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
522 ENC_BIG_ENDIAN);
523 offset += 14;
525 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
526 ENC_BIG_ENDIAN);
527 offset += 2;
529 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
530 ENC_BIG_ENDIAN);
531 offset += 12;
533 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
534 offset, 2, ENC_BIG_ENDIAN);
535 offset += 4;
537 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
538 offset, 2, ENC_BIG_ENDIAN);
539 offset += 2;
541 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
542 offset, 4, ENC_BIG_ENDIAN);
544 offset += 78;
545 display_application_name( tvb, offset, tree);
550 static void dissect_request_resolve(tvbuff_t *tvb, int offset,
551 proto_tree *tree, packet_info *pinfo) {
553 /* dissect the request resolve structure */
554 /* display a string with a length, characters encoding */
555 /* they are displayed under a tree with the name in Label variable */
556 /* return the length of the string and the length byte */
558 proto_tree *name_tree;
560 int length = tvb_get_uint8( tvb, offset);
562 if ( tree){
563 name_tree = proto_tree_add_subtree_format(tree, tvb, offset, length + 1,
564 ett_msproxy_name, NULL, "Host Name: %s",
565 tvb_get_string_enc( pinfo->pool, tvb, offset + 18, length, ENC_ASCII));
567 proto_tree_add_item(name_tree, hf_msproxy_req_resolve_length, tvb, offset, 1, ENC_NA);
569 ++offset;
570 offset += 17;
572 proto_tree_add_item(name_tree, hf_msproxy_host_name, tvb, offset, length, ENC_ASCII);
578 static void dissect_udp_bind(tvbuff_t *tvb, int offset,
579 proto_tree *tree, hash_entry_t *conv_info) {
582 * Dissect the udp bind request. Load the conversation key type
583 * (CONVERSATION_UDP) and the remote address so bind_info
584 * can use it to create conversation dissector.
587 conv_info->ctype = CONVERSATION_UDP;
590 offset += 8;
592 if ( tree)
593 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
594 ENC_BIG_ENDIAN);
595 offset += 12;
598 if ( tree)
599 proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
600 ENC_BIG_ENDIAN);
601 offset += 2;
603 if ( tree)
604 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
605 ENC_BIG_ENDIAN);
607 offset += 96;
609 if ( tree)
610 display_application_name( tvb, offset, tree);
614 static void dissect_udp_assoc(tvbuff_t *tvb, int offset,
615 proto_tree *tree, hash_entry_t *conv_info) {
617 /* dissect the udp associate request. And load client port into */
618 /* conversation data structure for later. */
621 offset += 28;
623 if ( tree)
624 proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
625 ENC_BIG_ENDIAN);
627 conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
629 offset += 90;
631 if ( tree)
632 display_application_name( tvb, offset, tree);
636 static void dissect_msproxy_request(tvbuff_t *tvb, packet_info *pinfo,
637 proto_tree *tree, hash_entry_t *conv_info) {
639 int offset = 0;
640 int cmd;
641 proto_item* cmd_item;
643 proto_tree_add_item( tree, hf_msproxy_client_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
644 offset += 4;
646 proto_tree_add_item( tree, hf_msproxy_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
647 offset += 4;
649 proto_tree_add_item( tree, hf_msproxy_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
650 offset += 4;
652 proto_tree_add_item( tree, hf_msproxy_server_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
653 offset += 4;
655 proto_tree_add_item( tree, hf_msproxy_seq_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
656 offset += 8;
658 proto_tree_add_item( tree, hf_msproxy_rwsp_signature, tvb, offset, 4, ENC_NA|ENC_ASCII);
659 offset += 12;
661 cmd = tvb_get_ntohs( tvb, offset);
663 cmd_item = proto_tree_add_uint_format_value( tree, hf_msproxy_cmd, tvb, offset, 2,
664 cmd, "%s (0x%02x)",
665 get_msproxy_cmd_name( cmd, FROM_CLIENT),
666 cmd);
668 offset += 2;
670 switch (cmd){
671 case MSPROXY_AUTH:
672 dissect_auth( tvb, offset, tree);
673 break;
675 case MSPROXY_BIND:
676 dissect_bind( tvb, offset, tree, conv_info);
677 break;
679 case MSPROXY_UDP_BIND_REQ:
680 dissect_udp_bind( tvb, offset, tree, conv_info);
681 break;
683 case MSPROXY_AUTH_2: /*$$ this is probably wrong place for this */
684 case MSPROXY_TCP_BIND:
685 dissect_tcp_bind( tvb, offset, tree, conv_info);
686 break;
688 case MSPROXY_RESOLVE:
689 dissect_request_resolve( tvb, offset, tree, pinfo);
690 break;
692 case MSPROXY_CONNECT:
693 case MSPROXY_LISTEN:
694 dissect_request_connect( tvb, offset, tree,
695 conv_info);
696 break;
698 case MSPROXY_BINDINFO_ACK:
699 dissect_bind_info_ack( tvb, offset, tree);
700 break;
702 case MSPROXY_HELLO:
703 case MSPROXY_HELLO_2:
704 dissect_msproxy_request_1( tvb, offset, tree);
705 break;
707 case MSPROXY_UDPASSOCIATE:
708 dissect_udp_assoc( tvb, offset, tree, conv_info);
709 break;
710 default:
711 expert_add_info_format(pinfo, cmd_item, &ei_msproxy_unhandled,
712 "Unhandled request command (report this, please)");
718 static int dissect_hello_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
720 /* decode the hello acknowledge packet */
722 offset += 60;
724 proto_tree_add_item( tree, hf_msproxy_serverport, tvb, offset, 2, ENC_BIG_ENDIAN);
725 offset += 2;
726 proto_tree_add_item( tree, hf_msproxy_serveraddr, tvb, offset, 4, ENC_BIG_ENDIAN);
727 offset += 4;
729 return offset;
734 /* XXX - implement me */
735 static int dissect_user_info_ack(tvbuff_t *tvb _U_, int offset,
736 proto_tree *tree _U_) {
738 /* decode the response _2 structure */
740 offset += 18;
742 offset += 2;
744 return offset;
749 static void dissect_udpassociate_ack(tvbuff_t *tvb, int offset,
750 proto_tree *tree) {
752 offset += 6;
754 if ( tree) {
755 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
756 ENC_BIG_ENDIAN);
757 offset += 14;
759 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
760 offset, 2, ENC_BIG_ENDIAN);
761 offset += 2;
763 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
764 offset, 4, ENC_BIG_ENDIAN);
766 offset += 96;
767 display_application_name( tvb, offset, tree);
773 static void dissect_auth_1_ack(tvbuff_t *tvb, int offset,
774 proto_tree *tree) {
776 offset += 134;
777 if ( tree) {
778 proto_tree_add_item( tree, hf_msproxy_ntlmssp_signature, tvb, offset, 7, ENC_NA|ENC_ASCII);
779 offset += 48;
781 /* XXX - always 255? */
782 proto_tree_add_item(tree, hf_msproxy_nt_domain, tvb, offset, 255, ENC_ASCII);
788 /* XXX - implement me */
789 static int dissect_msproxy_response_4( tvbuff_t *tvb _U_, int offset,
790 proto_tree *tree _U_) {
792 /* decode the response _4 structure */
794 offset += 134;
796 return offset;
801 static void dissect_connect_ack( tvbuff_t *tvb, int offset, packet_info *pinfo,
802 proto_tree *tree, hash_entry_t *conv_info) {
804 /* decode the connect ack packet */
805 offset += 20;
807 if ( tree)
808 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
809 offset, 2, ENC_BIG_ENDIAN);
812 conv_info->ctype = CONVERSATION_TCP;
813 conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
814 offset += 2;
816 if ( tree){
817 proto_tree_add_item( tree, hf_msproxy_server_int_addr, tvb,
818 offset, 4, ENC_BIG_ENDIAN);
819 offset += 14;
821 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
822 offset, 2, ENC_BIG_ENDIAN);
823 offset += 2;
825 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
826 offset, 4, ENC_BIG_ENDIAN);
827 offset += 80;
829 display_application_name( tvb, offset, tree);
832 add_msproxy_conversation( pinfo, conv_info);
837 static void dissect_tcp_bind_ack( tvbuff_t *tvb, int offset, proto_tree *tree) {
839 /* decode the tcp bind */
841 if ( tree) {
842 offset += 6;
844 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
845 ENC_BIG_ENDIAN);
846 offset += 16;
848 proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
849 offset, 2, ENC_BIG_ENDIAN);
850 offset += 6;
852 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
853 offset, 2, ENC_BIG_ENDIAN);
854 offset += 2;
856 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
857 offset, 4, ENC_BIG_ENDIAN);
859 offset += 88;
861 display_application_name( tvb, offset, tree);
867 static void dissect_bind_info( tvbuff_t *tvb, int offset, packet_info *pinfo,
868 proto_tree *tree, hash_entry_t *conv_info) {
870 /* decode the Bind info response from server */
872 offset += 6;
874 if ( tree)
875 proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
876 ENC_BIG_ENDIAN);
877 offset += 14;
880 conv_info->dst_port = tvb_get_ntohs( tvb, offset);
881 if ( tree)
882 proto_tree_add_uint( tree, hf_msproxy_dstport, tvb, offset, 2,
883 conv_info->dst_port);
884 offset += 2;
886 conv_info->dst_addr = tvb_get_ipv4( tvb, offset);
887 if ( tree)
888 proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
889 ENC_BIG_ENDIAN);
890 offset += 12;
892 conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
893 if ( tree)
894 proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
895 offset, 2, conv_info->server_int_port);
896 offset += 4;
898 if ( tree) {
899 proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
900 offset, 2, ENC_BIG_ENDIAN);
901 offset += 2;
903 proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
904 offset, 4, ENC_BIG_ENDIAN);
906 offset += 78;
907 display_application_name( tvb, offset, tree);
911 add_msproxy_conversation( pinfo, conv_info);
916 static void dissect_resolve(tvbuff_t *tvb, int offset, proto_tree *tree) {
918 /* dissect the response resolve structure */
919 /* display a string with a length, characters encoding */
920 /* they are displayed under a tree with the name in Label variable */
921 /* return the length of the string and the length byte */
923 if ( tree) {
924 int addr_offset;
926 addr_offset = tvb_get_uint8( tvb, offset);
928 proto_tree_add_item(tree, hf_msproxy_address_offset, tvb, offset, 1, ENC_NA);
930 ++offset;
932 offset += 13;
934 offset += addr_offset;
936 proto_tree_add_item( tree, hf_msproxy_resolvaddr, tvb, offset, 4,
937 ENC_BIG_ENDIAN);
943 static void dissect_msproxy_response(tvbuff_t *tvb, packet_info *pinfo,
944 proto_tree *tree, hash_entry_t *conv_info) {
946 int offset = 0;
947 int cmd;
948 proto_item* ti;
950 if ( tree) {
951 proto_tree_add_item( tree, hf_msproxy_client_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
952 offset += 4;
954 proto_tree_add_item( tree, hf_msproxy_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
955 offset += 4;
957 proto_tree_add_item( tree, hf_msproxy_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
958 offset += 4;
960 proto_tree_add_item( tree, hf_msproxy_client_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
961 offset += 4;
963 proto_tree_add_item( tree, hf_msproxy_seq_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
964 offset += 8;
966 proto_tree_add_item( tree, hf_msproxy_rwsp_signature, tvb, offset, 4, ENC_NA|ENC_ASCII);
967 offset += 12;
969 else
970 offset += 36;
972 cmd = tvb_get_ntohs( tvb, offset);
974 ti = proto_tree_add_uint_format_value( tree, hf_msproxy_cmd, tvb, offset, 2,
975 cmd, "0x%02x (%s)", cmd,
976 get_msproxy_cmd_name( cmd, FROM_SERVER));
977 offset += 2;
979 switch (cmd) {
980 case MSPROXY_HELLO_ACK:
981 dissect_hello_ack( tvb, offset, tree);
982 break;
984 case MSPROXY_USERINFO_ACK:
985 dissect_user_info_ack( tvb, offset, tree);
986 break;
988 case MSPROXY_AUTH_1_ACK:
989 dissect_auth_1_ack( tvb, offset, tree);
990 break;
992 /* this also handle the MSPROXY_BIND_ACK ??? check this */
994 case MSPROXY_UDPASSOCIATE_ACK:
995 dissect_udpassociate_ack( tvb, offset, tree);
996 break;
998 case MSPROXY_AUTH_2_ACK:
999 case MSPROXY_AUTH_2_ACK2:
1000 dissect_msproxy_response_4( tvb, offset, tree);
1001 break;
1003 case MSPROXY_TCP_BIND_ACK:
1004 dissect_tcp_bind_ack( tvb, offset, tree);
1005 break;
1007 case MSPROXY_CONNECT_ACK:
1008 dissect_connect_ack( tvb, offset, pinfo, tree,
1009 conv_info);
1010 break;
1012 case MSPROXY_BINDINFO:
1013 dissect_bind_info( tvb, offset, pinfo, tree, conv_info);
1014 break;
1016 case MSPROXY_RESOLVE_ACK:
1017 dissect_resolve( tvb, offset, tree);
1018 break;
1020 case MSPROXY_CONNECT_AUTHFAILED:
1021 case MSPROXY_BIND_AUTHFAILED:
1022 expert_add_info(pinfo, ti, &ei_msproxy_unknown);
1023 break;
1025 default:
1027 if ((((cmd >> 8) == MSPROXY_CONNREFUSED) ||
1028 ((cmd >> 12) == MSPROXY_CONNREFUSED)))
1029 expert_add_info(pinfo, ti, &ei_msproxy_unknown);
1030 else
1031 expert_add_info(pinfo, ti, &ei_msproxy_unhandled);
1039 static int dissect_msproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
1041 proto_tree *msproxy_tree;
1042 proto_item *ti;
1043 unsigned int cmd;
1046 hash_entry_t *hash_info;
1047 conversation_t *conversation;
1049 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSproxy");
1050 col_clear(pinfo->cinfo, COL_INFO);
1052 conversation = find_or_create_conversation(pinfo);
1054 hash_info = (hash_entry_t *)conversation_get_proto_data(conversation, proto_msproxy);
1055 if ( !hash_info) {
1056 hash_info = wmem_new0(wmem_file_scope(), hash_entry_t);
1057 conversation_add_proto_data(conversation, proto_msproxy,
1058 hash_info);
1061 cmd = tvb_get_ntohs( tvb, 36);
1063 if ( pinfo->srcport == UDP_PORT_MSPROXY)
1064 col_add_fstr( pinfo->cinfo, COL_INFO, "Server message: %s",
1065 get_msproxy_cmd_name( cmd, FROM_SERVER));
1066 else
1067 col_add_fstr(pinfo->cinfo, COL_INFO, "Client message: %s",
1068 get_msproxy_cmd_name( cmd, FROM_CLIENT));
1070 ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, -1, ENC_NA );
1071 msproxy_tree = proto_item_add_subtree(ti, ett_msproxy);
1073 if ( pinfo->srcport == UDP_PORT_MSPROXY)
1074 dissect_msproxy_response( tvb, pinfo, msproxy_tree, hash_info);
1075 else
1076 dissect_msproxy_request( tvb, pinfo, msproxy_tree, hash_info);
1078 return tvb_captured_length(tvb);
1082 void
1083 proto_register_msproxy( void){
1085 /* Prep the msproxy protocol, for now, just register it */
1087 static int *ett[] = {
1088 &ett_msproxy,
1089 &ett_msproxy_name
1091 static hf_register_info hf[] = {
1093 { &hf_msproxy_cmd,
1094 { "Command", "msproxy.command", FT_UINT16, BASE_DEC,
1095 NULL, 0x0, NULL, HFILL
1099 { &hf_msproxy_dstaddr,
1100 { "Destination Address", "msproxy.dstaddr", FT_IPv4, BASE_NONE, NULL,
1101 0x0, NULL, HFILL
1105 #if 0
1106 { &hf_msproxy_srcport,
1107 { "Source Port", "msproxy.srcport", FT_UINT16,
1108 BASE_DEC, NULL, 0x0, NULL, HFILL
1111 #endif
1112 { &hf_msproxy_dstport,
1113 { "Destination Port", "msproxy.dstport", FT_UINT16,
1114 BASE_DEC, NULL, 0x0, NULL, HFILL
1117 { &hf_msproxy_clntport,
1118 { "Client Port", "msproxy.clntport", FT_UINT16,
1119 BASE_DEC, NULL, 0x0, NULL, HFILL
1122 { &hf_msproxy_server_ext_addr,
1123 { "Server External Address", "msproxy.server_ext_addr", FT_IPv4, BASE_NONE, NULL,
1124 0x0, NULL, HFILL
1128 { &hf_msproxy_server_ext_port,
1129 { "Server External Port", "msproxy.server_ext_port", FT_UINT16,
1130 BASE_DEC, NULL, 0x0, NULL, HFILL
1134 { &hf_msproxy_server_int_addr,
1135 { "Server Internal Address", "msproxy.server_int_addr", FT_IPv4, BASE_NONE, NULL,
1136 0x0, NULL, HFILL
1140 { &hf_msproxy_server_int_port,
1141 { "Server Internal Port", "msproxy.server_int_port", FT_UINT16,
1142 BASE_DEC, NULL, 0x0, NULL, HFILL
1145 { &hf_msproxy_serverport,
1146 { "Server Port", "msproxy.serverport", FT_UINT16,
1147 BASE_DEC, NULL, 0x0, NULL, HFILL
1150 { &hf_msproxy_bindport,
1151 { "Bind Port", "msproxy.bindport", FT_UINT16,
1152 BASE_DEC, NULL, 0x0, NULL, HFILL
1155 { &hf_msproxy_boundport,
1156 { "Bound Port", "msproxy.boundport", FT_UINT16,
1157 BASE_DEC, NULL, 0x0, NULL, HFILL
1160 { &hf_msproxy_serveraddr,
1161 { "Server Address", "msproxy.serveraddr", FT_IPv4, BASE_NONE, NULL,
1162 0x0, NULL, HFILL
1165 { &hf_msproxy_bindaddr,
1166 { "Destination", "msproxy.bindaddr", FT_IPv4, BASE_NONE, NULL,
1167 0x0, NULL, HFILL
1170 { &hf_msproxy_bind_id,
1171 { "Bound Port Id", "msproxy.bindid", FT_UINT32,
1172 BASE_HEX, NULL, 0x0, NULL, HFILL
1175 { &hf_msproxy_resolvaddr,
1176 { "Address", "msproxy.resolvaddr", FT_IPv4, BASE_NONE, NULL,
1177 0x0, NULL, HFILL
1180 { &hf_msproxy_client_id,
1181 { "Client Id", "msproxy.client_id", FT_UINT32,
1182 BASE_HEX, NULL, 0x0, NULL, HFILL
1185 { &hf_msproxy_version,
1186 { "Version", "msproxy.version", FT_UINT32,
1187 BASE_HEX, NULL, 0x0, NULL, HFILL
1190 { &hf_msproxy_server_id,
1191 { "Server id", "msproxy.server_id", FT_UINT32,
1192 BASE_HEX, NULL, 0x0, NULL, HFILL
1195 { &hf_msproxy_server_ack,
1196 { "Server ack", "msproxy.server_ack", FT_UINT8,
1197 BASE_DEC, NULL, 0x0, NULL, HFILL
1200 { &hf_msproxy_client_ack,
1201 { "Client ack", "msproxy.client_ack", FT_UINT8,
1202 BASE_DEC, NULL, 0x0, NULL, HFILL
1205 { &hf_msproxy_seq_num,
1206 { "Sequence Number", "msproxy.seq_num", FT_UINT8,
1207 BASE_DEC, NULL, 0x0, NULL, HFILL
1210 { &hf_msproxy_rwsp_signature,
1211 { "RWSP signature", "msproxy.rwsp_signature", FT_STRING, BASE_NONE, NULL,
1212 0x0, NULL, HFILL
1215 { &hf_msproxy_ntlmssp_signature,
1216 { "NTLMSSP signature", "msproxy.ntlmssp_signature", FT_STRING, BASE_NONE, NULL,
1217 0x0, NULL, HFILL
1221 /* Generated from convert_proto_tree_add_text.pl */
1222 { &hf_msproxy_application, { "Application", "msproxy.application", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1223 { &hf_msproxy_user_name, { "User name", "msproxy.user_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1224 { &hf_msproxy_application_name, { "Application name", "msproxy.application_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1225 { &hf_msproxy_client_computer_name, { "Client computer name", "msproxy.client_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1226 { &hf_msproxy_req_resolve_length, { "Length", "msproxy.req_resolve.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1227 { &hf_msproxy_host_name, { "Host Name", "msproxy.host_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1228 { &hf_msproxy_nt_domain, { "NT domain", "msproxy.nt_domain", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1229 { &hf_msproxy_address_offset, { "Address offset", "msproxy.address_offset", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1232 static ei_register_info ei[] = {
1233 { &ei_msproxy_unknown,
1234 { "msproxy.unknown", PI_UNDECODED, PI_WARN, "No know information (help wanted)", EXPFILL }},
1235 { &ei_msproxy_unhandled,
1236 { "msproxy.command.unhandled", PI_UNDECODED, PI_WARN, "Unhandled response command (report this, please)", EXPFILL }},
1239 expert_module_t* expert_msproxy;
1241 proto_msproxy = proto_register_protocol( "MS Proxy Protocol", "MS Proxy", "msproxy");
1243 proto_register_field_array(proto_msproxy, hf, array_length(hf));
1244 proto_register_subtree_array(ett, array_length(ett));
1245 expert_msproxy = expert_register_protocol(proto_msproxy);
1246 expert_register_field_array(expert_msproxy, ei, array_length(ei));
1248 msproxy_sub_handle = register_dissector("msproxy", msproxy_sub_dissector,
1249 proto_msproxy);
1253 void
1254 proto_reg_handoff_msproxy(void) {
1256 /* dissector install routine */
1258 dissector_handle_t msproxy_handle;
1260 msproxy_handle = create_dissector_handle(dissect_msproxy, proto_msproxy);
1261 dissector_add_uint_with_preference("udp.port", UDP_PORT_MSPROXY, msproxy_handle);
1265 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1267 * Local variables:
1268 * c-basic-offset: 8
1269 * tab-width: 8
1270 * indent-tabs-mode: t
1271 * End:
1273 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1274 * :indentSize=8:tabSize=8:noTabs=false: