diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2010-08-13 22:14:09 +0800 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2010-08-13 22:22:25 +0800 |
commit | dd57dd21018ac62e2cc89f5aa5e24d682d4c9886 (patch) | |
tree | 8550f81452eebbfd36fb6b2f8f44fe76d46e2f45 | |
parent | c61bb1765e65369933a571b6dccb07ec338cb515 (diff) | |
download | gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.tar gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.tar.gz gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.tar.bz2 gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.tar.lz gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.tar.xz gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.tar.zst gsoc2013-empathy-dd57dd21018ac62e2cc89f5aa5e24d682d4c9886.zip |
Add a method to store the CA certificate
-rw-r--r-- | libempathy/empathy-tls-certificate.c | 119 | ||||
-rw-r--r-- | libempathy/empathy-tls-certificate.h | 2 |
2 files changed, 121 insertions, 0 deletions
diff --git a/libempathy/empathy-tls-certificate.c b/libempathy/empathy-tls-certificate.c index a9e323cc0..a6ee3b966 100644 --- a/libempathy/empathy-tls-certificate.c +++ b/libempathy/empathy-tls-certificate.c @@ -22,6 +22,13 @@ #include "empathy-tls-certificate.h" +#include <errno.h> + +#include <glib/gstdio.h> + +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> + #include <telepathy-glib/proxy-subclass.h> #define DEBUG_FLAG EMPATHY_DEBUG_TLS @@ -436,3 +443,115 @@ empathy_tls_certificate_reject (EmpathyTLSCertificate *self, g_hash_table_unref (details); } + +static gsize +get_exported_size (gnutls_x509_crt_t cert) +{ + gsize retval; + guchar fake; + + /* fake an export so we get the size to allocate */ + gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, + &fake, &retval); + + DEBUG ("Should allocate %lu bytes", (gulong) retval); + + return retval; +} + +void +empathy_tls_certificate_store_ca (EmpathyTLSCertificate *self) +{ + GArray *last_cert; + gnutls_x509_crt_t cert; + gnutls_datum_t datum = { NULL, 0 }; + gsize exported_len; + guchar *exported_cert = NULL; + gint res; + gchar *user_certs_dir = NULL, *filename = NULL, *path = NULL; + GError *error = NULL; + EmpathyTLSCertificatePriv *priv = GET_PRIV (self); + + last_cert = g_ptr_array_index (priv->cert_data, priv->cert_data->len - 1); + datum.data = (guchar *) last_cert->data; + datum.size = last_cert->len; + + gnutls_x509_crt_init (&cert); + gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER); + + /* make sure it's self-signed, otherwise it's not a CA */ + if (gnutls_x509_crt_check_issuer (cert, cert) <= 0) + { + DEBUG ("Can't import the CA, as it's not self-signed"); + gnutls_x509_crt_deinit (cert); + + return; + } + + if (gnutls_x509_crt_get_ca_status (cert, NULL) <= 0) + { + DEBUG ("Can't import the CA, it's not a valid CA certificate"); + gnutls_x509_crt_deinit (cert); + + goto out; + } + + exported_len = get_exported_size (cert); + exported_cert = g_malloc (sizeof (guchar) * exported_len); + + res = gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, + exported_cert, &exported_len); + + if (res < 0) + { + DEBUG ("Failed to export the CA certificate; GnuTLS returned %d", res); + gnutls_x509_crt_deinit (cert); + + goto out; + } + + gnutls_x509_crt_deinit (cert); + + /* write the file */ + user_certs_dir = g_build_filename (g_get_user_config_dir (), + "telepathy", "certs", NULL); + + res = g_mkdir_with_parents (user_certs_dir, S_IRWXU | S_IRWXG); + + if (res < 0) + { + DEBUG ("Failed to create the user certificate directory: %s", + g_strerror (errno)); + + goto out; + } + + do + { + g_free (path); + + filename = g_strdup_printf ("cert-%p", cert); + path = g_build_filename (user_certs_dir, filename, NULL); + + g_free (filename); + } + while (g_file_test (path, G_FILE_TEST_EXISTS)); + + DEBUG ("Will save to %s", path); + + g_file_set_contents (path, (const gchar *) exported_cert, exported_len, + &error); + + if (error != NULL) + { + DEBUG ("Can't save the CA certificate to %s: %s", + path, error->message); + + g_error_free (error); + } + + out: + g_free (path); + g_free (exported_cert); + g_free (user_certs_dir); +} diff --git a/libempathy/empathy-tls-certificate.h b/libempathy/empathy-tls-certificate.h index c79c26abd..4bf5c188a 100644 --- a/libempathy/empathy-tls-certificate.h +++ b/libempathy/empathy-tls-certificate.h @@ -71,6 +71,8 @@ void empathy_tls_certificate_reject (EmpathyTLSCertificate *self, EmpTLSCertificateRejectReason reason, gboolean user_requested); +void empathy_tls_certificate_store_ca (EmpathyTLSCertificate *self); + G_END_DECLS #endif /* #ifndef __EMPATHY_TLS_CERTIFICATE_H__*/ |