| 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, |
| 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 */ |