diff --git a/file.c b/file.c index 58518d68ac..414effde90 100644 --- a/file.c +++ b/file.c @@ -1740,6 +1740,18 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + if (redissect) { + /* + * Decryption secrets are read while sequentially processing records and + * then passed to the dissector. During redissection, the previous secrets + * are lost (see epan_free above), but they are not read again from the + * file as only packet records are re-read. Therefore reset the wtap secrets + * callback such that wtap resupplies the secrets callback with previously + * read secrets. + */ + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); + } + for (framenum = 1; framenum <= frames_count; framenum++) { fdata = frame_data_sequence_find(cf->provider.frames, framenum); diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 035f5b6a9e..55fd663360 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -2646,11 +2646,7 @@ pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock) static void pcapng_process_dsb(wtap *wth, wtapng_block_t *wblock) { - const wtapng_dsb_mandatory_t *dsb = (wtapng_dsb_mandatory_t*)wtap_block_get_mandatory_data(wblock->block); - - if (wth->add_new_secrets) { - wth->add_new_secrets(dsb->secrets_type, dsb->secrets_data, dsb->secrets_len); - } + wtapng_process_dsb(wth, wblock->block); /* Store DSB such that it can be saved by the dumper. */ g_array_append_val(wth->dsbs, wblock->block); diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h index 9271ac39fa..486b03685f 100644 --- a/wiretap/wtap-int.h +++ b/wiretap/wtap-int.h @@ -326,6 +326,12 @@ wtap_full_file_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset); */ gboolean wtap_full_file_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info); + +/** + * Invokes the callback with the given decryption secrets block. + */ +void +wtapng_process_dsb(wtap *wth, wtap_block_t dsb); #endif /* __WTAP_INT_H__ */ /* diff --git a/wiretap/wtap.c b/wiretap/wtap.c index b7498d337c..fe43e3b457 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -1266,8 +1266,29 @@ void wtap_set_cb_new_ipv6(wtap *wth, wtap_new_ipv6_callback_t add_new_ipv6) { } void wtap_set_cb_new_secrets(wtap *wth, wtap_new_secrets_callback_t add_new_secrets) { - if (wth) - wth->add_new_secrets = add_new_secrets; + /* Is a valid wth given that supports DSBs? */ + if (!wth || !wth->dsbs) + return; + + wth->add_new_secrets = add_new_secrets; + /* + * Send all DSBs that were read so far to the new callback. file.c + * relies on this to support redissection (during redissection, the + * previous secrets are lost and has to be resupplied). + */ + for (guint i = 0; i < wth->dsbs->len; i++) { + wtap_block_t dsb = g_array_index(wth->dsbs, wtap_block_t, i); + wtapng_process_dsb(wth, dsb); + } +} + +void +wtapng_process_dsb(wtap *wth, wtap_block_t dsb) +{ + const wtapng_dsb_mandatory_t *dsb_mand = (wtapng_dsb_mandatory_t*)wtap_block_get_mandatory_data(dsb); + + if (wth->add_new_secrets) + wth->add_new_secrets(dsb_mand->secrets_type, dsb_mand->secrets_data, dsb_mand->secrets_len); } gboolean