/pidgin/main: 1cdc641d433e: Add "NSS Preferences" plugin which a...
Daniel Atallah <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: 1cdc641d433e72e1335147f45c62dbe5958cba6b Author: Daniel Atallah <[email protected]> Date: 2014-11-05 13:13 -0500 Branch: release-2.x.y URL: https://hg.pidgin.im/pidgin/main/rev/1cdc641d433e Description: Add "NSS Preferences" plugin which allows configuration Min/Max TLS version and Ciphers. * The TLS version settings require NSS 3.14 or newer Refs #8061 diffstat: ChangeLog | 11 +- libpurple/plugins/ssl/Makefile.am | 10 +- libpurple/plugins/ssl/Makefile.mingw | 16 +- libpurple/plugins/ssl/nss-prefs.c | 529 +++++++++++++++++++++++++++++++++ libpurple/plugins/ssl/ssl-nss.c | 1 - pidgin/win32/nsis/pidgin-installer.nsi | 1 + 6 files changed, 557 insertions(+), 11 deletions(-) diffs (truncated from 693 to 300 lines): diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,14 +1,17 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.10.11 (?/?/?): + General: + * Fix handling of Self-Signed SSL/TLS Certificates when using the NSS + plugin (#16412) + * Improve default cipher suites used with the NSS plugin (#16262) + * Add NSS Preferences plugin which allows the SSL/TLS Versions and + cipher suites to be configured (#8061) + Gadu-Gadu: * Fix a bug that prevented plugin to load when compiled without GnuTLS. (mancha) (#16431) - General: - * Fix handling of Self-Signed SSL/TLS Certificates when using the NSS - plugin (#16412) - version 2.10.10 (10/22/14): General: * Check the basic constraints extension when validating SSL/TLS diff --git a/libpurple/plugins/ssl/Makefile.am b/libpurple/plugins/ssl/Makefile.am --- a/libpurple/plugins/ssl/Makefile.am +++ b/libpurple/plugins/ssl/Makefile.am @@ -6,6 +6,7 @@ plugindir = $(libdir)/purple-$(PURPLE_MA ssl_la_LDFLAGS = -module -avoid-version ssl_gnutls_la_LDFLAGS = -module -avoid-version ssl_nss_la_LDFLAGS = -module -avoid-version +nss_prefs_la_LDFLAGS = -module -avoid-version if PLUGINS @@ -18,7 +19,8 @@ if USE_NSS plugin_LTLIBRARIES = \ ssl.la \ ssl-gnutls.la \ - ssl-nss.la + ssl-nss.la \ + nss-prefs.la else plugin_LTLIBRARIES = \ ssl.la \ @@ -28,7 +30,8 @@ else if USE_NSS plugin_LTLIBRARIES = \ ssl.la \ - ssl-nss.la + ssl-nss.la \ + nss-prefs.la else plugin_LTLIBRARIES = \ ssl.la @@ -38,10 +41,12 @@ endif ssl_la_SOURCES = ssl.c ssl_gnutls_la_SOURCES = ssl-gnutls.c ssl_nss_la_SOURCES = ssl-nss.c +nss_prefs_la_SOURCES = nss-prefs.c ssl_la_LIBADD = $(GLIB_LIBS) ssl_gnutls_la_LIBADD = $(GLIB_LIBS) $(GNUTLS_LIBS) ssl_nss_la_LIBADD = $(GLIB_LIBS) $(NSS_LIBS) +nss_prefs_la_LIBADD = $(GLIB_LIBS) $(NSS_LIBS) endif # PLUGINS @@ -56,3 +61,4 @@ AM_CPPFLAGS = \ ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS) ssl_nss_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS) +nss_prefs_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS) diff --git a/libpurple/plugins/ssl/Makefile.mingw b/libpurple/plugins/ssl/Makefile.mingw --- a/libpurple/plugins/ssl/Makefile.mingw +++ b/libpurple/plugins/ssl/Makefile.mingw @@ -12,6 +12,7 @@ include $(PIDGIN_TREE_TOP)/libpurple/win ## TARGET = ssl TARGET_NSS = ssl-nss +TARGET_NSSPREEFS = nss-prefs NEEDED_DLLS = \ $(NSS_TOP)/lib/freebl3.dll \ @@ -22,8 +23,8 @@ NEEDED_DLLS = \ $(NSS_TOP)/lib/nssutil3.dll \ $(NSS_TOP)/lib/smime3.dll \ $(NSS_TOP)/lib/softokn3.dll \ - $(NSS_TOP)/lib/sqlite3.dll \ - $(NSS_TOP)/lib/ssl3.dll + $(NSS_TOP)/lib/sqlite3.dll \ + $(NSS_TOP)/lib/ssl3.dll ## ## INCLUDE PATHS @@ -46,8 +47,10 @@ LIB_PATHS += -L$(GTK_TOP)/lib \ ## C_SRC = ssl.c C_SRC_NSS = ssl-nss.c +C_SRC_NSSPREFS = nss-prefs.c OBJECTS = $(C_SRC:%.c=%.o) OBJECTS_NSS = $(C_SRC_NSS:%.c=%.o) +OBJECTS_NSSPREFS = $(C_SRC_NSSPREFS:%.c=%.o) ## ## LIBRARIES @@ -69,11 +72,13 @@ include $(PIDGIN_COMMON_RULES) ## .PHONY: all install clean -all: $(TARGET).dll $(TARGET_NSS).dll +all: $(TARGET).dll $(TARGET_NSS).dll $(TARGET_NSSPREFS).dll install: all $(PURPLE_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_DIR) cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR) cp $(TARGET_NSS).dll $(PURPLE_INSTALL_PLUGINS_DIR) + cp $(TARGET_NSS).dll $(PURPLE_INSTALL_PLUGINS_DIR) + cp $(TARGET_NSSPREFS).dll $(PURPLE_INSTALL_PLUGINS_DIR) cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR) $(OBJECTS) $(OBJECTS_NSS): $(PURPLE_CONFIG_H) @@ -87,10 +92,13 @@ install: all $(PURPLE_INSTALL_PLUGINS_DI $(TARGET_NSS).dll: $(PURPLE_DLL) $(OBJECTS_NSS) $(CC) -shared $(OBJECTS_NSS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET_NSS).dll +$(TARGET_NSSPREFS).dll: $(PURPLE_DLL) $(OBJECTS_NSSPREFS) + $(CC) -shared $(OBJECTS_NSSPREFS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET_NSSPREFS).dll + ## ## CLEAN RULES ## clean: - rm -f $(OBJECTS) $(OBJECTS_NSS) $(TARGET).dll $(TARGET_NSS).dll + rm -f $(OBJECTS) $(OBJECTS_NSS) $(OBJECTS_NSSPREFS) $(TARGET).dll $(TARGET_NSS).dll $(TARGET_NSSPREFS).dll include $(PIDGIN_COMMON_TARGETS) diff --git a/libpurple/plugins/ssl/nss-prefs.c b/libpurple/plugins/ssl/nss-prefs.c new file mode 100644 --- /dev/null +++ b/libpurple/plugins/ssl/nss-prefs.c @@ -0,0 +1,529 @@ +/* + * Plugin to configure NSS + * + * Copyright (C) 2014, Daniel Atallah <[email protected]> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02111-1301, USA. + */ +#include "internal.h" +#include "debug.h" +#include "plugin.h" +#include "version.h" + +#ifdef _WIN32 +# ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG +/* WINDDK_BUILD is defined because the checks around usage of + * intrisic functions are wrong in nspr */ +#define WINDDK_BUILD +# endif +#endif + +#include <nspr.h> +#include <nss.h> +#include <nssb64.h> +#include <ocsp.h> +#include <pk11func.h> +#include <prio.h> +#include <secerr.h> +#include <secmod.h> +#include <ssl.h> +#include <sslerr.h> +#include <sslproto.h> + +/* There's a bug in some versions of this header that requires that some of + the headers above be included first. This is true for at least libnss + 3.15.4. */ +#include <certdb.h> + +#define PLUGIN_ID "core-nss_prefs" + +#define PREF_BASE "/plugins/core/nss_prefs" +#define CIPHERS_PREF PREF_BASE "/cipher_list" +#define CIPHER_TMP_ROOT PREF_BASE "/ciphers_dummy_ui" +#define CIPHER_TMP CIPHER_TMP_ROOT "/0x%04x" +#define MIN_TLS PREF_BASE "/min_tls" +#define MAX_TLS PREF_BASE "/max_tls" + +static PurplePlugin *handle = NULL; +static GList *tmp_prefs = NULL; +static GList *default_ciphers = NULL; +#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 ) +static SSLVersionRange *default_versions = NULL; +#endif + +static gchar *get_error_text(void) +{ + PRInt32 len = PR_GetErrorTextLength(); + gchar *ret = NULL; + + if (len > 0) { + ret = g_malloc(len + 1); + len = PR_GetErrorText(ret); + ret[len] = '\0'; + } + + return ret; +} + +static GList *get_current_cipher_list(gboolean force_default) { + GList *conf_ciphers = NULL; + if (!force_default) { + conf_ciphers = purple_prefs_get_string_list(CIPHERS_PREF); + } + + /* If we don't have any specifically configured ciphers, use the + * a copy of the defaults */ + if (!conf_ciphers) { + GList *tmp; + for(tmp = default_ciphers; tmp; tmp = tmp->next) { + conf_ciphers = g_list_prepend(conf_ciphers, g_strdup(tmp->data)); + } + } + + return conf_ciphers; +} + +static void +enable_ciphers(gboolean force_default) { + const PRUint16 *cipher; + GList *conf_ciphers, *tmp; + SECStatus rv; + + conf_ciphers = get_current_cipher_list(force_default); + + /** First disable everything */ + for (cipher = SSL_GetImplementedCiphers(); *cipher != 0; ++cipher) { + rv = SSL_CipherPrefSetDefault(*cipher, PR_FALSE); + if (rv != SECSuccess) { + gchar *error_msg = get_error_text(); + purple_debug_warning("nss-prefs", + "Unable to disable 0x%04x: %s\n", + *cipher, error_msg); + g_free(error_msg); + } + } + + for (tmp = conf_ciphers; tmp; tmp = g_list_delete_link(tmp, tmp)) { + guint64 parsed = g_ascii_strtoull(tmp->data, NULL, 16); + + if (parsed == 0 || parsed > PR_UINT16_MAX) { + purple_debug_error("nss-prefs", + "Cipher '%s' is not valid.\n", + (const char *) tmp->data); + g_free(tmp->data); + continue; + } + + rv = SSL_CipherPrefSetDefault((PRUint16) parsed, PR_TRUE); + if (rv != SECSuccess) { + gchar *error_msg = get_error_text(); + purple_debug_warning("nss-prefs", + "Unable to enable 0x%04x: %s\n", + *cipher, error_msg); + g_free(error_msg); + } + purple_debug_info("nss-prefs", + "Enabled Cipher 0x%04x.\n", (PRUint16) parsed); + + g_free(tmp->data); + } +} + +static void set_cipher_pref(const char *pref, PurplePrefType type, + gconstpointer value, gpointer user_data) { + const PRUint16 *cipher = user_data; + GList *conf_ciphers, *tmp; + gboolean enabled = GPOINTER_TO_INT(value); + gboolean found = FALSE; + + purple_debug_info("nss-prefs", + "%s pref for Cipher 0x%04x.\n", + enabled ? "Adding" : "Removing", *cipher); + + conf_ciphers = get_current_cipher_list(FALSE); +