Don't pass ep_alloc()'ed strings to col_set_str().
[metze/wireshark/wip.git] / asn1 / pkixcmp / packet-cmp-template.c
1 /* packet-cmp.c
2  *
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
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <glib.h>
34 #include <epan/packet.h>
35
36 #include <stdio.h>
37 #include <string.h>
38
39 #include <epan/oids.h>
40 #include <epan/asn1.h>
41 #include "packet-ber.h"
42 #include "packet-cmp.h"
43 #include "packet-crmf.h"
44 #include "packet-pkix1explicit.h"
45 #include "packet-pkix1implicit.h"
46 #include "packet-tcp.h"
47 #include "packet-http.h"
48 #include <epan/prefs.h>
49 #include <epan/nstime.h>
50
51 #define PNAME  "Certificate Management Protocol"
52 #define PSNAME "CMP"
53 #define PFNAME "cmp"
54
55 #define TCP_PORT_CMP 829
56
57 /* desegmentation of CMP over TCP */
58 static gboolean cmp_desegment = TRUE;
59
60 static guint cmp_alternate_tcp_port = 0;
61 static guint cmp_alternate_http_port = 0;
62 static guint cmp_alternate_tcp_style_http_port = 0;
63
64 /* Initialize the protocol and registered fields */
65 int proto_cmp = -1;
66 static int hf_cmp_type_oid = -1;
67 static int hf_cmp_tcptrans_len = -1;
68 static int hf_cmp_tcptrans_type = -1;
69 static int hf_cmp_tcptrans_poll_ref = -1;
70 static int hf_cmp_tcptrans_next_poll_ref = -1;
71 static int hf_cmp_tcptrans_ttcb = -1;
72 static int hf_cmp_tcptrans10_version = -1;
73 static int hf_cmp_tcptrans10_flags = -1;
74 #include "packet-cmp-hf.c"
75
76 /* Initialize the subtree pointers */
77 static gint ett_cmp = -1;
78 #include "packet-cmp-ett.c"
79
80 static const char *object_identifier_id;
81
82
83 #include "packet-cmp-fn.c"
84
85 static int
86 dissect_cmp_pdu(tvbuff_t *tvb, proto_tree *tree, asn1_ctx_t *actx)
87 {
88         return dissect_cmp_PKIMessage(FALSE, tvb, 0, actx,tree, -1);
89 }
90
91 #define CMP_TYPE_PKIMSG         0
92 #define CMP_TYPE_POLLREP        1
93 #define CMP_TYPE_POLLREQ        2
94 #define CMP_TYPE_NEGPOLLREP     3
95 #define CMP_TYPE_PARTIALMSGREP  4
96 #define CMP_TYPE_FINALMSGREP    5
97 #define CMP_TYPE_ERRORMSGREP    6
98 static const value_string cmp_pdu_types[] = {
99         { CMP_TYPE_PKIMSG,              "pkiMsg" },
100         { CMP_TYPE_POLLREP,             "pollRep" },
101         { CMP_TYPE_POLLREQ,             "pollReq" },
102         { CMP_TYPE_NEGPOLLREP,          "negPollRep" },
103         { CMP_TYPE_PARTIALMSGREP,       "partialMsgRep" },
104         { CMP_TYPE_FINALMSGREP,         "finalMsgRep" },
105         { CMP_TYPE_ERRORMSGREP,         "errorMsgRep" },
106         { 0, NULL },
107 };
108
109
110 static int dissect_cmp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
111 {
112         tvbuff_t   *next_tvb;
113         guint32    pdu_len;
114         guint8     pdu_type;
115         nstime_t   ts;
116         proto_item *item=NULL;
117         proto_item *ti=NULL;
118         proto_tree *tree=NULL;
119         proto_tree *tcptrans_tree=NULL;
120         asn1_ctx_t asn1_ctx;
121         int offset=0;
122
123         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
124
125         col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMP");
126
127         if (check_col(pinfo->cinfo, COL_INFO)) {
128                 col_clear(pinfo->cinfo, COL_INFO);
129
130                 col_set_str(pinfo->cinfo, COL_INFO, "PKIXCMP");
131         }
132
133         if(parent_tree){
134                 item=proto_tree_add_item(parent_tree, proto_cmp, tvb, 0, -1, FALSE);
135                 tree = proto_item_add_subtree(item, ett_cmp);
136         }
137
138         pdu_len=tvb_get_ntohl(tvb, 0);
139         pdu_type=tvb_get_guint8(tvb, 4);
140
141         if (pdu_type < 10) {
142                 /* RFC2510 TCP transport */
143                 ti = proto_tree_add_item(tree, proto_cmp, tvb, offset, 5, FALSE);
144                 tcptrans_tree = proto_item_add_subtree(ti, ett_cmp);
145                 proto_tree_add_item(tree, hf_cmp_tcptrans_len, tvb, offset, 4, FALSE);
146                 offset += 4;
147                 proto_tree_add_item(tree, hf_cmp_tcptrans_type, tvb, offset++, 1, FALSE);
148         } else {
149                 /* post RFC2510 TCP transport - the former "type" field is now "version" */
150                 ti = proto_tree_add_text(tree, tvb, offset, 7, "TCP transport");
151                 tcptrans_tree = proto_item_add_subtree(ti, ett_cmp);
152                 pdu_type=tvb_get_guint8(tvb, 6);
153                 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_len, tvb, offset, 4, FALSE);
154                 offset += 4;
155                 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans10_version, tvb, offset++, 1, FALSE);
156                 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans10_flags, tvb, offset++, 1, FALSE);
157                 proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_type, tvb, offset++, 1, FALSE);
158         }
159
160         if (check_col (pinfo->cinfo, COL_INFO)) {
161                 col_add_fstr (pinfo->cinfo, COL_INFO, val_to_str (pdu_type, cmp_pdu_types, "0x%x"));
162         }
163
164         switch(pdu_type){
165                 case CMP_TYPE_PKIMSG:
166                         next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), pdu_len);
167                         dissect_cmp_pdu(next_tvb, tree, &asn1_ctx);
168                         offset += tvb_length_remaining(tvb, offset);
169                         break;
170                 case CMP_TYPE_POLLREP:
171                         proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_poll_ref, tvb, offset, 4, FALSE);
172                         offset += 4;
173
174                         ts.secs = tvb_get_ntohl(tvb, 4);
175                         ts.nsecs = 0;
176                         proto_tree_add_time(tcptrans_tree, hf_cmp_tcptrans_ttcb, tvb, offset, 4, &ts);
177                         offset += 4;
178                         break;
179                 case CMP_TYPE_POLLREQ:
180                         proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_poll_ref, tvb, offset, 4, FALSE);
181                         offset += 4;
182                         break;
183                 case CMP_TYPE_NEGPOLLREP:
184                         break;
185                 case CMP_TYPE_PARTIALMSGREP:
186                         proto_tree_add_item(tcptrans_tree, hf_cmp_tcptrans_next_poll_ref, tvb, offset, 4, FALSE);
187                         offset += 4;
188
189                         ts.secs = tvb_get_ntohl(tvb, 4);
190                         ts.nsecs = 0;
191                         proto_tree_add_time(tcptrans_tree, hf_cmp_tcptrans_ttcb, tvb, offset, 4, &ts);
192                         offset += 4;
193
194                         next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), pdu_len);
195                         dissect_cmp_pdu(next_tvb, tree, &asn1_ctx);
196                         offset += tvb_length_remaining(tvb, offset);
197                         break;
198                 case CMP_TYPE_FINALMSGREP:
199                         next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), pdu_len);
200                         dissect_cmp_pdu(next_tvb, tree, &asn1_ctx);
201                         offset += tvb_length_remaining(tvb, offset);
202                         break;
203                 case CMP_TYPE_ERRORMSGREP:
204                         /*XXX to be added*/
205                         break;
206         }
207
208         return offset;
209 }
210
211 static void dissect_cmp_tcp_pdu_no_return(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
212 {
213         dissect_cmp_tcp_pdu(tvb, pinfo, parent_tree);
214 }
215
216 static guint get_cmp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
217 {
218         guint32 plen;
219
220         /*
221          * Get the length of the CMP-over-TCP packet.
222          */
223         plen = tvb_get_ntohl(tvb, offset);
224
225         return plen+4;
226 }
227
228
229 /* CMP over TCP: RFC2510 section 5.2 and "Transport Protocols for CMP" draft */
230         static int
231 dissect_cmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
232 {
233         guint32 pdu_len;
234         guint8 pdu_type;
235         int offset=4; /* RFC2510 TCP transport header length */
236
237         /* only attempt to dissect it as CMP over TCP if we have
238          * at least 5 bytes.
239          */
240         if (!tvb_bytes_exist(tvb, 0, 5)) {
241                 return 0;
242         }
243
244         pdu_len=tvb_get_ntohl(tvb, 0);
245         pdu_type=tvb_get_guint8(tvb, 4);
246
247         if(pdu_type == 10) {
248                 /* post RFC2510 TCP transport */
249                 pdu_type = tvb_get_guint8(tvb, 7);
250                 offset = 7; /* post RFC2510 TCP transport header length */
251                 /* arbitrary limit: assume a CMP over TCP pdu is never >10000 bytes
252                  * in size.
253                  * It is definitely at least 3 byte for post RFC2510 TCP transport
254                  */
255                 if((pdu_len<=2)||(pdu_len>10000)){
256                         return 0;
257                 }
258         } else {
259                 /* RFC2510 TCP transport */
260                 /* type is between 0 and 6 */
261                 if(pdu_type>6){
262                         return 0;
263                 }
264                 /* arbitrary limit: assume a CMP over TCP pdu is never >10000 bytes
265                  * in size.
266                  * It is definitely at least 1 byte to accomodate the flags byte
267                  */
268                 if((pdu_len<=0)||(pdu_len>10000)){
269                         return 0;
270                 }
271         }
272
273         /* type 0 contains a PKI message and must therefore be >= 3 bytes
274          * long (flags + BER TAG + BER LENGTH
275          */
276         if((pdu_type==0)&&(pdu_len<3)){
277                 return 0;
278         }
279
280         tcp_dissect_pdus(tvb, pinfo, parent_tree, cmp_desegment, offset, get_cmp_pdu_len,
281                         dissect_cmp_tcp_pdu_no_return);
282
283         return tvb_length(tvb);
284 }
285
286
287         static int
288 dissect_cmp_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
289 {
290         proto_item *item=NULL;
291         proto_tree *tree=NULL;
292         asn1_ctx_t asn1_ctx;
293
294         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
295
296         col_set_str(pinfo->cinfo, COL_PROTOCOL, "CMP");
297
298         if (check_col(pinfo->cinfo, COL_INFO)) {
299                 col_clear(pinfo->cinfo, COL_INFO);
300                 col_set_str(pinfo->cinfo, COL_INFO, "PKIXCMP");
301         }
302
303         if(parent_tree){
304                 item=proto_tree_add_item(parent_tree, proto_cmp, tvb, 0, -1, FALSE);
305                 tree = proto_item_add_subtree(item, ett_cmp);
306         }
307
308         return dissect_cmp_pdu(tvb, tree, &asn1_ctx);
309 }
310
311
312 /*--- proto_register_cmp ----------------------------------------------*/
313 void proto_register_cmp(void) {
314
315         /* List of fields */
316         static hf_register_info hf[] = {
317                 { &hf_cmp_type_oid,
318                         { "InfoType", "cmp.type.oid",
319                                 FT_STRING, BASE_NONE, NULL, 0,
320                                 "Type of InfoTypeAndValue", HFILL }},
321                 { &hf_cmp_tcptrans_len,
322                         { "Length", "cmp.tcptrans.length",
323                                 FT_UINT32, BASE_DEC, NULL, 0,
324                                 "TCP transport Length of PDU in bytes", HFILL }},
325                 { &hf_cmp_tcptrans_type,
326                         { "Type", "cmp.tcptrans.type",
327                                 FT_UINT8, BASE_DEC, VALS(cmp_pdu_types), 0,
328                                 "TCP transport PDU Type", HFILL }},
329                 { &hf_cmp_tcptrans_poll_ref,
330                         { "Polling Reference", "cmp.tcptrans.poll_ref",
331                                 FT_UINT32, BASE_HEX, NULL, 0,
332                                 "TCP transport Polling Reference", HFILL }},
333                 { &hf_cmp_tcptrans_next_poll_ref,
334                         { "Next Polling Reference", "cmp.tcptrans.next_poll_ref",
335                                 FT_UINT32, BASE_HEX, NULL, 0,
336                                 "TCP transport Next Polling Reference", HFILL }},
337                 { &hf_cmp_tcptrans_ttcb,
338                         { "Time to check Back", "cmp.tcptrans.ttcb",
339                                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
340                                 "TCP transport Time to check Back", HFILL }},
341                 { &hf_cmp_tcptrans10_version,
342                         { "Version", "cmp.tcptrans10.version",
343                                 FT_UINT8, BASE_DEC, NULL, 0,
344                                 "TCP transport version", HFILL }},
345                 { &hf_cmp_tcptrans10_flags,
346                         { "Flags", "cmp.tcptrans10.flags",
347                                 FT_UINT8, BASE_DEC, NULL, 0,
348                                 "TCP transport flags", HFILL }},
349 #include "packet-cmp-hfarr.c"
350         };
351
352         /* List of subtrees */
353         static gint *ett[] = {
354                 &ett_cmp,
355 #include "packet-cmp-ettarr.c"
356         };
357         module_t *cmp_module;
358
359         /* Register protocol */
360         proto_cmp = proto_register_protocol(PNAME, PSNAME, PFNAME);
361
362         /* Register fields and subtrees */
363         proto_register_field_array(proto_cmp, hf, array_length(hf));
364         proto_register_subtree_array(ett, array_length(ett));
365
366         cmp_module = prefs_register_protocol(proto_cmp, proto_reg_handoff_cmp);
367         prefs_register_bool_preference(cmp_module, "desegment",
368                         "Reassemble CMP-over-TCP messages spanning multiple TCP segments",
369                         "Whether the CMP-over-TCP dissector should reassemble messages spanning multiple TCP segments. "
370                         "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
371                         &cmp_desegment);
372
373         prefs_register_uint_preference(cmp_module, "tcp_alternate_port",
374                         "Alternate TCP port",
375                         "Decode this TCP port\'s traffic as CMP. Set to \"0\" to disable.",
376                         10,
377                         &cmp_alternate_tcp_port);
378
379         prefs_register_uint_preference(cmp_module, "http_alternate_port",
380                         "Alternate HTTP port",
381                         "Decode this TCP port\'s traffic as CMP-over-HTTP. Set to \"0\" to disable. "
382                         "Use this if the Content-Type is not set correctly.",
383                         10,
384                         &cmp_alternate_http_port);
385
386         prefs_register_uint_preference(cmp_module, "tcp_style_http_alternate_port",
387                         "Alternate TCP-style-HTTP port",
388                         "Decode this TCP port\'s traffic as TCP-transport-style CMP-over-HTTP. Set to \"0\" to disable. "
389                         "Use this if the Content-Type is not set correctly.",
390                         10,
391                         &cmp_alternate_tcp_style_http_port);
392 }
393
394
395 /*--- proto_reg_handoff_cmp -------------------------------------------*/
396 void proto_reg_handoff_cmp(void) {
397         static gboolean inited = FALSE;
398         static dissector_handle_t cmp_http_handle;
399         static dissector_handle_t cmp_tcp_style_http_handle;
400         static dissector_handle_t cmp_tcp_handle;
401         static guint cmp_alternate_tcp_port_prev = 0;
402         static guint cmp_alternate_http_port_prev = 0;
403         static guint cmp_alternate_tcp_style_http_port_prev = 0;
404
405         if (!inited) {
406                 cmp_http_handle = new_create_dissector_handle(dissect_cmp_http, proto_cmp);
407                 dissector_add_string("media_type", "application/pkixcmp", cmp_http_handle);
408                 dissector_add_string("media_type", "application/x-pkixcmp", cmp_http_handle);
409
410                 cmp_tcp_style_http_handle = new_create_dissector_handle(dissect_cmp_tcp_pdu, proto_cmp);
411                 dissector_add_string("media_type", "application/pkixcmp-poll", cmp_tcp_style_http_handle);
412                 dissector_add_string("media_type", "application/x-pkixcmp-poll", cmp_tcp_style_http_handle);
413
414                 cmp_tcp_handle = new_create_dissector_handle(dissect_cmp_tcp, proto_cmp);
415                 dissector_add("tcp.port", TCP_PORT_CMP, cmp_tcp_handle);
416
417                 oid_add_from_string("Cryptlib-presence-check","1.3.6.1.4.1.3029.3.1.1");
418                 oid_add_from_string("Cryptlib-PKIBoot","1.3.6.1.4.1.3029.3.1.2");
419
420                 oid_add_from_string("HMAC MD5","1.3.6.1.5.5.8.1.1");
421                 oid_add_from_string("HMAC SHA-1","1.3.6.1.5.5.8.1.2");
422                 oid_add_from_string("HMAC TIGER","1.3.6.1.5.5.8.1.3");
423                 oid_add_from_string("HMAC RIPEMD-160","1.3.6.1.5.5.8.1.4");
424
425                 oid_add_from_string("sha256WithRSAEncryption","1.2.840.113549.1.1.11");
426
427 #include "packet-cmp-dis-tab.c"
428                 inited = TRUE;
429         }
430
431         /* change alternate TCP port if changed in the preferences */
432         if (cmp_alternate_tcp_port != cmp_alternate_tcp_port_prev) {
433                 if (cmp_alternate_tcp_port_prev != 0)
434                         dissector_delete("tcp.port", cmp_alternate_tcp_port_prev, cmp_tcp_handle);
435                 if (cmp_alternate_tcp_port != 0)
436                         dissector_add("tcp.port", cmp_alternate_tcp_port, cmp_tcp_handle);
437                 cmp_alternate_tcp_port_prev = cmp_alternate_tcp_port;
438         }
439
440         /* change alternate HTTP port if changed in the preferences */
441         if (cmp_alternate_http_port != cmp_alternate_http_port_prev) {
442                 if (cmp_alternate_http_port_prev != 0) {
443                         dissector_delete("tcp.port", cmp_alternate_http_port_prev, NULL);
444                         dissector_delete("http.port", cmp_alternate_http_port_prev, NULL);
445                 }
446                 if (cmp_alternate_http_port != 0)
447                         http_dissector_add( cmp_alternate_http_port, cmp_http_handle);
448                 cmp_alternate_http_port_prev = cmp_alternate_http_port;
449         }
450
451         /* change alternate TCP-style-HTTP port if changed in the preferences */
452         if (cmp_alternate_tcp_style_http_port != cmp_alternate_tcp_style_http_port_prev) {
453                 if (cmp_alternate_tcp_style_http_port_prev != 0) {
454                         dissector_delete("tcp.port", cmp_alternate_tcp_style_http_port_prev, NULL);
455                         dissector_delete("http.port", cmp_alternate_tcp_style_http_port_prev, NULL);
456                 }
457                 if (cmp_alternate_tcp_style_http_port != 0)
458                         http_dissector_add( cmp_alternate_tcp_style_http_port, cmp_tcp_style_http_handle);
459                 cmp_alternate_tcp_style_http_port_prev = cmp_alternate_tcp_style_http_port;
460         }
461
462 }
463