aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2018-11-17 13:56:12 +0100
committerAnders Broman <a.broman58@gmail.com>2018-11-20 05:12:37 +0000
commit52a667143929ace46929bfb6ad15b6a856cdbe77 (patch)
tree97dfedc45dd07c47116ba06cb13457f04a5d48df /wiretap
parentad21e3121f3307ee6cc2b4a2b296ef6dd83152ed (diff)
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>
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/CMakeLists.txt1
-rw-r--r--wiretap/file_access.c4
-rw-r--r--wiretap/merge.c33
-rw-r--r--wiretap/merge.h1
-rw-r--r--wiretap/pcapng.c149
-rw-r--r--wiretap/pcapng.h9
-rw-r--r--wiretap/pcapng_module.h1
-rw-r--r--wiretap/secrets-types.h19
-rw-r--r--wiretap/wtap-int.h21
-rw-r--r--wiretap/wtap.c5
-rw-r--r--wiretap/wtap.h25
-rw-r--r--wiretap/wtap_opttypes.c36
-rw-r--r--wiretap/wtap_opttypes.h1
13 files changed, 295 insertions, 10 deletions
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt
index 6f062f1762..cbf94aa396 100644
--- a/wiretap/CMakeLists.txt
+++ b/wiretap/CMakeLists.txt
@@ -14,6 +14,7 @@ set(WIRETAP_PUBLIC_HEADERS
merge.h
pcap-encap.h
pcapng_module.h
+ secrets-types.h
wtap.h
wtap_opttypes.h
)
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 24989bebe9..955f25b3d6 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -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;
}
diff --git a/wiretap/merge.c b/wiretap/merge.c
index 1a1f56ffac..42aa35507d 100644
--- a/wiretap/merge.c
+++ b/wiretap/merge.c
@@ -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;
}
diff --git a/wiretap/merge.h b/wiretap/merge.h
index aafbd81104..8a14c483a3 100644
--- a/wiretap/merge.h
+++ b/wiretap/merge.h
@@ -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(). */
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index ebc9f51041..c330c60f11 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -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;
}
diff --git a/wiretap/pcapng.h b/wiretap/pcapng.h
index d065131981..e43124da96 100644
--- a/wiretap/pcapng.h
+++ b/wiretap/pcapng.h
@@ -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);
diff --git a/wiretap/pcapng_module.h b/wiretap/pcapng_module.h
index 01abd39f49..78396f4265 100644
--- a/wiretap/pcapng_module.h
+++ b/wiretap/pcapng_module.h
@@ -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 */
diff --git a/wiretap/secrets-types.h b/wiretap/secrets-types.h
new file mode 100644
index 0000000000..513b901286
--- /dev/null
+++ b/wiretap/secrets-types.h
@@ -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__ */
diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h
index 76b6113531..5a6005571e 100644
--- a/wiretap/wtap-int.h
+++ b/wiretap/wtap-int.h
@@ -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:
*/
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index b9cc3571b5..a9ec1e35bd 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -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);
}
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 4a9ff7004d..ec7e390fb1 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -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.
diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c
index 91690d0e69..c50879e6a6 100644
--- a/wiretap/wtap_opttypes.c
+++ b/wiretap/wtap_opttypes.c
@@ -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)
diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h
index 328cd60a3e..07d3197eee 100644
--- a/wiretap/wtap_opttypes.h
+++ b/wiretap/wtap_opttypes.h
@@ -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;