changeset 28100:f834ffa7490b

cert: Validate subject name before prompting due to no CA pool. This likely 'broke' when the subject name validation was moved to the end of x509_tls_cached_unknown_peer. String changes going into 2.6.1. I need to stop looking at these functions, but the Black Hat conference provoked me.
author Paul Aurich <paul@darkrain42.org>
date Fri, 31 Jul 2009 06:35:35 +0000
parents 080cfd84038c
children 4a213a2b3d3d cdc294abb21f
files libpurple/certificate.c
diffstat 1 files changed, 47 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/certificate.c	Fri Jul 31 04:42:52 2009 +0000
+++ b/libpurple/certificate.c	Fri Jul 31 06:35:35 2009 +0000
@@ -1324,7 +1324,8 @@
  * the subject name of the certificate.
  */
 static void
-x509_tls_cached_check_subject_name(PurpleCertificateVerificationRequest *vrq)
+x509_tls_cached_check_subject_name(PurpleCertificateVerificationRequest *vrq,
+                                   gboolean had_ca_pool)
 {
 	PurpleCertificatePool *tls_peers;
 	PurpleCertificate *peer_crt;
@@ -1336,31 +1337,59 @@
 	if ( ! purple_certificate_check_subject_name(peer_crt,
 						     vrq->subject_name) ) {
 		gchar *sn = purple_certificate_get_subject_name(peer_crt);
-		gchar *msg;
 
 		purple_debug_error("certificate/x509/tls_cached",
 				  "Name mismatch: Certificate given for %s "
 				  "has a name of %s\n",
 				  vrq->subject_name, sn);
 
-		/* Prompt the user to authenticate the certificate */
-		/* TODO: Provide the user with more guidance about why he is
-		   being prompted */
-		/* vrq will be completed by user_auth */
-		msg = g_strdup_printf(_("The certificate presented by \"%s\" "
-					"claims to be from \"%s\" instead.  "
-					"This could mean that you are not "
-					"connecting to the service you "
-					"believe you are."),
-				      vrq->subject_name, sn);
+		if (had_ca_pool) {
+			/* Prompt the user to authenticate the certificate */
+			/* TODO: Provide the user with more guidance about why he is
+			   being prompted */
+			/* vrq will be completed by user_auth */
+			gchar *msg;
+			msg = g_strdup_printf(_("The certificate presented by \"%s\" "
+						"claims to be from \"%s\" instead.  "
+						"This could mean that you are not "
+						"connecting to the service you "
+						"believe you are."),
+					      vrq->subject_name, sn);
 
-		x509_tls_cached_user_auth(vrq,msg);
+			x509_tls_cached_user_auth(vrq, msg);
+			g_free(msg);
+		} else {
+			/* Had no CA pool, so couldn't verify the chain *and*
+			 * the subject name isn't valid.
+			 * I think this is bad enough to warrant a fatal error. It's
+			 * not likely anyway...
+			 */
+			/* FIXME: 2.6.1 */
+			purple_notify_error(NULL, /* TODO: Probably wrong. */
+						_("SSL Certificate Error"),
+						_("Invalid certificate chain"),
+						_("You have no database of root certificates, so "
+						"this certificate cannot be validated."));
+		}
 
 		g_free(sn);
-		g_free(msg);
 		return;
 	} /* if (name mismatch) */
 
+	if (had_ca_pool) {
+		/* The subject name is correct, but we weren't able to verify the
+		 * chain because there was no pool of root CAs found. Prompt the user
+		 * to validate it.
+		 */
+
+		/* vrq will be completed by user_auth */
+		x509_tls_cached_user_auth(vrq,_("You have no database of root "
+						"certificates, so this "
+						"certificate cannot be "
+						"validated."));
+		return;
+	}
+
 	/* If we reach this point, the certificate is good. */
 	/* Look up the local cache and store it there for future use */
 	tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,
@@ -1465,7 +1494,7 @@
 		 * or it didn't, in which case we give up and complain to the user.
 		 */
 		if (chain_validated) {
-			x509_tls_cached_check_subject_name(vrq);
+			x509_tls_cached_check_subject_name(vrq, TRUE);
 		} else {
 			/* TODO: Tell the user where the chain broke? */
 			/* TODO: This error will hopelessly confuse any
@@ -1494,17 +1523,13 @@
 	} /* if (signature chain not good) */
 
 	/* If, for whatever reason, there is no Certificate Authority pool
-	   loaded, we will simply present it to the user for checking. */
+	   loaded, we'll verify the subject name and then warn about thsi. */
 	if ( !ca ) {
 		purple_debug_error("certificate/x509/tls_cached",
 				   "No X.509 Certificate Authority pool "
 				   "could be found!\n");
 
-		/* vrq will be completed by user_auth */
-		x509_tls_cached_user_auth(vrq,_("You have no database of root "
-						"certificates, so this "
-						"certificate cannot be "
-						"validated."));
+		x509_tls_cached_check_subject_name(vrq, FALSE);
 		return;
 	}
 
@@ -1585,7 +1610,7 @@
 	g_byte_array_free(ca_fpr, TRUE);
 	g_byte_array_free(last_fpr, TRUE);
 
-	x509_tls_cached_check_subject_name(vrq);
+	x509_tls_cached_check_subject_name(vrq, TRUE);
 }
 
 static void