]> git.0d.be Git - empathy.git/commitdiff
Add a method to store the CA certificate
authorCosimo Cecchi <cosimoc@gnome.org>
Fri, 13 Aug 2010 14:14:09 +0000 (16:14 +0200)
committerCosimo Cecchi <cosimoc@gnome.org>
Fri, 13 Aug 2010 14:22:25 +0000 (16:22 +0200)
libempathy/empathy-tls-certificate.c
libempathy/empathy-tls-certificate.h

index a9e323cc04f31c29039addbb6a71831bc1f1509f..a6ee3b966c3e229081fc60b99719e85a53f543c3 100644 (file)
 
 #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);
+}
index c79c26abd8e4799b57073560bea2a656833d7da2..4bf5c188a8ab304bc2b6472fbe3c8ec2852b9113 100644 (file)
@@ -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__*/