1 /******************************************************************************
2 ** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved.
3 ** Web: http://www.ascolab.com
5 ** SPDX-License-Identifier: GPL-2.0-or-later
7 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
8 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
10 ** Project: OpcUa Wireshark Plugin
12 ** Description: OpcUa Protocol Decoder.
14 ** Author: Gerhard Gappmeier <gerhard.gappmeier@ascolab.com>
15 ******************************************************************************/
17 #include <epan/dissectors/packet-tcp.h>
18 #include <epan/packet.h>
19 #include <epan/prefs.h>
20 #include <epan/range.h>
21 #include <epan/reassemble.h>
22 #include <epan/secrets.h>
23 #include <epan/tvbuff.h>
25 #include <wiretap/secrets-types.h>
26 #include <wsutil/file_util.h>
29 #include "opcua_application_layer.h"
30 #include "opcua_complextypeparser.h"
31 #include "opcua_enumparser.h"
32 #include "opcua_hfindeces.h"
33 #include "opcua_keyset.h"
34 #include "opcua_security_layer.h"
35 #include "opcua_serviceparser.h"
36 #include "opcua_serviceids.h"
37 #include "opcua_simpletypes.h"
38 #include "opcua_transport_layer.h"
40 void proto_register_opcua(void);
42 extern const value_string g_requesttypes
[];
43 extern const int g_NumServices
;
44 static const char *g_opcua_debug_file_name
;
45 int g_opcua_default_sig_len
;
47 /* forward reference */
48 void proto_reg_handoff_opcua(void);
49 /* declare parse function pointer */
50 typedef int (*FctParse
)(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int *pOffset
, struct ua_metadata
*data
);
53 static dissector_handle_t opcua_handle
;
54 static module_t
*opcua_module
;
56 /* #define OPCUA_DEBUG */
58 # define debugprintf(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__);
60 # define debugprintf(fmt, ...)
63 /** Official IANA registered port for OPC UA Binary Protocol. */
64 #define OPCUA_DEFAULT_PORT 4840
65 /* default port range for preferences */
66 #define OPCUA_PORT_RANGE "4840"
67 /** header length that is needed to compute the pdu length.
68 * @see get_opcua_message_len
70 #define FRAME_HEADER_LEN 8
71 /* AES block size: for both AES128 and AES256 the block size is 128 bits */
72 #define AES_BLOCK_SIZE 16
74 /** subtree types used in opcua_transport_layer.c */
75 int ett_opcua_extensionobject
;
78 /** subtree types used locally */
79 static int ett_opcua_transport
;
80 static int ett_opcua_fragment
;
81 static int ett_opcua_fragments
;
83 static int hf_opcua_fragments
;
84 static int hf_opcua_fragment
;
85 static int hf_opcua_fragment_overlap
;
86 static int hf_opcua_fragment_overlap_conflicts
;
87 static int hf_opcua_fragment_multiple_tails
;
88 static int hf_opcua_fragment_too_long_fragment
;
89 static int hf_opcua_fragment_error
;
90 static int hf_opcua_fragment_count
;
91 static int hf_opcua_reassembled_in
;
92 static int hf_opcua_reassembled_length
;
94 static const fragment_items opcua_frag_items
= {
95 /* Fragment subtrees */
101 &hf_opcua_fragment_overlap
,
102 &hf_opcua_fragment_overlap_conflicts
,
103 &hf_opcua_fragment_multiple_tails
,
104 &hf_opcua_fragment_too_long_fragment
,
105 &hf_opcua_fragment_error
,
106 &hf_opcua_fragment_count
,
107 /* Reassembled in field */
108 &hf_opcua_reassembled_in
,
109 /* Reassembled length field */
110 &hf_opcua_reassembled_length
,
111 /* Reassembled data field */
117 static reassembly_table opcua_reassembly_table
;
119 /** OpcUa Transport Message Types */
127 MSG_OPENSECURECHANNEL
,
128 MSG_CLOSESECURECHANNEL
,
132 /** OpcUa Transport Message Type Names */
133 static const char* g_szMessageTypes
[] =
136 "Acknowledge message",
138 "Reverse Hello message",
139 "UA Secure Conversation Message",
140 "OpenSecureChannel message",
141 "CloseSecureChannel message",
145 static const enum_val_t opcua_sig_len_enum
[] = {
146 { "None", "Unsigned", 0 },
147 { "20", "20 Bytes", 20 },
148 { "32", "32 Bytes", 32 },
153 static char *ua_strtok_r(char *str
, const char *delim
, char **saveptr
)
155 /* use MSVC specific strtok_s */
156 return strtok_s(str
, delim
, saveptr
);
159 static char *ua_strtok_r(char *str
, const char *delim
, char **saveptr
)
161 /* use POSIX strtok_r */
162 return strtok_r(str
, delim
, saveptr
);
166 /** returns the length of an OpcUa message.
167 * This function reads the length information from
168 * the transport header.
170 static unsigned get_opcua_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
171 int offset
, void *data _U_
)
175 /* the message length starts at offset 4 */
176 plen
= tvb_get_letohl(tvb
, offset
+ 4);
181 /* Helper function to convert hex string to binary data */
182 unsigned hex_to_bin(const char *hex_string
, unsigned char *binary_data
, unsigned int binary_size
)
184 unsigned length
= (unsigned)strlen(hex_string
);
187 for (i
= 0; i
< length
/ 2 && i
< binary_size
; ++i
) {
188 sscanf(hex_string
+ 2 * i
, "%2hhx", &binary_data
[i
]);
194 /** Parsing context */
195 struct opcua_keylog_parser_ctx
{
196 struct ua_keyset
*keyset
; /**< current keyset */
197 uint64_t last_id
; /**< the id of the previous line, this is also the id of the keyset */
201 * Common function for parsing key log line used by opcua_keylog_process_lines and opcua_load_keylog_file.
203 * @param ctx Parsing context.
204 * @param line Current line to parse.
206 static void opcua_keylog_process_line(struct opcua_keylog_parser_ctx
*ctx
, const char *line
)
208 struct ua_keyset
*keyset
;
209 char key
[33]; /* 32 chars + null terminator */
210 char value
[65]; /* 64 hex chars + null terminator */
211 const char *parts
[4]; /* for string split */
212 unsigned int num_parts
;
214 uint32_t token_id
= 0;
215 uint32_t channel_id
= 0;
219 /* parse key/value pair */
220 n
= sscanf(line
, "%32[^:]: %64s\n", key
, value
);
223 debugprintf("%s = %s\n", key
, value
);
225 /* split key into parts */
227 tmp
= ua_strtok_r(key
, "_", &saveptr
);
228 while (tmp
&& num_parts
< 4) {
229 parts
[num_parts
++] = tmp
;
230 tmp
= ua_strtok_r(NULL
, "_", &saveptr
);
232 if (num_parts
!= 4) return; /* skip invalid enty */
233 channel_id
= (uint32_t)strtoul(parts
[2], NULL
, 10);
234 token_id
= (uint32_t)strtoul(parts
[3], NULL
, 10);
236 debugprintf("channel_id = %u\n", channel_id
);
237 debugprintf("token_id = %u\n", token_id
);
239 /* create unique keyset id */
240 id
= ua_keyset_id(channel_id
, token_id
);
242 if (ctx
->keyset
== NULL
|| id
!= ctx
->last_id
) {
243 debugprintf("Adding new keyset for id %lu...\n", id
);
244 /* create new keyset for new id */
245 ctx
->keyset
= ua_keysets_add();
248 keyset
= ctx
->keyset
;
251 /* store key material */
252 if (strcmp(parts
[0], "client") == 0) {
253 if (strcmp(parts
[1], "iv") == 0) {
254 hex_to_bin(value
, keyset
->client_iv
, sizeof(keyset
->client_iv
));
255 } else if (strcmp(parts
[1], "key") == 0) {
256 keyset
->client_key_len
= (unsigned int)hex_to_bin(value
, keyset
->client_key
, sizeof(keyset
->client_key
));
257 } else if (strcmp(parts
[1], "siglen") == 0) {
258 keyset
->client_sig_len
= (unsigned int)strtoul(value
, NULL
, 10);
260 } else if (strcmp(parts
[0], "server") == 0) {
261 if (strcmp(parts
[1], "iv") == 0) {
262 hex_to_bin(value
, keyset
->server_iv
, sizeof(keyset
->server_iv
));
263 } else if (strcmp(parts
[1], "key") == 0) {
264 keyset
->server_key_len
= (unsigned int)hex_to_bin(value
, keyset
->server_key
, sizeof(keyset
->server_key
));
265 } else if (strcmp(parts
[1], "siglen") == 0) {
266 keyset
->server_sig_len
= (unsigned int)strtoul(value
, NULL
, 10);
273 * Parses key log data from PCAP file.
274 * This function splits the data by \n and calls opcua_keylog_process_line.
276 static void opcua_keylog_process_lines(char *data
)
278 struct opcua_keylog_parser_ctx ctx
= { NULL
, 0 };
280 const char *line
= ua_strtok_r(data
, "\n", &saveptr
);
283 opcua_keylog_process_line(&ctx
, line
);
284 line
= ua_strtok_r(NULL
, "\n", &saveptr
);
287 /* sort data by id to make lookup working */
292 * Loads the configured OPCUA Keylog file.
294 static void opcua_load_keylog_file(const char *filename
)
296 struct opcua_keylog_parser_ctx ctx
= { NULL
, 0 };
299 debugprintf("Loading key file '%s'...\n", filename
);
300 FILE *f
= ws_fopen(filename
, "r");
302 debugprintf("error: '%s' not found\n", filename
);
306 /* parse file contents */
307 while (fgets(line
, sizeof(line
), f
)) {
308 opcua_keylog_process_line(&ctx
, line
);
312 /* sort data by id to make lookup working */
317 * Checks the padding of a symetric signed message.
318 * A message always contains a padding_len byte, which tells us the length of
319 * the padding. All following padding bytes contain the same value. This makes it
320 * possible the padding from the end of the message.
325 * @param padding Pointer to last padding byte.
326 * @return padding length on success, -1 if the paddding is invalid.
328 static int verify_padding(const uint8_t *padding
)
335 for (i
= 0; i
< pad_len
; ++i
) {
336 if (padding
[-pad_len
+ i
] != pad_len
) return -1;
342 * Gets security footer info.
344 * @param channel_id SecureChannelId for keyset lookup.
345 * @param token_id TokenId for keyset lookup.
346 * @param sig_len Returns the length of the signature.
347 * @param from_server True of the message is sent from the server, false when sent from the client.
349 * @return Returns 0 on success, -1 if parsing failed.
351 static int opcua_get_footer_info(uint32_t channel_id
, uint32_t token_id
, uint8_t *sig_len
, bool from_server
)
353 struct ua_keyset
*keyset
;
356 id
= ua_keyset_id(channel_id
, token_id
);
358 /* try to get correct signature length from key log file */
359 keyset
= ua_keysets_lookup(id
);
361 /* The Client keys are used to secure Messages sent by the Client. The Server keys are used to
362 * secure Messages sent by the Server.
365 *sig_len
= keyset
->server_sig_len
;
367 *sig_len
= keyset
->client_sig_len
;
371 debugprintf("no keyset found for channel_id=%u and token_id=%u\n", channel_id
, token_id
);
372 /* we use sig_len set from OpenSecurehChannel Policy in this case.
373 * this requires to have the OPN in the capture file, otherwise we are out of luck.
380 * This function to perform AES decryption on service data in-place.
381 * Add also determines the payload length by removing the padding and signature.
383 * @param channel_id SecureChannelId for keyset lookup.
384 * @param token_id TokenId for keyset lookup.
385 * @param cipher The cipher text.
386 * @param cipher_len The cipher test length in bytes.
387 * @param plaintext The plaintext to return.
388 * @param plaintext_len The plaintext in bytes, should be the same as cipher_len.
389 * @param padding_len Returns the length of the padding.
390 * @param sig_len Returns the length of the signature.
391 * @param from_server True of the message is sent from the server, false when sent from the client.
393 * @return Returns 0 on success, -1 if decryption failed.
395 static int decrypt_opcua(
396 uint32_t channel_id
, uint32_t token_id
,
397 const uint8_t *cipher
, unsigned cipher_len
,
398 uint8_t *plaintext
, unsigned plaintext_len
,
399 uint8_t *padding_len
, uint8_t *sig_len
, bool from_server
)
401 struct ua_keyset
*keyset
;
403 unsigned int keylen
, ivlen
;
404 unsigned char *keydata
, *ivdata
;
409 id
= ua_keyset_id(channel_id
, token_id
);
411 keyset
= ua_keysets_lookup(id
);
412 if (keyset
== NULL
) {
413 debugprintf("no keyset found for channel_id=%u and token_id=%u\n", channel_id
, token_id
);
414 /* col_append_fstr(pinfo->cinfo, COL_INFO, " (encrypted)"); */
417 debugprintf("found keyset for channel_id=%u and token_id=%u\n", channel_id
, token_id
);
419 /* The Client keys are used to secure Messages sent by the Client. The Server keys are used to
420 * secure Messages sent by the Server.
423 ivlen
= sizeof(keyset
->server_iv
);
424 ivdata
= keyset
->server_iv
;
425 keylen
= keyset
->server_key_len
;
426 keydata
= keyset
->server_key
;
427 *sig_len
= keyset
->server_sig_len
;
429 ivlen
= sizeof(keyset
->client_iv
);
430 ivdata
= keyset
->client_iv
;
431 keylen
= keyset
->client_key_len
;
432 keydata
= keyset
->client_key
;
433 *sig_len
= keyset
->client_sig_len
;
435 /* derive AES mode from key length */
438 debugprintf("using AES-128-CBC\n");
439 cipher_mode
= GCRY_CIPHER_AES128
;
442 debugprintf("using AES-256-CBC\n");
443 cipher_mode
= GCRY_CIPHER_AES256
;
446 debugprintf("invalid AES key length: %u bytes\n", keylen
);
447 /* col_append_fstr(pinfo->cinfo, COL_INFO, " (encrypted)"); */
451 debugprintf("cipher_len=%u\n", cipher_len
);
452 if (cipher_len
% 16 != 0) {
453 debugprintf("warning: cipher_len not a multiple of 16.\n");
456 gcry_cipher_hd_t handle
;
457 gcry_cipher_open(&handle
, cipher_mode
, GCRY_CIPHER_MODE_CBC
, GCRY_CIPHER_CBC_CTS
);
458 gcry_cipher_setkey(handle
, keydata
, keylen
);
459 gcry_cipher_setiv(handle
, ivdata
, ivlen
);
461 /* Decrypt the data in-place */
462 res
= gcry_cipher_decrypt(handle
, plaintext
, plaintext_len
, cipher
, cipher_len
);
464 /* col_append_fstr(pinfo->cinfo, COL_INFO, " (decrypted)"); */
465 debugprintf("decryption succeeded.\n");
467 /* col_append_fstr(pinfo->cinfo, COL_INFO, " (encrypted)"); */
468 debugprintf("decryption failed.\n");
471 gcry_cipher_close(handle
);
472 /* it makes no sense to continue and verify the padding if decryption failed */
477 ret
= verify_padding(&plaintext
[plaintext_len
- *sig_len
- 1]);
479 debugprintf("padding is invalid.\n");
482 /* return padding length */
483 *padding_len
= plaintext
[plaintext_len
- *sig_len
- 1];
484 debugprintf("sig_len=%u\n", *sig_len
);
485 debugprintf("pad_len=%u\n", *padding_len
);
490 /** The OpcUa message dissector.
491 * This method dissects full OpcUa messages.
492 * It gets only called with reassembled data
493 * from tcp_dissect_pdus.
495 static int dissect_opcua_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
497 FctParse pfctParse
= NULL
;
498 enum MessageType msgtype
= MSG_INVALID
;
499 uint16_t src_port
= pinfo
->srcport
;
501 bool from_server
= false;
502 bool decrypted
= false; /* successfully decrypted secure message */
503 enum ua_message_mode mode
= UA_MessageMode_None
;
505 struct ua_metadata metadata
;
506 tvbuff_t
*decrypted_tvb
= NULL
;
509 /* determine if telegram is from server or from client by checking the port number */
510 if (src_port
== OPCUA_DEFAULT_PORT
) {
513 port_range
= prefs_get_range_value("opcua", "tcp.port");
514 if (port_range
&& value_is_in_range(port_range
, src_port
)) {
519 metadata
.encrypted
= false;
520 get_encryption_info(pinfo
, &mode
, &sig_len
);
522 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "OpcUa");
525 /* parse message type */
526 if (tvb_memeql(tvb
, 0, (const uint8_t * )"HEL", 3) == 0)
529 pfctParse
= parseHello
;
531 else if (tvb_memeql(tvb
, 0, (const uint8_t*)"ACK", 3) == 0)
533 msgtype
= MSG_ACKNOWLEDGE
;
534 pfctParse
= parseAcknowledge
;
536 else if (tvb_memeql(tvb
, 0, (const uint8_t*)"ERR", 3) == 0)
539 pfctParse
= parseError
;
541 else if (tvb_memeql(tvb
, 0, (const uint8_t*)"RHE", 3) == 0)
543 msgtype
= MSG_REVERSEHELLO
;
544 pfctParse
= parseReverseHello
;
546 else if (tvb_memeql(tvb
, 0, (const uint8_t*)"MSG", 3) == 0)
548 msgtype
= MSG_MESSAGE
;
549 pfctParse
= parseMessage
;
551 else if (tvb_memeql(tvb
, 0, (const uint8_t*)"OPN", 3) == 0)
553 msgtype
= MSG_OPENSECURECHANNEL
;
554 pfctParse
= parseOpenSecureChannel
;
556 else if (tvb_memeql(tvb
, 0, (const uint8_t*)"CLO", 3) == 0)
558 msgtype
= MSG_CLOSESECURECHANNEL
;
559 pfctParse
= parseCloseSecureChannel
;
563 msgtype
= MSG_INVALID
;
565 /* Clear out stuff in the info column */
566 col_set_str(pinfo
->cinfo
, COL_INFO
, g_szMessageTypes
[msgtype
]);
568 /* add empty item to make filtering by 'opcua' work */
569 proto_tree_add_item(tree
, proto_opcua
, tvb
, 0, -1, ENC_NA
);
571 return tvb_reported_length(tvb
);
574 /* Clear out stuff in the info column */
575 col_set_str(pinfo
->cinfo
, COL_INFO
, g_szMessageTypes
[msgtype
]);
581 bool bParseService
= false; /* Only MSG, OPN and CLO have a service payload */
582 bool bIsFinalChunk
= false;
583 unsigned payload_len
= 0;
586 /* we are being asked for details */
587 proto_item
*ti
= NULL
;
588 proto_tree
*transport_tree
= NULL
;
590 ti
= proto_tree_add_item(tree
, proto_opcua
, tvb
, 0, -1, ENC_NA
);
591 transport_tree
= proto_item_add_subtree(ti
, ett_opcua_transport
);
593 /* call the transport message dissector */
594 (*pfctParse
)(transport_tree
, tvb
, pinfo
, &offset
, &metadata
);
596 /* MSG_MESSAGE and MSG_CLOSESECURECHANNEL can be decrypted.
597 * Also handle chunked message reassembly for MSG_MESSAGE.
599 if (msgtype
== MSG_MESSAGE
|| msgtype
== MSG_CLOSESECURECHANNEL
)
601 uint8_t chunkType
= 0;
602 uint32_t opcua_seqno
= 0; /* OPCUA sequence number */
603 uint32_t opcua_reqid
= 0; /* OPCUA request id */
604 fragment_head
*frag_msg
= NULL
;
606 bParseService
= true;
608 chunkType
= tvb_get_uint8(tvb
, offset
); offset
+= 1;
609 offset
+= 4; /* message size */
610 offset
+= 4; /* skip secure channel_id */
611 parseSecurityHeader(transport_tree
, tvb
, &offset
, &metadata
); /* only token_id (4 byte) */
613 if (mode
== UA_MessageMode_MaybeEncrypted
) {
614 /* try to parse ServiceId */
615 iServiceId
= getServiceNodeId(tvb
, offset
+ 8); /* skip 4 byte SeqNo and 4 byte RequestId */
616 const char *szServiceName
= val_to_str((uint32_t)iServiceId
, g_requesttypes
, "not found");
617 if (strcmp(szServiceName
, "not found") == 0) {
618 mode
= UA_MessageMode_SignAndEncrypt
;
620 mode
= UA_MessageMode_Sign
;
622 store_encryption_info(pinfo
, mode
, sig_len
);
625 /* Message Structure:
626 * +-----------------+
627 * / | Message Header | MSGF, MessageSize
628 * | +-----------------+
629 * | | Security Header | SecureChannelId, TokenId
630 * | +-----------------+
631 * Signed < | Sequence Header | \ SequenceNumber, RequestId
632 * | +-----------------+ |
634 * | +-----------------+ > Encrypted
636 * +-----------------+ |
638 * +-----------------+
640 if (mode
== UA_MessageMode_SignAndEncrypt
) {
641 uint32_t channel_id
= tvb_get_letohl(tvb
, 8);
642 uint32_t token_id
= tvb_get_letohl(tvb
, 12);
643 unsigned cipher_len
= tvb_ensure_captured_length_remaining(tvb
, 16);
644 unsigned plaintext_len
= cipher_len
;
645 const uint8_t *cipher
= tvb_get_ptr(tvb
, 16, (int)cipher_len
);
646 unsigned char *plaintext
= (unsigned char*)wmem_alloc(pinfo
->pool
, plaintext_len
);
648 ret
= decrypt_opcua(channel_id
, token_id
, cipher
, cipher_len
, plaintext
, plaintext_len
, &pad_len
, &sig_len
, from_server
);
651 /* to get the payload length we need to subtract the sequence header (8) byte,
652 * the padding (paddin_len+1), and the signature from the plaintext */
653 payload_len
= plaintext_len
- pad_len
- sig_len
- 9; /* pad_len 2 = 02 02 02 */
654 /* Now re-setup the tvb buffer to have the new data */
655 decrypted_tvb
= tvb_new_child_real_data(tvb
, plaintext
, (unsigned)plaintext_len
, (int)plaintext_len
);
656 add_new_data_source(pinfo
, decrypted_tvb
, "Decrypted Data");
657 /* process decrypted_tvb from here */
662 /* decryption failed */
663 metadata
.encrypted
= true;
665 } else if (mode
== UA_MessageMode_Sign
) {
666 uint32_t channel_id
= tvb_get_letohl(tvb
, 8);
667 uint32_t token_id
= tvb_get_letohl(tvb
, 12);
668 payload_len
= tvb_ensure_captured_length_remaining(tvb
, 24); /* subtract header */
670 ret
= opcua_get_footer_info(channel_id
, token_id
, &sig_len
, from_server
);
672 debugprintf("Processing security footer of signed message failed.\n");
674 /* signed only messages have no padding, so the payload is the message size
675 * without 24 byte header and without signature */
676 payload_len
-= sig_len
;
678 /* store the current tvb as decrypted tvb, because we need this to parse the signature
679 * at the end, and tvb gets replaces with the reassembled UA message if the message was chunked.
683 /* no padding, no signature, just payload */
684 payload_len
= tvb_ensure_captured_length_remaining(tvb
, 24); /* subtract header */
689 opcua_seqno
= tvb_get_letohl(tvb
, offset
); /* Sequence.Sequence Number */
690 opcua_reqid
= tvb_get_letohl(tvb
, offset
+ 4); /* Sequence.RequestId */
691 parseSequenceHeader(transport_tree
, tvb
, &offset
, &metadata
);
693 if (chunkType
== 'A')
695 /* cancel chunk reassembly */
696 fragment_delete(&opcua_reassembly_table
, pinfo
, opcua_reqid
, NULL
);
698 col_clear_fence(pinfo
->cinfo
, COL_INFO
);
699 col_set_str(pinfo
->cinfo
, COL_INFO
, "Abort message");
702 (*pfctParse
)(transport_tree
, tvb
, pinfo
, &offset
, &metadata
);
703 parseAbort(transport_tree
, tvb
, pinfo
, &offset
, &metadata
);
705 return tvb_reported_length(tvb
);
708 /* check if tvb is part of a chunked message:
709 the UA protocol does not tell us that, so we look into
710 opcua_reassembly_table if the opcua_reqid belongs to a
712 frag_msg
= fragment_get(&opcua_reassembly_table
, pinfo
, opcua_reqid
, NULL
);
713 if (frag_msg
== NULL
)
715 frag_msg
= fragment_get_reassembled_id(&opcua_reassembly_table
, pinfo
, opcua_reqid
);
718 if (frag_msg
!= NULL
|| chunkType
== 'C')
720 bool bSaveFragmented
= pinfo
->fragmented
;
721 bool bMoreFragments
= true;
722 tvbuff_t
*reassembled_tvb
= NULL
;
723 bool first_frag
= false;
725 pinfo
->fragmented
= true;
727 if (frag_msg
== NULL
)
733 if (chunkType
== 'F')
735 bMoreFragments
= false;
739 frag_msg
= fragment_add_seq_check(&opcua_reassembly_table
,
743 opcua_reqid
, /* ID for fragments belonging together */
745 first_frag
? 0 : opcua_seqno
, /* fragment sequence number */
747 bMoreFragments
); /* More fragments? */
750 /* the UA protocol does not number the chunks beginning
751 * from 0 but uses the common sequence number. We
752 * handle that in Wireshark by setting the sequence
753 * offset here, after passing in 0 for the first
754 * fragment. For later fragments we can use the
755 * sequence number as contained in the protocol.
758 fragment_add_seq_offset(&opcua_reassembly_table
, pinfo
, opcua_reqid
, NULL
, opcua_seqno
);
760 reassembled_tvb
= process_reassembled_data(tvb
,
763 "Reassembled UA Message",
772 bIsFinalChunk
= true;
774 tvb
= reassembled_tvb
;
775 /* new tvb starts at payload */
780 /* Not last packet of reassembled UA message */
781 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (Message fragment %u)", opcua_seqno
);
782 /* only show transport header */
783 bParseService
= false;
784 tvb
= tvb_new_subset_remaining(tvb
, 0);
787 pinfo
->fragmented
= bSaveFragmented
;
791 /* parse payload if not encrypted */
792 if (!metadata
.encrypted
&& bParseService
) {
793 if (msgtype
== MSG_CLOSESECURECHANNEL
) {
794 iServiceId
= parseService(transport_tree
, tvb
, pinfo
, &offset
, &metadata
);
795 if (iServiceId
== OpcUaId_CloseSecureChannelRequest_Encoding_DefaultBinary
) {
796 col_append_str(pinfo
->cinfo
, COL_INFO
, ": CloseSecureChannelRequest");
797 } else if (iServiceId
== OpcUaId_CloseSecureChannelResponse_Encoding_DefaultBinary
) {
798 col_append_str(pinfo
->cinfo
, COL_INFO
, ": CloseSecureChannelResponse");
800 const char *szServiceName
= val_to_str((uint32_t)iServiceId
, g_requesttypes
, "ServiceId %d");
801 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s (Wrong ServiceId)", szServiceName
);
803 } else if (msgtype
== MSG_MESSAGE
) {
804 /* parse the service if not chunked or message was reassembled */
805 iServiceId
= parseService(transport_tree
, tvb
, pinfo
, &offset
, &metadata
);
807 /* display the service type in addition to the message type */
808 if (iServiceId
!= -1)
810 const char *szServiceName
= val_to_str((uint32_t)iServiceId
, g_requesttypes
, "ServiceId %d");
812 if (bIsFinalChunk
== false)
814 /* normal message in one chunk */
815 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s", szServiceName
);
819 /* reassembled message from multiple chunks */
820 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s (Message Reassembled)", szServiceName
);
824 if (mode
== UA_MessageMode_SignAndEncrypt
&& decrypted
) {
825 /* parse padding and signature */
826 parseSecurityFooterSAE(transport_tree
, decrypted_tvb
, 8 + payload_len
, pad_len
, sig_len
);
827 } else if (mode
== UA_MessageMode_Sign
) {
828 /* parse signature */
829 parseSecurityFooterSO(transport_tree
, decrypted_tvb
, 24 + payload_len
, sig_len
);
832 if (metadata
.encrypted
) {
833 col_append_str(pinfo
->cinfo
, COL_INFO
, " (encrypted)");
834 } else if (mode
== UA_MessageMode_SignAndEncrypt
) {
835 col_append_str(pinfo
->cinfo
, COL_INFO
, " (decrypted)");
839 return tvb_reported_length(tvb
);
842 /** The main OpcUa dissector functions.
843 * It uses tcp_dissect_pdus from packet-tcp.h
844 * to reassemble the TCP data.
846 static int dissect_opcua(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
848 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, FRAME_HEADER_LEN
,
849 get_opcua_message_len
, dissect_opcua_message
, data
);
850 return tvb_reported_length(tvb
);
853 /** Init plugin resources */
854 void proto_init_opcua(void)
856 debugprintf("proto_init_opcua called.\n");
858 opcua_load_keylog_file(g_opcua_debug_file_name
);
861 /** Cleanup plugin resources */
862 void proto_cleanup_opcua(void)
864 debugprintf("proto_cleanup_opcua called.\n");
868 /** secrets callback called from Wireshark when loading a capture file with OPC UA Keylog File. */
869 static void opcua_secrets_block_callback(const void *secrets
, unsigned size
)
871 char *tmp
= g_memdup2(secrets
, size
+ 1);
872 if (tmp
== NULL
) return; /* OOM */
874 debugprintf("Loading secrets block '%s'...\n", (const char*)secrets
);
875 debugprintf("size = %u\n", size
);
876 /* ensure data is zero terminated */
879 opcua_keylog_process_lines(tmp
);
883 /** plugin entry functions.
884 * This registers the OpcUa protocol.
886 void proto_register_opcua(void)
888 static hf_register_info hf
[] =
890 /* id full name abbreviation type display strings bitmask blurb HFILL */
891 {&hf_opcua_fragments
, {"Message fragments", "opcua.fragments", FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
892 {&hf_opcua_fragment
, {"Message fragment", "opcua.fragment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
893 {&hf_opcua_fragment_overlap
, {"Message fragment overlap", "opcua.fragment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
894 {&hf_opcua_fragment_overlap_conflicts
, {"Message fragment overlapping with conflicting data", "opcua.fragment.overlap.conflicts", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
895 {&hf_opcua_fragment_multiple_tails
, {"Message has multiple tail fragments", "opcua.fragment.multiple_tails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
896 {&hf_opcua_fragment_too_long_fragment
, {"Message fragment too long", "opcua.fragment.too_long_fragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
897 {&hf_opcua_fragment_error
, {"Message defragmentation error", "opcua.fragment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
898 {&hf_opcua_fragment_count
, {"Message fragment count", "opcua.fragment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
899 {&hf_opcua_reassembled_in
, {"Reassembled in", "opcua.reassembled.in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
900 {&hf_opcua_reassembled_length
, {"Reassembled length", "opcua.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}}
903 /** Setup protocol subtree array */
906 &ett_opcua_extensionobject
,
908 &ett_opcua_transport
,
913 proto_opcua
= proto_register_protocol("OpcUa Binary Protocol", "OpcUa", "opcua");
914 opcua_handle
= register_dissector("opcua", dissect_opcua
, proto_opcua
);
916 register_init_routine(proto_init_opcua
);
917 register_cleanup_routine(proto_cleanup_opcua
);
919 opcua_module
= prefs_register_protocol(proto_opcua
, proto_reg_handoff_opcua
);
920 prefs_register_filename_preference(opcua_module
, "debug_file", "OPCUA debug file",
921 "Redirect OPC UA Secure Conversion session keys to the file specified to enable decryption.",
922 &g_opcua_debug_file_name
, false);
924 prefs_register_enum_preference(opcua_module
, "signature_length", "Default signature length",
925 "Default signature length to use if the OpenSecureChannel message is missing.",
926 &g_opcua_default_sig_len
, opcua_sig_len_enum
, false);
928 registerTransportLayerTypes(proto_opcua
);
929 registerSecurityLayerTypes(proto_opcua
);
930 registerSequenceLayerTypes(proto_opcua
);
931 registerApplicationLayerTypes(proto_opcua
);
932 registerSimpleTypes(proto_opcua
);
933 registerEnumTypes(proto_opcua
);
934 registerComplexTypes();
935 registerServiceTypes();
936 registerFieldTypes(proto_opcua
);
938 proto_register_subtree_array(ett
, array_length(ett
));
939 proto_register_field_array(proto_opcua
, hf
, array_length(hf
));
941 reassembly_table_register(&opcua_reassembly_table
,
942 &addresses_reassembly_table_functions
);
943 secrets_register_type(SECRETS_TYPE_OPCUA
, opcua_secrets_block_callback
);
946 void proto_reg_handoff_opcua(void)
948 dissector_add_uint_range_with_preference("tcp.port", OPCUA_PORT_RANGE
, opcua_handle
);
952 * Editor modelines - https://www.wireshark.org/tools/modelines.html
957 * indent-tabs-mode: nil
960 * vi: set shiftwidth=4 tabstop=8 expandtab:
961 * :indentSize=4:tabSize=8:noTabs=true: