1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 
19 // cip_definitions.h author RA/Cisco
20 
21 /* Description: Common types for the CIP inspector. */
22 
23 #ifndef CIP_DEFINITIONS_H
24 #define CIP_DEFINITIONS_H
25 
26 #include <sys/time.h>
27 
28 namespace snort
29 {
30 struct Packet;
31 }
32 
33 #define MSEC_PER_SEC (1000)
34 #define USEC_PER_SEC (1000000)
35 
36 // CIP inspector configuration
37 struct CipProtoConf
38 {
39     // Unconnected timeout, seconds.
40     uint32_t unconnected_timeout;
41 
42     // Maximum number of unconnected requests per TCP connection.
43     uint32_t max_unconnected_messages;
44 
45     // Maximum number of CIP connections per TCP connection.
46     uint32_t max_cip_connections;
47 
48     // Custom embedded packet parameters.
49     bool embedded_cip_enabled;
50     uint32_t embedded_cip_class_id;
51     uint8_t embedded_cip_service_id;
52 };
53 
54 /// CIP Request/Response Management
55 enum CipRequestType
56 {
57     CipRequestTypeOther = 0,
58     CipRequestTypeForwardOpen,
59     CipRequestTypeForwardClose,
60     CipRequestTypeUnconnectedSend,
61     CipRequestTypeMultipleServiceRequest,
62 
63     // Special case to represent when no request is found for a given response.
64     CipRequestTypeNoMatchFound
65 };
66 
67 struct CipStatus
68 {
69     uint8_t general_status;
70     size_t extended_status_size;
71 };
72 
73 enum CipPacketDirection
74 {
75     CIP_FROM_CLIENT,
76     CIP_FROM_SERVER,
77     CIP_FROM_UNKNOWN
78 };
79 
80 /// EtherNet/IP encapsulation layer definitions.
81 
82 // EtherNet/IP encapsulation header
83 struct EnipHeader
84 {
85     uint16_t command;
86     uint16_t length;
87     uint32_t session_handle;
88     uint32_t status;
89     uint64_t sender_context;
90     uint32_t options;
91 };
92 
93 // This is an EtherNet/IP encapsulation layer common packet format item.
94 struct EnipCpfItem
95 {
96     uint16_t type;
97     uint16_t length;
98 
99     // Used if length > 0. Data starts after the Length field.
100     const uint8_t* data;
101 };
102 
103 // Largest number of allowed CPF items for standard EtherNet/IP commands.
104 #define MAX_NUM_CPF_ITEMS 4
105 
106 // This is an EtherNet/IP encapsulation layer common packet format.
107 struct EnipCpf
108 {
109     uint16_t item_count;
110 
111     // All CPF items in the list are valid up to and including array index item_count.
112     EnipCpfItem item_list[MAX_NUM_CPF_ITEMS];
113 };
114 
115 /// CIP layer definitions.
116 enum CipMessageType
117 {
118     // Unknown CIP data type
119     CipMessageTypeUnknown,
120 
121     // CIP Explicit Data
122     CipMessageTypeExplicit,
123 
124     // CIP Implicit Data
125     CipMessageTypeImplicit
126 };
127 
128 enum CipSegmentType
129 {
130     CipSegment_Type_PORT_LINK_ADDRESS,
131     CipSegment_Type_PORT_LINK_ADDRESS_EXTENDED,
132 
133     CipSegment_Type_LOGICAL_CLASS,
134     CipSegment_Type_LOGICAL_INSTANCE,
135     CipSegment_Type_LOGICAL_MEMBER,
136     CipSegment_Type_LOGICAL_CONN_POINT,
137     CipSegment_Type_LOGICAL_ATTRIBUTE,
138     CipSegment_Type_LOGICAL_ELECTRONIC_KEY,
139     CipSegment_Type_LOGICAL_EXTENDED,
140     CipSegment_Type_LOGICAL_SERVICE_ID,
141 
142     CipSegment_Type_NETWORK,
143 
144     CipSegment_Type_SYMBOLIC,
145 
146     CipSegment_Type_DATA_SIMPLE,
147     CipSegment_Type_DATA_EXT_SYMBOL,
148 
149     CipSegment_Type_UNKNOWN
150 };
151 
152 #define CIP_STATUS_SUCCESS 0
153 #define ENIP_STATUS_SUCCESS 0
154 
155 // CIP Classes
156 #define MESSAGE_ROUTER_CLASS_ID 0x02
157 #define CONNECTION_MANAGER_CLASS_ID 0x06
158 
159 // CIP Services
160 #define SERVICE_SET_ATTRIBUTE_SINGLE 0x10
161 #define SERVICE_MULTIPLE_SERVICE_PACKET 0x0A
162 
163 // CIP Connection Manager Services
164 #define CONNECTION_MANAGER_UNCONNECTED_SEND 0x52
165 #define CONNECTION_MANAGER_FORWARD_OPEN 0x54
166 #define CONNECTION_MANAGER_LARGE_FORWARD_OPEN 0x5B
167 #define CONNECTION_MANAGER_FORWARD_CLOSE 0x4E
168 
169 #define CIP_WORD_TO_BYTES 2
170 
171 struct CipSegment
172 {
173     CipSegmentType type;
174 
175     // Total size of this segment.
176     size_t size;
177 
178     // When type = CipSegment_Type_PORT_LINK_ADDRESS
179     // When type = CipSegment_Type_PORT_LINK_ADDRESS_EXTENDED
180     uint16_t port_id;
181 
182     // When type = CipSegment_Type_PORT_LINK_ADDRESS
183     uint8_t link_address;
184 
185     // When type = CipSegment_Type_LOGICAL_CLASS
186     // When type = CipSegment_Type_LOGICAL_INSTANCE
187     // When type = CipSegment_Type_LOGICAL_MEMBER
188     // When type = CipSegment_Type_LOGICAL_CONN_POINT
189     // When type = CipSegment_Type_LOGICAL_ATTRIBUTE
190     uint32_t logical_value;
191 
192     // When type = CipSegment_Type_PORT_LINK_ADDRESS_EXTENDED, this is the link address.
193     // When type = CipSegment_Type_DATA_EXT_SYMBOL, this is the symbol string.
194     // When type = CipSegment_Type_DATA_SIMPLE, this is the start of the data words.
195     // When type = CipSegment_Type_SYMBOLIC, this is the symbol string.
196     const uint8_t* data;
197     size_t data_size;
198 };
199 
200 struct CipPath
201 {
202     // Size of the entire path.
203     size_t full_path_size;
204 
205     // True if path has been decoded successfully.
206     bool decoded;
207 
208     // Main segment type for this path, which drives message target.
209     CipSegmentType primary_segment_type;
210 
211     bool has_class_id;
212     uint32_t class_id;
213 
214     bool has_instance_id;
215     uint32_t instance_id;
216 
217     bool has_attribute_id;
218     uint32_t attribute_id;
219 
220     bool has_unknown_segment;
221 };
222 
223 // Matching pair of CIP Connection IDs.
224 struct ConnectionIdPair
225 {
226     uint32_t ot_connection_id;
227     uint32_t to_connection_id;
228 };
229 
230 // RPI and Network Connection Parameters from a Forward Open Request.
231 struct CipConnectionParameters
232 {
233     uint32_t rpi;
234     uint32_t network_connection_parameters;
235     bool is_null_connection;
236 };
237 
238 // Unique Connection Signature. This is unique to each CIP connection. This
239 //  tuple is unique on a given EtherNet/IP session.
240 struct CipConnectionSignature
241 {
242     uint16_t connection_serial_number;
243     uint16_t vendor_id;
244     uint32_t originator_serial_number;
245 };
246 
247 #define TRANSPORT_CLASS_MASK 0x0F
248 struct CipForwardOpenRequest
249 {
250     // Unconnected request timeout, milliseconds.
251     uint32_t timeout_ms;
252 
253     // Connection timeouts, microseconds.
254     uint64_t ot_connection_timeout_us;
255     uint64_t to_connection_timeout_us;
256 
257     CipConnectionSignature connection_signature;
258 
259     CipConnectionParameters ot_parameters;
260     CipConnectionParameters to_parameters;
261     uint8_t transport_class;
262 
263     CipPath connection_path;
264 
265     bool is_null_forward_open;
266 
267     // Timestamp for message request.
268     struct timeval timestamp;
269 };
270 
271 struct CipForwardOpenResponse
272 {
273     // True if this was a successful Forward Open Response.
274     bool success;
275 
276     // Properties for Success or Fail.
277     CipConnectionSignature connection_signature;
278 
279     // Properties for a Forward Open Response Success.
280     ConnectionIdPair connection_pair;
281 
282     size_t application_reply_size;
283 
284     // Timestamp for message response.
285     struct timeval timestamp;
286 };
287 
288 struct CipForwardCloseRequest
289 {
290     // Unconnected request timeout, milliseconds.
291     uint32_t timeout_ms;
292 
293     CipConnectionSignature connection_signature;
294 
295     CipPath connection_path;
296 };
297 
298 // Used to set error flags in enip_invalid_nonfatal.
299 #define ENIP_INVALID_COMMAND (1 << 0)
300 #define ENIP_INVALID_DUPLICATE_SESSION (1 << 1)
301 #define ENIP_INVALID_SESSION_HANDLE (1 << 2)
302 #define ENIP_INVALID_INTERFACE_HANDLE (1 << 3)
303 #define ENIP_INVALID_CONNECTION_ID (1 << 4)
304 #define ENIP_INVALID_PAYLOAD_SIZE (1 << 5)
305 #define ENIP_INVALID_ENIP_COMMAND_CPF_MISMATCH (1 << 6)
306 #define ENIP_INVALID_RESERVED_FUTURE_CPF_TYPE (1 << 7)
307 #define ENIP_INVALID_STATUS (1 << 8)
308 #define ENIP_INVALID_ENIP_TCP_ONLY (1 << 9)
309 
310 struct EnipSessionData
311 {
312     // True if the ENIP Header was parsed and is valid.
313     bool enip_decoded;
314 
315     // Full ENIP header.
316     EnipHeader enip_header;
317 
318     // Error states for non-fatal ENIP errors. Error conditions that could trigger this:
319     //  - Command code was not valid according to CIP Volume 2, Section 2-3.2.
320     //  - RegisterSession attempted when a session was already active.
321     //  - Session Handle did not match an active session.
322     //  - Interface Handle != 0
323     //  - Connection ID does not match an active connection.
324     //  - Larger amount of ENIP data than specific in ENIP length.
325     //  - Invalid CPF data item for a particular ENIP command.
326     //  - CPF Item Type ID was found in the Reserved for future expansion range.
327     //  - ENIP Status != 0, for a Request.
328     //  - Attempting to send an ENIP command that is TCP only on a UDP connection.
329     uint32_t enip_invalid_nonfatal;
330 
331     // True if the Common Packet Format was parsed and is valid.
332     bool cpf_decoded;
333 
334     // True if the required CPF items are present for this EtherNet/IP command.
335     bool required_cpf_items_present;
336 
337     // Common Packet Format data.
338     EnipCpf enip_cpf;
339 
340     // Connection Class from original connection request, for connected messages.
341     uint32_t connection_class_id;
342 };
343 
344 // Used to set error flags in cip_req_invalid_nonfatal.
345 #define CIP_REQ_INVALID_CONNECTION_ADD_FAILED (1 << 0)
346 #define CIP_REQ_INVALID_UNKNOWN_SEGMENT (1 << 1)
347 #define CIP_REQ_INVALID_TIMEOUT_MULTIPLIER (1 << 2)
348 struct CipRequest
349 {
350     // CIP Service code.
351     uint8_t service;
352 
353     CipPath request_path;
354 
355     CipRequestType request_type;
356 
357     // This is only valid for Unconnected Send messages.
358     CipPath route_path;
359 
360     // CIP application payload data. This starts after the Request Path.
361     const uint8_t* cip_data;
362     size_t cip_data_size;
363 
364     // Unconnected request timeout, milliseconds.
365     bool has_timeout;
366     uint32_t timeout_ms;
367 
368     // True if this request was a Forward Open Request.
369     bool is_forward_open_request;
370 
371     // Class ID in the Forward Open Request Connection Path.
372     // Used only when is_forward_open_request is true.
373     uint32_t connection_path_class_id;
374 
375     // Error states for non-fatal CIP errors. Error conditions that could trigger this:
376     //  - Forward Open Request received but couldn't add the connection to the list because a
377     //      connection already existed with that signature.
378     //  - Unknown segment type in request path.
379     //  - Forward Open Request contained invalid Connection Timeout Multiplier.
380     uint32_t cip_req_invalid_nonfatal;
381 };
382 
383 struct CipResponse
384 {
385     // CIP Service code. This does not include the first bit set (0x80).
386     uint8_t service;
387 
388     CipStatus status;
389 };
390 
391 struct CipMessage
392 {
393     // True if this is a CIP request (vs response).
394     bool is_cip_request;
395 
396     // Used if is_cip_request is true.
397     CipRequest request;
398 
399     // Used if is_cip_request is false.
400     CipResponse response;
401 };
402 
403 struct CipCurrentData
404 {
405     CipPacketDirection direction;
406 
407     // ENIP layer data.
408     EnipSessionData enip_data;
409 
410     // CIP layer data.
411     CipMessageType cip_message_type;
412 
413     // Used if cip_message_type is CipMessageTypeExplicit
414     CipMessage cip_msg;
415 
416     // True if the packet was not able to be fully parsed.
417     bool invalid_fatal;
418 };
419 
420 struct EnipSession
421 {
422     // ENIP session handle.
423     uint32_t session_handle;
424 
425     // True if this session is active.
426     bool active;
427 };
428 
429 // This represents an Unconnected message request.
430 //  Sender Context -> Request Type
431 struct CipUnconnectedMessage
432 {
433     uint64_t sender_context;
434 
435     CipRequestType request_type;
436 
437     // Unconnected request timeout, milliseconds.
438     uint32_t timeout_ms;
439 
440     // Timestamp for message request.
441     struct timeval timestamp;
442 
443     // True if this entry is in use.
444     bool slot_active;
445 };
446 
447 struct CipUnconnectedMessageList
448 {
449     CipUnconnectedMessage* list;
450     uint32_t list_size;
451     uint32_t count;
452 
453     // True if an active request was forced to be pruned.
454     bool request_pruned;
455 };
456 
457 // This represents a CIP connection.
458 // This is used to:
459 //  a) Get the connection IDs, during a Forward Close.
460 //  b) Get Class ID from the Connection Path.
461 struct CipConnection
462 {
463     CipConnectionSignature signature;
464 
465     ConnectionIdPair connection_id_pair;
466 
467     // Class ID from the Connection Path
468     uint32_t class_id;
469 
470     // True if the connection is fully established.
471     bool established;
472 
473     // Connection timeouts, seconds.
474     uint32_t ot_connection_timeout_sec;
475     uint32_t to_connection_timeout_sec;
476 
477     // Timestamp for last time connection was active.
478     struct timeval ot_timestamp;
479     struct timeval to_timestamp;
480 
481     // True if this entry is in use.
482     bool slot_active;
483 };
484 
485 struct CipConnectionList
486 {
487     CipConnection* list;
488     uint32_t list_size;
489     uint32_t count;
490 
491     // True if an active connection was forced to be pruned.
492     bool connection_pruned;
493 };
494 
495 struct CipGlobalSessionData
496 {
497     // ENIP Session for this TCP connection.
498     EnipSession enip_session;
499 
500     // List of CIP connections.
501     CipConnectionList connection_list;
502 
503     // List of outstanding unconnected messages (SendRRData).
504     CipUnconnectedMessageList unconnected_list;
505 
506     // Current configuration for use in lower-level parsing functions.
507     const CipProtoConf* config;
508 
509     snort::Packet* snort_packet;
510 };
511 
512 // This is the overall structure used by Snort to store current and global data
513 //  for a particular stream.
514 struct CipSessionData
515 {
516     // Current data for this packet.
517     CipCurrentData current_data;
518 
519     // Overall data for this session.
520     CipGlobalSessionData global_data;
521 };
522 
523 #endif  // CIP_DEFINITIONS_H
524 
525