comparison libpurple/certificate.c @ 19089:c8962b52579e

- Wrote a tls_cached unknown_peer function that does many fun things, including: - check the certificate signature chain - attempt to load the chain root from a CA database (not yet implemented) - check the chain root's CA-given signature Since I have no Internet access, this has not been tested.
author William Ehlhardt <williamehlhardt@gmail.com>
date Fri, 10 Aug 2007 05:36:42 +0000
parents f5802217844d
children 5310b1294287
comparison
equal deleted inserted replaced
19088:f5802217844d 19089:c8962b52579e
918 918
919 /* For when we've never communicated with this party before */ 919 /* For when we've never communicated with this party before */
920 static void 920 static void
921 x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq) 921 x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
922 { 922 {
923 /* For now, just toss it to the user */ 923 PurpleCertificatePool *ca, *tls_peers;
924 x509_tls_cached_user_auth(vrq); 924 PurpleCertificate *end_crt, *ca_crt;
925 GList *chain = vrq->cert_chain;
926 GList *last;
927 gchar *ca_id;
928
929 /* First, check that the certificate chain is valid */
930 if ( ! purple_certificate_check_signature_chain(chain) ) {
931 /* TODO: Tell the user where the chain broke? */
932 /* TODO: This error will hopelessly confuse any
933 non-elite user. */
934 gchar *secondary;
935
936 secondary = g_strdup_printf(_("The certificate chain presented"
937 " for %s is not valid."),
938 vrq->subject_name);
939
940 /* TODO: Make this error either block the ensuing SSL
941 connection error until the user dismisses this one, or
942 stifle it. */
943 purple_notify_error(NULL, /* TODO: Probably wrong. */
944 _("SSL Certificate Error"),
945 _("Invalid certificate chain"),
946 secondary );
947 g_free(secondary);
948
949 /* Okay, we're done here */
950 purple_certificate_verify_complete(vrq,
951 PURPLE_CERTIFICATE_INVALID);
952 } /* if (signature chain not good) */
953
954 /* Next, attempt to verify the last certificate against a CA */
955 ca = purple_certificate_find_pool(x509_tls_cached.scheme_name, "ca");
956
957 /* If, for whatever reason, there is no Certificate Authority pool
958 loaded, we will simply present it to the user for checking. */
959 if ( !ca ) {
960 purple_debug_error("certificate/x509/tls_cached",
961 "No X.509 Certificate Authority pool "
962 "could be found!\n");
963
964 /* vrq will be completed by user_auth */
965 x509_tls_cached_user_auth(vrq);
966 return;
967 }
968
969 /* TODO: I don't have the Glib documentation handy; is this correct? */
970 last = g_list_last(chain);
971 end_crt = (PurpleCertificate *) last->data;
972
973 /* Attempt to look up the last certificate's issuer */
974 ca_id = purple_certificate_get_issuer_unique_id(end_crt);
975 if ( !purple_certificate_pool_contains(ca, ca_id) ) {
976 purple_debug_info("certificate/x509/tls_cached",
977 "Certificate Authority with DN='%s' not "
978 "found. I'll prompt the user, I guess.\n",
979 ca_id);
980 g_free(ca_id);
981 /* vrq will be completed by user_auth */
982 x509_tls_cached_user_auth(vrq);
983 return;
984 }
985
986 ca_crt = purple_certificate_pool_retrieve(ca, ca_id);
987 g_free(ca_id);
988 g_assert(ca_crt);
989
990 /* Check the signature */
991 if ( !purple_certificate_signed_by(end_crt, ca_crt) ) {
992 /* TODO: If signed_by ever returns a reason, maybe mention
993 that, too. */
994 /* TODO: Also mention the CA involved. While I could do this
995 now, a full DN is a little much with which to assault the
996 user's poor, leaky eyes. */
997 /* TODO: This error message makes my eyes cross, and I wrote it */
998 gchar * secondary =
999 g_strdup_printf(_("The certificate chain presented by "
1000 "%s does not have a valid digital "
1001 "signature from the Certificate "
1002 "Authority it claims to have one "
1003 "from."),
1004 vrq->subject_name);
1005
1006 purple_notify_error(NULL, /* TODO: Probably wrong */
1007 _("SSL Certificate Error"),
1008 _("Invalid certificate authority"
1009 " signature"),
1010 secondary);
1011 g_free(secondary);
1012
1013 /* Signal "bad cert" */
1014 purple_certificate_verify_complete(vrq,
1015 PURPLE_CERTIFICATE_INVALID);
1016 return;
1017 } /* if (CA signature not good) */
1018
1019 /* If we reach this point, the certificate is good. */
1020 /* Look up the local cache and store it there for future use */
1021 tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,
1022 "tls_peers");
1023
1024 if (tls_peers) {
1025 PurpleCertificate *peer_crt = (PurpleCertificate *)chain->data;
1026 g_assert(purple_certificate_pool_store(tls_peers,
1027 vrq->subject_name,
1028 peer_crt) );
1029 } else {
1030 purple_debug_error("certificate/x509/tls_cached",
1031 "Unable to locate tls_peers certificate "
1032 "cache.\n");
1033 }
1034
1035 /* Whew! Done! */
1036 purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_VALID);
925 } 1037 }
926 1038
927 static void 1039 static void
928 x509_tls_cached_start_verify(PurpleCertificateVerificationRequest *vrq) 1040 x509_tls_cached_start_verify(PurpleCertificateVerificationRequest *vrq)
929 { 1041 {