Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / asn1 / cmp / packet-cmp-template.c
blobfc32893d10ef999e6f30366276200bc36c055c25
1 /* packet-cmp.c
3 * Routines for RFC2510 Certificate Management Protocol packet dissection
4 * Ronnie Sahlberg 2004
5 * Updated to RFC4210 CMPv2 and associated "Transport Protocols for CMP" draft
6 * Martin Peylo 2008
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
19 #include <epan/oids.h>
20 #include <epan/asn1.h>
21 #include <epan/proto_data.h>
22 #include <wsutil/array.h>
23 #include "packet-ber.h"
24 #include "packet-cmp.h"
25 #include "packet-crmf.h"
26 #include "packet-pkix1explicit.h"
27 #include "packet-pkix1implicit.h"
28 #include "packet-pkcs10.h"
29 #include "packet-tcp.h"
30 #include "packet-http.h"
31 #include <epan/prefs.h>
33 #define PNAME "Certificate Management Protocol"
34 #define PSNAME "CMP"
35 #define PFNAME "cmp"
37 #define TCP_PORT_CMP 829
39 void proto_register_cmp(void);
41 static dissector_handle_t cmp_http_handle;
42 static dissector_handle_t cmp_tcp_style_http_handle;
43 static dissector_handle_t cmp_tcp_handle;
45 /* desegmentation of CMP over TCP */
46 static bool cmp_desegment = true;
48 static unsigned cmp_alternate_http_port;
49 static unsigned cmp_alternate_tcp_style_http_port;
51 /* Initialize the protocol and registered fields */
52 static int proto_cmp;
53 static int hf_cmp_type_oid;
54 static int hf_cmp_tcptrans_len;
55 static int hf_cmp_tcptrans_type;
56 static int hf_cmp_tcptrans_poll_ref;
57 static int hf_cmp_tcptrans_next_poll_ref;
58 static int hf_cmp_tcptrans_ttcb;
59 static int hf_cmp_tcptrans10_version;
60 static int hf_cmp_tcptrans10_flags;
61 #include "packet-cmp-hf.c"
63 /* Initialize the subtree pointers */
64 static int ett_cmp;
65 #include "packet-cmp-ett.c"
66 #include "packet-cmp-fn.c"
68 static int
69 dissect_cmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
71 asn1_ctx_t asn1_ctx;
72 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
74 return dissect_cmp_PKIMessage(false, tvb, 0, &asn1_ctx, tree, -1);
77 #define CMP_TYPE_PKIMSG 0
78 #define CMP_TYPE_POLLREP 1
79 #define CMP_TYPE_POLLREQ 2
80 #define CMP_TYPE_NEGPOLLREP 3
81 #define CMP_TYPE_PARTIALMSGREP 4
82 #define CMP_TYPE_FINALMSGREP 5
83 #define CMP_TYPE_ERRORMSGREP 6
84 static const value_string cmp_pdu_types[] = {
85 { CMP_TYPE_PKIMSG, "pkiMsg" },
86 { CMP_TYPE_POLLREP, "pollRep" },
87 { CMP_TYPE_POLLREQ, "pollReq" },
88 { CMP_TYPE_NEGPOLLREP, "negPollRep" },
89 { CMP_TYPE_PARTIALMSGREP, "partialMsgRep" },
90 { CMP_TYPE_FINALMSGREP, "finalMsgRep" },
91 { CMP_TYPE_ERRORMSGREP, "errorMsgRep" },
92 { 0, NULL },
96 static int dissect_cmp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
98 tvbuff_t *next_tvb;
99 uint32_t pdu_len;
100 uint8_t pdu_type;
101 proto_item *item=NULL;
102 proto_item *ti=NULL;
103 proto_tree *tree=NULL;
104 proto_tree *tcptrans_tree=NULL;
105 int offset=0;
107 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMP");
108 col_set_str(pinfo->cinfo, COL_INFO, "PKIXCMP");
110 if(parent_tree){
111 item=proto_tree_add_item(parent_tree, proto_cmp, tvb, 0, -1, ENC_NA);
112 tree = proto_item_add_subtree(item, ett_cmp);
115 pdu_len=tvb_get_ntohl(tvb, 0);
116 pdu_type=tvb_get_uint8(tvb, 4);
118 if (pdu_type < 10) {
119 /* RFC2510 TCP transport */
120 ti = proto_tree_add_item(tree, proto_cmp, tvb, offset, 5, ENC_NA);
121 tcptrans_tree = proto_item_add_subtree(ti, ett_cmp);
122 proto_tree_add_item(tree, hf_cmp_tcptrans_len, tvb, offset, 4, ENC_BIG_ENDIAN);
123 offset += 4;
124 proto_tree_add_item(tree, hf_cmp_tcptrans_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
125 } else {
126 /* post RFC2510 TCP transport - the former "type" field is now "version" */
127 tcptrans_tree = proto_tree_add_subtree(tree, tvb, offset, 7, ett_cmp, NULL, "TCP transport");
128 pdu_type=tvb_get_uint8(tvb, 6);
129 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_len, tvb, offset, 4, ENC_BIG_ENDIAN);
130 offset += 4;
131 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans10_version, tvb, offset++, 1, ENC_BIG_ENDIAN);
132 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans10_flags, tvb, offset++, 1, ENC_BIG_ENDIAN);
133 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
136 col_add_str (pinfo->cinfo, COL_INFO, val_to_str (pdu_type, cmp_pdu_types, "0x%x"));
138 switch(pdu_type){
139 case CMP_TYPE_PKIMSG:
140 next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_reported_length_remaining(tvb, offset), pdu_len);
141 dissect_cmp_pdu(next_tvb, pinfo, tree, NULL);
142 offset += tvb_reported_length_remaining(tvb, offset);
143 break;
144 case CMP_TYPE_POLLREP:
145 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_poll_ref, tvb, offset, 4, ENC_BIG_ENDIAN);
146 offset += 4;
148 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_ttcb, tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN);
149 offset += 4;
150 break;
151 case CMP_TYPE_POLLREQ:
152 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_poll_ref, tvb, offset, 4, ENC_BIG_ENDIAN);
153 offset += 4;
154 break;
155 case CMP_TYPE_NEGPOLLREP:
156 break;
157 case CMP_TYPE_PARTIALMSGREP:
158 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_next_poll_ref, tvb, offset, 4, ENC_BIG_ENDIAN);
159 offset += 4;
161 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_ttcb, tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN);
162 offset += 4;
164 next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_reported_length_remaining(tvb, offset), pdu_len);
165 dissect_cmp_pdu(next_tvb, pinfo, tree, NULL);
166 offset += tvb_reported_length_remaining(tvb, offset);
167 break;
168 case CMP_TYPE_FINALMSGREP:
169 next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_reported_length_remaining(tvb, offset), pdu_len);
170 dissect_cmp_pdu(next_tvb, pinfo, tree, NULL);
171 offset += tvb_reported_length_remaining(tvb, offset);
172 break;
173 case CMP_TYPE_ERRORMSGREP:
174 /*XXX to be added*/
175 break;
178 return offset;
181 static unsigned get_cmp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
182 int offset, void *data _U_)
184 uint32_t plen;
187 * Get the length of the CMP-over-TCP packet.
189 plen = tvb_get_ntohl(tvb, offset);
191 return plen+4;
195 /* CMP over TCP: RFC2510 section 5.2 and "Transport Protocols for CMP" draft */
196 static int
197 dissect_cmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data)
199 uint32_t pdu_len;
200 uint8_t pdu_type;
201 int offset=4; /* RFC2510 TCP transport header length */
203 /* only attempt to dissect it as CMP over TCP if we have
204 * at least 5 bytes.
206 if (!tvb_bytes_exist(tvb, 0, 5)) {
207 return 0;
210 pdu_len=tvb_get_ntohl(tvb, 0);
211 pdu_type=tvb_get_uint8(tvb, 4);
213 if(pdu_type == 10) {
214 /* post RFC2510 TCP transport */
215 pdu_type = tvb_get_uint8(tvb, 7);
216 offset = 7; /* post RFC2510 TCP transport header length */
217 /* arbitrary limit: assume a CMP over TCP pdu is never >10000 bytes
218 * in size.
219 * It is definitely at least 3 byte for post RFC2510 TCP transport
221 if((pdu_len<=2)||(pdu_len>10000)){
222 return 0;
224 } else {
225 /* RFC2510 TCP transport */
226 /* type is between 0 and 6 */
227 if(pdu_type>6){
228 return 0;
230 /* arbitrary limit: assume a CMP over TCP pdu is never >10000 bytes
231 * in size.
232 * It is definitely at least 1 byte to accommodate the flags byte
234 if((pdu_len<=0)||(pdu_len>10000)){
235 return 0;
239 /* type 0 contains a PKI message and must therefore be >= 3 bytes
240 * long (flags + BER TAG + BER LENGTH
242 if((pdu_type==0)&&(pdu_len<3)){
243 return 0;
246 tcp_dissect_pdus(tvb, pinfo, parent_tree, cmp_desegment, offset, get_cmp_pdu_len,
247 dissect_cmp_tcp_pdu, data);
249 return tvb_captured_length(tvb);
253 static int
254 dissect_cmp_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
256 proto_item *item=NULL;
257 proto_tree *tree=NULL;
259 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMP");
260 col_set_str(pinfo->cinfo, COL_INFO, "PKIXCMP");
262 if(parent_tree){
263 item=proto_tree_add_item(parent_tree, proto_cmp, tvb, 0, -1, ENC_NA);
264 tree = proto_item_add_subtree(item, ett_cmp);
267 return dissect_cmp_pdu(tvb, pinfo, tree, NULL);
271 /*--- proto_register_cmp ----------------------------------------------*/
272 void proto_register_cmp(void) {
274 /* List of fields */
275 static hf_register_info hf[] = {
276 { &hf_cmp_type_oid,
277 { "InfoType", "cmp.type.oid",
278 FT_STRING, BASE_NONE, NULL, 0,
279 "Type of InfoTypeAndValue", HFILL }},
280 { &hf_cmp_tcptrans_len,
281 { "Length", "cmp.tcptrans.length",
282 FT_UINT32, BASE_DEC, NULL, 0,
283 "TCP transport Length of PDU in bytes", HFILL }},
284 { &hf_cmp_tcptrans_type,
285 { "Type", "cmp.tcptrans.type",
286 FT_UINT8, BASE_DEC, VALS(cmp_pdu_types), 0,
287 "TCP transport PDU Type", HFILL }},
288 { &hf_cmp_tcptrans_poll_ref,
289 { "Polling Reference", "cmp.tcptrans.poll_ref",
290 FT_UINT32, BASE_HEX, NULL, 0,
291 "TCP transport Polling Reference", HFILL }},
292 { &hf_cmp_tcptrans_next_poll_ref,
293 { "Next Polling Reference", "cmp.tcptrans.next_poll_ref",
294 FT_UINT32, BASE_HEX, NULL, 0,
295 "TCP transport Next Polling Reference", HFILL }},
296 { &hf_cmp_tcptrans_ttcb,
297 { "Time to check Back", "cmp.tcptrans.ttcb",
298 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
299 "TCP transport Time to check Back", HFILL }},
300 { &hf_cmp_tcptrans10_version,
301 { "Version", "cmp.tcptrans10.version",
302 FT_UINT8, BASE_DEC, NULL, 0,
303 "TCP transport version", HFILL }},
304 { &hf_cmp_tcptrans10_flags,
305 { "Flags", "cmp.tcptrans10.flags",
306 FT_UINT8, BASE_DEC, NULL, 0,
307 "TCP transport flags", HFILL }},
308 #include "packet-cmp-hfarr.c"
311 /* List of subtrees */
312 static int *ett[] = {
313 &ett_cmp,
314 #include "packet-cmp-ettarr.c"
316 module_t *cmp_module;
318 /* Register protocol */
319 proto_cmp = proto_register_protocol(PNAME, PSNAME, PFNAME);
321 /* Register fields and subtrees */
322 proto_register_field_array(proto_cmp, hf, array_length(hf));
323 proto_register_subtree_array(ett, array_length(ett));
325 /* Register preferences */
326 cmp_module = prefs_register_protocol(proto_cmp, proto_reg_handoff_cmp);
327 prefs_register_bool_preference(cmp_module, "desegment",
328 "Reassemble CMP-over-TCP messages spanning multiple TCP segments",
329 "Whether the CMP-over-TCP dissector should reassemble messages spanning multiple TCP segments. "
330 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
331 &cmp_desegment);
333 prefs_register_uint_preference(cmp_module, "http_alternate_port",
334 "Alternate HTTP port",
335 "Decode this TCP port\'s traffic as CMP-over-HTTP. Set to \"0\" to disable. "
336 "Use this if the Content-Type is not set correctly.",
338 &cmp_alternate_http_port);
340 prefs_register_uint_preference(cmp_module, "tcp_style_http_alternate_port",
341 "Alternate TCP-style-HTTP port",
342 "Decode this TCP port\'s traffic as TCP-transport-style CMP-over-HTTP. Set to \"0\" to disable. "
343 "Use this if the Content-Type is not set correctly.",
345 &cmp_alternate_tcp_style_http_port);
347 /* Register dissectors */
348 cmp_http_handle = register_dissector("cmp.http", dissect_cmp_http, proto_cmp);
349 cmp_tcp_style_http_handle = register_dissector("cmp.tcp_pdu", dissect_cmp_tcp_pdu, proto_cmp);
350 cmp_tcp_handle = register_dissector("cmp", dissect_cmp_tcp, proto_cmp);
351 register_ber_syntax_dissector("PKIMessage", proto_cmp, dissect_cmp_pdu);
355 /*--- proto_reg_handoff_cmp -------------------------------------------*/
356 void proto_reg_handoff_cmp(void) {
357 static bool inited = false;
358 static unsigned cmp_alternate_http_port_prev = 0;
359 static unsigned cmp_alternate_tcp_style_http_port_prev = 0;
361 if (!inited) {
362 dissector_add_string("media_type", "application/pkixcmp", cmp_http_handle);
363 dissector_add_string("media_type", "application/x-pkixcmp", cmp_http_handle);
365 dissector_add_string("media_type", "application/pkixcmp-poll", cmp_tcp_style_http_handle);
366 dissector_add_string("media_type", "application/x-pkixcmp-poll", cmp_tcp_style_http_handle);
368 dissector_add_uint_with_preference("tcp.port", TCP_PORT_CMP, cmp_tcp_handle);
370 oid_add_from_string("Cryptlib-presence-check","1.3.6.1.4.1.3029.3.1.1");
371 oid_add_from_string("Cryptlib-PKIBoot","1.3.6.1.4.1.3029.3.1.2");
373 oid_add_from_string("HMAC MD5","1.3.6.1.5.5.8.1.1");
374 oid_add_from_string("HMAC SHA-1","1.3.6.1.5.5.8.1.2");
375 oid_add_from_string("HMAC TIGER","1.3.6.1.5.5.8.1.3");
376 oid_add_from_string("HMAC RIPEMD-160","1.3.6.1.5.5.8.1.4");
378 #include "packet-cmp-dis-tab.c"
379 inited = true;
382 /* change alternate HTTP port if changed in the preferences */
383 if (cmp_alternate_http_port != cmp_alternate_http_port_prev) {
384 if (cmp_alternate_http_port_prev != 0) {
385 http_tcp_dissector_delete(cmp_alternate_http_port_prev);
387 if (cmp_alternate_http_port != 0)
388 http_tcp_dissector_add( cmp_alternate_http_port, cmp_http_handle);
389 cmp_alternate_http_port_prev = cmp_alternate_http_port;
392 /* change alternate TCP-style-HTTP port if changed in the preferences */
393 if (cmp_alternate_tcp_style_http_port != cmp_alternate_tcp_style_http_port_prev) {
394 if (cmp_alternate_tcp_style_http_port_prev != 0) {
395 http_tcp_dissector_delete(cmp_alternate_tcp_style_http_port_prev);
397 if (cmp_alternate_tcp_style_http_port != 0)
398 http_tcp_dissector_add( cmp_alternate_tcp_style_http_port, cmp_tcp_style_http_handle);
399 cmp_alternate_tcp_style_http_port_prev = cmp_alternate_tcp_style_http_port;