1 /* packet-disp.c
2 * Routines for X.525 (X.500 Directory Shadow Asbtract Service) and X.519 DISP packet dissection
3 * Graeme Lunt 2005
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "config.h"
13
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include <epan/prefs.h>
17 #include <epan/oids.h>
18 #include <epan/asn1.h>
19
20 #include "packet-ber.h"
21 #include "packet-acse.h"
22 #include "packet-ros.h"
23 #include "packet-rtse.h"
24
25 #include "packet-x509if.h"
26 #include "packet-x509af.h"
27 #include "packet-x509sat.h"
28 #include "packet-crmf.h"
29
30 #include "packet-dop.h"
31 #include "packet-dap.h"
32 #include "packet-dsp.h"
33 #include "packet-disp.h"
34
35
36 /* we don't have a separate dissector for X519 -
37 and most of DISP is defined in X525 */
38 #define PNAME "X.519 Directory Information Shadowing Protocol"
39 #define PSNAME "DISP"
40 #define PFNAME "disp"
41
42 void proto_register_disp(void);
43 void proto_reg_handoff_disp(void);
44
45 /* Initialize the protocol and registered fields */
46 static int proto_disp = -1;
47
48 #include "packet-disp-hf.c"
49
50 /* Initialize the subtree pointers */
51 static gint ett_disp = -1;
52 #include "packet-disp-ett.c"
53
54 static expert_field ei_disp_unsupported_opcode = EI_INIT;
55 static expert_field ei_disp_unsupported_errcode = EI_INIT;
56 static expert_field ei_disp_unsupported_pdu = EI_INIT;
57 static expert_field ei_disp_zero_pdu = EI_INIT;
58
59 static dissector_handle_t disp_handle = NULL;
60
61 #include "packet-disp-fn.c"
62
63 /*
64 * Dissect DISP PDUs inside a ROS PDUs
65 */
66 static int
dissect_disp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * parent_tree,void * data)67 dissect_disp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
68 {
69 int offset = 0;
70 int old_offset;
71 proto_item *item;
72 proto_tree *tree;
73 struct SESSION_DATA_STRUCTURE* session;
74 int (*disp_dissector)(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_) = NULL;
75 const char *disp_op_name;
76 asn1_ctx_t asn1_ctx;
77
78 /* do we have operation information from the ROS dissector */
79 if (data == NULL)
80 return 0;
81 session = (struct SESSION_DATA_STRUCTURE*)data;
82
83 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
84
85 asn1_ctx.private_data = session;
86
87 item = proto_tree_add_item(parent_tree, proto_disp, tvb, 0, -1, ENC_NA);
88 tree = proto_item_add_subtree(item, ett_disp);
89
90 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DISP");
91 col_clear(pinfo->cinfo, COL_INFO);
92
93 switch(session->ros_op & ROS_OP_MASK) {
94 case (ROS_OP_BIND | ROS_OP_ARGUMENT): /* BindInvoke */
95 disp_dissector = dissect_disp_DSAShadowBindArgument;
96 disp_op_name = "Shadow-Bind-Argument";
97 break;
98 case (ROS_OP_BIND | ROS_OP_RESULT): /* BindResult */
99 disp_dissector = dissect_disp_DSAShadowBindResult;
100 disp_op_name = "Shadow-Bind-Result";
101 break;
102 case (ROS_OP_BIND | ROS_OP_ERROR): /* BindError */
103 disp_dissector = dissect_disp_DSAShadowBindError;
104 disp_op_name = "Shadow-Bind-Error";
105 break;
106 case (ROS_OP_INVOKE | ROS_OP_ARGUMENT): /* Invoke Argument */
107 switch(session->ros_op & ROS_OP_OPCODE_MASK) {
108 case 1: /* requestShadowUpdate */
109 disp_dissector = dissect_disp_RequestShadowUpdateArgument;
110 disp_op_name = "Request-Shadow-Update-Argument";
111 break;
112 case 2: /* updateShadow*/
113 disp_dissector = dissect_disp_UpdateShadowArgument;
114 disp_op_name = "Update-Shadow-Argument";
115 break;
116 case 3: /* coordinateShadowUpdate */
117 disp_dissector = dissect_disp_CoordinateShadowUpdateArgument;
118 disp_op_name = "Coordinate-Shadow-Update-Argument";
119 break;
120 default:
121 proto_tree_add_expert_format(tree, pinfo, &ei_disp_unsupported_opcode, tvb, offset, -1,
122 "Unsupported DISP opcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK);
123 break;
124 }
125 break;
126 case (ROS_OP_INVOKE | ROS_OP_RESULT): /* Return Result */
127 switch(session->ros_op & ROS_OP_OPCODE_MASK) {
128 case 1: /* requestShadowUpdate */
129 disp_dissector = dissect_disp_RequestShadowUpdateResult;
130 disp_op_name = "Request-Shadow-Result";
131 break;
132 case 2: /* updateShadow */
133 disp_dissector = dissect_disp_UpdateShadowResult;
134 disp_op_name = "Update-Shadow-Result";
135 break;
136 case 3: /* coordinateShadowUpdate */
137 disp_dissector = dissect_disp_CoordinateShadowUpdateResult;
138 disp_op_name = "Coordinate-Shadow-Update-Result";
139 break;
140 default:
141 proto_tree_add_expert_format(tree, pinfo, &ei_disp_unsupported_opcode, tvb, offset, -1,
142 "Unsupported DISP opcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK);
143 break;
144 }
145 break;
146 case (ROS_OP_INVOKE | ROS_OP_ERROR): /* Return Error */
147 switch(session->ros_op & ROS_OP_OPCODE_MASK) {
148 case 1: /* shadowError */
149 disp_dissector = dissect_disp_ShadowError;
150 disp_op_name = "Shadow-Error";
151 break;
152 default:
153 proto_tree_add_expert_format(tree, pinfo, &ei_disp_unsupported_errcode, tvb, offset, -1,
154 "Unsupported DISP errcode (%d)", session->ros_op & ROS_OP_OPCODE_MASK);
155 break;
156 }
157 break;
158 default:
159 proto_tree_add_expert(tree, pinfo, &ei_disp_unsupported_pdu, tvb, offset, -1);
160 return tvb_captured_length(tvb);
161 }
162
163 if(disp_dissector) {
164 col_set_str(pinfo->cinfo, COL_INFO, disp_op_name);
165
166 while (tvb_reported_length_remaining(tvb, offset) > 0){
167 old_offset=offset;
168 offset=(*disp_dissector)(FALSE, tvb, offset, &asn1_ctx, tree, -1);
169 if(offset == old_offset){
170 proto_tree_add_expert(tree, pinfo, &ei_disp_zero_pdu, tvb, offset, -1);
171 break;
172 }
173 }
174 }
175
176 return tvb_captured_length(tvb);
177 }
178
179
180 /*--- proto_register_disp -------------------------------------------*/
proto_register_disp(void)181 void proto_register_disp(void) {
182
183 /* List of fields */
184 static hf_register_info hf[] =
185 {
186 #include "packet-disp-hfarr.c"
187 };
188
189 /* List of subtrees */
190 static gint *ett[] = {
191 &ett_disp,
192 #include "packet-disp-ettarr.c"
193 };
194
195 static ei_register_info ei[] = {
196 { &ei_disp_unsupported_opcode, { "disp.unsupported_opcode", PI_UNDECODED, PI_WARN, "Unsupported DISP opcode", EXPFILL }},
197 { &ei_disp_unsupported_errcode, { "disp.unsupported_errcode", PI_UNDECODED, PI_WARN, "Unsupported DISP errcode", EXPFILL }},
198 { &ei_disp_unsupported_pdu, { "disp.unsupported_pdu", PI_UNDECODED, PI_WARN, "Unsupported DISP PDU", EXPFILL }},
199 { &ei_disp_zero_pdu, { "disp.zero_pdu", PI_PROTOCOL, PI_ERROR, "Internal error, zero-byte DISP PDU", EXPFILL }},
200 };
201
202 module_t *disp_module;
203 expert_module_t* expert_disp;
204
205 /* Register protocol */
206 proto_disp = proto_register_protocol(PNAME, PSNAME, PFNAME);
207 disp_handle = register_dissector("disp", dissect_disp, proto_disp);
208
209 /* Register fields and subtrees */
210 proto_register_field_array(proto_disp, hf, array_length(hf));
211 proto_register_subtree_array(ett, array_length(ett));
212 expert_disp = expert_register_protocol(proto_disp);
213 expert_register_field_array(expert_disp, ei, array_length(ei));
214
215 /* Register our configuration options for DISP, particularly our port */
216
217 disp_module = prefs_register_protocol_subtree("OSI/X.500", proto_disp, NULL);
218
219 prefs_register_obsolete_preference(disp_module, "tcp.port");
220
221 prefs_register_static_text_preference(disp_module, "tcp_port_info",
222 "The TCP ports used by the DISP protocol should be added to the TPKT preference \"TPKT TCP ports\", or by selecting \"TPKT\" as the \"Transport\" protocol in the \"Decode As\" dialog.",
223 "DISP TCP Port preference moved information");
224
225 }
226
227
228 /*--- proto_reg_handoff_disp --- */
proto_reg_handoff_disp(void)229 void proto_reg_handoff_disp(void) {
230 #include "packet-disp-dis-tab.c"
231
232 /* APPLICATION CONTEXT */
233
234 oid_add_from_string("id-ac-shadow-consumer-initiated","2.5.3.4");
235 oid_add_from_string("id-ac-shadow-supplier-initiated","2.5.3.5");
236 oid_add_from_string("id-ac-reliable-shadow-consumer-initiated","2.5.3.6");
237 oid_add_from_string("id-ac-reliable-shadow-supplier-initiated","2.5.3.7");
238
239 /* ABSTRACT SYNTAXES */
240 register_ros_oid_dissector_handle("2.5.9.3", disp_handle, 0, "id-as-directory-shadow", FALSE);
241 register_rtse_oid_dissector_handle("2.5.9.5", disp_handle, 0, "id-as-directory-reliable-shadow", FALSE);
242 register_rtse_oid_dissector_handle("2.5.9.6", disp_handle, 0, "id-as-directory-reliable-binding", FALSE);
243
244 /* OPERATIONAL BINDING */
245 oid_add_from_string("id-op-binding-shadow","2.5.1.0.5.1");
246
247 /* DNs */
248 x509if_register_fmt(hf_disp_contextPrefix, "cp=");
249
250 }
251