/src/wireshark/epan/dissectors/packet-ms-nns.c
Line | Count | Source |
1 | | /* packet-ms-nns.c |
2 | | * Routines for .NET NegotiateStream Protocol (MS-NNS) dissection |
3 | | * Copyright 2020, Uli Heilmeier <uh@heilmeier.eu> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wieshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | /* |
13 | | * Basic dissector for .NET NegotiateStream Protocol based on protocol reference found at |
14 | | * https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-NNS/%5bMS-NNS%5d.pdf |
15 | | */ |
16 | | |
17 | | #include <config.h> |
18 | | |
19 | | #include <epan/packet.h> |
20 | | #include <epan/conversation.h> |
21 | | |
22 | | /* Prototypes */ |
23 | | void proto_reg_handoff_nns(void); |
24 | | void proto_register_nns(void); |
25 | | |
26 | | static dissector_handle_t gssapi_handle; |
27 | | |
28 | | |
29 | 0 | #define MS_NNS_MESSAGE_HANDSHAKE_DONE 20 |
30 | | #define MS_NNS_MESSAGE_HANDSHAKE_ERROR 21 |
31 | 0 | #define MS_NNS_MESSAGE_HANDSHAKE_PROGRESS 22 |
32 | | |
33 | | static const value_string nns_message_id_vals[] = { |
34 | | { MS_NNS_MESSAGE_HANDSHAKE_DONE, "Handshake Done" }, |
35 | | { MS_NNS_MESSAGE_HANDSHAKE_ERROR, "Handshake Error" }, |
36 | | { MS_NNS_MESSAGE_HANDSHAKE_PROGRESS, "Handshake In Progress" }, |
37 | | { 0, NULL} |
38 | | }; |
39 | | |
40 | | struct nns_session_state { |
41 | | uint32_t handshake_done; |
42 | | bool first_handshake_done; |
43 | | }; |
44 | | |
45 | | static int proto_nns; |
46 | | static int hf_nns_message_id; |
47 | | static int hf_nns_major_version; |
48 | | static int hf_nns_minor_version; |
49 | | static int hf_nns_auth_payload_size; |
50 | | static int hf_nns_auth_payload; |
51 | | static int hf_nns_payload_size; |
52 | | static int hf_nns_payload; |
53 | | |
54 | | static int ett_nns; |
55 | | static int ett_nns_payload; |
56 | | |
57 | 0 | #define MS_NNS_MIN_LENGTH 4 |
58 | | |
59 | | static int |
60 | | dissect_nns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
61 | 0 | { |
62 | 0 | proto_item *ti, *pti; |
63 | 0 | proto_tree *nns_tree, *payload_tree; |
64 | 0 | unsigned offset = 0; |
65 | 0 | uint32_t message_id; |
66 | 0 | uint32_t payload_size; |
67 | 0 | conversation_t *conversation; |
68 | 0 | tvbuff_t *nt_tvb; |
69 | 0 | int remaining; |
70 | 0 | struct nns_session_state *session_state; |
71 | |
|
72 | 0 | if (tvb_reported_length(tvb) < MS_NNS_MIN_LENGTH) |
73 | 0 | return 0; |
74 | | |
75 | 0 | conversation = find_or_create_conversation(pinfo); |
76 | |
|
77 | 0 | session_state = (struct nns_session_state *)conversation_get_proto_data(conversation, proto_nns); |
78 | 0 | if (!session_state) { |
79 | 0 | session_state = wmem_new0(wmem_file_scope(), struct nns_session_state); |
80 | 0 | conversation_add_proto_data(conversation, proto_nns, session_state); |
81 | 0 | } |
82 | |
|
83 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS-NNS"); |
84 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
85 | |
|
86 | 0 | ti = proto_tree_add_item(tree, proto_nns, tvb, 0, -1, ENC_NA); |
87 | |
|
88 | 0 | nns_tree = proto_item_add_subtree(ti, ett_nns); |
89 | | |
90 | | /* As it is unknown if there is a one-way Handshake Done or a two-way Handshake Done we check the first frame |
91 | | * after the first Handshake Done if it looks like a Handshake Done message (0x140100). */ |
92 | |
|
93 | 0 | if ( session_state->handshake_done && session_state->handshake_done < pinfo->num && |
94 | 0 | !(session_state->first_handshake_done && tvb_get_ntoh24(tvb, offset) == 0x140100)) { |
95 | 0 | proto_tree_add_item_ret_uint(nns_tree, hf_nns_payload_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &payload_size); |
96 | 0 | offset += 4; |
97 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Data"); |
98 | 0 | if ( payload_size > 0) { |
99 | 0 | remaining = tvb_reported_length_remaining(tvb, offset); |
100 | 0 | if ((uint32_t) remaining < payload_size) { |
101 | 0 | pinfo->desegment_offset = offset - 4; |
102 | 0 | pinfo->desegment_len = payload_size - remaining; |
103 | 0 | return (offset - 4); |
104 | 0 | } |
105 | 0 | proto_tree_add_item(nns_tree, hf_nns_payload, tvb, offset, payload_size, ENC_NA); |
106 | 0 | offset += payload_size; |
107 | 0 | session_state->first_handshake_done = false; |
108 | 0 | } |
109 | 0 | } |
110 | 0 | else { |
111 | 0 | proto_tree_add_item_ret_uint(nns_tree, hf_nns_message_id, tvb, offset, 1, ENC_NA, &message_id); |
112 | 0 | offset += 1; |
113 | 0 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s", val_to_str_const(message_id, nns_message_id_vals, "Unknown Record")); |
114 | 0 | proto_tree_add_item(nns_tree, hf_nns_major_version, tvb, offset, 1, ENC_NA); |
115 | 0 | offset += 1; |
116 | 0 | proto_tree_add_item(nns_tree, hf_nns_minor_version, tvb, offset, 1, ENC_NA); |
117 | 0 | offset += 1; |
118 | 0 | proto_tree_add_item_ret_uint(nns_tree, hf_nns_auth_payload_size, tvb, offset, 2, ENC_BIG_ENDIAN, &payload_size); |
119 | 0 | offset += 2; |
120 | 0 | if ( payload_size > 0) { |
121 | 0 | if ((uint32_t) tvb_reported_length_remaining(tvb, offset) < payload_size) { |
122 | 0 | pinfo->desegment_offset = offset - 5; |
123 | 0 | pinfo->desegment_len = payload_size; |
124 | 0 | return (offset - 5); |
125 | 0 | } |
126 | 0 | pti = proto_tree_add_item(nns_tree, hf_nns_auth_payload, tvb, offset, payload_size, ENC_NA); |
127 | 0 | if (message_id == MS_NNS_MESSAGE_HANDSHAKE_DONE || message_id == MS_NNS_MESSAGE_HANDSHAKE_PROGRESS) { |
128 | 0 | nt_tvb = tvb_new_subset_length(tvb, offset, payload_size); |
129 | 0 | payload_tree = proto_item_add_subtree(pti, ett_nns_payload); |
130 | 0 | call_dissector(gssapi_handle, nt_tvb, pinfo, payload_tree); |
131 | 0 | } |
132 | 0 | offset += payload_size; |
133 | 0 | } |
134 | 0 | if ( message_id == MS_NNS_MESSAGE_HANDSHAKE_DONE) { |
135 | 0 | session_state->handshake_done = pinfo->num; |
136 | 0 | session_state->first_handshake_done = (session_state->first_handshake_done ? false : true); |
137 | 0 | } |
138 | 0 | } |
139 | 0 | return offset; |
140 | 0 | } |
141 | | |
142 | | void proto_register_nns(void) |
143 | 14 | { |
144 | 14 | static hf_register_info hf[] = { |
145 | 14 | { &hf_nns_message_id, |
146 | 14 | { "MessageID", "ms-nns.message_id", |
147 | 14 | FT_UINT8, BASE_DEC, VALS(nns_message_id_vals), 0x0, |
148 | 14 | NULL, HFILL } |
149 | 14 | }, |
150 | 14 | { &hf_nns_major_version, |
151 | 14 | { "Major Version", "ms-nns.major_version", |
152 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
153 | 14 | NULL, HFILL } |
154 | 14 | }, |
155 | 14 | { &hf_nns_minor_version, |
156 | 14 | { "Minor Version", "ms-nns.minor_version", |
157 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
158 | 14 | NULL, HFILL } |
159 | 14 | }, |
160 | 14 | { &hf_nns_auth_payload_size, |
161 | 14 | { "Auth Payload Size", "ms-nns.auth_payload_size", |
162 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
163 | 14 | NULL, HFILL } |
164 | 14 | }, |
165 | 14 | { &hf_nns_auth_payload, |
166 | 14 | { "Auth Payload", "ms-nns.known_encoding", |
167 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
168 | 14 | NULL, HFILL } |
169 | 14 | }, |
170 | 14 | { &hf_nns_payload_size, |
171 | 14 | { "Payload Size", "ms-nns.payload_size", |
172 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
173 | 14 | NULL, HFILL } |
174 | 14 | }, |
175 | 14 | { &hf_nns_payload, |
176 | 14 | { "Payload", "ms-nns.payload", |
177 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
178 | 14 | NULL, HFILL } |
179 | 14 | } |
180 | 14 | }; |
181 | | |
182 | 14 | static int *ett[] = { |
183 | 14 | &ett_nns, |
184 | 14 | &ett_nns_payload |
185 | 14 | }; |
186 | | |
187 | 14 | proto_nns = proto_register_protocol(".NET NegotiateStream Protocol", "MS-NNS", "ms-nns"); |
188 | 14 | proto_register_field_array(proto_nns, hf, array_length(hf)); |
189 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
190 | 14 | register_dissector("ms-nns", dissect_nns, proto_nns); |
191 | 14 | } |
192 | | |
193 | | void proto_reg_handoff_nns(void) |
194 | 14 | { |
195 | 14 | gssapi_handle = find_dissector("gssapi"); |
196 | 14 | } |
197 | | |
198 | | /* |
199 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
200 | | * |
201 | | * Local variables: |
202 | | * c-basic-offset: 4 |
203 | | * tab-width: 8 |
204 | | * indent-tabs-mode: nil |
205 | | * End: |
206 | | * |
207 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
208 | | * :indentSize=4:tabSize=8:noTabs=true: |
209 | | */ |