# HG changeset patch # User William Ehlhardt # Date 1189657939 0 # Node ID c9f994a88f5f4cf1179f603a81ff0337bb1d3b0a # Parent e73e510d56ec634818545e26d9563c854b6d8578# Parent 401d1182d1dc3fa486be48529aee0e57fd044fd3 merge of '5d4b00a88466bb9e851eaca42ab3fd3f2c4093ef' and 'e2bf4d2bd2deeff5ae939ecc159eb07697dc61c0' diff -r e73e510d56ec -r c9f994a88f5f libpurple/plugins/ssl/ssl-nss.c --- a/libpurple/plugins/ssl/ssl-nss.c Thu Sep 13 03:02:34 2007 +0000 +++ b/libpurple/plugins/ssl/ssl-nss.c Thu Sep 13 04:32:19 2007 +0000 @@ -24,6 +24,7 @@ #include "certificate.h" #include "plugin.h" #include "sslconn.h" +#include "util.h" #include "version.h" #define SSL_NSS_PLUGIN_ID "ssl-nss" @@ -34,6 +35,7 @@ #include #include +#include #include #include #include @@ -454,11 +456,48 @@ * * @return TRUE if success, otherwise FALSE */ +/* This function should not be so complicated, but NSS doesn't seem to have a + "convert yon certificate to PEM format" function. */ static gboolean x509_export_certificate(const gchar *filename, PurpleCertificate *crt) { - /* TODO: WRITEME */ - return FALSE; + CERTCertificate *crt_dat; + SECItem *dercrt; + gchar *b64crt; + gchar *pemcrt; + gboolean ret = FALSE; + + g_return_val_if_fail(filename, FALSE); + g_return_val_if_fail(crt, FALSE); + g_return_val_if_fail(crt->scheme == &x509_nss, FALSE); + + crt_dat = X509_NSS_DATA(crt); + g_return_val_if_fail(crt_dat, FALSE); + + purple_debug_info("nss/x509", + "Exporting certificate to %s\n", filename); + + /* First, use NSS voodoo to create a DER-formatted certificate */ + dercrt = SEC_ASN1EncodeItem(NULL, NULL, crt_dat, + SEC_ASN1_GET(SEC_SignedCertificateTemplate)); + g_return_val_if_fail(dercrt != NULL, FALSE); + + /* Now encode it to b64 */ + b64crt = NSSBase64_EncodeItem(NULL, NULL, 0, dercrt); + SECITEM_FreeItem(dercrt, PR_TRUE); + g_return_val_if_fail(b64crt, FALSE); + + /* Wrap it in nice PEM header things */ + pemcrt = g_strdup_printf("-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n", b64crt); + PORT_Free(b64crt); /* Notice that b64crt was allocated by an NSS + function; hence, we'll let NSPR free it. */ + + /* Finally, dump the silly thing to a file. */ + ret = purple_util_write_data_to_file_absolute(filename, pemcrt, -1); + + g_free(pemcrt); + + return ret; } static PurpleCertificate * @@ -509,7 +548,6 @@ g_free(crt); } -#if 0 /** Determines whether one certificate has been issued and signed by another * * @param crt Certificate to check the signature of @@ -519,12 +557,11 @@ * @TODO Modify this function to return a reason for invalidity? */ static gboolean -x509_certificate_signed_by(PurpleCertificate * crt, - PurpleCertificate * issuer) +x509_signed_by(PurpleCertificate * crt, + PurpleCertificate * issuer) { - return FALSE; + return TRUE; } -#endif static GByteArray * x509_sha1sum(PurpleCertificate *crt) @@ -564,6 +601,34 @@ } static gchar * +x509_dn (PurpleCertificate *crt) +{ + CERTCertificate *crt_dat; + + g_return_val_if_fail(crt, NULL); + g_return_val_if_fail(crt->scheme == &x509_nss, NULL); + + crt_dat = X509_NSS_DATA(crt); + g_return_val_if_fail(crt_dat, NULL); + + return g_strdup(crt_dat->subjectName); +} + +static gchar * +x509_issuer_dn (PurpleCertificate *crt) +{ + CERTCertificate *crt_dat; + + g_return_val_if_fail(crt, NULL); + g_return_val_if_fail(crt->scheme == &x509_nss, NULL); + + crt_dat = X509_NSS_DATA(crt); + g_return_val_if_fail(crt_dat, NULL); + + return g_strdup(crt_dat->subjectName); +} + +static gchar * x509_common_name (PurpleCertificate *crt) { CERTCertificate *crt_dat; @@ -642,11 +707,14 @@ &nss_activ, &nss_expir), FALSE); + /* NSS's native PRTime type *almost* corresponds to time_t; however, + it measures *microseconds* since the epoch, not seconds. Hence + the funny conversion. */ if (activation) { - *activation = nss_activ; + *activation = nss_activ / 1000000; } if (expiration) { - *expiration = nss_expir; + *expiration = nss_expir / 1000000; } return TRUE; @@ -659,10 +727,10 @@ x509_export_certificate, /* Certificate export function */ x509_copy_certificate, /* Copy */ x509_destroy_certificate, /* Destroy cert */ - NULL, /* Signed-by */ + x509_signed_by, /* Signed-by */ x509_sha1sum, /* SHA1 fingerprint */ - NULL, /* Unique ID */ - NULL, /* Issuer Unique ID */ + x509_dn, /* Unique ID */ + x509_issuer_dn, /* Issuer Unique ID */ x509_common_name, /* Subject name */ x509_check_name, /* Check subject name */ x509_times, /* Activation/Expiration time */ diff -r e73e510d56ec -r c9f994a88f5f pidgin/gtkcertmgr.c --- a/pidgin/gtkcertmgr.c Thu Sep 13 03:02:34 2007 +0000 +++ b/pidgin/gtkcertmgr.c Thu Sep 13 04:32:19 2007 +0000 @@ -312,10 +312,6 @@ GtkTreeModel *model; gchar *id; PurpleCertificate *crt; - gchar *subject; - GByteArray *fpr_sha1; - gchar *fpr_sha1_asc; - gchar *primary, *secondary; /* See if things are selected */ if (!gtk_tree_selection_get_selected(select, &model, &iter)) { @@ -331,25 +327,9 @@ crt = purple_certificate_pool_retrieve(tpm_dat->tls_peers, id); g_return_if_fail(crt); - /* Build a notification thing */ - /* TODO: This needs a better GUI, but a notification will do for now */ - primary = g_strdup_printf(_("Certificate for %s"), id); - - fpr_sha1 = purple_certificate_get_fingerprint_sha1(crt); - fpr_sha1_asc = purple_base16_encode_chunked(fpr_sha1->data, - fpr_sha1->len); - subject = purple_certificate_get_subject_name(crt); - - secondary = g_strdup_printf(_("Common name: %s\n\nSHA1 fingerprint:\n%s"), subject, fpr_sha1_asc); + /* Fire the notification */ + purple_certificate_display_x509(crt); - purple_notify_info(tpm_dat, - _("SSL Host Certificate"), primary, secondary ); - - g_free(primary); - g_free(secondary); - g_byte_array_free(fpr_sha1, TRUE); - g_free(fpr_sha1_asc); - g_free(subject); g_free(id); purple_certificate_destroy(crt); }