diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:53 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:53 +0000 |
commit | a86c5f7cae7ec9a3398300555a0b644689d946a1 (patch) | |
tree | 39fe4b107c71174fd1e8a8ceb9a4d2aa14116248 /epan/dissectors/packet-openvpn.c | |
parent | Releasing progress-linux version 4.2.6-1~progress7.99u1. (diff) | |
download | wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.tar.xz wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.zip |
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-openvpn.c')
-rw-r--r-- | epan/dissectors/packet-openvpn.c | 247 |
1 files changed, 96 insertions, 151 deletions
diff --git a/epan/dissectors/packet-openvpn.c b/epan/dissectors/packet-openvpn.c index 17e59e50..5727b7b9 100644 --- a/epan/dissectors/packet-openvpn.c +++ b/epan/dissectors/packet-openvpn.c @@ -21,6 +21,7 @@ #include <epan/packet.h> #include <epan/prefs.h> #include <epan/reassemble.h> +#include <epan/conversation.h> #include "packet-tcp.h" void proto_register_openvpn(void); @@ -50,29 +51,29 @@ void proto_reg_handoff_openvpn(void); #define P_CONTROL_HARD_RESET_CLIENT_V3 10 #define P_CONTROL_WKC_V1 11 -static gint ett_openvpn = -1; -static gint ett_openvpn_data = -1; -static gint ett_openvpn_packetarray = -1; -static gint ett_openvpn_type = -1; -static gint ett_openvpn_wkc = -1; -static gint hf_openvpn_data = -1; -static gint hf_openvpn_wkc_data = -1; -static gint hf_openvpn_wkc_length = -1; -static gint hf_openvpn_fragment_bytes = -1; -static gint hf_openvpn_hmac = -1; -static gint hf_openvpn_keyid = -1; -static gint hf_openvpn_mpid = -1; -static gint hf_openvpn_mpid_arrayelement = -1; -static gint hf_openvpn_mpid_arraylength = -1; -static gint hf_openvpn_net_time = -1; -static gint hf_openvpn_opcode = -1; -static gint hf_openvpn_pdu_type = -1; -static gint hf_openvpn_pid = -1; -static gint hf_openvpn_plen = -1; -static gint hf_openvpn_rsessionid = -1; -static gint hf_openvpn_sessionid = -1; -static gint hf_openvpn_peerid = -1; -static gint proto_openvpn = -1; +static int ett_openvpn; +static int ett_openvpn_data; +static int ett_openvpn_packetarray; +static int ett_openvpn_type; +static int ett_openvpn_wkc; +static int hf_openvpn_data; +static int hf_openvpn_wkc_data; +static int hf_openvpn_wkc_length; +static int hf_openvpn_fragment_bytes; +static int hf_openvpn_hmac; +static int hf_openvpn_keyid; +static int hf_openvpn_mpid; +static int hf_openvpn_mpid_arrayelement; +static int hf_openvpn_mpid_arraylength; +static int hf_openvpn_net_time; +static int hf_openvpn_opcode; +static int hf_openvpn_pdu_type; +static int hf_openvpn_pid; +static int hf_openvpn_plen; +static int hf_openvpn_rsessionid; +static int hf_openvpn_sessionid; +static int hf_openvpn_peerid; +static int proto_openvpn; static dissector_handle_t openvpn_udp_handle; static dissector_handle_t openvpn_tcp_handle; @@ -80,11 +81,11 @@ static dissector_handle_t openvpn_tcp_handle; static dissector_handle_t tls_handle; /* Preferences */ -static gboolean pref_long_format = TRUE; -static gboolean pref_tls_auth = FALSE; -static gboolean pref_tls_auth_override = FALSE; -static gboolean pref_tls_crypt_override = FALSE; -static guint tls_auth_hmac_size = 20; /* Default SHA-1 160 Bits */ +static bool pref_long_format = true; +static bool pref_tls_auth; +static bool pref_tls_auth_override; +static bool pref_tls_crypt_override; +static unsigned tls_auth_hmac_size = 20; /* Default SHA-1 160 Bits */ static const value_string openvpn_message_types[] = { @@ -105,18 +106,18 @@ static const value_string openvpn_message_types[] = /* everything used during the reassembly process */ static reassembly_table msg_reassembly_table; -static gint ett_openvpn_fragment = -1; -static gint ett_openvpn_fragments = -1; -static gint hf_openvpn_fragment = -1; -static gint hf_openvpn_fragment_count = -1; -static gint hf_openvpn_fragment_error = -1; -static gint hf_openvpn_fragment_multiple_tails = -1; -static gint hf_openvpn_fragment_overlap = -1; -static gint hf_openvpn_fragment_overlap_conflicts = -1; -static gint hf_openvpn_fragment_too_long_fragment = -1; -static gint hf_openvpn_fragments = -1; -static gint hf_openvpn_reassembled_in = -1; -static gint hf_openvpn_reassembled_length = -1; +static int ett_openvpn_fragment; +static int ett_openvpn_fragments; +static int hf_openvpn_fragment; +static int hf_openvpn_fragment_count; +static int hf_openvpn_fragment_error; +static int hf_openvpn_fragment_multiple_tails; +static int hf_openvpn_fragment_overlap; +static int hf_openvpn_fragment_overlap_conflicts; +static int hf_openvpn_fragment_too_long_fragment; +static int hf_openvpn_fragments; +static int hf_openvpn_reassembled_in; +static int hf_openvpn_reassembled_length; static const fragment_items openvpn_frag_items = { /* Fragment subtrees */ @@ -144,11 +145,11 @@ static const fragment_items openvpn_frag_items = { /* we check the leading 4 byte of a suspected hmac for 0x00 bytes, if more than 1 byte out of the 4 provided contains 0x00, the hmac is considered not valid, which suggests that no tls auth is used. - unfortunatly there is no other way to detect tls auth on the fly */ -static gboolean -check_for_valid_hmac(guint32 hmac) + unfortunately there is no other way to detect tls auth on the fly */ +static bool +check_for_valid_hmac(uint32_t hmac) { - gint c = 0; + int c = 0; if ((hmac & 0x000000FF) == 0x00000000) { c++; } @@ -162,30 +163,25 @@ check_for_valid_hmac(guint32 hmac) c++; } if (c > 1) { - return FALSE; + return false; } else { - return TRUE; + return true; } } static int -dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvpn_tree, proto_tree *parent_tree, gint offset) +dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvpn_tree, proto_tree *parent_tree, int offset) { - gboolean tls_auth; - gboolean tls_crypt = FALSE; - guint openvpn_keyid; - guint openvpn_opcode; - guint32 msg_mpid = -1; - guint32 msg_sessionid = -1; - guint8 openvpn_predict_tlsauth_arraylength; + bool tls_auth; + bool tls_crypt = false; + unsigned openvpn_keyid; + unsigned openvpn_opcode; + uint32_t msg_sessionid = -1; + uint8_t openvpn_predict_tlsauth_arraylength; proto_item *ti2; proto_tree *packetarray_tree, *type_tree; - guint32 msg_length_remaining; - gboolean msg_lastframe; - fragment_head *frag_msg; - tvbuff_t *new_tvb; - gboolean save_fragmented; - gint wkc_offset = -1; + uint32_t msg_length_remaining; + int wkc_offset = -1; /* Clear out stuff in the info column */ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME); @@ -222,54 +218,54 @@ dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvp offset += 8; /* tls-auth detection (this can be overridden by preferences */ - openvpn_predict_tlsauth_arraylength = tvb_get_guint8(tvb, offset); + openvpn_predict_tlsauth_arraylength = tvb_get_uint8(tvb, offset); /* if the first 4 bytes that would, if tls-auth is used, contain part of the hmac, lack entropy, we assume no tls-auth is used */ - if (pref_tls_auth_override == FALSE) { + if (pref_tls_auth_override == false) { if ((openvpn_opcode != P_DATA_V1) && (openvpn_predict_tlsauth_arraylength > 0) && check_for_valid_hmac(tvb_get_ntohl(tvb, offset))) { - tls_auth = TRUE; + tls_auth = true; } else { - tls_auth = FALSE; + tls_auth = false; } } else { tls_auth = pref_tls_auth; } - if (openvpn_opcode == P_CONTROL_HARD_RESET_CLIENT_V3 || openvpn_opcode == P_CONTROL_WKC_V1 || pref_tls_crypt_override == TRUE) { + if (openvpn_opcode == P_CONTROL_HARD_RESET_CLIENT_V3 || openvpn_opcode == P_CONTROL_WKC_V1 || pref_tls_crypt_override == true) { /* these opcodes are always tls-crypt*/ - tls_crypt = TRUE; - tls_auth = FALSE; + tls_crypt = true; + tls_auth = false; } - if (tls_auth == TRUE) { + if (tls_auth == true) { proto_tree_add_item(openvpn_tree, hf_openvpn_hmac, tvb, offset, tls_auth_hmac_size, ENC_NA); offset += tls_auth_hmac_size; } - if (tls_auth == TRUE || tls_crypt == TRUE) { + if (tls_auth == true || tls_crypt == true) { if (tvb_reported_length_remaining(tvb, offset) >= 8) { proto_tree_add_item(openvpn_tree, hf_openvpn_pid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; - if (pref_long_format || tls_crypt == TRUE) { + if (pref_long_format || tls_crypt == true) { proto_tree_add_item(openvpn_tree, hf_openvpn_net_time, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } - if (tls_crypt == TRUE) { + if (tls_crypt == true) { /* tls-crypt uses HMAC-SHA256 */ proto_tree_add_item(openvpn_tree, hf_openvpn_hmac, tvb, offset, 32, ENC_NA); offset += 32; } } - if (tvb_reported_length_remaining(tvb, offset) >= 1 && tls_crypt == FALSE) { + if (tvb_reported_length_remaining(tvb, offset) >= 1 && tls_crypt == false) { /* read P_ACK packet-id array length */ - gint pid_arraylength = tvb_get_guint8(tvb, offset); - gint i; + int pid_arraylength = tvb_get_uint8(tvb, offset); + int i; proto_tree_add_item(openvpn_tree, hf_openvpn_mpid_arraylength, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; @@ -289,10 +285,9 @@ dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvp } /* if we have a P_CONTROL packet */ - if (openvpn_opcode != P_ACK_V1 && tls_crypt == FALSE) { + if (openvpn_opcode != P_ACK_V1 && tls_crypt == false) { /* read Message Packet-ID */ if (tvb_reported_length_remaining(tvb, offset) >= 4) { - msg_mpid = tvb_get_bits32(tvb, offset*8, 32, ENC_BIG_ENDIAN); proto_tree_add_item(openvpn_tree, hf_openvpn_mpid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } @@ -306,8 +301,8 @@ dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvp return tvb_captured_length(tvb); } - gint data_len = msg_length_remaining; - gint wkc_len = -1; + int data_len = msg_length_remaining; + int wkc_len = -1; if ((openvpn_opcode == P_CONTROL_HARD_RESET_CLIENT_V3 || openvpn_opcode == P_CONTROL_WKC_V1) && msg_length_remaining >= 2) { @@ -339,80 +334,30 @@ dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvp return tvb_captured_length(tvb); } - /* Try to reassemble */ + /* Control message, possibly fragmented, carrying TLS. Try to reassemble. */ - /* an ordinary openvpn control packet contains 100 bytes only if it is part of a - fragmented message and is not the last fragment of the current transmission. - Note that the tvb contains exactly one openvpn PDU: - UDP: by definition; - TCP: because of the use of tcp_dissect_pdus(). - */ - if (msg_length_remaining == 100) { - msg_lastframe = FALSE; - } else { - msg_lastframe = TRUE; - } - - save_fragmented = pinfo->fragmented; - pinfo->fragmented = TRUE; - - frag_msg = fragment_add_seq_next( - &msg_reassembly_table, - tvb, - offset, - pinfo, - msg_sessionid, /* ID for fragments belonging together */ - NULL, - msg_length_remaining, /* fragment length - to the end */ - !(msg_lastframe)); /* More fragments ? */ - - /* show "data" fragment on tree unless "reassembled" message has just one part. */ - /* i.e., show if ("not reassembled") or ("reassembled" and "has multiple fragments") */ - if ((frag_msg == NULL) || (frag_msg->next != NULL)) { - proto_tree *data_tree; - data_tree = proto_tree_add_subtree_format(openvpn_tree, tvb, offset, -1, - ett_openvpn_data, NULL, "Message fragment (%d bytes)", - tvb_captured_length_remaining(tvb, offset)); - - proto_tree_add_item(data_tree, hf_openvpn_fragment_bytes, tvb, offset, -1, ENC_NA); - } - - new_tvb = NULL; - if (frag_msg) { - if (msg_lastframe) { /* Reassembled */ - new_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Message", - frag_msg, &openvpn_frag_items, NULL, openvpn_tree); - if (frag_msg->next != NULL) { /* multiple frags ? */ - col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled "); /* overwritten by next dissector */ - } - - } else { /* Not last packet of reassembled Short Message */ - col_append_fstr(pinfo->cinfo, COL_INFO, " (Message fragment %d) ", msg_mpid); - if (pinfo->num != frag_msg->reassembled_in) { - /* Add a "Reassembled in" link if not reassembled in this frame */ - proto_tree_add_uint(openvpn_tree, hf_openvpn_reassembled_in, - tvb, 0, 0, frag_msg->reassembled_in); - } - } - } /* if (frag_msg) */ + streaming_reassembly_info_t *streaming_reassembly_info = NULL; - pinfo->fragmented = save_fragmented; - - /* Now see if we need to call subdissector. - new_tvb is non-null if we "reassembled* a message (even just one fragment) */ - - if (new_tvb) { - /* call SSL/TLS dissector if we just processed the last fragment */ - call_dissector(tls_handle, new_tvb, pinfo, parent_tree); + conversation_t *conv = find_or_create_conversation_by_id(pinfo, CONVERSATION_OPENVPN, msg_sessionid); + streaming_reassembly_info = conversation_get_proto_data(conv, proto_openvpn); + if (!streaming_reassembly_info) { + streaming_reassembly_info = streaming_reassembly_info_new(); + conversation_add_proto_data(conv, proto_openvpn, streaming_reassembly_info); } + reassemble_streaming_data_and_call_subdissector(tvb, pinfo, offset, + msg_length_remaining, openvpn_tree, parent_tree, msg_reassembly_table, + streaming_reassembly_info, get_virtual_frame_num64(tvb, pinfo, offset), + tls_handle, parent_tree, NULL /* should it be tcpinfo if we have it? */, "OpenVPN Message", + &openvpn_frag_items, hf_openvpn_fragment_bytes); + return tvb_captured_length(tvb); } -static guint -get_msg_length(packet_info *pinfo _U_, tvbuff_t *tvb, gint offset, void *data _U_) +static unsigned +get_msg_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { - return (guint)tvb_get_ntohs(tvb, offset) + 2; /* length field is at offset 0, + return (unsigned)tvb_get_ntohs(tvb, offset) + 2; /* length field is at offset 0, +2 to account for the length field itself */ } @@ -434,7 +379,7 @@ static int dissect_openvpn_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { tcp_dissect_pdus( tvb, pinfo, tree, - TRUE, /* should data be reassembled? */ + true, /* should data be reassembled? */ 2, /* how much bytes do we need for get_msg_length to be successful, since the length is the first thing in an openvpn packet we choose 2 */ get_msg_length, /* fptr for function to get the packetlength of current frame */ @@ -574,25 +519,25 @@ proto_register_openvpn(void) }, { &hf_openvpn_fragment_overlap, { "Message fragment overlap", "openvpn.fragment.overlap", - FT_BOOLEAN, 0, + FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_openvpn_fragment_overlap_conflicts, { "Message fragment overlapping with conflicting data", "openvpn.fragment.overlap.conflicts", - FT_BOOLEAN, 0, + FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_openvpn_fragment_multiple_tails, { "Message has multiple tail fragments", "openvpn.fragment.multiple_tails", - FT_BOOLEAN, 0, + FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_openvpn_fragment_too_long_fragment, { "Message fragment too long", "openvpn.fragment.too_long_fragment", - FT_BOOLEAN, 0, + FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, @@ -623,7 +568,7 @@ proto_register_openvpn(void) }; /* Setup protocol subtree array */ - static gint *ett[] = { + static int *ett[] = { &ett_openvpn, &ett_openvpn_type, &ett_openvpn_data, @@ -683,7 +628,7 @@ proto_register_openvpn(void) " is inserted after the HMAC signature." " This field can either be 4 bytes or 8 bytes including an optional time_t timestamp long.\n" " This option is only evaluated if tls_auth_hmac_size > 0.\n" - " The default value is TRUE.", + " The default value is true.", &pref_long_format); } |