gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r33592 - in gnunet-gtk: . src/namestore


From: gnunet
Subject: [GNUnet-SVN] r33592 - in gnunet-gtk: . src/namestore
Date: Sat, 7 Jun 2014 22:03:28 +0200

Author: grothoff
Date: 2014-06-07 22:03:27 +0200 (Sat, 07 Jun 2014)
New Revision: 33592

Modified:
   gnunet-gtk/configure.ac
   gnunet-gtk/src/namestore/plugin_gtk_namestore_tlsa.c
Log:
fixing #2526

Modified: gnunet-gtk/configure.ac
===================================================================
--- gnunet-gtk/configure.ac     2014-06-07 18:37:09 UTC (rev 33591)
+++ gnunet-gtk/configure.ac     2014-06-07 20:03:27 UTC (rev 33592)
@@ -351,7 +351,7 @@
       yes)
         AC_CHECK_HEADERS([gnutls/abstract.h],
             AC_CHECK_LIB([gnutls], [gnutls_pubkey_import],
-            gnutls=true))
+            gnutls=1))
         ;;
       *)
         LDFLAGS="-L$with_gnutls/lib $LDFLAGS"
@@ -359,16 +359,16 @@
         AC_CHECK_HEADERS([gnutls/abstract.h],
             AC_CHECK_LIB([gnutls], [gnutls_pubkey_import],
               EXT_LIB_PATH="-L$with_gnutls/lib $EXT_LIB_PATH"
-              gnutls=true))
+              gnutls=1))
         ;;
     esac
    ],
    [AC_MSG_RESULT([--with-gnutls not specified])
     AC_CHECK_HEADERS([gnutls/abstract.h],
         AC_CHECK_LIB([gnutls], [gnutls_pubkey_import],
-          gnutls=true))
+          gnutls=1))
    ])
-AM_CONDITIONAL(HAVE_GNUTLS, test x$gnutls = xtrue)
+AM_CONDITIONAL(HAVE_GNUTLS, test x$gnutls = x1)
 AC_DEFINE_UNQUOTED([HAVE_GNUTLS], $gnutls, [We have GnuTLS])
 
 

Modified: gnunet-gtk/src/namestore/plugin_gtk_namestore_tlsa.c
===================================================================
--- gnunet-gtk/src/namestore/plugin_gtk_namestore_tlsa.c        2014-06-07 
18:37:09 UTC (rev 33591)
+++ gnunet-gtk/src/namestore/plugin_gtk_namestore_tlsa.c        2014-06-07 
20:03:27 UTC (rev 33592)
@@ -32,8 +32,8 @@
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
 #include <gnutls/abstract.h>
+#include <gnunet/gnunet_resolver_service.h>
 
-
 /**
  * The user has edited the target value.  Enable/disable 'save'
  * button depending on the validity of the value.
@@ -352,7 +352,7 @@
  */
 static gchar *
 tlsa_store (void *cls,
-           GtkBuilder *builder)
+            GtkBuilder *builder)
 {
   unsigned int protocol;
   GtkComboBox *cb;
@@ -470,6 +470,8 @@
                                     &ti_start,
                                     &ti_end,
                                     FALSE);
+  if (0 == strlen (value))
+    return GNUNET_SYSERR;
   {
     size_t slen = strlen (value);
     uint8_t bin[slen / 2];
@@ -565,6 +567,335 @@
 
 
 /**
+ * We have successfully established a TLS session to
+ * import a certificate from the server.  Import the
+ * X509 certificate into the GUI.
+ *
+ * @param session TLS session to import from
+ * @param builder GTK builder to update GUI
+ */
+static void
+import_x509_certificate (gnutls_session_t session,
+                         GtkBuilder *builder)
+{
+  const gnutls_datum_t *cert_list;
+  unsigned int cert_list_size = 0;
+  gnutls_x509_crt_t cert;
+  unsigned int matching_type;
+  unsigned int selector;
+  gnutls_pubkey_t pk;
+  char buf[4092];
+  size_t bsize;
+  char *hex;
+  gnutls_datum_t datum;
+  uint8_t sha256[256/8];
+  uint8_t sha512[512/8];
+  size_t ssize;
+  GtkTextBuffer *tb;
+
+  cert_list = gnutls_certificate_get_peers (session,
+                                            &cert_list_size);
+  if (0 == cert_list_size)
+  {
+    /* is it possible to succeed with TLS handshake and have
+       NO certificates!? If so, how do we get the public key?*/
+    GNUNET_break (0);
+    return;
+  }
+  /* we only import the first certificate. */
+  gnutls_x509_crt_init (&cert);
+  if (GNUTLS_E_SUCCESS !=
+      gnutls_x509_crt_import (cert,
+                              &cert_list[0],
+                              GNUTLS_X509_FMT_DER))
+  {
+    GNUNET_break (0);
+    gnutls_x509_crt_deinit (cert);
+    return;
+  }
+  selector = get_selected_radio_value (builder,
+                                       selector_buttons);
+  switch (selector)
+  {
+  case 0: /* full cert */
+    bsize = sizeof (buf);
+    if (GNUTLS_E_SUCCESS !=
+        gnutls_x509_crt_export (cert,
+                                GNUTLS_X509_FMT_DER,
+                                buf,
+                                &bsize))
+    {
+      GNUNET_break (0);
+      gnutls_x509_crt_deinit (cert);
+      return;
+    }
+    break;
+  case 1: /* subject public key only */
+    if (GNUTLS_E_SUCCESS !=
+        gnutls_pubkey_init (&pk))
+    {
+      GNUNET_break (0);
+      gnutls_x509_crt_deinit (cert);
+      return;
+    }
+    if (GNUTLS_E_SUCCESS !=
+        gnutls_pubkey_import_x509 (pk,
+                                   cert,
+                                   0))
+    {
+      GNUNET_break (0);
+      gnutls_x509_crt_deinit (cert);
+      gnutls_pubkey_deinit (pk);
+      return;
+    }
+    bsize = sizeof (buf);
+    if (GNUTLS_E_SUCCESS !=
+        gnutls_pubkey_export (pk,
+                              GNUTLS_X509_FMT_DER,
+                              buf,
+                              &bsize))
+    {
+      GNUNET_break (0);
+      gnutls_x509_crt_deinit (cert);
+      gnutls_pubkey_deinit (pk);
+      return;
+    }
+    gnutls_pubkey_deinit (pk);
+    break;
+  default:
+    GNUNET_break (0);
+    gnutls_x509_crt_deinit (cert);
+    return;
+  }
+  gnutls_x509_crt_deinit (cert);
+  /* 'buf' now contains 'bsize' bytes of the binary data to
+     hash or store in the TLSA record; hash depending on
+     user preferences. */
+  matching_type = get_selected_radio_value (builder,
+                                            matching_type_buttons);
+  switch (matching_type)
+  {
+  case 0: /* exact match */
+    hex = GNUNET_DNSPARSER_bin_to_hex (buf,
+                                       bsize);
+    break;
+  case 1: /* SHA-256 hash */
+    datum.size = bsize;
+    datum.data = (void *) buf;
+    ssize = sizeof (sha256);
+    GNUNET_assert (GNUTLS_E_SUCCESS ==
+                   gnutls_fingerprint (GNUTLS_MAC_SHA256,
+                                       &datum,
+                                       sha256,
+                                       &ssize));
+    hex = GNUNET_DNSPARSER_bin_to_hex (sha256,
+                                       sizeof (sha256));
+    break;
+  case 2: /* SHA-512 hash */
+    datum.size = bsize;
+    datum.data = (void *) buf;
+    ssize = sizeof (sha512);
+    GNUNET_assert (GNUTLS_E_SUCCESS ==
+                   gnutls_fingerprint (GNUTLS_MAC_SHA512,
+                                       &datum,
+                                       sha512,
+                                       &ssize));
+    hex = GNUNET_DNSPARSER_bin_to_hex (sha512,
+                                       sizeof (sha512));
+    break;
+  default:
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Finally store 'hex' to the text buffer */
+  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW
+                                 (gtk_builder_get_object (builder,
+                                                          
"edit_dialog_tlsa_value_textview")));
+  gtk_text_buffer_set_text (tb,
+                            hex,
+                            -1);
+  GNUNET_free (hex);
+}
+
+
+/**
+ * Context for TLS certificate import from network.
+ */
+struct ImportContext
+{
+  /**
+   * The TLS session.
+   */
+  gnutls_session_t session;
+
+  /**
+   * Network handle for the session.
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * DNS resolution request to resolve the domain name.
+   */
+  struct GNUNET_RESOLVER_RequestHandle *rh;
+
+  /**
+   * Builder for accessing widgets.
+   */
+  GtkBuilder *builder;
+};
+
+
+/**
+ * We got an address from DNS, start TLS handshake.
+ *
+ * @param cls our `struct ImportContext`
+ * @param addr one of the addresses of the host, NULL for the last address
+ * @param addrlen length of @a addr
+ */
+static void
+import_address_cb (void *cls,
+                   const struct sockaddr *addr,
+                   socklen_t addrlen)
+{
+  struct ImportContext *ic = cls;
+  int pf;
+  int ret;
+  gnutls_certificate_credentials_t xcred;
+  struct sockaddr_in v4;
+  struct sockaddr_in6 v6;
+  struct sockaddr *a;
+  unsigned int port;
+  gnutls_certificate_type_t type;
+
+  if (NULL == addr)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Name resolution failed\n"));
+    GNUNET_free (ic);
+    return;
+  }
+  port = gtk_spin_button_get_value
+    (GTK_SPIN_BUTTON (gtk_builder_get_object (ic->builder,
+                                              "edit_dialog_port_spinbutton")));
+  switch (addr->sa_family)
+  {
+  case AF_INET:
+    pf = PF_INET;
+    memcpy (&v4, addr, addrlen);
+    v4.sin_port = htons ((uint16_t) port);
+    a = (struct sockaddr *) &v4;
+    break;
+  case AF_INET6:
+    pf = PF_INET6;
+    memcpy (&v6, addr, addrlen);
+    v6.sin6_port = htons ((uint16_t) port);
+    a = (struct sockaddr *) &v6;
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Unsupported address family %d\n"),
+                addr->sa_family);
+    return;
+  }
+  ic->sock = GNUNET_NETWORK_socket_create (pf,
+                                           SOCK_STREAM,
+                                           0);
+  if (NULL == ic->sock)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "socket");
+    return;
+  }
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_NETWORK_socket_set_blocking (ic->sock,
+                                                    GNUNET_YES));
+  if ( (GNUNET_OK !=
+        GNUNET_NETWORK_socket_connect (ic->sock,
+                                       a,
+                                       addrlen)) &&
+       (EINPROGRESS != errno) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Failed to connect to target address `%s': %s\n"),
+                GNUNET_a2s (addr, addrlen),
+                STRERROR (errno));
+    goto cleanup;
+  }
+
+  GNUNET_RESOLVER_request_cancel (ic->rh);
+
+  /* Use default priorities */
+  if (GNUTLS_E_SUCCESS !=
+      (ret = gnutls_priority_set_direct (ic->session,
+                                         "PERFORMANCE",
+                                         NULL)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to initialize cipher suite: %s\n"),
+                gnutls_strerror (ret));
+    goto cleanup;
+  }
+  /* put the x509 credentials to the current session */
+  gnutls_certificate_allocate_credentials (&xcred);
+  gnutls_credentials_set (ic->session,
+                          GNUTLS_CRD_CERTIFICATE,
+                          xcred);
+  gnutls_transport_set_int (ic->session,
+                            GNUNET_NETWORK_get_fd (ic->sock));
+  gnutls_handshake_set_timeout (ic->session,
+                                2000 /* 2s */);
+
+  /* TODO: do this in event loop, with insensitive GUI,
+     with possibly higher timeout ... */
+  /* Perform the TLS handshake */
+  do
+  {
+    ret = gnutls_handshake (ic->session);
+  }
+  while ( (ret < 0) && (0 == gnutls_error_is_fatal (ret)) );
+
+  /* finally, access the certificate */
+  if (GNUTLS_E_SUCCESS == ret)
+  {
+    type = gnutls_certificate_type_get (ic->session);
+    switch (type)
+    {
+    case GNUTLS_CRT_UNKNOWN:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Server certificate type not supported\n"));
+      break;
+    case GNUTLS_CRT_X509:
+      import_x509_certificate (ic->session,
+                               ic->builder);
+      break;
+    case GNUTLS_CRT_OPENPGP:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Server certificate type not supported\n"));
+      break;
+    case GNUTLS_CRT_RAW:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Server certificate type not supported\n"));
+      break;
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("TLS handshake failed: %s\n"),
+                gnutls_strerror (ret));
+  }
+  gnutls_bye (ic->session, GNUTLS_SHUT_RDWR);
+ cleanup:
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_NETWORK_socket_close (ic->sock));
+  gnutls_deinit (ic->session);
+  gnutls_certificate_free_credentials (xcred);
+  GNUNET_free (ic);
+}
+
+
+/**
  * The user clicked the "import" button.  Try to import
  * certificate from the server.
  *
@@ -576,27 +907,59 @@
                                gpointer user_data)
 {
   struct GNUNET_GTK_NAMESTORE_PluginEnvironment *edc = user_data;
+  struct ImportContext *ic;
+  const gchar *name;
+  GtkWidget *entry;
 
-  GNUNET_break (0); // FIXME: import not implemented
+  entry = GTK_WIDGET (gtk_builder_get_object (edc->builder,
+                                              
"edit_dialog_tlsa_import_entry"));
+  name = gtk_editable_get_chars (GTK_EDITABLE (entry),
+                                 0, -1);
+  if ( (NULL == name) ||
+       (0 == strlen (name)) ||
+       (GNUNET_OK != GNUNET_DNSPARSER_check_name (name)) )
+  {
+    /* import button should not have been sensitive */
+    GNUNET_break (0);
+    return;
+  }
+  ic = GNUNET_new (struct ImportContext);
+  ic->builder = edc->builder;
+  gnutls_init (&ic->session, GNUTLS_CLIENT);
+  gnutls_session_set_ptr (ic->session, ic);
+  gnutls_server_name_set (ic->session,
+                          GNUTLS_NAME_DNS,
+                          name,
+                          strlen (name));
+  gnutls_set_default_priority (ic->session);
+  ic->rh = GNUNET_RESOLVER_ip_get (name,
+                                   AF_UNSPEC,
+                                   GNUNET_TIME_UNIT_SECONDS,
+                                   &import_address_cb,
+                                   ic);
 }
 
 
 /**
  * The user has edited the hostname used for the import button.
  * Update the import button's sensitivity.
+ *
+ * @param entry edited entry
+ * @param user_data our plugin environment
  */
 static void
 edit_dialog_tlsa_import_entry_changed_cb (GtkEditable *entry,
                                           gpointer user_data)
 {
   struct GNUNET_GTK_NAMESTORE_PluginEnvironment *edc = user_data;
-  GtkWidget *button;
   const gchar *preedit;
   gboolean sens;
+  GtkWidget *button;
 
   button = GTK_WIDGET (gtk_builder_get_object (edc->builder,
-                                               "edit_dialog_tlsa_entry"));
-  preedit = gtk_editable_get_chars (entry, 0, -1);
+                                               
"edit_dialog_tlsa_import_button"));
+  preedit = gtk_editable_get_chars (GTK_EDITABLE (entry),
+                                    0, -1);
   if ( (NULL == preedit) ||
        (0 == strlen (preedit)) ||
        (GNUNET_OK != GNUNET_DNSPARSER_check_name (preedit)) )




reply via email to

[Prev in Thread] Current Thread [Next in Thread]