- Forward declaration of register functions.
[metze/wireshark/wip.git] / asn1 / dop / packet-dop-template.c
1 /* packet-dop.c
2  * Routines for X.501 (DSA Operational Attributes)  packet dissection
3  * Graeme Lunt 2005
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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.
24  */
25
26 #include "config.h"
27
28 #include <glib.h>
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31 #include <epan/oids.h>
32 #include <epan/asn1.h>
33 #include <epan/expert.h>
34 #include <epan/wmem/wmem.h>
35
36 #include "packet-ber.h"
37 #include "packet-acse.h"
38 #include "packet-ros.h"
39
40 #include "packet-x509sat.h"
41 #include "packet-x509af.h"
42 #include "packet-x509if.h"
43 #include "packet-dap.h"
44 #include "packet-dsp.h"
45 #include "packet-crmf.h"
46
47
48 #include "packet-dop.h"
49
50 #define PNAME  "X.501 Directory Operational Binding Management Protocol"
51 #define PSNAME "DOP"
52 #define PFNAME "dop"
53
54 void proto_register_dop(void);
55 void proto_reg_handoff_dop(void);
56
57 static guint global_dop_tcp_port = 102;
58 static dissector_handle_t tpkt_handle;
59 static void prefs_register_dop(void); /* forward declaration for use in preferences registration */
60
61 /* Initialize the protocol and registered fields */
62 static int proto_dop = -1;
63
64 static const char *binding_type = NULL; /* binding_type */
65
66 static int call_dop_oid_callback(const char *base_string, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char *col_info, void* data);
67
68 #include "packet-dop-hf.c"
69
70 /* Initialize the subtree pointers */
71 static gint ett_dop = -1;
72 static gint ett_dop_unknown = -1;
73 #include "packet-dop-ett.c"
74
75 static expert_field ei_dop_unknown_binding_parameter = EI_INIT;
76
77 /* Dissector table */
78 static dissector_table_t dop_dissector_table;
79
80 static void append_oid(packet_info *pinfo, const char *oid)
81 {
82         const char *name = NULL;
83
84     name = oid_resolved_from_string(oid);
85     col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name ? name : oid);
86 }
87
88 #include "packet-dop-fn.c"
89
90 static int
91 call_dop_oid_callback(const char *base_string, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char *col_info, void* data)
92 {
93   char* binding_param;
94
95   binding_param = wmem_strdup_printf(wmem_packet_scope(), "%s.%s", base_string, binding_type ? binding_type : "");
96
97   col_append_fstr(pinfo->cinfo, COL_INFO, " %s", col_info);
98
99   if (dissector_try_string(dop_dissector_table, binding_param, tvb, pinfo, tree, data)) {
100      offset = tvb_reported_length (tvb);
101   } else {
102      proto_item *item=NULL;
103      proto_tree *next_tree=NULL;
104
105      item = proto_tree_add_text(tree, tvb, 0, tvb_length_remaining(tvb, offset), "Dissector for parameter %s OID:%s not implemented. Contact Wireshark developers if you want this supported", base_string, binding_type ? binding_type : "<empty>");
106      if (item) {
107         next_tree = proto_item_add_subtree(item, ett_dop_unknown);
108      }
109      offset = dissect_unknown_ber(pinfo, tvb, offset, next_tree);
110      expert_add_info(pinfo, item, &ei_dop_unknown_binding_parameter);
111    }
112
113    return offset;
114 }
115
116
117 /*
118 * Dissect DOP PDUs inside a ROS PDUs
119 */
120 static int
121 dissect_dop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
122 {
123         int offset = 0;
124         int old_offset;
125         proto_item *item;
126         proto_tree *tree;
127         struct SESSION_DATA_STRUCTURE* session;
128         int (*dop_dissector)(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_) = NULL;
129         const char *dop_op_name;
130         asn1_ctx_t asn1_ctx;
131
132         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
133
134         /* do we have operation information from the ROS dissector?  */
135         if( data == NULL ){
136                 if(parent_tree){
137                         proto_tree_add_text(parent_tree, tvb, offset, -1,
138                                 "Internal error: can't get operation information from ROS dissector.");
139                 }
140                 return  0;
141         }
142
143         session = ( (struct SESSION_DATA_STRUCTURE*)data );
144
145         item = proto_tree_add_item(parent_tree, proto_dop, tvb, 0, -1, ENC_NA);
146         tree = proto_item_add_subtree(item, ett_dop);
147
148         col_set_str(pinfo->cinfo, COL_PROTOCOL, "DOP");
149         col_clear(pinfo->cinfo, COL_INFO);
150
151         asn1_ctx.private_data = session;
152
153         switch(session->ros_op & ROS_OP_MASK) {
154         case (ROS_OP_BIND | ROS_OP_ARGUMENT):   /*  BindInvoke */
155           dop_dissector = dissect_dop_DSAOperationalManagementBindArgument;
156           dop_op_name = "DSA-Operational-Bind-Argument";
157           break;
158         case (ROS_OP_BIND | ROS_OP_RESULT):     /*  BindResult */
159           dop_dissector = dissect_dop_DSAOperationalManagementBindResult;
160           dop_op_name = "DSA-Operational-Bind-Result";
161           break;
162         case (ROS_OP_BIND | ROS_OP_ERROR):      /*  BindError */
163           dop_dissector = dissect_dop_DSAOperationalManagementBindError;
164           dop_op_name = "DSA-Operational-Management-Bind-Error";
165           break;
166         case (ROS_OP_INVOKE | ROS_OP_ARGUMENT): /*  Invoke Argument */
167           switch(session->ros_op & ROS_OP_OPCODE_MASK) {
168           case 100: /* establish */
169             dop_dissector = dissect_dop_EstablishOperationalBindingArgument;
170             dop_op_name = "Establish-Operational-Binding-Argument";
171             break;
172           case 101: /* terminate */
173             dop_dissector = dissect_dop_TerminateOperationalBindingArgument;
174             dop_op_name = "Terminate-Operational-Binding-Argument";
175             break;
176           case 102: /* modify */
177             dop_dissector = dissect_dop_ModifyOperationalBindingArgument;
178             dop_op_name = "Modify-Operational-Binding-Argument";
179             break;
180           default:
181             proto_tree_add_text(tree, tvb, offset, -1,"Unsupported DOP Argument opcode (%d)",
182                                 session->ros_op & ROS_OP_OPCODE_MASK);
183             break;
184           }
185           break;
186         case (ROS_OP_INVOKE | ROS_OP_RESULT):   /*  Return Result */
187           switch(session->ros_op & ROS_OP_OPCODE_MASK) {
188           case 100: /* establish */
189             dop_dissector = dissect_dop_EstablishOperationalBindingResult;
190             dop_op_name = "Establish-Operational-Binding-Result";
191             break;
192           case 101: /* terminate */
193             dop_dissector = dissect_dop_TerminateOperationalBindingResult;
194             dop_op_name = "Terminate-Operational-Binding-Result";
195             break;
196           case 102: /* modify */
197             dop_dissector = dissect_dop_ModifyOperationalBindingResult;
198             dop_op_name = "Modify-Operational-Binding-Result";
199             break;
200           default:
201             proto_tree_add_text(tree, tvb, offset, -1,"Unsupported DOP Result opcode (%d)",
202                                 session->ros_op & ROS_OP_OPCODE_MASK);
203             break;
204           }
205           break;
206         case (ROS_OP_INVOKE | ROS_OP_ERROR):    /*  Return Error */
207           switch(session->ros_op & ROS_OP_OPCODE_MASK) {
208           case 100: /* operational-binding */
209             dop_dissector = dissect_dop_OpBindingErrorParam;
210             dop_op_name = "Operational-Binding-Error";
211             break;
212           default:
213             proto_tree_add_text(tree, tvb, offset, -1,"Unsupported DOP Error opcode (%d)",
214                                 session->ros_op & ROS_OP_OPCODE_MASK);
215             break;
216           }
217           break;
218         default:
219           proto_tree_add_text(tree, tvb, offset, -1,"Unsupported DOP PDU");
220           return tvb_length(tvb);
221         }
222
223         if(dop_dissector) {
224       col_set_str(pinfo->cinfo, COL_INFO, dop_op_name);
225
226           while (tvb_reported_length_remaining(tvb, offset) > 0){
227             old_offset=offset;
228             offset=(*dop_dissector)(FALSE, tvb, offset, &asn1_ctx, tree, -1);
229             if(offset == old_offset){
230               proto_tree_add_text(tree, tvb, offset, -1,"Internal error, zero-byte DOP PDU");
231               break;
232             }
233           }
234         }
235
236         return tvb_length(tvb);
237 }
238
239
240
241 /*--- proto_register_dop -------------------------------------------*/
242 void proto_register_dop(void) {
243
244   /* List of fields */
245   static hf_register_info hf[] =
246   {
247 #include "packet-dop-hfarr.c"
248   };
249
250   /* List of subtrees */
251   static gint *ett[] = {
252     &ett_dop,
253     &ett_dop_unknown,
254 #include "packet-dop-ettarr.c"
255   };
256
257   static ei_register_info ei[] = {
258      { &ei_dop_unknown_binding_parameter, { "dop.unknown_binding_parameter", PI_UNDECODED, PI_WARN, "Unknown binding-parameter", EXPFILL }},
259   };
260
261   expert_module_t* expert_dop;
262   module_t *dop_module;
263
264   /* Register protocol */
265   proto_dop = proto_register_protocol(PNAME, PSNAME, PFNAME);
266
267   new_register_dissector("dop", dissect_dop, proto_dop);
268
269   dop_dissector_table = register_dissector_table("dop.oid", "DOP OID Dissectors", FT_STRING, BASE_NONE);
270
271   /* Register fields and subtrees */
272   proto_register_field_array(proto_dop, hf, array_length(hf));
273   proto_register_subtree_array(ett, array_length(ett));
274   expert_dop = expert_register_protocol(proto_dop);
275   expert_register_field_array(expert_dop, ei, array_length(ei));
276
277   /* Register our configuration options for DOP, particularly our port */
278
279   dop_module = prefs_register_protocol_subtree("OSI/X.500", proto_dop, prefs_register_dop);
280
281   prefs_register_uint_preference(dop_module, "tcp.port", "DOP TCP Port",
282                                  "Set the port for DOP operations (if other"
283                                  " than the default of 102)",
284                                  10, &global_dop_tcp_port);
285
286
287 }
288
289
290 /*--- proto_reg_handoff_dop --- */
291 void proto_reg_handoff_dop(void) {
292   dissector_handle_t dop_handle;
293
294 #include "packet-dop-dis-tab.c"
295   /* APPLICATION CONTEXT */
296
297   oid_add_from_string("id-ac-directory-operational-binding-management","2.5.3.3");
298
299   /* ABSTRACT SYNTAXES */
300
301   /* Register DOP with ROS (with no use of RTSE) */
302   dop_handle = find_dissector("dop");
303   register_ros_oid_dissector_handle("2.5.9.4", dop_handle, 0, "id-as-directory-operational-binding-management", FALSE);
304
305   /* BINDING TYPES */
306
307   oid_add_from_string("shadow-agreement","2.5.19.1");
308   oid_add_from_string("hierarchical-agreement","2.5.19.2");
309   oid_add_from_string("non-specific-hierarchical-agreement","2.5.19.3");
310
311   /* ACCESS CONTROL SCHEMES */
312   oid_add_from_string("basic-ACS","2.5.28.1");
313   oid_add_from_string("simplified-ACS","2.5.28.2");
314   oid_add_from_string("ruleBased-ACS","2.5.28.3");
315   oid_add_from_string("ruleAndBasic-ACS","2.5.28.4");
316   oid_add_from_string("ruleAndSimple-ACS","2.5.28.5");
317
318   /* ADMINISTRATIVE ROLES */
319   oid_add_from_string("id-ar-autonomousArea","2.5.23.1");
320   oid_add_from_string("id-ar-accessControlSpecificArea","2.5.23.2");
321   oid_add_from_string("id-ar-accessControlInnerArea","2.5.23.3");
322   oid_add_from_string("id-ar-subschemaAdminSpecificArea","2.5.23.4");
323   oid_add_from_string("id-ar-collectiveAttributeSpecificArea","2.5.23.5");
324   oid_add_from_string("id-ar-collectiveAttributeInnerArea","2.5.23.6");
325   oid_add_from_string("id-ar-contextDefaultSpecificArea","2.5.23.7");
326   oid_add_from_string("id-ar-serviceSpecificArea","2.5.23.8");
327
328   /* remember the tpkt handler for change in preferences */
329   tpkt_handle = find_dissector("tpkt");
330
331 }
332
333 static void
334 prefs_register_dop(void)
335 {
336   static guint tcp_port = 0;
337
338   /* de-register the old port */
339   /* port 102 is registered by TPKT - don't undo this! */
340   if((tcp_port > 0) && (tcp_port != 102) && tpkt_handle)
341     dissector_delete_uint("tcp.port", tcp_port, tpkt_handle);
342
343   /* Set our port number for future use */
344   tcp_port = global_dop_tcp_port;
345
346   if((tcp_port > 0) && (tcp_port != 102) && tpkt_handle)
347     dissector_add_uint("tcp.port", tcp_port, tpkt_handle);
348
349 }