diff options
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | src/gns/Makefile.am | 3 | ||||
-rw-r--r-- | src/gns/gnunet-gns-proxy.c | 121 |
3 files changed, 122 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac index c68978d20..374f00cab 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1032,7 +1032,14 @@ AC_ARG_WITH(gnutls, | |||
1032 | AC_CHECK_LIB([gnutls], [gnutls_priority_set], | 1032 | AC_CHECK_LIB([gnutls], [gnutls_priority_set], |
1033 | gnutls=true))]) | 1033 | gnutls=true))]) |
1034 | AM_CONDITIONAL(HAVE_GNUTLS, test x$gnutls = xtrue) | 1034 | AM_CONDITIONAL(HAVE_GNUTLS, test x$gnutls = xtrue) |
1035 | AC_DEFINE_UNQUOTED([HAVE_GNUTLS], $gnutls, [We have gnutls]) | 1035 | AC_DEFINE_UNQUOTED([HAVE_GNUTLS], $gnutls, [We have GnuTLS]) |
1036 | |||
1037 | gnutls_dane=0 | ||
1038 | AC_CHECK_HEADERS([gnutls/dane.h], | ||
1039 | AC_CHECK_LIB([gnutls-dane], [dane_verify_crt_raw], | ||
1040 | gnutls_dane=true)) | ||
1041 | AM_CONDITIONAL(HAVE_GNUTLS_DANE, test x$gnutls_dane = xtrue) | ||
1042 | AC_DEFINE_UNQUOTED([HAVE_GNUTLS_DANE], $gnutls_dane, [We have GnuTLS with DANE support]) | ||
1036 | 1043 | ||
1037 | 1044 | ||
1038 | # Test if we are building for superMUC | 1045 | # Test if we are building for superMUC |
@@ -1470,7 +1477,12 @@ fi | |||
1470 | #gnutls | 1477 | #gnutls |
1471 | if test x$gnutls != xtrue | 1478 | if test x$gnutls != xtrue |
1472 | then | 1479 | then |
1473 | AC_MSG_NOTICE([NOTICE: gnutls not found, gnunet-gns-proxy will not be built]) | 1480 | AC_MSG_NOTICE([NOTICE: GnuTLS not found, gnunet-gns-proxy will not be built]) |
1481 | else | ||
1482 | if test x$gnutls_dane != xtrue | ||
1483 | then | ||
1484 | AC_MSG_NOTICE([NOTICE: GnuTLS has no DANE support, DANE validation will not be possible]) | ||
1485 | fi | ||
1474 | fi | 1486 | fi |
1475 | 1487 | ||
1476 | # java ports | 1488 | # java ports |
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index f36af6e64..d97a4b48c 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -124,6 +124,9 @@ gnunet_gns_proxy_LDADD = -lmicrohttpd -lcurl -lgnutls \ | |||
124 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 124 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
125 | $(top_builddir)/src/util/libgnunetutil.la \ | 125 | $(top_builddir)/src/util/libgnunetutil.la \ |
126 | $(GN_LIBINTL) | 126 | $(GN_LIBINTL) |
127 | if HAVE_GNUTLS_DANE | ||
128 | gnunet_gns_proxy_LDADD += -lgnutls-dane | ||
129 | endif | ||
127 | gnunet_gns_proxy_DEPENDENCIES = \ | 130 | gnunet_gns_proxy_DEPENDENCIES = \ |
128 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 131 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
129 | $(top_builddir)/src/util/libgnunetutil.la \ | 132 | $(top_builddir)/src/util/libgnunetutil.la \ |
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 4452e5e67..968470bd9 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c | |||
@@ -35,6 +35,9 @@ | |||
35 | #include <gnutls/x509.h> | 35 | #include <gnutls/x509.h> |
36 | #include <gnutls/abstract.h> | 36 | #include <gnutls/abstract.h> |
37 | #include <gnutls/crypto.h> | 37 | #include <gnutls/crypto.h> |
38 | #if HAVE_GNUTLS_DANE | ||
39 | #include <gnutls/dane.h> | ||
40 | #endif | ||
38 | #include <regex.h> | 41 | #include <regex.h> |
39 | #include "gnunet_util_lib.h" | 42 | #include "gnunet_util_lib.h" |
40 | #include "gnunet_gns_service.h" | 43 | #include "gnunet_gns_service.h" |
@@ -502,6 +505,11 @@ struct Socks5Request | |||
502 | char *leho; | 505 | char *leho; |
503 | 506 | ||
504 | /** | 507 | /** |
508 | * Payload of the (last) DANE record encountered. | ||
509 | */ | ||
510 | char *dane_data; | ||
511 | |||
512 | /** | ||
505 | * The URL to fetch | 513 | * The URL to fetch |
506 | */ | 514 | */ |
507 | char *url; | 515 | char *url; |
@@ -522,6 +530,11 @@ struct Socks5Request | |||
522 | unsigned int response_code; | 530 | unsigned int response_code; |
523 | 531 | ||
524 | /** | 532 | /** |
533 | * Number of bytes in @e dane_data. | ||
534 | */ | ||
535 | size_t dane_data_len; | ||
536 | |||
537 | /** | ||
525 | * Number of bytes already in read buffer | 538 | * Number of bytes already in read buffer |
526 | */ | 539 | */ |
527 | size_t rbuf_len; | 540 | size_t rbuf_len; |
@@ -725,6 +738,7 @@ cleanup_s5r (struct Socks5Request *s5r) | |||
725 | GNUNET_free_non_null (s5r->domain); | 738 | GNUNET_free_non_null (s5r->domain); |
726 | GNUNET_free_non_null (s5r->leho); | 739 | GNUNET_free_non_null (s5r->leho); |
727 | GNUNET_free_non_null (s5r->url); | 740 | GNUNET_free_non_null (s5r->url); |
741 | GNUNET_free_non_null (s5r->dane_data); | ||
728 | GNUNET_free (s5r); | 742 | GNUNET_free (s5r); |
729 | } | 743 | } |
730 | 744 | ||
@@ -809,7 +823,7 @@ check_ssl_certificate (struct Socks5Request *s5r) | |||
809 | } gptr; | 823 | } gptr; |
810 | char certdn[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 3]; | 824 | char certdn[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 3]; |
811 | size_t size; | 825 | size_t size; |
812 | gnutls_x509_crt x509_cert; | 826 | gnutls_x509_crt_t x509_cert; |
813 | int rc; | 827 | int rc; |
814 | const char *name; | 828 | const char *name; |
815 | 829 | ||
@@ -846,34 +860,101 @@ check_ssl_certificate (struct Socks5Request *s5r) | |||
846 | &size))) | 860 | &size))) |
847 | { | 861 | { |
848 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 862 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
849 | "Failed to fetch CN from cert: %s\n", | 863 | _("Failed to fetch CN from cert: %s\n"), |
850 | gnutls_strerror(rc)); | 864 | gnutls_strerror(rc)); |
851 | gnutls_x509_crt_deinit (x509_cert); | 865 | gnutls_x509_crt_deinit (x509_cert); |
852 | return GNUNET_SYSERR; | 866 | return GNUNET_SYSERR; |
853 | } | 867 | } |
854 | /* FIXME: here we should check for TLSA/DANE records */ | 868 | /* check for TLSA/DANE records */ |
855 | 869 | #if HAVE_GNUTLS_DANE | |
856 | name = s5r->domain; | 870 | if (NULL != s5r->dane_data) |
857 | if (NULL != s5r->leho) | ||
858 | name = s5r->leho; | ||
859 | if (NULL != name) | ||
860 | { | 871 | { |
861 | if (0 == (rc = gnutls_x509_crt_check_hostname (x509_cert, | 872 | char *dd[] = { s5r->dane_data, NULL }; |
862 | name))) | 873 | int dlen[] = { s5r->dane_data_len, 0}; |
874 | dane_state_t dane_state; | ||
875 | dane_query_t dane_query; | ||
876 | unsigned int verify; | ||
877 | |||
878 | /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */ | ||
879 | if (0 != (rc = dane_state_init (&dane_state, | ||
880 | DANE_F_IGNORE_LOCAL_RESOLVER))) | ||
881 | { | ||
882 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
883 | _("Failed to initialize DANE: %s\n"), | ||
884 | dane_strerror(rc)); | ||
885 | gnutls_x509_crt_deinit (x509_cert); | ||
886 | return GNUNET_SYSERR; | ||
887 | } | ||
888 | if (0 != (rc = dane_raw_tlsa (dane_state, | ||
889 | &dane_query, | ||
890 | dd, | ||
891 | dlen, | ||
892 | GNUNET_YES, | ||
893 | GNUNET_NO))) | ||
894 | { | ||
895 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
896 | _("Failed to parse DANE record: %s\n"), | ||
897 | dane_strerror(rc)); | ||
898 | dane_state_deinit (dane_state); | ||
899 | gnutls_x509_crt_deinit (x509_cert); | ||
900 | return GNUNET_SYSERR; | ||
901 | } | ||
902 | if (0 != (rc = dane_verify_crt_raw (dane_state, | ||
903 | chainp, | ||
904 | cert_list_size, | ||
905 | gnutls_certificate_type_get (tlsinfo.internals), | ||
906 | dane_query, | ||
907 | 0, 0, | ||
908 | &verify))) | ||
863 | { | 909 | { |
864 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 910 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
865 | _("SSL certificate subject name (%s) does not match `%s'\n"), | 911 | _("Failed to verify TLS connection using DANE: %s\n"), |
866 | certdn, | 912 | dane_strerror(rc)); |
867 | name); | 913 | dane_query_deinit (dane_query); |
914 | dane_state_deinit (dane_state); | ||
868 | gnutls_x509_crt_deinit (x509_cert); | 915 | gnutls_x509_crt_deinit (x509_cert); |
869 | return GNUNET_SYSERR; | 916 | return GNUNET_SYSERR; |
870 | } | 917 | } |
918 | if (0 != verify) | ||
919 | { | ||
920 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
921 | _("Failed DANE verification failed with GnuTLS verify status code: %u\n"), | ||
922 | verify); | ||
923 | dane_query_deinit (dane_query); | ||
924 | dane_state_deinit (dane_state); | ||
925 | gnutls_x509_crt_deinit (x509_cert); | ||
926 | return GNUNET_SYSERR; | ||
927 | } | ||
928 | dane_query_deinit (dane_query); | ||
929 | dane_state_deinit (dane_state); | ||
930 | /* success! */ | ||
871 | } | 931 | } |
872 | else | 932 | else |
933 | #endif | ||
873 | { | 934 | { |
874 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 935 | /* try LEHO or ordinary domain name X509 verification */ |
875 | _("No LEHO or domain name available and TLSA/DANE is not yet implemented!\n")); | 936 | name = s5r->domain; |
876 | return GNUNET_SYSERR; | 937 | if (NULL != s5r->leho) |
938 | name = s5r->leho; | ||
939 | if (NULL != name) | ||
940 | { | ||
941 | if (0 == (rc = gnutls_x509_crt_check_hostname (x509_cert, | ||
942 | name))) | ||
943 | { | ||
944 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
945 | _("SSL certificate subject name (%s) does not match `%s'\n"), | ||
946 | certdn, | ||
947 | name); | ||
948 | gnutls_x509_crt_deinit (x509_cert); | ||
949 | return GNUNET_SYSERR; | ||
950 | } | ||
951 | } | ||
952 | else | ||
953 | { | ||
954 | /* we did not even have the domain name!? */ | ||
955 | GNUNET_break (0); | ||
956 | return GNUNET_SYSERR; | ||
957 | } | ||
877 | } | 958 | } |
878 | gnutls_x509_crt_deinit (x509_cert); | 959 | gnutls_x509_crt_deinit (x509_cert); |
879 | #if 0 | 960 | #if 0 |
@@ -2355,6 +2436,14 @@ handle_gns_result (void *cls, | |||
2355 | s5r->leho = GNUNET_strndup (r->data, | 2436 | s5r->leho = GNUNET_strndup (r->data, |
2356 | r->data_size); | 2437 | r->data_size); |
2357 | break; | 2438 | break; |
2439 | case GNUNET_DNSPARSER_TYPE_TLSA: | ||
2440 | GNUNET_free_non_null (s5r->dane_data); | ||
2441 | s5r->dane_data_len = r->data_size; | ||
2442 | s5r->dane_data = GNUNET_malloc (r->data_size); | ||
2443 | memcpy (s5r->dane_data, | ||
2444 | r->data, | ||
2445 | r->data_size); | ||
2446 | break; | ||
2358 | default: | 2447 | default: |
2359 | /* don't care */ | 2448 | /* don't care */ |
2360 | break; | 2449 | break; |