[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)) )
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r33592 - in gnunet-gtk: . src/namestore,
gnunet <=