wiretap: add read/write support for Decryption Secrets Block (DSB)

Support reading and writing pcapng files with DSBs. A DSB may occur
multiple times but should appear before packets that need those
decryption secrets (so it cannot be moved to the end like NRB). The TLS
dissector will be updated in the future to make use of these secrets.
pcapng spec update: https://github.com/pcapng/pcapng/pull/54

As DSBs may be interleaved with packets, do not even try to read it in
pcapng_open (as is done for IDBs). Instead process them during the
sequential read, appending them to the 'wtap::dsbs' array.

Writing is more complicated, secrets may initially not be available when
'wtap_dumper' is created. As they may become available in 'wtap::dsbs'
as more packets are read, allow 'wtap_dumper::dsbs_growing' to reference
this array. This saves every user from checking/dumping DSBs.

If the wtap user needs to insert extra DSBs (while preserving existing
DSBs), they can set the 'wtap_dumper::dsbs_initial' field.

The test file was creating using a patched editcap (future patch) and
combined using mergecap (which required a change to preserve the DSBs).

Change-Id: I74e4ee3171bd852a89ea0f6fbae9e0f65ed6eda9
Ping-Bug: 15252
Reviewed-on: https://code.wireshark.org/review/30692
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Peter Wu 2018-11-17 13:56:12 +01:00 committed by Anders Broman
parent ad21e3121f
commit 52a6671439
18 changed files with 394 additions and 11 deletions

View File

@ -20,6 +20,7 @@
#include <epan/show_exception.h>
#include <epan/addr_resolv.h>
#include <epan/wmem/wmem.h>
#include <wiretap/secrets-types.h>
#include <epan/dissectors/packet-pcap_pktdata.h>
@ -121,6 +122,10 @@ static int hf_pcapng_record_ipv6 = -1;
static int hf_pcapng_record_name = -1;
static int hf_pcapng_record_padding = -1;
static int hf_pcapng_dsb_secrets_type = -1;
static int hf_pcapng_dsb_secrets_length = -1;
static int hf_pcapng_dsb_secrets_data = -1;
static int hf_pcapng_darwin_process_id = -1;
static int hf_pcapng_option_code_darwin_process_info = -1;
static int hf_pcapng_option_darwin_process_name = -1;
@ -531,6 +536,11 @@ static const value_string flags_reception_type_vals[] = {
{ 0, NULL }
};
static const value_string dsb_secrets_types_vals[] = {
{ SECRETS_TYPE_TLS, "TLS Key Log" },
{ 0, NULL }
};
void proto_register_pcapng(void);
void proto_reg_handoff_pcapng(void);
@ -1570,6 +1580,30 @@ static gint dissect_block(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 4 - 8 - 4 - 4 - captured_length - ((captured_length % 4)?(4 - (captured_length % 4)):0));
offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL);
break;
case BLOCK_DSB:
{
guint32 secrets_length;
proto_tree_add_item(block_data_tree, hf_pcapng_dsb_secrets_type, tvb, offset, 4, encoding);
offset += 4;
proto_tree_add_item_ret_uint(block_data_tree, hf_pcapng_dsb_secrets_length, tvb, offset, 4, encoding, &secrets_length);
offset += 4;
proto_tree_add_item(block_data_tree, hf_pcapng_dsb_secrets_data, tvb, offset, secrets_length, encoding);
offset += secrets_length;
guint32 padlen = (4 - (secrets_length & 3)) & 3;
if (padlen) {
proto_tree_add_item(block_data_tree, hf_pcapng_record_padding, tvb, offset, padlen, ENC_NA);
offset += padlen;
}
if (block_data_length > 4 + 4 + secrets_length + padlen) {
next_tvb = tvb_new_subset_length(tvb, offset, block_data_length - 4 - 4 - secrets_length - padlen);
offset += dissect_options(block_data_tree, pinfo, block_type, next_tvb, encoding, NULL);
}
}
break;
case BLOCK_DARWIN_PROCESS:
proto_item_append_text(block_item, " %u", info->darwin_process_event_number);
@ -1584,7 +1618,6 @@ static gint dissect_block(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
break;
case BLOCK_IRIG_TIMESTAMP:
case BLOCK_ARINC_429:
case BLOCK_DSB:
default:
offset += block_data_length;
}
@ -2138,6 +2171,21 @@ proto_register_pcapng(void)
FT_STRINGZ, STR_ASCII, NULL, 0x00,
NULL, HFILL }
},
{ &hf_pcapng_dsb_secrets_type,
{ "Secrets Type", "pcapng.dsb.secrets_type",
FT_UINT32, BASE_HEX, VALS(dsb_secrets_types_vals), 0x00,
NULL, HFILL }
},
{ &hf_pcapng_dsb_secrets_length,
{ "Secrets Type", "pcapng.dsb.secrets_length",
FT_UINT32, BASE_DEC, NULL, 0x00,
NULL, HFILL }
},
{ &hf_pcapng_dsb_secrets_data,
{ "Secrets Data", "pcapng.dsb.secrets_data",
FT_BYTES, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_pcapng_darwin_process_id,
{ "Darwin Process ID", "pcapng.darwin.process_id",
FT_UINT32, BASE_DEC_HEX, NULL, 0x00,

Binary file not shown.

View File

@ -0,0 +1,2 @@
# first
CLIENT_RANDOM f67a28b386b31c620d76c0026fdd9888edbe6bf0f5b715b2caca158f84ae9d66 cc38e78182b9dfd74ef3103d79bbc99cfc9b4dad209ed209062b5481e63353128da7571b13cfd4d3a5ae7d0520fb346d

View File

@ -0,0 +1 @@
CLIENT_RANDOM 1e0d63b41d7c7bb639559cfc9f06ffd5c65fe4a9df31abc5af833b0d834436f4 c7f5dda54fb417181cb26e52112afaf9e1756addd77d3c479d96a609c0d3c9bb9929c8475cafb4dbad8f72e868a43e02

View File

@ -110,6 +110,53 @@ class case_fileformat_pcapng(subprocesstest.SubprocessTestCase):
)
self.assertTrue(self.diffOutput(capture_proc.stdout_str, fileformats_baseline_str, 'tshark', baseline_file))
@fixtures.fixture
def check_pcapng_dsb_fields(request, cmd_tshark):
'''Factory that checks whether the DSB within the capture file matches.'''
self = request.instance
def check_dsb_fields_real(outfile, fields):
proc = self.runProcess((cmd_tshark,
'-r', outfile,
'-Xread_format:MIME Files Format',
'-Tfields',
'-e', 'pcapng.dsb.secrets_type',
'-e', 'pcapng.dsb.secrets_length',
'-e', 'pcapng.dsb.secrets_data',
'-Y', 'pcapng.dsb.secrets_data'
))
# Convert "t1,t2 l1,l2 v1,2" -> [(t1, l1, v1), (t2, l2, v2)]
output = proc.stdout_str.strip()
actual = list(zip(*[x.split(",") for x in output.split('\t')]))
def format_field(field):
t, l, v = field
v_hex = ''.join('%02x' % c for c in v)
return ('0x%08x' % t, str(l), v_hex)
fields = [format_field(field) for field in fields]
self.assertEqual(fields, actual)
return check_dsb_fields_real
@fixtures.mark_usefixtures('base_env')
@fixtures.uses_fixtures
class case_fileformat_pcapng_dsb(subprocesstest.SubprocessTestCase):
def test_pcapng_dsb_1(self, cmd_tshark, dirs, capture_file, check_pcapng_dsb_fields):
'''Check that DSBs are preserved while rewriting files.'''
dsb_keys1 = os.path.join(dirs.key_dir, 'tls12-dsb-1.keys')
dsb_keys2 = os.path.join(dirs.key_dir, 'tls12-dsb-2.keys')
outfile = self.filename_from_id('tls12-dsb-same.pcapng')
self.runProcess((cmd_tshark,
'-r', capture_file('tls12-dsb.pcapng'),
'-w', outfile,
))
with open(dsb_keys1, 'r') as f:
dsb1_contents = f.read().encode('utf8')
with open(dsb_keys2, 'r') as f:
dsb2_contents = f.read().encode('utf8')
check_pcapng_dsb_fields(outfile, (
(0x544c534b, len(dsb1_contents), dsb1_contents),
(0x544c534b, len(dsb2_contents), dsb2_contents),
))
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures

View File

@ -14,6 +14,7 @@ set(WIRETAP_PUBLIC_HEADERS
merge.h
pcap-encap.h
pcapng_module.h
secrets-types.h
wtap.h
wtap_opttypes.h
)

View File

@ -2347,6 +2347,9 @@ wtap_dump_init_dumper(int file_type_subtype, wtap_compression_type compression_t
descr_mand->interface_statistics = NULL;
g_array_append_val(wdh->interface_data, descr);
}
/* Set Decryption Secrets Blocks */
wdh->dsbs_initial = params->dsbs_initial;
wdh->dsbs_growing = params->dsbs_growing;
return wdh;
}
@ -2653,6 +2656,7 @@ wtap_dump_close(wtap_dumper *wdh, int *err)
}
g_free(wdh->priv);
wtap_block_array_free(wdh->interface_data);
wtap_block_array_free(wdh->dsbs_initial);
g_free(wdh);
return ret;
}

View File

@ -25,6 +25,7 @@
#include "merge.h"
#include "wtap_opttypes.h"
#include "pcapng.h"
#include "wtap-int.h"
#include <wsutil/filesystem.h>
#include "wsutil/os_version_info.h"
@ -832,6 +833,7 @@ merge_process_packets(wtap_dumper *pdh, const int file_type,
merge_in_file_t *in_files, const guint in_file_count,
const gboolean do_append, guint snaplen,
merge_progress_callback_t* cb,
GArray *dsb_combined,
int *err, gchar **err_info, guint *err_fileno,
guint32 *err_framenum)
{
@ -911,6 +913,18 @@ merge_process_packets(wtap_dumper *pdh, const int file_type,
}
}
}
/*
* If any DSBs were read before this record, be sure to pass those now
* such that wtap_dump can pick it up.
*/
if (dsb_combined && in_file->wth->dsbs) {
GArray *in_dsb = in_file->wth->dsbs;
for (guint i = in_file->dsbs_seen; i < in_dsb->len; i++) {
wtap_block_t wblock = g_array_index(in_dsb, wtap_block_t, i);
g_array_append_val(dsb_combined, wblock);
in_file->dsbs_seen++;
}
}
if (!wtap_dump(pdh, rec, wtap_get_buf_ptr(in_file->wth), err, err_info)) {
status = MERGE_ERR_CANT_WRITE_OUTFILE;
@ -921,8 +935,6 @@ merge_process_packets(wtap_dumper *pdh, const int file_type,
if (cb)
cb->callback_func(MERGE_EVENT_DONE, count, in_files, in_file_count, cb->data);
merge_close_in_files(in_file_count, in_files);
if (status == MERGE_OK || status == MERGE_USER_ABORTED) {
if (!wtap_dump_close(pdh, err))
status = MERGE_ERR_CANT_CLOSE_OUTFILE;
@ -937,6 +949,12 @@ merge_process_packets(wtap_dumper *pdh, const int file_type,
(void)wtap_dump_close(pdh, &close_err);
}
/* Close the input files after the output file in case the latter still
* holds references to blocks in the input file (such as the DSB). Even if
* those DSBs are only written when wtap_dump is called and nothing bad will
* happen now, let's keep all pointers in pdh valid for correctness sake. */
merge_close_in_files(in_file_count, in_files);
if (status == MERGE_OK || in_file == NULL) {
*err_fileno = 0;
*err_framenum = 0;
@ -964,6 +982,7 @@ merge_files_common(const gchar* out_filename, /* normal output mode */
wtap_dumper *pdh;
GArray *shb_hdrs = NULL;
wtapng_iface_descriptions_t *idb_inf = NULL;
GArray *dsb_combined = NULL;
g_assert(in_file_count > 0);
g_assert(in_filenames != NULL);
@ -1017,6 +1036,8 @@ merge_files_common(const gchar* out_filename, /* normal output mode */
/* XXX other blocks like NRB are now discarded. */
params.shb_hdrs = shb_hdrs;
params.idb_inf = idb_inf;
dsb_combined = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
params.dsbs_growing = dsb_combined;
}
if (out_filename) {
pdh = wtap_dump_open(out_filename, file_type, WTAP_UNCOMPRESSED, &params, err);
@ -1031,6 +1052,9 @@ merge_files_common(const gchar* out_filename, /* normal output mode */
g_free(in_files);
wtap_block_array_free(shb_hdrs);
wtap_free_idb_info(idb_inf);
if (dsb_combined) {
g_array_free(dsb_combined, TRUE);
}
*err_framenum = 0;
return MERGE_ERR_CANT_OPEN_OUTFILE;
}
@ -1039,12 +1063,15 @@ merge_files_common(const gchar* out_filename, /* normal output mode */
cb->callback_func(MERGE_EVENT_READY_TO_MERGE, 0, in_files, in_file_count, cb->data);
status = merge_process_packets(pdh, file_type, in_files, in_file_count,
do_append, snaplen, cb, err, err_info,
do_append, snaplen, cb, dsb_combined, err, err_info,
err_fileno, err_framenum);
g_free(in_files);
wtap_block_array_free(shb_hdrs);
wtap_free_idb_info(idb_inf);
if (dsb_combined) {
g_array_free(dsb_combined, TRUE);
}
return status;
}

View File

@ -34,6 +34,7 @@ typedef struct merge_in_file_s {
guint32 packet_num; /* current packet number */
gint64 size; /* file size */
GArray *idb_index_map; /* used for mapping the old phdr interface_id values to new during merge */
guint dsbs_seen; /* number of elements processed so far from wth->dsbs */
} merge_in_file_t;
/** Return values from merge_files(). */

View File

@ -29,6 +29,7 @@
#include "pcap-encap.h"
#include "pcapng.h"
#include "pcapng_module.h"
#include "secrets-types.h"
#if 0
#define pcapng_debug(...) g_warning(__VA_ARGS__)
@ -260,6 +261,7 @@ register_pcapng_block_type_handler(guint block_type, block_reader reader,
case BLOCK_TYPE_NRB:
case BLOCK_TYPE_ISB:
case BLOCK_TYPE_EPB:
case BLOCK_TYPE_DSB:
case BLOCK_TYPE_SYSDIG_EVENT:
case BLOCK_TYPE_SYSTEMD_JOURNAL:
/*
@ -352,8 +354,9 @@ register_pcapng_block_type_handler(guint block_type, block_reader reader,
#define BT_INDEX_NRB 3
#define BT_INDEX_ISB 4
#define BT_INDEX_EVT 5
#define BT_INDEX_DSB 6
#define NUM_BT_INDICES 6
#define NUM_BT_INDICES 7
typedef struct {
option_handler_fn hfunc;
@ -395,6 +398,10 @@ get_block_type_index(guint block_type, guint *bt_index)
*bt_index = BT_INDEX_EVT;
break;
case BLOCK_TYPE_DSB:
*bt_index = BT_INDEX_DSB;
break;
default:
/*
* This is a block type we don't process; either we ignore it,
@ -1057,6 +1064,56 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
return TRUE;
}
static gboolean
pcapng_read_decryption_secrets_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
wtapng_block_t *wblock, int *err, gchar **err_info)
{
guint to_read;
pcapng_decryption_secrets_block_t dsb;
wtapng_dsb_mandatory_t *dsb_mand;
/* read block content */
if (!wtap_read_bytes(fh, &dsb, sizeof(dsb), err, err_info)) {
pcapng_debug("%s: failed to read DSB", G_STRFUNC);
return FALSE;
}
/* mandatory values */
wblock->block = wtap_block_create(WTAP_BLOCK_DSB);
dsb_mand = (wtapng_dsb_mandatory_t *)wtap_block_get_mandatory_data(wblock->block);
if (pn->byte_swapped) {
dsb_mand->secrets_type = GUINT32_SWAP_LE_BE(dsb.secrets_type);
dsb_mand->secrets_len = GUINT32_SWAP_LE_BE(dsb.secrets_len);
} else {
dsb_mand->secrets_type = dsb.secrets_type;
dsb_mand->secrets_len = dsb.secrets_len;
}
/* Sanity check: assume the secrets are not larger than 1 GiB */
if (dsb_mand->secrets_len > 1024 * 1024 * 1024) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("%s: secrets block is too large: %u", G_STRFUNC, dsb_mand->secrets_len);
return FALSE;
}
dsb_mand->secrets_data = (char *)g_malloc0(dsb_mand->secrets_len);
if (!wtap_read_bytes(fh, dsb_mand->secrets_data, dsb_mand->secrets_len, err, err_info)) {
pcapng_debug("%s: failed to read DSB", G_STRFUNC);
return FALSE;
}
/* Skip past padding and discard options (not supported yet). */
to_read = bh->block_total_length - MIN_DSB_SIZE - dsb_mand->secrets_len;
if (!wtap_read_bytes(fh, NULL, to_read, err, err_info)) {
pcapng_debug("%s: failed to read DSB options", G_STRFUNC);
return FALSE;
}
/*
* We don't return these to the caller in pcapng_read().
*/
wblock->internal = TRUE;
return TRUE;
}
static gboolean
pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info, gboolean enhanced)
@ -2519,6 +2576,10 @@ pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, in
if (!pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR;
break;
case(BLOCK_TYPE_DSB):
if (!pcapng_read_decryption_secrets_block(fh, &bh, pn, wblock, err, err_info))
return PCAPNG_BLOCK_ERROR;
break;
case(BLOCK_TYPE_SYSDIG_EVENT):
/* case(BLOCK_TYPE_SYSDIG_EVF): */
if (!pcapng_read_sysdig_event_block(fh, &bh, pn, wblock, err, err_info))
@ -2581,6 +2642,14 @@ pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
g_array_append_val(pcapng->interfaces, iface_info);
}
/* Process a DSB that we have just read. */
static void
pcapng_process_dsb(wtap *wth, wtapng_block_t *wblock)
{
/* Store DSB such that it can be saved by the dumper. */
g_array_append_val(wth->dsbs, wblock->block);
}
/* classic wtap: open capture file */
wtap_open_return_val
pcapng_open(wtap *wth, int *err, gchar **err_info)
@ -2660,6 +2729,10 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
wth->subtype_close = pcapng_close;
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
/* Always initialize the list of Decryption Secret Blocks such that a
* wtap_dumper can refer to it right after opening the capture file. */
wth->dsbs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
/* Loop over all IDB:s that appear before any packets */
while (1) {
/* peek at next block */
@ -2759,6 +2832,13 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
wtap_block_free(wblock.block);
break;
case(BLOCK_TYPE_DSB):
/* Decryption secrets. */
pcapng_debug("pcapng_read: block type BLOCK_TYPE_DSB");
pcapng_process_dsb(wth, &wblock);
/* Do not free wblock.block, it is consumed by pcapng_process_dsb */
break;
case(BLOCK_TYPE_NRB):
/* More name resolution entries */
pcapng_debug("pcapng_read: block type BLOCK_TYPE_NRB");
@ -3437,6 +3517,49 @@ pcapng_write_systemd_journal_export_block(wtap_dumper *wdh, const wtap_rec *rec,
}
static gboolean
pcapng_write_decryption_secrets_block(wtap_dumper *wdh, wtap_block_t sdata, int *err)
{
pcapng_block_header_t bh;
pcapng_decryption_secrets_block_t dsb;
wtapng_dsb_mandatory_t *mand_data = (wtapng_dsb_mandatory_t *)wtap_block_get_mandatory_data(sdata);
guint pad_len = (4 - (mand_data->secrets_len & 3)) & 3;
/* write block header */
bh.block_type = BLOCK_TYPE_DSB;
bh.block_total_length = MIN_DSB_SIZE + mand_data->secrets_len + pad_len;
pcapng_debug("%s: Total len %u", G_STRFUNC, bh.block_total_length);
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
return FALSE;
wdh->bytes_dumped += sizeof bh;
/* write block fixed content */
dsb.secrets_type = mand_data->secrets_type;
dsb.secrets_len = mand_data->secrets_len;
if (!wtap_dump_file_write(wdh, &dsb, sizeof dsb, err))
return FALSE;
wdh->bytes_dumped += sizeof dsb;
if (!wtap_dump_file_write(wdh, mand_data->secrets_data, mand_data->secrets_len, err))
return FALSE;
wdh->bytes_dumped += mand_data->secrets_len;
if (pad_len) {
const guint32 zero_pad = 0;
if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
return FALSE;
wdh->bytes_dumped += pad_len;
}
/* write block footer */
if (!wtap_dump_file_write(wdh, &bh.block_total_length,
sizeof bh.block_total_length, err))
return FALSE;
wdh->bytes_dumped += sizeof bh.block_total_length;
return TRUE;
}
/*
* libpcap's maximum pcapng block size is currently 16MB.
*
@ -4258,6 +4381,20 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
block_handler *handler;
#endif
/* Write (optional) Decryption Secrets Blocks that were collected while
* reading packet blocks. */
if (wdh->dsbs_growing) {
for (guint i = wdh->dsbs_growing_written; i < wdh->dsbs_growing->len; i++) {
pcapng_debug("%s: writing DSB %u", G_STRFUNC, i);
wtap_block_t dsb = g_array_index(wdh->dsbs_growing, wtap_block_t, i);
if (!pcapng_write_decryption_secrets_block(wdh, dsb, err)) {
return FALSE;
}
++wdh->dsbs_growing_written;
}
}
pcapng_debug("%s: encap = %d (%s) rec type = %u", G_STRFUNC,
rec->rec_header.packet_header.pkt_encap,
wtap_encap_string(rec->rec_header.packet_header.pkt_encap),
@ -4395,6 +4532,16 @@ pcapng_dump_open(wtap_dumper *wdh, int *err)
}
/* Write (optional) fixed Decryption Secrets Blocks. */
if (wdh->dsbs_initial) {
for (i = 0; i < wdh->dsbs_initial->len; i++) {
wtap_block_t dsb = g_array_index(wdh->dsbs_initial, wtap_block_t, i);
if (!pcapng_write_decryption_secrets_block(wdh, dsb, err)) {
return FALSE;
}
}
}
return TRUE;
}

View File

@ -53,6 +53,14 @@ typedef struct pcapng_interface_statistics_block_s {
/* ... Options ... */
} pcapng_interface_statistics_block_t;
/* pcapng: Decryption Secrets Block file encoding */
typedef struct pcapng_decryption_secrets_block_s {
guint32 secrets_type; /* Secrets Type, see secrets-types.h */
guint32 secrets_len; /* Size of variable-length secrets data. */
/* x bytes Secrets Data. */
/* ... Options ... */
} pcapng_decryption_secrets_block_t;
struct pcapng_option_header {
guint16 type;
guint16 value_length;
@ -62,6 +70,7 @@ struct pcapng_option_header {
* Minimum IDB size = minimum block size + size of fixed length portion of IDB.
*/
#define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
#define MIN_DSB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_decryption_secrets_block_t)))
wtap_open_return_val pcapng_open(wtap *wth, int *err, gchar **err_info);
gboolean pcapng_dump_open(wtap_dumper *wdh, int *err);

View File

@ -25,6 +25,7 @@
#define BLOCK_TYPE_IRIG_TS 0x00000007 /* IRIG Timestamp Block */
#define BLOCK_TYPE_ARINC_429 0x00000008 /* ARINC 429 in AFDX Encapsulation Information Block */
#define BLOCK_TYPE_SYSTEMD_JOURNAL 0x00000009 /* systemd journal entry */
#define BLOCK_TYPE_DSB 0x0000000A /* Decryption Secrets Block */
#define BLOCK_TYPE_SYSDIG_EVENT 0x00000204 /* Sysdig Event Block */
#define BLOCK_TYPE_SYSDIG_EVF 0x00000208 /* Sysdig Event Block with flags */

19
wiretap/secrets-types.h Normal file
View File

@ -0,0 +1,19 @@
/* secrets-types.h
* Identifiers used by Decryption Secrets Blocks (DSB).
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __SECRETS_TYPES_H__
#define __SECRETS_TYPES_H__
/*
* Type describing the format of the opaque secrets value in a pcapng DSB.
*/
#define SECRETS_TYPE_TLS 0x544c534b /* TLS Key Log */
#endif /* __SECRETS_TYPES_H__ */

View File

@ -42,6 +42,7 @@ struct wtap {
GArray *shb_hdrs;
GArray *interface_data; /**< An array holding the interface data from pcapng IDB:s or equivalent(?)*/
GArray *nrb_hdrs; /**< holds the Name Res Block's comment/custom_opts, or NULL */
GArray *dsbs; /**< An array of DSBs (of type wtap_block_t), or NULL if not supported. */
void *priv; /* this one holds per-file state and is free'd automatically by wtap_close() */
void *wslua_data; /* this one holds wslua state info and is not free'd */
@ -102,6 +103,14 @@ struct wtap_dumper {
GArray *shb_hdrs;
GArray *nrb_hdrs; /**< name resolution comment/custom_opt, or NULL */
GArray *interface_data; /**< An array holding the interface data from pcapng IDB:s or equivalent(?) NULL if not present.*/
GArray *dsbs_initial; /**< An array of initial DSBs (of type wtap_block_t) */
/*
* Additional blocks that might grow as data is being collected.
* Subtypes should write these blocks before writing new packet blocks.
*/
const GArray *dsbs_growing; /**< A reference to an array of DSBs (of type wtap_block_t) */
guint dsbs_growing_written; /**< Number of already processed DSBs in dsbs_growing. */
};
WS_DLL_PUBLIC gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf,
@ -319,14 +328,14 @@ wtap_full_file_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
#endif /* __WTAP_INT_H__ */
/*
* Editor modelines
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local Variables:
* c-basic-offset: 8
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: t
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -321,6 +321,10 @@ wtap_dump_params_init(wtap_dump_params *params, wtap *wth)
params->shb_hdrs = wtap_file_get_shb_for_new_file(wth);
params->idb_inf = wtap_file_get_idb_info(wth);
params->nrb_hdrs = wtap_file_get_nrb_for_new_file(wth);
/* Assume that the input handle remains open until the dumper is closed.
* Refer to the DSBs from the input file, wtap_dump will then copy DSBs
* as they become available. */
params->dsbs_growing = wth ? wth->dsbs : NULL;
}
void
@ -1233,6 +1237,7 @@ wtap_close(wtap *wth)
wtap_block_array_free(wth->shb_hdrs);
wtap_block_array_free(wth->nrb_hdrs);
wtap_block_array_free(wth->interface_data);
wtap_block_array_free(wth->dsbs);
g_free(wth);
}

View File

@ -1377,6 +1377,15 @@ typedef struct wtapng_if_descr_mandatory_s {
* pcapng ISB:s or equivalent(?)*/
} wtapng_if_descr_mandatory_t;
/**
* Decryption Secrets Block data.
*/
typedef struct wtapng_dsb_mandatory_s {
guint32 secrets_type; /** Type of secrets stored in data (see secrets-types.h) */
guint32 secrets_len; /** Length of the secrets data in bytes */
guint8 *secrets_data; /** Buffer of secrets (not NUL-terminated) */
} wtapng_dsb_mandatory_t;
/* Interface description data - Option 11 structure */
typedef struct wtapng_if_descr_filter_s {
gchar *if_filter_str; /**< NULL if not available
@ -1430,6 +1439,8 @@ typedef struct addrinfo_lists {
* @note The shb_hdr, idb_inf, and nrb_hdr arguments will be used until
* wtap_dump_close() is called, but will not be free'd by the dumper. If
* you created them, you must free them yourself after wtap_dump_close().
* dsbs_initial will be freed by wtap_dump_close(),
* dsbs_growing typically refers to another wth->dsbs.
*
* @see wtap_dump_params_init, wtap_dump_params_cleanup.
*/
@ -1439,6 +1450,10 @@ typedef struct wtap_dump_params {
GArray *shb_hdrs; /**< The section header block(s) information, or NULL. */
wtapng_iface_descriptions_t *idb_inf; /**< The interface description information, or NULL. */
GArray *nrb_hdrs; /**< The name resolution blocks(s) comment/custom_opts information, or NULL. */
GArray *dsbs_initial; /**< The initial Decryption Secrets Block(s) to be written, or NULL. */
const GArray *dsbs_growing; /**< DSBs that will be written while writing packets, or NULL.
This array may grow since the dumper was opened and will subsequently
be written before newer packets are written in wtap_dump. */
} wtap_dump_params;
/* Zero-initializer for wtap_dump_params. */
@ -1664,6 +1679,14 @@ typedef void (*wtap_new_ipv6_callback_t) (const void *addrp, const gchar *name);
WS_DLL_PUBLIC
void wtap_set_cb_new_ipv6(wtap *wth, wtap_new_ipv6_callback_t add_new_ipv6);
/**
* Set callback function to receive new decryption secrets for a particular
* secrets type (as defined in secrets-types.h). Currently pcapng-only.
*/
typedef void (*wtap_new_secrets_callback_t)(guint32 secrets_type, const void *secrets, guint size);
WS_DLL_PUBLIC
void wtap_set_cb_new_secrets(wtap *wth, wtap_new_secrets_callback_t add_new_secrets);
/** Returns TRUE if read was successful. FALSE if failure. data_offset is
* set to the offset in the file where the data for the read packet is
* located. */
@ -1891,6 +1914,8 @@ gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types);
/**
* Initialize the per-file information based on an existing file. Its
* contents must be freed according to the requirements of wtap_dump_params.
* If wth does not remain valid for the duration of the session, dsbs_growing
* MUST be cleared after this function.
*
* @param params The parameters for wtap_dump_* to initialize.
* @param wth The wiretap session.

View File

@ -972,6 +972,27 @@ static void idb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
}
}
static void dsb_create(wtap_block_t block)
{
block->mandatory_data = g_new0(wtapng_dsb_mandatory_t, 1);
}
static void dsb_free_mand(wtap_block_t block)
{
wtapng_dsb_mandatory_t *mand = (wtapng_dsb_mandatory_t *)block->mandatory_data;
g_free(mand->secrets_data);
}
static void dsb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
{
wtapng_dsb_mandatory_t *src = (wtapng_dsb_mandatory_t *)src_block->mandatory_data;
wtapng_dsb_mandatory_t *dst = (wtapng_dsb_mandatory_t *)dest_block->mandatory_data;
dst->secrets_type = src->secrets_type;
dst->secrets_len = src->secrets_len;
g_free(dst->secrets_data);
dst->secrets_data = (guint8 *)g_memdup(src->secrets_data, src->secrets_len);
}
void wtap_opttypes_initialize(void)
{
static wtap_blocktype_t shb_block = {
@ -1082,6 +1103,16 @@ void wtap_opttypes_initialize(void)
NULL
};
static wtap_blocktype_t dsb_block = {
WTAP_BLOCK_DSB,
"DSB",
"Decryption Secrets Block",
dsb_create,
dsb_free_mand,
dsb_copy_mand,
NULL
};
static wtap_blocktype_t nrb_block = {
WTAP_BLOCK_NG_NRB, /* block_type */
"NRB", /* name */
@ -1227,6 +1258,11 @@ void wtap_opttypes_initialize(void)
wtap_opttype_option_register(&isb_block, OPT_ISB_FILTERACCEPT, &isb_filteraccept);
wtap_opttype_option_register(&isb_block, OPT_ISB_OSDROP, &isb_osdrop);
wtap_opttype_option_register(&isb_block, OPT_ISB_USRDELIV, &isb_usrdeliv);
/*
* Register the DSB, currently no options are defined.
*/
wtap_opttype_block_register(WTAP_BLOCK_DSB, &dsb_block);
}
void wtap_opttypes_cleanup(void)

View File

@ -133,6 +133,7 @@ typedef enum {
WTAP_BLOCK_IF_DESCR,
WTAP_BLOCK_NG_NRB,
WTAP_BLOCK_IF_STATS,
WTAP_BLOCK_DSB,
WTAP_BLOCK_END_OF_LIST
} wtap_block_type_t;