Mercurial > pidgin
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 { |