Merge the gnutls stuff with the cert updates release-2.x.y

Tue, 07 Mar 2017 20:29:05 -0600

author
Gary Kramlich <grim@reaperworld.com>
date
Tue, 07 Mar 2017 20:29:05 -0600
branch
release-2.x.y
changeset 38219
cf314c202ffa
parent 38218
c308c43378dd (current diff)
parent 38216
887efbd652d8 (diff)
child 38220
a6f3f989ada5

Merge the gnutls stuff with the cert updates

--- a/ChangeLog.API	Tue Mar 07 20:27:59 2017 -0600
+++ b/ChangeLog.API	Tue Mar 07 20:29:05 2017 -0600
@@ -5,6 +5,11 @@
 		Added:
 		* PURPLE_MESSAGE_REMOTE_SEND in PurpleMessageFlags, to specify
 		messages like _SEND that were sent from another location.
+		* purple_certificate_get_fingerprint_sha256
+		* purple_certificate_compare_pubkeys
+		* PurpleCertificateScheme.get_fingerprint_sha256
+		* PurpleCertificateScheme.compare_pubkeys
+		* PURPLE_CERTIFICATE_SCHEME_HAS_FUNC
 
 version 2.11.0:
 	libpurple:
--- a/finch/libgnt/gntkeys.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/finch/libgnt/gntkeys.c	Tue Mar 07 20:29:05 2017 -0600
@@ -211,7 +211,7 @@
  */
 #define SIZE 256
 
-#define IS_END         1 << 0
+#define IS_END         (1 << 0)
 struct _node
 {
 	struct _node *next[SIZE];
--- a/libpurple/buddyicon.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/buddyicon.c	Tue Mar 07 20:29:05 2017 -0600
@@ -1264,8 +1264,8 @@
 	                                        g_free, NULL);
 	pointer_icon_cache = g_hash_table_new(g_direct_hash, g_direct_equal);
 
-    if (!cache_dir)
-    	cache_dir = g_build_filename(purple_user_dir(), "icons", NULL);
+	if (!cache_dir)
+		cache_dir = g_build_filename(purple_user_dir(), "icons", NULL);
 
 	purple_signal_connect(purple_imgstore_get_handle(), "image-deleting",
 	                      purple_buddy_icons_get_handle(),
--- a/libpurple/certificate.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/certificate.c	Tue Mar 07 20:29:05 2017 -0600
@@ -84,6 +84,29 @@
 	}
 }
 
+static void
+get_ascii_fingerprints (PurpleCertificate *crt, gchar **sha1, gchar **sha256)
+{
+	GByteArray *sha_bin;
+
+	if (sha1 != NULL) {
+		sha_bin = purple_certificate_get_fingerprint_sha1(crt);
+
+		*sha1 = purple_base16_encode_chunked(sha_bin->data, sha_bin->len);
+
+		g_byte_array_free(sha_bin, TRUE);
+	}
+
+	if (sha256 != NULL) {
+		sha_bin = purple_certificate_get_fingerprint_sha256(crt, FALSE);
+
+		*sha256 = (sha_bin == NULL) ? g_strdup("(null)") :
+			purple_base16_encode_chunked(sha_bin->data, sha_bin->len);
+
+		g_byte_array_free(sha_bin, TRUE);
+	}
+}
+
 void
 purple_certificate_verify (PurpleCertificateVerifier *verifier,
 			   const gchar *subject_name, GList *cert_chain,
@@ -388,6 +411,30 @@
 	return fpr;
 }
 
+GByteArray *
+purple_certificate_get_fingerprint_sha256(PurpleCertificate *crt, gboolean sha1_fallback)
+{
+	PurpleCertificateScheme *scheme;
+	GByteArray *fpr = NULL;
+
+	g_return_val_if_fail(crt, NULL);
+	g_return_val_if_fail(crt->scheme, NULL);
+
+	scheme = crt->scheme;
+
+	if (!PURPLE_CERTIFICATE_SCHEME_HAS_FUNC(scheme, get_fingerprint_sha256)) {
+		/* outdated ssl module? fallback to sha1 and print a warning */
+		if (sha1_fallback) {
+			fpr = purple_certificate_get_fingerprint_sha1(crt);
+		}
+		g_return_val_if_reached(fpr);
+	}
+
+	fpr = (scheme->get_fingerprint_sha256)(crt);
+
+	return fpr;
+}
+
 gchar *
 purple_certificate_get_unique_id(PurpleCertificate *crt)
 {
@@ -461,6 +508,24 @@
 	return (scheme->get_times)(crt, activation, expiration);
 }
 
+gboolean
+purple_certificate_compare_pubkeys(PurpleCertificate *crt1, PurpleCertificate *crt2)
+{
+	PurpleCertificateScheme *scheme;
+
+	g_return_val_if_fail(crt1 && crt2, FALSE);
+	g_return_val_if_fail(crt1->scheme && crt2->scheme, FALSE);
+	g_return_val_if_fail(crt1->scheme == crt2->scheme, FALSE);
+
+	scheme = crt1->scheme;
+
+	if (!(PURPLE_CERTIFICATE_SCHEME_HAS_FUNC(scheme, compare_pubkeys))) {
+		return FALSE;
+	}
+
+	return (scheme->compare_pubkeys)(crt1, crt2);
+}
+
 gchar *
 purple_certificate_pool_mkpath(PurpleCertificatePool *pool, const gchar *id)
 {
@@ -630,18 +695,13 @@
 static void
 x509_singleuse_start_verify (PurpleCertificateVerificationRequest *vrq)
 {
-	gchar *sha_asc;
-	GByteArray *sha_bin;
+	gchar *sha1_asc, *sha256_asc;
 	gchar *cn;
 	const gchar *cn_match;
-	gchar *primary, *secondary;
+	gchar *primary, *secondary, *secondary_extra;
 	PurpleCertificate *crt = (PurpleCertificate *) vrq->cert_chain->data;
 
-	/* Pull out the SHA1 checksum */
-	sha_bin = purple_certificate_get_fingerprint_sha1(crt);
-	/* Now decode it for display */
-	sha_asc = purple_base16_encode_chunked(sha_bin->data,
-					       sha_bin->len);
+	get_ascii_fingerprints(crt, &sha1_asc, &sha256_asc);
 
 	/* Get the cert Common Name */
 	cn = purple_certificate_get_subject_name(crt);
@@ -655,14 +715,17 @@
 
 	/* Make messages */
 	primary = g_strdup_printf(_("%s has presented the following certificate for just-this-once use:"), vrq->subject_name);
-	secondary = g_strdup_printf(_("Common name: %s %s\nFingerprint (SHA1): %s"), cn, cn_match, sha_asc);
+	secondary = g_strdup_printf(_("Common name: %s %s\nFingerprint (SHA1): %s"), cn, cn_match, sha1_asc);
+
+	/* TODO: make this part of the translatable string above */
+	secondary_extra = g_strdup_printf("%s\nSHA256: %s", secondary, sha256_asc);
 
 	/* Make a semi-pretty display */
 	purple_request_accept_cancel(
 		vrq->cb_data, /* TODO: Find what the handle ought to be */
 		_("Single-use Certificate Verification"),
 		primary,
-		secondary,
+		secondary_extra,
 		0,            /* Accept by default */
 		NULL,         /* No account */
 		NULL,         /* No other user */
@@ -675,8 +738,9 @@
 	g_free(cn);
 	g_free(primary);
 	g_free(secondary);
-	g_free(sha_asc);
-	g_byte_array_free(sha_bin, TRUE);
+	g_free(secondary_extra);
+	g_free(sha1_asc);
+	g_free(sha256_asc);
 }
 
 static void
@@ -1506,10 +1570,10 @@
 		return;
 	}
 
-	/* Now get SHA1 sums for both and compare them */
+	/* Now get SHA256 sums for both and compare them */
 	/* TODO: This is not an elegant way to compare certs */
-	peer_fpr = purple_certificate_get_fingerprint_sha1(peer_crt);
-	cached_fpr = purple_certificate_get_fingerprint_sha1(cached_crt);
+	peer_fpr = purple_certificate_get_fingerprint_sha256(peer_crt, TRUE);
+	cached_fpr = purple_certificate_get_fingerprint_sha256(cached_crt, TRUE);
 	if (!memcmp(peer_fpr->data, cached_fpr->data, peer_fpr->len)) {
 		purple_debug_info("certificate/x509/tls_cached",
 				  "Peer cert matched cached\n");
@@ -1616,8 +1680,8 @@
 			if (ca_crt != NULL) {
 				GByteArray *failing_fpr;
 				GByteArray *ca_fpr;
-				failing_fpr = purple_certificate_get_fingerprint_sha1(failing_crt);
-				ca_fpr = purple_certificate_get_fingerprint_sha1(ca_crt);
+				failing_fpr = purple_certificate_get_fingerprint_sha256(failing_crt, TRUE);
+				ca_fpr = purple_certificate_get_fingerprint_sha256(ca_crt, TRUE);
 				if (byte_arrays_equal(failing_fpr, ca_fpr)) {
 					purple_debug_info("certificate/x509/tls_cached",
 							"Full chain verification failed (probably a bad "
@@ -1699,12 +1763,18 @@
 	 * If the fingerprints don't match, we'll fall back to checking the
 	 * signature.
 	 */
-	last_fpr = purple_certificate_get_fingerprint_sha1(end_crt);
+	last_fpr = purple_certificate_get_fingerprint_sha256(end_crt, TRUE);
+
+	ca_id = purple_certificate_get_unique_id(end_crt);
+
 	for (cur = ca_crts; cur; cur = cur->next) {
 		ca_crt = cur->data;
-		ca_fpr = purple_certificate_get_fingerprint_sha1(ca_crt);
+		ca_fpr = purple_certificate_get_fingerprint_sha256(ca_crt, TRUE);
+		ca2_id = purple_certificate_get_unique_id(ca_crt);
 
 		if ( byte_arrays_equal(last_fpr, ca_fpr) ||
+				(purple_strequal(ca_id, ca2_id) &&
+				 purple_certificate_compare_pubkeys(end_crt, ca_crt)) ||
 				purple_certificate_signed_by(end_crt, ca_crt) )
 		{
 			/* TODO: If signed_by ever returns a reason, maybe mention
@@ -1714,11 +1784,14 @@
 			   user's poor, leaky eyes. */
 			valid = TRUE;
 			g_byte_array_free(ca_fpr, TRUE);
+			g_free(ca2_id);
 			break;
 		}
 
 		g_byte_array_free(ca_fpr, TRUE);
+		g_free(ca2_id);
 	}
+	g_free(ca_id);
 
 	if (valid == FALSE)
 		flags |= PURPLE_CERTIFICATE_INVALID_CHAIN;
@@ -2152,19 +2225,14 @@
 void
 purple_certificate_display_x509(PurpleCertificate *crt)
 {
-	gchar *sha_asc;
-	GByteArray *sha_bin;
+	gchar *sha1_asc, *sha256_asc;
 	gchar *cn, *issuer_id;
 	time_t activation, expiration;
 	gchar *activ_str, *expir_str;
-	gchar *secondary;
+	gchar *secondary, *secondary_extra;
 	gboolean self_signed;
 
-	/* Pull out the SHA1 checksum */
-	sha_bin = purple_certificate_get_fingerprint_sha1(crt);
-	/* Now decode it for display */
-	sha_asc = purple_base16_encode_chunked(sha_bin->data,
-					       sha_bin->len);
+	get_ascii_fingerprints(crt, &sha1_asc, &sha256_asc);
 
 	/* Get the cert Common Name */
 	/* TODO: Will break on CA certs */
@@ -2193,20 +2261,23 @@
 				  "Expiration date: %s\n"),
 				cn ? cn : "(null)",
 				self_signed ? _("(self-signed)") : (issuer_id ? issuer_id : "(null)"),
-				sha_asc ? sha_asc : "(null)",
+				sha1_asc ? sha1_asc : "(null)",
 				activ_str ? activ_str : "(null)",
 				expir_str ? expir_str : "(null)");
 
+	/* TODO: make this part of the translatable string above */
+	secondary_extra = g_strdup_printf("%sSHA256: %s", secondary, sha256_asc);
+
 	/* Make a semi-pretty display */
 	if (self_signed) {
 		purple_notify_info(NULL, /* TODO: Find what the handle ought to be */
 			_("Certificate Information"),
 			"",
-			secondary);
+			secondary_extra);
 	} else {
 		purple_request_action(NULL, /* TODO: Find what the handle ought to be */
 			_("Certificate Information"), _("Certificate Information"),
-			secondary, 2, NULL, NULL, NULL, 
+			secondary_extra, 2, NULL, NULL, NULL,
 			issuer_id, 2,
 			_("View Issuer Certificate"), PURPLE_CALLBACK(display_x509_issuer),
 			_("Close"), PURPLE_CALLBACK(g_free));
@@ -2219,10 +2290,11 @@
 	g_free(cn);
 	g_free(issuer_id);
 	g_free(secondary);
-	g_free(sha_asc);
+	g_free(secondary_extra);
+	g_free(sha1_asc);
+	g_free(sha256_asc);
 	g_free(activ_str);
 	g_free(expir_str);
-	g_byte_array_free(sha_bin, TRUE);
 }
 
 void purple_certificate_add_ca_search_path(const char *path)
--- a/libpurple/certificate.h	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/certificate.h	Tue Mar 07 20:29:05 2017 -0600
@@ -315,9 +315,41 @@
 	 */
 	void (* verify_cert)(PurpleCertificateVerificationRequest *vrq, PurpleCertificateInvalidityFlags *flags);
 
-	void (*_purple_reserved3)(void);
+	/**
+	 * The size of the PurpleCertificateScheme. This should always be sizeof(PurpleCertificateScheme).
+	 * This allows adding more functions to this struct without requiring a major version bump.
+	 *
+	 * PURPLE_CERTIFICATE_SCHEME_HAS_FUNC() should be used for functions after this point.
+	 */
+	unsigned long struct_size;
+
+	/**
+	 * Retrieves the certificate public key fingerprint using SHA256
+	 *
+	 * @param crt   Certificate instance
+	 * @return Binary representation of SHA256 hash - must be freed using
+	 *         g_byte_array_free()
+	 * @since 2.12.0
+	 */
+	GByteArray * (* get_fingerprint_sha256)(PurpleCertificate *crt);
+
+	/**
+	 * Compares the public keys of two certificates
+	 *
+	 * @param crt1  A certificate instance
+	 * @param crt2  Another certificate instance
+	 * @return TRUE if both certificates have the same key, otherwise FALSE
+	 * @since 2.12.0
+	 */
+	gboolean (* compare_pubkeys)(PurpleCertificate *crt1, PurpleCertificate *crt2);
 };
 
+#define PURPLE_CERTIFICATE_SCHEME_HAS_FUNC(obj, member) \
+	(((G_STRUCT_OFFSET(PurpleCertificateScheme, member) < G_STRUCT_OFFSET(PurpleCertificateScheme, struct_size)) \
+	  || (G_STRUCT_OFFSET(PurpleCertificateScheme, member) < obj->struct_size)) && \
+	 obj->member != NULL)
+
+
 /** A set of operations used to provide logic for verifying a Certificate's
  *  authenticity.
  *
@@ -578,12 +610,26 @@
  * Retrieves the certificate public key fingerprint using SHA1.
  *
  * @param crt        Certificate instance
- * @return Binary representation of the hash. You are responsible for free()ing
- *         this.
+ * @return Binary representation of the hash. You are responsible for freeing
+ *         this with g_byte_array_free().
+ * @see purple_base16_encode_chunked()
+ * @see purple_certificate_get_fingerprint_sha256()
+ */
+GByteArray *
+purple_certificate_get_fingerprint_sha1(PurpleCertificate *crt);
+
+/**
+ * Retrieves the certificate public key fingerprint using SHA256.
+ *
+ * @param crt        Certificate instance
+ * @param sha1_fallback  If true, return SHA1 if the SSL module doesn't
+ *                       implement SHA256. Otherwise, return NULL.
+ * @return Binary representation of the hash. You are responsible for freeing
+ *         this with g_byte_array_free().
  * @see purple_base16_encode_chunked()
  */
 GByteArray *
-purple_certificate_get_fingerprint_sha1(PurpleCertificate *crt);
+purple_certificate_get_fingerprint_sha256(PurpleCertificate *crt, gboolean sha1_fallback);
 
 /**
  * Get a unique identifier for the certificate
@@ -638,6 +684,20 @@
 gboolean
 purple_certificate_get_times(PurpleCertificate *crt, time_t *activation, time_t *expiration);
 
+/**
+ * Compares the public keys of two certificates.
+ *
+ * If the SSL backend does not implement this function, it may return FALSE
+ * every time. This is the case with the NSS plugin, which doesn't need it.
+ *
+ * @param crt1  A certificate instance
+ * @param crt2  Another certificate instance
+ * @return TRUE if both certificates have the same key, otherwise FALSE
+ * @since 2.12.0
+ */
+gboolean
+purple_certificate_compare_pubkeys(PurpleCertificate *crt1, PurpleCertificate *crt2);
+
 /*@}*/
 
 /*****************************************************************************/
--- a/libpurple/dbus-server.h	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/dbus-server.h	Tue Mar 07 20:29:05 2017 -0600
@@ -199,7 +199,9 @@
 
  */
 
+#ifndef DBUS_EXPORT
 #define DBUS_EXPORT
+#endif
 
 /*
    Here we include the list of #PURPLE_DBUS_DECLARE_TYPE statements for
--- a/libpurple/plugins/perl/common/Certificate.xs	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/plugins/perl/common/Certificate.xs	Tue Mar 07 20:29:05 2017 -0600
@@ -219,6 +219,19 @@
 	OUTPUT:
 		RETVAL
 
+SV*
+purple_certificate_get_fingerprint_sha256(crt, sha1_fallback)
+	Purple::Certificate crt
+	gboolean sha1_fallback
+	PREINIT:
+		GByteArray *gba = NULL;
+	CODE:
+		gba = purple_certificate_get_fingerprint_sha256(crt, sha1_fallback);
+		RETVAL = newSVpv((gchar *)gba->data, gba->len);
+		g_byte_array_free(gba, TRUE);
+	OUTPUT:
+		RETVAL
+
 void
 purple_certificate_verify(verifier, subject_name, cert_chain, cb, cb_data)
 	Purple::Certificate::Verifier verifier
--- a/libpurple/plugins/ssl/ssl-gnutls.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/plugins/ssl/ssl-gnutls.c	Tue Mar 07 20:29:05 2017 -0600
@@ -1037,9 +1037,9 @@
 }
 
 static GByteArray *
-x509_sha1sum(PurpleCertificate *crt)
+x509_shasum(PurpleCertificate *crt, gnutls_digest_algorithm_t algo)
 {
-	size_t hashlen = 20; /* SHA1 hashes are 20 bytes */
+	size_t hashlen = (algo == GNUTLS_DIG_SHA1) ? 20 : 32;
 	size_t tmpsz = hashlen; /* Throw-away variable for GnuTLS to stomp on*/
 	gnutls_x509_crt_t crt_dat;
 	GByteArray *hash; /**< Final hash container */
@@ -1051,7 +1051,7 @@
 
 	/* Extract the fingerprint */
 	g_return_val_if_fail(
-		0 == gnutls_x509_crt_get_fingerprint(crt_dat, GNUTLS_DIG_SHA,
+		0 == gnutls_x509_crt_get_fingerprint(crt_dat, algo,
 						     hashbuf, &tmpsz),
 		NULL);
 
@@ -1065,6 +1065,18 @@
 	return hash;
 }
 
+static GByteArray *
+x509_sha1sum(PurpleCertificate *crt)
+{
+	return x509_shasum(crt, GNUTLS_DIG_SHA1);
+}
+
+static GByteArray *
+x509_sha256sum(PurpleCertificate *crt)
+{
+	return x509_shasum(crt, GNUTLS_DIG_SHA256);
+}
+
 static gchar *
 x509_cert_dn (PurpleCertificate *crt)
 {
@@ -1220,6 +1232,46 @@
 	return success;
 }
 
+/* GNUTLS_KEYID_USE_BEST_KNOWN was added in gnutls 3.4.1, but can't ifdef it
+ * because it's an enum member. Older versions will ignore it, which means
+ * using SHA1 instead of SHA256 to compare pubkeys. But hey, not my fault. */
+#if GNUTLS_VERSION_NUMBER < 0x030401
+#define KEYID_FLAG (1<<30)
+#else
+#define KEYID_FLAG GNUTLS_KEYID_USE_BEST_KNOWN
+#endif
+
+static gboolean
+x509_compare_pubkeys (PurpleCertificate *crt1, PurpleCertificate *crt2)
+{
+	gnutls_x509_crt_t crt_dat1, crt_dat2;
+	unsigned char buffer1[64], buffer2[64];
+	size_t size1, size2;
+	size1 = size2 = sizeof(buffer1);
+
+	g_return_val_if_fail(crt1 && crt2, FALSE);
+	g_return_val_if_fail(crt1->scheme == &x509_gnutls, FALSE);
+	g_return_val_if_fail(crt2->scheme == &x509_gnutls, FALSE);
+
+	crt_dat1 = X509_GET_GNUTLS_DATA(crt1);
+
+	if (gnutls_x509_crt_get_key_id(crt_dat1, KEYID_FLAG, buffer1, &size1) != 0) {
+		return FALSE;
+	}
+
+	crt_dat2 = X509_GET_GNUTLS_DATA(crt2);
+
+	if (gnutls_x509_crt_get_key_id(crt_dat2, KEYID_FLAG, buffer2, &size2) != 0) {
+		return FALSE;
+	}
+
+	if (size1 != size2) {
+		return FALSE;
+	}
+
+	return memcmp(buffer1, buffer2, size1) == 0;
+}
+
 /* X.509 certificate operations provided by this plugin */
 static PurpleCertificateScheme x509_gnutls = {
 	"x509",                          /* Scheme name */
@@ -1239,8 +1291,9 @@
 
 	NULL,
 	NULL,
-	NULL
-
+	sizeof(PurpleCertificateScheme), /* struct_size */
+	x509_sha256sum,                  /* SHA256 fingerprint */
+	x509_compare_pubkeys,            /* Compare public keys */
 };
 
 static PurpleSslOps ssl_ops =
--- a/libpurple/plugins/ssl/ssl-nss.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/plugins/ssl/ssl-nss.c	Tue Mar 07 20:29:05 2017 -0600
@@ -881,11 +881,11 @@
 }
 
 static GByteArray *
-x509_sha1sum(PurpleCertificate *crt)
+x509_shasum(PurpleCertificate *crt, SECOidTag algo)
 {
 	CERTCertificate *crt_dat;
-	size_t hashlen = 20; /* Size of an sha1sum */
-	GByteArray *sha1sum;
+	size_t hashlen = (algo == SEC_OID_SHA1) ? 20 : 32;
+	GByteArray *hash;
 	SECItem *derCert; /* DER representation of the cert */
 	SECStatus st;
 
@@ -899,22 +899,34 @@
 	derCert = &(crt_dat->derCert);
 
 	/* Make a hash! */
-	sha1sum = g_byte_array_sized_new(hashlen);
+	hash = g_byte_array_sized_new(hashlen);
 	/* glib leaves the size as 0 by default */
-	sha1sum->len = hashlen;
+	hash->len = hashlen;
 
-	st = PK11_HashBuf(SEC_OID_SHA1, sha1sum->data,
+	st = PK11_HashBuf(algo, hash->data,
 			  derCert->data, derCert->len);
 
 	/* Check for errors */
 	if (st != SECSuccess) {
-		g_byte_array_free(sha1sum, TRUE);
+		g_byte_array_free(hash, TRUE);
 		purple_debug_error("nss/x509",
 				   "Error: hashing failed!\n");
 		return NULL;
 	}
 
-	return sha1sum;
+	return hash;
+}
+
+static GByteArray *
+x509_sha1sum(PurpleCertificate *crt)
+{
+	return x509_shasum(crt, SEC_OID_SHA1);
+}
+
+static GByteArray *
+x509_sha256sum(PurpleCertificate *crt)
+{
+	return x509_shasum(crt, SEC_OID_SHA256);
 }
 
 static gchar *
@@ -1211,7 +1223,9 @@
 	x509_importcerts_from_file,      /* Multiple certificate import function */
 	x509_register_trusted_tls_cert,  /* Register a certificate as trusted for TLS */
 	x509_verify_cert,                /* Verify that the specified cert chain is trusted */
-	NULL
+	sizeof(PurpleCertificateScheme), /* struct_size */
+	x509_sha256sum,                  /* SHA256 fingerprint */
+	NULL,
 };
 
 static PurpleSslOps ssl_ops =
--- a/libpurple/protocols/bonjour/jabber.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/protocols/bonjour/jabber.c	Tue Mar 07 20:29:05 2017 -0600
@@ -1320,8 +1320,8 @@
 	if(check_if_blocked(pb))
 		return;
 
-		account = purple_buddy_get_account(pb);
-		gc = purple_account_get_connection(account);
+	account = purple_buddy_get_account(pb);
+	gc = purple_account_get_connection(account);
 
 	if (xmlnode_get_child(packet, "si") != NULL || xmlnode_get_child(packet, "error") != NULL)
 		xep_si_parse(gc, packet, pb);
--- a/libpurple/protocols/novell/nmrtf.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/protocols/novell/nmrtf.c	Tue Mar 07 20:29:05 2017 -0600
@@ -474,23 +474,23 @@
 static int
 rtf_pop_state(NMRtfContext *ctx)
 {
-    NMRtfStateSave *save_old;
+	NMRtfStateSave *save_old;
 	GSList *link_old;
 
-    if (ctx->saved == NULL)
-        return NMRTF_STACK_UNDERFLOW;
+	if (ctx->saved == NULL)
+		return NMRTF_STACK_UNDERFLOW;
 
 	save_old = ctx->saved->data;
-    ctx->chp = save_old->chp;
-    ctx->rds = save_old->rds;
-    ctx->ris = save_old->ris;
-    (ctx->depth)--;
+	ctx->chp = save_old->chp;
+	ctx->rds = save_old->rds;
+	ctx->ris = save_old->ris;
+	(ctx->depth)--;
 
-    g_free(save_old);
+	g_free(save_old);
 	link_old = ctx->saved;
 	ctx->saved = g_slist_remove_link(ctx->saved, link_old);
 	g_slist_free_1(link_old);
-    return NMRTF_OK;
+	return NMRTF_OK;
 }
 
 /*
@@ -671,13 +671,13 @@
 static int
 rtf_apply_property(NMRtfContext *ctx, NMRtfProperty prop, int val)
 {
-    if (ctx->rds == NMRTF_STATE_SKIP)  /* If we're skipping text, */
-        return NMRTF_OK;          /* don't do anything. */
+	if (ctx->rds == NMRTF_STATE_SKIP)  /* If we're skipping text, */
+		return NMRTF_OK;          /* don't do anything. */
 
 	/* Need to flush any temporary data before a property change*/
 	rtf_flush_data(ctx);
 
-    switch (prop) {
+	switch (prop) {
 		case NMRTF_PROP_FONT_IDX:
 			ctx->chp.font_idx = val;
 			break;
@@ -686,9 +686,9 @@
 			break;
 		default:
 			return NMRTF_BAD_TABLE;
-    }
+	}
 
-    return NMRTF_OK;
+	return NMRTF_OK;
 }
 
 /*
--- a/libpurple/protocols/zephyr/Zinternal.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/protocols/zephyr/Zinternal.c	Tue Mar 07 20:29:05 2017 -0600
@@ -259,7 +259,7 @@
     if (!packet_len)
 	return (ZERR_EOF);
 
-	packet[packet_len] = '\0';
+    packet[packet_len] = '\0';
 
     /* Ignore obviously non-Zephyr packets. */
     zvlen = sizeof(ZVERSIONHDR) - 1;
--- a/libpurple/sslconn.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/sslconn.c	Tue Mar 07 20:29:05 2017 -0600
@@ -190,7 +190,7 @@
 					PurpleSslErrorFunction error_func,
                     void *data)
 {
-    return purple_ssl_connect_with_host_fd(account, fd, func, error_func, NULL, data);
+	return purple_ssl_connect_with_host_fd(account, fd, func, error_func, NULL, data);
 }
 
 PurpleSslConnection *
@@ -219,8 +219,9 @@
 	gsc->connect_cb      = func;
 	gsc->error_cb        = error_func;
 	gsc->fd              = fd;
-    if(host)
-        gsc->host            = g_strdup(host);
+	if (host) {
+		gsc->host = g_strdup(host);
+	}
 
 	/* TODO: Move this elsewhere */
 	gsc->verifier = purple_certificate_find_verifier("x509","tls_cached");
--- a/libpurple/util.c	Tue Mar 07 20:27:59 2017 -0600
+++ b/libpurple/util.c	Tue Mar 07 20:29:05 2017 -0600
@@ -219,10 +219,6 @@
 /**************************************************************************
  * Base64 Functions
  **************************************************************************/
-static const char alphabet[] =
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-	"0123456789+/";
-
 static const char xdigits[] =
 	"0123456789abcdef";
 

mercurial