pidgin: 8eed0a9a: Implement reading multiple certificates ...
nosnilmot at pidgin.im
nosnilmot at pidgin.im
Sat Mar 27 00:01:22 EDT 2010
-----------------------------------------------------------------
Revision: 8eed0a9af24ccfb18ff90b20d0d4fce2c3a4e4d4
Ancestor: 21968e25181ee86f5556544054046884f68fa3ce
Author: nosnilmot at pidgin.im
Date: 2010-03-27T03:55:09
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/8eed0a9af24ccfb18ff90b20d0d4fce2c3a4e4d4
Modified files:
ChangeLog.API libpurple/certificate.c
libpurple/certificate.h libpurple/plugins/ssl/ssl-gnutls.c
libpurple/plugins/ssl/ssl-nss.c
ChangeLog:
Implement reading multiple certificates from a single "bundle" of
certificates in one file. This is most helpful for systems where system
CA certs are installed as a bundle.
Please test, preferably after removing any cached certificates from
~/.purple/certificates/x509/tls_peers/
-------------- next part --------------
============================================================
--- ChangeLog.API 8dc578fe8807312fc203315088f6ce38dbb7e75a
+++ ChangeLog.API 5ad213e1c28066ca0f3c73006af4a703ea87b387
@@ -24,6 +24,9 @@ version 2.7.0 (??/??/????):
* sent-attention conversation signal
* got-attention conversation signal
* PurpleMood struct in status.h
+ * purple_certificates_import for importing multiple certificates from
+ a single file (and corresponding import_certificates member of
+ PurpleCertificateScheme struct)
Pidgin:
Added:
============================================================
--- libpurple/certificate.c 91514d3480129ea19c002057110eeb639e9bd8ac
+++ libpurple/certificate.c 5276d4a955fd0890b6446317e1aa79ff6065565c
@@ -377,6 +377,16 @@ purple_certificate_import(PurpleCertific
return (scheme->import_certificate)(filename);
}
+GSList *
+purple_certificates_import(PurpleCertificateScheme *scheme, const gchar *filename)
+{
+ g_return_val_if_fail(scheme, NULL);
+ g_return_val_if_fail(scheme->import_certificates, NULL);
+ g_return_val_if_fail(filename, NULL);
+
+ return (scheme->import_certificates)(filename);
+}
+
gboolean
purple_certificate_export(const gchar *filename, PurpleCertificate *crt)
{
@@ -800,8 +810,9 @@ x509_ca_lazy_init(void)
PurpleCertificateScheme *x509;
GDir *certdir;
const gchar *entry;
- GPatternSpec *pempat;
+ GPatternSpec *pempat, *crtpat;
GList *iter = NULL;
+ GSList *crts = NULL;
if (x509_ca_initialized) return TRUE;
@@ -817,6 +828,7 @@ x509_ca_lazy_init(void)
/* Use a glob to only read .pem files */
pempat = g_pattern_spec_new("*.pem");
+ crtpat = g_pattern_spec_new("*.crt");
/* Populate the certificates pool from the search path(s) */
for (iter = x509_ca_paths; iter; iter = iter->next) {
@@ -830,32 +842,39 @@ x509_ca_lazy_init(void)
gchar *fullpath;
PurpleCertificate *crt;
- if ( !g_pattern_match_string(pempat, entry) ) {
+ if (!g_pattern_match_string(pempat, entry) && !g_pattern_match_string(crtpat, entry)) {
continue;
}
fullpath = g_build_filename(iter->data, entry, NULL);
/* TODO: Respond to a failure in the following? */
- crt = purple_certificate_import(x509, fullpath);
+ crts = purple_certificates_import(x509, fullpath);
- if (x509_ca_quiet_put_cert(crt)) {
- purple_debug_info("certificate/x509/ca",
- "Loaded %s\n",
- fullpath);
- } else {
- purple_debug_error("certificate/x509/ca",
- "Failed to load %s\n",
- fullpath);
+ while (crts && crts->data) {
+ crt = crts->data;
+ if (x509_ca_quiet_put_cert(crt)) {
+ gchar *name;
+ name = purple_certificate_get_subject_name(crt);
+ purple_debug_info("certificate/x509/ca",
+ "Loaded %s from %s\n",
+ name ? name : "(unknown)", fullpath);
+ } else {
+ purple_debug_error("certificate/x509/ca",
+ "Failed to load certificate from %s\n",
+ fullpath);
+ }
+ purple_certificate_destroy(crt);
+ crts = g_slist_delete_link(crts, crts);
}
- purple_certificate_destroy(crt);
g_free(fullpath);
}
g_dir_close(certdir);
}
g_pattern_spec_free(pempat);
+ g_pattern_spec_free(crtpat);
purple_debug_info("certificate/x509/ca",
"Lazy init completed.\n");
============================================================
--- libpurple/certificate.h 15d1462698743a031b64c8230aabcd5ea5ab2191
+++ libpurple/certificate.h ce6122d62967a91f101c7d06ec0febe9910abfee
@@ -250,10 +250,17 @@ struct _PurpleCertificateScheme
/** Retrieve the certificate activation/expiration times */
gboolean (* get_times)(PurpleCertificate *crt, time_t *activation, time_t *expiration);
+ /** Imports certificates from a file
+ *
+ * @param filename File to import the certificates from
+ * @return GSList of pointers to the newly allocated Certificate structs
+ * or NULL on failure.
+ */
+ GSList * (* import_certificates)(const gchar * filename);
+
void (*_purple_reserved1)(void);
void (*_purple_reserved2)(void);
void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
};
/** A set of operations used to provide logic for verifying a Certificate's
@@ -492,6 +499,16 @@ purple_certificate_import(PurpleCertific
purple_certificate_import(PurpleCertificateScheme *scheme, const gchar *filename);
/**
+ * Imports a list of PurpleCertificates from a file
+ *
+ * @param scheme Scheme to import under
+ * @param filename File path to import from
+ * @return Pointer to a GSList of new PurpleCertificates, or NULL on failure
+ */
+GSList *
+purple_certificates_import(PurpleCertificateScheme *scheme, const gchar *filename);
+
+/**
* Exports a PurpleCertificate to a file
*
* @param filename File to export the certificate to
============================================================
--- libpurple/plugins/ssl/ssl-gnutls.c 51dadf178a49905cb0b75e909a7dade86894107a
+++ libpurple/plugins/ssl/ssl-gnutls.c 1526683b3f6f214b78c819b849f80cab5ac2a5c1
@@ -548,6 +548,55 @@ x509_import_from_file(const gchar * file
return crt;
}
+/** Imports a number of PEM-formatted X.509 certificates from the specified file.
+ * @param filename Filename to import from. Format is PEM
+ *
+ * @return A newly allocated GSList of Certificate structures of the x509_gnutls scheme
+ */
+static GSList *
+x509_importcerts_from_file(const gchar * filename)
+{
+ PurpleCertificate *crt; /* Certificate being constructed */
+ gchar *buf; /* Used to load the raw file data */
+ gchar *begin, *end;
+ GSList *crts = NULL;
+ gsize buf_sz; /* Size of the above */
+ gnutls_datum dt; /* Struct to pass down to GnuTLS */
+
+ purple_debug_info("gnutls",
+ "Attempting to load X.509 certificates from %s\n",
+ filename);
+
+ /* Next, we'll simply yank the entire contents of the file
+ into memory */
+ /* TODO: Should I worry about very large files here? */
+ g_return_val_if_fail(
+ g_file_get_contents(filename,
+ &buf,
+ &buf_sz,
+ NULL /* No error checking for now */
+ ),
+ NULL);
+
+ begin = buf;
+ while((end = strstr(begin, "-----END CERTIFICATE-----")) != NULL) {
+ end += sizeof("-----END CERTIFICATE-----")-1;
+ /* Load the datum struct */
+ dt.data = (unsigned char *) begin;
+ dt.size = (end-begin);
+
+ /* Perform the conversion; files should be in PEM format */
+ crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM);
+ crts = g_slist_prepend(crts, crt);
+ begin = end;
+ }
+
+ /* Cleanup */
+ g_free(buf);
+
+ return crts;
+}
+
/**
* Exports a PEM-formatted X.509 certificate to the specified file.
* @param filename Filename to export to. Format will be PEM
@@ -964,10 +1013,10 @@ static PurpleCertificateScheme x509_gnut
x509_common_name, /* Subject name */
x509_check_name, /* Check subject name */
x509_times, /* Activation/Expiration time */
+ x509_importcerts_from_file, /* Multiple certificates import function */
NULL,
NULL,
- NULL,
NULL
};
============================================================
--- libpurple/plugins/ssl/ssl-nss.c 02eb54c44d77b4f743640b43f6876433756673ae
+++ libpurple/plugins/ssl/ssl-nss.c 39de6b0dda68930e4b5b0f7b01f03933cf1c49ad
@@ -530,7 +530,7 @@ static PurpleCertificateScheme x509_nss;
/** Imports a PEM-formatted X.509 certificate from the specified file.
* @param filename Filename to import from. Format is PEM
*
- * @return A newly allocated Certificate structure of the x509_gnutls scheme
+ * @return A newly allocated Certificate structure of the x509_nss scheme
*/
static PurpleCertificate *
x509_import_from_file(const gchar *filename)
@@ -575,6 +575,60 @@ x509_import_from_file(const gchar *filen
return crt;
}
+/** Imports a number of PEM-formatted X.509 certificates from the specified file.
+ * @param filename Filename to import from. Format is PEM
+ *
+ * @return A GSList of newly allocated Certificate structures of the x509_nss scheme
+ */
+static GSList *
+x509_importcerts_from_file(const gchar *filename)
+{
+ gchar *rawcert, *begin, *end;
+ gsize len = 0;
+ GSList *crts = NULL;
+ CERTCertificate *crt_dat;
+ PurpleCertificate *crt;
+
+ g_return_val_if_fail(filename != NULL, NULL);
+
+ purple_debug_info("nss/x509",
+ "Loading certificate from %s\n",
+ filename);
+
+ /* Load the raw data up */
+ if (!g_file_get_contents(filename,
+ &rawcert, &len,
+ NULL)) {
+ purple_debug_error("nss/x509", "Unable to read certificate file.\n");
+ return NULL;
+ }
+
+ if (len == 0) {
+ purple_debug_error("nss/x509",
+ "Certificate file has no contents!\n");
+ if (rawcert)
+ g_free(rawcert);
+ return NULL;
+ }
+
+ begin = rawcert;
+ while((end = strstr(begin, "-----END CERTIFICATE-----")) != NULL) {
+ end += sizeof("-----END CERTIFICATE-----")-1;
+ /* Decode the certificate */
+ crt_dat = CERT_DecodeCertFromPackage(begin, (end-begin));
+
+ g_return_val_if_fail(crt_dat != NULL, NULL);
+
+ crt = g_new0(PurpleCertificate, 1);
+ crt->scheme = &x509_nss;
+ crt->data = crt_dat;
+ crts = g_slist_prepend(crts, crt);
+ begin = end;
+ }
+ g_free(rawcert);
+
+ return crts;
+}
/**
* Exports a PEM-formatted X.509 certificate to the specified file.
* @param filename Filename to export to. Format will be PEM
@@ -874,10 +928,10 @@ static PurpleCertificateScheme x509_nss
x509_common_name, /* Subject name */
x509_check_name, /* Check subject name */
x509_times, /* Activation/Expiration time */
+ x509_importcerts_from_file, /* Multiple certificate import function */
NULL,
NULL,
- NULL,
NULL
};
More information about the Commits
mailing list