pidgin/pidgin

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
--- a/ChangeLog Wed Nov 05 12:04:11 2014 -0500
+++ b/ChangeLog Wed Nov 05 13:13:37 2014 -0500
@@ -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
--- a/libpurple/plugins/ssl/Makefile.am Wed Nov 05 12:04:11 2014 -0500
+++ b/libpurple/plugins/ssl/Makefile.am Wed Nov 05 13:13:37 2014 -0500
@@ -6,6 +6,7 @@
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 @@
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 @@
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 @@
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 @@
ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS)
ssl_nss_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS)
+nss_prefs_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS)
--- a/libpurple/plugins/ssl/Makefile.mingw Wed Nov 05 12:04:11 2014 -0500
+++ b/libpurple/plugins/ssl/Makefile.mingw Wed Nov 05 13:13:37 2014 -0500
@@ -12,6 +12,7 @@
##
TARGET = ssl
TARGET_NSS = ssl-nss
+TARGET_NSSPREEFS = nss-prefs
NEEDED_DLLS = \
$(NSS_TOP)/lib/freebl3.dll \
@@ -22,8 +23,8 @@
$(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 @@
##
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 @@
##
.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 @@
$(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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/ssl/nss-prefs.c Wed Nov 05 13:13:37 2014 -0500
@@ -0,0 +1,529 @@
+/*
+ * Plugin to configure NSS
+ *
+ * Copyright (C) 2014, Daniel Atallah <datallah@pidgin.im>
+ *
+ * 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);
+
+ for (tmp = conf_ciphers; tmp; tmp = tmp->next) {
+ 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 to set_cipher_pref.\n",
+ (const char *) tmp->data);
+ }
+ if (parsed == *cipher) {
+ if (!enabled) {
+ g_free(tmp->data);
+ conf_ciphers = g_list_delete_link(conf_ciphers, tmp);
+ }
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ if (enabled) {
+ conf_ciphers = g_list_prepend(conf_ciphers,
+ g_strdup_printf("0x%04x", *cipher));
+ } else {
+ purple_debug_info("nss-prefs",
+ "Unable to find 0x%04x to disable.\n",
+ *cipher);
+ }
+ }
+
+ purple_prefs_set_string_list(CIPHERS_PREF, conf_ciphers);
+
+ for (tmp = conf_ciphers; tmp; tmp = g_list_delete_link(tmp, tmp)) {
+ g_free(tmp->data);
+ }
+
+ enable_ciphers(FALSE);
+}
+
+static void set_versions(gboolean force_default) {
+#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 )
+ SSLVersionRange supported, enabled;
+
+ /* Get the ranges of supported and enabled SSL versions */
+ if ((SSL_VersionRangeGetSupported(ssl_variant_stream, &supported) == SECSuccess) &&
+ (SSL_VersionRangeGetDefault(ssl_variant_stream, &enabled) == SECSuccess)) {
+ PRUint16 tmp;
+
+ /* Store the defaults if this is the first time we've encountered them */
+ if (!default_versions) {
+ default_versions = g_new0(SSLVersionRange, 1);
+ default_versions->min = enabled.min;
+ default_versions->max = enabled.max;
+ }
+
+ if (force_default) {
+ tmp = default_versions->min;
+ } else {
+ tmp = purple_prefs_get_int(MIN_TLS);
+ }
+ if (tmp > 0) {
+ enabled.min = tmp;
+ }
+
+ if (force_default) {
+ tmp = default_versions->max;
+ } else {
+ tmp = purple_prefs_get_int(MAX_TLS);
+ }
+ if (tmp > 0) {
+ enabled.max = tmp;
+ }
+
+ if (SSL_VersionRangeSetDefault(ssl_variant_stream, &enabled) == SECSuccess) {
+ purple_debug_info("nss-prefs", "Changed allowed TLS versions to "
+ "0x%04hx through 0x%04hx\n", enabled.min, enabled.max);
+ } else {
+ purple_debug_error("nss-prefs", "Error setting allowed TLS versions to "
+ "0x%04hx through 0x%04hx\n", enabled.min, enabled.max);
+ }
+ }
+#else
+ purple_debug_error("nss-prefs", "Unable set SSL/TLS Versions\n");
+#endif /* NSS >= 3.14 */
+}
+
+static void set_version_pref(const char *pref, PurplePrefType type,
+ gconstpointer value, gpointer user_data) {
+ set_versions(FALSE);
+}
+
+/* This is horrible, but is the only way I can think of to tie into the
+ * prefs UI. Add a bunch of temporary prefs that will be used to set
+ * the prefs list. They'll get cleaned up when the plugin is unloaded*/
+static void init_tmp_prefs(void) {
+ GList *conf_ciphers, *tmp;
+ const PRUint16 *cipher;
+
+ if (tmp_prefs) {
+ return;
+ }
+
+ conf_ciphers = get_current_cipher_list(FALSE);
+
+ purple_prefs_add_none(CIPHER_TMP_ROOT);
+ for (cipher = SSL_GetImplementedCiphers(); *cipher != 0; ++cipher) {
+ gboolean found = FALSE;
+ gchar *pref_name = g_strdup_printf(CIPHER_TMP, *cipher);
+
+ tmp_prefs = g_list_prepend(tmp_prefs, pref_name);
+
+ tmp = conf_ciphers;
+ while (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 to init_tmp_pref.\n",
+ (const char *) tmp->data);
+ }
+ if (parsed == *cipher) {
+ found = TRUE;
+ /** Remove the entry since we're done with it */
+ g_free(tmp->data);
+ conf_ciphers = g_list_delete_link(conf_ciphers, tmp);
+ break;
+ }
+ tmp = tmp->next;
+ }
+ purple_prefs_add_bool(pref_name, found);
+ purple_prefs_set_bool(pref_name, found);
+ purple_prefs_connect_callback(handle, pref_name,
+ set_cipher_pref, (void *) cipher);
+ }
+ tmp_prefs = g_list_reverse(tmp_prefs);
+
+ for (tmp = conf_ciphers; tmp; tmp = g_list_delete_link(tmp, tmp)) {
+ g_free(tmp->data);
+ }
+
+}
+
+static PurplePluginPrefFrame *
+get_plugin_pref_frame(PurplePlugin *plugin) {
+ PurplePluginPrefFrame *frame;
+ PurplePluginPref *ppref;
+ int offset;
+ GList *tmp;
+#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 )
+ SSLVersionRange supported, enabled;
+#endif /* NSS >= 3.14 */
+
+ frame = purple_plugin_pref_frame_new();
+
+ ppref = purple_plugin_pref_new_with_label(_("TLS/SSL Versions"));
+ purple_plugin_pref_frame_add(frame, ppref);
+#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 )
+ /* Get the ranges of supported and enabled SSL versions */
+ if ((SSL_VersionRangeGetSupported(ssl_variant_stream, &supported) == SECSuccess) &&
+ (SSL_VersionRangeGetDefault(ssl_variant_stream, &enabled) == SECSuccess)) {
+ PRUint16 tmp_version;
+ PurplePluginPref *ppref_max;
+
+ ppref = purple_plugin_pref_new_with_name_and_label(MIN_TLS,
+ _("Minimum Version"));
+ purple_plugin_pref_set_type(ppref, PURPLE_PLUGIN_PREF_CHOICE);
+ ppref_max = purple_plugin_pref_new_with_name_and_label(MAX_TLS,
+ _("Maximum Version"));
+ purple_plugin_pref_set_type(ppref_max, PURPLE_PLUGIN_PREF_CHOICE);
+
+ for (tmp_version = supported.min; tmp_version <= supported.max; tmp_version++) {
+ gchar *ver;
+ switch (tmp_version) {
+ case SSL_LIBRARY_VERSION_2:
+ ver = g_strdup(_("SSL 2"));
+ break;
+ case SSL_LIBRARY_VERSION_3_0:
+ ver = g_strdup(_("SSL 3"));
+ break;
+ case SSL_LIBRARY_VERSION_TLS_1_0:
+ ver = g_strdup(_("TLS 1.0"));
+ break;
+ case SSL_LIBRARY_VERSION_TLS_1_1:
+ ver = g_strdup(_("TLS 1.1"));
+ break;
+ case SSL_LIBRARY_VERSION_TLS_1_2:
+ ver = g_strdup(_("TLS 1.2"));
+ break;
+ case SSL_LIBRARY_VERSION_TLS_1_3:
+ ver = g_strdup(_("TLS 1.3"));
+ break;
+ default:
+ ver = g_strdup_printf("0x%04hx", tmp_version);
+ }
+ purple_plugin_pref_add_choice(ppref, ver, GINT_TO_POINTER((gint) tmp_version));
+ purple_plugin_pref_add_choice(ppref_max, ver, GINT_TO_POINTER((gint) tmp_version));
+ g_free(ver);
+ }
+ purple_plugin_pref_frame_add(frame, ppref);
+ purple_plugin_pref_frame_add(frame, ppref_max);
+ }
+#else
+ /* TODO: look into how to do this for older versions? */
+
+ ppref = purple_plugin_pref_new_with_label(_("Not Supported for NSS < 3.14"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+#endif /* NSS >= 3.14 */
+
+ ppref = purple_plugin_pref_new_with_label(_("Ciphers"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ init_tmp_prefs();
+
+ offset = strlen(CIPHER_TMP_ROOT) + 1;
+ for (tmp = tmp_prefs; tmp; tmp = tmp->next) {
+ guint64 parsed = g_ascii_strtoull( (char *) tmp->data + offset,
+ NULL, 16);
+ PRUint16 cipher;
+ SECStatus rv;
+ gchar **split;
+ gchar *escaped_name;
+ SSLCipherSuiteInfo info;
+
+ if (parsed == 0 || parsed > PR_UINT16_MAX) {
+ purple_debug_error("nss-prefs",
+ "Cipher '%s' is not valid to build pref frame.\n",
+ (const char *) tmp->data + offset);
+ continue;
+ }
+
+ cipher = (PRUint16) parsed;
+
+ rv = SSL_GetCipherSuiteInfo(cipher, &info, (int)(sizeof info));
+ if (rv != SECSuccess) {
+ gchar *error_msg = get_error_text();
+ purple_debug_warning("nss-prefs",
+ "SSL_GetCipherSuiteInfo didn't like value 0x%04x: %s\n",
+ cipher, error_msg);
+ g_free(error_msg);
+ continue;
+ }
+ escaped_name = g_strdup_printf("%s (0x%04x)",
+ info.cipherSuiteName, cipher);
+ /** Escape the _ for the label */
+ split = g_strsplit(escaped_name, "_", -1);
+ g_free(escaped_name);
+ escaped_name = g_strjoinv("__", split);
+ g_strfreev(split);
+ ppref = purple_plugin_pref_new_with_name_and_label(
+ (const char *) tmp->data, escaped_name);
+ g_free(escaped_name);
+ purple_plugin_pref_frame_add(frame, ppref);
+ }
+
+ return frame;
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin) {
+ const PRUint16 *cipher;
+
+ handle = plugin;
+
+ tmp_prefs = NULL;
+ default_ciphers = NULL;
+
+ for (cipher = SSL_GetImplementedCiphers(); *cipher != 0; ++cipher) {
+ PRBool enabled;
+ SECStatus rv = SSL_CipherPrefGetDefault(*cipher, &enabled);
+ if (rv == SECSuccess && enabled) {
+ default_ciphers = g_list_prepend(default_ciphers,
+ g_strdup_printf("0x%04x", *cipher));
+ }
+ }
+
+ enable_ciphers(FALSE);
+ set_versions(FALSE);
+ purple_prefs_connect_callback(handle, MIN_TLS,
+ set_version_pref, GINT_TO_POINTER(FALSE));
+ purple_prefs_connect_callback(handle, MAX_TLS,
+ set_version_pref, GINT_TO_POINTER(TRUE));
+
+ return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin) {
+
+ /* Remove the temporary prefs */
+ if (tmp_prefs) {
+ purple_prefs_remove(CIPHER_TMP_ROOT);
+ while (tmp_prefs) {
+ g_free(tmp_prefs->data);
+ tmp_prefs = g_list_delete_link(tmp_prefs, tmp_prefs);
+ }
+ }
+
+ /* Restore the original ciphers */
+ enable_ciphers(TRUE);
+ while (default_ciphers) {
+ g_free(default_ciphers->data);
+ default_ciphers = g_list_delete_link(default_ciphers,
+ default_ciphers);
+ }
+
+ set_versions(TRUE);
+#if NSS_VMAJOR > 3 || ( NSS_VMAJOR == 3 && NSS_VMINOR >= 14 )
+ g_free(default_versions);
+ default_versions = NULL;
+#endif
+
+ return TRUE;
+}
+
+
+static PurplePluginUiInfo prefs_info = {
+ get_plugin_pref_frame,
+ 0, /* page_num (Reserved) */
+ NULL, /* frame (Reserved) */
+ /* Padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static PurplePluginInfo info = {
+ PURPLE_PLUGIN_MAGIC,
+ PURPLE_MAJOR_VERSION,
+ PURPLE_MINOR_VERSION,
+ PURPLE_PLUGIN_STANDARD, /**< type */
+ NULL, /**< ui_requirement */
+ 0, /**< flags */
+ NULL, /**< dependencies */
+ PURPLE_PRIORITY_DEFAULT, /**< priority */
+
+ PLUGIN_ID, /**< id */
+ N_("NSS Preferences"), /**< name */
+ DISPLAY_VERSION, /**< version */
+ /** summary */
+ N_("Configure Ciphers and other Settings for "
+ "the NSS SSL/TLS Plugin"),
+ /** description */
+ N_("Configure Ciphers and other Settings for "
+ "the NSS SSL/TLS Plugin"),
+ "Daniel Atallah <datallah@pidgin.im>", /**< author */
+ PURPLE_WEBSITE, /**< homepage */
+
+ plugin_load, /**< load */
+ plugin_unload, /**< unload */
+ NULL, /**< destroy */
+
+ NULL, /**< ui_info */
+ NULL, /**< extra_info */
+ &prefs_info, /**< prefs_info */
+ NULL,
+ /* Padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+init_plugin(PurplePlugin *plugin) {
+ info.dependencies = g_list_prepend(info.dependencies, "ssl-nss");
+
+ purple_prefs_add_none(PREF_BASE);
+ purple_prefs_add_string_list(CIPHERS_PREF, NULL);
+ purple_prefs_add_int(MIN_TLS, 0);
+ purple_prefs_add_int(MAX_TLS, 0);
+}
+
+PURPLE_INIT_PLUGIN(nss_prefs, init_plugin, info)
--- a/libpurple/plugins/ssl/ssl-nss.c Wed Nov 05 12:04:11 2014 -0500
+++ b/libpurple/plugins/ssl/ssl-nss.c Wed Nov 05 13:13:37 2014 -0500
@@ -197,7 +197,6 @@
const PRUint16 suite = *cipher;
SECStatus rv;
PRBool enabled;
- PRErrorCode err;
SSLCipherSuiteInfo info;
rv = SSL_CipherPrefGetDefault(suite, &enabled);
--- a/pidgin/win32/nsis/pidgin-installer.nsi Wed Nov 05 12:04:11 2014 -0500
+++ b/pidgin/win32/nsis/pidgin-installer.nsi Wed Nov 05 13:13:37 2014 -0500
@@ -592,6 +592,7 @@
Delete "$INSTDIR\plugins\markerline.dll"
Delete "$INSTDIR\plugins\newline.dll"
Delete "$INSTDIR\plugins\notify.dll"
+ Delete "$INSTDIR\plugins\nss-prefs.dll"
Delete "$INSTDIR\plugins\offlinemsg.dll"
Delete "$INSTDIR\plugins\perl.dll"
Delete "$INSTDIR\plugins\pidginrc.dll"