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