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