From ba086053c7f7e3a16c673a999e53dab5eba3ba84 Mon Sep 17 00:00:00 2001 From: Sake Blok Date: Sat, 28 May 2011 18:17:50 +0000 Subject: [PATCH] Add "File -> Export -> SSL Session Keys..." to be able to save the keyring info for each session in the trace file. This makes it possible to give someone the trace and the exported keys so that they can decrypt the traffic in the trace, but not new sessions to the same server. (See also: https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=3444) svn path=/trunk/; revision=37446 --- AUTHORS | 1 + epan/dissectors/packet-ssl-utils.c | 2 +- epan/dissectors/packet-ssl.c | 4 +- epan/dissectors/packet-ssl.h | 2 + epan/libwireshark.def | 1 + gtk/Makefile.common | 2 + gtk/export_sslkeys.c | 266 +++++++++++++++++++++++++++++ gtk/export_sslkeys.h | 43 +++++ gtk/menus.c | 5 + image/file_dlg_win32.rc | 7 + win32/file_dlg_win32.c | 135 +++++++++++++++ win32/file_dlg_win32.h | 9 + 12 files changed, 475 insertions(+), 2 deletions(-) create mode 100644 gtk/export_sslkeys.c create mode 100644 gtk/export_sslkeys.h diff --git a/AUTHORS b/AUTHORS index 5d32025379..414bab65aa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2795,6 +2795,7 @@ Sake Blok { Ignore all packets functionality Enable printing of all occurrences of fields Follow TCP stream enhancements + Export SSL Session Keys Miscellaneous enhancements and fixes } diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index 8c4821cbbb..60e90beded 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -3349,7 +3349,7 @@ ssl_keylog_lookup(SslDecryptSession* ssl_session, offset = 4; - if ( memcmp(line+4,"Session-ID:",11) == 0 ) { + if ( ssl_session->session_id.data_len>0 && memcmp(line+offset,"Session-ID:",11) == 0 ) { offset += 11; for (i = 0; i < ssl_session->session_id.data_len; i++) { if (from_hex_char(line[offset + i*2]) != (ssl_session->session_id.data[i] >> 4) || diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c index 9e4f1ee905..2c1e9d8dec 100644 --- a/epan/dissectors/packet-ssl.c +++ b/epan/dissectors/packet-ssl.c @@ -289,7 +289,9 @@ static const fragment_items ssl_segment_items = { "Segments" }; -static GHashTable *ssl_session_hash = NULL; +/* ssl_session_hash is used by "Export SSL Session Keys" */ +GHashTable *ssl_session_hash = NULL; + static GHashTable *ssl_key_hash = NULL; static GTree* ssl_associations = NULL; static dissector_handle_t ssl_handle = NULL; diff --git a/epan/dissectors/packet-ssl.h b/epan/dissectors/packet-ssl.h index db08f1e489..55795b44f9 100644 --- a/epan/dissectors/packet-ssl.h +++ b/epan/dissectors/packet-ssl.h @@ -25,6 +25,8 @@ #ifndef __PACKET_SSL_H__ #define __PACKET_SSL_H__ +WS_VAR_IMPORT GHashTable *ssl_session_hash; + extern void ssl_dissector_add(guint port, const gchar *protocol, gboolean tcp); extern void ssl_dissector_delete(guint port, const gchar *protocol, gboolean tcp); diff --git a/epan/libwireshark.def b/epan/libwireshark.def index dde4458c37..4305f55ece 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -974,6 +974,7 @@ srtp_add_address ssl_dissector_add ssl_dissector_delete ssl_set_master_secret +ssl_session_hash DATA start_requested_stats stats_tree_branch_max_namelen stats_tree_branch_to_str diff --git a/gtk/Makefile.common b/gtk/Makefile.common index 33748f8305..418ef61794 100644 --- a/gtk/Makefile.common +++ b/gtk/Makefile.common @@ -68,6 +68,7 @@ WIRESHARK_GTK_SRC = \ export_object_dicom.c \ export_object_http.c \ export_object_smb.c \ + export_sslkeys.c \ filter_autocomplete.c \ file_dlg.c \ file_import_dlg.c \ @@ -249,6 +250,7 @@ noinst_HEADERS = \ expert_comp_table.h \ expert_indicators.h \ export_object.h \ + export_sslkeys.h \ file_dlg.h \ file_import_dlg.h \ fileset_dlg.h \ diff --git a/gtk/export_sslkeys.c b/gtk/export_sslkeys.c new file mode 100644 index 0000000000..20b4d90450 --- /dev/null +++ b/gtk/export_sslkeys.c @@ -0,0 +1,266 @@ +/* export_sslkeys.c + * + * $Id$ + * + * Export SSL Session Keys dialog + * by Sake Blok (20110526) + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include + +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include "../simple_dialog.h" +#include "../isprint.h" +#include "../alert_box.h" +#include "../progress_dlg.h" +#include "../ui_util.h" + +#include "gtk/keys.h" +#include "gtk/color_utils.h" +#include "gtk/capture_file_dlg.h" +#include "gtk/packet_win.h" +#include "gtk/file_dlg.h" +#include "gtk/gui_utils.h" +#include "gtk/gtkglobals.h" +#include "gtk/font_utils.h" +#include "gtk/webbrowser.h" +#include "gtk/main.h" +#include "gtk/menus.h" +#include "gtk/recent.h" +#include "gtk/export_sslkeys.h" + +#ifdef _WIN32 +#include +#include +#include "win32/file_dlg_win32.h" +#endif + +void +ssl_export_sessions_func(gpointer key, gpointer value, gpointer user_data) +{ + guint i,offset; + StringInfo* sslid = (StringInfo*)key; + StringInfo* mastersecret = (StringInfo*)value; + StringInfo* keylist = (StringInfo*)user_data; + + offset = strlen(keylist->data); + + g_snprintf(keylist->data+offset,keylist->data_len-offset,"RSA Session-ID:"); + offset += 15; + + for( i=0; idata_len; i++) { + g_snprintf(keylist->data+offset,keylist->data_len-offset,"%.2x",sslid->data[i]&255); + offset += 2; + } + + g_snprintf(keylist->data+offset,keylist->data_len-offset," Master-Key:"); + offset += 12; + + for( i=0; idata_len; i++) { + g_snprintf(keylist->data+offset,keylist->data_len-offset,"%.2x",mastersecret->data[i]&255); + offset += 2; + } + + g_snprintf(keylist->data+offset,keylist->data_len-offset,"\n"); +} + +StringInfo* +ssl_export_sessions(GHashTable *session_hash) +{ + StringInfo* keylist; + + /* Output format is: + * "RSA Session-ID:xxxx Master-Key:yyyy\n" + * Where xxxx is the session ID in hex (max 64 chars) + * Where yyyy is the Master Key in hex (always 96 chars) + * So in total max 3+1+11+64+1+11+96+2 = 189 chars + */ + keylist = g_malloc0(sizeof(StringInfo)+189*g_hash_table_size (session_hash)); + keylist->data = ((guchar*)keylist+sizeof(StringInfo)); + keylist->data_len = sizeof(StringInfo)+189*g_hash_table_size (session_hash); + + g_hash_table_foreach(session_hash, ssl_export_sessions_func, (gpointer)keylist); + + return keylist; +} +static GtkWidget *savesslkeys_dlg=NULL; + +static void +savesslkeys_dlg_destroy_cb(GtkWidget *w _U_, gpointer user_data _U_) +{ + savesslkeys_dlg = NULL; +} + +/* save the SSL Session Keys */ +static gboolean +savesslkeys_save_clicked_cb(GtkWidget * w _U_, gpointer data _U_) +{ + int fd; + char *file; + StringInfo *keylist; + + file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(savesslkeys_dlg)); + + if (test_for_directory(file) == EISDIR) { + /* It's a directory - set the file selection box to display that + directory, and leave the selection box displayed. */ + set_last_open_dir(file); + g_free(file); + file_selection_set_current_folder(savesslkeys_dlg, get_last_open_dir()); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(savesslkeys_dlg), ""); + return FALSE; /* do gtk_dialog_run again */ + } + + /* XXX: Must check if file name exists first */ + + /* + * Retrieve the info we need + */ + keylist = ssl_export_sessions(ssl_session_hash); + + if (keylist->data_len == 0 ) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "No SSL Session Keys to export!"); + g_free(keylist); + g_free(file); + return TRUE; + } + + fd = ws_open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666); + if (fd == -1) { + open_failure_alert_box(file, errno, TRUE); + g_free(keylist); + g_free(file); + return TRUE; + } + if (ws_write(fd, keylist->data, strlen(keylist->data)) < 0) { + write_failure_alert_box(file, errno); + ws_close(fd); + g_free(keylist); + g_free(file); + return TRUE; + } + if (ws_close(fd) < 0) { + write_failure_alert_box(file, errno); + g_free(keylist); + g_free(file); + return TRUE; + } + + /* Get rid of the dialog box */ + g_free(keylist); + g_free(file); + return TRUE; +} + + +/* Launch the dialog box to put up the file selection box etc */ +#ifdef _WIN32 +void +savesslkeys_cb(GtkWidget * w _U_, gpointer data _U_) +{ + win32_export_sslkeys_file(GDK_WINDOW_HWND(top_level->window)); + return; +} +#else +void +savesslkeys_cb(GtkWidget * w _U_, gpointer data _U_) +{ + gchar *label; + GtkWidget *dlg_lb; + guint keylist_len; + + keylist_len = g_hash_table_size(ssl_session_hash); + /* don't show up the dialog, if no data has to be saved */ + if (keylist_len==0) { + /* shouldn't happen as the menu item should have been greyed out */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "There are no SSL Session Keys to save!"); + return; + } + + + /* + * Build the dialog box we need. + */ + savesslkeys_dlg = file_selection_new("Wireshark: Export SSL Session Keys", FILE_SELECTION_SAVE); +#if GTK_CHECK_VERSION(2,8,0) + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(savesslkeys_dlg), TRUE); +#endif + + /* label */ + label = g_strdup_printf("Will save %u SSL Session %s to specified file.", + keylist_len, plurality(keylist_len, "key", "keys")); + dlg_lb = gtk_label_new(label); + g_free(label); + file_selection_set_extra_widget(savesslkeys_dlg, dlg_lb); + gtk_widget_show(dlg_lb); + + g_signal_connect(savesslkeys_dlg, "destroy", G_CALLBACK(savesslkeys_dlg_destroy_cb), NULL); + + /* "Run" the GtkFileChooserDialog. */ + /* Upon exit: If "Accept" run the OK callback. */ + /* If the OK callback returns with a FALSE status, re-run the dialog.*/ + /* If not accept (ie: cancel) destroy the window. */ + /* XXX: If the OK callback pops up an alert box (eg: for an error) it *must* */ + /* return with a TRUE status so that the dialog window will be destroyed. */ + /* Trying to re-run the dialog after popping up an alert box will not work */ + /* since the user will not be able to dismiss the alert box. */ + /* The (somewhat unfriendly) effect: the user must re-invoke the */ + /* GtkFileChooserDialog whenever the OK callback pops up an alert box. */ + /* */ + /* ToDo: use GtkFileChooserWidget in a dialog window instead of */ + /* GtkFileChooserDialog. */ + while (gtk_dialog_run(GTK_DIALOG(savesslkeys_dlg)) == GTK_RESPONSE_ACCEPT) { + if (savesslkeys_save_clicked_cb(NULL, savesslkeys_dlg)) { + break; /* we're done */ + } + } + window_destroy(savesslkeys_dlg); +} +#endif diff --git a/gtk/export_sslkeys.h b/gtk/export_sslkeys.h new file mode 100644 index 0000000000..355f0046e4 --- /dev/null +++ b/gtk/export_sslkeys.h @@ -0,0 +1,43 @@ +/* export_sslkeys.h + * + * $Id$ + * + * Export SSL Session Keys dialog + * by Sake Blok (20110526) + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __EXPORT_SSLKEYS_H__ +#define __EXPORT_SSLKEYS_H__ + +/** Callback for "Export SSL Session Keys" operation. + * + * @param w unused + * @param data unused + */ +extern void savesslkeys_cb(GtkWidget * w, gpointer data); + +/** Dump the SSL Session Keys to a StringInfo string + * + * @param session_hash contains all the SSL Session Keys + */ +extern StringInfo* ssl_export_sessions(GHashTable *session_hash); + +#endif /* __MAIN_PROTO_DRAW_H__ */ diff --git a/gtk/menus.c b/gtk/menus.c index 0e8eb500a8..d8ae22560f 100644 --- a/gtk/menus.c +++ b/gtk/menus.c @@ -88,6 +88,8 @@ #include "gtk/firewall_dlg.h" #include "gtk/macros_dlg.h" #include "gtk/export_object.h" +#include "epan/dissectors/packet-ssl-utils.h" +#include "gtk/export_sslkeys.h" #include "gtk/gui_stat_menu.h" #include "gtk/main.h" #include "gtk/menus.h" @@ -1434,6 +1436,7 @@ static const GtkActionEntry main_menu_bar_entries[] = { NULL, NULL, G_CALLBACK(export_pdml_cmd_cb) }, #endif /* _WIN32 */ { "/File/Export/SelectedPacketBytes", NULL, "Selected Packet _Bytes...", "H", NULL, G_CALLBACK(savehex_cb) }, + { "/File/Export/SslSessionKeys", NULL, "SSL Session Keys...", NULL, NULL, G_CALLBACK(savesslkeys_cb) }, { "/File/Export/Objects", NULL, "Objects", NULL, NULL, NULL }, { "/File/Export/Objects/HTTP", NULL, "_HTTP", NULL, NULL, G_CALLBACK(eo_http_cb) }, { "/File/Export/Objects/DICOM", NULL, "_DICOM", NULL, NULL, G_CALLBACK(eo_dicom_cb) }, @@ -1876,6 +1879,8 @@ static GtkItemFactoryEntry menu_items[] = #endif {"/File/Export/Selected Packet _Bytes...", "H", GTK_MENU_FUNC(savehex_cb), 0, NULL, NULL,}, + {"/File/Export/SSL Session Keys...", NULL, GTK_MENU_FUNC(savesslkeys_cb), + 0, NULL, NULL,}, {"/File/Export/_Objects/_HTTP", NULL, GTK_MENU_FUNC(eo_http_cb), 0, NULL, NULL,}, {"/File/Export/_Objects/_DICOM", NULL, GTK_MENU_FUNC(eo_dicom_cb), 0, NULL, NULL,}, {"/File/Export/_Objects/_SMB", NULL, GTK_MENU_FUNC(eo_smb_cb), 0, NULL, NULL,}, diff --git a/image/file_dlg_win32.rc b/image/file_dlg_win32.rc index 1c3a9a26a4..3f5daecdd4 100644 --- a/image/file_dlg_win32.rc +++ b/image/file_dlg_win32.rc @@ -138,3 +138,10 @@ FONT 8, "MS Shell Dlg" { LTEXT "-", EWFD_EXPORTRAW_ST, 5, 5, 180, 8 } + +WIRESHARK_EXPORTSSLKEYSFILENAME_TEMPLATE DIALOG 0, 0, 200, 18 +STYLE WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | DS_3DLOOK | DS_CONTROL +FONT 8, "MS Shell Dlg" +{ + LTEXT "-", EWFD_EXPORTSSLKEYS_ST, 5, 5, 180, 8 +} diff --git a/win32/file_dlg_win32.c b/win32/file_dlg_win32.c index fa319af24f..92eeafea36 100644 --- a/win32/file_dlg_win32.c +++ b/win32/file_dlg_win32.c @@ -44,6 +44,8 @@ #include "epan/filesystem.h" #include "epan/addr_resolv.h" #include "epan/prefs.h" +#include "epan/dissectors/packet-ssl.h" +#include "epan/dissectors/packet-ssl-utils.h" #include "wsutil/file_util.h" #include "wsutil/unicode-utils.h" @@ -63,6 +65,7 @@ #include "gtk/capture_dlg.h" #include "win32/file_dlg_win32.h" #include "gtk/help_dlg.h" +#include "gtk/export_sslkeys.h" typedef enum { merge_append, @@ -90,6 +93,12 @@ typedef enum { #define FILE_RAW_DEFAULT 1 +#define FILE_TYPES_SSLKEYS \ + _T("SSL Session Keys (*.keys)\0") _T("*.keys\0") \ + _T("All Files (*.*)\0") _T("*.*\0") + +#define FILE_SSLKEYS_DEFAULT 1 + #define FILE_TYPES_COLOR \ _T("Text Files (*.txt)\0") _T("*.txt\0") \ _T("All Files (*.*)\0") _T("*.*\0") @@ -106,12 +115,14 @@ static UINT CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_ static UINT CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); static UINT CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); static UINT CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); +static UINT CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); #else static UINT_PTR CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); static UINT_PTR CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); static UINT_PTR CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); static UINT_PTR CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); static UINT_PTR CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); +static UINT_PTR CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param); #endif /* (_MSC_VER <= 1200) */ static void range_update_dynamics(HWND sf_hwnd, packet_range_t *range); @@ -722,6 +733,98 @@ win32_export_raw_file(HWND h_wnd) { } } +void +win32_export_sslkeys_file(HWND h_wnd) { + OPENFILENAME *ofn; + TCHAR file_name[MAX_PATH] = _T(""); + char *dirname; + StringInfo *keylist; + char *file_name8; + int fd; + int ofnsize; + int keylist_size; +#if (_MSC_VER >= 1500) + OSVERSIONINFO osvi; +#endif + + keylist_size = g_hash_table_size(ssl_session_hash); + if (keylist_size==0) { + /* This shouldn't happen */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No SSL Session Keys to export."); + return; + } + + /* see OPENFILENAME comment in win32_open_file */ +#if (_MSC_VER >= 1500) + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + if (osvi.dwMajorVersion >= 5) { + ofnsize = sizeof(OPENFILENAME); + } else { + ofnsize = OPENFILENAME_SIZE_VERSION_400; + } +#else + ofnsize = sizeof(OPENFILENAME) + 12; +#endif + ofn = g_malloc0(ofnsize); + + ofn->lStructSize = ofnsize; + ofn->hwndOwner = h_wnd; +#if (_MSC_VER <= 1200) + ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE); +#else + ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE); +#endif + ofn->lpstrFilter = FILE_TYPES_SSLKEYS; + ofn->lpstrCustomFilter = NULL; + ofn->nMaxCustFilter = 0; + ofn->nFilterIndex = FILE_SSLKEYS_DEFAULT; + ofn->lpstrFile = file_name; + ofn->nMaxFile = MAX_PATH; + ofn->lpstrFileTitle = NULL; + ofn->nMaxFileTitle = 0; + ofn->lpstrInitialDir = utf_8to16(get_last_open_dir()); + ofn->lpstrTitle = _T("Wireshark: Export SSL Session Keys"); + ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER | + OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | + OFN_PATHMUSTEXIST | OFN_ENABLEHOOK | OFN_SHOWHELP; + ofn->lpstrDefExt = NULL; + ofn->lCustData = keylist_size; + ofn->lpfnHook = export_sslkeys_file_hook_proc; + ofn->lpTemplateName = _T("WIRESHARK_EXPORTSSLKEYSFILENAME_TEMPLATE"); + + if (GetSaveFileName(ofn)) { + g_free( (void *) ofn); + file_name8 = utf_16to8(file_name); + keylist = ssl_export_sessions(ssl_session_hash); + fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666); + if (fd == -1) { + open_failure_alert_box(file_name8, errno, TRUE); + g_free(keylist); + return; + } + if (write(fd, keylist->data, strlen(keylist->data)) < 0) { + write_failure_alert_box(file_name8, errno); + close(fd); + g_free(keylist); + return; + } + if (close(fd) < 0) { + write_failure_alert_box(file_name8, errno); + g_free(keylist); + return; + } + + /* Save the directory name for future file dialogs. */ + dirname = get_dirname(file_name8); /* Overwrites cf_name */ + set_last_open_dir(dirname); + } else { + g_free( (void *) ofn); + } + g_free(keylist); +} + void win32_export_color_file(HWND h_wnd, gpointer filter_list) { OPENFILENAME *ofn; @@ -1958,6 +2061,38 @@ export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param return 0; } +#if (_MSC_VER <= 1200) +static UINT CALLBACK +#else +static UINT_PTR CALLBACK +#endif +export_sslkeys_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) { + HWND cur_ctrl; + OPENFILENAME *ofnp = (OPENFILENAME *) l_param; + TCHAR sslkeys_msg[STATIC_LABEL_CHARS]; + OFNOTIFY *notify = (OFNOTIFY *) l_param; + + switch(msg) { + case WM_INITDIALOG: + _snwprintf(sslkeys_msg, STATIC_LABEL_CHARS, _T("%d SSL Session Key%s will be written"), + ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s"))); + cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTSSLKEYS_ST); + SetWindowText(cur_ctrl, sslkeys_msg); + break; + case WM_NOTIFY: + switch (notify->hdr.code) { + case CDN_HELP: + topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG); + break; + default: + break; + } + default: + break; + } + return 0; +} + /* * Editor modelines * diff --git a/win32/file_dlg_win32.h b/win32/file_dlg_win32.h index 9fab732f0f..cb62c29ee8 100644 --- a/win32/file_dlg_win32.h +++ b/win32/file_dlg_win32.h @@ -67,6 +67,12 @@ void win32_export_file (HWND h_wnd, export_type_e export_type); */ void win32_export_raw_file (HWND h_wnd); +/** Open the "Export SSL Session Keys" dialog box. + * + * @param h_wnd HWND of the parent window. + */ +void win32_export_sslkeys_file (HWND h_wnd); + /** Open the "Export Color Filters" dialog box * * @param h_wnd HWND of the parent window @@ -138,6 +144,9 @@ void file_set_save_marked_sensitive(); /* Export raw dialog defines. */ #define EWFD_EXPORTRAW_ST 1000 +/* Export SSL Session Keys dialog defines. */ +#define EWFD_EXPORTSSLKEYS_ST 1000 + /* Merge dialog defines. Overlays Open dialog defines above. */ #define EWFD_MERGE_PREPEND_BTN 1050 #define EWFD_MERGE_CHRONO_BTN 1051