libpurple/certificate.c

branch
release-2.x.y
changeset 38214
b3d0ba7c75f6
parent 36191
2e4475087f04
child 38216
887efbd652d8
equal deleted inserted replaced
38212:274575856b52 38214:b3d0ba7c75f6
82 return _("An unknown certificate error occurred."); 82 return _("An unknown certificate error occurred.");
83 break; 83 break;
84 } 84 }
85 } 85 }
86 86
87 static void
88 get_ascii_fingerprints (PurpleCertificate *crt, gchar **sha1, gchar **sha256)
89 {
90 GByteArray *sha_bin;
91
92 if (sha1 != NULL) {
93 sha_bin = purple_certificate_get_fingerprint_sha1(crt);
94
95 *sha1 = purple_base16_encode_chunked(sha_bin->data, sha_bin->len);
96
97 g_byte_array_free(sha_bin, TRUE);
98 }
99
100 if (sha256 != NULL) {
101 sha_bin = purple_certificate_get_fingerprint_sha256(crt, FALSE);
102
103 *sha256 = (sha_bin == NULL) ? g_strdup("(null)") :
104 purple_base16_encode_chunked(sha_bin->data, sha_bin->len);
105
106 g_byte_array_free(sha_bin, TRUE);
107 }
108 }
109
87 void 110 void
88 purple_certificate_verify (PurpleCertificateVerifier *verifier, 111 purple_certificate_verify (PurpleCertificateVerifier *verifier,
89 const gchar *subject_name, GList *cert_chain, 112 const gchar *subject_name, GList *cert_chain,
90 PurpleCertificateVerifiedCallback cb, 113 PurpleCertificateVerifiedCallback cb,
91 gpointer cb_data) 114 gpointer cb_data)
386 fpr = (scheme->get_fingerprint_sha1)(crt); 409 fpr = (scheme->get_fingerprint_sha1)(crt);
387 410
388 return fpr; 411 return fpr;
389 } 412 }
390 413
414 GByteArray *
415 purple_certificate_get_fingerprint_sha256(PurpleCertificate *crt, gboolean sha1_fallback)
416 {
417 PurpleCertificateScheme *scheme;
418 GByteArray *fpr = NULL;
419
420 g_return_val_if_fail(crt, NULL);
421 g_return_val_if_fail(crt->scheme, NULL);
422
423 scheme = crt->scheme;
424
425 if (!PURPLE_CERTIFICATE_SCHEME_HAS_FUNC(scheme, get_fingerprint_sha256)) {
426 /* outdated ssl module? fallback to sha1 and print a warning */
427 if (sha1_fallback) {
428 fpr = purple_certificate_get_fingerprint_sha1(crt);
429 }
430 g_return_val_if_reached(fpr);
431 }
432
433 fpr = (scheme->get_fingerprint_sha256)(crt);
434
435 return fpr;
436 }
437
391 gchar * 438 gchar *
392 purple_certificate_get_unique_id(PurpleCertificate *crt) 439 purple_certificate_get_unique_id(PurpleCertificate *crt)
393 { 440 {
394 g_return_val_if_fail(crt, NULL); 441 g_return_val_if_fail(crt, NULL);
395 g_return_val_if_fail(crt->scheme, NULL); 442 g_return_val_if_fail(crt->scheme, NULL);
628 } 675 }
629 676
630 static void 677 static void
631 x509_singleuse_start_verify (PurpleCertificateVerificationRequest *vrq) 678 x509_singleuse_start_verify (PurpleCertificateVerificationRequest *vrq)
632 { 679 {
633 gchar *sha_asc; 680 gchar *sha1_asc, *sha256_asc;
634 GByteArray *sha_bin;
635 gchar *cn; 681 gchar *cn;
636 const gchar *cn_match; 682 const gchar *cn_match;
637 gchar *primary, *secondary; 683 gchar *primary, *secondary, *secondary_extra;
638 PurpleCertificate *crt = (PurpleCertificate *) vrq->cert_chain->data; 684 PurpleCertificate *crt = (PurpleCertificate *) vrq->cert_chain->data;
639 685
640 /* Pull out the SHA1 checksum */ 686 get_ascii_fingerprints(crt, &sha1_asc, &sha256_asc);
641 sha_bin = purple_certificate_get_fingerprint_sha1(crt);
642 /* Now decode it for display */
643 sha_asc = purple_base16_encode_chunked(sha_bin->data,
644 sha_bin->len);
645 687
646 /* Get the cert Common Name */ 688 /* Get the cert Common Name */
647 cn = purple_certificate_get_subject_name(crt); 689 cn = purple_certificate_get_subject_name(crt);
648 690
649 /* Determine whether the name matches */ 691 /* Determine whether the name matches */
653 cn_match = _("(DOES NOT MATCH)"); 695 cn_match = _("(DOES NOT MATCH)");
654 } 696 }
655 697
656 /* Make messages */ 698 /* Make messages */
657 primary = g_strdup_printf(_("%s has presented the following certificate for just-this-once use:"), vrq->subject_name); 699 primary = g_strdup_printf(_("%s has presented the following certificate for just-this-once use:"), vrq->subject_name);
658 secondary = g_strdup_printf(_("Common name: %s %s\nFingerprint (SHA1): %s"), cn, cn_match, sha_asc); 700 secondary = g_strdup_printf(_("Common name: %s %s\nFingerprint (SHA1): %s"), cn, cn_match, sha1_asc);
701
702 /* TODO: make this part of the translatable string above */
703 secondary_extra = g_strdup_printf("%s\nSHA256: %s", secondary, sha256_asc);
659 704
660 /* Make a semi-pretty display */ 705 /* Make a semi-pretty display */
661 purple_request_accept_cancel( 706 purple_request_accept_cancel(
662 vrq->cb_data, /* TODO: Find what the handle ought to be */ 707 vrq->cb_data, /* TODO: Find what the handle ought to be */
663 _("Single-use Certificate Verification"), 708 _("Single-use Certificate Verification"),
664 primary, 709 primary,
665 secondary, 710 secondary_extra,
666 0, /* Accept by default */ 711 0, /* Accept by default */
667 NULL, /* No account */ 712 NULL, /* No account */
668 NULL, /* No other user */ 713 NULL, /* No other user */
669 NULL, /* No associated conversation */ 714 NULL, /* No associated conversation */
670 vrq, 715 vrq,
673 718
674 /* Cleanup */ 719 /* Cleanup */
675 g_free(cn); 720 g_free(cn);
676 g_free(primary); 721 g_free(primary);
677 g_free(secondary); 722 g_free(secondary);
678 g_free(sha_asc); 723 g_free(secondary_extra);
679 g_byte_array_free(sha_bin, TRUE); 724 g_free(sha1_asc);
725 g_free(sha256_asc);
680 } 726 }
681 727
682 static void 728 static void
683 x509_singleuse_destroy_request (PurpleCertificateVerificationRequest *vrq) 729 x509_singleuse_destroy_request (PurpleCertificateVerificationRequest *vrq)
684 { 730 {
1504 /* vrq now becomes the problem of unknown_peer */ 1550 /* vrq now becomes the problem of unknown_peer */
1505 x509_tls_cached_unknown_peer(vrq, flags); 1551 x509_tls_cached_unknown_peer(vrq, flags);
1506 return; 1552 return;
1507 } 1553 }
1508 1554
1509 /* Now get SHA1 sums for both and compare them */ 1555 /* Now get SHA256 sums for both and compare them */
1510 /* TODO: This is not an elegant way to compare certs */ 1556 /* TODO: This is not an elegant way to compare certs */
1511 peer_fpr = purple_certificate_get_fingerprint_sha1(peer_crt); 1557 peer_fpr = purple_certificate_get_fingerprint_sha256(peer_crt, TRUE);
1512 cached_fpr = purple_certificate_get_fingerprint_sha1(cached_crt); 1558 cached_fpr = purple_certificate_get_fingerprint_sha256(cached_crt, TRUE);
1513 if (!memcmp(peer_fpr->data, cached_fpr->data, peer_fpr->len)) { 1559 if (!memcmp(peer_fpr->data, cached_fpr->data, peer_fpr->len)) {
1514 purple_debug_info("certificate/x509/tls_cached", 1560 purple_debug_info("certificate/x509/tls_cached",
1515 "Peer cert matched cached\n"); 1561 "Peer cert matched cached\n");
1516 x509_tls_cached_complete(vrq, flags); 1562 x509_tls_cached_complete(vrq, flags);
1517 } else { 1563 } else {
1614 gchar *uid = purple_certificate_get_unique_id(failing_crt); 1660 gchar *uid = purple_certificate_get_unique_id(failing_crt);
1615 PurpleCertificate *ca_crt = purple_certificate_pool_retrieve(ca, uid); 1661 PurpleCertificate *ca_crt = purple_certificate_pool_retrieve(ca, uid);
1616 if (ca_crt != NULL) { 1662 if (ca_crt != NULL) {
1617 GByteArray *failing_fpr; 1663 GByteArray *failing_fpr;
1618 GByteArray *ca_fpr; 1664 GByteArray *ca_fpr;
1619 failing_fpr = purple_certificate_get_fingerprint_sha1(failing_crt); 1665 failing_fpr = purple_certificate_get_fingerprint_sha256(failing_crt, TRUE);
1620 ca_fpr = purple_certificate_get_fingerprint_sha1(ca_crt); 1666 ca_fpr = purple_certificate_get_fingerprint_sha256(ca_crt, TRUE);
1621 if (byte_arrays_equal(failing_fpr, ca_fpr)) { 1667 if (byte_arrays_equal(failing_fpr, ca_fpr)) {
1622 purple_debug_info("certificate/x509/tls_cached", 1668 purple_debug_info("certificate/x509/tls_cached",
1623 "Full chain verification failed (probably a bad " 1669 "Full chain verification failed (probably a bad "
1624 "signature algorithm), but found the last " 1670 "signature algorithm), but found the last "
1625 "certificate %s in the CA pool.\n", uid); 1671 "certificate %s in the CA pool.\n", uid);
1697 * circumstances (one of Verisign's root CAs is self-signed with MD2). 1743 * circumstances (one of Verisign's root CAs is self-signed with MD2).
1698 * 1744 *
1699 * If the fingerprints don't match, we'll fall back to checking the 1745 * If the fingerprints don't match, we'll fall back to checking the
1700 * signature. 1746 * signature.
1701 */ 1747 */
1702 last_fpr = purple_certificate_get_fingerprint_sha1(end_crt); 1748 last_fpr = purple_certificate_get_fingerprint_sha256(end_crt, TRUE);
1703 for (cur = ca_crts; cur; cur = cur->next) { 1749 for (cur = ca_crts; cur; cur = cur->next) {
1704 ca_crt = cur->data; 1750 ca_crt = cur->data;
1705 ca_fpr = purple_certificate_get_fingerprint_sha1(ca_crt); 1751 ca_fpr = purple_certificate_get_fingerprint_sha256(ca_crt, TRUE);
1706 1752
1707 if ( byte_arrays_equal(last_fpr, ca_fpr) || 1753 if ( byte_arrays_equal(last_fpr, ca_fpr) ||
1708 purple_certificate_signed_by(end_crt, ca_crt) ) 1754 purple_certificate_signed_by(end_crt, ca_crt) )
1709 { 1755 {
1710 /* TODO: If signed_by ever returns a reason, maybe mention 1756 /* TODO: If signed_by ever returns a reason, maybe mention
2150 } 2196 }
2151 2197
2152 void 2198 void
2153 purple_certificate_display_x509(PurpleCertificate *crt) 2199 purple_certificate_display_x509(PurpleCertificate *crt)
2154 { 2200 {
2155 gchar *sha_asc; 2201 gchar *sha1_asc, *sha256_asc;
2156 GByteArray *sha_bin;
2157 gchar *cn, *issuer_id; 2202 gchar *cn, *issuer_id;
2158 time_t activation, expiration; 2203 time_t activation, expiration;
2159 gchar *activ_str, *expir_str; 2204 gchar *activ_str, *expir_str;
2160 gchar *secondary; 2205 gchar *secondary, *secondary_extra;
2161 gboolean self_signed; 2206 gboolean self_signed;
2162 2207
2163 /* Pull out the SHA1 checksum */ 2208 get_ascii_fingerprints(crt, &sha1_asc, &sha256_asc);
2164 sha_bin = purple_certificate_get_fingerprint_sha1(crt);
2165 /* Now decode it for display */
2166 sha_asc = purple_base16_encode_chunked(sha_bin->data,
2167 sha_bin->len);
2168 2209
2169 /* Get the cert Common Name */ 2210 /* Get the cert Common Name */
2170 /* TODO: Will break on CA certs */ 2211 /* TODO: Will break on CA certs */
2171 cn = purple_certificate_get_subject_name(crt); 2212 cn = purple_certificate_get_subject_name(crt);
2172 2213
2191 "Fingerprint (SHA1): %s\n\n" 2232 "Fingerprint (SHA1): %s\n\n"
2192 "Activation date: %s\n" 2233 "Activation date: %s\n"
2193 "Expiration date: %s\n"), 2234 "Expiration date: %s\n"),
2194 cn ? cn : "(null)", 2235 cn ? cn : "(null)",
2195 self_signed ? _("(self-signed)") : (issuer_id ? issuer_id : "(null)"), 2236 self_signed ? _("(self-signed)") : (issuer_id ? issuer_id : "(null)"),
2196 sha_asc ? sha_asc : "(null)", 2237 sha1_asc ? sha1_asc : "(null)",
2197 activ_str ? activ_str : "(null)", 2238 activ_str ? activ_str : "(null)",
2198 expir_str ? expir_str : "(null)"); 2239 expir_str ? expir_str : "(null)");
2240
2241 /* TODO: make this part of the translatable string above */
2242 secondary_extra = g_strdup_printf("%sSHA256: %s", secondary, sha256_asc);
2199 2243
2200 /* Make a semi-pretty display */ 2244 /* Make a semi-pretty display */
2201 if (self_signed) { 2245 if (self_signed) {
2202 purple_notify_info(NULL, /* TODO: Find what the handle ought to be */ 2246 purple_notify_info(NULL, /* TODO: Find what the handle ought to be */
2203 _("Certificate Information"), 2247 _("Certificate Information"),
2204 "", 2248 "",
2205 secondary); 2249 secondary_extra);
2206 } else { 2250 } else {
2207 purple_request_action(NULL, /* TODO: Find what the handle ought to be */ 2251 purple_request_action(NULL, /* TODO: Find what the handle ought to be */
2208 _("Certificate Information"), _("Certificate Information"), 2252 _("Certificate Information"), _("Certificate Information"),
2209 secondary, 2, NULL, NULL, NULL, 2253 secondary_extra, 2, NULL, NULL, NULL,
2210 issuer_id, 2, 2254 issuer_id, 2,
2211 _("View Issuer Certificate"), PURPLE_CALLBACK(display_x509_issuer), 2255 _("View Issuer Certificate"), PURPLE_CALLBACK(display_x509_issuer),
2212 _("Close"), PURPLE_CALLBACK(g_free)); 2256 _("Close"), PURPLE_CALLBACK(g_free));
2213 2257
2214 /* purple_request_action has taken ownership of issuer_id */ 2258 /* purple_request_action has taken ownership of issuer_id */
2217 2261
2218 /* Cleanup */ 2262 /* Cleanup */
2219 g_free(cn); 2263 g_free(cn);
2220 g_free(issuer_id); 2264 g_free(issuer_id);
2221 g_free(secondary); 2265 g_free(secondary);
2222 g_free(sha_asc); 2266 g_free(secondary_extra);
2267 g_free(sha1_asc);
2268 g_free(sha256_asc);
2223 g_free(activ_str); 2269 g_free(activ_str);
2224 g_free(expir_str); 2270 g_free(expir_str);
2225 g_byte_array_free(sha_bin, TRUE);
2226 } 2271 }
2227 2272
2228 void purple_certificate_add_ca_search_path(const char *path) 2273 void purple_certificate_add_ca_search_path(const char *path)
2229 { 2274 {
2230 if (g_list_find_custom(x509_ca_paths, path, (GCompareFunc)strcmp)) 2275 if (g_list_find_custom(x509_ca_paths, path, (GCompareFunc)strcmp))

mercurial