aboutsummaryrefslogtreecommitdiff
path: root/lib/libmicrohttpd/src
diff options
context:
space:
mode:
authordavilla <davilla@svn>2010-02-13 17:31:51 +0000
committerdavilla <davilla@svn>2010-02-13 17:31:51 +0000
commitfa8e3ef23bd203e98e3b3de423e8359c10167159 (patch)
tree7eb0513fb5ee6fa0f71726e49fdcaf1e0de59973 /lib/libmicrohttpd/src
parent7ab2873c972ab1cd95f9bd7f158fc5aeeb25e2dd (diff)
commit libmicrohttpd-0.4.5 into trunk
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@27720 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'lib/libmicrohttpd/src')
-rw-r--r--lib/libmicrohttpd/src/Makefile.am9
-rw-r--r--lib/libmicrohttpd/src/Makefile.in576
-rw-r--r--lib/libmicrohttpd/src/daemon/EXPORT.sym23
-rw-r--r--lib/libmicrohttpd/src/daemon/Makefile.am64
-rw-r--r--lib/libmicrohttpd/src/daemon/Makefile.in896
-rw-r--r--lib/libmicrohttpd/src/daemon/connection.c2230
-rw-r--r--lib/libmicrohttpd/src/daemon/connection.h66
-rw-r--r--lib/libmicrohttpd/src/daemon/connection_https.c309
-rw-r--r--lib/libmicrohttpd/src/daemon/connection_https.h35
-rw-r--r--lib/libmicrohttpd/src/daemon/daemon.c1971
-rw-r--r--lib/libmicrohttpd/src/daemon/daemon_test.c168
-rw-r--r--lib/libmicrohttpd/src/daemon/https/Makefile.am3
-rw-r--r--lib/libmicrohttpd/src/daemon/https/Makefile.in575
-rw-r--r--lib/libmicrohttpd/src/daemon/https/gnutls.h697
-rw-r--r--lib/libmicrohttpd/src/daemon/https/lgl/Makefile.am13
-rw-r--r--lib/libmicrohttpd/src/daemon/https/lgl/Makefile.in495
-rw-r--r--lib/libmicrohttpd/src/daemon/https/lgl/gc-libgcrypt.c407
-rw-r--r--lib/libmicrohttpd/src/daemon/https/lgl/gc.h172
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.am18
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.in506
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/README3
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/coding.c1211
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/decoding.c1673
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/element.c902
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/element.h14
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.c68
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.h5
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/int.h112
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/libtasn1.h216
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/mem.h25
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.c774
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.h37
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/structure.c585
-rw-r--r--lib/libmicrohttpd/src/daemon/https/minitasn1/structure.h18
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/Makefile.am100
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/Makefile.in635
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_cert.c1329
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_cert.h159
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.c327
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.h48
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_dhe.c274
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_rsa.c415
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/auth_rsa_export.c323
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/debug.c95
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/debug.h27
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/defines.h66
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.c246
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.h31
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.c198
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.h33
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.c223
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.h28
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_alert.c296
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.c1340
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.h148
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_asn1_tab.c63
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.c361
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.h51
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth_int.h33
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.c1111
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.h64
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.c441
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.h127
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.c499
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.h41
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.c109
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.h43
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.c999
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.h41
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.c82
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.h38
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.c162
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.h38
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh_primes.c214
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.c404
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.h71
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.c301
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.h47
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.c298
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.h54
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.c2804
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.h47
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.c448
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.h72
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_int.h642
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.c726
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.h40
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.c65
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.h61
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.c267
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.h55
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.c192
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.h49
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.c636
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.h40
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_priority.c242
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.c1087
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.h33
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.c63
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.h26
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.c476
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.h49
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.c804
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.h77
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.c157
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.h53
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.c199
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.h30
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_ui.c58
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.c604
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.h50
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/memmem.c78
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/pkix_asn1_tab.c1130
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/str-two-way.h429
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/x509_b64.c413
-rw-r--r--lib/libmicrohttpd/src/daemon/https/tls/x509_b64.h43
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/Makefile.am24
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/Makefile.in509
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/common.c447
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/common.h84
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/extensions.c218
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/extensions.h35
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/mpi.c212
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/mpi.h37
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/privkey.h32
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/x509.c364
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/x509.h409
-rw-r--r--lib/libmicrohttpd/src/daemon/https/x509/x509_privkey.c289
-rw-r--r--lib/libmicrohttpd/src/daemon/internal.c159
-rw-r--r--lib/libmicrohttpd/src/daemon/internal.h855
-rw-r--r--lib/libmicrohttpd/src/daemon/memorypool.c241
-rw-r--r--lib/libmicrohttpd/src/daemon/memorypool.h97
-rw-r--r--lib/libmicrohttpd/src/daemon/postprocessor.c1044
-rw-r--r--lib/libmicrohttpd/src/daemon/postprocessor_large_test.c105
-rw-r--r--lib/libmicrohttpd/src/daemon/postprocessor_test.c226
-rw-r--r--lib/libmicrohttpd/src/daemon/reason_phrase.c128
-rw-r--r--lib/libmicrohttpd/src/daemon/reason_phrase.h37
-rw-r--r--lib/libmicrohttpd/src/daemon/response.c303
-rw-r--r--lib/libmicrohttpd/src/daemon/response.h37
-rw-r--r--lib/libmicrohttpd/src/examples/Makefile.am70
-rw-r--r--lib/libmicrohttpd/src/examples/Makefile.in791
-rw-r--r--lib/libmicrohttpd/src/examples/authorization_example.c102
-rw-r--r--lib/libmicrohttpd/src/examples/fileserver_example.c106
-rw-r--r--lib/libmicrohttpd/src/examples/fileserver_example_dirs.c129
-rw-r--r--lib/libmicrohttpd/src/examples/fileserver_example_external_select.c136
-rw-r--r--lib/libmicrohttpd/src/examples/https_fileserver_example.c194
-rw-r--r--lib/libmicrohttpd/src/examples/minimal_example.c77
-rw-r--r--lib/libmicrohttpd/src/examples/minimal_example_comet.c85
-rw-r--r--lib/libmicrohttpd/src/examples/querystring_example.c84
-rw-r--r--lib/libmicrohttpd/src/examples/refuse_post_example.c99
-rw-r--r--lib/libmicrohttpd/src/include/Makefile.am4
-rw-r--r--lib/libmicrohttpd/src/include/Makefile.in625
-rw-r--r--lib/libmicrohttpd/src/include/microhttpd.h1312
-rw-r--r--lib/libmicrohttpd/src/include/platform.h115
-rw-r--r--lib/libmicrohttpd/src/include/plibc.h809
-rw-r--r--lib/libmicrohttpd/src/testcurl/Makefile.am181
-rw-r--r--lib/libmicrohttpd/src/testcurl/Makefile.in1147
-rw-r--r--lib/libmicrohttpd/src/testcurl/curl_version_check.c156
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemon_options_test.c127
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_get.c501
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_get_chunked.c405
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_iplimit.c301
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_large_put.c469
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_long_header.c241
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_parse_cookies.c249
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_post.c430
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_post_loop.c452
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_postform.c457
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_process_arguments.c238
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_process_headers.c428
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_put.c432
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_put_chunked.c440
-rw-r--r--lib/libmicrohttpd/src/testcurl/daemontest_termination.c114
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/Makefile.am132
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/Makefile.in986
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/cert.pem17
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/key.pem27
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/mhds_get_test.c136
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/mhds_multi_daemon_test.c226
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/mhds_session_info_test.c172
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_alert_test.c187
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_authentication_test.c237
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_cipher_change_test.c154
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_daemon_options_test.c182
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_extension_test.c276
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_multi_thread_mode_test.c178
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_session_time_out_test.c171
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_test_common.c424
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_test_common.h118
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_test_keys.h173
-rw-r--r--lib/libmicrohttpd/src/testcurl/https/tls_thread_mode_test.c172
-rw-r--r--lib/libmicrohttpd/src/testzzuf/Makefile.am105
-rw-r--r--lib/libmicrohttpd/src/testzzuf/Makefile.in943
-rw-r--r--lib/libmicrohttpd/src/testzzuf/README13
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_get.c313
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_get_chunked.c330
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_large_put.c381
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_long_header.c231
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_post.c372
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_postform.c387
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_put.c360
-rw-r--r--lib/libmicrohttpd/src/testzzuf/daemontest_put_chunked.c370
-rw-r--r--lib/libmicrohttpd/src/testzzuf/socat.c107
203 files changed, 64432 insertions, 0 deletions
diff --git a/lib/libmicrohttpd/src/Makefile.am b/lib/libmicrohttpd/src/Makefile.am
new file mode 100644
index 0000000000..4868557b19
--- /dev/null
+++ b/lib/libmicrohttpd/src/Makefile.am
@@ -0,0 +1,9 @@
+if HAVE_CURL
+curltests = testcurl
+if HAVE_ZZUF
+if HAVE_SOCAT
+zzuftests = testzzuf
+endif
+endif
+endif
+SUBDIRS = include daemon examples $(curltests) $(zzuftests) .
diff --git a/lib/libmicrohttpd/src/Makefile.in b/lib/libmicrohttpd/src/Makefile.in
new file mode 100644
index 0000000000..ac7d244307
--- /dev/null
+++ b/lib/libmicrohttpd/src/Makefile.in
@@ -0,0 +1,576 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = include daemon examples testcurl testzzuf .
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@HAVE_CURL_TRUE@curltests = testcurl
+@HAVE_CURL_TRUE@@HAVE_SOCAT_TRUE@@HAVE_ZZUF_TRUE@zzuftests = testzzuf
+SUBDIRS = include daemon examples $(curltests) $(zzuftests) .
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/EXPORT.sym b/lib/libmicrohttpd/src/daemon/EXPORT.sym
new file mode 100644
index 0000000000..b57c523384
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/EXPORT.sym
@@ -0,0 +1,23 @@
+MHD_start_daemon
+MHD_start_daemon_va
+MHD_stop_daemon
+MHD_get_fdset
+MHD_get_timeout
+MHD_run
+MHD_get_connection_values
+MHD_set_connection_value
+MHD_lookup_connection_value
+MHD_queue_response
+MHD_create_response_from_callback
+MHD_create_response_from_data
+MHD_destroy_response
+MHD_add_response_header
+MHD_del_response_header
+MHD_get_response_headers
+MHD_get_response_header
+MHD_create_post_processor
+MHD_post_process
+MHD_destroy_post_processor
+MHD_get_daemon_info
+MHD_get_connection_info
+MHD_set_panic_func
diff --git a/lib/libmicrohttpd/src/daemon/Makefile.am b/lib/libmicrohttpd/src/daemon/Makefile.am
new file mode 100644
index 0000000000..de5152f2cc
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/Makefile.am
@@ -0,0 +1,64 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/x509 \
+ -I$(top_srcdir)/src/daemon/https/minitasn1 \
+ -I$(top_srcdir)/src/daemon/https/tls \
+ -I$(top_srcdir)/src/daemon/https \
+ @LIBGCRYPT_CFLAGS@
+
+EXTRA_DIST = EXPORT.sym
+
+lib_LTLIBRARIES = \
+ libmicrohttpd.la
+
+libmicrohttpd_la_SOURCES = \
+ connection.c connection.h \
+ reason_phrase.c reason_phrase.h \
+ daemon.c \
+ internal.c internal.h \
+ memorypool.c memorypool.h \
+ postprocessor.c \
+ response.c response.h
+libmicrohttpd_la_LDFLAGS = \
+ $(MHD_LIB_LDFLAGS) \
+ -version-info @LIB_VERSION_CURRENT@:@LIB_VERSION_REVISION@:@LIB_VERSION_AGE@
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage
+endif
+
+
+if ENABLE_HTTPS
+SUBDIRS = https .
+libmicrohttpd_la_SOURCES += \
+ connection_https.c connection_https.h
+libmicrohttpd_la_LIBADD = \
+ https/lgl/liblgl.la \
+ https/x509/libx509.la \
+ https/tls/libtls.la \
+ https/minitasn1/libasn1.la
+endif
+
+check_PROGRAMS = \
+ postprocessor_test \
+ postprocessor_large_test \
+ daemon_test
+
+TESTS = $(check_PROGRAMS)
+
+daemon_test_SOURCES = \
+ daemon_test.c
+daemon_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+postprocessor_test_SOURCES = \
+ postprocessor_test.c
+postprocessor_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+postprocessor_large_test_SOURCES = \
+ postprocessor_large_test.c
+postprocessor_large_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
diff --git a/lib/libmicrohttpd/src/daemon/Makefile.in b/lib/libmicrohttpd/src/daemon/Makefile.in
new file mode 100644
index 0000000000..212c3d9f28
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/Makefile.in
@@ -0,0 +1,896 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@ENABLE_HTTPS_TRUE@am__append_1 = \
+@ENABLE_HTTPS_TRUE@ connection_https.c connection_https.h
+
+check_PROGRAMS = postprocessor_test$(EXEEXT) \
+ postprocessor_large_test$(EXEEXT) daemon_test$(EXEEXT)
+subdir = src/daemon
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+@ENABLE_HTTPS_TRUE@libmicrohttpd_la_DEPENDENCIES = \
+@ENABLE_HTTPS_TRUE@ https/lgl/liblgl.la https/x509/libx509.la \
+@ENABLE_HTTPS_TRUE@ https/tls/libtls.la \
+@ENABLE_HTTPS_TRUE@ https/minitasn1/libasn1.la
+am__libmicrohttpd_la_SOURCES_DIST = connection.c connection.h \
+ reason_phrase.c reason_phrase.h daemon.c internal.c internal.h \
+ memorypool.c memorypool.h postprocessor.c response.c \
+ response.h connection_https.c connection_https.h
+@ENABLE_HTTPS_TRUE@am__objects_1 = connection_https.lo
+am_libmicrohttpd_la_OBJECTS = connection.lo reason_phrase.lo daemon.lo \
+ internal.lo memorypool.lo postprocessor.lo response.lo \
+ $(am__objects_1)
+libmicrohttpd_la_OBJECTS = $(am_libmicrohttpd_la_OBJECTS)
+libmicrohttpd_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libmicrohttpd_la_LDFLAGS) $(LDFLAGS) -o $@
+am_daemon_test_OBJECTS = daemon_test.$(OBJEXT)
+daemon_test_OBJECTS = $(am_daemon_test_OBJECTS)
+daemon_test_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_postprocessor_large_test_OBJECTS = \
+ postprocessor_large_test.$(OBJEXT)
+postprocessor_large_test_OBJECTS = \
+ $(am_postprocessor_large_test_OBJECTS)
+postprocessor_large_test_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_postprocessor_test_OBJECTS = postprocessor_test.$(OBJEXT)
+postprocessor_test_OBJECTS = $(am_postprocessor_test_OBJECTS)
+postprocessor_test_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libmicrohttpd_la_SOURCES) $(daemon_test_SOURCES) \
+ $(postprocessor_large_test_SOURCES) \
+ $(postprocessor_test_SOURCES)
+DIST_SOURCES = $(am__libmicrohttpd_la_SOURCES_DIST) \
+ $(daemon_test_SOURCES) $(postprocessor_large_test_SOURCES) \
+ $(postprocessor_test_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DIST_SUBDIRS = https .
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/x509 \
+ -I$(top_srcdir)/src/daemon/https/minitasn1 \
+ -I$(top_srcdir)/src/daemon/https/tls \
+ -I$(top_srcdir)/src/daemon/https \
+ @LIBGCRYPT_CFLAGS@
+
+EXTRA_DIST = EXPORT.sym
+lib_LTLIBRARIES = \
+ libmicrohttpd.la
+
+libmicrohttpd_la_SOURCES = connection.c connection.h reason_phrase.c \
+ reason_phrase.h daemon.c internal.c internal.h memorypool.c \
+ memorypool.h postprocessor.c response.c response.h \
+ $(am__append_1)
+libmicrohttpd_la_LDFLAGS = \
+ $(MHD_LIB_LDFLAGS) \
+ -version-info @LIB_VERSION_CURRENT@:@LIB_VERSION_REVISION@:@LIB_VERSION_AGE@
+
+@USE_COVERAGE_TRUE@AM_CFLAGS = --coverage
+@ENABLE_HTTPS_TRUE@SUBDIRS = https .
+@ENABLE_HTTPS_TRUE@libmicrohttpd_la_LIBADD = \
+@ENABLE_HTTPS_TRUE@ https/lgl/liblgl.la \
+@ENABLE_HTTPS_TRUE@ https/x509/libx509.la \
+@ENABLE_HTTPS_TRUE@ https/tls/libtls.la \
+@ENABLE_HTTPS_TRUE@ https/minitasn1/libasn1.la
+
+TESTS = $(check_PROGRAMS)
+daemon_test_SOURCES = \
+ daemon_test.c
+
+daemon_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+postprocessor_test_SOURCES = \
+ postprocessor_test.c
+
+postprocessor_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+postprocessor_large_test_SOURCES = \
+ postprocessor_large_test.c
+
+postprocessor_large_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/daemon/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/daemon/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libmicrohttpd.la: $(libmicrohttpd_la_OBJECTS) $(libmicrohttpd_la_DEPENDENCIES)
+ $(libmicrohttpd_la_LINK) -rpath $(libdir) $(libmicrohttpd_la_OBJECTS) $(libmicrohttpd_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+daemon_test$(EXEEXT): $(daemon_test_OBJECTS) $(daemon_test_DEPENDENCIES)
+ @rm -f daemon_test$(EXEEXT)
+ $(LINK) $(daemon_test_OBJECTS) $(daemon_test_LDADD) $(LIBS)
+postprocessor_large_test$(EXEEXT): $(postprocessor_large_test_OBJECTS) $(postprocessor_large_test_DEPENDENCIES)
+ @rm -f postprocessor_large_test$(EXEEXT)
+ $(LINK) $(postprocessor_large_test_OBJECTS) $(postprocessor_large_test_LDADD) $(LIBS)
+postprocessor_test$(EXEEXT): $(postprocessor_test_OBJECTS) $(postprocessor_test_DEPENDENCIES)
+ @rm -f postprocessor_test$(EXEEXT)
+ $(LINK) $(postprocessor_test_OBJECTS) $(postprocessor_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection_https.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/internal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memorypool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/postprocessor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/postprocessor_large_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/postprocessor_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reason_phrase.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/response.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \
+ ctags-recursive install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/connection.c b/lib/libmicrohttpd/src/daemon/connection.c
new file mode 100644
index 0000000000..ef47b1c95f
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/connection.c
@@ -0,0 +1,2230 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file connection.c
+ * @brief Methods for managing connections
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#include "internal.h"
+#include "connection.h"
+#include "memorypool.h"
+#include "response.h"
+#include "reason_phrase.h"
+
+#if HAVE_NETINET_TCP_H
+/* for TCP_CORK */
+#include <netinet/tcp.h>
+#endif
+
+/**
+ * Message to transmit when http 1.1 request is received
+ */
+#define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
+
+/**
+ * Response text used when the request (http header) is too big to
+ * be processed.
+ *
+ * Intentionally empty here to keep our memory footprint
+ * minimal.
+ */
+#if HAVE_MESSAGES
+#define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
+#else
+#define REQUEST_TOO_BIG ""
+#endif
+
+/**
+ * Response text used when the request (http header) does not
+ * contain a "Host:" header and still claims to be HTTP 1.1.
+ *
+ * Intentionally empty here to keep our memory footprint
+ * minimal.
+ */
+#if HAVE_MESSAGES
+#define REQUEST_LACKS_HOST "<html><head><title>&quot;Host:&quot; header required</title></head><body>In HTTP 1.1, requests must include a &quot;Host:&quot; header, and your HTTP 1.1 request lacked such a header.</body></html>"
+#else
+#define REQUEST_LACKS_HOST ""
+#endif
+
+/**
+ * Response text used when the request (http header) is
+ * malformed.
+ *
+ * Intentionally empty here to keep our memory footprint
+ * minimal.
+ */
+#if HAVE_MESSAGES
+#define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
+#else
+#define REQUEST_MALFORMED ""
+#endif
+
+/**
+ * Response text used when there is an internal server error.
+ *
+ * Intentionally empty here to keep our memory footprint
+ * minimal.
+ */
+#if HAVE_MESSAGES
+#define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
+#else
+#define INTERNAL_ERROR ""
+#endif
+
+/**
+ * Add extra debug messages with reasons for closing connections
+ * (non-error reasons).
+ */
+#define DEBUG_CLOSE MHD_NO
+
+/**
+ * Should all data send be printed to stderr?
+ */
+#define DEBUG_SEND_DATA MHD_NO
+
+/**
+ * Get all of the headers from the request.
+ *
+ * @param iterator callback to call on each header;
+ * maybe NULL (then just count headers)
+ * @param iterator_cls extra argument to iterator
+ * @return number of entries iterated over
+ */
+int
+MHD_get_connection_values (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ MHD_KeyValueIterator iterator, void *iterator_cls)
+{
+ int ret;
+ struct MHD_HTTP_Header *pos;
+
+ if (connection == NULL)
+ return -1;
+ ret = 0;
+ pos = connection->headers_received;
+ while (pos != NULL)
+ {
+ if (0 != (pos->kind & kind))
+ {
+ ret++;
+ if ((iterator != NULL) &&
+ (MHD_YES != iterator (iterator_cls,
+ kind, pos->header, pos->value)))
+ return ret;
+ }
+ pos = pos->next;
+ }
+ return ret;
+}
+
+/**
+ * This function can be used to add an entry to
+ * the HTTP headers of a connection (so that the
+ * MHD_get_connection_values function will return
+ * them -- and the MHD PostProcessor will also
+ * see them). This maybe required in certain
+ * situations (see Mantis #1399) where (broken)
+ * HTTP implementations fail to supply values needed
+ * by the post processor (or other parts of the
+ * application).
+ * <p>
+ * This function MUST only be called from within
+ * the MHD_AccessHandlerCallback (otherwise, access
+ * maybe improperly synchronized). Furthermore,
+ * the client must guarantee that the key and
+ * value arguments are 0-terminated strings that
+ * are NOT freed until the connection is closed.
+ * (The easiest way to do this is by passing only
+ * arguments to permanently allocated strings.).
+ *
+ * @param connection the connection for which a
+ * value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself
+ * @return MHD_NO if the operation could not be
+ * performed due to insufficient memory;
+ * MHD_YES on success
+ */
+int
+MHD_set_connection_value (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ const char *key, const char *value)
+{
+ struct MHD_HTTP_Header *pos;
+
+ pos = MHD_pool_allocate (connection->pool,
+ sizeof (struct MHD_HTTP_Header), MHD_NO);
+ if (pos == NULL)
+ return MHD_NO;
+ pos->header = (char *) key;
+ pos->value = (char *) value;
+ pos->kind = kind;
+ pos->next = connection->headers_received;
+ connection->headers_received = pos;
+ return MHD_YES;
+}
+
+/**
+ * Get a particular header value. If multiple
+ * values match the kind, return any one of them.
+ *
+ * @param key the header to look for
+ * @return NULL if no such item was found
+ */
+const char *
+MHD_lookup_connection_value (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind, const char *key)
+{
+ struct MHD_HTTP_Header *pos;
+
+ if (connection == NULL)
+ return NULL;
+ pos = connection->headers_received;
+ while (pos != NULL)
+ {
+ if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header)))
+ return pos->value;
+ pos = pos->next;
+ }
+ return NULL;
+}
+
+/**
+ * Queue a response to be transmitted to the client (as soon as
+ * possible but after MHD_AccessHandlerCallback returns).
+ *
+ * @param connection the connection identifying the client
+ * @param status_code HTTP status code (i.e. 200 for OK)
+ * @param response response to transmit
+ * @return MHD_NO on error (i.e. reply already sent),
+ * MHD_YES on success or if message has been queued
+ */
+int
+MHD_queue_response (struct MHD_Connection *connection,
+ unsigned int status_code, struct MHD_Response *response)
+{
+ if ((connection == NULL) ||
+ (response == NULL) ||
+ (connection->response != NULL) ||
+ ((connection->state != MHD_CONNECTION_HEADERS_PROCESSED) &&
+ (connection->state != MHD_CONNECTION_FOOTERS_RECEIVED)))
+ return MHD_NO;
+ MHD_increment_response_rc (response);
+ connection->response = response;
+ connection->responseCode = status_code;
+ if ((connection->method != NULL) &&
+ (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)))
+ {
+ /* if this is a "HEAD" request, pretend that we
+ have already sent the full message body */
+ connection->response_write_position = response->total_size;
+ }
+ if ((response->total_size == MHD_SIZE_UNKNOWN) &&
+ (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
+ connection->have_chunked_response = MHD_YES;
+ else
+ connection->have_chunked_response = MHD_NO;
+ if (connection->state == MHD_CONNECTION_HEADERS_PROCESSED)
+ {
+ /* response was queued "early",
+ refuse to read body / footers or further
+ requests! */
+ SHUTDOWN (connection->socket_fd, SHUT_RD);
+ connection->read_closed = MHD_YES;
+ connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
+ }
+ return MHD_YES;
+}
+
+/**
+ * Do we (still) need to send a 100 continue
+ * message for this connection?
+ */
+static int
+need_100_continue (struct MHD_Connection *connection)
+{
+ const char *expect;
+
+ return ((connection->response == NULL) &&
+ (connection->version != NULL) &&
+ (0 == strcasecmp (connection->version,
+ MHD_HTTP_VERSION_1_1)) &&
+ (NULL != (expect = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_EXPECT)))
+ && (0 == strcasecmp (expect, "100-continue"))
+ && (connection->continue_message_write_offset <
+ strlen (HTTP_100_CONTINUE)));
+}
+
+/**
+ * Close the given connection and give the
+ * specified termination code to the user.
+ */
+void
+MHD_connection_close (struct MHD_Connection *connection,
+ enum MHD_RequestTerminationCode termination_code)
+{
+ SHUTDOWN (connection->socket_fd, SHUT_RDWR);
+ CLOSE (connection->socket_fd);
+ connection->socket_fd = -1;
+ connection->state = MHD_CONNECTION_CLOSED;
+ if ( (NULL != connection->daemon->notify_completed) &&
+ (MHD_YES == connection->client_aware) )
+ connection->daemon->notify_completed (connection->daemon->
+ notify_completed_cls, connection,
+ &connection->client_context,
+ termination_code);
+ connection->client_aware = MHD_NO;
+}
+
+/**
+ * A serious error occured, close the
+ * connection (and notify the application).
+ */
+static void
+connection_close_error (struct MHD_Connection *connection)
+{
+ MHD_connection_close (connection, MHD_REQUEST_TERMINATED_WITH_ERROR);
+}
+
+/**
+ * Prepare the response buffer of this connection for
+ * sending. Assumes that the response mutex is
+ * already held. If the transmission is complete,
+ * this function may close the socket (and return
+ * MHD_NO).
+ *
+ * @return MHD_NO if readying the response failed
+ */
+static int
+try_ready_normal_body (struct MHD_Connection *connection)
+{
+ int ret;
+ struct MHD_Response *response;
+
+ response = connection->response;
+ if (response->crc == NULL)
+ return MHD_YES;
+ if ( (response->data_start <=
+ connection->response_write_position) &&
+ (response->data_size + response->data_start >
+ connection->response_write_position) )
+ return MHD_YES; /* response already ready */
+ ret = response->crc (response->crc_cls,
+ connection->response_write_position,
+ response->data,
+ MHD_MIN (response->data_buffer_size,
+ response->total_size -
+ connection->response_write_position));
+ if ((ret == 0) &&
+ (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY)))
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
+#if HAVE_MESSAGES
+ "API violation"
+#else
+ NULL
+#endif
+ );
+ if (ret == -1)
+ {
+ /* either error or http 1.0 transfer, close
+ socket! */
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon, "Closing connection (end of response)\n");
+#endif
+#endif
+ response->total_size = connection->response_write_position;
+ connection_close_error (connection);
+ return MHD_NO;
+ }
+ response->data_start = connection->response_write_position;
+ response->data_size = ret;
+ if (ret == 0)
+ return MHD_NO;
+ return MHD_YES;
+}
+
+/**
+ * Prepare the response buffer of this connection for
+ * sending. Assumes that the response mutex is
+ * already held. If the transmission is complete,
+ * this function may close the socket (and return
+ * MHD_NO).
+ *
+ * @return MHD_NO if readying the response failed
+ */
+static int
+try_ready_chunked_body (struct MHD_Connection *connection)
+{
+ int ret;
+ char *buf;
+ struct MHD_Response *response;
+ size_t size;
+ char cbuf[10]; /* 10: max strlen of "%x\r\n" */
+ int cblen;
+
+ response = connection->response;
+ if (connection->write_buffer_size == 0)
+ {
+ size = connection->daemon->pool_size;
+ do
+ {
+ size /= 2;
+ if (size < 128)
+ {
+ /* not enough memory */
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Closing connection (out of memory)\n");
+#endif
+#endif
+ connection_close_error (connection);
+ return MHD_NO;
+ }
+ buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
+ }
+ while (buf == NULL);
+ connection->write_buffer_size = size;
+ connection->write_buffer = buf;
+ }
+
+ if ( (response->data_start <=
+ connection->response_write_position) &&
+ (response->data_size + response->data_start >
+ connection->response_write_position) )
+ {
+ /* buffer already ready, use what is there for the chunk */
+ ret = response->data_size + response->data_start - connection->response_write_position;
+ if (ret > connection->write_buffer_size - sizeof (cbuf) - 2)
+ ret = connection->write_buffer_size - sizeof (cbuf) - 2;
+ memcpy (&connection->write_buffer[sizeof (cbuf)],
+ &response->data[connection->response_write_position - response->data_start],
+ ret);
+ }
+ else
+ {
+ /* buffer not in range, try to fill it */
+ ret = response->crc (response->crc_cls,
+ connection->response_write_position,
+ &connection->write_buffer[sizeof (cbuf)],
+ connection->write_buffer_size - sizeof (cbuf) - 2);
+ }
+ if (ret == -1)
+ {
+ /* end of message, signal other side! */
+ strcpy (connection->write_buffer, "0\r\n");
+ connection->write_buffer_append_offset = 3;
+ connection->write_buffer_send_offset = 0;
+ response->total_size = connection->response_write_position;
+ return MHD_YES;
+ }
+ if (ret == 0)
+ {
+ connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
+ return MHD_NO;
+ }
+ if (ret > 0xFFFFFF)
+ ret = 0xFFFFFF;
+ SPRINTF (cbuf, "%X\r\n", ret);
+ cblen = strlen (cbuf);
+ EXTRA_CHECK (cblen <= sizeof (cbuf));
+ memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
+ memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
+ connection->response_write_position += ret;
+ connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
+ connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
+ return MHD_YES;
+}
+
+/**
+ * Check if we need to set some additional headers
+ * for http-compiliance.
+ */
+static void
+add_extra_headers (struct MHD_Connection *connection)
+{
+ const char *have;
+ char buf[128];
+
+ connection->have_chunked_upload = MHD_NO;
+ if (connection->response->total_size == MHD_SIZE_UNKNOWN)
+ {
+ have = MHD_get_response_header (connection->response,
+ MHD_HTTP_HEADER_CONNECTION);
+ if ((have == NULL) || (0 != strcasecmp (have, "close")))
+ {
+ if ((connection->version != NULL) &&
+ (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
+ {
+ connection->have_chunked_upload = MHD_YES;
+ have = MHD_get_response_header (connection->response,
+ MHD_HTTP_HEADER_TRANSFER_ENCODING);
+ if (have == NULL)
+ MHD_add_response_header (connection->response,
+ MHD_HTTP_HEADER_TRANSFER_ENCODING,
+ "chunked");
+ }
+ else
+ {
+ MHD_add_response_header (connection->response,
+ MHD_HTTP_HEADER_CONNECTION, "close");
+ }
+ }
+ }
+ else if (NULL == MHD_get_response_header (connection->response,
+ MHD_HTTP_HEADER_CONTENT_LENGTH))
+ {
+ SPRINTF (buf,
+ "%llu",
+ (unsigned long long)connection->response->total_size);
+ MHD_add_response_header (connection->response,
+ MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
+ }
+}
+
+/**
+ * Produce HTTP "Date:" header.
+ *
+ * @param date where to write the header, with
+ * at least 128 bytes available space.
+ */
+static void
+get_date_string (char *date)
+{
+ static const char *days[] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+ static const char *mons[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
+ "Nov", "Dec"
+ };
+ struct tm now;
+ time_t t;
+
+ time (&t);
+ gmtime_r (&t, &now);
+ SPRINTF (date,
+ "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
+ days[now.tm_wday % 7],
+ now.tm_mday,
+ mons[now.tm_mon % 12],
+ 1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
+}
+
+/**
+ * Try growing the read buffer
+ *
+ * @return MHD_YES on success, MHD_NO on failure
+ */
+static int
+try_grow_read_buffer (struct MHD_Connection *connection)
+{
+ void *buf;
+
+ buf = MHD_pool_reallocate (connection->pool,
+ connection->read_buffer,
+ connection->read_buffer_size,
+ connection->read_buffer_size * 2 +
+ MHD_BUF_INC_SIZE + 1);
+ if (buf == NULL)
+ return MHD_NO;
+ /* we can actually grow the buffer, do it! */
+ connection->read_buffer = buf;
+ connection->read_buffer_size =
+ connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
+ return MHD_YES;
+}
+
+/**
+ * Allocate the connection's write buffer and
+ * fill it with all of the headers (or footers,
+ * if we have already sent the body) from the
+ * HTTPd's response.
+ */
+static int
+build_header_response (struct MHD_Connection *connection)
+{
+ size_t size;
+ size_t off;
+ struct MHD_HTTP_Header *pos;
+ char code[256];
+ char date[128];
+ char *data;
+ enum MHD_ValueKind kind;
+ const char *reason_phrase;
+
+ if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
+ {
+ add_extra_headers (connection);
+ reason_phrase = MHD_get_reason_phrase_for (connection->responseCode);
+ SPRINTF (code,
+ "%s %u %s\r\n",
+ MHD_HTTP_VERSION_1_1, connection->responseCode, reason_phrase);
+ off = strlen (code);
+ /* estimate size */
+ size = off + 2; /* extra \r\n at the end */
+ kind = MHD_HEADER_KIND;
+ if (NULL == MHD_get_response_header (connection->response,
+ MHD_HTTP_HEADER_DATE))
+ get_date_string (date);
+ else
+ date[0] = '\0';
+ size += strlen (date);
+ }
+ else
+ {
+ size = 2;
+ kind = MHD_FOOTER_KIND;
+ off = 0;
+ }
+ pos = connection->response->first_header;
+ while (pos != NULL)
+ {
+ if (pos->kind == kind)
+ size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
+ pos = pos->next;
+ }
+ /* produce data */
+ data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
+ if (data == NULL)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
+#endif
+ return MHD_NO;
+ }
+ if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
+ {
+ memcpy (data, code, off);
+ }
+ pos = connection->response->first_header;
+ while (pos != NULL)
+ {
+ if (pos->kind == kind)
+ off += SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
+ pos = pos->next;
+ }
+ if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
+ {
+ strcpy (&data[off], date);
+ off += strlen (date);
+ }
+ memcpy (&data[off], "\r\n", 2);
+ off += 2;
+ if (off != size)
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
+ connection->write_buffer = data;
+ connection->write_buffer_append_offset = size;
+ connection->write_buffer_send_offset = 0;
+ connection->write_buffer_size = size + 1;
+ return MHD_YES;
+}
+
+/**
+ * We encountered an error processing the request.
+ * Handle it properly by stopping to read data
+ * and sending the indicated response code and message.
+ *
+ * @param status_code the response code to send (400, 413 or 414)
+ */
+static void
+transmit_error_response (struct MHD_Connection *connection,
+ unsigned int status_code, const char *message)
+{
+ struct MHD_Response *response;
+
+ /* die, header far too long to be reasonable */
+ connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
+ connection->read_closed = MHD_YES;
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Error %u (`%s') processing request, closing connection.\n",
+ status_code, message);
+#endif
+ response = MHD_create_response_from_data (strlen (message),
+ (void *) message, MHD_NO, MHD_NO);
+ MHD_queue_response (connection, status_code, response);
+ EXTRA_CHECK (connection->response != NULL);
+ MHD_destroy_response (response);
+ if (MHD_NO == build_header_response (connection))
+ {
+ /* oops - close! */
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Closing connection (failed to create response header)\n");
+#endif
+ connection->state = MHD_CONNECTION_CLOSED;
+ }
+ else
+ {
+ connection->state = MHD_CONNECTION_HEADERS_SENDING;
+ }
+}
+
+/**
+ * Add "fd" to the "fd_set". If "fd" is
+ * greater than "*max", set "*max" to fd.
+ */
+static void
+do_fd_set (int fd, fd_set * set, int *max_fd)
+{
+ FD_SET (fd, set);
+ if (fd > *max_fd)
+ *max_fd = fd;
+}
+
+/**
+ * Obtain the select sets for this connection
+ *
+ * @return MHD_YES on success
+ */
+int
+MHD_connection_get_fdset (struct MHD_Connection *connection,
+ fd_set * read_fd_set,
+ fd_set * write_fd_set,
+ fd_set * except_fd_set, int *max_fd)
+{
+ int ret;
+ struct MHD_Pollfd p;
+
+ memset(&p, 0, sizeof(struct MHD_Pollfd));
+ ret = MHD_connection_get_pollfd(connection, &p);
+ if ( (ret == MHD_YES) && (p.fd >= 0) ) {
+ if (0 != (p.events & MHD_POLL_ACTION_IN))
+ do_fd_set(p.fd, read_fd_set, max_fd);
+ if (0 != (p.events & MHD_POLL_ACTION_OUT))
+ do_fd_set(p.fd, write_fd_set, max_fd);
+ }
+ return ret;
+}
+
+/**
+ * Obtain the pollfd for this connection
+ *
+ * @return MHD_YES on success. If return MHD_YES and p->fd < 0, this
+ * connection is not waiting for any read or write events
+ */
+int
+MHD_connection_get_pollfd(struct MHD_Connection *connection, struct MHD_Pollfd *p)
+{
+ int fd;
+
+ if (connection->pool == NULL)
+ connection->pool = MHD_pool_create (connection->daemon->pool_size);
+ if (connection->pool == NULL)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
+#endif
+ connection_close_error (connection);
+ return MHD_NO;
+ }
+ fd = connection->socket_fd;
+ p->fd = fd;
+ if (fd == -1)
+ return MHD_YES;
+ while (1)
+ {
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+ switch (connection->state)
+ {
+ case MHD_CONNECTION_INIT:
+ case MHD_CONNECTION_URL_RECEIVED:
+ case MHD_CONNECTION_HEADER_PART_RECEIVED:
+#if HTTPS_SUPPORT
+ case MHD_TLS_CONNECTION_INIT:
+#endif
+ /* while reading headers, we always grow the
+ read buffer if needed, no size-check required */
+ if ((connection->read_closed) &&
+ (connection->read_buffer_offset == 0))
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ if ((connection->read_buffer_offset == connection->read_buffer_size)
+ && (MHD_NO == try_grow_read_buffer (connection)))
+ {
+ transmit_error_response (connection,
+ (connection->url != NULL)
+ ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
+ : MHD_HTTP_REQUEST_URI_TOO_LONG,
+ REQUEST_TOO_BIG);
+ continue;
+ }
+ if (MHD_NO == connection->read_closed)
+ p->events |= MHD_POLL_ACTION_IN;
+ break;
+ case MHD_CONNECTION_HEADERS_RECEIVED:
+ /* we should never get here */
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_HEADERS_PROCESSED:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_CONTINUE_SENDING:
+ p->events |= MHD_POLL_ACTION_OUT;
+ break;
+ case MHD_CONNECTION_CONTINUE_SENT:
+ if (connection->read_buffer_offset == connection->read_buffer_size)
+ {
+ if ((MHD_YES != try_grow_read_buffer (connection)) &&
+ (0 != (connection->daemon->options &
+ (MHD_USE_SELECT_INTERNALLY |
+ MHD_USE_THREAD_PER_CONNECTION))))
+ {
+ /* failed to grow the read buffer, and the
+ client which is supposed to handle the
+ received data in a *blocking* fashion
+ (in this mode) did not handle the data as
+ it was supposed to!
+ => we would either have to do busy-waiting
+ (on the client, which would likely fail),
+ or if we do nothing, we would just timeout
+ on the connection (if a timeout is even
+ set!).
+ Solution: we kill the connection with an error */
+ transmit_error_response (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ INTERNAL_ERROR);
+ continue;
+ }
+ }
+ if ((connection->read_buffer_offset < connection->read_buffer_size)
+ && (MHD_NO == connection->read_closed))
+ p->events |= MHD_POLL_ACTION_IN;
+ break;
+ case MHD_CONNECTION_BODY_RECEIVED:
+ case MHD_CONNECTION_FOOTER_PART_RECEIVED:
+ /* while reading footers, we always grow the
+ read buffer if needed, no size-check required */
+ if (MHD_YES == connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ p->events |= MHD_POLL_ACTION_IN;
+ /* transition to FOOTERS_RECEIVED
+ happens in read handler */
+ break;
+ case MHD_CONNECTION_FOOTERS_RECEIVED:
+ /* no socket action, wait for client
+ to provide response */
+ break;
+ case MHD_CONNECTION_HEADERS_SENDING:
+ /* headers in buffer, keep writing */
+ p->events |= MHD_POLL_ACTION_OUT;
+ break;
+ case MHD_CONNECTION_HEADERS_SENT:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_NORMAL_BODY_READY:
+ p->events |= MHD_POLL_ACTION_OUT;
+ break;
+ case MHD_CONNECTION_NORMAL_BODY_UNREADY:
+ /* not ready, no socket action */
+ break;
+ case MHD_CONNECTION_CHUNKED_BODY_READY:
+ p->events |= MHD_POLL_ACTION_OUT;
+ break;
+ case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
+ /* not ready, no socket action */
+ break;
+ case MHD_CONNECTION_BODY_SENT:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_FOOTERS_SENDING:
+ p->events |= MHD_POLL_ACTION_OUT;
+ break;
+ case MHD_CONNECTION_FOOTERS_SENT:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_CLOSED:
+ if (connection->socket_fd != -1)
+ connection_close_error (connection);
+ return MHD_YES; /* do nothing, not even reading */
+
+ default:
+ EXTRA_CHECK (0);
+ }
+ break;
+ }
+ return MHD_YES;
+}
+
+/**
+ * Parse a single line of the HTTP header. Advance
+ * read_buffer (!) appropriately. If the current line does not
+ * fit, consider growing the buffer. If the line is
+ * far too long, close the connection. If no line is
+ * found (incomplete, buffer too small, line too long),
+ * return NULL. Otherwise return a pointer to the line.
+ */
+static char *
+get_next_header_line (struct MHD_Connection *connection)
+{
+ char *rbuf;
+ size_t pos;
+
+ if (connection->read_buffer_offset == 0)
+ return NULL;
+ pos = 0;
+ rbuf = connection->read_buffer;
+ while ((pos < connection->read_buffer_offset - 1) &&
+ (rbuf[pos] != '\r') && (rbuf[pos] != '\n'))
+ pos++;
+ if (pos == connection->read_buffer_offset - 1)
+ {
+ /* not found, consider growing... */
+ if (connection->read_buffer_offset == connection->read_buffer_size)
+ {
+ rbuf = MHD_pool_reallocate (connection->pool,
+ connection->read_buffer,
+ connection->read_buffer_size,
+ connection->read_buffer_size * 2 +
+ MHD_BUF_INC_SIZE);
+ if (rbuf == NULL)
+ {
+ transmit_error_response (connection,
+ (connection->url != NULL)
+ ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
+ : MHD_HTTP_REQUEST_URI_TOO_LONG,
+ REQUEST_TOO_BIG);
+ }
+ else
+ {
+ connection->read_buffer_size =
+ connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
+ connection->read_buffer = rbuf;
+ }
+ }
+ return NULL;
+ }
+ /* found, check if we have proper CRLF */
+ if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n'))
+ rbuf[pos++] = '\0'; /* skip both r and n */
+ rbuf[pos++] = '\0';
+ connection->read_buffer += pos;
+ connection->read_buffer_size -= pos;
+ connection->read_buffer_offset -= pos;
+ return rbuf;
+}
+
+/**
+ * @return MHD_NO on failure (out of memory), MHD_YES for success
+ */
+static int
+connection_add_header (struct MHD_Connection *connection,
+ char *key, char *value, enum MHD_ValueKind kind)
+{
+ struct MHD_HTTP_Header *hdr;
+
+ hdr = MHD_pool_allocate (connection->pool,
+ sizeof (struct MHD_HTTP_Header), MHD_YES);
+ if (hdr == NULL)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Not enough memory to allocate header record!\n");
+#endif
+ transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
+ REQUEST_TOO_BIG);
+ return MHD_NO;
+ }
+ hdr->next = connection->headers_received;
+ hdr->header = key;
+ hdr->value = value;
+ hdr->kind = kind;
+ connection->headers_received = hdr;
+ return MHD_YES;
+}
+
+/**
+ * @return MHD_NO on failure (out of memory), MHD_YES for success
+ */
+static int
+parse_arguments (enum MHD_ValueKind kind,
+ struct MHD_Connection *connection, char *args)
+{
+ char *equals;
+ char *amper;
+
+ while (args != NULL)
+ {
+ equals = strstr (args, "=");
+ if (equals == NULL)
+ return MHD_NO; /* invalid, ignore */
+ equals[0] = '\0';
+ equals++;
+ amper = strstr (equals, "&");
+ if (amper != NULL)
+ {
+ amper[0] = '\0';
+ amper++;
+ }
+ MHD_http_unescape (args);
+ MHD_http_unescape (equals);
+ if (MHD_NO == connection_add_header (connection, args, equals, kind))
+ return MHD_NO;
+ args = amper;
+ }
+ return MHD_YES;
+}
+
+/**
+ * Parse the cookie header (see RFC 2109).
+ *
+ * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory)
+ */
+static int
+parse_cookie_header (struct MHD_Connection *connection)
+{
+ const char *hdr;
+ char *cpy;
+ char *pos;
+ char *sce;
+ char *semicolon;
+ char *equals;
+ char *ekill;
+ char old;
+ int quotes;
+
+ hdr = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_COOKIE);
+ if (hdr == NULL)
+ return MHD_YES;
+ cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
+ if (cpy == NULL)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
+#endif
+ transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
+ REQUEST_TOO_BIG);
+ return MHD_NO;
+ }
+ memcpy (cpy, hdr, strlen (hdr) + 1);
+ pos = cpy;
+ while (pos != NULL)
+ {
+ while (*pos == ' ')
+ pos++; /* skip spaces */
+
+ sce = pos;
+ while (((*sce) != '\0') &&
+ ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
+ sce++;
+ /* remove tailing whitespace (if any) from key */
+ ekill = sce - 1;
+ while ((*ekill == ' ') && (ekill >= pos))
+ *(ekill--) = '\0';
+ old = *sce;
+ *sce = '\0';
+ if (old != '=')
+ {
+ /* value part omitted, use empty string... */
+ if (MHD_NO ==
+ connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
+ return MHD_NO;
+ if (old == '\0')
+ break;
+ pos = sce + 1;
+ continue;
+ }
+ equals = sce + 1;
+ quotes = 0;
+ semicolon = equals;
+ while ((semicolon[0] != '\0') &&
+ ((quotes != 0) ||
+ ((semicolon[0] != ';') && (semicolon[0] != ','))))
+ {
+ if (semicolon[0] == '"')
+ quotes = (quotes + 1) & 1;
+ semicolon++;
+ }
+ if (semicolon[0] == '\0')
+ semicolon = NULL;
+ if (semicolon != NULL)
+ {
+ semicolon[0] = '\0';
+ semicolon++;
+ }
+ /* remove quotes */
+ if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
+ {
+ equals[strlen (equals) - 1] = '\0';
+ equals++;
+ }
+ if (MHD_NO == connection_add_header (connection,
+ pos, equals, MHD_COOKIE_KIND))
+ return MHD_NO;
+ pos = semicolon;
+ }
+ return MHD_YES;
+}
+
+/**
+ * Parse the first line of the HTTP HEADER.
+ *
+ * @param connection the connection (updated)
+ * @param line the first line
+ * @return MHD_YES if the line is ok, MHD_NO if it is malformed
+ */
+static int
+parse_initial_message_line (struct MHD_Connection *connection, char *line)
+{
+ char *uri;
+ char *httpVersion;
+ char *args;
+
+ uri = strstr (line, " ");
+ if (uri == NULL)
+ return MHD_NO; /* serious error */
+ uri[0] = '\0';
+ connection->method = line;
+ uri++;
+ while (uri[0] == ' ')
+ uri++;
+ httpVersion = strstr (uri, " ");
+ if (httpVersion != NULL)
+ {
+ httpVersion[0] = '\0';
+ httpVersion++;
+ }
+ if (connection->daemon->uri_log_callback != NULL)
+ connection->client_context
+ =
+ connection->daemon->uri_log_callback (connection->daemon->
+ uri_log_callback_cls, uri);
+ args = strstr (uri, "?");
+ if (args != NULL)
+ {
+ args[0] = '\0';
+ args++;
+ parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
+ }
+ MHD_http_unescape (uri);
+ connection->url = uri;
+ if (httpVersion == NULL)
+ connection->version = "";
+ else
+ connection->version = httpVersion;
+ return MHD_YES;
+}
+
+/**
+ * Call the handler of the application for this
+ * connection. Handles chunking of the upload
+ * as well as normal uploads.
+ */
+static void
+call_connection_handler (struct MHD_Connection *connection)
+{
+ size_t processed;
+ size_t available;
+ size_t used;
+ size_t i;
+ int instant_retry;
+ int malformed;
+ char *buffer_head;
+
+ if (connection->response != NULL)
+ return; /* already queued a response */
+
+ buffer_head = connection->read_buffer;
+ available = connection->read_buffer_offset;
+ do
+ {
+ instant_retry = MHD_NO;
+ if ((connection->have_chunked_upload == MHD_YES) &&
+ (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
+ {
+ if ((connection->current_chunk_offset ==
+ connection->current_chunk_size)
+ && (connection->current_chunk_offset != 0) && (available >= 2))
+ {
+ /* skip new line at the *end* of a chunk */
+ i = 0;
+ if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
+ i++; /* skip 1st part of line feed */
+ if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
+ i++; /* skip 2nd part of line feed */
+ if (i == 0)
+ {
+ /* malformed encoding */
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
+#endif
+ connection_close_error (connection);
+ return;
+ }
+ available -= i;
+ buffer_head += i;
+ connection->current_chunk_offset = 0;
+ connection->current_chunk_size = 0;
+ }
+ if (connection->current_chunk_offset <
+ connection->current_chunk_size)
+ {
+ /* we are in the middle of a chunk, give
+ as much as possible to the client (without
+ crossing chunk boundaries) */
+ processed =
+ connection->current_chunk_size -
+ connection->current_chunk_offset;
+ if (processed > available)
+ processed = available;
+ if (available > processed)
+ instant_retry = MHD_YES;
+ }
+ else
+ {
+ /* we need to read chunk boundaries */
+ i = 0;
+ while (i < available)
+ {
+ if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
+ break;
+ i++;
+ if (i >= 6)
+ break;
+ }
+ /* take '\n' into account; if '\n'
+ is the unavailable character, we
+ will need to wait until we have it
+ before going further */
+ if ((i + 1 >= available) &&
+ !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
+ break; /* need more data... */
+ malformed = (i >= 6);
+ if (!malformed)
+ {
+ buffer_head[i] = '\0';
+ malformed =
+ (1 != SSCANF (buffer_head, "%X",
+ &connection->current_chunk_size)) &&
+ (1 != SSCANF (buffer_head, "%x",
+ &connection->current_chunk_size));
+ }
+ if (malformed)
+ {
+ /* malformed encoding */
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
+#endif
+ connection_close_error (connection);
+ return;
+ }
+ i++;
+ if ((i < available) &&
+ ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
+ i++; /* skip 2nd part of line feed */
+
+ buffer_head += i;
+ available -= i;
+ connection->current_chunk_offset = 0;
+
+ if (available > 0)
+ instant_retry = MHD_YES;
+ if (connection->current_chunk_size == 0)
+ {
+ connection->remaining_upload_size = 0;
+ break;
+ }
+ continue;
+ }
+ }
+ else
+ {
+ /* no chunked encoding, give all to the client */
+ processed = available;
+ }
+ used = processed;
+ connection->client_aware = MHD_YES;
+ if (MHD_NO ==
+ connection->daemon->default_handler (connection->daemon->
+ default_handler_cls,
+ connection, connection->url,
+ connection->method,
+ connection->version,
+ buffer_head, &processed,
+ &connection->client_context))
+ {
+ /* serious internal error, close connection */
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Internal application error, closing connection.\n");
+#endif
+ connection_close_error (connection);
+ return;
+ }
+ if (processed > used)
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
+#if HAVE_MESSAGES
+ "API violation"
+#else
+ NULL
+#endif
+ );
+ if (processed != 0)
+ instant_retry = MHD_NO; /* client did not process everything */
+ used -= processed;
+ if (connection->have_chunked_upload == MHD_YES)
+ connection->current_chunk_offset += used;
+ /* dh left "processed" bytes in buffer for next time... */
+ buffer_head += used;
+ available -= used;
+ if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
+ connection->remaining_upload_size -= used;
+ }
+ while (instant_retry == MHD_YES);
+ if (available > 0)
+ memmove (connection->read_buffer, buffer_head, available);
+ connection->read_buffer_offset = available;
+}
+
+/**
+ * Try reading data from the socket into the
+ * read buffer of the connection.
+ *
+ * @return MHD_YES if something changed,
+ * MHD_NO if we were interrupted or if
+ * no space was available
+ */
+static int
+do_read (struct MHD_Connection *connection)
+{
+ int bytes_read;
+
+ if (connection->read_buffer_size == connection->read_buffer_offset)
+ return MHD_NO;
+
+ bytes_read = connection->recv_cls (connection,
+ &connection->read_buffer
+ [connection->read_buffer_offset],
+ connection->read_buffer_size -
+ connection->read_buffer_offset);
+ if (bytes_read < 0)
+ {
+ if (errno == EINTR)
+ return MHD_NO;
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Failed to receive data: %s\n", STRERROR (errno));
+#endif
+ connection_close_error (connection);
+ return MHD_YES;
+ }
+ if (bytes_read == 0)
+ {
+ /* other side closed connection */
+ connection->read_closed = MHD_YES;
+ SHUTDOWN (connection->socket_fd, SHUT_RD);
+ return MHD_NO;
+ }
+ connection->read_buffer_offset += bytes_read;
+ return MHD_YES;
+}
+
+/**
+ * Try writing data to the socket from the
+ * write buffer of the connection.
+ *
+ * @return MHD_YES if something changed,
+ * MHD_NO if we were interrupted
+ */
+static int
+do_write (struct MHD_Connection *connection)
+{
+ int ret;
+
+ ret = connection->send_cls (connection,
+ &connection->write_buffer
+ [connection->write_buffer_send_offset],
+ connection->write_buffer_append_offset
+ - connection->write_buffer_send_offset);
+
+ if (ret < 0)
+ {
+ if (errno == EINTR)
+ return MHD_NO;
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Failed to send data: %s\n", STRERROR (errno));
+#endif
+ connection_close_error (connection);
+ return MHD_YES;
+ }
+#if DEBUG_SEND_DATA
+ FPRINTF (stderr,
+ "Sent response: `%.*s'\n",
+ ret,
+ &connection->write_buffer[connection->write_buffer_send_offset]);
+#endif
+ connection->write_buffer_send_offset += ret;
+ return MHD_YES;
+}
+
+/**
+ * Check if we are done sending the write-buffer.
+ * If so, transition into "next_state".
+ * @return MHY_NO if we are not done, MHD_YES if we are
+ */
+static int
+check_write_done (struct MHD_Connection *connection,
+ enum MHD_CONNECTION_STATE next_state)
+{
+ if (connection->write_buffer_append_offset !=
+ connection->write_buffer_send_offset)
+ return MHD_NO;
+ connection->write_buffer_append_offset = 0;
+ connection->write_buffer_send_offset = 0;
+ connection->state = next_state;
+ MHD_pool_reallocate (connection->pool, connection->write_buffer,
+ connection->write_buffer_size, 0);
+ connection->write_buffer = NULL;
+ connection->write_buffer_size = 0;
+ return MHD_YES;
+}
+
+/**
+ * We have received (possibly the beginning of) a line in the
+ * header (or footer). Validate (check for ":") and prepare
+ * to process.
+ */
+static int
+process_header_line (struct MHD_Connection *connection, char *line)
+{
+ char *colon;
+
+ /* line should be normal header line, find colon */
+ colon = strstr (line, ":");
+ if (colon == NULL)
+ {
+ /* error in header line, die hard */
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Received malformed line (no colon), closing connection.\n");
+#endif
+ connection->state = MHD_CONNECTION_CLOSED;
+ return MHD_NO;
+ }
+ /* zero-terminate header */
+ colon[0] = '\0';
+ colon++; /* advance to value */
+ while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
+ colon++;
+ /* we do the actual adding of the connection
+ header at the beginning of the while
+ loop since we need to be able to inspect
+ the *next* header line (in case it starts
+ with a space...) */
+ connection->last = line;
+ connection->colon = colon;
+ return MHD_YES;
+}
+
+/**
+ * Process a header value that spans multiple lines.
+ * The previous line(s) are in connection->last.
+ *
+ * @param line the current input line
+ * @param kind if the line is complete, add a header
+ * of the given kind
+ * @return MHD_YES if the line was processed successfully
+ */
+static int
+process_broken_line (struct MHD_Connection *connection,
+ char *line, enum MHD_ValueKind kind)
+{
+ char *last;
+ char *tmp;
+
+ last = connection->last;
+ if ((line[0] == ' ') || (line[0] == '\t'))
+ {
+ /* value was continued on the next line, see
+ http://www.jmarshall.com/easy/http/ */
+ last = MHD_pool_reallocate (connection->pool,
+ last,
+ strlen (last) + 1,
+ strlen (line) + strlen (last) + 1);
+ if (last == NULL)
+ {
+ transmit_error_response (connection,
+ MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
+ REQUEST_TOO_BIG);
+ return MHD_NO;
+ }
+ tmp = line;
+ while ((tmp[0] == ' ') || (tmp[0] == '\t'))
+ tmp++; /* skip whitespace at start of 2nd line */
+ strcat (last, tmp);
+ connection->last = last;
+ return MHD_YES; /* possibly more than 2 lines... */
+ }
+ EXTRA_CHECK ((last != NULL) && (connection->colon != NULL));
+ if ((MHD_NO == connection_add_header (connection,
+ last, connection->colon, kind)))
+ {
+ transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
+ REQUEST_TOO_BIG);
+ return MHD_NO;
+ }
+ /* we still have the current line to deal with... */
+ if (strlen (line) != 0)
+ {
+ if (MHD_NO == process_header_line (connection, line))
+ {
+ transmit_error_response (connection,
+ MHD_HTTP_BAD_REQUEST, REQUEST_MALFORMED);
+ return MHD_NO;
+ }
+ }
+ return MHD_YES;
+}
+
+/**
+ * Parse the various headers; figure out the size
+ * of the upload and make sure the headers follow
+ * the protocol. Advance to the appropriate state.
+ */
+static void
+parse_connection_headers (struct MHD_Connection *connection)
+{
+ const char *clen;
+ unsigned long long cval;
+ struct MHD_Response *response;
+
+ parse_cookie_header (connection);
+ if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
+ && (NULL != connection->version)
+ && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
+ && (NULL ==
+ MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_HOST)))
+ {
+ /* die, http 1.1 request without host and we are pedantic */
+ connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
+ connection->read_closed = MHD_YES;
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Received `%s' request without `%s' header.\n",
+ MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
+#endif
+ response =
+ MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
+ REQUEST_LACKS_HOST, MHD_NO, MHD_NO);
+ MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
+ MHD_destroy_response (response);
+ return;
+ }
+
+ clen = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_CONTENT_LENGTH);
+ if (clen != NULL)
+ {
+ if (1 != SSCANF (clen, "%llu", &cval))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Failed to parse `%s' header `%s', closing connection.\n",
+ MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
+#endif
+ connection->state = MHD_CONNECTION_CLOSED;
+ return;
+ }
+ connection->remaining_upload_size = cval;
+ }
+ else
+ {
+ if (NULL == MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_TRANSFER_ENCODING))
+ {
+ /* this request does not have a body */
+ connection->remaining_upload_size = 0;
+ }
+ else
+ {
+ connection->remaining_upload_size = MHD_SIZE_UNKNOWN;
+ if (0 ==
+ strcasecmp (MHD_lookup_connection_value
+ (connection, MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_TRANSFER_ENCODING), "chunked"))
+ connection->have_chunked_upload = MHD_YES;
+ }
+ }
+}
+
+/**
+ * This function handles a particular connection when it has been
+ * determined that there is data to be read off a socket. All
+ * implementations (multithreaded, external select, internal select)
+ * call this function to handle reads.
+ *
+ * @return MHD_YES if we should continue to process the
+ * connection (not dead yet), MHD_NO if it died
+ */
+int
+MHD_connection_handle_read (struct MHD_Connection *connection)
+{
+ connection->last_activity = time (NULL);
+ if (connection->state == MHD_CONNECTION_CLOSED)
+ return MHD_NO;
+ /* make sure "read" has a reasonable number of bytes
+ in buffer to use per system call (if possible) */
+ if (connection->read_buffer_offset + MHD_BUF_INC_SIZE >
+ connection->read_buffer_size)
+ try_grow_read_buffer (connection);
+ if (MHD_NO == do_read (connection))
+ return MHD_YES;
+ while (1)
+ {
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+ switch (connection->state)
+ {
+ case MHD_CONNECTION_INIT:
+ case MHD_CONNECTION_URL_RECEIVED:
+ case MHD_CONNECTION_HEADER_PART_RECEIVED:
+ case MHD_CONNECTION_HEADERS_RECEIVED:
+ case MHD_CONNECTION_HEADERS_PROCESSED:
+ case MHD_CONNECTION_CONTINUE_SENDING:
+ case MHD_CONNECTION_CONTINUE_SENT:
+ case MHD_CONNECTION_BODY_RECEIVED:
+ case MHD_CONNECTION_FOOTER_PART_RECEIVED:
+ /* nothing to do but default action */
+ if (MHD_YES == connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ break;
+ case MHD_CONNECTION_CLOSED:
+ if (connection->socket_fd != -1)
+ connection_close_error (connection);
+ return MHD_NO;
+ default:
+ /* shrink read buffer to how much is actually used */
+ MHD_pool_reallocate (connection->pool,
+ connection->read_buffer,
+ connection->read_buffer_size + 1,
+ connection->read_buffer_offset);
+ break;
+ }
+ break;
+ }
+ return MHD_YES;
+}
+
+/**
+ * This function was created to handle writes to sockets when it has
+ * been determined that the socket can be written to. All
+ * implementations (multithreaded, external select, internal select)
+ * call this function
+ *
+ * @return MHD_YES if we should continue to process the
+ * connection (not dead yet), MHD_NO if it died
+ */
+int
+MHD_connection_handle_write (struct MHD_Connection *connection)
+{
+ struct MHD_Response *response;
+ int ret;
+ connection->last_activity = time (NULL);
+ while (1)
+ {
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+ switch (connection->state)
+ {
+ case MHD_CONNECTION_INIT:
+ case MHD_CONNECTION_URL_RECEIVED:
+ case MHD_CONNECTION_HEADER_PART_RECEIVED:
+ case MHD_CONNECTION_HEADERS_RECEIVED:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_HEADERS_PROCESSED:
+ break;
+ case MHD_CONNECTION_CONTINUE_SENDING:
+ ret = connection->send_cls (connection,
+ &HTTP_100_CONTINUE
+ [connection->continue_message_write_offset],
+ strlen (HTTP_100_CONTINUE) -
+ connection->continue_message_write_offset);
+ if (ret < 0)
+ {
+ if (errno == EINTR)
+ break;
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Failed to send data: %s\n", STRERROR (errno));
+#endif
+ connection_close_error (connection);
+ return MHD_NO;
+ }
+#if DEBUG_SEND_DATA
+ FPRINTF (stderr,
+ "Sent 100 continue response: `%.*s'\n",
+ ret,
+ &HTTP_100_CONTINUE
+ [connection->continue_message_write_offset]);
+#endif
+ connection->continue_message_write_offset += ret;
+ break;
+ case MHD_CONNECTION_CONTINUE_SENT:
+ case MHD_CONNECTION_BODY_RECEIVED:
+ case MHD_CONNECTION_FOOTER_PART_RECEIVED:
+ case MHD_CONNECTION_FOOTERS_RECEIVED:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_HEADERS_SENDING:
+ do_write (connection);
+ check_write_done (connection, MHD_CONNECTION_HEADERS_SENT);
+ break;
+ case MHD_CONNECTION_HEADERS_SENT:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_NORMAL_BODY_READY:
+ response = connection->response;
+ if (response->crc != NULL)
+ pthread_mutex_lock (&response->mutex);
+ if (MHD_YES != try_ready_normal_body (connection))
+ {
+ if (response->crc != NULL)
+ pthread_mutex_unlock (&response->mutex);
+ connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
+ break;
+ }
+#if HTTPS_SUPPORT
+ if (connection->daemon->options & MHD_USE_SSL)
+ {
+ ret = MHD__gnutls_record_send (connection->tls_session,
+ &connection->response->data
+ [connection->
+ response_write_position -
+ response->data_start],
+ response->data_size -
+ (connection->response_write_position
+ - response->data_start));
+ }
+ else
+#endif
+ {
+ ret = connection->send_cls (connection,
+ &response->data
+ [connection->response_write_position
+ - response->data_start],
+ response->data_size -
+ (connection->response_write_position
+ - response->data_start));
+ }
+#if DEBUG_SEND_DATA
+ if (ret > 0)
+ FPRINTF (stderr,
+ "Sent DATA response: `%.*s'\n",
+ ret,
+ &response->data[connection->response_write_position -
+ response->data_start]);
+#endif
+ if (response->crc != NULL)
+ pthread_mutex_unlock (&response->mutex);
+ if (ret < 0)
+ {
+ if (errno == EINTR)
+ return MHD_YES;
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Failed to send data: %s\n", STRERROR (errno));
+#endif
+ connection_close_error (connection);
+ return MHD_NO;
+ }
+ connection->response_write_position += ret;
+ if (connection->response_write_position ==
+ connection->response->total_size)
+ connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers... */
+ break;
+ case MHD_CONNECTION_NORMAL_BODY_UNREADY:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_CHUNKED_BODY_READY:
+ do_write (connection);
+ check_write_done (connection,
+ (connection->response->total_size ==
+ connection->response_write_position) ?
+ MHD_CONNECTION_BODY_SENT :
+ MHD_CONNECTION_CHUNKED_BODY_UNREADY);
+ break;
+ case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
+ case MHD_CONNECTION_BODY_SENT:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_FOOTERS_SENDING:
+ do_write (connection);
+ check_write_done (connection, MHD_CONNECTION_FOOTERS_SENT);
+ break;
+ case MHD_CONNECTION_FOOTERS_SENT:
+ EXTRA_CHECK (0);
+ break;
+ case MHD_CONNECTION_CLOSED:
+ if (connection->socket_fd != -1)
+ connection_close_error (connection);
+ return MHD_NO;
+ case MHD_TLS_CONNECTION_INIT:
+ case MHD_TLS_HELLO_REQUEST:
+ case MHD_TLS_HANDSHAKE_FAILED:
+ EXTRA_CHECK (0);
+ break;
+ default:
+ EXTRA_CHECK (0);
+ connection_close_error (connection);
+ return MHD_NO;
+ }
+ break;
+ }
+ return MHD_YES;
+}
+
+/**
+ * This function was created to handle per-connection processing that
+ * has to happen even if the socket cannot be read or written to. All
+ * implementations (multithreaded, external select, internal select)
+ * call this function.
+ *
+ * @return MHD_YES if we should continue to process the
+ * connection (not dead yet), MHD_NO if it died
+ */
+int
+MHD_connection_handle_idle (struct MHD_Connection *connection)
+{
+ unsigned int timeout;
+ const char *end;
+ char *line;
+
+ while (1)
+ {
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+ switch (connection->state)
+ {
+ case MHD_CONNECTION_INIT:
+ line = get_next_header_line (connection);
+ if (line == NULL)
+ {
+ if (connection->state != MHD_CONNECTION_INIT)
+ continue;
+ if (connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ break;
+ }
+ if (MHD_NO == parse_initial_message_line (connection, line))
+ connection->state = MHD_CONNECTION_CLOSED;
+ else
+ connection->state = MHD_CONNECTION_URL_RECEIVED;
+ continue;
+ case MHD_CONNECTION_URL_RECEIVED:
+ line = get_next_header_line (connection);
+ if (line == NULL)
+ {
+ if (connection->state != MHD_CONNECTION_URL_RECEIVED)
+ continue;
+ if (connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ break;
+ }
+ if (strlen (line) == 0)
+ {
+ connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
+ continue;
+ }
+ if (MHD_NO == process_header_line (connection, line))
+ {
+ transmit_error_response (connection,
+ MHD_HTTP_BAD_REQUEST,
+ REQUEST_MALFORMED);
+ break;
+ }
+ connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED;
+ continue;
+ case MHD_CONNECTION_HEADER_PART_RECEIVED:
+ line = get_next_header_line (connection);
+ if (line == NULL)
+ {
+ if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
+ continue;
+ if (connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ break;
+ }
+ if (MHD_NO ==
+ process_broken_line (connection, line, MHD_HEADER_KIND))
+ continue;
+ if (strlen (line) == 0)
+ {
+ connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
+ continue;
+ }
+ continue;
+ case MHD_CONNECTION_HEADERS_RECEIVED:
+ parse_connection_headers (connection);
+ if (connection->state == MHD_CONNECTION_CLOSED)
+ continue;
+ connection->state = MHD_CONNECTION_HEADERS_PROCESSED;
+ continue;
+ case MHD_CONNECTION_HEADERS_PROCESSED:
+ call_connection_handler (connection); /* first call */
+ if (connection->state == MHD_CONNECTION_CLOSED)
+ continue;
+ if (need_100_continue (connection))
+ {
+ connection->state = MHD_CONNECTION_CONTINUE_SENDING;
+ break;
+ }
+ if (connection->response != NULL)
+ {
+ /* we refused (no upload allowed!) */
+ connection->remaining_upload_size = 0;
+ /* force close, in case client still tries to upload... */
+ connection->read_closed = MHD_YES;
+ }
+ connection->state = (connection->remaining_upload_size == 0)
+ ? MHD_CONNECTION_FOOTERS_RECEIVED : MHD_CONNECTION_CONTINUE_SENT;
+ continue;
+ case MHD_CONNECTION_CONTINUE_SENDING:
+ if (connection->continue_message_write_offset ==
+ strlen (HTTP_100_CONTINUE))
+ {
+ connection->state = MHD_CONNECTION_CONTINUE_SENT;
+ continue;
+ }
+ break;
+ case MHD_CONNECTION_CONTINUE_SENT:
+ if (connection->read_buffer_offset != 0)
+ {
+ call_connection_handler (connection); /* loop call */
+ if (connection->state == MHD_CONNECTION_CLOSED)
+ continue;
+ }
+ if ((connection->remaining_upload_size == 0) ||
+ ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
+ (connection->read_buffer_offset == 0) &&
+ (MHD_YES == connection->read_closed)))
+ {
+ if ((MHD_YES == connection->have_chunked_upload) &&
+ (MHD_NO == connection->read_closed))
+ connection->state = MHD_CONNECTION_BODY_RECEIVED;
+ else
+ connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
+ continue;
+ }
+ break;
+ case MHD_CONNECTION_BODY_RECEIVED:
+ line = get_next_header_line (connection);
+ if (line == NULL)
+ {
+ if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
+ continue;
+ if (connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ break;
+ }
+ if (strlen (line) == 0)
+ {
+ connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
+ continue;
+ }
+ if (MHD_NO == process_header_line (connection, line))
+ {
+ transmit_error_response (connection,
+ MHD_HTTP_BAD_REQUEST,
+ REQUEST_MALFORMED);
+ break;
+ }
+ connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED;
+ continue;
+ case MHD_CONNECTION_FOOTER_PART_RECEIVED:
+ line = get_next_header_line (connection);
+ if (line == NULL)
+ {
+ if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
+ continue;
+ if (connection->read_closed)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ break;
+ }
+ if (MHD_NO ==
+ process_broken_line (connection, line, MHD_FOOTER_KIND))
+ continue;
+ if (strlen (line) == 0)
+ {
+ connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
+ continue;
+ }
+ continue;
+ case MHD_CONNECTION_FOOTERS_RECEIVED:
+ call_connection_handler (connection); /* "final" call */
+ if (connection->state == MHD_CONNECTION_CLOSED)
+ continue;
+ if (connection->response == NULL)
+ break; /* try again next time */
+ if (MHD_NO == build_header_response (connection))
+ {
+ /* oops - close! */
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Closing connection (failed to create response header)\n");
+#endif
+ connection->state = MHD_CONNECTION_CLOSED;
+ continue;
+ }
+ connection->state = MHD_CONNECTION_HEADERS_SENDING;
+
+#if HAVE_DECL_TCP_CORK
+ /* starting header send, set TCP cork */
+ {
+ const int val = 1;
+ setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
+ sizeof (val));
+ }
+#endif
+ break;
+ case MHD_CONNECTION_HEADERS_SENDING:
+ /* no default action */
+ break;
+ case MHD_CONNECTION_HEADERS_SENT:
+ if (connection->have_chunked_upload)
+ connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
+ else
+ connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
+ continue;
+ case MHD_CONNECTION_NORMAL_BODY_READY:
+ /* nothing to do here */
+ break;
+ case MHD_CONNECTION_NORMAL_BODY_UNREADY:
+ if (connection->response->crc != NULL)
+ pthread_mutex_lock (&connection->response->mutex);
+ if (MHD_YES == try_ready_normal_body (connection))
+ {
+ if (connection->response->crc != NULL)
+ pthread_mutex_unlock (&connection->response->mutex);
+ connection->state = MHD_CONNECTION_NORMAL_BODY_READY;
+ break;
+ }
+ if (connection->response->crc != NULL)
+ pthread_mutex_unlock (&connection->response->mutex);
+ /* not ready, no socket action */
+ break;
+ case MHD_CONNECTION_CHUNKED_BODY_READY:
+ /* nothing to do here */
+ break;
+ case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
+ if (connection->response->crc != NULL)
+ pthread_mutex_lock (&connection->response->mutex);
+ if (MHD_YES == try_ready_chunked_body (connection))
+ {
+ if (connection->response->crc != NULL)
+ pthread_mutex_unlock (&connection->response->mutex);
+ connection->state = MHD_CONNECTION_CHUNKED_BODY_READY;
+ continue;
+ }
+ if (connection->response->crc != NULL)
+ pthread_mutex_unlock (&connection->response->mutex);
+ break;
+ case MHD_CONNECTION_BODY_SENT:
+ build_header_response (connection);
+ if (connection->write_buffer_send_offset ==
+ connection->write_buffer_append_offset)
+ connection->state = MHD_CONNECTION_FOOTERS_SENT;
+ else
+ connection->state = MHD_CONNECTION_FOOTERS_SENDING;
+ continue;
+ case MHD_CONNECTION_FOOTERS_SENDING:
+ /* no default action */
+ break;
+ case MHD_CONNECTION_FOOTERS_SENT:
+#if HAVE_DECL_TCP_CORK
+ /* done sending, uncork */
+ {
+ const int val = 0;
+ setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
+ sizeof (val));
+ }
+#endif
+ MHD_destroy_response (connection->response);
+ if (connection->daemon->notify_completed != NULL)
+ {
+ connection->daemon->notify_completed (connection->daemon->
+ notify_completed_cls,
+ connection,
+ &connection->client_context,
+ MHD_REQUEST_TERMINATED_COMPLETED_OK);
+ }
+ connection->client_aware = MHD_NO;
+ end =
+ MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_CONNECTION);
+ connection->client_context = NULL;
+ connection->continue_message_write_offset = 0;
+ connection->responseCode = 0;
+ connection->response = NULL;
+ connection->headers_received = NULL;
+ connection->response_write_position = 0;
+ connection->have_chunked_upload = MHD_NO;
+ connection->method = NULL;
+ connection->url = NULL;
+ connection->write_buffer = NULL;
+ connection->write_buffer_size = 0;
+ connection->write_buffer_send_offset = 0;
+ connection->write_buffer_append_offset = 0;
+ if ((end != NULL) && (0 == strcasecmp (end, "close")))
+ {
+ connection->read_closed = MHD_YES;
+ connection->read_buffer_offset = 0;
+ }
+ if (((MHD_YES == connection->read_closed) &&
+ (0 == connection->read_buffer_offset)) ||
+ (connection->version == NULL) ||
+ (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
+ {
+ /* http 1.0, version-less requests cannot be pipelined */
+ connection->state = MHD_CONNECTION_CLOSED;
+ MHD_pool_destroy (connection->pool);
+ connection->pool = NULL;
+ connection->read_buffer = NULL;
+ connection->read_buffer_size = 0;
+ connection->read_buffer_offset = 0;
+ }
+ else
+ {
+ connection->version = NULL;
+ connection->state = MHD_CONNECTION_INIT;
+ connection->read_buffer
+ = MHD_pool_reset (connection->pool,
+ connection->read_buffer,
+ connection->read_buffer_size);
+ }
+ continue;
+ case MHD_CONNECTION_CLOSED:
+ if (connection->socket_fd != -1)
+ connection_close_error (connection);
+ break;
+ default:
+ EXTRA_CHECK (0);
+ break;
+ }
+ break;
+ }
+ timeout = connection->daemon->connection_timeout;
+ if ((connection->socket_fd != -1) &&
+ (timeout != 0) && (time (NULL) - timeout > connection->last_activity))
+ {
+ MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
+ return MHD_NO;
+ }
+ return MHD_YES;
+
+}
+
+void
+MHD_set_http_calbacks (struct MHD_Connection *connection)
+{
+ connection->read_handler = &MHD_connection_handle_read;
+ connection->write_handler = &MHD_connection_handle_write;
+ connection->idle_handler = &MHD_connection_handle_idle;
+}
+
+#if HTTPS_SUPPORT
+#include "gnutls_int.h"
+#include "gnutls_record.h"
+#endif
+
+/**
+ * Obtain information about the given connection.
+ *
+ * @param connection what connection to get information about
+ * @param infoType what information is desired?
+ * @param ... depends on infoType
+ * @return NULL if this information is not available
+ * (or if the infoType is unknown)
+ */
+const union MHD_ConnectionInfo *
+MHD_get_connection_info (struct MHD_Connection *connection,
+ enum MHD_ConnectionInfoType infoType, ...)
+{
+ switch (infoType)
+ {
+#if HTTPS_SUPPORT
+ case MHD_CONNECTION_INFO_CIPHER_ALGO:
+ if (connection->tls_session == NULL)
+ return NULL;
+ return (const union MHD_ConnectionInfo *) &connection->
+ tls_session->security_parameters.read_bulk_cipher_algorithm;
+ case MHD_CONNECTION_INFO_PROTOCOL:
+ if (connection->tls_session == NULL)
+ return NULL;
+ return (const union MHD_ConnectionInfo *) &connection->
+ tls_session->security_parameters.version;
+#endif
+ case MHD_CONNECTION_INFO_CLIENT_ADDRESS:
+ return (const union MHD_ConnectionInfo *) &connection->addr;
+ default:
+ return NULL;
+ };
+}
+
+
+/* end of connection.c */
diff --git a/lib/libmicrohttpd/src/daemon/connection.h b/lib/libmicrohttpd/src/daemon/connection.h
new file mode 100644
index 0000000000..e7491590c2
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/connection.h
@@ -0,0 +1,66 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file connection.h
+ * @brief Methods for managing connections
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+#include "internal.h"
+
+/**
+ * Obtain the select sets for this connection.
+ *
+ * @return MHD_YES on success
+ */
+int
+MHD_connection_get_fdset (struct MHD_Connection *connection,
+ fd_set * read_fd_set,
+ fd_set * write_fd_set,
+ fd_set * except_fd_set, int *max_fd);
+
+/**
+ * Obtain the pollfd for this connection. The poll interface allows large
+ * file descriptors. Select goes stupid when the fd overflows fdset (which
+ * is fixed).
+ */
+int MHD_connection_get_pollfd(struct MHD_Connection *connection,
+ struct MHD_Pollfd *p);
+
+void MHD_set_http_calbacks (struct MHD_Connection *connection);
+
+int MHD_connection_handle_read (struct MHD_Connection *connection);
+
+int MHD_connection_handle_write (struct MHD_Connection *connection);
+
+int MHD_connection_handle_idle (struct MHD_Connection *connection);
+
+/**
+ * Close the given connection and give the
+ * specified termination code to the user.
+ */
+void MHD_connection_close (struct MHD_Connection *connection,
+ enum MHD_RequestTerminationCode termination_code);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/connection_https.c b/lib/libmicrohttpd/src/daemon/connection_https.c
new file mode 100644
index 0000000000..b5b1a4ba8f
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/connection_https.c
@@ -0,0 +1,309 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file connection.c
+ * @brief Methods for managing SSL/TLS connections. This file is only
+ * compiled if ENABLE_HTTPS is set.
+ * @author Sagie Amir
+ * @author Christian Grothoff
+ */
+
+#include "internal.h"
+#include "connection.h"
+#include "memorypool.h"
+#include "response.h"
+#include "reason_phrase.h"
+
+/* get opaque type */
+#include "gnutls_int.h"
+#include "gnutls_record.h"
+
+/* TODO #include rm "gnutls_errors.h" */
+#include "gnutls_errors.h"
+
+/**
+ * This function is called once a secure connection has been marked
+ * for closure.
+ *
+ * NOTE: Some code duplication with connection_close_error
+ * in connection.c
+ *
+ * @param connection: the connection to close
+ * @param termination_code: the termination code with which the notify completed callback function is called.
+ */
+static void
+MHD_tls_connection_close (struct MHD_Connection *connection,
+ enum MHD_RequestTerminationCode termination_code)
+{
+ MHD__gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
+ connection->tls_session->internals.read_eof = 1;
+ MHD_connection_close (connection, termination_code);
+}
+
+/**
+ * This function was created to handle per-connection processing that
+ * has to happen even if the socket cannot be read or written to. All
+ * implementations (multithreaded, external select, internal select)
+ * call this function.
+ *
+ * @param connection being handled
+ * @return MHD_YES if we should continue to process the
+ * connection (not dead yet), MHD_NO if it died
+ */
+static int
+MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
+{
+ unsigned int timeout;
+
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+ timeout = connection->daemon->connection_timeout;
+ if ((connection->socket_fd != -1) && (timeout != 0)
+ && (time (NULL) - timeout > connection->last_activity))
+ {
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
+ return MHD_NO;
+ }
+ switch (connection->state)
+ {
+ /* on newly created connections we might reach here before any reply has been received */
+ case MHD_TLS_CONNECTION_INIT:
+ return MHD_YES;
+ /* close connection if necessary */
+ case MHD_CONNECTION_CLOSED:
+ if (connection->socket_fd != -1)
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_COMPLETED_OK);
+ return MHD_NO;
+ case MHD_TLS_HANDSHAKE_FAILED:
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_WITH_ERROR);
+ return MHD_NO;
+ /* some HTTP state */
+ default:
+ return MHD_connection_handle_idle (connection);
+ }
+ return MHD_YES;
+}
+
+/**
+ * This function handles a particular SSL/TLS connection when
+ * it has been determined that there is data to be read off a
+ * socket. Message processing is done by message type which is
+ * determined by peeking into the first message type byte of the
+ * stream.
+ *
+ * Error message handling: all fatal level messages cause the
+ * connection to be terminated.
+ *
+ * Application data is forwarded to the underlying daemon for
+ * processing.
+ *
+ * @param connection : the source connection
+ * @return MHD_YES if we should continue to process the
+ * connection (not dead yet), MHD_NO if it died
+ */
+static int
+MHD_tls_connection_handle_read (struct MHD_Connection *connection)
+{
+ int ret;
+ unsigned char msg_type;
+
+ connection->last_activity = time (NULL);
+ if (connection->state == MHD_CONNECTION_CLOSED ||
+ connection->state == MHD_TLS_HANDSHAKE_FAILED)
+ return MHD_NO;
+
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+
+ /* discover content type */
+ if (RECV (connection->socket_fd, &msg_type, 1, MSG_PEEK) == -1)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon, "Failed to peek into TLS content type\n");
+#endif
+ return MHD_NO;
+ }
+
+ switch (msg_type)
+ {
+ /* check for handshake messages first */
+ case GNUTLS_HANDSHAKE:
+ /* negotiate handshake only while in INIT & HELLO_REQUEST states */
+ if (connection->state == MHD_TLS_CONNECTION_INIT ||
+ connection->state == MHD_TLS_HELLO_REQUEST)
+ {
+ ret = MHD__gnutls_handshake (connection->tls_session);
+ if (ret == 0)
+ {
+ /* set connection state to enable HTTP processing */
+ connection->state = MHD_CONNECTION_INIT;
+ break;
+ }
+ /* set connection as closed */
+ else
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Error: Handshake has failed (%d)\n", ret);
+#endif
+ connection->state = MHD_TLS_HANDSHAKE_FAILED;
+ return MHD_NO;
+ }
+ }
+ /* a handshake message has been received out of bound */
+ else
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Error: received handshake message out of context\n");
+#endif
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_WITH_ERROR);
+ return MHD_NO;
+ }
+
+ /* ignore any out of bound change chiper spec messages */
+ case GNUTLS_CHANGE_CIPHER_SPEC:
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_WITH_ERROR);
+ return MHD_NO;
+
+ case GNUTLS_ALERT:
+ /*
+ * this call of MHD_gtls_recv_int expects 0 bytes read.
+ * done to decrypt alert message
+ */
+ MHD_gtls_recv_int (connection->tls_session, GNUTLS_ALERT,
+ GNUTLS_HANDSHAKE_FINISHED, 0, 0);
+
+ /* CLOSE_NOTIFY */
+ if (connection->tls_session->internals.last_alert ==
+ GNUTLS_A_CLOSE_NOTIFY)
+ {
+ connection->state = MHD_CONNECTION_CLOSED;
+ return MHD_YES;
+ }
+ /* non FATAL or WARNING */
+ else if (connection->tls_session->internals.last_alert_level !=
+ GNUTLS_AL_FATAL)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Received TLS alert: %s\n",
+ MHD__gnutls_alert_get_name ((int)
+ connection->tls_session->
+ internals.last_alert));
+#endif
+ return MHD_YES;
+ }
+ /* FATAL */
+ else if (connection->tls_session->internals.last_alert_level ==
+ GNUTLS_AL_FATAL)
+ {
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_WITH_ERROR);
+ return MHD_NO;
+ }
+ /* this should never execute */
+ else
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Received unrecognized alert: %d\n",
+ connection->tls_session->internals.last_alert);
+#endif
+ return MHD_NO;
+ }
+
+
+ /* forward application level content to MHD */
+ case GNUTLS_APPLICATION_DATA:
+ return MHD_connection_handle_read (connection);
+
+ case GNUTLS_INNER_APPLICATION:
+ break;
+ default:
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Error: unrecognized TLS message type: %d, connection state: %s. l: %d, f: %s\n",
+ msg_type, MHD_state_to_string (connection->state), __LINE__,
+ __FUNCTION__);
+#endif
+ /* close connection upon reception of unrecognized message type */
+ MHD_tls_connection_close (connection,
+ MHD_REQUEST_TERMINATED_WITH_ERROR);
+ return MHD_NO;
+ }
+
+ return MHD_YES;
+}
+
+/**
+ * This function was created to handle writes to sockets when it has
+ * been determined that the socket can be written to. This function
+ * will forward all write requests to the underlying daemon unless
+ * the connection has been marked for closing.
+ *
+ * @return MHD_connection_handle_write() if we should continue to
+ * process the connection (not dead yet), MHD_NO if it died
+ */
+static int
+MHD_tls_connection_handle_write (struct MHD_Connection *connection)
+{
+ connection->last_activity = time (NULL);
+
+#if DEBUG_STATES
+ MHD_DLOG (connection->daemon, "%s: state: %s\n",
+ __FUNCTION__, MHD_state_to_string (connection->state));
+#endif
+
+ switch (connection->state)
+ {
+ case MHD_CONNECTION_CLOSED:
+ case MHD_TLS_HANDSHAKE_FAILED:
+ return MHD_NO;
+ /* some HTTP connection state */
+ default:
+ return MHD_connection_handle_write (connection);
+ }
+ return MHD_NO;
+}
+
+/**
+ * Set connection callback function to be used through out
+ * the processing of this secure connection.
+ */
+void
+MHD_set_https_calbacks (struct MHD_Connection *connection)
+{
+ connection->read_handler = &MHD_tls_connection_handle_read;
+ connection->write_handler = &MHD_tls_connection_handle_write;
+ connection->idle_handler = &MHD_tls_connection_handle_idle;
+}
+
+/* end of connection_https.c */
diff --git a/lib/libmicrohttpd/src/daemon/connection_https.h b/lib/libmicrohttpd/src/daemon/connection_https.h
new file mode 100644
index 0000000000..ef6f5dc683
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/connection_https.h
@@ -0,0 +1,35 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2008 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file connection_https.h
+ * @brief Methods for managing connections
+ * @author Christian Grothoff
+ */
+
+#ifndef CONNECTION_HTTPS_H
+#define CONNECTION_HTTPS_H
+
+#include "internal.h"
+
+#if HTTPS_SUPPORT
+void MHD_set_https_calbacks (struct MHD_Connection *connection);
+#endif
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/daemon.c b/lib/libmicrohttpd/src/daemon/daemon.c
new file mode 100644
index 0000000000..98b22bdd95
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/daemon.c
@@ -0,0 +1,1971 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008, 2009 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file daemon.c
+ * @brief A minimal-HTTP server library
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "internal.h"
+#include "response.h"
+#include "connection.h"
+#include "memorypool.h"
+
+#if HTTPS_SUPPORT
+#include "connection_https.h"
+#include "gnutls_int.h"
+#include "gnutls_global.h"
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
+/**
+ * Default connection limit.
+ */
+#ifndef WINDOWS
+#define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
+#else
+#define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
+#endif
+
+/**
+ * Default memory allowed per connection.
+ */
+#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
+
+/**
+ * Print extra messages with reasons for closing
+ * sockets? (only adds non-error messages).
+ */
+#define DEBUG_CLOSE MHD_NO
+
+/**
+ * Print extra messages when establishing
+ * connections? (only adds non-error messages).
+ */
+#define DEBUG_CONNECT MHD_NO
+
+#ifndef LINUX
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+#endif
+
+#ifdef __SYMBIAN32__
+static void pthread_kill (int, int) {
+ // Symbian doesn't have signals. The user of the library is required to
+ // run it in an external select loop.
+ abort();
+}
+#endif // __SYMBIAN32__
+
+/**
+ * Default implementation of the panic function
+ */
+static void
+mhd_panic_std(void *cls,
+ const char *file,
+ unsigned int line,
+ const char *reason)
+{
+ abort ();
+}
+
+
+/**
+ * Handler for fatal errors.
+ */
+MHD_PanicCallback mhd_panic;
+
+/**
+ * Closure argument for "mhd_panic".
+ */
+void *mhd_panic_cls;
+
+/**
+ * Trace up to and return master daemon. If the supplied daemon
+ * is a master, then return the daemon itself.
+ */
+static struct MHD_Daemon*
+MHD_get_master (struct MHD_Daemon *daemon)
+{
+ while (NULL != daemon->master)
+ daemon = daemon->master;
+ return daemon;
+}
+
+/**
+ * Maintain connection count for single address.
+ */
+struct MHD_IPCount
+{
+ int family;
+ union
+ {
+ struct in_addr ipv4;
+#if HAVE_IPV6
+ struct in6_addr ipv6;
+#endif
+ } addr;
+ unsigned int count;
+};
+
+/**
+ * Lock shared structure for IP connection counts
+ */
+static void
+MHD_ip_count_lock(struct MHD_Daemon *daemon)
+{
+ if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to acquire IP connection limit mutex\n");
+#endif
+ abort();
+ }
+}
+
+/**
+ * Unlock shared structure for IP connection counts
+ */
+static void
+MHD_ip_count_unlock(struct MHD_Daemon *daemon)
+{
+ if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to release IP connection limit mutex\n");
+#endif
+ abort();
+ }
+}
+
+/**
+ * Tree comparison function for IP addresses (supplied to tsearch() family).
+ * We compare everything in the struct up through the beginning of the
+ * 'count' field.
+ */
+static int
+MHD_ip_addr_compare(const void *a1, const void *a2)
+{
+ return memcmp (a1, a2, offsetof(struct MHD_IPCount, count));
+}
+
+/**
+ * Parse address and initialize 'key' using the address. Returns MHD_YES
+ * on success and MHD_NO otherwise (e.g., invalid address type).
+ */
+static int
+MHD_ip_addr_to_key(struct sockaddr *addr, socklen_t addrlen,
+ struct MHD_IPCount *key)
+{
+ memset(key, 0, sizeof(*key));
+
+ /* IPv4 addresses */
+ if (addrlen == sizeof(struct sockaddr_in))
+ {
+ const struct sockaddr_in *addr4 = (const struct sockaddr_in*)addr;
+ key->family = AF_INET;
+ memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
+ return MHD_YES;
+ }
+
+#if HAVE_IPV6
+ /* IPv6 addresses */
+ if (addrlen == sizeof (struct sockaddr_in6))
+ {
+ const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)addr;
+ key->family = AF_INET6;
+ memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
+ return MHD_YES;
+ }
+#endif
+
+ /* Some other address */
+ return MHD_NO;
+}
+
+/**
+ * Check if IP address is over its limit.
+ *
+ * @return Return MHD_YES if IP below limit, MHD_NO if IP has surpassed limit.
+ * Also returns MHD_NO if fails to allocate memory.
+ */
+static int
+MHD_ip_limit_add(struct MHD_Daemon *daemon,
+ struct sockaddr *addr, socklen_t addrlen)
+{
+ struct MHD_IPCount *key;
+ void *node;
+ int result;
+
+ daemon = MHD_get_master (daemon);
+
+ /* Ignore if no connection limit assigned */
+ if (daemon->per_ip_connection_limit == 0)
+ return MHD_YES;
+
+ key = malloc (sizeof(*key));
+ if (NULL == key)
+ return MHD_NO;
+
+ /* Initialize key */
+ if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
+ {
+ /* Allow unhandled address types through */
+ free (key);
+ return MHD_YES;
+ }
+
+ MHD_ip_count_lock (daemon);
+
+ /* Search for the IP address */
+ node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
+ if (!node)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG(daemon,
+ "Failed to add IP connection count node\n");
+#endif
+ MHD_ip_count_unlock (daemon);
+ return MHD_NO;
+ }
+ node = *(void**)node;
+
+ /* If we got an existing node back, free the one we created */
+ if (node != key)
+ free(key);
+ key = (struct MHD_IPCount*)node;
+
+ /* Test if there is room for another connection; if so,
+ * increment count */
+ result = (key->count < daemon->per_ip_connection_limit);
+ if (result == MHD_YES)
+ ++key->count;
+
+ MHD_ip_count_unlock (daemon);
+ return result;
+}
+
+/**
+ * Decrement connection count for IP address, removing from table
+ * count reaches 0
+ */
+static void
+MHD_ip_limit_del(struct MHD_Daemon *daemon,
+ struct sockaddr *addr, socklen_t addrlen)
+{
+ struct MHD_IPCount search_key;
+ struct MHD_IPCount *found_key;
+ void *node;
+
+ daemon = MHD_get_master (daemon);
+
+ /* Ignore if no connection limit assigned */
+ if (daemon->per_ip_connection_limit == 0)
+ return;
+
+ /* Initialize search key */
+ if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
+ return;
+
+ MHD_ip_count_lock (daemon);
+
+ /* Search for the IP address */
+ node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
+
+ /* Something's wrong if we couldn't find an IP address
+ * that was previously added */
+ if (!node)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Failed to find previously-added IP address\n");
+#endif
+ abort();
+ }
+ found_key = (struct MHD_IPCount*)*(void**)node;
+
+ /* Validate existing count for IP address */
+ if (found_key->count == 0)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Previously-added IP address had 0 count\n");
+#endif
+ abort();
+ }
+
+ /* Remove the node entirely if count reduces to 0 */
+ if (--found_key->count == 0)
+ {
+ TDELETE (found_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
+ free (found_key);
+ }
+
+ MHD_ip_count_unlock (daemon);
+}
+
+#if HTTPS_SUPPORT
+pthread_mutex_t MHD_gnutls_init_mutex;
+
+/**
+ * Note: code duplication with code in MHD_gnutls_priority.c
+ *
+ * @return 0
+ */
+static int
+_set_priority (MHD_gtls_priority_st * st, const int *list)
+{
+ int num = 0;
+
+ while ((list[num] != 0) && (num < MAX_ALGOS))
+ num++;
+ st->num_algorithms = num;
+ memcpy (st->priority, list, num * sizeof (int));
+ return 0;
+}
+
+
+/**
+ * Callback for receiving data from the socket.
+ *
+ * @param conn the MHD connection structure
+ * @param other where to write received data to
+ * @param i maximum size of other (in bytes)
+ * @return number of bytes actually received
+ */
+static ssize_t
+recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
+{
+ return MHD__gnutls_record_recv (connection->tls_session, other, i);
+}
+
+/**
+ * Callback for writing data to the socket.
+ *
+ * @param conn the MHD connection structure
+ * @param other data to write
+ * @param i number of bytes to write
+ * @return actual number of bytes written
+ */
+static ssize_t
+send_tls_adapter (struct MHD_Connection *connection,
+ const void *other, size_t i)
+{
+ return MHD__gnutls_record_send (connection->tls_session, other, i);
+}
+
+
+/**
+ * Read and setup our certificate and key.
+ *
+ * @return 0 on success
+ */
+static int
+MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
+{
+ MHD_gnutls_datum_t key;
+ MHD_gnutls_datum_t cert;
+
+ /* certificate & key loaded from memory */
+ if (daemon->https_mem_cert && daemon->https_mem_key)
+ {
+ key.data = (unsigned char *) daemon->https_mem_key;
+ key.size = strlen (daemon->https_mem_key);
+ cert.data = (unsigned char *) daemon->https_mem_cert;
+ cert.size = strlen (daemon->https_mem_cert);
+
+ return MHD__gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
+ &cert, &key,
+ GNUTLS_X509_FMT_PEM);
+ }
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
+#endif
+ return -1;
+}
+
+/**
+ * Initialize security aspects of the HTTPS daemon
+ *
+ * @return 0 on success
+ */
+static int
+MHD_TLS_init (struct MHD_Daemon *daemon)
+{
+ switch (daemon->cred_type)
+ {
+ case MHD_GNUTLS_CRD_CERTIFICATE:
+ if (0 !=
+ MHD__gnutls_certificate_allocate_credentials (&daemon->x509_cred))
+ return GNUTLS_E_MEMORY_ERROR;
+ return MHD_init_daemon_certificate (daemon);
+ default:
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Error: invalid credentials type %d specified.\n",
+ daemon->cred_type);
+#endif
+ return -1;
+ }
+}
+#endif
+
+/**
+ * Obtain the select sets for this daemon.
+ *
+ * @return MHD_YES on success, MHD_NO if this
+ * daemon was not started with the right
+ * options for this call.
+ */
+int
+MHD_get_fdset (struct MHD_Daemon *daemon,
+ fd_set * read_fd_set,
+ fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
+{
+ struct MHD_Connection *con_itr;
+ int fd;
+
+ if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
+ || (except_fd_set == NULL) || (max_fd == NULL)
+ || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
+ || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
+ || ((daemon->options & MHD_USE_POLL) != 0))
+ return MHD_NO;
+
+ FD_SET (fd, read_fd_set);
+ /* update max file descriptor */
+ if ((*max_fd) < fd)
+ *max_fd = fd;
+
+ con_itr = daemon->connections;
+ while (con_itr != NULL)
+ {
+ if (MHD_YES != MHD_connection_get_fdset (con_itr,
+ read_fd_set,
+ write_fd_set,
+ except_fd_set, max_fd))
+ return MHD_NO;
+ con_itr = con_itr->next;
+ }
+#if DEBUG_CONNECT
+ MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
+#endif
+ return MHD_YES;
+}
+
+/**
+ * Main function of the thread that handles an individual
+ * connection when MHD_USE_THREAD_PER_CONNECTION.
+ */
+static void *
+MHD_handle_connection (void *data)
+{
+ struct MHD_Connection *con = data;
+ int num_ready;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ struct timeval tv;
+ unsigned int timeout;
+ time_t now;
+#ifdef HAVE_POLL_H
+ struct MHD_Pollfd mp;
+ struct pollfd p;
+#endif
+
+ timeout = con->daemon->connection_timeout;
+ while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
+ now = time (NULL);
+ tv.tv_usec = 0;
+ if ( (timeout > (now - con->last_activity)) ||
+ (timeout == 0) )
+ {
+ /* in case we are missing the SIGALRM, keep going after
+ at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
+ tv.tv_sec = 1;
+ if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
+ (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
+ {
+ /* do not block (we're waiting for our callback to succeed) */
+ tv.tv_sec = 0;
+ }
+ }
+ else
+ {
+ tv.tv_sec = 0;
+ }
+#ifdef HAVE_POLL_H
+ if (0 == (con->daemon->options & MHD_USE_POLL)) {
+#else
+ {
+#endif
+ /* use select */
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ max = 0;
+ MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
+ num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
+ if (num_ready < 0) {
+ if (errno == EINTR)
+ continue;
+#if HAVE_MESSAGES
+ MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
+ STRERROR (errno));
+#endif
+ break;
+ }
+ /* call appropriate connection handler if necessary */
+ if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
+ con->read_handler (con);
+ if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
+ con->write_handler (con);
+ if (con->socket_fd != -1)
+ con->idle_handler (con);
+ }
+#ifdef HAVE_POLL_H
+ else
+ {
+ /* use poll */
+ memset(&mp, 0, sizeof (struct MHD_Pollfd));
+ MHD_connection_get_pollfd(con, &mp);
+ memset(&p, 0, sizeof (struct pollfd));
+ p.fd = mp.fd;
+ if (mp.events & MHD_POLL_ACTION_IN)
+ p.events |= POLLIN;
+ if (mp.events & MHD_POLL_ACTION_OUT)
+ p.events |= POLLOUT;
+ /* in case we are missing the SIGALRM, keep going after
+ at most 1s */
+ if (poll (&p, 1, 1000) < 0) {
+ if (errno == EINTR)
+ continue;
+#if HAVE_MESSAGES
+ MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
+ STRERROR (errno));
+#endif
+ break;
+ }
+ if ( (con->socket_fd != -1) &&
+ (0 != (p.revents & POLLIN)) )
+ con->read_handler (con);
+ if ( (con->socket_fd != -1) &&
+ (0 != (p.revents & POLLOUT)) )
+ con->write_handler (con);
+ if (con->socket_fd != -1)
+ con->idle_handler (con);
+ if ( (con->socket_fd != -1) &&
+ (0 != (p.revents & (POLLERR | POLLHUP))) )
+ MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
+ }
+#endif
+ }
+ if (con->socket_fd != -1)
+ {
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (con->daemon,
+ "Processing thread terminating, closing connection\n");
+#endif
+#endif
+ MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
+ }
+ return NULL;
+}
+
+/**
+ * Callback for receiving data from the socket.
+ *
+ * @param conn the MHD connection structure
+ * @param other where to write received data to
+ * @param i maximum size of other (in bytes)
+ * @return number of bytes actually received
+ */
+static ssize_t
+recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
+{
+ if (connection->socket_fd == -1)
+ return -1;
+ if (0 != (connection->daemon->options & MHD_USE_SSL))
+ return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
+ else
+ return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
+}
+
+/**
+ * Callback for writing data to the socket.
+ *
+ * @param conn the MHD connection structure
+ * @param other data to write
+ * @param i number of bytes to write
+ * @return actual number of bytes written
+ */
+static ssize_t
+send_param_adapter (struct MHD_Connection *connection,
+ const void *other, size_t i)
+{
+ if (connection->socket_fd == -1)
+ return -1;
+ if (0 != (connection->daemon->options & MHD_USE_SSL))
+ return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
+ else
+ return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
+}
+
+/**
+ * Accept an incoming connection and create the MHD_Connection object for
+ * it. This function also enforces policy by way of checking with the
+ * accept policy callback.
+ */
+static int
+MHD_accept_connection (struct MHD_Daemon *daemon)
+{
+ struct MHD_Connection *connection;
+#if HAVE_INET6
+ struct sockaddr_in6 addrstorage;
+#else
+ struct sockaddr_in addrstorage;
+#endif
+ struct sockaddr *addr = (struct sockaddr *) &addrstorage;
+ socklen_t addrlen;
+ int s;
+ int res_thread_create;
+#if OSX
+ static int on = 1;
+#endif
+
+ addrlen = sizeof (addrstorage);
+ memset (addr, 0, sizeof (addrstorage));
+
+ s = ACCEPT (daemon->socket_fd, addr, &addrlen);
+ if ((s == -1) || (addrlen <= 0))
+ {
+#if HAVE_MESSAGES
+ /* This could be a common occurance with multiple worker threads */
+ if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
+ MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
+#endif
+ if (s != -1)
+ {
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ /* just in case */
+ }
+ return MHD_NO;
+ }
+#ifndef WINDOWS
+ if ( (s >= FD_SETSIZE) &&
+ (0 == (daemon->options & MHD_USE_POLL)) )
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
+ s,
+ FD_SETSIZE);
+#endif
+ CLOSE (s);
+ return MHD_NO;
+ }
+#endif
+
+
+#if HAVE_MESSAGES
+#if DEBUG_CONNECT
+ MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
+#endif
+#endif
+ if ((daemon->max_connections == 0)
+ || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
+ {
+ /* above connection limit - reject */
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Server reached connection limit (closing inbound connection)\n");
+#endif
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ return MHD_NO;
+ }
+
+ /* apply connection acceptance policy if present */
+ if ((daemon->apc != NULL)
+ && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
+ {
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Connection rejected, closing connection\n");
+#endif
+#endif
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ MHD_ip_limit_del (daemon, addr, addrlen);
+ return MHD_YES;
+ }
+#if OSX
+#ifdef SOL_SOCKET
+#ifdef SO_NOSIGPIPE
+ setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
+#endif
+#endif
+#endif
+ connection = malloc (sizeof (struct MHD_Connection));
+ if (NULL == connection)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
+#endif
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ MHD_ip_limit_del (daemon, addr, addrlen);
+ return MHD_NO;
+ }
+ memset (connection, 0, sizeof (struct MHD_Connection));
+ connection->pool = NULL;
+ connection->addr = malloc (addrlen);
+ if (connection->addr == NULL)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
+#endif
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ MHD_ip_limit_del (daemon, addr, addrlen);
+ free (connection);
+ return MHD_NO;
+ }
+ memcpy (connection->addr, addr, addrlen);
+ connection->addr_len = addrlen;
+ connection->socket_fd = s;
+ connection->daemon = daemon;
+ connection->last_activity = time (NULL);
+
+ /* set default connection handlers */
+ MHD_set_http_calbacks (connection);
+ connection->recv_cls = &recv_param_adapter;
+ connection->send_cls = &send_param_adapter;
+#if HTTPS_SUPPORT
+ if (0 != (daemon->options & MHD_USE_SSL))
+ {
+ connection->recv_cls = &recv_tls_adapter;
+ connection->send_cls = &send_tls_adapter;
+ connection->state = MHD_TLS_CONNECTION_INIT;
+ MHD_set_https_calbacks (connection);
+ MHD__gnutls_init (&connection->tls_session, GNUTLS_SERVER);
+ MHD__gnutls_priority_set (connection->tls_session,
+ connection->daemon->priority_cache);
+ switch (connection->daemon->cred_type)
+ {
+ /* set needed credentials for certificate authentication. */
+ case MHD_GNUTLS_CRD_CERTIFICATE:
+ MHD__gnutls_credentials_set (connection->tls_session,
+ MHD_GNUTLS_CRD_CERTIFICATE,
+ connection->daemon->x509_cred);
+ break;
+ default:
+#if HAVE_MESSAGES
+ MHD_DLOG (connection->daemon,
+ "Failed to setup TLS credentials: unknown credential type %d\n",
+ connection->daemon->cred_type);
+#endif
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ MHD_ip_limit_del (daemon, addr, addrlen);
+ free (connection->addr);
+ free (connection);
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
+#if HAVE_MESSAGES
+ "Unknown credential type"
+#else
+ NULL
+#endif
+ );
+ return MHD_NO;
+ }
+ MHD__gnutls_transport_set_ptr (connection->tls_session,
+ (MHD_gnutls_transport_ptr_t) connection);
+ MHD__gnutls_transport_set_pull_function (connection->tls_session,
+ (MHD_gtls_pull_func) &
+ recv_param_adapter);
+ MHD__gnutls_transport_set_push_function (connection->tls_session,
+ (MHD_gtls_push_func) &
+ send_param_adapter);
+ }
+#endif
+
+ /* attempt to create handler thread */
+ if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ res_thread_create = pthread_create (&connection->pid, NULL,
+ &MHD_handle_connection, connection);
+ if (res_thread_create != 0)
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to create a thread: %s\n",
+ STRERROR (res_thread_create));
+#endif
+ SHUTDOWN (s, SHUT_RDWR);
+ CLOSE (s);
+ MHD_ip_limit_del (daemon, addr, addrlen);
+ free (connection->addr);
+ free (connection);
+ return MHD_NO;
+ }
+ }
+ connection->next = daemon->connections;
+ daemon->connections = connection;
+ daemon->max_connections--;
+ return MHD_YES;
+}
+
+/**
+ * Free resources associated with all closed connections.
+ * (destroy responses, free buffers, etc.). A connection
+ * is known to be closed if the socket_fd is -1.
+ */
+static void
+MHD_cleanup_connections (struct MHD_Daemon *daemon)
+{
+ struct MHD_Connection *pos;
+ struct MHD_Connection *prev;
+ void *unused;
+ int rc;
+
+ pos = daemon->connections;
+ prev = NULL;
+ while (pos != NULL)
+ {
+ if ((pos->socket_fd == -1) ||
+ (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
+ (daemon->shutdown) && (pos->socket_fd != -1))))
+ {
+ if (prev == NULL)
+ daemon->connections = pos->next;
+ else
+ prev->next = pos->next;
+ if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ pthread_kill (pos->pid, SIGALRM);
+ if (0 != (rc = pthread_join (pos->pid, &unused)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to join a thread: %s\n",
+ STRERROR (rc));
+#endif
+ abort();
+ }
+ }
+ MHD_destroy_response (pos->response);
+ MHD_pool_destroy (pos->pool);
+#if HTTPS_SUPPORT
+ if (pos->tls_session != NULL)
+ MHD__gnutls_deinit (pos->tls_session);
+#endif
+ MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
+ free (pos->addr);
+ free (pos);
+ daemon->max_connections++;
+ if (prev == NULL)
+ pos = daemon->connections;
+ else
+ pos = prev->next;
+ continue;
+ }
+ prev = pos;
+ pos = pos->next;
+ }
+}
+
+/**
+ * Obtain timeout value for select for this daemon
+ * (only needed if connection timeout is used). The
+ * returned value is how long select should at most
+ * block, not the timeout value set for connections.
+ *
+ * @param timeout set to the timeout (in milliseconds)
+ * @return MHD_YES on success, MHD_NO if timeouts are
+ * not used (or no connections exist that would
+ * necessiate the use of a timeout right now).
+ */
+int
+MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
+{
+ time_t earliest_deadline;
+ time_t now;
+ struct MHD_Connection *pos;
+ unsigned int dto;
+
+ dto = daemon->connection_timeout;
+ if (0 == dto)
+ return MHD_NO;
+ pos = daemon->connections;
+ if (pos == NULL)
+ return MHD_NO; /* no connections */
+ now = time (NULL);
+ /* start with conservative estimate */
+ earliest_deadline = now + dto;
+ while (pos != NULL)
+ {
+ if (earliest_deadline > pos->last_activity + dto)
+ earliest_deadline = pos->last_activity + dto;
+ pos = pos->next;
+ }
+ if (earliest_deadline < now)
+ *timeout = 0;
+ else
+ *timeout = (earliest_deadline - now);
+ return MHD_YES;
+}
+
+/**
+ * Main select call.
+ *
+ * @param may_block YES if blocking, NO if non-blocking
+ * @return MHD_NO on serious errors, MHD_YES on success
+ */
+static int
+MHD_select (struct MHD_Daemon *daemon, int may_block)
+{
+ struct MHD_Connection *pos;
+ int num_ready;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ struct timeval timeout;
+ unsigned long long ltimeout;
+ int ds;
+ time_t now;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ if (daemon->shutdown == MHD_YES)
+ return MHD_NO;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ max = 0;
+
+ if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ /* single-threaded, go over everything */
+ if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
+ return MHD_NO;
+
+ /* If we're at the connection limit, no need to
+ accept new connections. */
+ if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
+ FD_CLR(daemon->socket_fd, &rs);
+ }
+ else
+ {
+ /* accept only, have one thread per connection */
+ max = daemon->socket_fd;
+ if (max == -1)
+ return MHD_NO;
+ FD_SET (max, &rs);
+ }
+
+ /* in case we are missing the SIGALRM, keep going after
+ at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 1;
+ if (may_block == MHD_NO)
+ {
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 0;
+ }
+ else
+ {
+ /* ltimeout is in ms */
+ if ( (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) &&
+ (ltimeout < 1000) )
+ {
+ timeout.tv_usec = ltimeout * 1000;
+ timeout.tv_sec = 0;
+ }
+ }
+ num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
+
+ if (daemon->shutdown == MHD_YES)
+ return MHD_NO;
+ if (num_ready < 0)
+ {
+ if (errno == EINTR)
+ return MHD_YES;
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
+#endif
+ return MHD_NO;
+ }
+ ds = daemon->socket_fd;
+ if (ds == -1)
+ return MHD_YES;
+
+ /* select connection thread handling type */
+ if (FD_ISSET (ds, &rs))
+ MHD_accept_connection (daemon);
+ if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ {
+ /* do not have a thread per connection, process all connections now */
+ now = time (NULL);
+ pos = daemon->connections;
+ while (pos != NULL)
+ {
+ ds = pos->socket_fd;
+ if (ds != -1)
+ {
+ /* TODO call con->read handler */
+ if (FD_ISSET (ds, &rs))
+ pos->read_handler (pos);
+ if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
+ pos->write_handler (pos);
+ if (pos->socket_fd != -1)
+ pos->idle_handler (pos);
+ }
+ pos = pos->next;
+ }
+ }
+ return MHD_YES;
+}
+
+/**
+ * Poll for new connection. Used only with THREAD_PER_CONNECTION
+ */
+static int
+MHD_poll (struct MHD_Daemon *daemon)
+{
+#ifdef HAVE_POLL_H
+ struct pollfd p;
+
+ if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+ return MHD_NO;
+ p.fd = daemon->socket_fd;
+ p.events = POLLIN;
+ p.revents = 0;
+
+ if (poll(&p, 1, 0) < 0) {
+ if (errno == EINTR)
+ return MHD_YES;
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
+#endif
+ return MHD_NO;
+ }
+ /* handle shutdown cases */
+ if (daemon->shutdown == MHD_YES)
+ return MHD_NO;
+ if (daemon->socket_fd < 0)
+ return MHD_YES;
+ if (0 != (p.revents & POLLIN))
+ MHD_accept_connection (daemon);
+ return MHD_YES;
+#else
+ return MHD_NO;
+#endif
+}
+
+/**
+ * Run webserver operations (without blocking unless
+ * in client callbacks). This method should be called
+ * by clients in combination with MHD_get_fdset
+ * if the client-controlled select method is used.
+ *
+ * @return MHD_YES on success, MHD_NO if this
+ * daemon was not started with the right
+ * options for this call.
+ */
+int
+MHD_run (struct MHD_Daemon *daemon)
+{
+ if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
+ & MHD_USE_THREAD_PER_CONNECTION))
+ || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
+ return MHD_NO;
+ MHD_select (daemon, MHD_NO);
+ MHD_cleanup_connections (daemon);
+ return MHD_YES;
+}
+
+/**
+ * Thread that runs the select loop until the daemon
+ * is explicitly shut down.
+ */
+static void *
+MHD_select_thread (void *cls)
+{
+ struct MHD_Daemon *daemon = cls;
+ while (daemon->shutdown == MHD_NO)
+ {
+ if ((daemon->options & MHD_USE_POLL) == 0)
+ MHD_select (daemon, MHD_YES);
+ else
+ MHD_poll(daemon);
+ MHD_cleanup_connections (daemon);
+ }
+ return NULL;
+}
+
+/**
+ * Start a webserver on the given port.
+ *
+ * @param port port to bind to
+ * @param apc callback to call to check which clients
+ * will be allowed to connect
+ * @param apc_cls extra argument to apc
+ * @param dh default handler for all URIs
+ * @param dh_cls extra argument to dh
+ * @return NULL on error, handle to daemon on success
+ */
+struct MHD_Daemon *
+MHD_start_daemon (unsigned int options,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls,
+ MHD_AccessHandlerCallback dh, void *dh_cls, ...)
+{
+ struct MHD_Daemon *ret;
+ va_list ap;
+
+ va_start (ap, dh_cls);
+ ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
+ va_end (ap);
+ return ret;
+}
+
+
+typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
+
+
+/**
+ * Parse a list of options given as varargs.
+ *
+ * @param daemon the daemon to initialize
+ * @param ap the options
+ * @return MHD_YES on success, MHD_NO on error
+ */
+static int
+parse_options_va (struct MHD_Daemon *daemon,
+ const struct sockaddr **servaddr,
+ va_list ap);
+
+
+/**
+ * Parse a list of options given as varargs.
+ *
+ * @param daemon the daemon to initialize
+ * @param ... the options
+ * @return MHD_YES on success, MHD_NO on error
+ */
+static int
+parse_options (struct MHD_Daemon *daemon,
+ const struct sockaddr **servaddr,
+ ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start (ap, servaddr);
+ ret = parse_options_va (daemon, servaddr, ap);
+ va_end (ap);
+ return ret;
+}
+
+
+/**
+ * Parse a list of options given as varargs.
+ *
+ * @param daemon the daemon to initialize
+ * @param ap the options
+ * @return MHD_YES on success, MHD_NO on error
+ */
+static int
+parse_options_va (struct MHD_Daemon *daemon,
+ const struct sockaddr **servaddr,
+ va_list ap)
+{
+ enum MHD_OPTION opt;
+ struct MHD_OptionItem *oa;
+ unsigned int i;
+
+ while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
+ {
+ switch (opt)
+ {
+ case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
+ daemon->pool_size = va_arg (ap, size_t);
+ break;
+ case MHD_OPTION_CONNECTION_LIMIT:
+ daemon->max_connections = va_arg (ap, unsigned int);
+ break;
+ case MHD_OPTION_CONNECTION_TIMEOUT:
+ daemon->connection_timeout = va_arg (ap, unsigned int);
+ break;
+ case MHD_OPTION_NOTIFY_COMPLETED:
+ daemon->notify_completed =
+ va_arg (ap, MHD_RequestCompletedCallback);
+ daemon->notify_completed_cls = va_arg (ap, void *);
+ break;
+ case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
+ daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
+ break;
+ case MHD_OPTION_SOCK_ADDR:
+ *servaddr = va_arg (ap, const struct sockaddr *);
+ break;
+ case MHD_OPTION_URI_LOG_CALLBACK:
+ daemon->uri_log_callback =
+ va_arg (ap, LogCallback);
+ daemon->uri_log_callback_cls = va_arg (ap, void *);
+ break;
+ case MHD_OPTION_THREAD_POOL_SIZE:
+ daemon->worker_pool_size = va_arg (ap, unsigned int);
+ break;
+#if HTTPS_SUPPORT
+ case MHD_OPTION_PROTOCOL_VERSION:
+ _set_priority (&daemon->priority_cache->protocol,
+ va_arg (ap, const int *));
+ break;
+ case MHD_OPTION_HTTPS_MEM_KEY:
+ daemon->https_mem_key = va_arg (ap, const char *);
+ break;
+ case MHD_OPTION_HTTPS_MEM_CERT:
+ daemon->https_mem_cert = va_arg (ap, const char *);
+ break;
+ case MHD_OPTION_CIPHER_ALGORITHM:
+ _set_priority (&daemon->priority_cache->cipher,
+ va_arg (ap, const int *));
+ break;
+#endif
+ case MHD_OPTION_EXTERNAL_LOGGER:
+#if HAVE_MESSAGES
+ daemon->custom_error_log =
+ va_arg (ap, VfprintfFunctionPointerType);
+ daemon->custom_error_log_cls = va_arg (ap, void *);
+#else
+ va_arg (ap, VfprintfFunctionPointerType);
+ va_arg (ap, void *);
+#endif
+ break;
+ case MHD_OPTION_ARRAY:
+ oa = va_arg (ap, struct MHD_OptionItem*);
+ i = 0;
+ while (MHD_OPTION_END != (opt = oa[i].option))
+ {
+ switch (opt)
+ {
+ /* all options taking 'size_t' */
+ case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
+ if (MHD_YES != parse_options (daemon,
+ servaddr,
+ opt,
+ (size_t) oa[i].value,
+ MHD_OPTION_END))
+ return MHD_NO;
+ break;
+ /* all options taking 'unsigned int' */
+ case MHD_OPTION_CONNECTION_LIMIT:
+ case MHD_OPTION_CONNECTION_TIMEOUT:
+ case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
+ case MHD_OPTION_THREAD_POOL_SIZE:
+ if (MHD_YES != parse_options (daemon,
+ servaddr,
+ opt,
+ (unsigned int) oa[i].value,
+ MHD_OPTION_END))
+ return MHD_NO;
+ break;
+ /* all options taking 'int' or 'enum' */
+ case MHD_OPTION_CRED_TYPE:
+ if (MHD_YES != parse_options (daemon,
+ servaddr,
+ opt,
+ (int) oa[i].value,
+ MHD_OPTION_END))
+ return MHD_NO;
+ break;
+ /* all options taking one pointer */
+ case MHD_OPTION_SOCK_ADDR:
+ case MHD_OPTION_HTTPS_MEM_KEY:
+ case MHD_OPTION_HTTPS_MEM_CERT:
+ case MHD_OPTION_PROTOCOL_VERSION:
+ case MHD_OPTION_CIPHER_ALGORITHM:
+ case MHD_OPTION_ARRAY:
+ if (MHD_YES != parse_options (daemon,
+ servaddr,
+ opt,
+ oa[i].ptr_value,
+ MHD_OPTION_END))
+ return MHD_NO;
+ break;
+ /* all options taking two pointers */
+ case MHD_OPTION_NOTIFY_COMPLETED:
+ case MHD_OPTION_URI_LOG_CALLBACK:
+ case MHD_OPTION_EXTERNAL_LOGGER:
+ if (MHD_YES != parse_options (daemon,
+ servaddr,
+ opt,
+ (void *) oa[i].value,
+ oa[i].ptr_value,
+ MHD_OPTION_END))
+ return MHD_NO;
+ break;
+
+ default:
+ return MHD_NO;
+ }
+ i++;
+ }
+ break;
+ default:
+#if HAVE_MESSAGES
+ if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
+ (opt <= MHD_OPTION_CIPHER_ALGORITHM))
+ {
+ FPRINTF (stderr,
+ "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
+ opt);
+ }
+ else
+ {
+ FPRINTF (stderr,
+ "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
+ opt);
+ }
+#endif
+ return MHD_NO;
+ }
+ }
+ return MHD_YES;
+}
+
+
+/**
+ * Start a webserver on the given port.
+ *
+ * @param port port to bind to
+ * @param apc callback to call to check which clients
+ * will be allowed to connect
+ * @param apc_cls extra argument to apc
+ * @param dh default handler for all URIs
+ * @param dh_cls extra argument to dh
+ * @return NULL on error, handle to daemon on success
+ */
+struct MHD_Daemon *
+MHD_start_daemon_va (unsigned int options,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls,
+ MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
+{
+ const int on = 1;
+ struct MHD_Daemon *retVal;
+ int socket_fd;
+ struct sockaddr_in servaddr4;
+#if HAVE_INET6
+ struct sockaddr_in6 servaddr6;
+#endif
+ const struct sockaddr *servaddr = NULL;
+ socklen_t addrlen;
+ unsigned int i;
+ int res_thread_create;
+
+ if ((port == 0) || (dh == NULL))
+ return NULL;
+ retVal = malloc (sizeof (struct MHD_Daemon));
+ if (retVal == NULL)
+ return NULL;
+ memset (retVal, 0, sizeof (struct MHD_Daemon));
+ retVal->options = (enum MHD_OPTION)options;
+ retVal->port = port;
+ retVal->apc = apc;
+ retVal->apc_cls = apc_cls;
+ retVal->default_handler = dh;
+ retVal->default_handler_cls = dh_cls;
+ retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
+ retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
+ retVal->connection_timeout = 0; /* no timeout */
+#if HAVE_MESSAGES
+ retVal->custom_error_log =
+ (void (*)(void *, const char *, va_list)) &vfprintf;
+ retVal->custom_error_log_cls = stderr;
+#endif
+#if HTTPS_SUPPORT
+ if (options & MHD_USE_SSL)
+ {
+ /* lock MHD_gnutls_global mutex since it uses reference counting */
+ if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
+#endif
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
+ }
+ if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
+#endif
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
+ }
+ /* set default priorities */
+ MHD_tls_set_default_priority (&retVal->priority_cache, "", NULL);
+ retVal->cred_type = MHD_GNUTLS_CRD_CERTIFICATE;
+ }
+#endif
+
+ if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
+ {
+ free (retVal);
+ return NULL;
+ }
+
+ /* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
+ if ( (0 != (options & MHD_USE_POLL)) &&
+ (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) ) {
+#if HAVE_MESSAGES
+ fprintf (stderr,
+ "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
+#endif
+ free (retVal);
+ return NULL;
+ }
+
+ /* Thread pooling currently works only with internal select thread model */
+ if ((0 == (options & MHD_USE_SELECT_INTERNALLY))
+ && (retVal->worker_pool_size > 0))
+ {
+#if HAVE_MESSAGES
+ fprintf (stderr,
+ "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
+#endif
+ free (retVal);
+ return NULL;
+ }
+
+#ifdef __SYMBIAN32__
+ if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
+ {
+#if HAVE_MESSAGES
+ fprintf (stderr,
+ "Threaded operations are not supported on Symbian.\n");
+#endif
+ free (retVal);
+ return NULL;
+ }
+#endif
+ if ((options & MHD_USE_IPv6) != 0)
+#if HAVE_INET6
+ socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
+#else
+ {
+#if HAVE_MESSAGES
+ fprintf (stderr, "AF_INET6 not supported\n");
+#endif
+ free (retVal);
+ return NULL;
+ }
+#endif
+ else
+ socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
+ if (socket_fd == -1)
+ {
+#if HAVE_MESSAGES
+ if ((options & MHD_USE_DEBUG) != 0)
+ FPRINTF (stderr, "Call to socket failed: %s\n", STRERROR (errno));
+#endif
+ free (retVal);
+ return NULL;
+ }
+#ifndef WINDOWS
+ if ( (socket_fd >= FD_SETSIZE) &&
+ (0 == (options & MHD_USE_POLL)) )
+ {
+#if HAVE_MESSAGES
+ if ((options & MHD_USE_DEBUG) != 0)
+ FPRINTF (stderr,
+ "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
+ socket_fd,
+ FD_SETSIZE);
+#endif
+ CLOSE (socket_fd);
+ free (retVal);
+ return NULL;
+ }
+#endif
+ if ((SETSOCKOPT (socket_fd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
+ {
+#if HAVE_MESSAGES
+ FPRINTF (stderr, "setsockopt failed: %s\n", STRERROR (errno));
+#endif
+ }
+
+ /* check for user supplied sockaddr */
+#if HAVE_INET6
+ if ((options & MHD_USE_IPv6) != 0)
+ addrlen = sizeof (struct sockaddr_in6);
+ else
+#endif
+ addrlen = sizeof (struct sockaddr_in);
+ if (NULL == servaddr)
+ {
+#if HAVE_INET6
+ if ((options & MHD_USE_IPv6) != 0)
+ {
+ memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
+ servaddr6.sin6_family = AF_INET6;
+ servaddr6.sin6_port = htons (port);
+ servaddr = (struct sockaddr *) &servaddr6;
+ }
+ else
+#endif
+ {
+ memset (&servaddr4, 0, sizeof (struct sockaddr_in));
+ servaddr4.sin_family = AF_INET;
+ servaddr4.sin_port = htons (port);
+ servaddr = (struct sockaddr *) &servaddr4;
+ }
+ }
+ retVal->socket_fd = socket_fd;
+ if (BIND (socket_fd, servaddr, addrlen) == -1)
+ {
+#if HAVE_MESSAGES
+ if ((options & MHD_USE_DEBUG) != 0)
+ FPRINTF (stderr,
+ "Failed to bind to port %u: %s\n", port, STRERROR (errno));
+#endif
+ CLOSE (socket_fd);
+ free (retVal);
+ return NULL;
+ }
+
+ if (LISTEN (socket_fd, 20) < 0)
+ {
+#if HAVE_MESSAGES
+ if ((options & MHD_USE_DEBUG) != 0)
+ FPRINTF (stderr,
+ "Failed to listen for connections: %s\n", STRERROR (errno));
+#endif
+ CLOSE (socket_fd);
+ free (retVal);
+ return NULL;
+ }
+
+ if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (retVal,
+ "MHD failed to initialize IP connection limit mutex\n");
+#endif
+ CLOSE (socket_fd);
+ free (retVal);
+ return NULL;
+ }
+
+#if HTTPS_SUPPORT
+ /* initialize HTTPS daemon certificate aspects & send / recv functions */
+ if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (retVal, "Failed to initialize TLS support\n");
+#endif
+ CLOSE (socket_fd);
+ pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
+ free (retVal);
+ return NULL;
+ }
+#endif
+ if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
+ ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
+ (0 == retVal->worker_pool_size)) ) &&
+ (0 != (res_thread_create =
+ pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal))))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (retVal,
+ "Failed to create listen thread: %s\n", STRERROR (res_thread_create));
+#endif
+ pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
+ free (retVal);
+ CLOSE (socket_fd);
+ return NULL;
+ }
+ else if (retVal->worker_pool_size > 0)
+ {
+#ifndef MINGW
+ int sk_flags;
+#else
+ unsigned long sk_flags;
+#endif
+
+ /* Coarse-grained count of connections per thread (note error
+ * due to integer division). Also keep track of how many
+ * connections are leftover after an equal split. */
+ unsigned int conns_per_thread = retVal->max_connections
+ / retVal->worker_pool_size;
+ unsigned int leftover_conns = retVal->max_connections
+ % retVal->worker_pool_size;
+
+ i = 0; /* we need this in case fcntl or malloc fails */
+
+ /* Accept must be non-blocking. Multiple children may wake up
+ * to handle a new connection, but only one will win the race.
+ * The others must immediately return. */
+#ifndef MINGW
+ sk_flags = fcntl (socket_fd, F_GETFL);
+ if (sk_flags < 0)
+ goto thread_failed;
+ if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
+ goto thread_failed;
+#else
+ sk_flags = 1;
+#if HAVE_PLIBC_FD
+ if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
+ SOCKET_ERROR)
+#else
+ if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
+#endif // PLIBC_FD
+ goto thread_failed;
+#endif // MINGW
+
+ /* Allocate memory for pooled objects */
+ retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
+ * retVal->worker_pool_size);
+ if (NULL == retVal->worker_pool)
+ goto thread_failed;
+
+ /* Start the workers in the pool */
+ for (i = 0; i < retVal->worker_pool_size; ++i)
+ {
+ /* Create copy of the Daemon object for each worker */
+ struct MHD_Daemon *d = &retVal->worker_pool[i];
+ memcpy (d, retVal, sizeof (struct MHD_Daemon));
+
+ /* Adjust pooling params for worker daemons; note that memcpy()
+ has already copied MHD_USE_SELECT_INTERNALLY thread model into
+ the worker threads. */
+ d->master = retVal;
+ d->worker_pool_size = 0;
+ d->worker_pool = NULL;
+
+ /* Divide available connections evenly amongst the threads.
+ * Thread indexes in [0, leftover_conns) each get one of the
+ * leftover connections. */
+ d->max_connections = conns_per_thread;
+ if (i < leftover_conns)
+ ++d->max_connections;
+
+ /* Spawn the worker thread */
+ if (0 != (res_thread_create = pthread_create (&d->pid, NULL, &MHD_select_thread, d)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (retVal,
+ "Failed to create pool thread: %s\n",
+ STRERROR (res_thread_create));
+#endif
+ /* Free memory for this worker; cleanup below handles
+ * all previously-created workers. */
+ goto thread_failed;
+ }
+ }
+ }
+ return retVal;
+
+thread_failed:
+ /* If no worker threads created, then shut down normally. Calling
+ MHD_stop_daemon (as we do below) doesn't work here since it
+ assumes a 0-sized thread pool means we had been in the default
+ MHD_USE_SELECT_INTERNALLY mode. */
+ if (i == 0)
+ {
+ CLOSE (socket_fd);
+ pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
+ if (NULL != retVal->worker_pool)
+ free (retVal->worker_pool);
+ free (retVal);
+ return NULL;
+ }
+
+ /* Shutdown worker threads we've already created. Pretend
+ as though we had fully initialized our daemon, but
+ with a smaller number of threads than had been
+ requested. */
+ retVal->worker_pool_size = i - 1;
+ MHD_stop_daemon (retVal);
+ return NULL;
+}
+
+/**
+ * Close all connections for the daemon
+ */
+static void
+MHD_close_connections (struct MHD_Daemon *daemon)
+{
+ while (daemon->connections != NULL)
+ {
+ if (-1 != daemon->connections->socket_fd)
+ {
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
+#endif
+#endif
+ MHD_connection_close (daemon->connections,
+ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
+ }
+ MHD_cleanup_connections (daemon);
+ }
+}
+
+/**
+ * Shutdown an http daemon
+ */
+void
+MHD_stop_daemon (struct MHD_Daemon *daemon)
+{
+ void *unused;
+ int fd;
+ unsigned int i;
+ int rc;
+
+ if (daemon == NULL)
+ return;
+ daemon->shutdown = MHD_YES;
+ fd = daemon->socket_fd;
+ daemon->socket_fd = -1;
+
+ /* Prepare workers for shutdown */
+ for (i = 0; i < daemon->worker_pool_size; ++i)
+ {
+ daemon->worker_pool[i].shutdown = MHD_YES;
+ daemon->worker_pool[i].socket_fd = -1;
+ }
+
+#if OSX
+ /* without this, either (thread pool = 0) threads would get stuck or
+ * CLOSE would get stuck if attempted before (thread pool > 0)
+ * threads have ended */
+ SHUTDOWN (fd, SHUT_RDWR);
+#else
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
+#endif
+#endif
+ CLOSE (fd);
+#endif
+
+ /* Signal workers to stop and clean them up */
+ for (i = 0; i < daemon->worker_pool_size; ++i)
+ pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
+ for (i = 0; i < daemon->worker_pool_size; ++i)
+ {
+ if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to join a thread: %s\n",
+ STRERROR (rc));
+#endif
+ abort();
+ }
+ MHD_close_connections (&daemon->worker_pool[i]);
+ }
+ free (daemon->worker_pool);
+
+ if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
+ ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
+ && (0 == daemon->worker_pool_size)))
+ {
+ pthread_kill (daemon->pid, SIGALRM);
+ if (0 != (rc = pthread_join (daemon->pid, &unused)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to join a thread: %s\n",
+ STRERROR (rc));
+#endif
+ abort();
+ }
+ }
+ MHD_close_connections (daemon);
+
+#if OSX
+#if DEBUG_CLOSE
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
+#endif
+#endif
+ CLOSE (fd);
+#endif
+
+ /* TLS clean up */
+#if HTTPS_SUPPORT
+ if (daemon->options & MHD_USE_SSL)
+ {
+ MHD__gnutls_priority_deinit (daemon->priority_cache);
+ if (daemon->x509_cred)
+ MHD__gnutls_certificate_free_credentials (daemon->x509_cred);
+ /* lock MHD_gnutls_global mutex since it uses reference counting */
+ if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
+#endif
+ abort();
+ }
+ if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
+#endif
+ abort();
+ }
+ }
+#endif
+ pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
+ free (daemon);
+}
+
+/**
+ * Obtain information about the given daemon
+ * (not fully implemented!).
+ *
+ * @param daemon what daemon to get information about
+ * @param infoType what information is desired?
+ * @param ... depends on infoType
+ * @return NULL if this information is not available
+ * (or if the infoType is unknown)
+ */
+const union MHD_DaemonInfo *
+MHD_get_daemon_info (struct MHD_Daemon *daemon,
+ enum MHD_DaemonInfoType infoType, ...)
+{
+ switch (infoType)
+ {
+ case MHD_DAEMON_INFO_LISTEN_FD:
+ return (const union MHD_DaemonInfo *) &daemon->socket_fd;
+ default:
+ return NULL;
+ };
+}
+
+/**
+ * Sets the global error handler to a different implementation. "cb"
+ * will only be called in the case of typically fatal, serious
+ * internal consistency issues. These issues should only arise in the
+ * case of serious memory corruption or similar problems with the
+ * architecture. While "cb" is allowed to return and MHD will then
+ * try to continue, this is never safe.
+ *
+ * The default implementation that is used if no panic function is set
+ * simply calls "abort". Alternative implementations might call
+ * "exit" or other similar functions.
+ *
+ * @param cb new error handler
+ * @param cls passed to error handler
+ */
+void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
+{
+ mhd_panic = cb;
+ mhd_panic_cls = cls;
+}
+
+/**
+ * Obtain the version of this library
+ *
+ * @return static version string, e.g. "0.4.1"
+ */
+const char *
+MHD_get_version (void)
+{
+ return PACKAGE_VERSION;
+}
+
+#ifndef WINDOWS
+
+static struct sigaction sig;
+
+static struct sigaction old;
+
+static void
+sigalrmHandler (int sig)
+{
+}
+#endif
+
+#ifdef __GNUC__
+#define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
+#define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
+#else // !__GNUC__
+#define ATTRIBUTE_CONSTRUCTOR
+#define ATTRIBUTE_DESTRUCTOR
+#endif // __GNUC__
+
+/**
+ * Initialize the signal handler for SIGALRM
+ * and do other setup work.
+ */
+void ATTRIBUTE_CONSTRUCTOR MHD_init ()
+{
+ mhd_panic = &mhd_panic_std;
+ mhd_panic_cls = NULL;
+
+#ifndef WINDOWS
+ /* make sure SIGALRM does not kill us */
+ memset (&sig, 0, sizeof (struct sigaction));
+ memset (&old, 0, sizeof (struct sigaction));
+ sig.sa_flags = SA_NODEFER;
+ sig.sa_handler = &sigalrmHandler;
+ sigaction (SIGALRM, &sig, &old);
+#else
+ plibc_init ("GNU", "libmicrohttpd");
+#endif
+#if HTTPS_SUPPORT
+ MHD__gnutls_global_init ();
+ if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
+ abort();
+#endif
+}
+
+void ATTRIBUTE_DESTRUCTOR MHD_fini ()
+{
+#if HTTPS_SUPPORT
+ MHD__gnutls_global_deinit ();
+ if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
+#endif
+#ifndef WINDOWS
+ sigaction (SIGALRM, &old, &sig);
+#else
+ plibc_shutdown ();
+#endif
+}
+
+/* end of daemon.c */
diff --git a/lib/libmicrohttpd/src/daemon/daemon_test.c b/lib/libmicrohttpd/src/daemon/daemon_test.c
new file mode 100644
index 0000000000..6340a2e73b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/daemon_test.c
@@ -0,0 +1,168 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest.c
+ * @brief Testcase for libmicrohttpd starts and stops
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "platform.h"
+#include "microhttpd.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+
+static int
+testStartError ()
+{
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_DEBUG, 0, NULL, NULL, NULL, NULL);
+ if (d != NULL)
+ return 1;
+ return 0;
+}
+
+static int
+apc_nothing (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return MHD_NO;
+}
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return MHD_YES;
+}
+
+static int
+ahc_nothing (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ return MHD_NO;
+}
+
+static int
+testStartStop ()
+{
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080,
+ &apc_nothing,
+ NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 2;
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testExternalRun ()
+{
+ struct MHD_Daemon *d;
+ fd_set rs;
+ int maxfd;
+ int i;
+
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1081,
+ &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+ if (d == NULL)
+ return 4;
+ i = 0;
+ while (i < 15)
+ {
+ maxfd = 0;
+ FD_ZERO (&rs);
+ if (MHD_YES != MHD_get_fdset (d, &rs, &rs, &rs, &maxfd))
+ {
+ MHD_stop_daemon (d);
+ return 256;
+ }
+ if (MHD_run (d) == MHD_NO)
+ {
+ MHD_stop_daemon (d);
+ return 8;
+ }
+ i++;
+ }
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testThread ()
+{
+ struct MHD_Daemon *d;
+ d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY,
+ 1082,
+ &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+ if (d == NULL)
+ return 16;
+ if (MHD_run (d) != MHD_NO)
+ return 32;
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithread ()
+{
+ struct MHD_Daemon *d;
+ d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
+ 1083,
+ &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+ if (d == NULL)
+ return 64;
+ if (MHD_run (d) != MHD_NO)
+ return 128;
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ int errorCount = 0;
+ errorCount += testStartError ();
+ errorCount += testStartStop ();
+ errorCount += testExternalRun ();
+ errorCount += testThread ();
+ errorCount += testMultithread ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/Makefile.am b/lib/libmicrohttpd/src/daemon/https/Makefile.am
new file mode 100644
index 0000000000..8b4c1aa15c
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/Makefile.am
@@ -0,0 +1,3 @@
+EXTRA_DIST = gnutls.h
+
+SUBDIRS = minitasn1 lgl x509 tls .
diff --git a/lib/libmicrohttpd/src/daemon/https/Makefile.in b/lib/libmicrohttpd/src/daemon/https/Makefile.in
new file mode 100644
index 0000000000..069f1c6e87
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/Makefile.in
@@ -0,0 +1,575 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/daemon/https
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = gnutls.h
+SUBDIRS = minitasn1 lgl x509 tls .
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/daemon/https/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/daemon/https/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/https/gnutls.h b/lib/libmicrohttpd/src/daemon/https/gnutls.h
new file mode 100644
index 0000000000..f2f6f06925
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/gnutls.h
@@ -0,0 +1,697 @@
+/* -*- c -*-
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+/* This file contains the types and prototypes for all the
+ * high level functionality of gnutls main library. For the
+ * extra functionality (which is under the GNU GPL license) check
+ * the gnutls/extra.h header. The openssl compatibility layer is
+ * in gnutls/openssl.h.
+ *
+ * The low level cipher functionality is in libgcrypt. Check
+ * gcrypt.h
+ */
+
+#ifndef GNUTLS_H
+#define GNUTLS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * List of key exchange algorithms.
+ * Note that not all listed algorithms are necessarily
+ * supported by all builds of MHD.
+ */
+enum MHD_GNUTLS_KeyExchangeAlgorithm
+{
+ MHD_GNUTLS_KX_UNKNOWN = 0,
+ MHD_GNUTLS_KX_RSA = 1,
+};
+
+/**
+ * Server credentials type (note that not all types
+ * maybe supported by all MHD builds).
+ */
+enum MHD_GNUTLS_CredentialsType
+{
+ /**
+ * We have a x.509 certificate.
+ */
+ MHD_GNUTLS_CRD_CERTIFICATE = 1,
+
+};
+
+/**
+ * Enumeration of possible cryptographic
+ * hash functions (for MAC and Digest operations).
+ * Note that not all listed algorithms are necessarily
+ * supported by all builds of MHD.
+ */
+enum MHD_GNUTLS_HashAlgorithm
+{
+ MHD_GNUTLS_MAC_UNKNOWN = 0,
+ MHD_GNUTLS_MAC_NULL = 1,
+ MHD_GNUTLS_MAC_MD5,
+ MHD_GNUTLS_MAC_SHA1,
+ MHD_GNUTLS_MAC_SHA256
+};
+
+/**
+ * List of compression methods.
+ * Note that not all listed algorithms are necessarily
+ * supported by all builds of MHD.
+ */
+enum MHD_GNUTLS_CompressionMethod
+{
+ MHD_GNUTLS_COMP_UNKNOWN = 0,
+
+ /**
+ * No compression.
+ */
+ MHD_GNUTLS_COMP_NULL = 1,
+
+};
+/**
+ * Types of certificates.
+ */
+enum MHD_GNUTLS_CertificateType
+{
+ MHD_GNUTLS_CRT_UNKNOWN = 0,
+ MHD_GNUTLS_CRT_X509 = 1
+};
+
+/**
+ * List of public key algorithms.
+ * Note that not all listed algorithms are necessarily
+ * supported by all builds of MHD.
+ */
+enum MHD_GNUTLS_PublicKeyAlgorithm
+{
+ MHD_GNUTLS_PK_UNKNOWN = 0,
+ MHD_GNUTLS_PK_RSA = 1,
+ MHD_GNUTLS_KX_RSA_EXPORT
+};
+
+
+
+#define LIBGNUTLS_VERSION "2.2.3"
+
+/* Get size_t. */
+#include <stddef.h>
+
+#define GNUTLS_CIPHER_RIJNDAEL_128_CBC GNUTLS_CIPHER_AES_128_CBC
+#define GNUTLS_CIPHER_RIJNDAEL_256_CBC GNUTLS_CIPHER_AES_256_CBC
+#define GNUTLS_CIPHER_RIJNDAEL_CBC GNUTLS_CIPHER_AES_128_CBC
+#define GNUTLS_CIPHER_ARCFOUR GNUTLS_CIPHER_ARCFOUR_128
+
+#define GNUTLS_MAX_SESSION_ID 32
+#define TLS_MASTER_SIZE 48
+#define TLS_RANDOM_SIZE 32
+
+#include "platform.h"
+#include "microhttpd.h"
+
+typedef enum
+{
+ GNUTLS_PARAMS_RSA_EXPORT = 1,
+ GNUTLS_PARAMS_DH
+} MHD_gnutls_params_type_t;
+
+ /* exported for other gnutls headers. This is the maximum number of
+ * algorithms (ciphers, kx or macs).
+ */
+#define GNUTLS_MAX_ALGORITHM_NUM 16
+#define GNUTLS_COMP_ZLIB GNUTLS_COMP_DEFLATE
+
+typedef enum
+{
+ GNUTLS_SERVER = 1,
+ GNUTLS_CLIENT
+} MHD_gnutls_connection_end_t;
+
+typedef enum
+{
+ GNUTLS_AL_WARNING = 1,
+ GNUTLS_AL_FATAL
+} MHD_gnutls_alert_level_t;
+
+typedef enum
+{
+ GNUTLS_A_CLOSE_NOTIFY,
+ GNUTLS_A_UNEXPECTED_MESSAGE = 10,
+ GNUTLS_A_BAD_RECORD_MAC = 20,
+ GNUTLS_A_DECRYPTION_FAILED,
+ GNUTLS_A_RECORD_OVERFLOW,
+ GNUTLS_A_DECOMPRESSION_FAILURE = 30,
+ GNUTLS_A_HANDSHAKE_FAILURE = 40,
+ GNUTLS_A_SSL3_NO_CERTIFICATE = 41,
+ GNUTLS_A_BAD_CERTIFICATE = 42,
+ GNUTLS_A_UNSUPPORTED_CERTIFICATE,
+ GNUTLS_A_CERTIFICATE_REVOKED,
+ GNUTLS_A_CERTIFICATE_EXPIRED,
+ GNUTLS_A_CERTIFICATE_UNKNOWN,
+ GNUTLS_A_ILLEGAL_PARAMETER,
+ GNUTLS_A_UNKNOWN_CA,
+ GNUTLS_A_ACCESS_DENIED,
+ GNUTLS_A_DECODE_ERROR = 50,
+ GNUTLS_A_DECRYPT_ERROR,
+ GNUTLS_A_EXPORT_RESTRICTION = 60,
+ GNUTLS_A_PROTOCOL_VERSION = 70,
+ GNUTLS_A_INSUFFICIENT_SECURITY,
+ GNUTLS_A_INTERNAL_ERROR = 80,
+ GNUTLS_A_USER_CANCELED = 90,
+ GNUTLS_A_NO_RENEGOTIATION = 100,
+ GNUTLS_A_UNSUPPORTED_EXTENSION = 110,
+ GNUTLS_A_CERTIFICATE_UNOBTAINABLE = 111,
+ GNUTLS_A_UNRECOGNIZED_NAME = 112,
+ GNUTLS_A_UNKNOWN_PSK_IDENTITY = 115,
+} MHD_gnutls_alert_description_t;
+
+typedef enum
+{ GNUTLS_HANDSHAKE_HELLO_REQUEST = 0,
+ GNUTLS_HANDSHAKE_CLIENT_HELLO = 1,
+ GNUTLS_HANDSHAKE_SERVER_HELLO = 2,
+ GNUTLS_HANDSHAKE_CERTIFICATE_PKT = 11,
+ GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE = 12,
+ GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST = 13,
+ GNUTLS_HANDSHAKE_SERVER_HELLO_DONE = 14,
+ GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY = 15,
+ GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE = 16,
+ GNUTLS_HANDSHAKE_FINISHED = 20,
+ GNUTLS_HANDSHAKE_SUPPLEMENTAL = 23
+} MHD_gnutls_handshake_description_t;
+
+typedef enum
+{
+ GNUTLS_CERT_INVALID = 2, /* will be set if the certificate
+ * was not verified.
+ */
+ GNUTLS_CERT_REVOKED = 32, /* in X.509 this will be set only if CRLs are checked
+ */
+
+ /* Those are extra information about the verification
+ * process. Will be set only if the certificate was
+ * not verified.
+ */
+ GNUTLS_CERT_SIGNER_NOT_FOUND = 64,
+ GNUTLS_CERT_SIGNER_NOT_CA = 128,
+ GNUTLS_CERT_INSECURE_ALGORITHM = 256
+} MHD_gnutls_certificate_status_t;
+
+typedef enum
+{
+ GNUTLS_CERT_IGNORE,
+ GNUTLS_CERT_REQUEST = 1,
+ GNUTLS_CERT_REQUIRE
+} MHD_gnutls_certificate_request_t;
+
+typedef enum
+{
+ GNUTLS_SHUT_RDWR = 0,
+ GNUTLS_SHUT_WR = 1
+} MHD_gnutls_close_request_t;
+
+typedef enum
+{
+ GNUTLS_X509_FMT_DER,
+ GNUTLS_X509_FMT_PEM
+} MHD_gnutls_x509_crt_fmt_t;
+
+typedef enum
+{
+ GNUTLS_SIGN_UNKNOWN = 0,
+ GNUTLS_SIGN_RSA_SHA1 = 1,
+ GNUTLS_SIGN_DSA_SHA1,
+ GNUTLS_SIGN_RSA_MD5,
+ GNUTLS_SIGN_RSA_MD2,
+ GNUTLS_SIGN_RSA_RMD160,
+ GNUTLS_SIGN_RSA_SHA256,
+ GNUTLS_SIGN_RSA_SHA384,
+ GNUTLS_SIGN_RSA_SHA512
+} MHD_gnutls_sign_algorithm_t;
+
+/* If you want to change this, then also change the define in
+ * MHD_gnutls_int.h, and recompile.
+ */
+typedef void *MHD_gnutls_transport_ptr_t;
+
+struct MHD_gtls_session_int;
+typedef struct MHD_gtls_session_int *MHD_gtls_session_t;
+
+struct MHD_gtls_dh_params_int;
+typedef struct MHD_gtls_dh_params_int *MHD_gtls_dh_params_t;
+
+struct MHD_gtls_x509_privkey_int; /* XXX ugly. */
+typedef struct MHD_gtls_x509_privkey_int *MHD_gtls_rsa_params_t; /* XXX ugly. */
+
+struct MHD_gtls_priority_st;
+typedef struct MHD_gtls_priority_st *MHD_gnutls_priority_t;
+
+typedef struct
+{
+ unsigned char *data;
+ unsigned int size;
+} MHD_gnutls_datum_t;
+
+
+typedef struct MHD_gnutls_params_st
+{
+ MHD_gnutls_params_type_t type;
+ union params
+ {
+ MHD_gtls_dh_params_t dh;
+ MHD_gtls_rsa_params_t rsa_export;
+ } params;
+ int deinit;
+} MHD_gnutls_params_st;
+
+typedef int MHD_gnutls_params_function (MHD_gtls_session_t,
+ MHD_gnutls_params_type_t,
+ MHD_gnutls_params_st *);
+
+/* internal functions */
+int MHD__gnutls_global_init (void);
+void MHD__gnutls_global_deinit (void);
+
+int MHD__gnutls_init (MHD_gtls_session_t * session,
+ MHD_gnutls_connection_end_t con_end);
+void MHD__gnutls_deinit (MHD_gtls_session_t session);
+
+int MHD__gnutls_bye (MHD_gtls_session_t session,
+ MHD_gnutls_close_request_t how);
+int MHD__gnutls_handshake (MHD_gtls_session_t session);
+int MHD__gnutls_rehandshake (MHD_gtls_session_t session);
+
+MHD_gnutls_alert_description_t MHD_gnutls_alert_get (MHD_gtls_session_t
+ session);
+int MHD__gnutls_alert_send (MHD_gtls_session_t session,
+ MHD_gnutls_alert_level_t level,
+ MHD_gnutls_alert_description_t desc);
+int MHD__gnutls_alert_send_appropriate (MHD_gtls_session_t session, int err);
+const char *MHD__gnutls_alert_get_name (MHD_gnutls_alert_description_t alert);
+
+size_t MHD__gnutls_cipher_get_key_size (enum MHD_GNUTLS_CipherAlgorithm
+ algorithm);
+
+ /* error functions */
+int MHD_gtls_error_is_fatal (int error);
+int MHD_gtls_error_to_alert (int err, int *level);
+void MHD_gtls_perror (int error);
+const char *MHD_gtls_strerror (int error);
+
+/*
+ * Record layer functions.
+ */
+ssize_t MHD__gnutls_record_send (MHD_gtls_session_t session,
+ const void *data, size_t sizeofdata);
+ssize_t MHD__gnutls_record_recv (MHD_gtls_session_t session, void *data,
+ size_t sizeofdata);
+
+ /* provides extra compatibility */
+int MHD__gnutls_record_get_direction (MHD_gtls_session_t session);
+
+/*
+ * TLS Extensions
+ */
+typedef enum
+{
+ GNUTLS_NAME_DNS = 1
+} MHD_gnutls_server_name_type_t;
+
+ /* Supplemental data, RFC 4680. */
+typedef enum
+{
+ GNUTLS_SUPPLEMENTAL_USER_MAPPING_DATA = 0
+} MHD_gnutls_supplemental_data_format_type_t;
+
+
+int MHD_tls_set_default_priority (MHD_gnutls_priority_t *,
+ const char *priority, const char **err_pos);
+void MHD__gnutls_priority_deinit (MHD_gnutls_priority_t);
+
+int MHD__gnutls_priority_set (MHD_gtls_session_t session,
+ MHD_gnutls_priority_t);
+int MHD__gnutls_priority_set_direct (MHD_gtls_session_t session,
+ const char *priority,
+ const char **err_pos);
+
+/* get the currently used protocol version */
+enum MHD_GNUTLS_Protocol
+MHD__gnutls_protocol_get_version (MHD_gtls_session_t session);
+
+typedef
+ int (*MHD_gnutls_handshake_post_client_hello_func) (MHD_gtls_session_t);
+void MHD__gnutls_handshake_set_max_packet_length (MHD_gtls_session_t
+ session, size_t max);
+
+/*
+ * Functions for setting/clearing credentials
+ */
+void MHD__gnutls_credentials_clear (MHD_gtls_session_t session);
+
+/*
+ * cred is a structure defined by the kx algorithm
+ */
+int MHD__gnutls_credentials_set (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CredentialsType type,
+ void *cred);
+
+/* Credential structures - used in MHD__gnutls_credentials_set(); */
+struct MHD_gtls_certificate_credentials_st;
+typedef struct MHD_gtls_certificate_credentials_st
+ *MHD_gtls_cert_credentials_t;
+typedef MHD_gtls_cert_credentials_t MHD_gtls_cert_server_credentials;
+typedef MHD_gtls_cert_credentials_t MHD_gtls_cert_client_credentials;
+
+void MHD__gnutls_certificate_free_credentials (MHD_gtls_cert_credentials_t
+ sc);
+int
+MHD__gnutls_certificate_allocate_credentials (MHD_gtls_cert_credentials_t
+ * res);
+
+void MHD__gnutls_certificate_free_keys (MHD_gtls_cert_credentials_t sc);
+void MHD__gnutls_certificate_free_cas (MHD_gtls_cert_credentials_t sc);
+void MHD__gnutls_certificate_free_ca_names (MHD_gtls_cert_credentials_t sc);
+
+int MHD__gnutls_certificate_set_x509_key_mem (MHD_gtls_cert_credentials_t
+ res,
+ const MHD_gnutls_datum_t *
+ CERT,
+ const MHD_gnutls_datum_t *
+ KEY,
+ MHD_gnutls_x509_crt_fmt_t type);
+
+void MHD__gnutls_certificate_send_x509_rdn_sequence (MHD_gtls_session_t
+ session, int status);
+
+/*
+ * New functions to allow setting already parsed X.509 stuff.
+ */
+struct MHD_gtls_x509_privkey_int;
+typedef struct MHD_gtls_x509_privkey_int *MHD_gnutls_x509_privkey_t;
+
+struct MHD_gnutls_x509_crl_int;
+typedef struct MHD_gnutls_x509_crl_int *MHD_gnutls_x509_crl_t;
+
+struct MHD_gnutls_x509_crt_int;
+typedef struct MHD_gnutls_x509_crt_int *MHD_gnutls_x509_crt_t;
+
+/* global state functions
+ */
+
+
+typedef void *(*MHD_gnutls_alloc_function) (size_t);
+typedef int (*MHD_gnutls_is_secure_function) (const void *);
+typedef void *(*MHD_gnutls_calloc_function) (size_t, size_t);
+typedef void (*MHD_gnutls_free_function) (void *);
+typedef void *(*MHD_gnutls_realloc_function) (void *, size_t);
+
+/* For use in callbacks */
+extern MHD_gnutls_alloc_function MHD_gnutls_malloc;
+extern MHD_gnutls_alloc_function MHD_gnutls_secure_malloc;
+extern MHD_gnutls_realloc_function MHD_gnutls_realloc;
+extern MHD_gnutls_calloc_function MHD_gnutls_calloc;
+extern MHD_gnutls_free_function MHD_gnutls_free;
+
+typedef void (*MHD_gnutls_log_func) (int, const char *);
+void MHD_gtls_global_set_log_function (MHD_gnutls_log_func log_func);
+void MHD_gtls_global_set_log_level (int level);
+
+/*
+ * Diffie Hellman parameter handling.
+ */
+int MHD__gnutls_dh_params_init (MHD_gtls_dh_params_t * dh_params);
+void MHD__gnutls_dh_params_deinit (MHD_gtls_dh_params_t dh_params);
+
+
+/* RSA params */
+int MHD__gnutls_rsa_params_init (MHD_gtls_rsa_params_t * rsa_params);
+void MHD__gnutls_rsa_params_deinit (MHD_gtls_rsa_params_t rsa_params);
+int MHD__gnutls_rsa_params_generate2 (MHD_gtls_rsa_params_t params,
+ unsigned int bits);
+
+
+/*
+ * Session stuff
+ */
+typedef ssize_t (*MHD_gtls_pull_func) (MHD_gnutls_transport_ptr_t, void *,
+ size_t);
+typedef ssize_t (*MHD_gtls_push_func) (MHD_gnutls_transport_ptr_t,
+ const void *, size_t);
+void MHD__gnutls_transport_set_ptr (MHD_gtls_session_t session,
+ MHD_gnutls_transport_ptr_t ptr);
+void MHD__gnutls_transport_set_lowat (MHD_gtls_session_t session, int num);
+
+
+void MHD__gnutls_transport_set_push_function (MHD_gtls_session_t session,
+ MHD_gtls_push_func push_func);
+void MHD__gnutls_transport_set_pull_function (MHD_gtls_session_t session,
+ MHD_gtls_pull_func pull_func);
+
+typedef enum MHD_gnutls_x509_subject_alt_name_t
+{
+ GNUTLS_SAN_DNSNAME = 1,
+ GNUTLS_SAN_RFC822NAME,
+ GNUTLS_SAN_URI,
+ GNUTLS_SAN_IPADDRESS,
+ GNUTLS_SAN_OTHERNAME,
+ GNUTLS_SAN_DN,
+ /* The following are "virtual" subject alternative name types, in
+ that they are represented by an otherName value and an OID.
+ Used by MHD_gnutls_x509_crt_get_subject_alt_othername_oid(). */
+ GNUTLS_SAN_OTHERNAME_XMPP = 1000
+} MHD_gnutls_x509_subject_alt_name_t;
+
+typedef struct MHD_gnutls_retr_st
+{
+ enum MHD_GNUTLS_CertificateType type;
+ union cert
+ {
+ MHD_gnutls_x509_crt_t *x509;
+ } cert;
+ unsigned int ncerts;
+
+ union key
+ {
+ MHD_gnutls_x509_privkey_t x509;
+ } key;
+
+ unsigned int deinit_all; /* if non zero all keys will be deinited */
+} MHD_gnutls_retr_st;
+
+typedef int
+MHD_gnutls_certificate_client_retrieve_function (MHD_gtls_session_t,
+ const MHD_gnutls_datum_t
+ * req_ca_rdn, int nreqs,
+ const enum
+ MHD_GNUTLS_PublicKeyAlgorithm
+ *pk_algos,
+ int pk_algos_length,
+ MHD_gnutls_retr_st *);
+
+typedef int
+MHD_gnutls_certificate_server_retrieve_function (MHD_gtls_session_t,
+ MHD_gnutls_retr_st *);
+
+ /*
+ * Functions that allow auth_info_t structures handling
+ */
+enum MHD_GNUTLS_CredentialsType MHD_gtls_auth_get_type (MHD_gtls_session_t
+ session);
+ /*
+ * DH
+ */
+void MHD__gnutls_dh_set_prime_bits (MHD_gtls_session_t session,
+ unsigned int bits);
+
+ /* External signing callback. Experimental. */
+typedef int (*MHD_gnutls_sign_func) (MHD_gtls_session_t session,
+ void *userdata,
+ enum MHD_GNUTLS_CertificateType
+ cert_type,
+ const MHD_gnutls_datum_t * cert,
+ const MHD_gnutls_datum_t * hash,
+ MHD_gnutls_datum_t * signature);
+
+ /* key_usage will be an OR of the following values: */
+ /* when the key is to be used for signing: */
+#define GNUTLS_KEY_DIGITAL_SIGNATURE 128
+#define GNUTLS_KEY_NON_REPUDIATION 64
+ /* when the key is to be used for encryption: */
+#define GNUTLS_KEY_KEY_ENCIPHERMENT 32
+#define GNUTLS_KEY_DATA_ENCIPHERMENT 16
+#define GNUTLS_KEY_KEY_AGREEMENT 8
+#define GNUTLS_KEY_KEY_CERT_SIGN 4
+#define GNUTLS_KEY_CRL_SIGN 2
+#define GNUTLS_KEY_ENCIPHER_ONLY 1
+#define GNUTLS_KEY_DECIPHER_ONLY 32768
+
+ /*
+ * Error codes. TLS alert mapping shown in comments.
+ */
+#define GNUTLS_E_SUCCESS 0
+#define GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM -3
+#define GNUTLS_E_UNKNOWN_CIPHER_TYPE -6
+#define GNUTLS_E_LARGE_PACKET -7
+#define GNUTLS_E_UNSUPPORTED_VERSION_PACKET -8 /* GNUTLS_A_PROTOCOL_VERSION */
+#define GNUTLS_E_UNEXPECTED_PACKET_LENGTH -9 /* GNUTLS_A_RECORD_OVERFLOW */
+#define GNUTLS_E_INVALID_SESSION -10
+#define GNUTLS_E_FATAL_ALERT_RECEIVED -12
+#define GNUTLS_E_UNEXPECTED_PACKET -15 /* GNUTLS_A_UNEXPECTED_MESSAGE */
+#define GNUTLS_E_WARNING_ALERT_RECEIVED -16
+#define GNUTLS_E_ERROR_IN_FINISHED_PACKET -18
+#define GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET -19
+#define GNUTLS_E_UNKNOWN_CIPHER_SUITE -21 /* GNUTLS_A_HANDSHAKE_FAILURE */
+#define GNUTLS_E_UNWANTED_ALGORITHM -22
+#define GNUTLS_E_MPI_SCAN_FAILED -23
+#define GNUTLS_E_DECRYPTION_FAILED -24 /* GNUTLS_A_DECRYPTION_FAILED, GNUTLS_A_BAD_RECORD_MAC */
+#define GNUTLS_E_MEMORY_ERROR -25
+#define GNUTLS_E_DECOMPRESSION_FAILED -26 /* GNUTLS_A_DECOMPRESSION_FAILURE */
+#define GNUTLS_E_COMPRESSION_FAILED -27
+#define GNUTLS_E_AGAIN -28
+#define GNUTLS_E_EXPIRED -29
+#define GNUTLS_E_DB_ERROR -30
+#define GNUTLS_E_SRP_PWD_ERROR -31
+#define GNUTLS_E_INSUFFICIENT_CREDENTIALS -32
+#define GNUTLS_E_INSUFICIENT_CREDENTIALS GNUTLS_E_INSUFFICIENT_CREDENTIALS /* for backwards compatibility only */
+#define GNUTLS_E_INSUFFICIENT_CRED GNUTLS_E_INSUFFICIENT_CREDENTIALS
+#define GNUTLS_E_INSUFICIENT_CRED GNUTLS_E_INSUFFICIENT_CREDENTIALS /* for backwards compatibility only */
+
+#define GNUTLS_E_HASH_FAILED -33
+#define GNUTLS_E_BASE64_DECODING_ERROR -34
+
+#define GNUTLS_E_MPI_PRINT_FAILED -35
+#define GNUTLS_E_REHANDSHAKE -37 /* GNUTLS_A_NO_RENEGOTIATION */
+#define GNUTLS_E_GOT_APPLICATION_DATA -38
+#define GNUTLS_E_RECORD_LIMIT_REACHED -39
+#define GNUTLS_E_ENCRYPTION_FAILED -40
+
+#define GNUTLS_E_PK_ENCRYPTION_FAILED -44
+#define GNUTLS_E_PK_DECRYPTION_FAILED -45
+#define GNUTLS_E_PK_SIGN_FAILED -46
+#define GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION -47
+#define GNUTLS_E_KEY_USAGE_VIOLATION -48
+#define GNUTLS_E_NO_CERTIFICATE_FOUND -49 /* GNUTLS_A_BAD_CERTIFICATE */
+#define GNUTLS_E_INVALID_REQUEST -50
+#define GNUTLS_E_SHORT_MEMORY_BUFFER -51
+#define GNUTLS_E_INTERRUPTED -52
+#define GNUTLS_E_PUSH_ERROR -53
+#define GNUTLS_E_PULL_ERROR -54
+#define GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER -55 /* GNUTLS_A_ILLEGAL_PARAMETER */
+#define GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE -56
+#define GNUTLS_E_PKCS1_WRONG_PAD -57
+#define GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION -58
+#define GNUTLS_E_INTERNAL_ERROR -59
+#define GNUTLS_E_DH_PRIME_UNACCEPTABLE -63
+#define GNUTLS_E_FILE_ERROR -64
+#define GNUTLS_E_TOO_MANY_EMPTY_PACKETS -78
+#define GNUTLS_E_UNKNOWN_PK_ALGORITHM -80
+
+
+ /* returned if libextra functionality was requested but
+ * MHD_gnutls_global_init_extra() was not called.
+ */
+#define GNUTLS_E_INIT_LIBEXTRA -82
+#define GNUTLS_E_LIBRARY_VERSION_MISMATCH -83
+
+
+ /* returned if you need to generate temporary RSA
+ * parameters. These are needed for export cipher suites.
+ */
+#define GNUTLS_E_NO_TEMPORARY_RSA_PARAMS -84
+
+#define GNUTLS_E_LZO_INIT_FAILED -85
+#define GNUTLS_E_NO_COMPRESSION_ALGORITHMS -86
+#define GNUTLS_E_NO_CIPHER_SUITES -87
+
+#define GNUTLS_E_PK_SIG_VERIFY_FAILED -89
+
+#define GNUTLS_E_ILLEGAL_SRP_USERNAME -90
+#define GNUTLS_E_SRP_PWD_PARSING_ERROR -91
+#define GNUTLS_E_NO_TEMPORARY_DH_PARAMS -93
+
+ /* For certificate and key stuff
+ */
+#define GNUTLS_E_ASN1_ELEMENT_NOT_FOUND -67
+#define GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND -68
+#define GNUTLS_E_ASN1_DER_ERROR -69
+#define GNUTLS_E_ASN1_VALUE_NOT_FOUND -70
+#define GNUTLS_E_ASN1_GENERIC_ERROR -71
+#define GNUTLS_E_ASN1_VALUE_NOT_VALID -72
+#define GNUTLS_E_ASN1_TAG_ERROR -73
+#define GNUTLS_E_ASN1_TAG_IMPLICIT -74
+#define GNUTLS_E_ASN1_TYPE_ANY_ERROR -75
+#define GNUTLS_E_ASN1_SYNTAX_ERROR -76
+#define GNUTLS_E_ASN1_DER_OVERFLOW -77
+#define GNUTLS_E_CERTIFICATE_ERROR -43
+#define GNUTLS_E_X509_CERTIFICATE_ERROR GNUTLS_E_CERTIFICATE_ERROR
+#define GNUTLS_E_CERTIFICATE_KEY_MISMATCH -60
+#define GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE -61 /* GNUTLS_A_UNSUPPORTED_CERTIFICATE */
+#define GNUTLS_E_X509_UNKNOWN_SAN -62
+#define GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE -95
+#define GNUTLS_E_UNKNOWN_HASH_ALGORITHM -96
+#define GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE -97
+#define GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE -98
+#define GNUTLS_E_INVALID_PASSWORD -99
+#define GNUTLS_E_MAC_VERIFY_FAILED -100 /* for PKCS #12 MAC */
+#define GNUTLS_E_CONSTRAINT_ERROR -101
+
+#define GNUTLS_E_WARNING_IA_IPHF_RECEIVED -102
+#define GNUTLS_E_WARNING_IA_FPHF_RECEIVED -103
+
+#define GNUTLS_E_IA_VERIFY_FAILED -104
+
+#define GNUTLS_E_UNKNOWN_ALGORITHM -105
+
+#define GNUTLS_E_BASE64_ENCODING_ERROR -201
+#define GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY -202 /* obsolete */
+#define GNUTLS_E_INCOMPATIBLE_CRYPTO_LIBRARY -202
+#define GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY -203
+
+#define GNUTLS_E_X509_UNSUPPORTED_OID -205
+
+#define GNUTLS_E_RANDOM_FAILED -206
+#define GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR -207
+
+
+#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
+
+#define GNUTLS_E_APPLICATION_ERROR_MAX -65000
+#define GNUTLS_E_APPLICATION_ERROR_MIN -65500
+
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNUTLS_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/lgl/Makefile.am b/lib/libmicrohttpd/src/daemon/https/lgl/Makefile.am
new file mode 100644
index 0000000000..5659d5c5ef
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/lgl/Makefile.am
@@ -0,0 +1,13 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include @LIBGCRYPT_CFLAGS@
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+noinst_LTLIBRARIES = liblgl.la
+
+liblgl_la_SOURCES = \
+ gc-libgcrypt.c \
+ gc.h
+liblgl_la_LIBADD = @LIBGCRYPT_LIBS@
diff --git a/lib/libmicrohttpd/src/daemon/https/lgl/Makefile.in b/lib/libmicrohttpd/src/daemon/https/lgl/Makefile.in
new file mode 100644
index 0000000000..ea0602fda9
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/lgl/Makefile.in
@@ -0,0 +1,495 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/daemon/https/lgl
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+liblgl_la_DEPENDENCIES =
+am_liblgl_la_OBJECTS = gc-libgcrypt.lo
+liblgl_la_OBJECTS = $(am_liblgl_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(liblgl_la_SOURCES)
+DIST_SOURCES = $(liblgl_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include @LIBGCRYPT_CFLAGS@
+
+@USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage
+noinst_LTLIBRARIES = liblgl.la
+liblgl_la_SOURCES = \
+ gc-libgcrypt.c \
+ gc.h
+
+liblgl_la_LIBADD = @LIBGCRYPT_LIBS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/daemon/https/lgl/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/daemon/https/lgl/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+liblgl.la: $(liblgl_la_OBJECTS) $(liblgl_la_DEPENDENCIES)
+ $(LINK) $(liblgl_la_OBJECTS) $(liblgl_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gc-libgcrypt.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/https/lgl/gc-libgcrypt.c b/lib/libmicrohttpd/src/daemon/https/lgl/gc-libgcrypt.c
new file mode 100644
index 0000000000..0995740584
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/lgl/gc-libgcrypt.c
@@ -0,0 +1,407 @@
+/* gc-libgcrypt.c --- Crypto wrappers around Libgcrypt for GC.
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Simon Josefsson
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1, or (at your
+ * option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/* Note: This file is only built if GC uses Libgcrypt. */
+
+#include "MHD_config.h"
+
+/* Get prototype. */
+#include "gc.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* Get libgcrypt API. */
+#include <gcrypt.h>
+
+#include <assert.h>
+
+/* Initialization. */
+
+Gc_rc
+MHD_gc_init (void)
+{
+ gcry_error_t err;
+
+ err = gcry_control (GCRYCTL_ANY_INITIALIZATION_P);
+ if (err == GPG_ERR_NO_ERROR)
+ {
+ if (gcry_check_version (GCRYPT_VERSION) == NULL)
+ return GC_INIT_ERROR;
+
+ err = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
+ if (err != GPG_ERR_NO_ERROR)
+ return GC_INIT_ERROR;
+ }
+ return GC_OK;
+}
+
+void
+MHD_gc_done (void)
+{
+ return;
+}
+
+#ifdef GNULIB_GC_RANDOM
+
+/* Randomness. */
+
+Gc_rc
+MHD_gc_nonce (char *data, size_t datalen)
+{
+ gcry_create_nonce ((unsigned char *) data, datalen);
+ return GC_OK;
+}
+
+Gc_rc
+MHD_gc_pseudo_random (char *data, size_t datalen)
+{
+ gcry_randomize ((unsigned char *) data, datalen, GCRY_STRONG_RANDOM);
+ return GC_OK;
+}
+
+#endif
+
+/* Memory allocation. */
+
+/* Ciphers. */
+
+Gc_rc
+MHD_gc_cipher_open (Gc_cipher alg,
+ Gc_cipher_mode mode, MHD_gc_cipher_handle * outhandle)
+{
+ int gcryalg, gcrymode;
+ gcry_error_t err;
+
+ switch (alg)
+ {
+ case GC_AES128:
+ gcryalg = GCRY_CIPHER_RIJNDAEL;
+ break;
+
+ case GC_AES192:
+ gcryalg = GCRY_CIPHER_RIJNDAEL;
+ break;
+
+ case GC_AES256:
+ gcryalg = GCRY_CIPHER_RIJNDAEL256;
+ break;
+
+ case GC_3DES:
+ gcryalg = GCRY_CIPHER_3DES;
+ break;
+
+ case GC_DES:
+ gcryalg = GCRY_CIPHER_DES;
+ break;
+
+ case GC_ARCFOUR128:
+ case GC_ARCFOUR40:
+ gcryalg = GCRY_CIPHER_ARCFOUR;
+ break;
+
+ case GC_ARCTWO40:
+ gcryalg = GCRY_CIPHER_RFC2268_40;
+ break;
+
+ default:
+ return GC_INVALID_CIPHER;
+ }
+
+ switch (mode)
+ {
+ case GC_ECB:
+ gcrymode = GCRY_CIPHER_MODE_ECB;
+ break;
+
+ case GC_CBC:
+ gcrymode = GCRY_CIPHER_MODE_CBC;
+ break;
+
+ case GC_STREAM:
+ gcrymode = GCRY_CIPHER_MODE_STREAM;
+ break;
+
+ default:
+ return GC_INVALID_CIPHER;
+ }
+
+ err =
+ gcry_cipher_open ((gcry_cipher_hd_t *) outhandle, gcryalg, gcrymode, 0);
+ if (gcry_err_code (err))
+ return GC_INVALID_CIPHER;
+
+ return GC_OK;
+}
+
+Gc_rc
+MHD_gc_cipher_setkey (MHD_gc_cipher_handle handle, size_t keylen,
+ const char *key)
+{
+ gcry_error_t err;
+
+ err = gcry_cipher_setkey ((gcry_cipher_hd_t) handle, key, keylen);
+ if (gcry_err_code (err))
+ return GC_INVALID_CIPHER;
+
+ return GC_OK;
+}
+
+Gc_rc
+MHD_gc_cipher_setiv (MHD_gc_cipher_handle handle, size_t ivlen,
+ const char *iv)
+{
+ gcry_error_t err;
+
+ err = gcry_cipher_setiv ((gcry_cipher_hd_t) handle, iv, ivlen);
+ if (gcry_err_code (err))
+ return GC_INVALID_CIPHER;
+
+ return GC_OK;
+}
+
+Gc_rc
+MHD_gc_cipher_encrypt_inline (MHD_gc_cipher_handle handle, size_t len,
+ char *data)
+{
+ if (gcry_cipher_encrypt ((gcry_cipher_hd_t) handle, data, len, NULL, len) !=
+ 0)
+ return GC_INVALID_CIPHER;
+
+ return GC_OK;
+}
+
+Gc_rc
+MHD_gc_cipher_decrypt_inline (MHD_gc_cipher_handle handle, size_t len,
+ char *data)
+{
+ if (gcry_cipher_decrypt ((gcry_cipher_hd_t) handle, data, len, NULL, len) !=
+ 0)
+ return GC_INVALID_CIPHER;
+
+ return GC_OK;
+}
+
+Gc_rc
+MHD_gc_cipher_close (MHD_gc_cipher_handle handle)
+{
+ gcry_cipher_close (handle);
+
+ return GC_OK;
+}
+
+/* Hashes. */
+
+typedef struct _MHD_gc_hash_ctx
+{
+ Gc_hash alg;
+ Gc_hash_mode mode;
+ gcry_md_hd_t gch;
+} _MHD_gc_hash_ctx;
+
+Gc_rc
+MHD_gc_hash_open (Gc_hash hash, Gc_hash_mode mode,
+ MHD_gc_hash_handle * outhandle)
+{
+ _MHD_gc_hash_ctx *ctx;
+ int gcryalg = 0, gcrymode = 0;
+ gcry_error_t err;
+ Gc_rc rc = GC_OK;
+
+ ctx = calloc (sizeof (*ctx), 1);
+ if (!ctx)
+ return GC_MALLOC_ERROR;
+
+ ctx->alg = hash;
+ ctx->mode = mode;
+
+ switch (hash)
+ {
+ case GC_MD2:
+ gcryalg = GCRY_MD_NONE;
+ break;
+
+ case GC_MD4:
+ gcryalg = GCRY_MD_MD4;
+ break;
+
+ case GC_MD5:
+ gcryalg = GCRY_MD_MD5;
+ break;
+
+ case GC_SHA1:
+ gcryalg = GCRY_MD_SHA1;
+ break;
+
+ case GC_SHA256:
+ gcryalg = GCRY_MD_SHA256;
+ break;
+
+ case GC_SHA384:
+ gcryalg = GCRY_MD_SHA384;
+ break;
+
+ case GC_SHA512:
+ gcryalg = GCRY_MD_SHA512;
+ break;
+
+ case GC_RMD160:
+ gcryalg = GCRY_MD_RMD160;
+ break;
+
+ default:
+ rc = GC_INVALID_HASH;
+ }
+
+ switch (mode)
+ {
+ case 0:
+ gcrymode = 0;
+ break;
+
+ case GC_HMAC:
+ gcrymode = GCRY_MD_FLAG_HMAC;
+ break;
+
+ default:
+ rc = GC_INVALID_HASH;
+ }
+
+ if (rc == GC_OK && gcryalg != GCRY_MD_NONE)
+ {
+ err = gcry_md_open (&ctx->gch, gcryalg, gcrymode);
+ if (gcry_err_code (err))
+ rc = GC_INVALID_HASH;
+ }
+
+ if (rc == GC_OK)
+ *outhandle = ctx;
+ else
+ free (ctx);
+
+ return rc;
+}
+
+Gc_rc
+MHD_gc_hash_clone (MHD_gc_hash_handle handle, MHD_gc_hash_handle * outhandle)
+{
+ _MHD_gc_hash_ctx *in = handle;
+ _MHD_gc_hash_ctx *out;
+ int err;
+
+ *outhandle = out = calloc (sizeof (*out), 1);
+ if (!out)
+ return GC_MALLOC_ERROR;
+
+ memcpy (out, in, sizeof (*out));
+
+ err = gcry_md_copy (&out->gch, in->gch);
+ if (err)
+ {
+ free (out);
+ return GC_INVALID_HASH;
+ }
+
+ return GC_OK;
+}
+
+size_t
+MHD_gc_hash_digest_length (Gc_hash hash)
+{
+ size_t len;
+
+ switch (hash)
+ {
+ case GC_MD2:
+ len = GC_MD2_DIGEST_SIZE;
+ break;
+
+ case GC_MD4:
+ len = GC_MD4_DIGEST_SIZE;
+ break;
+
+ case GC_MD5:
+ len = GC_MD5_DIGEST_SIZE;
+ break;
+
+ case GC_RMD160:
+ len = GC_RMD160_DIGEST_SIZE;
+ break;
+
+ case GC_SHA1:
+ len = GC_SHA1_DIGEST_SIZE;
+ break;
+
+ case GC_SHA256:
+ len = GC_SHA256_DIGEST_SIZE;
+ break;
+
+ case GC_SHA384:
+ len = GC_SHA384_DIGEST_SIZE;
+ break;
+
+ case GC_SHA512:
+ len = GC_SHA512_DIGEST_SIZE;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return len;
+}
+
+void
+MHD_gc_hash_MHD_hmac_setkey (MHD_gc_hash_handle handle, size_t len,
+ const char *key)
+{
+ _MHD_gc_hash_ctx *ctx = handle;
+ gcry_md_setkey (ctx->gch, key, len);
+}
+
+void
+MHD_gc_hash_write (MHD_gc_hash_handle handle, size_t len, const char *data)
+{
+ _MHD_gc_hash_ctx *ctx = handle;
+ gcry_md_write (ctx->gch, data, len);
+}
+
+const char *
+MHD_gc_hash_read (MHD_gc_hash_handle handle)
+{
+ _MHD_gc_hash_ctx *ctx = handle;
+ const char *digest;
+ {
+ gcry_md_final (ctx->gch);
+ digest = (const char *) gcry_md_read (ctx->gch, 0);
+ }
+
+ return digest;
+}
+
+void
+MHD_gc_hash_close (MHD_gc_hash_handle handle)
+{
+ _MHD_gc_hash_ctx *ctx = handle;
+
+ gcry_md_close (ctx->gch);
+
+ free (ctx);
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/lgl/gc.h b/lib/libmicrohttpd/src/daemon/https/lgl/gc.h
new file mode 100644
index 0000000000..30c4e45bc2
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/lgl/gc.h
@@ -0,0 +1,172 @@
+/* gc.h --- Header file for implementation agnostic crypto wrapper API.
+ * Copyright (C) 2002, 2003, 2004, 2005, 2007 Simon Josefsson
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1, or (at your
+ * option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef GC_H
+#define GC_H
+
+/* Get size_t. */
+# include <stddef.h>
+
+enum Gc_rc
+{
+ GC_OK = 0,
+ GC_MALLOC_ERROR,
+ GC_INIT_ERROR,
+ GC_RANDOM_ERROR,
+ GC_INVALID_CIPHER,
+ GC_INVALID_HASH,
+ GC_PKCS5_INVALID_ITERATION_COUNT,
+ GC_PKCS5_INVALID_DERIVED_KEY_LENGTH,
+ GC_PKCS5_DERIVED_KEY_TOO_LONG
+};
+typedef enum Gc_rc Gc_rc;
+
+/* Hash types. */
+enum Gc_hash
+{
+ GC_MD4,
+ GC_MD5,
+ GC_SHA1,
+ GC_MD2,
+ GC_RMD160,
+ GC_SHA256,
+ GC_SHA384,
+ GC_SHA512
+};
+typedef enum Gc_hash Gc_hash;
+
+enum Gc_hash_mode
+{
+ GC_HMAC = 1
+};
+typedef enum Gc_hash_mode Gc_hash_mode;
+
+typedef void *MHD_gc_hash_handle;
+
+#define GC_MD2_DIGEST_SIZE 16
+#define GC_MD4_DIGEST_SIZE 16
+#define GC_MD5_DIGEST_SIZE 16
+#define GC_RMD160_DIGEST_SIZE 20
+#define GC_SHA1_DIGEST_SIZE 20
+#define GC_SHA256_DIGEST_SIZE 32
+#define GC_SHA384_DIGEST_SIZE 48
+#define GC_SHA512_DIGEST_SIZE 64
+
+/* Cipher types. */
+enum Gc_cipher
+{
+ GC_AES128,
+ GC_AES192,
+ GC_AES256,
+ GC_3DES,
+ GC_DES,
+ GC_ARCFOUR128,
+ GC_ARCFOUR40,
+ GC_ARCTWO40,
+ GC_CAMELLIA128,
+ GC_CAMELLIA256
+};
+typedef enum Gc_cipher Gc_cipher;
+
+enum Gc_cipher_mode
+{
+ GC_ECB,
+ GC_CBC,
+ GC_STREAM
+};
+typedef enum Gc_cipher_mode Gc_cipher_mode;
+
+typedef void *MHD_gc_cipher_handle;
+
+/* Call before respectively after any other functions. */
+Gc_rc MHD_gc_init (void);
+void MHD_gc_done (void);
+
+/* Memory allocation (avoid). */
+typedef void *(*MHD_gc_malloc_t) (size_t n);
+typedef int (*MHD_gc_secure_check_t) (const void *);
+typedef void *(*MHD_gc_realloc_t) (void *p, size_t n);
+typedef void (*MHD_gc_free_t) (void *);
+/* Randomness. */
+Gc_rc MHD_gc_nonce (char *data, size_t datalen);
+Gc_rc MHD_gc_pseudo_random (char *data, size_t datalen);
+
+/* Ciphers. */
+Gc_rc MHD_gc_cipher_open (Gc_cipher cipher,
+ Gc_cipher_mode mode,
+ MHD_gc_cipher_handle * outhandle);
+Gc_rc MHD_gc_cipher_setkey (MHD_gc_cipher_handle handle, size_t keylen,
+ const char *key);
+Gc_rc MHD_gc_cipher_setiv (MHD_gc_cipher_handle handle, size_t ivlen,
+ const char *iv);
+Gc_rc MHD_gc_cipher_encrypt_inline (MHD_gc_cipher_handle handle, size_t len,
+ char *data);
+Gc_rc MHD_gc_cipher_decrypt_inline (MHD_gc_cipher_handle handle, size_t len,
+ char *data);
+Gc_rc MHD_gc_cipher_close (MHD_gc_cipher_handle handle);
+
+/* Hashes. */
+
+Gc_rc MHD_gc_hash_open (Gc_hash hash,
+ Gc_hash_mode mode, MHD_gc_hash_handle * outhandle);
+Gc_rc MHD_gc_hash_clone (MHD_gc_hash_handle handle,
+ MHD_gc_hash_handle * outhandle);
+size_t MHD_gc_hash_digest_length (Gc_hash hash);
+void MHD_gc_hash_MHD_hmac_setkey (MHD_gc_hash_handle handle, size_t len,
+ const char *key);
+void MHD_gc_hash_write (MHD_gc_hash_handle handle, size_t len,
+ const char *data);
+const char *MHD_gc_hash_read (MHD_gc_hash_handle handle);
+void MHD_gc_hash_close (MHD_gc_hash_handle handle);
+
+/* Compute a hash value over buffer IN of INLEN bytes size using the
+ algorithm HASH, placing the result in the pre-allocated buffer OUT.
+ The required size of OUT depends on HASH, and is generally
+ GC_<HASH>_DIGEST_SIZE. For example, for GC_MD5 the output buffer
+ must be 16 bytes. The return value is 0 (GC_OK) on success, or
+ another Gc_rc error code. */
+Gc_rc MHD_gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen,
+ char *out);
+
+/* One-call interface. */
+Gc_rc MHD_gc_md2 (const void *in, size_t inlen, void *resbuf);
+Gc_rc MHD_gc_md4 (const void *in, size_t inlen, void *resbuf);
+Gc_rc MHD_gc_md5 (const void *in, size_t inlen, void *resbuf);
+Gc_rc MHD_gc_sha1 (const void *in, size_t inlen, void *resbuf);
+Gc_rc MHD_gc_MHD_hmac_md5 (const void *key,
+ size_t keylen, const void *in, size_t inlen,
+ char *resbuf);
+Gc_rc MHD_gc_MHD_hmac_sha1 (const void *key, size_t keylen, const void *in,
+ size_t inlen, char *resbuf);
+
+/* Derive cryptographic keys from a password P of length PLEN, with
+ salt S of length SLEN, placing the result in pre-allocated buffer
+ DK of length DKLEN. An iteration count is specified in C, where a
+ larger value means this function take more time (typical iteration
+ counts are 1000-20000). This function "stretches" the key to be
+ exactly dkLen bytes long. GC_OK is returned on success, otherwise
+ an Gc_rc error code is returned. */
+Gc_rc MHD_gc_pbkdf2_sha1 (const char *P,
+ size_t Plen,
+ const char *S,
+ size_t Slen, unsigned int c, char *DK,
+ size_t dkLen);
+
+#endif /* GC_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.am b/lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.am
new file mode 100644
index 0000000000..1d5c68d99e
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/tls
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+noinst_LTLIBRARIES = libasn1.la
+
+libasn1_la_SOURCES = \
+libtasn1.h \
+mem.h \
+gstr.h \
+int.h \
+parser_aux.h structure.h element.h decoding.c gstr.c \
+parser_aux.c structure.c element.c coding.c
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.in b/lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.in
new file mode 100644
index 0000000000..29440d3362
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/Makefile.in
@@ -0,0 +1,506 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/daemon/https/minitasn1
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libasn1_la_LIBADD =
+am_libasn1_la_OBJECTS = decoding.lo gstr.lo parser_aux.lo structure.lo \
+ element.lo coding.lo
+libasn1_la_OBJECTS = $(am_libasn1_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libasn1_la_SOURCES)
+DIST_SOURCES = $(libasn1_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/tls
+
+@USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage
+noinst_LTLIBRARIES = libasn1.la
+libasn1_la_SOURCES = \
+libtasn1.h \
+mem.h \
+gstr.h \
+int.h \
+parser_aux.h structure.h element.h decoding.c gstr.c \
+parser_aux.c structure.c element.c coding.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/daemon/https/minitasn1/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/daemon/https/minitasn1/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libasn1.la: $(libasn1_la_OBJECTS) $(libasn1_la_DEPENDENCIES)
+ $(LINK) $(libasn1_la_OBJECTS) $(libasn1_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coding.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decoding.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/element.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_aux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/structure.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/README b/lib/libmicrohttpd/src/daemon/https/minitasn1/README
new file mode 100644
index 0000000000..9d484dfccc
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/README
@@ -0,0 +1,3 @@
+This is just a mirror of the files in the libtasn1's
+lib/ directory.
+
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/coding.c b/lib/libmicrohttpd/src/daemon/https/minitasn1/coding.c
new file mode 100644
index 0000000000..02d046834c
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/coding.c
@@ -0,0 +1,1211 @@
+/*
+ * Copyright (C) 2004, 2006 Free Software Foundation
+ * Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+
+/*****************************************************/
+/* File: coding.c */
+/* Description: Functions to create a DER coding of */
+/* an ASN1 type. */
+/*****************************************************/
+
+#include <int.h>
+#include "parser_aux.h"
+#include <gstr.h>
+#include "element.h"
+#include <structure.h>
+
+#define MAX_TAG_LEN 16
+
+/******************************************************/
+/* Function : MHD__asn1_error_description_value_not_found */
+/* Description: creates the ErrorDescription string */
+/* for the ASN1_VALUE_NOT_FOUND error. */
+/* Parameters: */
+/* node: node of the tree where the value is NULL. */
+/* ErrorDescription: string returned. */
+/* Return: */
+/******************************************************/
+static void
+MHD__asn1_error_description_value_not_found (node_asn * node,
+ char *ErrorDescription)
+{
+
+ if (ErrorDescription == NULL)
+ return;
+
+ Estrcpy (ErrorDescription, ":: value of element '");
+ MHD__asn1_hierarchical_name (node,
+ ErrorDescription + strlen (ErrorDescription),
+ MAX_ERROR_DESCRIPTION_SIZE - 40);
+ Estrcat (ErrorDescription, "' not found");
+
+}
+
+/**
+ * MHD__asn1_length_der:
+ * @len: value to convert.
+ * @ans: string returned.
+ * @ans_len: number of meaningful bytes of ANS (ans[0]..ans[ans_len-1]).
+ *
+ * Creates the DER coding for the LEN parameter (only the length).
+ * The @ans buffer is pre-allocated and must have room for the output.
+ **/
+void
+MHD__asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len)
+{
+ int k;
+ unsigned char temp[SIZEOF_UNSIGNED_LONG_INT];
+
+ if (len < 128)
+ {
+ /* short form */
+ if (ans != NULL)
+ ans[0] = (unsigned char) len;
+ *ans_len = 1;
+ }
+ else
+ {
+ /* Long form */
+ k = 0;
+ while (len)
+ {
+ temp[k++] = len & 0xFF;
+ len = len >> 8;
+ }
+ *ans_len = k + 1;
+ if (ans != NULL)
+ {
+ ans[0] = ((unsigned char) k & 0x7F) + 128;
+ while (k--)
+ ans[*ans_len - 1 - k] = temp[k];
+ }
+ }
+}
+
+/******************************************************/
+/* Function : MHD__asn1_tag_der */
+/* Description: creates the DER coding for the CLASS */
+/* and TAG parameters. */
+/* Parameters: */
+/* class: value to convert. */
+/* tag_value: value to convert. */
+/* ans: string returned. */
+/* ans_len: number of meaningful bytes of ANS */
+/* (ans[0]..ans[ans_len-1]). */
+/* Return: */
+/******************************************************/
+static void
+MHD__asn1_tag_der (unsigned char class, unsigned int tag_value,
+ unsigned char *ans, int *ans_len)
+{
+ int k;
+ unsigned char temp[SIZEOF_UNSIGNED_INT];
+
+ if (tag_value < 31)
+ {
+ /* short form */
+ ans[0] = (class & 0xE0) + ((unsigned char) (tag_value & 0x1F));
+ *ans_len = 1;
+ }
+ else
+ {
+ /* Long form */
+ ans[0] = (class & 0xE0) + 31;
+ k = 0;
+ while (tag_value)
+ {
+ temp[k++] = tag_value & 0x7F;
+ tag_value = tag_value >> 7;
+ }
+ *ans_len = k + 1;
+ while (k--)
+ ans[*ans_len - 1 - k] = temp[k] + 128;
+ ans[*ans_len - 1] -= 128;
+ }
+}
+
+/**
+ * MHD__asn1_octet_der:
+ * @str: OCTET string.
+ * @str_len: STR length (str[0]..str[str_len-1]).
+ * @der: string returned.
+ * @der_len: number of meaningful bytes of DER (der[0]..der[ans_len-1]).
+ *
+ * Creates the DER coding for an OCTET type (length included).
+ **/
+void
+MHD__asn1_octet_der (const unsigned char *str, int str_len,
+ unsigned char *der, int *der_len)
+{
+ int len_len;
+
+ if (der == NULL || str_len < 0)
+ return;
+ MHD__asn1_length_der (str_len, der, &len_len);
+ memcpy (der + len_len, str, str_len);
+ *der_len = str_len + len_len;
+}
+
+/******************************************************/
+/* Function : MHD__asn1_time_der */
+/* Description: creates the DER coding for a TIME */
+/* type (length included). */
+/* Parameters: */
+/* str: TIME null-terminated string. */
+/* der: string returned. */
+/* der_len: number of meaningful bytes of DER */
+/* (der[0]..der[ans_len-1]). Initially it */
+/* if must store the lenght of DER. */
+/* Return: */
+/* ASN1_MEM_ERROR when DER isn't big enough */
+/* ASN1_SUCCESS otherwise */
+/******************************************************/
+static MHD__asn1_retCode
+MHD__asn1_time_der (unsigned char *str, unsigned char *der, int *der_len)
+{
+ int len_len;
+ int max_len;
+
+ max_len = *der_len;
+
+ MHD__asn1_length_der (strlen ((const char *) str),
+ (max_len > 0) ? der : NULL, &len_len);
+
+ if ((len_len + (int) strlen ((const char *) str)) <= max_len)
+ memcpy (der + len_len, str, strlen ((const char *) str));
+ *der_len = len_len + strlen ((const char *) str);
+
+ if ((*der_len) > max_len)
+ return ASN1_MEM_ERROR;
+
+ return ASN1_SUCCESS;
+}
+
+/******************************************************/
+/* Function : MHD__asn1_objectid_der */
+/* Description: creates the DER coding for an */
+/* OBJECT IDENTIFIER type (length included). */
+/* Parameters: */
+/* str: OBJECT IDENTIFIER null-terminated string. */
+/* der: string returned. */
+/* der_len: number of meaningful bytes of DER */
+/* (der[0]..der[ans_len-1]). Initially it */
+/* must store the length of DER. */
+/* Return: */
+/* ASN1_MEM_ERROR when DER isn't big enough */
+/* ASN1_SUCCESS otherwise */
+/******************************************************/
+static MHD__asn1_retCode
+MHD__asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
+{
+ int len_len, counter, k, first, max_len;
+ char *temp, *n_end, *n_start;
+ unsigned char bit7;
+ unsigned long val, val1 = 0;
+
+ max_len = *der_len;
+
+ temp = (char *) MHD__asn1_alloca (strlen ((const char *) str) + 2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ strcpy (temp, (const char *) str);
+ strcat (temp, ".");
+
+ counter = 0;
+ n_start = temp;
+ while ((n_end = strchr (n_start, '.')))
+ {
+ *n_end = 0;
+ val = strtoul (n_start, NULL, 10);
+ counter++;
+
+ if (counter == 1)
+ val1 = val;
+ else if (counter == 2)
+ {
+ if (max_len > 0)
+ der[0] = 40 * val1 + val;
+ *der_len = 1;
+ }
+ else
+ {
+ first = 0;
+ for (k = 4; k >= 0; k--)
+ {
+ bit7 = (val >> (k * 7)) & 0x7F;
+ if (bit7 || first || !k)
+ {
+ if (k)
+ bit7 |= 0x80;
+ if (max_len > (*der_len))
+ der[*der_len] = bit7;
+ (*der_len)++;
+ first = 1;
+ }
+ }
+
+ }
+ n_start = n_end + 1;
+ }
+
+ MHD__asn1_length_der (*der_len, NULL, &len_len);
+ if (max_len >= (*der_len + len_len))
+ {
+ memmove (der + len_len, der, *der_len);
+ MHD__asn1_length_der (*der_len, der, &len_len);
+ }
+ *der_len += len_len;
+
+ MHD__asn1_afree (temp);
+
+ if (max_len < (*der_len))
+ return ASN1_MEM_ERROR;
+
+ return ASN1_SUCCESS;
+}
+
+
+const char MHD_bit_mask[] =
+ { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
+
+/**
+ * MHD__asn1_bit_der:
+ * @str: BIT string.
+ * @bit_len: number of meaningful bits in STR.
+ * @der: string returned.
+ * @der_len: number of meaningful bytes of DER
+ * (der[0]..der[ans_len-1]).
+ *
+ * Creates the DER coding for a BIT STRING type (length and pad
+ * included).
+ **/
+void
+MHD__asn1_bit_der (const unsigned char *str, int bit_len,
+ unsigned char *der, int *der_len)
+{
+ int len_len, len_byte, len_pad;
+
+ if (der == NULL)
+ return;
+ len_byte = bit_len >> 3;
+ len_pad = 8 - (bit_len & 7);
+ if (len_pad == 8)
+ len_pad = 0;
+ else
+ len_byte++;
+ MHD__asn1_length_der (len_byte + 1, der, &len_len);
+ der[len_len] = len_pad;
+ memcpy (der + len_len + 1, str, len_byte);
+ der[len_len + len_byte] &= MHD_bit_mask[len_pad];
+ *der_len = len_byte + len_len + 1;
+}
+
+
+/******************************************************/
+/* Function : MHD__asn1_complete_explicit_tag */
+/* Description: add the length coding to the EXPLICIT */
+/* tags. */
+/* Parameters: */
+/* node: pointer to the tree element. */
+/* der: string with the DER coding of the whole tree*/
+/* counter: number of meaningful bytes of DER */
+/* (der[0]..der[*counter-1]). */
+/* max_len: size of der vector */
+/* Return: */
+/* ASN1_MEM_ERROR if der vector isn't big enough, */
+/* otherwise ASN1_SUCCESS. */
+/******************************************************/
+static MHD__asn1_retCode
+MHD__asn1_complete_explicit_tag (node_asn * node, unsigned char *der,
+ int *counter, int *max_len)
+{
+ node_asn *p;
+ int is_tag_implicit, len2, len3;
+ unsigned char temp[SIZEOF_UNSIGNED_INT];
+
+ is_tag_implicit = 0;
+
+ if (node->type & CONST_TAG)
+ {
+ p = node->down;
+ /* When there are nested tags we must complete them reverse to
+ the order they were created. This is because completing a tag
+ modifies all data within it, including the incomplete tags
+ which store buffer positions -- simon@josefsson.org 2002-09-06
+ */
+ while (p->right)
+ p = p->right;
+ while (p && p != node->down->left)
+ {
+ if (type_field (p->type) == TYPE_TAG)
+ {
+ if (p->type & CONST_EXPLICIT)
+ {
+ len2 = strtol (p->name, NULL, 10);
+ MHD__asn1_set_name (p, NULL);
+ MHD__asn1_length_der (*counter - len2, temp, &len3);
+ if (len3 <= (*max_len))
+ {
+ memmove (der + len2 + len3, der + len2,
+ *counter - len2);
+ memcpy (der + len2, temp, len3);
+ }
+ *max_len -= len3;
+ *counter += len3;
+ is_tag_implicit = 0;
+ }
+ else
+ { /* CONST_IMPLICIT */
+ if (!is_tag_implicit)
+ {
+ is_tag_implicit = 1;
+ }
+ }
+ }
+ p = p->left;
+ }
+ }
+
+ if (*max_len < 0)
+ return ASN1_MEM_ERROR;
+
+ return ASN1_SUCCESS;
+}
+
+
+/******************************************************/
+/* Function : MHD__asn1_insert_tag_der */
+/* Description: creates the DER coding of tags of one */
+/* NODE. */
+/* Parameters: */
+/* node: pointer to the tree element. */
+/* der: string returned */
+/* counter: number of meaningful bytes of DER */
+/* (counter[0]..der[*counter-1]). */
+/* max_len: size of der vector */
+/* Return: */
+/* ASN1_GENERIC_ERROR if the type is unknown, */
+/* ASN1_MEM_ERROR if der vector isn't big enough, */
+/* otherwise ASN1_SUCCESS. */
+/******************************************************/
+static MHD__asn1_retCode
+MHD__asn1_insert_tag_der (node_asn * node, unsigned char *der, int *counter,
+ int *max_len)
+{
+ node_asn *p;
+ int tag_len, is_tag_implicit;
+ unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1];
+ unsigned long tag_implicit = 0;
+ char tag_der[MAX_TAG_LEN];
+
+ is_tag_implicit = 0;
+
+ if (node->type & CONST_TAG)
+ {
+ p = node->down;
+ while (p)
+ {
+ if (type_field (p->type) == TYPE_TAG)
+ {
+ if (p->type & CONST_APPLICATION)
+ class = ASN1_CLASS_APPLICATION;
+ else if (p->type & CONST_UNIVERSAL)
+ class = ASN1_CLASS_UNIVERSAL;
+ else if (p->type & CONST_PRIVATE)
+ class = ASN1_CLASS_PRIVATE;
+ else
+ class = ASN1_CLASS_CONTEXT_SPECIFIC;
+
+ if (p->type & CONST_EXPLICIT)
+ {
+ if (is_tag_implicit)
+ MHD__asn1_tag_der (class_implicit, tag_implicit,
+ (unsigned char *) tag_der, &tag_len);
+ else
+ MHD__asn1_tag_der (class | ASN1_CLASS_STRUCTURED,
+ strtoul ((const char *) p->value, NULL,
+ 10),
+ (unsigned char *) tag_der, &tag_len);
+
+ *max_len -= tag_len;
+ if (*max_len >= 0)
+ memcpy (der + *counter, tag_der, tag_len);
+ *counter += tag_len;
+
+ MHD__asn1_ltostr (*counter, (char *) temp);
+ MHD__asn1_set_name (p, (const char *) temp);
+
+ is_tag_implicit = 0;
+ }
+ else
+ { /* CONST_IMPLICIT */
+ if (!is_tag_implicit)
+ {
+ if ((type_field (node->type) == TYPE_SEQUENCE) ||
+ (type_field (node->type) == TYPE_SEQUENCE_OF) ||
+ (type_field (node->type) == TYPE_SET) ||
+ (type_field (node->type) == TYPE_SET_OF))
+ class |= ASN1_CLASS_STRUCTURED;
+ class_implicit = class;
+ tag_implicit =
+ strtoul ((const char *) p->value, NULL, 10);
+ is_tag_implicit = 1;
+ }
+ }
+ }
+ p = p->right;
+ }
+ }
+
+ if (is_tag_implicit)
+ {
+ MHD__asn1_tag_der (class_implicit, tag_implicit,
+ (unsigned char *) tag_der, &tag_len);
+ }
+ else
+ {
+ switch (type_field (node->type))
+ {
+ case TYPE_NULL:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_NULL,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_BOOLEAN:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_BOOLEAN,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_INTEGER:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_INTEGER,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_ENUMERATED:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_ENUMERATED,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_OBJECT_ID:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_OBJECT_ID,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_TIME:
+ if (node->type & CONST_UTC)
+ {
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_UTCTime,
+ (unsigned char *) tag_der, &tag_len);
+ }
+ else
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALIZEDTime,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_OCTET_STRING:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_OCTET_STRING,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_GENERALSTRING:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALSTRING,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_BIT_STRING:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_BIT_STRING,
+ (unsigned char *) tag_der, &tag_len);
+ break;
+ case TYPE_SEQUENCE:
+ case TYPE_SEQUENCE_OF:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+ ASN1_TAG_SEQUENCE, (unsigned char *) tag_der,
+ &tag_len);
+ break;
+ case TYPE_SET:
+ case TYPE_SET_OF:
+ MHD__asn1_tag_der (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+ ASN1_TAG_SET, (unsigned char *) tag_der,
+ &tag_len);
+ break;
+ case TYPE_TAG:
+ tag_len = 0;
+ break;
+ case TYPE_CHOICE:
+ tag_len = 0;
+ break;
+ case TYPE_ANY:
+ tag_len = 0;
+ break;
+ default:
+ return ASN1_GENERIC_ERROR;
+ }
+ }
+
+ *max_len -= tag_len;
+ if (*max_len >= 0)
+ memcpy (der + *counter, tag_der, tag_len);
+ *counter += tag_len;
+
+ if (*max_len < 0)
+ return ASN1_MEM_ERROR;
+
+ return ASN1_SUCCESS;
+}
+
+/******************************************************/
+/* Function : MHD__asn1_ordering_set */
+/* Description: puts the elements of a SET type in */
+/* the correct order according to DER rules. */
+/* Parameters: */
+/* der: string with the DER coding. */
+/* node: pointer to the SET element. */
+/* Return: */
+/******************************************************/
+static void
+MHD__asn1_ordering_set (unsigned char *der, int der_len, node_asn * node)
+{
+ struct vet
+ {
+ int end;
+ uint32_t value;
+ struct vet *next, *prev;
+ };
+
+ int counter, len, len2;
+ struct vet *first, *last, *p_vet, *p2_vet;
+ node_asn *p;
+ unsigned char class, *temp;
+ unsigned long tag;
+
+ counter = 0;
+
+ if (type_field (node->type) != TYPE_SET)
+ return;
+
+ p = node->down;
+ while ((p != NULL) &&
+ ((type_field (p->type) == TYPE_TAG)
+ || (type_field (p->type) == TYPE_SIZE)))
+ p = p->right;
+
+ if ((p == NULL) || (p->right == NULL))
+ return;
+
+ first = last = NULL;
+ while (p)
+ {
+ p_vet = (struct vet *) MHD__asn1_alloca (sizeof (struct vet));
+ if (p_vet == NULL)
+ return;
+
+ p_vet->next = NULL;
+ p_vet->prev = last;
+ if (first == NULL)
+ first = p_vet;
+ else
+ last->next = p_vet;
+ last = p_vet;
+
+ /* tag value calculation */
+ if (MHD__asn1_get_tag_der
+ (der + counter, der_len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return;
+ p_vet->value = (class << 24) | tag;
+ counter += len2;
+
+ /* extraction and length */
+ len2 =
+ MHD__asn1_get_length_der (der + counter, der_len - counter, &len);
+ if (len2 < 0)
+ return;
+ counter += len + len2;
+
+ p_vet->end = counter;
+ p = p->right;
+ }
+
+ p_vet = first;
+
+ while (p_vet)
+ {
+ p2_vet = p_vet->next;
+ counter = 0;
+ while (p2_vet)
+ {
+ if (p_vet->value > p2_vet->value)
+ {
+ /* change position */
+ temp =
+ (unsigned char *) MHD__asn1_alloca (p_vet->end - counter);
+ if (temp == NULL)
+ return;
+
+ memcpy (temp, der + counter, p_vet->end - counter);
+ memcpy (der + counter, der + p_vet->end,
+ p2_vet->end - p_vet->end);
+ memcpy (der + counter + p2_vet->end - p_vet->end, temp,
+ p_vet->end - counter);
+ MHD__asn1_afree (temp);
+
+ tag = p_vet->value;
+ p_vet->value = p2_vet->value;
+ p2_vet->value = tag;
+
+ p_vet->end = counter + (p2_vet->end - p_vet->end);
+ }
+ counter = p_vet->end;
+
+ p2_vet = p2_vet->next;
+ p_vet = p_vet->next;
+ }
+
+ if (p_vet != first)
+ p_vet->prev->next = NULL;
+ else
+ first = NULL;
+ MHD__asn1_afree (p_vet);
+ p_vet = first;
+ }
+}
+
+/******************************************************/
+/* Function : MHD__asn1_ordering_set_of */
+/* Description: puts the elements of a SET OF type in */
+/* the correct order according to DER rules. */
+/* Parameters: */
+/* der: string with the DER coding. */
+/* node: pointer to the SET OF element. */
+/* Return: */
+/******************************************************/
+static void
+MHD__asn1_ordering_set_of (unsigned char *der, int der_len, node_asn * node)
+{
+ struct vet
+ {
+ int end;
+ struct vet *next, *prev;
+ };
+
+ int counter, len, len2, change;
+ struct vet *first, *last, *p_vet, *p2_vet;
+ node_asn *p;
+ unsigned char *temp, class;
+ unsigned long k, max;
+
+ counter = 0;
+
+ if (type_field (node->type) != TYPE_SET_OF)
+ return;
+
+ p = node->down;
+ while ((type_field (p->type) == TYPE_TAG)
+ || (type_field (p->type) == TYPE_SIZE))
+ p = p->right;
+ p = p->right;
+
+ if ((p == NULL) || (p->right == NULL))
+ return;
+
+ first = last = NULL;
+ while (p)
+ {
+ p_vet = (struct vet *) MHD__asn1_alloca (sizeof (struct vet));
+ if (p_vet == NULL)
+ return;
+
+ p_vet->next = NULL;
+ p_vet->prev = last;
+ if (first == NULL)
+ first = p_vet;
+ else
+ last->next = p_vet;
+ last = p_vet;
+
+ /* extraction of tag and length */
+ if (der_len - counter > 0)
+ {
+
+ if (MHD__asn1_get_tag_der
+ (der + counter, der_len - counter, &class, &len,
+ NULL) != ASN1_SUCCESS)
+ return;
+ counter += len;
+
+ len2 =
+ MHD__asn1_get_length_der (der + counter, der_len - counter, &len);
+ if (len2 < 0)
+ return;
+ counter += len + len2;
+ }
+
+ p_vet->end = counter;
+ p = p->right;
+ }
+
+ p_vet = first;
+
+ while (p_vet)
+ {
+ p2_vet = p_vet->next;
+ counter = 0;
+ while (p2_vet)
+ {
+ if ((p_vet->end - counter) > (p2_vet->end - p_vet->end))
+ max = p_vet->end - counter;
+ else
+ max = p2_vet->end - p_vet->end;
+
+ change = -1;
+ for (k = 0; k < max; k++)
+ if (der[counter + k] > der[p_vet->end + k])
+ {
+ change = 1;
+ break;
+ }
+ else if (der[counter + k] < der[p_vet->end + k])
+ {
+ change = 0;
+ break;
+ }
+
+ if ((change == -1)
+ && ((p_vet->end - counter) > (p2_vet->end - p_vet->end)))
+ change = 1;
+
+ if (change == 1)
+ {
+ /* change position */
+ temp =
+ (unsigned char *) MHD__asn1_alloca (p_vet->end - counter);
+ if (temp == NULL)
+ return;
+
+ memcpy (temp, der + counter, (p_vet->end) - counter);
+ memcpy (der + counter, der + (p_vet->end),
+ (p2_vet->end) - (p_vet->end));
+ memcpy (der + counter + (p2_vet->end) - (p_vet->end), temp,
+ (p_vet->end) - counter);
+ MHD__asn1_afree (temp);
+
+ p_vet->end = counter + (p2_vet->end - p_vet->end);
+ }
+ counter = p_vet->end;
+
+ p2_vet = p2_vet->next;
+ p_vet = p_vet->next;
+ }
+
+ if (p_vet != first)
+ p_vet->prev->next = NULL;
+ else
+ first = NULL;
+ MHD__asn1_afree (p_vet);
+ p_vet = first;
+ }
+}
+
+/**
+ * MHD__asn1_der_coding - Creates the DER encoding for the NAME structure
+ * @element: pointer to an ASN1 element
+ * @name: the name of the structure you want to encode (it must be
+ * inside *POINTER).
+ * @ider: vector that will contain the DER encoding. DER must be a
+ * pointer to memory cells already allocated.
+ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy
+ * holds the sizeof of der vector.
+ * @errorDescription : return the error description or an empty
+ * string if success.
+ *
+ * Creates the DER encoding for the NAME structure (inside *POINTER
+ * structure).
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: DER encoding OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+ *
+ * ASN1_VALUE_NOT_FOUND: There is an element without a value.
+ *
+ * ASN1_MEM_ERROR: @ider vector isn't big enough. Also in this case
+ * LEN will contain the length needed.
+ *
+ **/
+MHD__asn1_retCode
+MHD__asn1_der_coding (ASN1_TYPE element, const char *name, void *ider,
+ int *len, char *ErrorDescription)
+{
+ node_asn *node, *p, *p2;
+ char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1];
+ int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old;
+ MHD__asn1_retCode err;
+ unsigned char *der = ider;
+
+ node = MHD__asn1_find_node (element, name);
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ /* Node is now a locally allocated variable.
+ * That is because in some point we modify the
+ * structure, and I don't know why! --nmav
+ */
+ node = MHD__asn1_copy_structure3 (node);
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ max_len = *len;
+
+ counter = 0;
+ move = DOWN;
+ p = node;
+ while (1)
+ {
+
+ counter_old = counter;
+ max_len_old = max_len;
+ if (move != UP)
+ {
+ err = MHD__asn1_insert_tag_der (p, der, &counter, &max_len);
+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+ goto error;
+ }
+ switch (type_field (p->type))
+ {
+ case TYPE_NULL:
+ max_len--;
+ if (max_len >= 0)
+ der[counter] = 0;
+ counter++;
+ move = RIGHT;
+ break;
+ case TYPE_BOOLEAN:
+ if ((p->type & CONST_DEFAULT) && (p->value == NULL))
+ {
+ counter = counter_old;
+ max_len = max_len_old;
+ }
+ else
+ {
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ max_len -= 2;
+ if (max_len >= 0)
+ {
+ der[counter++] = 1;
+ if (p->value[0] == 'F')
+ der[counter++] = 0;
+ else
+ der[counter++] = 0xFF;
+ }
+ else
+ counter += 2;
+ }
+ move = RIGHT;
+ break;
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ if ((p->type & CONST_DEFAULT) && (p->value == NULL))
+ {
+ counter = counter_old;
+ max_len = max_len_old;
+ }
+ else
+ {
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = MHD__asn1_get_length_der (p->value, p->value_len, &len3);
+ if (len2 < 0)
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
+ max_len -= len2 + len3;
+ if (max_len >= 0)
+ memcpy (der + counter, p->value, len3 + len2);
+ counter += len3 + len2;
+ }
+ move = RIGHT;
+ break;
+ case TYPE_OBJECT_ID:
+ if ((p->type & CONST_DEFAULT) && (p->value == NULL))
+ {
+ counter = counter_old;
+ max_len = max_len_old;
+ }
+ else
+ {
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = max_len;
+ err = MHD__asn1_objectid_der (p->value, der + counter, &len2);
+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+ goto error;
+
+ max_len -= len2;
+ counter += len2;
+ }
+ move = RIGHT;
+ break;
+ case TYPE_TIME:
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = max_len;
+ err = MHD__asn1_time_der (p->value, der + counter, &len2);
+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+ goto error;
+
+ max_len -= len2;
+ counter += len2;
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = MHD__asn1_get_length_der (p->value, p->value_len, &len3);
+ if (len2 < 0)
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
+ max_len -= len2 + len3;
+ if (max_len >= 0)
+ memcpy (der + counter, p->value, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_GENERALSTRING:
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = MHD__asn1_get_length_der (p->value, p->value_len, &len3);
+ if (len2 < 0)
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
+ max_len -= len2 + len3;
+ if (max_len >= 0)
+ memcpy (der + counter, p->value, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_BIT_STRING:
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = MHD__asn1_get_length_der (p->value, p->value_len, &len3);
+ if (len2 < 0)
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
+ max_len -= len2 + len3;
+ if (max_len >= 0)
+ memcpy (der + counter, p->value, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_SEQUENCE:
+ case TYPE_SET:
+ if (move != UP)
+ {
+ MHD__asn1_ltostr (counter, temp);
+ tlen = strlen (temp);
+ if (tlen > 0)
+ MHD__asn1_set_value (p, temp, tlen + 1);
+ if (p->down == NULL)
+ {
+ move = UP;
+ continue;
+ }
+ else
+ {
+ p2 = p->down;
+ while (p2 && (type_field (p2->type) == TYPE_TAG))
+ p2 = p2->right;
+ if (p2)
+ {
+ p = p2;
+ move = RIGHT;
+ continue;
+ }
+ move = UP;
+ continue;
+ }
+ }
+ else
+ { /* move==UP */
+ len2 = strtol ((const char *) p->value, NULL, 10);
+ MHD__asn1_set_value (p, NULL, 0);
+ if ((type_field (p->type) == TYPE_SET) && (max_len >= 0))
+ MHD__asn1_ordering_set (der + len2, max_len - len2, p);
+ MHD__asn1_length_der (counter - len2, (unsigned char *) temp,
+ &len3);
+ max_len -= len3;
+ if (max_len >= 0)
+ {
+ memmove (der + len2 + len3, der + len2, counter - len2);
+ memcpy (der + len2, temp, len3);
+ }
+ counter += len3;
+ move = RIGHT;
+ }
+ break;
+ case TYPE_SEQUENCE_OF:
+ case TYPE_SET_OF:
+ if (move != UP)
+ {
+ MHD__asn1_ltostr (counter, temp);
+ tlen = strlen (temp);
+
+ if (tlen > 0)
+ MHD__asn1_set_value (p, temp, tlen + 1);
+ p = p->down;
+ while ((type_field (p->type) == TYPE_TAG)
+ || (type_field (p->type) == TYPE_SIZE))
+ p = p->right;
+ if (p->right)
+ {
+ p = p->right;
+ move = RIGHT;
+ continue;
+ }
+ else
+ p = MHD__asn1_find_up (p);
+ move = UP;
+ }
+ if (move == UP)
+ {
+ len2 = strtol ((const char *) p->value, NULL, 10);
+ MHD__asn1_set_value (p, NULL, 0);
+ if ((type_field (p->type) == TYPE_SET_OF)
+ && (max_len - len2 > 0))
+ {
+ MHD__asn1_ordering_set_of (der + len2, max_len - len2, p);
+ }
+ MHD__asn1_length_der (counter - len2, (unsigned char *) temp,
+ &len3);
+ max_len -= len3;
+ if (max_len >= 0)
+ {
+ memmove (der + len2 + len3, der + len2, counter - len2);
+ memcpy (der + len2, temp, len3);
+ }
+ counter += len3;
+ move = RIGHT;
+ }
+ break;
+ case TYPE_ANY:
+ if (p->value == NULL)
+ {
+ MHD__asn1_error_description_value_not_found (p,
+ ErrorDescription);
+ err = ASN1_VALUE_NOT_FOUND;
+ goto error;
+ }
+ len2 = MHD__asn1_get_length_der (p->value, p->value_len, &len3);
+ if (len2 < 0)
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
+ max_len -= len2;
+ if (max_len >= 0)
+ memcpy (der + counter, p->value + len3, len2);
+ counter += len2;
+ move = RIGHT;
+ break;
+ default:
+ move = (move == UP) ? RIGHT : DOWN;
+ break;
+ }
+
+ if ((move != DOWN) && (counter != counter_old))
+ {
+ err = MHD__asn1_complete_explicit_tag (p, der, &counter, &max_len);
+ if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+ goto error;
+ }
+
+ if (p == node && move != DOWN)
+ break;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+ if (move == RIGHT)
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+ *len = counter;
+
+ if (max_len < 0)
+ {
+ err = ASN1_MEM_ERROR;
+ goto error;
+ }
+
+ err = ASN1_SUCCESS;
+
+error:
+ MHD__asn1_delete_structure (&node);
+ return err;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/decoding.c b/lib/libmicrohttpd/src/daemon/https/minitasn1/decoding.c
new file mode 100644
index 0000000000..9a4e23a397
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/decoding.c
@@ -0,0 +1,1673 @@
+/*
+ * Copyright (C) 2004, 2006 Free Software Foundation
+ * Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+
+/*****************************************************/
+/* File: decoding.c */
+/* Description: Functions to manage DER decoding */
+/*****************************************************/
+
+#include <int.h>
+#include "parser_aux.h"
+#include <gstr.h>
+#include "structure.h"
+#include "element.h"
+
+
+static void
+MHD__asn1_error_description_tag_error (node_asn * node,
+ char *ErrorDescription)
+{
+
+ Estrcpy (ErrorDescription, ":: tag error near element '");
+ MHD__asn1_hierarchical_name (node,
+ ErrorDescription + strlen (ErrorDescription),
+ MAX_ERROR_DESCRIPTION_SIZE - 40);
+ Estrcat (ErrorDescription, "'");
+
+}
+
+/**
+ * MHD__asn1_get_length_der:
+ * @der: DER data to decode.
+ * @der_len: Length of DER data to decode.
+ * @len: Output variable containing the length of the DER length field.
+ *
+ * Extract a length field from DER data.
+ *
+ * Return value: Return the decoded length value, or -1 on indefinite
+ * length, or -2 when the value was too big.
+ **/
+signed long
+MHD__asn1_get_length_der (const unsigned char *der, int der_len, int *len)
+{
+ unsigned long ans;
+ int k, punt;
+
+ *len = 0;
+ if (der_len <= 0)
+ return 0;
+
+ if (!(der[0] & 128))
+ {
+ /* short form */
+ *len = 1;
+ return der[0];
+ }
+ else
+ {
+ /* Long form */
+ k = der[0] & 0x7F;
+ punt = 1;
+ if (k)
+ { /* definite length method */
+ ans = 0;
+ while (punt <= k && punt < der_len)
+ {
+ unsigned long last = ans;
+
+ ans = ans * 256 + der[punt++];
+ if (ans < last)
+ /* we wrapped around, no bignum support... */
+ return -2;
+ }
+ }
+ else
+ { /* indefinite length method */
+ ans = -1;
+ }
+
+ *len = punt;
+ return ans;
+ }
+}
+
+
+
+
+/**
+ * MHD__asn1_get_tag_der:
+ * @der: DER data to decode.
+ * @der_len: Length of DER data to decode.
+ * @cls: Output variable containing decoded class.
+ * @len: Output variable containing the length of the DER TAG data.
+ * @tag: Output variable containing the decoded tag.
+ *
+ * Decode the class and TAG from DER code.
+ *
+ * Return value: Returns ASN1_SUCCESS on success, or an error.
+ **/
+int
+MHD__asn1_get_tag_der (const unsigned char *der, int der_len,
+ unsigned char *cls, int *len, unsigned long *tag)
+{
+ int punt, ris;
+
+ if (der == NULL || der_len <= 0 || len == NULL)
+ return ASN1_DER_ERROR;
+
+ *cls = der[0] & 0xE0;
+ if ((der[0] & 0x1F) != 0x1F)
+ {
+ /* short form */
+ *len = 1;
+ ris = der[0] & 0x1F;
+ }
+ else
+ {
+ /* Long form */
+ punt = 1;
+ ris = 0;
+ while (punt <= der_len && der[punt] & 128)
+ {
+ int last = ris;
+ ris = ris * 128 + (der[punt++] & 0x7F);
+ if (ris < last)
+ /* wrapper around, and no bignums... */
+ return ASN1_DER_ERROR;
+ }
+ if (punt >= der_len)
+ return ASN1_DER_ERROR;
+ {
+ int last = ris;
+ ris = ris * 128 + (der[punt++] & 0x7F);
+ if (ris < last)
+ /* wrapper around, and no bignums... */
+ return ASN1_DER_ERROR;
+ }
+ *len = punt;
+ }
+ if (tag)
+ *tag = ris;
+ return ASN1_SUCCESS;
+}
+
+
+
+
+/**
+ * MHD__asn1_get_octet_der:
+ * @der: DER data to decode containing the OCTET SEQUENCE.
+ * @der_len: Length of DER data to decode.
+ * @ret_len: Output variable containing the length of the DER data.
+ * @str: Pre-allocated output buffer to put decoded OCTET SEQUENCE in.
+ * @str_size: Length of pre-allocated output buffer.
+ * @str_len: Output variable containing the length of the OCTET SEQUENCE.
+ *
+ * Extract an OCTET SEQUENCE from DER data.
+ *
+ * Return value: Returns ASN1_SUCCESS on success, or an error.
+ **/
+int
+MHD__asn1_get_octet_der (const unsigned char *der, int der_len,
+ int *ret_len, unsigned char *str, int str_size,
+ int *str_len)
+{
+ int len_len;
+
+ if (der_len <= 0)
+ return ASN1_GENERIC_ERROR;
+
+ /* if(str==NULL) return ASN1_SUCCESS; */
+ *str_len = MHD__asn1_get_length_der (der, der_len, &len_len);
+
+ if (*str_len < 0)
+ return ASN1_DER_ERROR;
+
+ *ret_len = *str_len + len_len;
+ if (str_size >= *str_len)
+ memcpy (str, der + len_len, *str_len);
+ else
+ {
+ return ASN1_MEM_ERROR;
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+
+/* Returns ASN1_SUCCESS on success or an error code on error.
+ */
+static int
+MHD__asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len,
+ char *str, int str_size)
+{
+ int len_len, str_len;
+
+ if (der_len <= 0 || str == NULL)
+ return ASN1_DER_ERROR;
+ str_len = MHD__asn1_get_length_der (der, der_len, &len_len);
+ if (str_len < 0 || str_size < str_len)
+ return ASN1_DER_ERROR;
+ memcpy (str, der + len_len, str_len);
+ str[str_len] = 0;
+ *ret_len = str_len + len_len;
+
+ return ASN1_SUCCESS;
+}
+
+
+
+static void
+MHD__asn1_get_objectid_der (const unsigned char *der, int der_len,
+ int *ret_len, char *str, int str_size)
+{
+ int len_len, len, k;
+ char temp[20];
+ unsigned long val, val1;
+
+ *ret_len = 0;
+ if (str && str_size > 0)
+ str[0] = 0; /* no oid */
+
+ if (str == NULL || der_len <= 0)
+ return;
+ len = MHD__asn1_get_length_der (der, der_len, &len_len);
+
+ if (len < 0 || len > der_len || len_len > der_len)
+ return;
+
+ val1 = der[len_len] / 40;
+ val = der[len_len] - val1 * 40;
+
+ MHD__asn1_str_cpy (str, str_size, MHD__asn1_ltostr (val1, temp));
+ MHD__asn1_str_cat (str, str_size, ".");
+ MHD__asn1_str_cat (str, str_size, MHD__asn1_ltostr (val, temp));
+
+ val = 0;
+ for (k = 1; k < len; k++)
+ {
+ val = val << 7;
+ val |= der[len_len + k] & 0x7F;
+ if (!(der[len_len + k] & 0x80))
+ {
+ MHD__asn1_str_cat (str, str_size, ".");
+ MHD__asn1_str_cat (str, str_size, MHD__asn1_ltostr (val, temp));
+ val = 0;
+ }
+ }
+ *ret_len = len + len_len;
+}
+
+
+
+
+/**
+ * MHD__asn1_get_bit_der:
+ * @der: DER data to decode containing the BIT SEQUENCE.
+ * @der_len: Length of DER data to decode.
+ * @ret_len: Output variable containing the length of the DER data.
+ * @str: Pre-allocated output buffer to put decoded BIT SEQUENCE in.
+ * @str_size: Length of pre-allocated output buffer.
+ * @bit_len: Output variable containing the size of the BIT SEQUENCE.
+ *
+ * Extract a BIT SEQUENCE from DER data.
+ *
+ * Return value: Return ASN1_SUCCESS on success, or an error.
+ **/
+int
+MHD__asn1_get_bit_der (const unsigned char *der, int der_len,
+ int *ret_len, unsigned char *str, int str_size,
+ int *bit_len)
+{
+ int len_len, len_byte;
+
+ if (der_len <= 0)
+ return ASN1_GENERIC_ERROR;
+ len_byte = MHD__asn1_get_length_der (der, der_len, &len_len) - 1;
+ if (len_byte < 0)
+ return ASN1_DER_ERROR;
+
+ *ret_len = len_byte + len_len + 1;
+ *bit_len = len_byte * 8 - der[len_len];
+
+ if (str_size >= len_byte)
+ memcpy (str, der + len_len + 1, len_byte);
+ else
+ {
+ return ASN1_MEM_ERROR;
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+
+
+static int
+MHD__asn1_extract_tag_der (node_asn * node, const unsigned char *der,
+ int der_len, int *ret_len)
+{
+ node_asn *p;
+ int counter, len2, len3, is_tag_implicit;
+ unsigned long tag, tag_implicit = 0;
+ unsigned char class, class2, class_implicit = 0;
+
+ if (der_len <= 0)
+ return ASN1_GENERIC_ERROR;
+
+ counter = is_tag_implicit = 0;
+
+ if (node->type & CONST_TAG)
+ {
+ p = node->down;
+ while (p)
+ {
+ if (type_field (p->type) == TYPE_TAG)
+ {
+ if (p->type & CONST_APPLICATION)
+ class2 = ASN1_CLASS_APPLICATION;
+ else if (p->type & CONST_UNIVERSAL)
+ class2 = ASN1_CLASS_UNIVERSAL;
+ else if (p->type & CONST_PRIVATE)
+ class2 = ASN1_CLASS_PRIVATE;
+ else
+ class2 = ASN1_CLASS_CONTEXT_SPECIFIC;
+
+ if (p->type & CONST_EXPLICIT)
+ {
+ if (MHD__asn1_get_tag_der
+ (der + counter, der_len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+ if (counter + len2 > der_len)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ len3 =
+ MHD__asn1_get_length_der (der + counter,
+ der_len - counter, &len2);
+ if (len3 < 0)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ if (!is_tag_implicit)
+ {
+ if ((class != (class2 | ASN1_CLASS_STRUCTURED)) ||
+ (tag != strtoul ((char *) p->value, NULL, 10)))
+ return ASN1_TAG_ERROR;
+ }
+ else
+ { /* ASN1_TAG_IMPLICIT */
+ if ((class != class_implicit) || (tag != tag_implicit))
+ return ASN1_TAG_ERROR;
+ }
+
+ is_tag_implicit = 0;
+ }
+ else
+ { /* ASN1_TAG_IMPLICIT */
+ if (!is_tag_implicit)
+ {
+ if ((type_field (node->type) == TYPE_SEQUENCE) ||
+ (type_field (node->type) == TYPE_SEQUENCE_OF) ||
+ (type_field (node->type) == TYPE_SET) ||
+ (type_field (node->type) == TYPE_SET_OF))
+ class2 |= ASN1_CLASS_STRUCTURED;
+ class_implicit = class2;
+ tag_implicit = strtoul ((char *) p->value, NULL, 10);
+ is_tag_implicit = 1;
+ }
+ }
+ }
+ p = p->right;
+ }
+ }
+
+ if (is_tag_implicit)
+ {
+ if (MHD__asn1_get_tag_der
+ (der + counter, der_len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+ if (counter + len2 > der_len)
+ return ASN1_DER_ERROR;
+
+ if ((class != class_implicit) || (tag != tag_implicit))
+ {
+ if (type_field (node->type) == TYPE_OCTET_STRING)
+ {
+ class_implicit |= ASN1_CLASS_STRUCTURED;
+ if ((class != class_implicit) || (tag != tag_implicit))
+ return ASN1_TAG_ERROR;
+ }
+ else
+ return ASN1_TAG_ERROR;
+ }
+ }
+ else
+ {
+ if (type_field (node->type) == TYPE_TAG)
+ {
+ counter = 0;
+ *ret_len = counter;
+ return ASN1_SUCCESS;
+ }
+
+ if (MHD__asn1_get_tag_der
+ (der + counter, der_len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+ if (counter + len2 > der_len)
+ return ASN1_DER_ERROR;
+
+ switch (type_field (node->type))
+ {
+ case TYPE_NULL:
+ if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_NULL))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_BOOLEAN:
+ if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_BOOLEAN))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_INTEGER:
+ if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_INTEGER))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_ENUMERATED:
+ if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_ENUMERATED))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_OBJECT_ID:
+ if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_OBJECT_ID))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_TIME:
+ if (node->type & CONST_UTC)
+ {
+ if ((class != ASN1_CLASS_UNIVERSAL)
+ || (tag != ASN1_TAG_UTCTime))
+ return ASN1_DER_ERROR;
+ }
+ else
+ {
+ if ((class != ASN1_CLASS_UNIVERSAL)
+ || (tag != ASN1_TAG_GENERALIZEDTime))
+ return ASN1_DER_ERROR;
+ }
+ break;
+ case TYPE_OCTET_STRING:
+ if (((class != ASN1_CLASS_UNIVERSAL)
+ && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED)))
+ || (tag != ASN1_TAG_OCTET_STRING))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_GENERALSTRING:
+ if ((class != ASN1_CLASS_UNIVERSAL)
+ || (tag != ASN1_TAG_GENERALSTRING))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_BIT_STRING:
+ if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_BIT_STRING))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_SEQUENCE:
+ case TYPE_SEQUENCE_OF:
+ if ((class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))
+ || (tag != ASN1_TAG_SEQUENCE))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_SET:
+ case TYPE_SET_OF:
+ if ((class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))
+ || (tag != ASN1_TAG_SET))
+ return ASN1_DER_ERROR;
+ break;
+ case TYPE_ANY:
+ counter -= len2;
+ break;
+ default:
+ return ASN1_DER_ERROR;
+ break;
+ }
+ }
+
+ counter += len2;
+ *ret_len = counter;
+ return ASN1_SUCCESS;
+}
+
+
+static int
+MHD__asn1_delete_not_used (node_asn * node)
+{
+ node_asn *p, *p2;
+
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = node;
+ while (p)
+ {
+ if (p->type & CONST_NOT_USED)
+ {
+ p2 = NULL;
+ if (p != node)
+ {
+ p2 = MHD__asn1_find_left (p);
+ if (!p2)
+ p2 = MHD__asn1_find_up (p);
+ }
+ MHD__asn1_delete_structure (&p);
+ p = p2;
+ }
+
+ if (!p)
+ break; /* reach node */
+
+ if (p->down)
+ {
+ p = p->down;
+ }
+ else
+ {
+ if (p == node)
+ p = NULL;
+ else if (p->right)
+ p = p->right;
+ else
+ {
+ while (1)
+ {
+ p = MHD__asn1_find_up (p);
+ if (p == node)
+ {
+ p = NULL;
+ break;
+ }
+ if (p->right)
+ {
+ p = p->right;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return ASN1_SUCCESS;
+}
+
+
+static MHD__asn1_retCode
+MHD__asn1_get_octet_string (const unsigned char *der, node_asn * node,
+ int *len)
+{
+ int len2, len3, counter, counter2, counter_end, tot_len, indefinite;
+ unsigned char *temp, *temp2;
+
+ counter = 0;
+
+ if (*(der - 1) & ASN1_CLASS_STRUCTURED)
+ {
+ tot_len = 0;
+ indefinite = MHD__asn1_get_length_der (der, *len, &len3);
+ if (indefinite < -1)
+ return ASN1_DER_ERROR;
+
+ counter += len3;
+ if (indefinite >= 0)
+ indefinite += len3;
+
+ while (1)
+ {
+ if (counter > (*len))
+ return ASN1_DER_ERROR;
+
+ if (indefinite == -1)
+ {
+ if ((der[counter] == 0) && (der[counter + 1] == 0))
+ {
+ counter += 2;
+ break;
+ }
+ }
+ else if (counter >= indefinite)
+ break;
+
+ if (der[counter] != ASN1_TAG_OCTET_STRING)
+ return ASN1_DER_ERROR;
+
+ counter++;
+
+ len2 =
+ MHD__asn1_get_length_der (der + counter, *len - counter, &len3);
+ if (len2 <= 0)
+ return ASN1_DER_ERROR;
+
+ counter += len3 + len2;
+ tot_len += len2;
+ }
+
+ /* copy */
+ if (node)
+ {
+ MHD__asn1_length_der (tot_len, NULL, &len2);
+ temp = MHD__asn1_alloca (len2 + tot_len);
+ if (temp == NULL)
+ {
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+ MHD__asn1_length_der (tot_len, temp, &len2);
+ tot_len += len2;
+ temp2 = temp + len2;
+ len2 = MHD__asn1_get_length_der (der, *len, &len3);
+ if (len2 < -1)
+ {
+ MHD__asn1_afree (temp);
+ return ASN1_DER_ERROR;
+ }
+ counter2 = len3 + 1;
+
+ if (indefinite == -1)
+ counter_end = counter - 2;
+ else
+ counter_end = counter;
+
+ while (counter2 < counter_end)
+ {
+ len2 =
+ MHD__asn1_get_length_der (der + counter2, *len - counter,
+ &len3);
+ if (len2 < -1)
+ {
+ MHD__asn1_afree (temp);
+ return ASN1_DER_ERROR;
+ }
+
+ /* FIXME: to be checked. Is this ok? Has the
+ * size been checked before?
+ */
+ memcpy (temp2, der + counter2 + len3, len2);
+ temp2 += len2;
+ counter2 += len2 + len3 + 1;
+ }
+
+ MHD__asn1_set_value (node, temp, tot_len);
+ MHD__asn1_afree (temp);
+ }
+ }
+ else
+ { /* NOT STRUCTURED */
+ len2 = MHD__asn1_get_length_der (der, *len, &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ if (len3 + len2 > *len)
+ return ASN1_DER_ERROR;
+ if (node)
+ MHD__asn1_set_value (node, der, len3 + len2);
+ counter = len3 + len2;
+ }
+
+ *len = counter;
+ return ASN1_SUCCESS;
+
+}
+
+
+static MHD__asn1_retCode
+MHD__asn1_get_indefinite_length_string (const unsigned char *der, int *len)
+{
+ int len2, len3, counter, indefinite;
+ unsigned long tag;
+ unsigned char class;
+
+ counter = indefinite = 0;
+
+ while (1)
+ {
+ if ((*len) < counter)
+ return ASN1_DER_ERROR;
+
+ if ((der[counter] == 0) && (der[counter + 1] == 0))
+ {
+ counter += 2;
+ indefinite--;
+ if (indefinite <= 0)
+ break;
+ else
+ continue;
+ }
+
+ if (MHD__asn1_get_tag_der
+ (der + counter, *len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+ if (counter + len2 > *len)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ len2 = MHD__asn1_get_length_der (der + counter, *len - counter, &len3);
+ if (len2 < -1)
+ return ASN1_DER_ERROR;
+ if (len2 == -1)
+ {
+ indefinite++;
+ counter += 1;
+ }
+ else
+ {
+ counter += len2 + len3;
+ }
+ }
+
+ *len = counter;
+ return ASN1_SUCCESS;
+
+}
+
+
+/**
+ * MHD__asn1_der_decoding - Fill the structure *ELEMENT with values of a DER encoding string.
+ * @element: pointer to an ASN1 structure.
+ * @ider: vector that contains the DER encoding.
+ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @errorDescription: null-terminated string contains details when an
+ * error occurred.
+ *
+ * Fill the structure *ELEMENT with values of a DER encoding
+ * string. The sructure must just be created with function
+ * 'create_stucture'. If an error occurs during the decoding
+ * procedure, the *ELEMENT is deleted and set equal to
+ * %ASN1_TYPE_EMPTY.
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: DER encoding OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: ELEMENT is ASN1_TYPE_EMPTY.
+ *
+ * ASN1_TAG_ERROR,ASN1_DER_ERROR: The der encoding doesn't match
+ * the structure NAME. *ELEMENT deleted.
+ **/
+
+MHD__asn1_retCode
+MHD__asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len,
+ char *errorDescription)
+{
+ node_asn *node, *p, *p2, *p3;
+ char temp[128];
+ int counter, len2, len3, len4, move, ris, tlen;
+ unsigned char class, *temp2;
+ unsigned long tag;
+ int indefinite, result;
+ const unsigned char *der = ider;
+
+ node = *element;
+
+ if (node == ASN1_TYPE_EMPTY)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if (node->type & CONST_OPTION)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_GENERIC_ERROR;
+ }
+
+ counter = 0;
+ move = DOWN;
+ p = node;
+ while (1)
+ {
+ ris = ASN1_SUCCESS;
+ if (move != UP)
+ {
+ if (p->type & CONST_SET)
+ {
+ p2 = MHD__asn1_find_up (p);
+ len2 = strtol ((const char *) p2->value, NULL, 10);
+ if (len2 == -1)
+ {
+ if (!der[counter] && !der[counter + 1])
+ {
+ p = p2;
+ move = UP;
+ counter += 2;
+ continue;
+ }
+ }
+ else if (counter == len2)
+ {
+ p = p2;
+ move = UP;
+ continue;
+ }
+ else if (counter > len2)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ p2 = p2->down;
+ while (p2)
+ {
+ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ {
+ if (type_field (p2->type) != TYPE_CHOICE)
+ ris =
+ MHD__asn1_extract_tag_der (p2, der + counter,
+ len - counter, &len2);
+ else
+ {
+ p3 = p2->down;
+ while (p3)
+ {
+ ris =
+ MHD__asn1_extract_tag_der (p3, der + counter,
+ len - counter,
+ &len2);
+ if (ris == ASN1_SUCCESS)
+ break;
+ p3 = p3->right;
+ }
+ }
+ if (ris == ASN1_SUCCESS)
+ {
+ p2->type &= ~CONST_NOT_USED;
+ p = p2;
+ break;
+ }
+ }
+ p2 = p2->right;
+ }
+ if (p2 == NULL)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ }
+
+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ {
+ p2 = MHD__asn1_find_up (p);
+ len2 = strtol ((const char *) p2->value, NULL, 10);
+ if (counter == len2)
+ {
+ if (p->right)
+ {
+ p2 = p->right;
+ move = RIGHT;
+ }
+ else
+ move = UP;
+
+ if (p->type & CONST_OPTION)
+ MHD__asn1_delete_structure (&p);
+
+ p = p2;
+ continue;
+ }
+ }
+
+ if (type_field (p->type) == TYPE_CHOICE)
+ {
+ while (p->down)
+ {
+ if (counter < len)
+ ris =
+ MHD__asn1_extract_tag_der (p->down, der + counter,
+ len - counter, &len2);
+ else
+ ris = ASN1_DER_ERROR;
+ if (ris == ASN1_SUCCESS)
+ {
+ while (p->down->right)
+ {
+ p2 = p->down->right;
+ MHD__asn1_delete_structure (&p2);
+ }
+ break;
+ }
+ else if (ris == ASN1_ERROR_TYPE_ANY)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_ERROR_TYPE_ANY;
+ }
+ else
+ {
+ p2 = p->down;
+ MHD__asn1_delete_structure (&p2);
+ }
+ }
+
+ if (p->down == NULL)
+ {
+ if (!(p->type & CONST_OPTION))
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ }
+ else
+ p = p->down;
+ }
+
+ if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ {
+ p2 = MHD__asn1_find_up (p);
+ len2 = strtol ((const char *) p2->value, NULL, 10);
+ if ((len2 != -1) && (counter > len2))
+ ris = ASN1_TAG_ERROR;
+ }
+
+ if (ris == ASN1_SUCCESS)
+ ris =
+ MHD__asn1_extract_tag_der (p, der + counter, len - counter,
+ &len2);
+ if (ris != ASN1_SUCCESS)
+ {
+ if (p->type & CONST_OPTION)
+ {
+ p->type |= CONST_NOT_USED;
+ move = RIGHT;
+ }
+ else if (p->type & CONST_DEFAULT)
+ {
+ MHD__asn1_set_value (p, NULL, 0);
+ move = RIGHT;
+ }
+ else
+ {
+ if (errorDescription != NULL)
+ MHD__asn1_error_description_tag_error (p,
+ errorDescription);
+
+ MHD__asn1_delete_structure (element);
+ return ASN1_TAG_ERROR;
+ }
+ }
+ else
+ counter += len2;
+ }
+
+ if (ris == ASN1_SUCCESS)
+ {
+ switch (type_field (p->type))
+ {
+ case TYPE_NULL:
+ if (der[counter])
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ counter++;
+ move = RIGHT;
+ break;
+ case TYPE_BOOLEAN:
+ if (der[counter++] != 1)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ if (der[counter++] == 0)
+ MHD__asn1_set_value (p, "F", 1);
+ else
+ MHD__asn1_set_value (p, "T", 1);
+ move = RIGHT;
+ break;
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ if (len2 + len3 > len - counter)
+ return ASN1_DER_ERROR;
+ MHD__asn1_set_value (p, der + counter, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_OBJECT_ID:
+ MHD__asn1_get_objectid_der (der + counter, len - counter, &len2,
+ temp, sizeof (temp));
+ tlen = strlen (temp);
+ if (tlen > 0)
+ MHD__asn1_set_value (p, temp, tlen + 1);
+ counter += len2;
+ move = RIGHT;
+ break;
+ case TYPE_TIME:
+ result =
+ MHD__asn1_get_time_der (der + counter, len - counter, &len2,
+ temp, sizeof (temp) - 1);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD__asn1_delete_structure (element);
+ return result;
+ }
+ tlen = strlen (temp);
+ if (tlen > 0)
+ MHD__asn1_set_value (p, temp, tlen + 1);
+ counter += len2;
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+ len3 = len - counter;
+ ris = MHD__asn1_get_octet_string (der + counter, p, &len3);
+ if (ris != ASN1_SUCCESS)
+ return ris;
+ counter += len3;
+ move = RIGHT;
+ break;
+ case TYPE_GENERALSTRING:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ if (len3 + len2 > len - counter)
+ return ASN1_DER_ERROR;
+ MHD__asn1_set_value (p, der + counter, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_BIT_STRING:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ if (len3 + len2 > len - counter)
+ return ASN1_DER_ERROR;
+ MHD__asn1_set_value (p, der + counter, len3 + len2);
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_SEQUENCE:
+ case TYPE_SET:
+ if (move == UP)
+ {
+ len2 = strtol ((const char *) p->value, NULL, 10);
+ MHD__asn1_set_value (p, NULL, 0);
+ if (len2 == -1)
+ { /* indefinite length method */
+ if (len - counter + 1 > 0)
+ {
+ if ((der[counter]) || der[counter + 1])
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ }
+ else
+ return ASN1_DER_ERROR;
+ counter += 2;
+ }
+ else
+ { /* definite length method */
+ if (len2 != counter)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ }
+ move = RIGHT;
+ }
+ else
+ { /* move==DOWN || move==RIGHT */
+ len3 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < -1)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ if (len3 > 0)
+ {
+ MHD__asn1_ltostr (counter + len3, temp);
+ tlen = strlen (temp);
+ if (tlen > 0)
+ MHD__asn1_set_value (p, temp, tlen + 1);
+ move = DOWN;
+ }
+ else if (len3 == 0)
+ {
+ p2 = p->down;
+ while (p2)
+ {
+ if (type_field (p2->type) != TYPE_TAG)
+ {
+ p3 = p2->right;
+ MHD__asn1_delete_structure (&p2);
+ p2 = p3;
+ }
+ else
+ p2 = p2->right;
+ }
+ move = RIGHT;
+ }
+ else
+ { /* indefinite length method */
+ MHD__asn1_set_value (p, "-1", 3);
+ move = DOWN;
+ }
+ }
+ break;
+ case TYPE_SEQUENCE_OF:
+ case TYPE_SET_OF:
+ if (move == UP)
+ {
+ len2 = strtol ((const char *) p->value, NULL, 10);
+ if (len2 == -1)
+ { /* indefinite length method */
+ if ((counter + 2) > len)
+ return ASN1_DER_ERROR;
+ if ((der[counter]) || der[counter + 1])
+ {
+ MHD__asn1_append_sequence_set (p);
+ p = p->down;
+ while (p->right)
+ p = p->right;
+ move = RIGHT;
+ continue;
+ }
+ MHD__asn1_set_value (p, NULL, 0);
+ counter += 2;
+ }
+ else
+ { /* definite length method */
+ if (len2 > counter)
+ {
+ MHD__asn1_append_sequence_set (p);
+ p = p->down;
+ while (p->right)
+ p = p->right;
+ move = RIGHT;
+ continue;
+ }
+ MHD__asn1_set_value (p, NULL, 0);
+ if (len2 != counter)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ }
+ }
+ else
+ { /* move==DOWN || move==RIGHT */
+ len3 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < -1)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ if (len3)
+ {
+ if (len3 > 0)
+ { /* definite length method */
+ MHD__asn1_ltostr (counter + len3, temp);
+ tlen = strlen (temp);
+
+ if (tlen > 0)
+ MHD__asn1_set_value (p, temp, tlen + 1);
+ }
+ else
+ { /* indefinite length method */
+ MHD__asn1_set_value (p, "-1", 3);
+ }
+ p2 = p->down;
+ while ((type_field (p2->type) == TYPE_TAG)
+ || (type_field (p2->type) == TYPE_SIZE))
+ p2 = p2->right;
+ if (p2->right == NULL)
+ MHD__asn1_append_sequence_set (p);
+ p = p2;
+ }
+ }
+ move = RIGHT;
+ break;
+ case TYPE_ANY:
+ if (MHD__asn1_get_tag_der
+ (der + counter, len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+ if (counter + len2 > len)
+ return ASN1_DER_ERROR;
+ len4 =
+ MHD__asn1_get_length_der (der + counter + len2,
+ len - counter - len2, &len3);
+ if (len4 < -1)
+ return ASN1_DER_ERROR;
+ if (len4 > len - counter + len2 + len3)
+ return ASN1_DER_ERROR;
+ if (len4 != -1)
+ {
+ len2 += len4;
+ MHD__asn1_length_der (len2 + len3, NULL, &len4);
+ temp2 =
+ (unsigned char *) MHD__asn1_alloca (len2 + len3 + len4);
+ if (temp2 == NULL)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+ MHD__asn1_octet_der (der + counter, len2 + len3, temp2,
+ &len4);
+ MHD__asn1_set_value (p, temp2, len4);
+ MHD__asn1_afree (temp2);
+ counter += len2 + len3;
+ }
+ else
+ { /* indefinite length */
+ /* Check indefinite lenth method in an EXPLICIT TAG */
+ if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+ indefinite = 1;
+ else
+ indefinite = 0;
+
+ len2 = len - counter;
+ ris =
+ MHD__asn1_get_indefinite_length_string (der + counter,
+ &len2);
+ if (ris != ASN1_SUCCESS)
+ {
+ MHD__asn1_delete_structure (element);
+ return ris;
+ }
+ MHD__asn1_length_der (len2, NULL, &len4);
+ temp2 = (unsigned char *) MHD__asn1_alloca (len2 + len4);
+ if (temp2 == NULL)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+ MHD__asn1_octet_der (der + counter, len2, temp2, &len4);
+ MHD__asn1_set_value (p, temp2, len4);
+ MHD__asn1_afree (temp2);
+ counter += len2;
+
+ /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+ an indefinite length method. */
+ if (indefinite)
+ {
+ if (!der[counter] && !der[counter + 1])
+ {
+ counter += 2;
+ }
+ else
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+ }
+ }
+ move = RIGHT;
+ break;
+ default:
+ move = (move == UP) ? RIGHT : DOWN;
+ break;
+ }
+ }
+
+ if (p == node && move != DOWN)
+ break;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+ if ((move == RIGHT) && !(p->type & CONST_SET))
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+ MHD__asn1_delete_not_used (*element);
+
+ if (counter != len)
+ {
+ MHD__asn1_delete_structure (element);
+ return ASN1_DER_ERROR;
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+/**
+ * MHD__asn1_der_decoding_startEnd - Find the start and end point of an element in a DER encoding string.
+ * @element: pointer to an ASN1 element
+ * @ider: vector that contains the DER encoding.
+ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1]
+ * @name_element: an element of NAME structure.
+ * @start: the position of the first byte of NAME_ELEMENT decoding
+ * (@ider[*start])
+ * @end: the position of the last byte of NAME_ELEMENT decoding
+ * (@ider[*end])
+ *
+ * Find the start and end point of an element in a DER encoding
+ * string. I mean that if you have a der encoding and you have
+ * already used the function "MHD__asn1_der_decoding" to fill a structure,
+ * it may happen that you want to find the piece of string concerning
+ * an element of the structure.
+ *
+ * Example: the sequence "tbsCertificate" inside an X509 certificate.
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: DER encoding OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: ELEMENT is ASN1_TYPE EMPTY or
+ * NAME_ELEMENT is not a valid element.
+ *
+ * ASN1_TAG_ERROR,ASN1_DER_ERROR: the der encoding doesn't match
+ * the structure ELEMENT.
+ *
+ **/
+MHD__asn1_retCode
+MHD__asn1_der_decoding_startEnd (ASN1_TYPE element, const void *ider, int len,
+ const char *name_element, int *start,
+ int *end)
+{
+ node_asn *node, *node_to_find, *p, *p2, *p3;
+ int counter, len2, len3, len4, move, ris;
+ unsigned char class;
+ unsigned long tag;
+ int indefinite;
+ const unsigned char *der = ider;
+
+ node = element;
+
+ if (node == ASN1_TYPE_EMPTY)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ node_to_find = MHD__asn1_find_node (node, name_element);
+
+ if (node_to_find == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if (node_to_find == node)
+ {
+ *start = 0;
+ *end = len - 1;
+ return ASN1_SUCCESS;
+ }
+
+ if (node->type & CONST_OPTION)
+ return ASN1_GENERIC_ERROR;
+
+ counter = 0;
+ move = DOWN;
+ p = node;
+ while (1)
+ {
+ ris = ASN1_SUCCESS;
+
+ if (move != UP)
+ {
+ if (p->type & CONST_SET)
+ {
+ p2 = MHD__asn1_find_up (p);
+ len2 = strtol ((const char *) p2->value, NULL, 10);
+ if (len2 == -1)
+ {
+ if (!der[counter] && !der[counter + 1])
+ {
+ p = p2;
+ move = UP;
+ counter += 2;
+ continue;
+ }
+ }
+ else if (counter == len2)
+ {
+ p = p2;
+ move = UP;
+ continue;
+ }
+ else if (counter > len2)
+ return ASN1_DER_ERROR;
+ p2 = p2->down;
+ while (p2)
+ {
+ if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ { /* CONTROLLARE */
+ if (type_field (p2->type) != TYPE_CHOICE)
+ ris =
+ MHD__asn1_extract_tag_der (p2, der + counter,
+ len - counter, &len2);
+ else
+ {
+ p3 = p2->down;
+ ris =
+ MHD__asn1_extract_tag_der (p3, der + counter,
+ len - counter, &len2);
+ }
+ if (ris == ASN1_SUCCESS)
+ {
+ p2->type &= ~CONST_NOT_USED;
+ p = p2;
+ break;
+ }
+ }
+ p2 = p2->right;
+ }
+ if (p2 == NULL)
+ return ASN1_DER_ERROR;
+ }
+
+ if (p == node_to_find)
+ *start = counter;
+
+ if (type_field (p->type) == TYPE_CHOICE)
+ {
+ p = p->down;
+ ris =
+ MHD__asn1_extract_tag_der (p, der + counter, len - counter,
+ &len2);
+ if (p == node_to_find)
+ *start = counter;
+ }
+
+ if (ris == ASN1_SUCCESS)
+ ris =
+ MHD__asn1_extract_tag_der (p, der + counter, len - counter,
+ &len2);
+ if (ris != ASN1_SUCCESS)
+ {
+ if (p->type & CONST_OPTION)
+ {
+ p->type |= CONST_NOT_USED;
+ move = RIGHT;
+ }
+ else if (p->type & CONST_DEFAULT)
+ {
+ move = RIGHT;
+ }
+ else
+ {
+ return ASN1_TAG_ERROR;
+ }
+ }
+ else
+ counter += len2;
+ }
+
+ if (ris == ASN1_SUCCESS)
+ {
+ switch (type_field (p->type))
+ {
+ case TYPE_NULL:
+ if (der[counter])
+ return ASN1_DER_ERROR;
+ counter++;
+ move = RIGHT;
+ break;
+ case TYPE_BOOLEAN:
+ if (der[counter++] != 1)
+ return ASN1_DER_ERROR;
+ counter++;
+ move = RIGHT;
+ break;
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_OBJECT_ID:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ counter += len2 + len3;
+ move = RIGHT;
+ break;
+ case TYPE_TIME:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ counter += len2 + len3;
+ move = RIGHT;
+ break;
+ case TYPE_OCTET_STRING:
+ len3 = len - counter;
+ ris = MHD__asn1_get_octet_string (der + counter, NULL, &len3);
+ if (ris != ASN1_SUCCESS)
+ return ris;
+ counter += len3;
+ move = RIGHT;
+ break;
+ case TYPE_GENERALSTRING:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_BIT_STRING:
+ len2 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ counter += len3 + len2;
+ move = RIGHT;
+ break;
+ case TYPE_SEQUENCE:
+ case TYPE_SET:
+ if (move != UP)
+ {
+ len3 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < -1)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ if (len3 == 0)
+ move = RIGHT;
+ else
+ move = DOWN;
+ }
+ else
+ {
+ if (!der[counter] && !der[counter + 1]) /* indefinite length method */
+ counter += 2;
+ move = RIGHT;
+ }
+ break;
+ case TYPE_SEQUENCE_OF:
+ case TYPE_SET_OF:
+ if (move != UP)
+ {
+ len3 =
+ MHD__asn1_get_length_der (der + counter, len - counter,
+ &len2);
+ if (len3 < -1)
+ return ASN1_DER_ERROR;
+ counter += len2;
+ if ((len3 == -1) && !der[counter] && !der[counter + 1])
+ counter += 2;
+ else if (len3)
+ {
+ p2 = p->down;
+ while ((type_field (p2->type) == TYPE_TAG) ||
+ (type_field (p2->type) == TYPE_SIZE))
+ p2 = p2->right;
+ p = p2;
+ }
+ }
+ else
+ {
+ if (!der[counter] && !der[counter + 1]) /* indefinite length method */
+ counter += 2;
+ }
+ move = RIGHT;
+ break;
+ case TYPE_ANY:
+ if (MHD__asn1_get_tag_der
+ (der + counter, len - counter, &class, &len2,
+ &tag) != ASN1_SUCCESS)
+ return ASN1_DER_ERROR;
+ if (counter + len2 > len)
+ return ASN1_DER_ERROR;
+
+ len4 =
+ MHD__asn1_get_length_der (der + counter + len2,
+ len - counter - len2, &len3);
+ if (len4 < -1)
+ return ASN1_DER_ERROR;
+
+ if (len4 != -1)
+ {
+ counter += len2 + len4 + len3;
+ }
+ else
+ { /* indefinite length */
+ /* Check indefinite lenth method in an EXPLICIT TAG */
+ if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+ indefinite = 1;
+ else
+ indefinite = 0;
+
+ len2 = len - counter;
+ ris =
+ MHD__asn1_get_indefinite_length_string (der + counter,
+ &len2);
+ if (ris != ASN1_SUCCESS)
+ return ris;
+ counter += len2;
+
+ /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+ an indefinite length method. */
+ if (indefinite)
+ {
+ if (!der[counter] && !der[counter + 1])
+ counter += 2;
+ else
+ return ASN1_DER_ERROR;
+ }
+ }
+ move = RIGHT;
+ break;
+ default:
+ move = (move == UP) ? RIGHT : DOWN;
+ break;
+ }
+ }
+
+ if ((p == node_to_find) && (move == RIGHT))
+ {
+ *end = counter - 1;
+ return ASN1_SUCCESS;
+ }
+
+ if (p == node && move != DOWN)
+ break;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+ if ((move == RIGHT) && !(p->type & CONST_SET))
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+ return ASN1_ELEMENT_NOT_FOUND;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/element.c b/lib/libmicrohttpd/src/daemon/https/minitasn1/element.c
new file mode 100644
index 0000000000..4834c604a7
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/element.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright (C) 2004, 2006 Free Software Foundation
+ * Copyright (C) 2000, 2001, 2002, 2003 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+/*****************************************************/
+/* File: element.c */
+/* Description: Functions with the read and write */
+/* functions. */
+/*****************************************************/
+
+
+#include <int.h>
+#include "parser_aux.h"
+#include <gstr.h>
+#include "structure.h"
+
+void
+MHD__asn1_hierarchical_name (node_asn * node, char *name, int name_size)
+{
+ node_asn *p;
+ char tmp_name[64];
+
+ p = node;
+
+ name[0] = 0;
+
+ while (p != NULL)
+ {
+ if (p->name != NULL)
+ {
+ MHD__asn1_str_cpy (tmp_name, sizeof (tmp_name), name),
+ MHD__asn1_str_cpy (name, name_size, p->name);
+ MHD__asn1_str_cat (name, name_size, ".");
+ MHD__asn1_str_cat (name, name_size, tmp_name);
+ }
+ p = MHD__asn1_find_up (p);
+ }
+
+ if (name[0] == 0)
+ MHD__asn1_str_cpy (name, name_size, "ROOT");
+}
+
+
+/******************************************************************/
+/* Function : MHD__asn1_convert_integer */
+/* Description: converts an integer from a null terminated string */
+/* to der decoding. The convertion from a null */
+/* terminated string to an integer is made with */
+/* the 'strtol' function. */
+/* Parameters: */
+/* value: null terminated string to convert. */
+/* value_out: convertion result (memory must be already */
+/* allocated). */
+/* value_out_size: number of bytes of value_out. */
+/* len: number of significant byte of value_out. */
+/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */
+/******************************************************************/
+MHD__asn1_retCode
+MHD__asn1_convert_integer (const char *value, unsigned char *value_out,
+ int value_out_size, int *len)
+{
+ char negative;
+ unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
+ long valtmp;
+ int k, k2;
+
+ valtmp = strtol (value, NULL, 10);
+
+ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
+ {
+ val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF;
+ }
+
+ if (val[0] & 0x80)
+ negative = 1;
+ else
+ negative = 0;
+
+ for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++)
+ {
+ if (negative && (val[k] != 0xFF))
+ break;
+ else if (!negative && val[k])
+ break;
+ }
+
+ if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80)))
+ k--;
+
+ *len = SIZEOF_UNSIGNED_LONG_INT - k;
+
+ if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size)
+ /* VALUE_OUT is too short to contain the value conversion */
+ return ASN1_MEM_ERROR;
+
+ for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+ value_out[k2 - k] = val[k2];
+
+ return ASN1_SUCCESS;
+}
+
+
+int
+MHD__asn1_append_sequence_set (node_asn * node)
+{
+ node_asn *p, *p2;
+ char temp[10];
+ long n;
+
+ if (!node || !(node->down))
+ return ASN1_GENERIC_ERROR;
+
+ p = node->down;
+ while ((type_field (p->type) == TYPE_TAG)
+ || (type_field (p->type) == TYPE_SIZE))
+ p = p->right;
+ p2 = MHD__asn1_copy_structure3 (p);
+ while (p->right)
+ p = p->right;
+ MHD__asn1_set_right (p, p2);
+
+ if (p->name == NULL)
+ MHD__asn1_str_cpy (temp, sizeof (temp), "?1");
+ else
+ {
+ n = strtol (p->name + 1, NULL, 0);
+ n++;
+ temp[0] = '?';
+ MHD__asn1_ltostr (n, temp + 1);
+ }
+ MHD__asn1_set_name (p2, temp);
+ /* p2->type |= CONST_OPTION; */
+
+ return ASN1_SUCCESS;
+}
+
+
+/**
+ * MHD__asn1_write_value - Set the value of one element inside a structure.
+ * @node_root: pointer to a structure
+ * @name: the name of the element inside the structure that you want to set.
+ * @ivalue: vector used to specify the value to set. If len is >0,
+ * VALUE must be a two's complement form integer. if len=0 *VALUE
+ * must be a null terminated string with an integer value.
+ * @len: number of bytes of *value to use to set the value:
+ * value[0]..value[len-1] or 0 if value is a null terminated string
+ *
+ * Set the value of one element inside a structure.
+ *
+ * If an element is OPTIONAL and you want to delete it, you must use
+ * the value=NULL and len=0. Using "pkix.asn":
+ *
+ * result=MHD__asn1_write_value(cert, "tbsCertificate.issuerUniqueID",
+ * NULL, 0);
+ *
+ * Description for each type:
+ *
+ * INTEGER: VALUE must contain a two's complement form integer.
+ *
+ * value[0]=0xFF , len=1 -> integer=-1.
+ * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1.
+ * value[0]=0x01 , len=1 -> integer= 1.
+ * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1.
+ * value="123" , len=0 -> integer= 123.
+ *
+ * ENUMERATED: As INTEGER (but only with not negative numbers).
+ *
+ * BOOLEAN: VALUE must be the null terminated string "TRUE" or
+ * "FALSE" and LEN != 0.
+ *
+ * value="TRUE" , len=1 -> boolean=TRUE.
+ * value="FALSE" , len=1 -> boolean=FALSE.
+ *
+ * OBJECT IDENTIFIER: VALUE must be a null terminated string with
+ * each number separated by a dot (e.g. "1.2.3.543.1"). LEN != 0.
+ *
+ * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha.
+ *
+ * UTCTime: VALUE must be a null terminated string in one of these
+ * formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ",
+ * "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'",
+ * "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'". LEN != 0.
+ *
+ * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998
+ * at 12h 00m Greenwich Mean Time
+ *
+ * GeneralizedTime: VALUE must be in one of this format:
+ * "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ",
+ * "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'",
+ * "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s
+ * indicates the seconds with any precision like "10.1" or "01.02".
+ * LEN != 0
+ *
+ * value="2001010112001.12-0700" , len=1 -> time=Jannuary
+ * 1st, 2001 at 12h 00m 01.12s Pacific Daylight Time
+ *
+ * OCTET STRING: VALUE contains the octet string and LEN is the
+ * number of octets.
+ *
+ * value="$\backslash$x01$\backslash$x02$\backslash$x03" ,
+ * len=3 -> three bytes octet string
+ *
+ * GeneralString: VALUE contains the generalstring and LEN is the
+ * number of octets.
+ *
+ * value="$\backslash$x01$\backslash$x02$\backslash$x03" ,
+ * len=3 -> three bytes generalstring
+ *
+ * BIT STRING: VALUE contains the bit string organized by bytes and
+ * LEN is the number of bits.
+ *
+ * value="$\backslash$xCF" , len=6 -> bit string="110011" (six
+ * bits)
+ *
+ * CHOICE: if NAME indicates a choice type, VALUE must specify one of
+ * the alternatives with a null terminated string. LEN != 0. Using
+ * "pkix.asn"\:
+ *
+ * result=MHD__asn1_write_value(cert,
+ * "certificate1.tbsCertificate.subject", "rdnSequence",
+ * 1);
+ *
+ * ANY: VALUE indicates the der encoding of a structure. LEN != 0.
+ *
+ * SEQUENCE OF: VALUE must be the null terminated string "NEW" and
+ * LEN != 0. With this instruction another element is appended in
+ * the sequence. The name of this element will be "?1" if it's the
+ * first one, "?2" for the second and so on.
+ *
+ * Using "pkix.asn"\:
+ *
+ * result=MHD__asn1_write_value(cert,
+ * "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1);
+ *
+ * SET OF: the same as SEQUENCE OF. Using "pkix.asn":
+ *
+ * result=MHD__asn1_write_value(cert,
+ * "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1);
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: Set value OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+ *
+ * ASN1_VALUE_NOT_VALID: VALUE has a wrong format.
+ *
+ **/
+MHD__asn1_retCode
+MHD__asn1_write_value (ASN1_TYPE node_root, const char *name,
+ const void *ivalue, int len)
+{
+ node_asn *node, *p, *p2;
+ unsigned char *temp, *value_temp = NULL, *default_temp = NULL;
+ int len2, k, k2, negative;
+ const char *value = ivalue;
+
+ node = MHD__asn1_find_node (node_root, name);
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0))
+ {
+ MHD__asn1_delete_structure (&node);
+ return ASN1_SUCCESS;
+ }
+
+ if ((type_field (node->type) == TYPE_SEQUENCE_OF) && (value == NULL)
+ && (len == 0))
+ {
+ p = node->down;
+ while ((type_field (p->type) == TYPE_TAG)
+ || (type_field (p->type) == TYPE_SIZE))
+ p = p->right;
+
+ while (p->right)
+ MHD__asn1_delete_structure (&p->right);
+
+ return ASN1_SUCCESS;
+ }
+
+ switch (type_field (node->type))
+ {
+ case TYPE_BOOLEAN:
+ if (!strcmp (value, "TRUE"))
+ {
+ if (node->type & CONST_DEFAULT)
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ if (p->type & CONST_TRUE)
+ MHD__asn1_set_value (node, NULL, 0);
+ else
+ MHD__asn1_set_value (node, "T", 1);
+ }
+ else
+ MHD__asn1_set_value (node, "T", 1);
+ }
+ else if (!strcmp (value, "FALSE"))
+ {
+ if (node->type & CONST_DEFAULT)
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ if (p->type & CONST_FALSE)
+ MHD__asn1_set_value (node, NULL, 0);
+ else
+ MHD__asn1_set_value (node, "F", 1);
+ }
+ else
+ MHD__asn1_set_value (node, "F", 1);
+ }
+ else
+ return ASN1_VALUE_NOT_VALID;
+ break;
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ if (len == 0)
+ {
+ if ((isdigit (value[0])) || (value[0] == '-'))
+ {
+ value_temp =
+ (unsigned char *) MHD__asn1_alloca (SIZEOF_UNSIGNED_LONG_INT);
+ if (value_temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ MHD__asn1_convert_integer (value, value_temp,
+ SIZEOF_UNSIGNED_LONG_INT, &len);
+ }
+ else
+ { /* is an identifier like v1 */
+ if (!(node->type & CONST_LIST))
+ return ASN1_VALUE_NOT_VALID;
+ p = node->down;
+ while (p)
+ {
+ if (type_field (p->type) == TYPE_CONSTANT)
+ {
+ if ((p->name) && (!strcmp (p->name, value)))
+ {
+ value_temp =
+ (unsigned char *)
+ MHD__asn1_alloca (SIZEOF_UNSIGNED_LONG_INT);
+ if (value_temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ MHD__asn1_convert_integer ((const char *) p->value,
+ value_temp,
+ SIZEOF_UNSIGNED_LONG_INT,
+ &len);
+ break;
+ }
+ }
+ p = p->right;
+ }
+ if (p == NULL)
+ return ASN1_VALUE_NOT_VALID;
+ }
+ }
+ else
+ { /* len != 0 */
+ value_temp = (unsigned char *) MHD__asn1_alloca (len);
+ if (value_temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+ memcpy (value_temp, value, len);
+ }
+
+
+ if (value_temp[0] & 0x80)
+ negative = 1;
+ else
+ negative = 0;
+
+ if (negative && (type_field (node->type) == TYPE_ENUMERATED))
+ {
+ MHD__asn1_afree (value_temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+
+ for (k = 0; k < len - 1; k++)
+ if (negative && (value_temp[k] != 0xFF))
+ break;
+ else if (!negative && value_temp[k])
+ break;
+
+ if ((negative && !(value_temp[k] & 0x80)) ||
+ (!negative && (value_temp[k] & 0x80)))
+ k--;
+
+ MHD__asn1_length_der (len - k, NULL, &len2);
+ temp = (unsigned char *) MHD__asn1_alloca (len - k + len2);
+ if (temp == NULL)
+ {
+ MHD__asn1_afree (value_temp);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+ MHD__asn1_octet_der (value_temp + k, len - k, temp, &len2);
+ MHD__asn1_set_value (node, temp, len2);
+
+ MHD__asn1_afree (temp);
+
+
+ if (node->type & CONST_DEFAULT)
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ if ((isdigit (p->value[0])) || (p->value[0] == '-'))
+ {
+ default_temp =
+ (unsigned char *) MHD__asn1_alloca (SIZEOF_UNSIGNED_LONG_INT);
+ if (default_temp == NULL)
+ {
+ MHD__asn1_afree (value_temp);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+ MHD__asn1_convert_integer ((const char *) p->value,
+ default_temp,
+ SIZEOF_UNSIGNED_LONG_INT, &len2);
+ }
+ else
+ { /* is an identifier like v1 */
+ if (!(node->type & CONST_LIST))
+ {
+ MHD__asn1_afree (value_temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+ p2 = node->down;
+ while (p2)
+ {
+ if (type_field (p2->type) == TYPE_CONSTANT)
+ {
+ if ((p2->name)
+ && (!strcmp (p2->name, (const char *) p->value)))
+ {
+ default_temp =
+ (unsigned char *)
+ MHD__asn1_alloca (SIZEOF_UNSIGNED_LONG_INT);
+ if (default_temp == NULL)
+ {
+ MHD__asn1_afree (value_temp);
+ return ASN1_MEM_ALLOC_ERROR;
+ }
+
+ MHD__asn1_convert_integer ((const char *) p2->value,
+ default_temp,
+ SIZEOF_UNSIGNED_LONG_INT,
+ &len2);
+ break;
+ }
+ }
+ p2 = p2->right;
+ }
+ if (p2 == NULL)
+ {
+ MHD__asn1_afree (value_temp);
+ return ASN1_VALUE_NOT_VALID;
+ }
+ }
+
+
+ if ((len - k) == len2)
+ {
+ for (k2 = 0; k2 < len2; k2++)
+ if (value_temp[k + k2] != default_temp[k2])
+ {
+ break;
+ }
+ if (k2 == len2)
+ MHD__asn1_set_value (node, NULL, 0);
+ }
+ MHD__asn1_afree (default_temp);
+ }
+ MHD__asn1_afree (value_temp);
+ break;
+ case TYPE_OBJECT_ID:
+ for (k = 0; k < strlen (value); k++)
+ if ((!isdigit (value[k])) && (value[k] != '.') && (value[k] != '+'))
+ return ASN1_VALUE_NOT_VALID;
+ if (node->type & CONST_DEFAULT)
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ if (!strcmp (value, (const char *) p->value))
+ {
+ MHD__asn1_set_value (node, NULL, 0);
+ break;
+ }
+ }
+ MHD__asn1_set_value (node, value, strlen (value) + 1);
+ break;
+ case TYPE_TIME:
+ if (node->type & CONST_UTC)
+ {
+ if (strlen (value) < 11)
+ return ASN1_VALUE_NOT_VALID;
+ for (k = 0; k < 10; k++)
+ if (!isdigit (value[k]))
+ return ASN1_VALUE_NOT_VALID;
+ switch (strlen (value))
+ {
+ case 11:
+ if (value[10] != 'Z')
+ return ASN1_VALUE_NOT_VALID;
+ break;
+ case 13:
+ if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
+ (value[12] != 'Z'))
+ return ASN1_VALUE_NOT_VALID;
+ break;
+ case 15:
+ if ((value[10] != '+') && (value[10] != '-'))
+ return ASN1_VALUE_NOT_VALID;
+ for (k = 11; k < 15; k++)
+ if (!isdigit (value[k]))
+ return ASN1_VALUE_NOT_VALID;
+ break;
+ case 17:
+ if ((!isdigit (value[10])) || (!isdigit (value[11])))
+ return ASN1_VALUE_NOT_VALID;
+ if ((value[12] != '+') && (value[12] != '-'))
+ return ASN1_VALUE_NOT_VALID;
+ for (k = 13; k < 17; k++)
+ if (!isdigit (value[k]))
+ return ASN1_VALUE_NOT_VALID;
+ break;
+ default:
+ return ASN1_VALUE_NOT_FOUND;
+ }
+ MHD__asn1_set_value (node, value, strlen (value) + 1);
+ }
+ else
+ { /* GENERALIZED TIME */
+ if (value)
+ MHD__asn1_set_value (node, value, strlen (value) + 1);
+ }
+ break;
+ case TYPE_OCTET_STRING:
+ if (len == 0)
+ len = strlen (value);
+ MHD__asn1_length_der (len, NULL, &len2);
+ temp = (unsigned char *) MHD__asn1_alloca (len + len2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ MHD__asn1_octet_der ((const unsigned char *) value, len, temp, &len2);
+ MHD__asn1_set_value (node, temp, len2);
+ MHD__asn1_afree (temp);
+ break;
+ case TYPE_GENERALSTRING:
+ if (len == 0)
+ len = strlen (value);
+ MHD__asn1_length_der (len, NULL, &len2);
+ temp = (unsigned char *) MHD__asn1_alloca (len + len2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ MHD__asn1_octet_der ((const unsigned char *) value, len, temp, &len2);
+ MHD__asn1_set_value (node, temp, len2);
+ MHD__asn1_afree (temp);
+ break;
+ case TYPE_BIT_STRING:
+ if (len == 0)
+ len = strlen (value);
+ MHD__asn1_length_der ((len >> 3) + 2, NULL, &len2);
+ temp = (unsigned char *) MHD__asn1_alloca ((len >> 3) + 2 + len2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ MHD__asn1_bit_der ((const unsigned char *) value, len, temp, &len2);
+ MHD__asn1_set_value (node, temp, len2);
+ MHD__asn1_afree (temp);
+ break;
+ case TYPE_CHOICE:
+ p = node->down;
+ while (p)
+ {
+ if (!strcmp (p->name, value))
+ {
+ p2 = node->down;
+ while (p2)
+ {
+ if (p2 != p)
+ {
+ MHD__asn1_delete_structure (&p2);
+ p2 = node->down;
+ }
+ else
+ p2 = p2->right;
+ }
+ break;
+ }
+ p = p->right;
+ }
+ if (!p)
+ return ASN1_ELEMENT_NOT_FOUND;
+ break;
+ case TYPE_ANY:
+ MHD__asn1_length_der (len, NULL, &len2);
+ temp = (unsigned char *) MHD__asn1_alloca (len + len2);
+ if (temp == NULL)
+ return ASN1_MEM_ALLOC_ERROR;
+
+ MHD__asn1_octet_der ((const unsigned char *) value, len, temp, &len2);
+ MHD__asn1_set_value (node, temp, len2);
+ MHD__asn1_afree (temp);
+ break;
+ case TYPE_SEQUENCE_OF:
+ case TYPE_SET_OF:
+ if (strcmp (value, "NEW"))
+ return ASN1_VALUE_NOT_VALID;
+ MHD__asn1_append_sequence_set (node);
+ break;
+ default:
+ return ASN1_ELEMENT_NOT_FOUND;
+ break;
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+#define PUT_VALUE( ptr, ptr_size, data, data_size) \
+ *len = data_size; \
+ if (ptr_size < data_size) { \
+ return ASN1_MEM_ERROR; \
+ } else { \
+ memcpy( ptr, data, data_size); \
+ }
+
+#define PUT_STR_VALUE( ptr, ptr_size, data) \
+ *len = strlen(data) + 1; \
+ if (ptr_size < *len) { \
+ return ASN1_MEM_ERROR; \
+ } else { \
+ /* this strcpy is checked */ \
+ strcpy(ptr, data); \
+ }
+
+#define ADD_STR_VALUE( ptr, ptr_size, data) \
+ *len = strlen(data) + 1; \
+ if (ptr_size < strlen(ptr)+(*len)) { \
+ return ASN1_MEM_ERROR; \
+ } else { \
+ /* this strcat is checked */ \
+ strcat(ptr, data); \
+ }
+
+/**
+ * MHD__asn1_read_value - Returns the value of one element inside a structure
+ * @root: pointer to a structure.
+ * @name: the name of the element inside a structure that you want to read.
+ * @ivalue: vector that will contain the element's content, must be a
+ * pointer to memory cells already allocated.
+ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
+ * holds the sizeof value.
+ *
+ * Returns the value of one element inside a structure.
+ *
+ * If an element is OPTIONAL and the function "read_value" returns
+ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
+ * in the der encoding that created the structure. The first element
+ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
+ * so on.
+ *
+ * INTEGER: VALUE will contain a two's complement form integer.
+ *
+ * integer=-1 -> value[0]=0xFF , len=1.
+ * integer=1 -> value[0]=0x01 , len=1.
+ *
+ * ENUMERATED: As INTEGER (but only with not negative numbers).
+ *
+ * BOOLEAN: VALUE will be the null terminated string "TRUE" or
+ * "FALSE" and LEN=5 or LEN=6.
+ *
+ * OBJECT IDENTIFIER: VALUE will be a null terminated string with
+ * each number separated by a dot (i.e. "1.2.3.543.1").
+ *
+ * LEN = strlen(VALUE)+1
+ *
+ * UTCTime: VALUE will be a null terminated string in one of these
+ * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
+ * LEN=strlen(VALUE)+1.
+ *
+ * GeneralizedTime: VALUE will be a null terminated string in the
+ * same format used to set the value.
+ *
+ * OCTET STRING: VALUE will contain the octet string and LEN will be
+ * the number of octets.
+ *
+ * GeneralString: VALUE will contain the generalstring and LEN will
+ * be the number of octets.
+ *
+ * BIT STRING: VALUE will contain the bit string organized by bytes
+ * and LEN will be the number of bits.
+ *
+ * CHOICE: If NAME indicates a choice type, VALUE will specify the
+ * alternative selected.
+ *
+ * ANY: If NAME indicates an any type, VALUE will indicate the DER
+ * encoding of the structure actually used.
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: Set value OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+ *
+ * ASN1_VALUE_NOT_FOUND: There isn't any value for the element selected.
+ *
+ * ASN1_MEM_ERROR: The value vector isn't big enough to store the result.
+ * In this case LEN will contain the number of bytes needed.
+ *
+ **/
+MHD__asn1_retCode
+MHD__asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue,
+ int *len)
+{
+ node_asn *node, *p, *p2;
+ int len2, len3;
+ int value_size = *len;
+ char *value = ivalue;
+
+ node = MHD__asn1_find_node (root, name);
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ if ((type_field (node->type) != TYPE_NULL) &&
+ (type_field (node->type) != TYPE_CHOICE) &&
+ !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) &&
+ (node->value == NULL))
+ return ASN1_VALUE_NOT_FOUND;
+
+ switch (type_field (node->type))
+ {
+ case TYPE_NULL:
+ PUT_STR_VALUE (value, value_size, "NULL");
+ break;
+ case TYPE_BOOLEAN:
+ if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ if (p->type & CONST_TRUE)
+ {
+ PUT_STR_VALUE (value, value_size, "TRUE");
+ }
+ else
+ {
+ PUT_STR_VALUE (value, value_size, "FALSE");
+ }
+ }
+ else if (node->value[0] == 'T')
+ {
+ PUT_STR_VALUE (value, value_size, "TRUE");
+ }
+ else
+ {
+ PUT_STR_VALUE (value, value_size, "FALSE");
+ }
+ break;
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ if ((isdigit (p->value[0])) || (p->value[0] == '-')
+ || (p->value[0] == '+'))
+ {
+ if (MHD__asn1_convert_integer
+ ((const char *) p->value, (unsigned char *) value,
+ value_size, len) != ASN1_SUCCESS)
+ return ASN1_MEM_ERROR;
+ }
+ else
+ { /* is an identifier like v1 */
+ p2 = node->down;
+ while (p2)
+ {
+ if (type_field (p2->type) == TYPE_CONSTANT)
+ {
+ if ((p2->name)
+ && (!strcmp (p2->name, (const char *) p->value)))
+ {
+ if (MHD__asn1_convert_integer
+ ((const char *) p2->value,
+ (unsigned char *) value, value_size,
+ len) != ASN1_SUCCESS)
+ return ASN1_MEM_ERROR;
+ break;
+ }
+ }
+ p2 = p2->right;
+ }
+ }
+ }
+ else
+ {
+ len2 = -1;
+ if (MHD__asn1_get_octet_der
+ (node->value, node->value_len, &len2, (unsigned char *) value,
+ value_size, len) != ASN1_SUCCESS)
+ return ASN1_MEM_ERROR;
+ }
+ break;
+ case TYPE_OBJECT_ID:
+ if (node->type & CONST_ASSIGN)
+ {
+ value[0] = 0;
+ p = node->down;
+ while (p)
+ {
+ if (type_field (p->type) == TYPE_CONSTANT)
+ {
+ ADD_STR_VALUE (value, value_size, (const char *) p->value);
+ if (p->right)
+ {
+ ADD_STR_VALUE (value, value_size, ".");
+ }
+ }
+ p = p->right;
+ }
+ *len = strlen (value) + 1;
+ }
+ else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+ {
+ p = node->down;
+ while (type_field (p->type) != TYPE_DEFAULT)
+ p = p->right;
+ PUT_STR_VALUE (value, value_size, (const char *) p->value);
+ }
+ else
+ {
+ PUT_STR_VALUE (value, value_size, (const char *) node->value);
+ }
+ break;
+ case TYPE_TIME:
+ PUT_STR_VALUE (value, value_size, (const char *) node->value);
+ break;
+ case TYPE_OCTET_STRING:
+ len2 = -1;
+ if (MHD__asn1_get_octet_der
+ (node->value, node->value_len, &len2, (unsigned char *) value,
+ value_size, len) != ASN1_SUCCESS)
+ return ASN1_MEM_ERROR;
+ break;
+ case TYPE_GENERALSTRING:
+ len2 = -1;
+ if (MHD__asn1_get_octet_der
+ (node->value, node->value_len, &len2, (unsigned char *) value,
+ value_size, len) != ASN1_SUCCESS)
+ return ASN1_MEM_ERROR;
+ break;
+ case TYPE_BIT_STRING:
+ len2 = -1;
+ if (MHD__asn1_get_bit_der
+ (node->value, node->value_len, &len2, (unsigned char *) value,
+ value_size, len) != ASN1_SUCCESS)
+ return ASN1_MEM_ERROR;
+ break;
+ case TYPE_CHOICE:
+ PUT_STR_VALUE (value, value_size, node->down->name);
+ break;
+ case TYPE_ANY:
+ len3 = -1;
+ len2 = MHD__asn1_get_length_der (node->value, node->value_len, &len3);
+ if (len2 < 0)
+ return ASN1_DER_ERROR;
+ PUT_VALUE (value, value_size, node->value + len3, len2);
+ break;
+ default:
+ return ASN1_ELEMENT_NOT_FOUND;
+ break;
+ }
+ return ASN1_SUCCESS;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/element.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/element.h
new file mode 100644
index 0000000000..e4484925d9
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/element.h
@@ -0,0 +1,14 @@
+
+#ifndef _ELEMENT_H
+#define _ELEMENT_H
+
+
+MHD__asn1_retCode MHD__asn1_append_sequence_set (node_asn * node);
+
+MHD__asn1_retCode MHD__asn1_convert_integer (const char *value,
+ unsigned char *value_out,
+ int value_out_size, int *len);
+
+void MHD__asn1_hierarchical_name (node_asn * node, char *name, int name_size);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.c b/lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.c
new file mode 100644
index 0000000000..7068db51fc
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006 Free Software Foundation
+ * Copyright (C) 2002 Nikos Mavroyanopoulos
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <int.h>
+
+/* These function are like strcat, strcpy. They only
+ * do bounds checking (they shouldn't cause buffer overruns),
+ * and they always produce null terminated strings.
+ *
+ * They should be used only with null terminated strings.
+ */
+void
+MHD__asn1_str_cat (char *dest, size_t dest_tot_size, const char *src)
+{
+ size_t str_size = strlen (src);
+ size_t dest_size = strlen (dest);
+
+ if (dest_tot_size - dest_size > str_size)
+ {
+ strcat (dest, src);
+ }
+ else
+ {
+ if (dest_tot_size - dest_size > 0)
+ {
+ strncat (dest, src, (dest_tot_size - dest_size) - 1);
+ dest[dest_tot_size - 1] = 0;
+ }
+ }
+}
+
+void
+MHD__asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src)
+{
+ size_t str_size = strlen (src);
+
+ if (dest_tot_size > str_size)
+ {
+ strcpy (dest, src);
+ }
+ else
+ {
+ if (dest_tot_size > 0)
+ {
+ strncpy (dest, src, (dest_tot_size) - 1);
+ dest[dest_tot_size - 1] = 0;
+ }
+ }
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.h
new file mode 100644
index 0000000000..e0cda357b5
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/gstr.h
@@ -0,0 +1,5 @@
+void MHD__asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src);
+void MHD__asn1_str_cat (char *dest, size_t dest_tot_size, const char *src);
+
+#define Estrcpy(x,y) MHD__asn1_str_cpy(x,MAX_ERROR_DESCRIPTION_SIZE,y)
+#define Estrcat(x,y) MHD__asn1_str_cat(x,MAX_ERROR_DESCRIPTION_SIZE,y)
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/int.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/int.h
new file mode 100644
index 0000000000..a99fb6dbb1
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/int.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#ifndef INT_H
+#define INT_H
+
+#include <libtasn1.h>
+#include <defines.h>
+
+/*
+#define LIBTASN1_DEBUG
+#define LIBTASN1_DEBUG_PARSER
+#define LIBTASN1_DEBUG_INTEGER
+*/
+
+#include <mem.h>
+
+#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */
+
+/* Define used for visiting trees. */
+#define UP 1
+#define RIGHT 2
+#define DOWN 3
+
+/****************************************/
+/* Returns the first 8 bits. */
+/* Used with the field type of node_asn */
+/****************************************/
+#define type_field(x) (x&0xFF)
+
+/* List of constants for field type of typedef node_asn */
+#define TYPE_CONSTANT 1
+#define TYPE_IDENTIFIER 2
+#define TYPE_INTEGER 3
+#define TYPE_BOOLEAN 4
+#define TYPE_SEQUENCE 5
+#define TYPE_BIT_STRING 6
+#define TYPE_OCTET_STRING 7
+#define TYPE_TAG 8
+#define TYPE_DEFAULT 9
+#define TYPE_SIZE 10
+#define TYPE_SEQUENCE_OF 11
+#define TYPE_OBJECT_ID 12
+#define TYPE_ANY 13
+#define TYPE_SET 14
+#define TYPE_SET_OF 15
+#define TYPE_DEFINITIONS 16
+#define TYPE_TIME 17
+#define TYPE_CHOICE 18
+#define TYPE_IMPORTS 19
+#define TYPE_NULL 20
+#define TYPE_ENUMERATED 21
+#define TYPE_GENERALSTRING 27
+
+
+/***********************************************************************/
+/* List of constants to better specify the type of typedef node_asn. */
+/***********************************************************************/
+/* Used with TYPE_TAG */
+#define CONST_UNIVERSAL (1<<8)
+#define CONST_PRIVATE (1<<9)
+#define CONST_APPLICATION (1<<10)
+#define CONST_EXPLICIT (1<<11)
+#define CONST_IMPLICIT (1<<12)
+
+#define CONST_TAG (1<<13) /* Used in ASN.1 assignement */
+#define CONST_OPTION (1<<14)
+#define CONST_DEFAULT (1<<15)
+#define CONST_TRUE (1<<16)
+#define CONST_FALSE (1<<17)
+
+#define CONST_LIST (1<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */
+#define CONST_MIN_MAX (1<<19)
+
+#define CONST_1_PARAM (1<<20)
+
+#define CONST_SIZE (1<<21)
+
+#define CONST_DEFINED_BY (1<<22)
+
+#define CONST_GENERALIZED (1<<23)
+#define CONST_UTC (1<<24)
+
+/* #define CONST_IMPORTS (1<<25) */
+
+#define CONST_NOT_USED (1<<26)
+#define CONST_SET (1<<27)
+#define CONST_ASSIGN (1<<28)
+
+#define CONST_DOWN (1<<29)
+#define CONST_RIGHT (1<<30)
+
+#endif /* INT_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/libtasn1.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/libtasn1.h
new file mode 100644
index 0000000000..f478d0b7a5
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/libtasn1.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Free Software Foundation
+ * Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * LIBTASN1 is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * LIBTASN1 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with LIBTASN1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#ifndef LIBTASN1_H
+# define LIBTASN1_H
+
+#include <stdio.h> /* for FILE* */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define LIBTASN1_VERSION "1.2"
+
+#include <sys/types.h>
+#include <time.h>
+
+#define MAX_NAME_SIZE 128 /* maximum number of characters of a name */
+ /* inside a file with ASN1 definitons */
+#define MAX_ERROR_DESCRIPTION_SIZE 128 /* maximum number of characters */
+ /* of a description message */
+ /* (null character included) */
+
+
+ typedef int MHD__asn1_retCode; /* type returned by libtasn1 functions */
+
+ /*****************************************/
+ /* Errors returned by libtasn1 functions */
+ /*****************************************/
+#define ASN1_SUCCESS 0
+#define ASN1_FILE_NOT_FOUND 1
+#define ASN1_ELEMENT_NOT_FOUND 2
+#define ASN1_IDENTIFIER_NOT_FOUND 3
+#define ASN1_DER_ERROR 4
+#define ASN1_VALUE_NOT_FOUND 5
+#define ASN1_GENERIC_ERROR 6
+#define ASN1_VALUE_NOT_VALID 7
+#define ASN1_TAG_ERROR 8
+#define ASN1_TAG_IMPLICIT 9
+#define ASN1_ERROR_TYPE_ANY 10
+#define ASN1_SYNTAX_ERROR 11
+#define ASN1_MEM_ERROR 12
+#define ASN1_MEM_ALLOC_ERROR 13
+#define ASN1_DER_OVERFLOW 14
+#define ASN1_NAME_TOO_LONG 15
+#define ASN1_ARRAY_ERROR 16
+#define ASN1_ELEMENT_NOT_EMPTY 17
+
+/*************************************/
+/* Constants used in MHD__asn1_visit_tree */
+/*************************************/
+#define ASN1_PRINT_NAME 1
+#define ASN1_PRINT_NAME_TYPE 2
+#define ASN1_PRINT_NAME_TYPE_VALUE 3
+#define ASN1_PRINT_ALL 4
+
+/*****************************************/
+/* Constants returned by MHD__asn1_read_tag */
+/*****************************************/
+#define ASN1_CLASS_UNIVERSAL 0x00 /* old: 1 */
+#define ASN1_CLASS_APPLICATION 0x40 /* old: 2 */
+#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /* old: 3 */
+#define ASN1_CLASS_PRIVATE 0xC0 /* old: 4 */
+#define ASN1_CLASS_STRUCTURED 0x20
+
+/*****************************************/
+/* Constants returned by MHD__asn1_read_tag */
+/*****************************************/
+#define ASN1_TAG_BOOLEAN 0x01
+#define ASN1_TAG_INTEGER 0x02
+#define ASN1_TAG_SEQUENCE 0x10
+#define ASN1_TAG_SET 0x11
+#define ASN1_TAG_OCTET_STRING 0x04
+#define ASN1_TAG_BIT_STRING 0x03
+#define ASN1_TAG_UTCTime 0x17
+#define ASN1_TAG_GENERALIZEDTime 0x18
+#define ASN1_TAG_OBJECT_ID 0x06
+#define ASN1_TAG_ENUMERATED 0x0A
+#define ASN1_TAG_NULL 0x05
+#define ASN1_TAG_GENERALSTRING 0x1B
+
+/******************************************************/
+/* Structure definition used for the node of the tree */
+/* that represent an ASN.1 DEFINITION. */
+/******************************************************/
+
+ struct node_asn_struct
+ {
+ char *name; /* Node name */
+ unsigned int type; /* Node type */
+ unsigned char *value; /* Node value */
+ int value_len;
+ struct node_asn_struct *down; /* Pointer to the son node */
+ struct node_asn_struct *right; /* Pointer to the brother node */
+ struct node_asn_struct *left; /* Pointer to the next list element */
+ };
+
+ typedef struct node_asn_struct node_asn;
+
+ typedef node_asn *ASN1_TYPE;
+
+#define ASN1_TYPE_EMPTY NULL
+
+ struct static_struct_asn
+ {
+ const char *name; /* Node name */
+ unsigned int type; /* Node type */
+ const void *value; /* Node value */
+ };
+
+ typedef struct static_struct_asn ASN1_ARRAY_TYPE;
+
+
+
+ /***********************************/
+ /* Functions definitions */
+ /***********************************/
+
+ MHD__asn1_retCode MHD__asn1_parser2tree (const char *file_name,
+ ASN1_TYPE * definitions,
+ char *errorDescription);
+
+ MHD__asn1_retCode MHD__asn1_parser2array (const char *inputFileName,
+ const char *outputFileName,
+ const char *vectorName,
+ char *errorDescription);
+
+ MHD__asn1_retCode MHD__asn1_array2tree (const ASN1_ARRAY_TYPE * array,
+ ASN1_TYPE * definitions,
+ char *errorDescription);
+
+ MHD__asn1_retCode MHD__asn1_create_element (ASN1_TYPE definitions,
+ const char *source_name,
+ ASN1_TYPE * element);
+
+ MHD__asn1_retCode MHD__asn1_delete_structure (ASN1_TYPE * structure);
+
+ MHD__asn1_retCode MHD__asn1_write_value (ASN1_TYPE node_root,
+ const char *name,
+ const void *ivalue, int len);
+
+ MHD__asn1_retCode MHD__asn1_read_value (ASN1_TYPE root, const char *name,
+ void *ivalue, int *len);
+
+ MHD__asn1_retCode MHD__asn1_der_coding (ASN1_TYPE element, const char *name,
+ void *ider, int *len,
+ char *ErrorDescription);
+
+ MHD__asn1_retCode MHD__asn1_der_decoding (ASN1_TYPE * element,
+ const void *ider, int len,
+ char *errorDescription);
+
+ MHD__asn1_retCode MHD__asn1_der_decoding_startEnd (ASN1_TYPE element,
+ const void *ider,
+ int len,
+ const char *name_element,
+ int *start, int *end);
+
+ /* DER utility functions. */
+
+ int MHD__asn1_get_tag_der (const unsigned char *der, int der_len,
+ unsigned char *cls, int *len,
+ unsigned long *tag);
+
+ void MHD__asn1_octet_der (const unsigned char *str, int str_len,
+ unsigned char *der, int *der_len);
+
+ MHD__asn1_retCode MHD__asn1_get_octet_der (const unsigned char *der,
+ int der_len, int *ret_len,
+ unsigned char *str, int str_size,
+ int *str_len);
+
+ void MHD__asn1_bit_der (const unsigned char *str, int bit_len,
+ unsigned char *der, int *der_len);
+
+ MHD__asn1_retCode MHD__asn1_get_bit_der (const unsigned char *der,
+ int der_len, int *ret_len,
+ unsigned char *str, int str_size,
+ int *bit_len);
+
+ signed long MHD__asn1_get_length_der (const unsigned char *der, int der_len,
+ int *len);
+
+ void MHD__asn1_length_der (unsigned long int len, unsigned char *ans,
+ int *ans_len);
+
+ /* Other utility functions. */
+
+ ASN1_TYPE MHD__asn1_find_node (ASN1_TYPE pointer, const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBTASN1_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/mem.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/mem.h
new file mode 100644
index 0000000000..76139df034
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/mem.h
@@ -0,0 +1,25 @@
+#ifndef MEM_H
+# define MEM_H
+
+/* Use MHD__asn1_afree() when calling alloca, or
+ * memory leaks may occur in systems which do not
+ * support alloca.
+ */
+#ifdef HAVE_ALLOCA
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# endif
+# define MHD__asn1_alloca alloca
+# define MHD__asn1_afree(x)
+#else
+# define MHD__asn1_alloca MHD__asn1_malloc
+# define MHD__asn1_afree MHD__asn1_free
+#endif /* HAVE_ALLOCA */
+
+#define MHD__asn1_malloc malloc
+#define MHD__asn1_free free
+#define MHD__asn1_calloc calloc
+#define MHD__asn1_realloc realloc
+#define MHD__asn1_strdup strdup
+
+#endif /* MEM_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.c b/lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.c
new file mode 100644
index 0000000000..0643ff4c56
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Free Software Foundation
+ * Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <int.h>
+#include "parser_aux.h"
+#include "gstr.h"
+#include "structure.h"
+#include "element.h"
+
+
+
+char MHD__asn1_identifierMissing[MAX_NAME_SIZE + 1]; /* identifier name not found */
+
+/***********************************************/
+/* Type: list_type */
+/* Description: type used in the list during */
+/* the structure creation. */
+/***********************************************/
+typedef struct list_struct
+{
+ node_asn *node;
+ struct list_struct *next;
+} list_type;
+
+
+/* Pointer to the first element of the list */
+list_type *MHD_firstElement = NULL;
+
+/******************************************************/
+/* Function : MHD__asn1_add_node */
+/* Description: creates a new NODE_ASN element and */
+/* puts it in the list pointed by MHD_firstElement. */
+/* Parameters: */
+/* type: type of the new element (see TYPE_ */
+/* and CONST_ constants). */
+/* Return: pointer to the new element. */
+/******************************************************/
+node_asn *
+MHD__asn1_add_node (unsigned int type)
+{
+ list_type *listElement;
+ node_asn *punt;
+
+ punt = (node_asn *) MHD__asn1_calloc (1, sizeof (node_asn));
+ if (punt == NULL)
+ return NULL;
+
+ listElement = (list_type *) MHD__asn1_malloc (sizeof (list_type));
+ if (listElement == NULL)
+ {
+ MHD__asn1_free (punt);
+ return NULL;
+ }
+
+ listElement->node = punt;
+ listElement->next = MHD_firstElement;
+ MHD_firstElement = listElement;
+
+ punt->type = type;
+
+ return punt;
+}
+
+/**
+ * MHD__asn1_find_node:
+ * @pointer: NODE_ASN element pointer.
+ * @name: null terminated string with the element's name to find.
+ *
+ * Searches for an element called NAME starting from POINTER. The
+ * name is composed by differents identifiers separated by dots. When
+ * *POINTER has a name, the first identifier must be the name of
+ * *POINTER, otherwise it must be the name of one child of *POINTER.
+ *
+ * Return value: the searching result. NULL if not found.
+ **/
+ASN1_TYPE
+MHD__asn1_find_node (ASN1_TYPE pointer, const char *name)
+{
+ node_asn *p;
+ char *n_end, n[MAX_NAME_SIZE + 1];
+ const char *n_start;
+
+ if (pointer == NULL)
+ return NULL;
+
+ if (name == NULL)
+ return NULL;
+
+ p = pointer;
+ n_start = name;
+
+ if (p->name != NULL)
+ { /* has *pointer got a name ? */
+ n_end = strchr (n_start, '.'); /* search the first dot */
+ if (n_end)
+ {
+ memcpy (n, n_start, n_end - n_start);
+ n[n_end - n_start] = 0;
+ n_start = n_end;
+ n_start++;
+ }
+ else
+ {
+ MHD__asn1_str_cpy (n, sizeof (n), n_start);
+ n_start = NULL;
+ }
+
+ while (p)
+ {
+ if ((p->name) && (!strcmp (p->name, n)))
+ break;
+ else
+ p = p->right;
+ } /* while */
+
+ if (p == NULL)
+ return NULL;
+ }
+ else
+ { /* *pointer doesn't have a name */
+ if (n_start[0] == 0)
+ return p;
+ }
+
+ while (n_start)
+ { /* Has the end of NAME been reached? */
+ n_end = strchr (n_start, '.'); /* search the next dot */
+ if (n_end)
+ {
+ memcpy (n, n_start, n_end - n_start);
+ n[n_end - n_start] = 0;
+ n_start = n_end;
+ n_start++;
+ }
+ else
+ {
+ MHD__asn1_str_cpy (n, sizeof (n), n_start);
+ n_start = NULL;
+ }
+
+ if (p->down == NULL)
+ return NULL;
+
+ p = p->down;
+
+ /* The identifier "?LAST" indicates the last element
+ in the right chain. */
+ if (!strcmp (n, "?LAST"))
+ {
+ if (p == NULL)
+ return NULL;
+ while (p->right)
+ p = p->right;
+ }
+ else
+ { /* no "?LAST" */
+ while (p)
+ {
+ if ((p->name) && (!strcmp (p->name, n)))
+ break;
+ else
+ p = p->right;
+ }
+ if (p == NULL)
+ return NULL;
+ }
+ } /* while */
+
+ return p;
+}
+
+
+/******************************************************************/
+/* Function : MHD__asn1_set_value */
+/* Description: sets the field VALUE in a NODE_ASN element. The */
+/* previous value (if exist) will be lost */
+/* Parameters: */
+/* node: element pointer. */
+/* value: pointer to the value that you want to set. */
+/* len: character number of value. */
+/* Return: pointer to the NODE_ASN element. */
+/******************************************************************/
+node_asn *
+MHD__asn1_set_value (node_asn * node, const void *_value, unsigned int len)
+{
+ const unsigned char *value = _value;
+
+ if (node == NULL)
+ return node;
+ if (node->value)
+ {
+ MHD__asn1_free (node->value);
+ node->value = NULL;
+ node->value_len = 0;
+ }
+ if (!len)
+ return node;
+ node->value = (unsigned char *) MHD__asn1_malloc (len);
+ if (node->value == NULL)
+ return NULL;
+ node->value_len = len;
+
+ memcpy (node->value, value, len);
+ return node;
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_set_name */
+/* Description: sets the field NAME in a NODE_ASN element. The */
+/* previous value (if exist) will be lost */
+/* Parameters: */
+/* node: element pointer. */
+/* name: a null terminated string with the name that you want */
+/* to set. */
+/* Return: pointer to the NODE_ASN element. */
+/******************************************************************/
+node_asn *
+MHD__asn1_set_name (node_asn * node, const char *name)
+{
+ if (node == NULL)
+ return node;
+
+ if (node->name)
+ {
+ MHD__asn1_free (node->name);
+ node->name = NULL;
+ }
+
+ if (name == NULL)
+ return node;
+
+ if (strlen (name))
+ {
+ node->name = (char *) MHD__asn1_strdup (name);
+ if (node->name == NULL)
+ return NULL;
+ }
+ else
+ node->name = NULL;
+ return node;
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_set_right */
+/* Description: sets the field RIGHT in a NODE_ASN element. */
+/* Parameters: */
+/* node: element pointer. */
+/* right: pointer to a NODE_ASN element that you want be pointed*/
+/* by NODE. */
+/* Return: pointer to *NODE. */
+/******************************************************************/
+node_asn *
+MHD__asn1_set_right (node_asn * node, node_asn * right)
+{
+ if (node == NULL)
+ return node;
+ node->right = right;
+ if (right)
+ right->left = node;
+ return node;
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_set_down */
+/* Description: sets the field DOWN in a NODE_ASN element. */
+/* Parameters: */
+/* node: element pointer. */
+/* down: pointer to a NODE_ASN element that you want be pointed */
+/* by NODE. */
+/* Return: pointer to *NODE. */
+/******************************************************************/
+node_asn *
+MHD__asn1_set_down (node_asn * node, node_asn * down)
+{
+ if (node == NULL)
+ return node;
+ node->down = down;
+ if (down)
+ down->left = node;
+ return node;
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_remove_node */
+/* Description: gets free the memory allocated for an NODE_ASN */
+/* element (not the elements pointed by it). */
+/* Parameters: */
+/* node: NODE_ASN element pointer. */
+/******************************************************************/
+void
+MHD__asn1_remove_node (node_asn * node)
+{
+ if (node == NULL)
+ return;
+
+ if (node->name != NULL)
+ MHD__asn1_free (node->name);
+ if (node->value != NULL)
+ MHD__asn1_free (node->value);
+ MHD__asn1_free (node);
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_find_up */
+/* Description: return the father of the NODE_ASN element. */
+/* Parameters: */
+/* node: NODE_ASN element pointer. */
+/* Return: Null if not found. */
+/******************************************************************/
+node_asn *
+MHD__asn1_find_up (node_asn * node)
+{
+ node_asn *p;
+
+ if (node == NULL)
+ return NULL;
+
+ p = node;
+
+ while ((p->left != NULL) && (p->left->right == p))
+ p = p->left;
+
+ return p->left;
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_delete_list */
+/* Description: deletes the list elements (not the elements */
+/* pointed by them). */
+/******************************************************************/
+void
+MHD__asn1_delete_list (void)
+{
+ list_type *listElement;
+
+ while (MHD_firstElement)
+ {
+ listElement = MHD_firstElement;
+ MHD_firstElement = MHD_firstElement->next;
+ MHD__asn1_free (listElement);
+ }
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_delete_list_and nodes */
+/* Description: deletes the list elements and the elements */
+/* pointed by them. */
+/******************************************************************/
+void
+MHD__asn1_delete_list_and_nodes (void)
+{
+ list_type *listElement;
+
+ while (MHD_firstElement)
+ {
+ listElement = MHD_firstElement;
+ MHD_firstElement = MHD_firstElement->next;
+ MHD__asn1_remove_node (listElement->node);
+ MHD__asn1_free (listElement);
+ }
+}
+
+
+char *
+MHD__asn1_ltostr (long v, char *str)
+{
+ long d, r;
+ char temp[20];
+ int count, k, start;
+
+ if (v < 0)
+ {
+ str[0] = '-';
+ start = 1;
+ v = -v;
+ }
+ else
+ start = 0;
+
+ count = 0;
+ do
+ {
+ d = v / 10;
+ r = v - d * 10;
+ temp[start + count] = '0' + (char) r;
+ count++;
+ v = d;
+ }
+ while (v);
+
+ for (k = 0; k < count; k++)
+ str[k + start] = temp[start + count - k - 1];
+ str[count + start] = 0;
+ return str;
+}
+
+
+/******************************************************************/
+/* Function : MHD__asn1_change_integer_value */
+/* Description: converts into DER coding the value assign to an */
+/* INTEGER constant. */
+/* Parameters: */
+/* node: root of an ASN1element. */
+/* Return: */
+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
+/* otherwise ASN1_SUCCESS */
+/******************************************************************/
+MHD__asn1_retCode
+MHD__asn1_change_integer_value (ASN1_TYPE node)
+{
+ node_asn *p;
+ unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
+ unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
+ int len;
+
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = node;
+ while (p)
+ {
+ if ((type_field (p->type) == TYPE_INTEGER) && (p->type & CONST_ASSIGN))
+ {
+ if (p->value)
+ {
+ MHD__asn1_convert_integer ((const char *) p->value, val,
+ sizeof (val), &len);
+ MHD__asn1_octet_der (val, len, val2, &len);
+ MHD__asn1_set_value (p, val2, len);
+ }
+ }
+
+ if (p->down)
+ {
+ p = p->down;
+ }
+ else
+ {
+ if (p == node)
+ p = NULL;
+ else if (p->right)
+ p = p->right;
+ else
+ {
+ while (1)
+ {
+ p = MHD__asn1_find_up (p);
+ if (p == node)
+ {
+ p = NULL;
+ break;
+ }
+ if (p->right)
+ {
+ p = p->right;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+/******************************************************************/
+/* Function : MHD__asn1_expand_object_id */
+/* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
+/* Parameters: */
+/* node: root of an ASN1 element. */
+/* Return: */
+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
+/* otherwise ASN1_SUCCESS */
+/******************************************************************/
+MHD__asn1_retCode
+MHD__asn1_expand_object_id (ASN1_TYPE node)
+{
+ node_asn *p, *p2, *p3, *p4, *p5;
+ char name_root[MAX_NAME_SIZE], name2[2 * MAX_NAME_SIZE + 1];
+ int move, tlen;
+
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ MHD__asn1_str_cpy (name_root, sizeof (name_root), node->name);
+
+ p = node;
+ move = DOWN;
+
+ while (!((p == node) && (move == UP)))
+ {
+ if (move != UP)
+ {
+ if ((type_field (p->type) == TYPE_OBJECT_ID)
+ && (p->type & CONST_ASSIGN))
+ {
+ p2 = p->down;
+ if (p2 && (type_field (p2->type) == TYPE_CONSTANT))
+ {
+ if (p2->value && !isdigit (p2->value[0]))
+ {
+ MHD__asn1_str_cpy (name2, sizeof (name2), name_root);
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2),
+ (const char *) p2->value);
+ p3 = MHD__asn1_find_node (node, name2);
+ if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+ !(p3->type & CONST_ASSIGN))
+ return ASN1_ELEMENT_NOT_FOUND;
+ MHD__asn1_set_down (p, p2->right);
+ MHD__asn1_remove_node (p2);
+ p2 = p;
+ p4 = p3->down;
+ while (p4)
+ {
+ if (type_field (p4->type) == TYPE_CONSTANT)
+ {
+ p5 = MHD__asn1_add_node_only (TYPE_CONSTANT);
+ MHD__asn1_set_name (p5, p4->name);
+ tlen = strlen ((const char *) p4->value);
+ if (tlen > 0)
+ MHD__asn1_set_value (p5, p4->value, tlen + 1);
+ if (p2 == p)
+ {
+ MHD__asn1_set_right (p5, p->down);
+ MHD__asn1_set_down (p, p5);
+ }
+ else
+ {
+ MHD__asn1_set_right (p5, p2->right);
+ MHD__asn1_set_right (p2, p5);
+ }
+ p2 = p5;
+ }
+ p4 = p4->right;
+ }
+ move = DOWN;
+ continue;
+ }
+ }
+ }
+ move = DOWN;
+ }
+ else
+ move = RIGHT;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+
+ if (p == node)
+ {
+ move = UP;
+ continue;
+ }
+
+ if (move == RIGHT)
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+
+ /*******************************/
+ /* expand DEFAULT */
+ /*******************************/
+ p = node;
+ move = DOWN;
+
+ while (!((p == node) && (move == UP)))
+ {
+ if (move != UP)
+ {
+ if ((type_field (p->type) == TYPE_OBJECT_ID) &&
+ (p->type & CONST_DEFAULT))
+ {
+ p2 = p->down;
+ if (p2 && (type_field (p2->type) == TYPE_DEFAULT))
+ {
+ MHD__asn1_str_cpy (name2, sizeof (name2), name_root);
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2),
+ (const char *) p2->value);
+ p3 = MHD__asn1_find_node (node, name2);
+ if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+ !(p3->type & CONST_ASSIGN))
+ return ASN1_ELEMENT_NOT_FOUND;
+ p4 = p3->down;
+ name2[0] = 0;
+ while (p4)
+ {
+ if (type_field (p4->type) == TYPE_CONSTANT)
+ {
+ if (name2[0])
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2),
+ (const char *) p4->value);
+ }
+ p4 = p4->right;
+ }
+ tlen = strlen (name2);
+ if (tlen > 0)
+ MHD__asn1_set_value (p2, name2, tlen + 1);
+ }
+ }
+ move = DOWN;
+ }
+ else
+ move = RIGHT;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+
+ if (p == node)
+ {
+ move = UP;
+ continue;
+ }
+
+ if (move == RIGHT)
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+ return ASN1_SUCCESS;
+}
+
+/******************************************************************/
+/* Function : MHD__asn1_check_identifier */
+/* Description: checks the definitions of all the identifiers */
+/* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
+/* The MHD__asn1_identifierMissing global variable is filled if */
+/* necessary. */
+/* Parameters: */
+/* node: root of an ASN1 element. */
+/* Return: */
+/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
+/* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
+/* otherwise ASN1_SUCCESS */
+/******************************************************************/
+MHD__asn1_retCode
+MHD__asn1_check_identifier (ASN1_TYPE node)
+{
+ node_asn *p, *p2;
+ char name2[MAX_NAME_SIZE * 2 + 2];
+
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = node;
+ while (p)
+ {
+ if (type_field (p->type) == TYPE_IDENTIFIER)
+ {
+ MHD__asn1_str_cpy (name2, sizeof (name2), node->name);
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2), (const char *) p->value);
+ p2 = MHD__asn1_find_node (node, name2);
+ if (p2 == NULL)
+ {
+ strcpy (MHD__asn1_identifierMissing, (const char *) p->value);
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ }
+ }
+ else if ((type_field (p->type) == TYPE_OBJECT_ID) &&
+ (p->type & CONST_DEFAULT))
+ {
+ p2 = p->down;
+ if (p2 && (type_field (p2->type) == TYPE_DEFAULT))
+ {
+ MHD__asn1_str_cpy (name2, sizeof (name2), node->name);
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2),
+ (const char *) p2->value);
+ strcpy (MHD__asn1_identifierMissing, (const char *) p2->value);
+ p2 = MHD__asn1_find_node (node, name2);
+ if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
+ !(p2->type & CONST_ASSIGN))
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ else
+ MHD__asn1_identifierMissing[0] = 0;
+ }
+ }
+ else if ((type_field (p->type) == TYPE_OBJECT_ID) &&
+ (p->type & CONST_ASSIGN))
+ {
+ p2 = p->down;
+ if (p2 && (type_field (p2->type) == TYPE_CONSTANT))
+ {
+ if (p2->value && !isdigit (p2->value[0]))
+ {
+ MHD__asn1_str_cpy (name2, sizeof (name2), node->name);
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2),
+ (const char *) p2->value);
+ strcpy (MHD__asn1_identifierMissing,
+ (const char *) p2->value);
+ p2 = MHD__asn1_find_node (node, name2);
+ if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
+ !(p2->type & CONST_ASSIGN))
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ else
+ MHD__asn1_identifierMissing[0] = 0;
+ }
+ }
+ }
+
+ if (p->down)
+ {
+ p = p->down;
+ }
+ else if (p->right)
+ p = p->right;
+ else
+ {
+ while (1)
+ {
+ p = MHD__asn1_find_up (p);
+ if (p == node)
+ {
+ p = NULL;
+ break;
+ }
+ if (p->right)
+ {
+ p = p->right;
+ break;
+ }
+ }
+ }
+ }
+
+ return ASN1_SUCCESS;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.h
new file mode 100644
index 0000000000..4437fb191e
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/parser_aux.h
@@ -0,0 +1,37 @@
+
+#ifndef _PARSER_AUX_H
+#define _PARSER_AUX_H
+
+
+/***************************************/
+/* Functions used by ASN.1 parser */
+/***************************************/
+node_asn *MHD__asn1_add_node (unsigned int type);
+
+node_asn *MHD__asn1_set_value (node_asn * node, const void *value,
+ unsigned int len);
+
+node_asn *MHD__asn1_set_name (node_asn * node, const char *name);
+
+node_asn *MHD__asn1_set_right (node_asn * node, node_asn * right);
+
+node_asn *MHD__asn1_set_down (node_asn * node, node_asn * down);
+
+void MHD__asn1_remove_node (node_asn * node);
+
+void MHD__asn1_delete_list (void);
+
+void MHD__asn1_delete_list_and_nodes (void);
+
+char *MHD__asn1_ltostr (long v, char *str);
+
+node_asn *MHD__asn1_find_up (node_asn * node);
+
+MHD__asn1_retCode MHD__asn1_change_integer_value (ASN1_TYPE node);
+
+MHD__asn1_retCode MHD__asn1_expand_object_id (ASN1_TYPE node);
+
+MHD__asn1_retCode MHD__asn1_check_identifier (ASN1_TYPE node);
+
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/structure.c b/lib/libmicrohttpd/src/daemon/https/minitasn1/structure.c
new file mode 100644
index 0000000000..fdaeea471b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/structure.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Free Software Foundation
+ * Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+
+/*****************************************************/
+/* File: structure.c */
+/* Description: Functions to create and delete an */
+/* ASN1 tree. */
+/*****************************************************/
+
+
+#include <int.h>
+#include <structure.h>
+#include "parser_aux.h"
+#include <gstr.h>
+
+
+extern char MHD__asn1_identifierMissing[];
+
+static node_asn *MHD__asn1_copy_structure2 (node_asn * root,
+ const char *source_name);
+
+
+
+/******************************************************/
+/* Function : MHD__asn1_add_node_only */
+/* Description: creates a new NODE_ASN element. */
+/* Parameters: */
+/* type: type of the new element (see TYPE_ */
+/* and CONST_ constants). */
+/* Return: pointer to the new element. */
+/******************************************************/
+node_asn *
+MHD__asn1_add_node_only (unsigned int type)
+{
+ node_asn *punt;
+
+ punt = (node_asn *) MHD__asn1_calloc (1, sizeof (node_asn));
+ if (punt == NULL)
+ return NULL;
+
+ punt->type = type;
+
+ return punt;
+}
+
+
+/******************************************************************/
+/* Function : MHD__asn1_find_left */
+/* Description: returns the NODE_ASN element with RIGHT field that*/
+/* points the element NODE. */
+/* Parameters: */
+/* node: NODE_ASN element pointer. */
+/* Return: NULL if not found. */
+/******************************************************************/
+node_asn *
+MHD__asn1_find_left (node_asn * node)
+{
+ if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
+ return NULL;
+
+ return node->left;
+}
+
+
+
+/**
+ * MHD__asn1_array2tree - Creates the structures needed to manage the ASN1 definitions.
+ * @array: specify the array that contains ASN.1 declarations
+ * @definitions: return the pointer to the structure created by
+ * *ARRAY ASN.1 declarations
+ * @errorDescription: return the error description.
+ *
+ * Creates the structures needed to manage the ASN.1 definitions.
+ * @array is a vector created by MHD__asn1_parser2array().
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: Structure created correctly.
+ *
+ * ASN1_ELEMENT_NOT_EMPTY: *@definitions not ASN1_TYPE_EMPTY.
+ *
+ * ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+ * is not defined (see @errorDescription for more information).
+ *
+ * ASN1_ARRAY_ERROR: The array pointed by @array is wrong.
+ **/
+MHD__asn1_retCode
+MHD__asn1_array2tree (const ASN1_ARRAY_TYPE * array, ASN1_TYPE * definitions,
+ char *errorDescription)
+{
+ node_asn *p, *p_last = NULL;
+ unsigned long k;
+ int move;
+ MHD__asn1_retCode result;
+
+
+ if (*definitions != ASN1_TYPE_EMPTY)
+ return ASN1_ELEMENT_NOT_EMPTY;
+
+ move = UP;
+
+ k = 0;
+ while (array[k].value || array[k].type || array[k].name)
+ {
+ p = MHD__asn1_add_node (array[k].type & (~CONST_DOWN));
+ if (array[k].name)
+ MHD__asn1_set_name (p, array[k].name);
+ if (array[k].value)
+ MHD__asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
+
+ if (*definitions == NULL)
+ *definitions = p;
+
+ if (move == DOWN)
+ MHD__asn1_set_down (p_last, p);
+ else if (move == RIGHT)
+ MHD__asn1_set_right (p_last, p);
+
+ p_last = p;
+
+ if (array[k].type & CONST_DOWN)
+ move = DOWN;
+ else if (array[k].type & CONST_RIGHT)
+ move = RIGHT;
+ else
+ {
+ while (1)
+ {
+ if (p_last == *definitions)
+ break;
+
+ p_last = MHD__asn1_find_up (p_last);
+
+ if (p_last == NULL)
+ break;
+
+ if (p_last->type & CONST_RIGHT)
+ {
+ p_last->type &= ~CONST_RIGHT;
+ move = RIGHT;
+ break;
+ }
+ } /* while */
+ }
+ k++;
+ } /* while */
+
+ if (p_last == *definitions)
+ {
+ result = MHD__asn1_check_identifier (*definitions);
+ if (result == ASN1_SUCCESS)
+ {
+ MHD__asn1_change_integer_value (*definitions);
+ MHD__asn1_expand_object_id (*definitions);
+ }
+ }
+ else
+ {
+ result = ASN1_ARRAY_ERROR;
+ }
+
+ if (errorDescription != NULL)
+ {
+ if (result == ASN1_IDENTIFIER_NOT_FOUND)
+ {
+ Estrcpy (errorDescription, ":: identifier '");
+ Estrcat (errorDescription, MHD__asn1_identifierMissing);
+ Estrcat (errorDescription, "' not found");
+ }
+ else
+ errorDescription[0] = 0;
+ }
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD__asn1_delete_list_and_nodes ();
+ *definitions = ASN1_TYPE_EMPTY;
+ }
+ else
+ MHD__asn1_delete_list ();
+
+ return result;
+}
+
+/**
+ * MHD__asn1_delete_structure - Deletes the structure pointed by *ROOT.
+ * @structure: pointer to the structure that you want to delete.
+ *
+ * Deletes the structure *@structure. At the end, *@structure is set
+ * to ASN1_TYPE_EMPTY.
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: Everything OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: *@structure was ASN1_TYPE_EMPTY.
+ *
+ **/
+MHD__asn1_retCode
+MHD__asn1_delete_structure (ASN1_TYPE * structure)
+{
+ node_asn *p, *p2, *p3;
+
+ if (*structure == ASN1_TYPE_EMPTY)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = *structure;
+ while (p)
+ {
+ if (p->down)
+ {
+ p = p->down;
+ }
+ else
+ { /* no down */
+ p2 = p->right;
+ if (p != *structure)
+ {
+ p3 = MHD__asn1_find_up (p);
+ MHD__asn1_set_down (p3, p2);
+ MHD__asn1_remove_node (p);
+ p = p3;
+ }
+ else
+ { /* p==root */
+ p3 = MHD__asn1_find_left (p);
+ if (!p3)
+ {
+ p3 = MHD__asn1_find_up (p);
+ if (p3)
+ MHD__asn1_set_down (p3, p2);
+ else
+ {
+ if (p->right)
+ p->right->left = NULL;
+ }
+ }
+ else
+ MHD__asn1_set_right (p3, p2);
+ MHD__asn1_remove_node (p);
+ p = NULL;
+ }
+ }
+ }
+
+ *structure = ASN1_TYPE_EMPTY;
+ return ASN1_SUCCESS;
+}
+
+node_asn *
+MHD__asn1_copy_structure3 (node_asn * source_node)
+{
+ node_asn *dest_node, *p_s, *p_d, *p_d_prev;
+ int move;
+
+ if (source_node == NULL)
+ return NULL;
+
+ dest_node = MHD__asn1_add_node_only (source_node->type);
+
+ p_s = source_node;
+ p_d = dest_node;
+
+ move = DOWN;
+
+ do
+ {
+ if (move != UP)
+ {
+ if (p_s->name)
+ MHD__asn1_set_name (p_d, p_s->name);
+ if (p_s->value)
+ MHD__asn1_set_value (p_d, p_s->value, p_s->value_len);
+ move = DOWN;
+ }
+ else
+ move = RIGHT;
+
+ if (move == DOWN)
+ {
+ if (p_s->down)
+ {
+ p_s = p_s->down;
+ p_d_prev = p_d;
+ p_d = MHD__asn1_add_node_only (p_s->type);
+ MHD__asn1_set_down (p_d_prev, p_d);
+ }
+ else
+ move = RIGHT;
+ }
+
+ if (p_s == source_node)
+ break;
+
+ if (move == RIGHT)
+ {
+ if (p_s->right)
+ {
+ p_s = p_s->right;
+ p_d_prev = p_d;
+ p_d = MHD__asn1_add_node_only (p_s->type);
+ MHD__asn1_set_right (p_d_prev, p_d);
+ }
+ else
+ move = UP;
+ }
+ if (move == UP)
+ {
+ p_s = MHD__asn1_find_up (p_s);
+ p_d = MHD__asn1_find_up (p_d);
+ }
+ }
+ while (p_s != source_node);
+
+ return dest_node;
+}
+
+
+static node_asn *
+MHD__asn1_copy_structure2 (node_asn * root, const char *source_name)
+{
+ node_asn *source_node;
+
+ source_node = MHD__asn1_find_node (root, source_name);
+
+ return MHD__asn1_copy_structure3 (source_node);
+
+}
+
+
+static MHD__asn1_retCode
+MHD__asn1_type_choice_config (node_asn * node)
+{
+ node_asn *p, *p2, *p3, *p4;
+ int move, tlen;
+
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = node;
+ move = DOWN;
+
+ while (!((p == node) && (move == UP)))
+ {
+ if (move != UP)
+ {
+ if ((type_field (p->type) == TYPE_CHOICE) && (p->type & CONST_TAG))
+ {
+ p2 = p->down;
+ while (p2)
+ {
+ if (type_field (p2->type) != TYPE_TAG)
+ {
+ p2->type |= CONST_TAG;
+ p3 = MHD__asn1_find_left (p2);
+ while (p3)
+ {
+ if (type_field (p3->type) == TYPE_TAG)
+ {
+ p4 = MHD__asn1_add_node_only (p3->type);
+ tlen = strlen ((const char *) p3->value);
+ if (tlen > 0)
+ MHD__asn1_set_value (p4, p3->value, tlen + 1);
+ MHD__asn1_set_right (p4, p2->down);
+ MHD__asn1_set_down (p2, p4);
+ }
+ p3 = MHD__asn1_find_left (p3);
+ }
+ }
+ p2 = p2->right;
+ }
+ p->type &= ~(CONST_TAG);
+ p2 = p->down;
+ while (p2)
+ {
+ p3 = p2->right;
+ if (type_field (p2->type) == TYPE_TAG)
+ MHD__asn1_delete_structure (&p2);
+ p2 = p3;
+ }
+ }
+ move = DOWN;
+ }
+ else
+ move = RIGHT;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+
+ if (p == node)
+ {
+ move = UP;
+ continue;
+ }
+
+ if (move == RIGHT)
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+static MHD__asn1_retCode
+MHD__asn1_expand_identifier (node_asn ** node, node_asn * root)
+{
+ node_asn *p, *p2, *p3;
+ char name2[MAX_NAME_SIZE + 2];
+ int move;
+
+ if (node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ p = *node;
+ move = DOWN;
+
+ while (!((p == *node) && (move == UP)))
+ {
+ if (move != UP)
+ {
+ if (type_field (p->type) == TYPE_IDENTIFIER)
+ {
+ MHD__asn1_str_cpy (name2, sizeof (name2), root->name);
+ MHD__asn1_str_cat (name2, sizeof (name2), ".");
+ MHD__asn1_str_cat (name2, sizeof (name2),
+ (const char *) p->value);
+ p2 = MHD__asn1_copy_structure2 (root, name2);
+ if (p2 == NULL)
+ {
+ return ASN1_IDENTIFIER_NOT_FOUND;
+ }
+ MHD__asn1_set_name (p2, p->name);
+ p2->right = p->right;
+ p2->left = p->left;
+ if (p->right)
+ p->right->left = p2;
+ p3 = p->down;
+ if (p3)
+ {
+ while (p3->right)
+ p3 = p3->right;
+ MHD__asn1_set_right (p3, p2->down);
+ MHD__asn1_set_down (p2, p->down);
+ }
+
+ p3 = MHD__asn1_find_left (p);
+ if (p3)
+ MHD__asn1_set_right (p3, p2);
+ else
+ {
+ p3 = MHD__asn1_find_up (p);
+ if (p3)
+ MHD__asn1_set_down (p3, p2);
+ else
+ {
+ p2->left = NULL;
+ }
+ }
+
+ if (p->type & CONST_SIZE)
+ p2->type |= CONST_SIZE;
+ if (p->type & CONST_TAG)
+ p2->type |= CONST_TAG;
+ if (p->type & CONST_OPTION)
+ p2->type |= CONST_OPTION;
+ if (p->type & CONST_DEFAULT)
+ p2->type |= CONST_DEFAULT;
+ if (p->type & CONST_SET)
+ p2->type |= CONST_SET;
+ if (p->type & CONST_NOT_USED)
+ p2->type |= CONST_NOT_USED;
+
+ if (p == *node)
+ *node = p2;
+ MHD__asn1_remove_node (p);
+ p = p2;
+ move = DOWN;
+ continue;
+ }
+ move = DOWN;
+ }
+ else
+ move = RIGHT;
+
+ if (move == DOWN)
+ {
+ if (p->down)
+ p = p->down;
+ else
+ move = RIGHT;
+ }
+
+ if (p == *node)
+ {
+ move = UP;
+ continue;
+ }
+
+ if (move == RIGHT)
+ {
+ if (p->right)
+ p = p->right;
+ else
+ move = UP;
+ }
+ if (move == UP)
+ p = MHD__asn1_find_up (p);
+ }
+
+ return ASN1_SUCCESS;
+}
+
+
+/**
+ * MHD__asn1_create_element - Creates a structure of type SOURCE_NAME.
+ * @definitions: pointer to the structure returned by "parser_asn1" function
+ * @source_name: the name of the type of the new structure (must be
+ * inside p_structure).
+ * @element: pointer to the structure created.
+ *
+ * Creates a structure of type @source_name. Example using
+ * "pkix.asn":
+ *
+ * rc = MHD__asn1_create_structure(cert_def, "PKIX1.Certificate",
+ * certptr);
+ *
+ * Returns:
+ *
+ * ASN1_SUCCESS: Creation OK.
+ *
+ * ASN1_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
+ **/
+MHD__asn1_retCode
+MHD__asn1_create_element (ASN1_TYPE definitions, const char *source_name,
+ ASN1_TYPE * element)
+{
+ node_asn *dest_node;
+ int res;
+
+ dest_node = MHD__asn1_copy_structure2 (definitions, source_name);
+
+ if (dest_node == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
+
+ MHD__asn1_set_name (dest_node, "");
+
+ res = MHD__asn1_expand_identifier (&dest_node, definitions);
+ MHD__asn1_type_choice_config (dest_node);
+
+ *element = dest_node;
+
+ return res;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/minitasn1/structure.h b/lib/libmicrohttpd/src/daemon/https/minitasn1/structure.h
new file mode 100644
index 0000000000..c447fc925b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/minitasn1/structure.h
@@ -0,0 +1,18 @@
+
+/*************************************************/
+/* File: structure.h */
+/* Description: list of exported object by */
+/* "structure.c" */
+/*************************************************/
+
+#ifndef _STRUCTURE_H
+#define _STRUCTURE_H
+
+node_asn *MHD__asn1_copy_structure3 (node_asn * source_node);
+
+
+node_asn *MHD__asn1_add_node_only (unsigned int type);
+
+node_asn *MHD__asn1_find_left (node_asn * node);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/Makefile.am b/lib/libmicrohttpd/src/daemon/https/tls/Makefile.am
new file mode 100644
index 0000000000..d6bb83074e
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/Makefile.am
@@ -0,0 +1,100 @@
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/include \
+-I$(top_srcdir)/src/daemon/ \
+-I$(top_srcdir)/src/daemon/https \
+-I$(top_srcdir)/src/daemon/https/tls \
+-I$(top_srcdir)/src/daemon/https/lgl \
+-I$(top_srcdir)/src/daemon/https/minitasn1 \
+-I$(top_srcdir)/src/daemon/https/x509 \
+ @LIBGCRYPT_CFLAGS@
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+noinst_LTLIBRARIES = libtls.la
+
+libtls_la_SOURCES = \
+auth_cert.c \
+auth_dhe.c \
+auth_dh_common.c \
+auth_rsa.c \
+auth_rsa_export.c \
+debug.c \
+defines.h \
+ext_cert_type.c \
+ext_max_record.c \
+ext_server_name.c \
+gnutls_alert.c \
+gnutls_algorithms.c \
+gnutls_asn1_tab.c \
+gnutls_auth.c \
+gnutls_buffers.c \
+gnutls_cert.c \
+gnutls_cipher.c \
+gnutls_cipher_int.c \
+gnutls_constate.c \
+gnutls_datum.c \
+gnutls_dh.c \
+gnutls_dh_primes.c \
+gnutls_errors.c \
+gnutls_extensions.c \
+gnutls_global.c \
+gnutls_handshake.c \
+gnutls_hash_int.c \
+gnutls_kx.c \
+gnutls_mem.c \
+gnutls_mpi.c \
+gnutls_num.c \
+gnutls_pk.c \
+gnutls_priority.c \
+gnutls_record.c \
+gnutls_rsa_export.c \
+gnutls_sig.c \
+gnutls_state.c \
+gnutls_str.c \
+gnutls_supplemental.c \
+gnutls_ui.c \
+gnutls_x509.c \
+pkix_asn1_tab.c \
+x509_b64.c \
+auth_cert.h \
+auth_dh_common.h \
+debug.h \
+defines.h \
+ext_cert_type.h \
+ext_max_record.h \
+ext_server_name.h \
+gnutls_algorithms.h \
+gnutls_auth.h \
+gnutls_auth_int.h \
+gnutls_buffers.h \
+gnutls_cert.h \
+gnutls_cipher.h \
+gnutls_cipher_int.h \
+gnutls_constate.h \
+gnutls_datum.h \
+gnutls_dh.h \
+gnutls_errors.h \
+gnutls_extensions.h \
+gnutls_global.h \
+gnutls_handshake.h \
+gnutls_hash_int.h \
+gnutls_int.h \
+gnutls_kx.h \
+gnutls_mem.h \
+gnutls_mpi.h \
+gnutls_num.h \
+gnutls_pk.h \
+gnutls_record.h \
+gnutls_rsa_export.h \
+gnutls_sig.h \
+gnutls_state.h \
+gnutls_str.h \
+gnutls_supplemental.h \
+gnutls_x509.h \
+x509_b64.h \
+memmem.c \
+str-two-way.h
+libtls_la_LIBADD = @LIBGCRYPT_LIBS@
+
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/Makefile.in b/lib/libmicrohttpd/src/daemon/https/tls/Makefile.in
new file mode 100644
index 0000000000..23c09ff54d
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/Makefile.in
@@ -0,0 +1,635 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/daemon/https/tls
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libtls_la_DEPENDENCIES =
+am_libtls_la_OBJECTS = auth_cert.lo auth_dhe.lo auth_dh_common.lo \
+ auth_rsa.lo auth_rsa_export.lo debug.lo ext_cert_type.lo \
+ ext_max_record.lo ext_server_name.lo gnutls_alert.lo \
+ gnutls_algorithms.lo gnutls_asn1_tab.lo gnutls_auth.lo \
+ gnutls_buffers.lo gnutls_cert.lo gnutls_cipher.lo \
+ gnutls_cipher_int.lo gnutls_constate.lo gnutls_datum.lo \
+ gnutls_dh.lo gnutls_dh_primes.lo gnutls_errors.lo \
+ gnutls_extensions.lo gnutls_global.lo gnutls_handshake.lo \
+ gnutls_hash_int.lo gnutls_kx.lo gnutls_mem.lo gnutls_mpi.lo \
+ gnutls_num.lo gnutls_pk.lo gnutls_priority.lo gnutls_record.lo \
+ gnutls_rsa_export.lo gnutls_sig.lo gnutls_state.lo \
+ gnutls_str.lo gnutls_supplemental.lo gnutls_ui.lo \
+ gnutls_x509.lo pkix_asn1_tab.lo x509_b64.lo memmem.lo
+libtls_la_OBJECTS = $(am_libtls_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libtls_la_SOURCES)
+DIST_SOURCES = $(libtls_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/include \
+-I$(top_srcdir)/src/daemon/ \
+-I$(top_srcdir)/src/daemon/https \
+-I$(top_srcdir)/src/daemon/https/tls \
+-I$(top_srcdir)/src/daemon/https/lgl \
+-I$(top_srcdir)/src/daemon/https/minitasn1 \
+-I$(top_srcdir)/src/daemon/https/x509 \
+ @LIBGCRYPT_CFLAGS@
+
+@USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage
+noinst_LTLIBRARIES = libtls.la
+libtls_la_SOURCES = \
+auth_cert.c \
+auth_dhe.c \
+auth_dh_common.c \
+auth_rsa.c \
+auth_rsa_export.c \
+debug.c \
+defines.h \
+ext_cert_type.c \
+ext_max_record.c \
+ext_server_name.c \
+gnutls_alert.c \
+gnutls_algorithms.c \
+gnutls_asn1_tab.c \
+gnutls_auth.c \
+gnutls_buffers.c \
+gnutls_cert.c \
+gnutls_cipher.c \
+gnutls_cipher_int.c \
+gnutls_constate.c \
+gnutls_datum.c \
+gnutls_dh.c \
+gnutls_dh_primes.c \
+gnutls_errors.c \
+gnutls_extensions.c \
+gnutls_global.c \
+gnutls_handshake.c \
+gnutls_hash_int.c \
+gnutls_kx.c \
+gnutls_mem.c \
+gnutls_mpi.c \
+gnutls_num.c \
+gnutls_pk.c \
+gnutls_priority.c \
+gnutls_record.c \
+gnutls_rsa_export.c \
+gnutls_sig.c \
+gnutls_state.c \
+gnutls_str.c \
+gnutls_supplemental.c \
+gnutls_ui.c \
+gnutls_x509.c \
+pkix_asn1_tab.c \
+x509_b64.c \
+auth_cert.h \
+auth_dh_common.h \
+debug.h \
+defines.h \
+ext_cert_type.h \
+ext_max_record.h \
+ext_server_name.h \
+gnutls_algorithms.h \
+gnutls_auth.h \
+gnutls_auth_int.h \
+gnutls_buffers.h \
+gnutls_cert.h \
+gnutls_cipher.h \
+gnutls_cipher_int.h \
+gnutls_constate.h \
+gnutls_datum.h \
+gnutls_dh.h \
+gnutls_errors.h \
+gnutls_extensions.h \
+gnutls_global.h \
+gnutls_handshake.h \
+gnutls_hash_int.h \
+gnutls_int.h \
+gnutls_kx.h \
+gnutls_mem.h \
+gnutls_mpi.h \
+gnutls_num.h \
+gnutls_pk.h \
+gnutls_record.h \
+gnutls_rsa_export.h \
+gnutls_sig.h \
+gnutls_state.h \
+gnutls_str.h \
+gnutls_supplemental.h \
+gnutls_x509.h \
+x509_b64.h \
+memmem.c \
+str-two-way.h
+
+libtls_la_LIBADD = @LIBGCRYPT_LIBS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/daemon/https/tls/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/daemon/https/tls/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libtls.la: $(libtls_la_OBJECTS) $(libtls_la_DEPENDENCIES)
+ $(LINK) $(libtls_la_OBJECTS) $(libtls_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cert.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_dh_common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_dhe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_rsa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_rsa_export.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext_cert_type.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext_max_record.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext_server_name.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_alert.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_algorithms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_asn1_tab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_auth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_buffers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_cert.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_cipher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_cipher_int.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_constate.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_datum.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_dh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_dh_primes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_errors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_extensions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_global.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_handshake.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_hash_int.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_kx.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_mem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_mpi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_num.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_pk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_priority.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_record.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_rsa_export.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_sig.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_state.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_str.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_supplemental.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_ui.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls_x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memmem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkix_asn1_tab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509_b64.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_cert.c b/lib/libmicrohttpd/src/daemon/https/tls/auth_cert.c
new file mode 100644
index 0000000000..f4a784b5e3
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_cert.c
@@ -0,0 +1,1329 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* The certificate authentication functions which are needed in the handshake,
+ * and are common to RSA and DHE key exchange, are in this file.
+ */
+
+#include <gnutls_int.h>
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include <gnutls_cert.h>
+#include <auth_cert.h>
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "libtasn1.h"
+#include "gnutls_datum.h"
+#include <gnutls_pk.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_global.h>
+#include <gnutls_record.h>
+#include <gnutls_sig.h>
+#include <gnutls_state.h>
+#include <gnutls_pk.h>
+#include <gnutls_x509.h>
+#include "debug.h"
+
+static MHD_gnutls_cert *alloc_and_load_x509_certs (MHD_gnutls_x509_crt_t *
+ certs, unsigned);
+static MHD_gnutls_privkey *alloc_and_load_x509_key (MHD_gnutls_x509_privkey_t
+ key);
+
+
+/* Copies data from a internal certificate struct (MHD_gnutls_cert) to
+ * exported certificate struct (cert_auth_info_t)
+ */
+static int
+MHD__gnutls_copy_certificate_auth_info (cert_auth_info_t info,
+ MHD_gnutls_cert * cert, int ncerts)
+{
+ /* Copy peer's information to auth_info_t
+ */
+ int ret, i, j;
+
+ if (ncerts == 0)
+ {
+ info->raw_certificate_list = NULL;
+ info->ncerts = 0;
+ return 0;
+ }
+
+ info->raw_certificate_list =
+ MHD_gnutls_calloc (1, sizeof (MHD_gnutls_datum_t) * ncerts);
+ if (info->raw_certificate_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ for (i = 0; i < ncerts; i++)
+ {
+ if (cert->raw.size > 0)
+ {
+ ret =
+ MHD__gnutls_set_datum (&info->raw_certificate_list[i],
+ cert[i].raw.data, cert[i].raw.size);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ goto clear;
+ }
+ }
+ }
+ info->ncerts = ncerts;
+
+ return 0;
+
+clear:
+
+ for (j = 0; j < i; j++)
+ MHD__gnutls_free_datum (&info->raw_certificate_list[j]);
+
+ MHD_gnutls_free (info->raw_certificate_list);
+ info->raw_certificate_list = NULL;
+
+ return ret;
+}
+
+
+
+
+/* returns 0 if the algo_to-check exists in the pk_algos list,
+ * -1 otherwise.
+ */
+inline static int
+MHD__gnutls_check_pk_algo_in_list (const enum MHD_GNUTLS_PublicKeyAlgorithm
+ *pk_algos, int pk_algos_length,
+ enum MHD_GNUTLS_PublicKeyAlgorithm
+ algo_to_check)
+{
+ int i;
+ for (i = 0; i < pk_algos_length; i++)
+ {
+ if (algo_to_check == pk_algos[i])
+ {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+/* Returns the issuer's Distinguished name in odn, of the certificate
+ * specified in cert.
+ */
+static int
+MHD__gnutls_cert_get_issuer_dn (MHD_gnutls_cert * cert,
+ MHD_gnutls_datum_t * odn)
+{
+ ASN1_TYPE dn;
+ int len, result;
+ int start, end;
+
+ if ((result = MHD__asn1_create_element
+ (MHD__gnutls_get_pkix (), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ result = MHD__asn1_der_decoding (&dn, cert->raw.data, cert->raw.size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ /* couldn't decode DER */
+ MHD_gnutls_assert ();
+ MHD__asn1_delete_structure (&dn);
+ return MHD_gtls_asn2err (result);
+ }
+
+ result =
+ MHD__asn1_der_decoding_startEnd (dn, cert->raw.data, cert->raw.size,
+ "tbsCertificate.issuer", &start, &end);
+
+ if (result != ASN1_SUCCESS)
+ {
+ /* couldn't decode DER */
+ MHD_gnutls_assert ();
+ MHD__asn1_delete_structure (&dn);
+ return MHD_gtls_asn2err (result);
+ }
+ MHD__asn1_delete_structure (&dn);
+
+ len = end - start + 1;
+
+ odn->size = len;
+ odn->data = &cert->raw.data[start];
+
+ return 0;
+}
+
+
+/* Locates the most appropriate x509 certificate using the
+ * given DN. If indx == -1 then no certificate was found.
+ *
+ * That is to guess which certificate to use, based on the
+ * CAs and sign algorithms supported by the peer server.
+ */
+static int
+_find_x509_cert (const MHD_gtls_cert_credentials_t cred,
+ opaque * _data, size_t _data_size,
+ const enum MHD_GNUTLS_PublicKeyAlgorithm *pk_algos,
+ int pk_algos_length, int *indx)
+{
+ unsigned size;
+ MHD_gnutls_datum_t odn;
+ opaque *data = _data;
+ ssize_t data_size = _data_size;
+ unsigned i, j;
+ int result, cert_pk;
+
+ *indx = -1;
+ odn.size = 0;
+ odn.data = NULL;
+ do
+ {
+
+ DECR_LENGTH_RET (data_size, 2, 0);
+ size = MHD_gtls_read_uint16 (data);
+ DECR_LENGTH_RET (data_size, size, 0);
+ data += 2;
+
+ for (i = 0; i < cred->ncerts; i++)
+ {
+ for (j = 0; j < cred->cert_list_length[i]; j++)
+ {
+ if ((result =
+ MHD__gnutls_cert_get_issuer_dn (&cred->cert_list[i][j],
+ &odn)) != 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ if (odn.size != size)
+ continue;
+
+ /* If the DN matches and
+ * the *_SIGN algorithm matches
+ * the cert is our cert!
+ */
+ cert_pk = cred->cert_list[i][0].subject_pk_algorithm;
+
+ if ((memcmp (odn.data, data, size) == 0) &&
+ (MHD__gnutls_check_pk_algo_in_list
+ (pk_algos, pk_algos_length, cert_pk) == 0))
+ {
+ *indx = i;
+ break;
+ }
+ }
+ if (*indx != -1)
+ break;
+ }
+
+ if (*indx != -1)
+ break;
+
+ /* move to next record */
+ data += size;
+
+ }
+ while (1);
+
+ return 0;
+
+}
+
+/* Returns the number of issuers in the server's
+ * certificate request packet.
+ */
+static int
+get_issuers_num (MHD_gtls_session_t session, opaque * data, ssize_t data_size)
+{
+ int issuers_dn_len = 0, result;
+ unsigned size;
+
+ /* Count the number of the given issuers;
+ * This is used to allocate the issuers_dn without
+ * using realloc().
+ */
+
+ if (data_size == 0 || data == NULL)
+ return 0;
+
+ if (data_size > 0)
+ do
+ {
+ /* This works like DECR_LEN()
+ */
+ result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ DECR_LENGTH_COM (data_size, 2, goto error);
+ size = MHD_gtls_read_uint16 (data);
+
+ result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ DECR_LENGTH_COM (data_size, size, goto error);
+
+ data += 2;
+
+ if (size > 0)
+ {
+ issuers_dn_len++;
+ data += size;
+ }
+
+ if (data_size == 0)
+ break;
+
+ }
+ while (1);
+
+ return issuers_dn_len;
+
+error:
+ return result;
+}
+
+/* Returns the issuers in the server's certificate request
+ * packet.
+ */
+static int
+get_issuers (MHD_gtls_session_t session,
+ MHD_gnutls_datum_t * issuers_dn, int issuers_len,
+ opaque * data, size_t data_size)
+{
+ int i;
+ unsigned size;
+
+ if (MHD_gnutls_certificate_type_get (session) != MHD_GNUTLS_CRT_X509)
+ return 0;
+
+ /* put the requested DNs to req_dn, only in case
+ * of X509 certificates.
+ */
+ if (issuers_len > 0)
+ {
+
+ for (i = 0; i < issuers_len; i++)
+ {
+ /* The checks here for the buffer boundaries
+ * are not needed since the buffer has been
+ * parsed above.
+ */
+ data_size -= 2;
+
+ size = MHD_gtls_read_uint16 (data);
+
+ data += 2;
+
+ issuers_dn[i].data = data;
+ issuers_dn[i].size = size;
+
+ data += size;
+ }
+ }
+
+ return 0;
+}
+
+/* Calls the client get callback.
+ */
+static int
+call_get_cert_callback (MHD_gtls_session_t session,
+ MHD_gnutls_datum_t * issuers_dn,
+ int issuers_dn_length,
+ enum MHD_GNUTLS_PublicKeyAlgorithm *pk_algos,
+ int pk_algos_length)
+{
+ unsigned i;
+ MHD_gnutls_cert *local_certs = NULL;
+ MHD_gnutls_privkey *local_key = NULL;
+ MHD_gnutls_retr_st st;
+ int ret;
+ enum MHD_GNUTLS_CertificateType type =
+ MHD_gnutls_certificate_type_get (session);
+ MHD_gtls_cert_credentials_t cred;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ memset (&st, 0, sizeof (st));
+
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ {
+ ret = cred->server_get_cert_callback (session, &st);
+ }
+ else
+ { /* CLIENT */
+ ret =
+ cred->client_get_cert_callback (session,
+ issuers_dn, issuers_dn_length,
+ pk_algos, pk_algos_length, &st);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (st.ncerts == 0)
+ return 0; /* no certificate was selected */
+
+ if (type != st.type)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ if (type == MHD_GNUTLS_CRT_X509)
+ {
+ local_certs = alloc_and_load_x509_certs (st.cert.x509, st.ncerts);
+ if (local_certs != NULL)
+ local_key = alloc_and_load_x509_key (st.key.x509);
+
+ }
+ else
+ { /* PGP */
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ MHD_gtls_selected_certs_set (session, local_certs,
+ (local_certs != NULL) ? st.ncerts : 0,
+ local_key, 1);
+
+ ret = 0;
+
+cleanup:
+
+ if (st.type == MHD_GNUTLS_CRT_X509)
+ {
+ if (st.deinit_all)
+ {
+ for (i = 0; i < st.ncerts; i++)
+ {
+ MHD_gnutls_x509_crt_deinit (st.cert.x509[i]);
+ }
+ MHD_gnutls_free (st.cert.x509);
+ MHD_gnutls_x509_privkey_deinit (st.key.x509);
+ }
+ }
+ return ret;
+}
+
+/* Finds the appropriate certificate depending on the cA Distinguished name
+ * advertized by the server. If none matches then returns 0 and -1 as index.
+ * In case of an error a negative value, is returned.
+ *
+ * 20020128: added ability to select a certificate depending on the SIGN
+ * algorithm (only in automatic mode).
+ */
+static int
+_select_client_cert (MHD_gtls_session_t session,
+ opaque * _data, size_t _data_size,
+ enum MHD_GNUTLS_PublicKeyAlgorithm *pk_algos,
+ int pk_algos_length)
+{
+ int result;
+ int indx = -1;
+ MHD_gtls_cert_credentials_t cred;
+ opaque *data = _data;
+ ssize_t data_size = _data_size;
+ int issuers_dn_length;
+ MHD_gnutls_datum_t *issuers_dn = NULL;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ if (cred->client_get_cert_callback != NULL)
+ {
+
+ /* use a callback to get certificate
+ */
+ if (session->security_parameters.cert_type != MHD_GNUTLS_CRT_X509)
+ issuers_dn_length = 0;
+ else
+ {
+ issuers_dn_length = get_issuers_num (session, data, data_size);
+ if (issuers_dn_length < 0)
+ {
+ MHD_gnutls_assert ();
+ return issuers_dn_length;
+ }
+
+ if (issuers_dn_length > 0)
+ {
+ issuers_dn =
+ MHD_gnutls_malloc (sizeof (MHD_gnutls_datum_t) *
+ issuers_dn_length);
+ if (issuers_dn == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ result =
+ get_issuers (session, issuers_dn, issuers_dn_length,
+ data, data_size);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+ }
+ }
+
+ result =
+ call_get_cert_callback (session, issuers_dn, issuers_dn_length,
+ pk_algos, pk_algos_length);
+ goto cleanup;
+
+ }
+ else
+ {
+ /* If we have no callbacks, try to guess.
+ */
+ result = 0;
+
+ if (session->security_parameters.cert_type == MHD_GNUTLS_CRT_X509)
+ result =
+ _find_x509_cert (cred, _data, _data_size,
+ pk_algos, pk_algos_length, &indx);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ if (indx >= 0)
+ {
+ MHD_gtls_selected_certs_set (session,
+ &cred->cert_list[indx][0],
+ cred->cert_list_length[indx],
+ &cred->pkey[indx], 0);
+ }
+ else
+ {
+ MHD_gtls_selected_certs_set (session, NULL, 0, NULL, 0);
+ }
+
+ result = 0;
+ }
+
+cleanup:
+ MHD_gnutls_free (issuers_dn);
+ return result;
+
+}
+
+/* Generate client certificate
+ */
+static int
+MHD_gtls_gen_x509_crt (MHD_gtls_session_t session, opaque ** data)
+{
+ int ret, i;
+ opaque *pdata;
+ MHD_gnutls_cert *apr_cert_list;
+ MHD_gnutls_privkey *apr_pkey;
+ int apr_cert_list_length;
+
+ /* find the appropriate certificate
+ */
+ if ((ret =
+ MHD_gtls_get_selected_cert (session, &apr_cert_list,
+ &apr_cert_list_length, &apr_pkey)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = 3;
+ for (i = 0; i < apr_cert_list_length; i++)
+ {
+ ret += apr_cert_list[i].raw.size + 3;
+ /* hold size
+ * for uint24 */
+ }
+
+ /* if no certificates were found then send:
+ * 0B 00 00 03 00 00 00 // Certificate with no certs
+ * instead of:
+ * 0B 00 00 00 // empty certificate handshake
+ *
+ * ( the above is the whole handshake message, not
+ * the one produced here )
+ */
+
+ (*data) = MHD_gnutls_malloc (ret);
+ pdata = (*data);
+
+ if (pdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ MHD_gtls_write_uint24 (ret - 3, pdata);
+ pdata += 3;
+ for (i = 0; i < apr_cert_list_length; i++)
+ {
+ MHD_gtls_write_datum24 (pdata, apr_cert_list[i].raw);
+ pdata += (3 + apr_cert_list[i].raw.size);
+ }
+
+ return ret;
+}
+
+int
+MHD_gtls_gen_cert_client_certificate (MHD_gtls_session_t session,
+ opaque ** data)
+{
+ switch (session->security_parameters.cert_type)
+ {
+ case MHD_GNUTLS_CRT_X509:
+ return MHD_gtls_gen_x509_crt (session, data);
+
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+}
+
+int
+MHD_gtls_gen_cert_server_certificate (MHD_gtls_session_t session,
+ opaque ** data)
+{
+ switch (session->security_parameters.cert_type)
+ {
+ case MHD_GNUTLS_CRT_X509:
+ return MHD_gtls_gen_x509_crt (session, data);
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+}
+
+/* Process server certificate
+ */
+
+#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) MHD_gtls_gcert_deinit(&peer_certificate_list[x])
+static int
+MHD_gtls_proc_x509_server_certificate (MHD_gtls_session_t session,
+ opaque * data, size_t data_size)
+{
+ int size, len, ret;
+ opaque *p = data;
+ cert_auth_info_t info;
+ MHD_gtls_cert_credentials_t cred;
+ ssize_t dsize = data_size;
+ int i, j, x;
+ MHD_gnutls_cert *peer_certificate_list;
+ int peer_certificate_list_size = 0;
+ MHD_gnutls_datum_t tmp;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+
+ if ((ret =
+ MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
+ sizeof (cert_auth_info_st), 1)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ info = MHD_gtls_get_auth_info (session);
+
+ if (data == NULL || data_size == 0)
+ {
+ MHD_gnutls_assert ();
+ /* no certificate was sent */
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ DECR_LEN (dsize, 3);
+ size = MHD_gtls_read_uint24 (p);
+ p += 3;
+
+ /* some implementations send 0B 00 00 06 00 00 03 00 00 00
+ * instead of just 0B 00 00 03 00 00 00 as an empty certificate message.
+ */
+ if (size == 0 || size == 3)
+ {
+ MHD_gnutls_assert ();
+ /* no certificate was sent */
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ i = dsize;
+ while (i > 0)
+ {
+ DECR_LEN (dsize, 3);
+ len = MHD_gtls_read_uint24 (p);
+ p += 3;
+ DECR_LEN (dsize, len);
+ peer_certificate_list_size++;
+ p += len;
+ i -= len + 3;
+ }
+
+ if (peer_certificate_list_size == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ /* Ok we now allocate the memory to hold the
+ * certificate list
+ */
+
+ peer_certificate_list =
+ MHD_gnutls_malloc (sizeof (MHD_gnutls_cert) *
+ (peer_certificate_list_size));
+
+ if (peer_certificate_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memset (peer_certificate_list, 0, sizeof (MHD_gnutls_cert) *
+ peer_certificate_list_size);
+
+ p = data + 3;
+
+ /* Now we start parsing the list (again).
+ * We don't use DECR_LEN since the list has
+ * been parsed before.
+ */
+
+ for (j = 0; j < peer_certificate_list_size; j++)
+ {
+ len = MHD_gtls_read_uint24 (p);
+ p += 3;
+
+ tmp.size = len;
+ tmp.data = p;
+
+ if ((ret =
+ MHD_gtls_x509_raw_cert_to_gcert (&peer_certificate_list
+ [j], &tmp,
+ CERT_ONLY_EXTENSIONS)) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ p += len;
+ }
+
+
+ if ((ret =
+ MHD__gnutls_copy_certificate_auth_info (info,
+ peer_certificate_list,
+ peer_certificate_list_size)) <
+ 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ if ((ret =
+ MHD__gnutls_check_key_usage (&peer_certificate_list[0],
+ MHD_gnutls_kx_get (session))) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ CLEAR_CERTS;
+ MHD_gnutls_free (peer_certificate_list);
+ return ret;
+
+}
+
+#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) MHD_gtls_gcert_deinit(&peer_certificate_list[x])
+
+int
+MHD_gtls_proc_cert_server_certificate (MHD_gtls_session_t session,
+ opaque * data, size_t data_size)
+{
+ switch (session->security_parameters.cert_type)
+ {
+ case MHD_GNUTLS_CRT_X509:
+ return MHD_gtls_proc_x509_server_certificate (session, data, data_size);
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+}
+
+#define MAX_SIGN_ALGOS 2
+typedef enum CertificateSigType
+{ RSA_SIGN = 1, DSA_SIGN
+} CertificateSigType;
+
+/* Checks if we support the given signature algorithm
+ * (RSA or DSA). Returns the corresponding enum MHD_GNUTLS_PublicKeyAlgorithm
+ * if true;
+ */
+inline static int
+MHD__gnutls_check_supported_sign_algo (CertificateSigType algo)
+{
+ switch (algo)
+ {
+ case RSA_SIGN:
+ return MHD_GNUTLS_PK_RSA;
+ default:
+ return -1;
+ }
+}
+
+int
+MHD_gtls_proc_cert_cert_req (MHD_gtls_session_t session, opaque * data,
+ size_t data_size)
+{
+ int size, ret;
+ opaque *p;
+ MHD_gtls_cert_credentials_t cred;
+ ssize_t dsize;
+ int i, j;
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk_algos[MAX_SIGN_ALGOS];
+ int pk_algos_length;
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ if ((ret =
+ MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
+ sizeof (cert_auth_info_st), 0)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ p = data;
+ dsize = data_size;
+
+ DECR_LEN (dsize, 1);
+ size = p[0];
+ p++;
+ /* check if the sign algorithm is supported.
+ */
+ pk_algos_length = j = 0;
+ for (i = 0; i < size; i++, p++)
+ {
+ DECR_LEN (dsize, 1);
+ if ((ret = MHD__gnutls_check_supported_sign_algo (*p)) > 0)
+ {
+ if (j < MAX_SIGN_ALGOS)
+ {
+ pk_algos[j++] = ret;
+ pk_algos_length++;
+ }
+ }
+ }
+
+ if (pk_algos_length == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
+ }
+
+ if (ver == MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ /* read supported hashes */
+ int hash_num;
+ DECR_LEN (dsize, 1);
+
+ hash_num = p[0] & 0xFF;
+ p++;
+
+ DECR_LEN (dsize, hash_num);
+ p += hash_num;
+ }
+
+ /* read the certificate authorities */
+ DECR_LEN (dsize, 2);
+ size = MHD_gtls_read_uint16 (p);
+ p += 2;
+
+ DECR_LEN (dsize, size);
+
+ /* now we ask the user to tell which one
+ * he wants to use.
+ */
+ if ((ret =
+ _select_client_cert (session, p, size, pk_algos, pk_algos_length)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* We should reply with a certificate message,
+ * even if we have no certificate to send.
+ */
+ session->key->certificate_requested = 1;
+
+ return 0;
+}
+
+int
+MHD_gtls_gen_cert_client_cert_vrfy (MHD_gtls_session_t session,
+ opaque ** data)
+{
+ int ret;
+ MHD_gnutls_cert *apr_cert_list;
+ MHD_gnutls_privkey *apr_pkey;
+ int apr_cert_list_length, size;
+ MHD_gnutls_datum_t signature;
+
+ *data = NULL;
+
+ /* find the appropriate certificate */
+ if ((ret =
+ MHD_gtls_get_selected_cert (session, &apr_cert_list,
+ &apr_cert_list_length, &apr_pkey)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (apr_cert_list_length > 0)
+ {
+ if ((ret =
+ MHD_gtls_tls_sign_hdata (session,
+ &apr_cert_list[0],
+ apr_pkey, &signature)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+
+ *data = MHD_gnutls_malloc (signature.size + 2);
+ if (*data == NULL)
+ {
+ MHD__gnutls_free_datum (&signature);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ size = signature.size;
+ MHD_gtls_write_uint16 (size, *data);
+
+ memcpy (&(*data)[2], signature.data, size);
+
+ MHD__gnutls_free_datum (&signature);
+
+ return size + 2;
+}
+
+int
+MHD_gtls_proc_cert_client_cert_vrfy (MHD_gtls_session_t session,
+ opaque * data, size_t data_size)
+{
+ int size, ret;
+ ssize_t dsize = data_size;
+ opaque *pdata = data;
+ MHD_gnutls_datum_t sig;
+ cert_auth_info_t info = MHD_gtls_get_auth_info (session);
+ MHD_gnutls_cert peer_cert;
+
+ if (info == NULL || info->ncerts == 0)
+ {
+ MHD_gnutls_assert ();
+ /* we need this in order to get peer's certificate */
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ DECR_LEN (dsize, 2);
+ size = MHD_gtls_read_uint16 (pdata);
+ pdata += 2;
+
+ DECR_LEN (dsize, size);
+
+ sig.data = pdata;
+ sig.size = size;
+
+ ret = MHD_gtls_raw_cert_to_gcert (&peer_cert,
+ session->security_parameters.cert_type,
+ &info->raw_certificate_list[0],
+ CERT_NO_COPY);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if ((ret = MHD_gtls_verify_sig_hdata (session, &peer_cert, &sig)) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gtls_gcert_deinit (&peer_cert);
+ return ret;
+ }
+ MHD_gtls_gcert_deinit (&peer_cert);
+
+ return 0;
+}
+
+#define CERTTYPE_SIZE 3
+int
+MHD_gtls_gen_cert_server_cert_req (MHD_gtls_session_t session, opaque ** data)
+{
+ MHD_gtls_cert_credentials_t cred;
+ int size;
+ opaque *pdata;
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ /* Now we need to generate the RDN sequence. This is
+ * already in the CERTIFICATE_CRED structure, to improve
+ * performance.
+ */
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ size = CERTTYPE_SIZE + 2; /* 2 for enum MHD_GNUTLS_CertificateType + 2 for size of rdn_seq
+ */
+
+ if (session->security_parameters.cert_type == MHD_GNUTLS_CRT_X509 &&
+ session->internals.ignore_rdn_sequence == 0)
+ size += cred->x509_rdn_sequence.size;
+
+ if (ver == MHD_GNUTLS_PROTOCOL_TLS1_2)
+ /* Need at least one byte to announce the number of supported hash
+ functions (see below). */
+ size += 1;
+
+ (*data) = MHD_gnutls_malloc (size);
+ pdata = (*data);
+
+ if (pdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ pdata[0] = CERTTYPE_SIZE - 1;
+
+ pdata[1] = RSA_SIGN;
+ pdata[2] = DSA_SIGN; /* only these for now */
+ pdata += CERTTYPE_SIZE;
+
+ if (ver == MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ /* Supported hashes (nothing for now -- FIXME). */
+ *pdata = 0;
+ pdata++;
+ }
+
+ if (session->security_parameters.cert_type == MHD_GNUTLS_CRT_X509 &&
+ session->internals.ignore_rdn_sequence == 0)
+ {
+ MHD_gtls_write_datum16 (pdata, cred->x509_rdn_sequence);
+ /* pdata += cred->x509_rdn_sequence.size + 2; */
+ }
+ else
+ {
+ MHD_gtls_write_uint16 (0, pdata);
+ /* pdata+=2; */
+ }
+
+ return size;
+}
+
+
+/* This function will return the appropriate certificate to use.
+ * Fills in the apr_cert_list, apr_cert_list_length and apr_pkey.
+ * The return value is a negative value on error.
+ *
+ * It is normal to return 0 with no certificates in client side.
+ *
+ */
+int
+MHD_gtls_get_selected_cert (MHD_gtls_session_t session,
+ MHD_gnutls_cert ** apr_cert_list,
+ int *apr_cert_list_length,
+ MHD_gnutls_privkey ** apr_pkey)
+{
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ {
+
+ /* select_client_cert() has been called before.
+ */
+
+ *apr_cert_list = session->internals.selected_cert_list;
+ *apr_pkey = session->internals.selected_key;
+ *apr_cert_list_length = session->internals.selected_cert_list_length;
+
+ if (*apr_cert_list_length == 0 || *apr_cert_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ }
+ else
+ { /* CLIENT SIDE
+ */
+
+ /* we have already decided which certificate
+ * to send.
+ */
+ *apr_cert_list = session->internals.selected_cert_list;
+ *apr_cert_list_length = session->internals.selected_cert_list_length;
+ *apr_pkey = session->internals.selected_key;
+
+ }
+
+ return 0;
+}
+
+/* converts the given x509 certificate to MHD_gnutls_cert* and allocates
+ * space for them.
+ */
+static MHD_gnutls_cert *
+alloc_and_load_x509_certs (MHD_gnutls_x509_crt_t * certs, unsigned ncerts)
+{
+ MHD_gnutls_cert *local_certs;
+ int ret = 0;
+ unsigned i, j;
+
+ if (certs == NULL)
+ return NULL;
+
+ local_certs = MHD_gnutls_malloc (sizeof (MHD_gnutls_cert) * ncerts);
+ if (local_certs == NULL)
+ {
+ MHD_gnutls_assert ();
+ return NULL;
+ }
+
+ for (i = 0; i < ncerts; i++)
+ {
+ ret = MHD_gtls_x509_crt_to_gcert (&local_certs[i], certs[i], 0);
+ if (ret < 0)
+ break;
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ for (j = 0; j < i; j++)
+ {
+ MHD_gtls_gcert_deinit (&local_certs[j]);
+ }
+ MHD_gnutls_free (local_certs);
+ return NULL;
+ }
+
+ return local_certs;
+}
+
+/* converts the given x509 key to MHD_gnutls_privkey* and allocates
+ * space for it.
+ */
+static MHD_gnutls_privkey *
+alloc_and_load_x509_key (MHD_gnutls_x509_privkey_t key)
+{
+ MHD_gnutls_privkey *local_key;
+ int ret = 0;
+
+ if (key == NULL)
+ return NULL;
+
+ local_key = MHD_gnutls_malloc (sizeof (MHD_gnutls_privkey));
+ if (local_key == NULL)
+ {
+ MHD_gnutls_assert ();
+ return NULL;
+ }
+
+ ret = MHD__gnutls_x509_privkey_to_gkey (local_key, key);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return NULL;
+ }
+
+ return local_key;
+}
+
+void
+MHD_gtls_selected_certs_deinit (MHD_gtls_session_t session)
+{
+ if (session->internals.selected_need_free != 0)
+ {
+ int i;
+
+ for (i = 0; i < session->internals.selected_cert_list_length; i++)
+ {
+ MHD_gtls_gcert_deinit (&session->internals.selected_cert_list[i]);
+ }
+ MHD_gnutls_free (session->internals.selected_cert_list);
+ session->internals.selected_cert_list = NULL;
+ session->internals.selected_cert_list_length = 0;
+
+ MHD_gtls_gkey_deinit (session->internals.selected_key);
+ if (session->internals.selected_key)
+ {
+ MHD_gnutls_free (session->internals.selected_key);
+ session->internals.selected_key = NULL;
+ }
+ }
+
+ return;
+}
+
+void
+MHD_gtls_selected_certs_set (MHD_gtls_session_t session,
+ MHD_gnutls_cert * certs, int ncerts,
+ MHD_gnutls_privkey * key, int need_free)
+{
+ MHD_gtls_selected_certs_deinit (session);
+
+ session->internals.selected_cert_list = certs;
+ session->internals.selected_cert_list_length = ncerts;
+ session->internals.selected_key = key;
+ session->internals.selected_need_free = need_free;
+
+}
+
+
+/* finds the most appropriate certificate in the cert list.
+ * The 'appropriate' is defined by the user.
+ *
+ * requested_algo holds the parameters required by the peer (RSA, DSA
+ * or -1 for any).
+ *
+ * Returns 0 on success and a negative value on error. The
+ * selected certificate will be in session->internals.selected_*.
+ *
+ */
+int
+MHD_gtls_server_select_cert (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_PublicKeyAlgorithm
+ requested_algo)
+{
+ unsigned i;
+ int idx, ret;
+ MHD_gtls_cert_credentials_t cred;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ /* If the callback which retrieves certificate has been set,
+ * use it and leave.
+ */
+ if (cred->server_get_cert_callback != NULL)
+ return call_get_cert_callback (session, NULL, 0, NULL, 0);
+
+ /* Otherwise... */
+
+ ret = 0;
+ idx = -1; /* default is use no certificate */
+
+
+ for (i = 0; i < cred->ncerts; i++)
+ {
+ /* find one compatible certificate
+ */
+ if (requested_algo == GNUTLS_PK_ANY ||
+ requested_algo == cred->cert_list[i][0].subject_pk_algorithm)
+ {
+ /* if cert type matches
+ */
+ if (session->security_parameters.cert_type ==
+ cred->cert_list[i][0].cert_type)
+ {
+ idx = i;
+ break;
+ }
+ }
+ }
+
+ /* store the certificate pointer for future use, in the handshake.
+ * (This will allow not calling this callback again.)
+ */
+ if (idx >= 0 && ret == 0)
+ {
+ MHD_gtls_selected_certs_set (session,
+ &cred->cert_list[idx][0],
+ cred->cert_list_length[idx],
+ &cred->pkey[idx], 0);
+ }
+ else
+ /* Certificate does not support REQUESTED_ALGO. */
+ ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+
+ return ret;
+}
+
+/* Frees the MHD_gtls_rsa_info_st structure.
+ */
+void
+MHD_gtls_free_rsa_info (rsa_info_st * rsa)
+{
+ MHD__gnutls_free_datum (&rsa->modulus);
+ MHD__gnutls_free_datum (&rsa->exponent);
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_cert.h b/lib/libmicrohttpd/src/daemon/https/tls/auth_cert.h
new file mode 100644
index 0000000000..395fdd29fc
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_cert.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef AUTH_CERT_H
+#define AUTH_CERT_H
+
+#include "gnutls_cert.h"
+#include "gnutls_auth.h"
+#include "auth_dh_common.h"
+#include "x509.h"
+
+/* This structure may be complex, but it's the only way to
+ * support a server that has multiple certificates
+ */
+
+typedef struct MHD_gtls_certificate_credentials_st
+{
+ MHD_gtls_dh_params_t dh_params;
+ MHD_gtls_rsa_params_t rsa_params;
+ /* this callback is used to retrieve the DH or RSA
+ * parameters.
+ */
+ MHD_gnutls_params_function *params_func;
+
+ MHD_gnutls_cert **cert_list;
+ /* contains a list of a list of certificates.
+ * eg (X509): [0] certificate1, certificate11, certificate111
+ * (if more than one, one certificate certifies the one before)
+ * [1] certificate2, certificate22, ...
+ */
+ unsigned *cert_list_length;
+ /* contains the number of the certificates in a
+ * row (should be 1 for OpenPGP keys).
+ */
+ unsigned ncerts; /* contains the number of columns in cert_list.
+ * This is the same with the number of pkeys.
+ */
+
+ MHD_gnutls_privkey *pkey;
+ /* private keys. It contains ncerts private
+ * keys. pkey[i] corresponds to certificate in
+ * cert_list[i][0].
+ */
+
+ /* OpenPGP specific stuff */
+
+#ifndef KEYRING_HACK
+ MHD_gnutls_openpgp_keyring_t keyring;
+#else
+ MHD_gnutls_datum_t keyring;
+ int keyring_format;
+#endif
+
+ /* X509 specific stuff */
+
+ MHD_gnutls_x509_crt_t *x509_ca_list;
+ unsigned x509_ncas; /* number of CAs in the ca_list
+ */
+
+ MHD_gnutls_x509_crl_t *x509_crl_list;
+ unsigned x509_ncrls; /* number of CRLs in the crl_list
+ */
+
+ unsigned int verify_flags; /* flags to be used at
+ * certificate verification.
+ */
+ unsigned int verify_depth;
+ unsigned int verify_bits;
+
+ /* holds a sequence of the
+ * RDNs of the CAs above.
+ * This is better than
+ * generating on every handshake.
+ */
+ MHD_gnutls_datum_t x509_rdn_sequence;
+
+ MHD_gnutls_certificate_client_retrieve_function *client_get_cert_callback;
+ MHD_gnutls_certificate_server_retrieve_function *server_get_cert_callback;
+} MHD_gtls_cert_credentials_st;
+
+typedef struct MHD_gtls_rsa_info_st
+{
+ MHD_gnutls_datum_t modulus;
+ MHD_gnutls_datum_t exponent;
+} rsa_info_st;
+
+typedef struct MHD_gtls_cert_auth_info_st
+{
+ int certificate_requested; /* if the peer requested certificate
+ * this is non zero;
+ */
+
+ /* These (dh/rsa) are just copies from the credentials_t structure.
+ * They must be freed.
+ */
+ MHD_gtls_dh_info_st dh;
+ rsa_info_st rsa_export;
+
+ MHD_gnutls_datum_t *raw_certificate_list; /* holds the raw certificate of the
+ * peer.
+ */
+ unsigned int ncerts; /* holds the size of the list above */
+} *cert_auth_info_t;
+
+typedef struct MHD_gtls_cert_auth_info_st cert_auth_info_st;
+
+void MHD_gtls_free_rsa_info (rsa_info_st * rsa);
+
+/* AUTH X509 functions */
+int MHD_gtls_gen_cert_server_certificate (MHD_gtls_session_t, opaque **);
+int MHD_gtls_gen_cert_client_certificate (MHD_gtls_session_t, opaque **);
+int MHD_gtls_gen_cert_client_cert_vrfy (MHD_gtls_session_t, opaque **);
+int MHD_gtls_gen_cert_server_cert_req (MHD_gtls_session_t, opaque **);
+int MHD_gtls_proc_cert_cert_req (MHD_gtls_session_t, opaque *, size_t);
+int MHD_gtls_proc_cert_client_cert_vrfy (MHD_gtls_session_t, opaque *,
+ size_t);
+int MHD_gtls_proc_cert_server_certificate (MHD_gtls_session_t, opaque *,
+ size_t);
+int MHD_gtls_get_selected_cert (MHD_gtls_session_t session,
+ MHD_gnutls_cert ** apr_cert_list,
+ int *apr_cert_list_length,
+ MHD_gnutls_privkey ** apr_pkey);
+
+int MHD_gtls_server_select_cert (struct MHD_gtls_session_int *,
+ enum MHD_GNUTLS_PublicKeyAlgorithm);
+void MHD_gtls_selected_certs_deinit (MHD_gtls_session_t session);
+void MHD_gtls_selected_certs_set (MHD_gtls_session_t session,
+ MHD_gnutls_cert * certs, int ncerts,
+ MHD_gnutls_privkey * key, int need_free);
+
+#define MHD__gnutls_proc_cert_client_certificate MHD_gtls_proc_cert_server_certificate
+
+MHD_gtls_rsa_params_t
+MHD_gtls_certificate_get_rsa_params (MHD_gtls_rsa_params_t rsa_params,
+ MHD_gnutls_params_function * func,
+ MHD_gtls_session_t);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.c b/lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.c
new file mode 100644
index 0000000000..8fc6e3914a
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains common stuff in Ephemeral Diffie Hellman (DHE) and
+ * Anonymous DH key exchange(DHA). These are used in the handshake procedure
+ * of the certificate and anoymous authentication.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "gnutls_sig.h"
+#include <gnutls_datum.h>
+#include <gnutls_x509.h>
+#include <gnutls_state.h>
+#include <auth_dh_common.h>
+#include <gnutls_algorithms.h>
+
+/* Frees the MHD_gtls_dh_info_st structure.
+ */
+void
+MHD_gtls_free_dh_info (MHD_gtls_dh_info_st * dh)
+{
+ dh->secret_bits = 0;
+ MHD__gnutls_free_datum (&dh->prime);
+ MHD__gnutls_free_datum (&dh->generator);
+ MHD__gnutls_free_datum (&dh->public_key);
+}
+
+int
+MHD_gtls_proc_dh_common_client_kx (MHD_gtls_session_t session,
+ opaque * data, size_t _data_size,
+ mpi_t g, mpi_t p)
+{
+ uint16_t n_Y;
+ size_t _n_Y;
+ int ret;
+ ssize_t data_size = _data_size;
+
+
+ DECR_LEN (data_size, 2);
+ n_Y = MHD_gtls_read_uint16 (&data[0]);
+ _n_Y = n_Y;
+
+ DECR_LEN (data_size, n_Y);
+ if (MHD_gtls_mpi_scan_nz (&session->key->client_Y, &data[2], &_n_Y))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ MHD_gtls_dh_set_peer_public (session, session->key->client_Y);
+
+ session->key->KEY =
+ MHD_gtls_calc_dh_key (session->key->client_Y, session->key->dh_secret, p);
+
+ if (session->key->KEY == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD_gtls_mpi_release (&session->key->client_Y);
+ MHD_gtls_mpi_release (&session->key->dh_secret);
+
+ ret = MHD_gtls_mpi_dprint (&session->key->key, session->key->KEY);
+
+ MHD_gtls_mpi_release (&session->key->KEY);
+
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+MHD_gtls_gen_dh_common_client_kx (MHD_gtls_session_t session, opaque ** data)
+{
+ mpi_t x = NULL, X = NULL;
+ size_t n_X;
+ int ret;
+
+ *data = NULL;
+
+ X = MHD_gtls_calc_dh_secret (&x, session->key->client_g,
+ session->key->client_p);
+ if (X == NULL || x == NULL)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto error;
+ }
+
+ MHD_gtls_dh_set_secret_bits (session, MHD__gnutls_mpi_get_nbits (x));
+
+ MHD_gtls_mpi_print (NULL, &n_X, X);
+ (*data) = MHD_gnutls_malloc (n_X + 2);
+ if (*data == NULL)
+ {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto error;
+ }
+
+ MHD_gtls_mpi_print (&(*data)[2], &n_X, X);
+ MHD_gtls_mpi_release (&X);
+
+ MHD_gtls_write_uint16 (n_X, &(*data)[0]);
+
+ /* calculate the key after calculating the message */
+ session->key->KEY =
+ MHD_gtls_calc_dh_key (session->key->client_Y, x, session->key->client_p);
+
+ MHD_gtls_mpi_release (&x);
+ if (session->key->KEY == NULL)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto error;
+ }
+
+ /* THESE SHOULD BE DISCARDED */
+ MHD_gtls_mpi_release (&session->key->client_Y);
+ MHD_gtls_mpi_release (&session->key->client_p);
+ MHD_gtls_mpi_release (&session->key->client_g);
+
+ ret = MHD_gtls_mpi_dprint (&session->key->key, session->key->KEY);
+
+ MHD_gtls_mpi_release (&session->key->KEY);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ return n_X + 2;
+
+error:
+ MHD_gtls_mpi_release (&x);
+ MHD_gtls_mpi_release (&X);
+ MHD_gnutls_free (*data);
+ *data = NULL;
+ return ret;
+}
+
+int
+MHD_gtls_proc_dh_common_server_kx (MHD_gtls_session_t session,
+ opaque * data, size_t _data_size, int psk)
+{
+ uint16_t n_Y, n_g, n_p;
+ size_t _n_Y, _n_g, _n_p;
+ uint8_t *data_p;
+ uint8_t *data_g;
+ uint8_t *data_Y;
+ int i, bits, psk_size, ret;
+ ssize_t data_size = _data_size;
+
+ i = 0;
+
+ if (psk != 0)
+ {
+ DECR_LEN (data_size, 2);
+ psk_size = MHD_gtls_read_uint16 (&data[i]);
+ DECR_LEN (data_size, psk_size);
+ i += 2 + psk_size;
+ }
+
+ DECR_LEN (data_size, 2);
+ n_p = MHD_gtls_read_uint16 (&data[i]);
+ i += 2;
+
+ DECR_LEN (data_size, n_p);
+ data_p = &data[i];
+ i += n_p;
+
+ DECR_LEN (data_size, 2);
+ n_g = MHD_gtls_read_uint16 (&data[i]);
+ i += 2;
+
+ DECR_LEN (data_size, n_g);
+ data_g = &data[i];
+ i += n_g;
+
+ DECR_LEN (data_size, 2);
+ n_Y = MHD_gtls_read_uint16 (&data[i]);
+ i += 2;
+
+ DECR_LEN (data_size, n_Y);
+ data_Y = &data[i];
+ i += n_Y;
+
+ _n_Y = n_Y;
+ _n_g = n_g;
+ _n_p = n_p;
+
+ if (MHD_gtls_mpi_scan_nz (&session->key->client_Y, data_Y, &_n_Y) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ if (MHD_gtls_mpi_scan_nz (&session->key->client_g, data_g, &_n_g) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+ if (MHD_gtls_mpi_scan_nz (&session->key->client_p, data_p, &_n_p) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ bits = MHD_gtls_dh_get_allowed_prime_bits (session);
+ if (bits < 0)
+ {
+ MHD_gnutls_assert ();
+ return bits;
+ }
+
+ if (MHD__gnutls_mpi_get_nbits (session->key->client_p) < (size_t) bits)
+ {
+ /* the prime used by the peer is not acceptable
+ */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
+ }
+
+ MHD_gtls_dh_set_group (session, session->key->client_g,
+ session->key->client_p);
+ MHD_gtls_dh_set_peer_public (session, session->key->client_Y);
+
+ ret = n_Y + n_p + n_g + 6;
+ if (psk != 0)
+ ret += 2;
+
+ return ret;
+}
+
+/* If the psk flag is set, then an empty psk_identity_hint will
+ * be inserted */
+int
+MHD_gtls_dh_common_print_server_kx (MHD_gtls_session_t session,
+ mpi_t g, mpi_t p, opaque ** data, int psk)
+{
+ mpi_t x, X;
+ size_t n_X, n_g, n_p;
+ int ret, data_size, pos;
+ uint8_t *pdata;
+
+ X = MHD_gtls_calc_dh_secret (&x, g, p);
+ if (X == NULL || x == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ session->key->dh_secret = x;
+ MHD_gtls_dh_set_secret_bits (session, MHD__gnutls_mpi_get_nbits (x));
+
+ MHD_gtls_mpi_print (NULL, &n_g, g);
+ MHD_gtls_mpi_print (NULL, &n_p, p);
+ MHD_gtls_mpi_print (NULL, &n_X, X);
+
+ data_size = n_g + n_p + n_X + 6;
+ if (psk != 0)
+ data_size += 2;
+
+ (*data) = MHD_gnutls_malloc (data_size);
+ if (*data == NULL)
+ {
+ MHD_gtls_mpi_release (&X);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ pos = 0;
+ pdata = *data;
+
+ if (psk != 0)
+ {
+ MHD_gtls_write_uint16 (0, &pdata[pos]);
+ pos += 2;
+ }
+
+ MHD_gtls_mpi_print (&pdata[pos + 2], &n_p, p);
+ MHD_gtls_write_uint16 (n_p, &pdata[pos]);
+
+ pos += n_p + 2;
+
+ MHD_gtls_mpi_print (&pdata[pos + 2], &n_g, g);
+ MHD_gtls_write_uint16 (n_g, &pdata[pos]);
+
+ pos += n_g + 2;
+
+ MHD_gtls_mpi_print (&pdata[pos + 2], &n_X, X);
+ MHD_gtls_mpi_release (&X);
+
+ MHD_gtls_write_uint16 (n_X, &pdata[pos]);
+
+ ret = data_size;
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.h b/lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.h
new file mode 100644
index 0000000000..f09ce6dc4b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_dh_common.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef AUTH_DH_COMMON
+# define AUTH_DH_COMMON
+
+typedef struct
+{
+ int secret_bits;
+
+ MHD_gnutls_datum_t prime;
+ MHD_gnutls_datum_t generator;
+ MHD_gnutls_datum_t public_key;
+} MHD_gtls_dh_info_st;
+
+void MHD_gtls_free_dh_info (MHD_gtls_dh_info_st * dh);
+int MHD_gtls_gen_dh_common_client_kx (MHD_gtls_session_t, opaque **);
+int MHD_gtls_proc_dh_common_client_kx (MHD_gtls_session_t session,
+ opaque * data, size_t _data_size,
+ mpi_t p, mpi_t g);
+int MHD_gtls_dh_common_print_server_kx (MHD_gtls_session_t, mpi_t g, mpi_t p,
+ opaque ** data, int psk);
+int MHD_gtls_proc_dh_common_server_kx (MHD_gtls_session_t session,
+ opaque * data, size_t _data_size,
+ int psk);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_dhe.c b/lib/libmicrohttpd/src/daemon/https/tls/auth_dhe.c
new file mode 100644
index 0000000000..38407f9dc2
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_dhe.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains everything for the Ephemeral Diffie Hellman (DHE)
+ * key exchange. This is used in the handshake procedure of the certificate
+ * authentication.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "gnutls_sig.h"
+#include <gnutls_datum.h>
+#include <auth_cert.h>
+#include <gnutls_x509.h>
+#include <gnutls_state.h>
+#include <auth_dh_common.h>
+
+static int gen_dhe_server_kx (MHD_gtls_session_t, opaque **);
+static int proc_dhe_server_kx (MHD_gtls_session_t, opaque *, size_t);
+static int proc_dhe_client_kx (MHD_gtls_session_t, opaque *, size_t);
+
+const MHD_gtls_mod_auth_st MHD_gtls_dhe_rsa_auth_struct = {
+ "DHE_RSA",
+ MHD_gtls_gen_cert_server_certificate,
+ MHD_gtls_gen_cert_client_certificate,
+ gen_dhe_server_kx,
+ MHD_gtls_gen_dh_common_client_kx,
+ MHD_gtls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
+ MHD_gtls_gen_cert_server_cert_req, /* server cert request */
+
+ MHD_gtls_proc_cert_server_certificate,
+ MHD__gnutls_proc_cert_client_certificate,
+ proc_dhe_server_kx,
+ proc_dhe_client_kx,
+ MHD_gtls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
+ MHD_gtls_proc_cert_cert_req /* proc server cert request */
+};
+
+const MHD_gtls_mod_auth_st MHD_gtls_dhe_dss_auth_struct = {
+ "DHE_DSS",
+ MHD_gtls_gen_cert_server_certificate,
+ MHD_gtls_gen_cert_client_certificate,
+ gen_dhe_server_kx,
+ MHD_gtls_gen_dh_common_client_kx,
+ MHD_gtls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
+ MHD_gtls_gen_cert_server_cert_req, /* server cert request */
+
+ MHD_gtls_proc_cert_server_certificate,
+ MHD__gnutls_proc_cert_client_certificate,
+ proc_dhe_server_kx,
+ proc_dhe_client_kx,
+ MHD_gtls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
+ MHD_gtls_proc_cert_cert_req /* proc server cert request */
+};
+
+
+static int
+gen_dhe_server_kx (MHD_gtls_session_t session, opaque ** data)
+{
+ mpi_t g, p;
+ const mpi_t *mpis;
+ int ret = 0, data_size;
+ MHD_gnutls_cert *apr_cert_list;
+ MHD_gnutls_privkey *apr_pkey;
+ int apr_cert_list_length;
+ MHD_gnutls_datum_t signature, ddata;
+ MHD_gtls_cert_credentials_t cred;
+ MHD_gtls_dh_params_t dh_params;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ /* find the appropriate certificate */
+ if ((ret =
+ MHD_gtls_get_selected_cert (session, &apr_cert_list,
+ &apr_cert_list_length, &apr_pkey)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ dh_params =
+ MHD_gtls_get_dh_params (cred->dh_params, cred->params_func, session);
+ mpis = MHD_gtls_dh_params_to_mpi (dh_params);
+ if (mpis == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
+ }
+
+ p = mpis[0];
+ g = mpis[1];
+
+ if ((ret = MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
+ sizeof (cert_auth_info_st), 0)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gtls_dh_set_group (session, g, p);
+
+ ret = MHD_gtls_dh_common_print_server_kx (session, g, p, data, 0);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ data_size = ret;
+
+ /* Generate the signature. */
+
+ ddata.data = *data;
+ ddata.size = data_size;
+
+ if (apr_cert_list_length > 0)
+ {
+ if ((ret =
+ MHD_gtls_tls_sign_params (session, &apr_cert_list[0],
+ apr_pkey, &ddata, &signature)) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (*data);
+ return ret;
+ }
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return data_size; /* do not put a signature - ILLEGAL! */
+ }
+
+ *data = MHD_gtls_realloc_fast (*data, data_size + signature.size + 2);
+ if (*data == NULL)
+ {
+ MHD__gnutls_free_datum (&signature);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD_gtls_write_datum16 (&(*data)[data_size], signature);
+ data_size += signature.size + 2;
+
+ MHD__gnutls_free_datum (&signature);
+
+ return data_size;
+}
+
+static int
+proc_dhe_server_kx (MHD_gtls_session_t session, opaque * data,
+ size_t _data_size)
+{
+ int sigsize;
+ MHD_gnutls_datum_t vparams, signature;
+ int ret;
+ cert_auth_info_t info = MHD_gtls_get_auth_info (session);
+ ssize_t data_size = _data_size;
+ MHD_gnutls_cert peer_cert;
+
+ if (info == NULL || info->ncerts == 0)
+ {
+ MHD_gnutls_assert ();
+ /* we need this in order to get peer's certificate */
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ret = MHD_gtls_proc_dh_common_server_kx (session, data, _data_size, 0);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* VERIFY SIGNATURE */
+
+ vparams.size = ret;
+ vparams.data = data;
+
+ DECR_LEN (data_size, 2);
+ sigsize = MHD_gtls_read_uint16 (&data[vparams.size]);
+
+ DECR_LEN (data_size, sigsize);
+ signature.data = &data[vparams.size + 2];
+ signature.size = sigsize;
+
+ if ((ret =
+ MHD_gtls_raw_cert_to_gcert (&peer_cert,
+ session->security_parameters.cert_type,
+ &info->raw_certificate_list[0],
+ CERT_NO_COPY)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret =
+ MHD_gtls_verify_sig_params (session, &peer_cert, &vparams, &signature);
+
+ MHD_gtls_gcert_deinit (&peer_cert);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return ret;
+}
+
+
+
+static int
+proc_dhe_client_kx (MHD_gtls_session_t session, opaque * data,
+ size_t _data_size)
+{
+ MHD_gtls_cert_credentials_t cred;
+ int ret;
+ mpi_t p, g;
+ const mpi_t *mpis;
+ MHD_gtls_dh_params_t dh_params;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ dh_params =
+ MHD_gtls_get_dh_params (cred->dh_params, cred->params_func, session);
+ mpis = MHD_gtls_dh_params_to_mpi (dh_params);
+ if (mpis == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
+ }
+
+ p = mpis[0];
+ g = mpis[1];
+
+ ret = MHD_gtls_proc_dh_common_client_kx (session, data, _data_size, g, p);
+
+ return ret;
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_rsa.c b/lib/libmicrohttpd/src/daemon/https/tls/auth_rsa.c
new file mode 100644
index 0000000000..9548a8f17b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_rsa.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the RSA key exchange part of the certificate
+ * authentication.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "gnutls_datum.h"
+#include "auth_cert.h"
+#include <gnutls_pk.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_global.h>
+#include "debug.h"
+#include <gnutls_sig.h>
+#include <gnutls_x509.h>
+#include <gc.h>
+
+int MHD__gnutls_gen_rsa_client_kx (MHD_gtls_session_t, opaque **);
+int MHD__gnutls_proc_rsa_client_kx (MHD_gtls_session_t, opaque *, size_t);
+
+const MHD_gtls_mod_auth_st MHD_gtls_rsa_auth_struct = {
+ "RSA",
+ MHD_gtls_gen_cert_server_certificate,
+ MHD_gtls_gen_cert_client_certificate,
+ NULL, /* gen server kx */
+ MHD__gnutls_gen_rsa_client_kx,
+ MHD_gtls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
+ MHD_gtls_gen_cert_server_cert_req, /* server cert request */
+
+ MHD_gtls_proc_cert_server_certificate,
+ MHD__gnutls_proc_cert_client_certificate,
+ NULL, /* proc server kx */
+ MHD__gnutls_proc_rsa_client_kx, /* proc client kx */
+ MHD_gtls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
+ MHD_gtls_proc_cert_cert_req /* proc server cert request */
+};
+
+/* This function reads the RSA parameters from peer's certificate;
+ */
+int
+MHD__gnutls_get_public_rsa_params (MHD_gtls_session_t session,
+ mpi_t params[MAX_PUBLIC_PARAMS_SIZE],
+ int *params_len)
+{
+ int ret;
+ cert_auth_info_t info;
+ MHD_gnutls_cert peer_cert;
+ int i;
+
+ /* normal non export case */
+
+ info = MHD_gtls_get_auth_info (session);
+
+ if (info == NULL || info->ncerts == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ret =
+ MHD_gtls_raw_cert_to_gcert (&peer_cert,
+ session->security_parameters.cert_type,
+ &info->raw_certificate_list[0],
+ CERT_ONLY_PUBKEY | CERT_NO_COPY);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+
+ /* EXPORT case: */
+ if (MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.current_cipher_suite)
+ == MHD_GNUTLS_KX_RSA_EXPORT
+ && MHD__gnutls_mpi_get_nbits (peer_cert.params[0]) > 512)
+ {
+
+ MHD_gtls_gcert_deinit (&peer_cert);
+
+ if (session->key->rsa[0] == NULL || session->key->rsa[1] == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (*params_len < 2)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ *params_len = 2;
+ for (i = 0; i < *params_len; i++)
+ {
+ params[i] = MHD__gnutls_mpi_copy (session->key->rsa[i]);
+ }
+
+ return 0;
+ }
+
+ /* end of export case */
+
+ if (*params_len < peer_cert.params_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ *params_len = peer_cert.params_size;
+
+ for (i = 0; i < *params_len; i++)
+ {
+ params[i] = MHD__gnutls_mpi_copy (peer_cert.params[i]);
+ }
+ MHD_gtls_gcert_deinit (&peer_cert);
+
+ return 0;
+}
+
+/* This function reads the RSA parameters from the private key
+ */
+int
+MHD__gnutls_get_private_rsa_params (MHD_gtls_session_t session,
+ mpi_t ** params, int *params_size)
+{
+ int bits;
+ MHD_gtls_cert_credentials_t cred;
+ MHD_gtls_rsa_params_t rsa_params;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ if (session->internals.selected_cert_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ bits =
+ MHD__gnutls_mpi_get_nbits (session->internals.selected_cert_list[0].
+ params[0]);
+
+ if (MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.current_cipher_suite)
+ == MHD_GNUTLS_KX_RSA_EXPORT && bits > 512)
+ {
+
+ rsa_params =
+ MHD_gtls_certificate_get_rsa_params (cred->rsa_params,
+ cred->params_func, session);
+ /* EXPORT case: */
+ if (rsa_params == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
+ }
+
+ /* In the export case, we do use temporary RSA params
+ * of 512 bits size. The params in the certificate are
+ * used to sign this temporary stuff.
+ */
+ *params_size = RSA_PRIVATE_PARAMS;
+ *params = rsa_params->params;
+
+ return 0;
+ }
+
+ /* non export cipher suites. */
+
+ *params_size = session->internals.selected_key->params_size;
+ *params = session->internals.selected_key->params;
+
+ return 0;
+}
+
+int
+MHD__gnutls_proc_rsa_client_kx (MHD_gtls_session_t session, opaque * data,
+ size_t _data_size)
+{
+ MHD_gnutls_datum_t plaintext;
+ MHD_gnutls_datum_t ciphertext;
+ int ret, dsize;
+ mpi_t *params;
+ int params_len;
+ int randomize_key = 0;
+ ssize_t data_size = _data_size;
+
+ if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ /* SSL 3.0
+ */
+ ciphertext.data = data;
+ ciphertext.size = data_size;
+ }
+ else
+ {
+ /* TLS 1.0
+ */
+ DECR_LEN (data_size, 2);
+ ciphertext.data = &data[2];
+ dsize = MHD_gtls_read_uint16 (data);
+
+ if (dsize != data_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ ciphertext.size = dsize;
+ }
+
+ ret = MHD__gnutls_get_private_rsa_params (session, &params, &params_len);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD_gtls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, params_len, 2); /* btype==2 */
+
+ if (ret < 0 || plaintext.size != TLS_MASTER_SIZE)
+ {
+ /* In case decryption fails then don't inform
+ * the peer. Just use a random key. (in order to avoid
+ * attack against pkcs-1 formating).
+ */
+ MHD_gnutls_assert ();
+ MHD__gnutls_x509_log ("auth_rsa: Possible PKCS #1 format attack\n");
+ randomize_key = 1;
+ }
+ else
+ {
+ /* If the secret was properly formatted, then
+ * check the version number.
+ */
+ if (MHD__gnutls_get_adv_version_major (session) != plaintext.data[0]
+ || MHD__gnutls_get_adv_version_minor (session) != plaintext.data[1])
+ {
+ /* No error is returned here, if the version number check
+ * fails. We proceed normally.
+ * That is to defend against the attack described in the paper
+ * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
+ * Ondej Pokorny and Tomas Rosa.
+ */
+ MHD_gnutls_assert ();
+ MHD__gnutls_x509_log
+ ("auth_rsa: Possible PKCS #1 version check format attack\n");
+ }
+ }
+
+ if (randomize_key != 0)
+ {
+ session->key->key.size = TLS_MASTER_SIZE;
+ session->key->key.data = MHD_gnutls_malloc (session->key->key.size);
+ if (session->key->key.data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* we do not need strong random numbers here.
+ */
+ if (MHD_gc_nonce
+ ((char *) session->key->key.data, session->key->key.size) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+
+ }
+ else
+ {
+ session->key->key.data = plaintext.data;
+ session->key->key.size = plaintext.size;
+ }
+
+ /* This is here to avoid the version check attack
+ * discussed above.
+ */
+ session->key->key.data[0] = MHD__gnutls_get_adv_version_major (session);
+ session->key->key.data[1] = MHD__gnutls_get_adv_version_minor (session);
+
+ return 0;
+}
+
+
+
+/* return RSA(random) using the peers public key
+ */
+int
+MHD__gnutls_gen_rsa_client_kx (MHD_gtls_session_t session, opaque ** data)
+{
+ cert_auth_info_t auth;
+ MHD_gnutls_datum_t sdata; /* data to send */
+ mpi_t params[MAX_PUBLIC_PARAMS_SIZE];
+ int params_len = MAX_PUBLIC_PARAMS_SIZE;
+ int ret, i;
+ enum MHD_GNUTLS_Protocol ver;
+
+ if (session->key == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ auth = session->key->auth_info;
+ if (auth == NULL)
+ {
+ /* this shouldn't have happened. The proc_certificate
+ * function should have detected that.
+ */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ session->key->key.size = TLS_MASTER_SIZE;
+ session->key->key.data = MHD_gnutls_secure_malloc (session->key->key.size);
+
+ if (session->key->key.data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (MHD_gc_pseudo_random ((char *) session->key->key.data,
+ session->key->key.size) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+
+ ver = MHD_gtls_get_adv_version (session);
+
+ if (session->internals.rsa_pms_version[0] == 0)
+ {
+ session->key->key.data[0] = MHD_gtls_version_get_major (ver);
+ session->key->key.data[1] = MHD_gtls_version_get_minor (ver);
+ }
+ else
+ { /* use the version provided */
+ session->key->key.data[0] = session->internals.rsa_pms_version[0];
+ session->key->key.data[1] = session->internals.rsa_pms_version[1];
+ }
+
+ /* move RSA parameters to key (session).
+ */
+ if ((ret =
+ MHD__gnutls_get_public_rsa_params (session, params, &params_len)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if ((ret =
+ MHD_gtls_pkcs1_rsa_encrypt (&sdata, &session->key->key,
+ params, params_len, 2)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ for (i = 0; i < params_len; i++)
+ MHD_gtls_mpi_release (&params[i]);
+
+ if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ /* SSL 3.0 */
+ *data = sdata.data;
+ return sdata.size;
+ }
+ else
+ { /* TLS 1 */
+ *data = MHD_gnutls_malloc (sdata.size + 2);
+ if (*data == NULL)
+ {
+ MHD__gnutls_free_datum (&sdata);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ MHD_gtls_write_datum16 (*data, sdata);
+ ret = sdata.size + 2;
+ MHD__gnutls_free_datum (&sdata);
+ return ret;
+ }
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/auth_rsa_export.c b/lib/libmicrohttpd/src/daemon/https/tls/auth_rsa_export.c
new file mode 100644
index 0000000000..575a2b72e1
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/auth_rsa_export.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the RSA key exchange part of the certificate
+ * authentication.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "gnutls_datum.h"
+#include "auth_cert.h"
+#include <gnutls_pk.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_global.h>
+#include "debug.h"
+#include <gnutls_sig.h>
+#include <gnutls_x509.h>
+#include <gnutls_rsa_export.h>
+#include <gnutls_state.h>
+
+int MHD__gnutls_gen_rsa_client_kx (MHD_gtls_session_t, opaque **);
+int MHD__gnutls_proc_rsa_client_kx (MHD_gtls_session_t, opaque *, size_t);
+static int gen_rsa_export_server_kx (MHD_gtls_session_t, opaque **);
+static int proc_rsa_export_server_kx (MHD_gtls_session_t, opaque *, size_t);
+
+const MHD_gtls_mod_auth_st MHD_rsa_export_auth_struct = {
+ "RSA EXPORT",
+ MHD_gtls_gen_cert_server_certificate,
+ MHD_gtls_gen_cert_client_certificate,
+ gen_rsa_export_server_kx,
+ MHD__gnutls_gen_rsa_client_kx,
+ MHD_gtls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
+ MHD_gtls_gen_cert_server_cert_req, /* server cert request */
+
+ MHD_gtls_proc_cert_server_certificate,
+ MHD__gnutls_proc_cert_client_certificate,
+ proc_rsa_export_server_kx,
+ MHD__gnutls_proc_rsa_client_kx, /* proc client kx */
+ MHD_gtls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
+ MHD_gtls_proc_cert_cert_req /* proc server cert request */
+};
+
+static int
+gen_rsa_export_server_kx (MHD_gtls_session_t session, opaque ** data)
+{
+ MHD_gtls_rsa_params_t rsa_params;
+ const mpi_t *rsa_mpis;
+ size_t n_e, n_m;
+ uint8_t *data_e, *data_m;
+ int ret = 0, data_size;
+ MHD_gnutls_cert *apr_cert_list;
+ MHD_gnutls_privkey *apr_pkey;
+ int apr_cert_list_length;
+ MHD_gnutls_datum_t signature, ddata;
+ MHD_gtls_cert_credentials_t cred;
+
+ cred = (MHD_gtls_cert_credentials_t)
+ MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ /* find the appropriate certificate */
+ if ((ret =
+ MHD_gtls_get_selected_cert (session, &apr_cert_list,
+ &apr_cert_list_length, &apr_pkey)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* abort sending this message if we have a certificate
+ * of 512 bits or less.
+ */
+ if (apr_pkey && MHD__gnutls_mpi_get_nbits (apr_pkey->params[0]) <= 512)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INT_RET_0;
+ }
+
+ rsa_params =
+ MHD_gtls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
+ session);
+ rsa_mpis = MHD__gnutls_rsa_params_to_mpi (rsa_params);
+ if (rsa_mpis == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
+ }
+
+ if ((ret = MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
+ sizeof (cert_auth_info_st), 0)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gtls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);
+
+ MHD_gtls_mpi_print (NULL, &n_m, rsa_mpis[0]);
+ MHD_gtls_mpi_print (NULL, &n_e, rsa_mpis[1]);
+
+ (*data) = MHD_gnutls_malloc (n_e + n_m + 4);
+ if (*data == NULL)
+ {
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ data_m = &(*data)[0];
+ MHD_gtls_mpi_print (&data_m[2], &n_m, rsa_mpis[0]);
+
+ MHD_gtls_write_uint16 (n_m, data_m);
+
+ data_e = &data_m[2 + n_m];
+ MHD_gtls_mpi_print (&data_e[2], &n_e, rsa_mpis[1]);
+
+ MHD_gtls_write_uint16 (n_e, data_e);
+
+ data_size = n_m + n_e + 4;
+
+
+ /* Generate the signature. */
+
+ ddata.data = *data;
+ ddata.size = data_size;
+
+ if (apr_cert_list_length > 0)
+ {
+ if ((ret =
+ MHD_gtls_tls_sign_params (session, &apr_cert_list[0],
+ apr_pkey, &ddata, &signature)) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (*data);
+ *data = NULL;
+ return ret;
+ }
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return data_size; /* do not put a signature - ILLEGAL! */
+ }
+
+ *data = MHD_gtls_realloc_fast (*data, data_size + signature.size + 2);
+ if (*data == NULL)
+ {
+ MHD__gnutls_free_datum (&signature);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD_gtls_write_datum16 (&((*data)[data_size]), signature);
+ data_size += signature.size + 2;
+
+ MHD__gnutls_free_datum (&signature);
+
+ return data_size;
+}
+
+/* if the peer's certificate is of 512 bits or less, returns non zero.
+ */
+int
+MHD__gnutls_peers_cert_less_512 (MHD_gtls_session_t session)
+{
+ MHD_gnutls_cert peer_cert;
+ int ret;
+ cert_auth_info_t info = MHD_gtls_get_auth_info (session);
+
+ if (info == NULL || info->ncerts == 0)
+ {
+ MHD_gnutls_assert ();
+ /* we need this in order to get peer's certificate */
+ return 0;
+ }
+
+ if ((ret =
+ MHD_gtls_raw_cert_to_gcert (&peer_cert,
+ session->security_parameters.cert_type,
+ &info->raw_certificate_list[0],
+ CERT_NO_COPY)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return 0;
+ }
+
+ if (peer_cert.subject_pk_algorithm != MHD_GNUTLS_PK_RSA)
+ {
+ MHD_gnutls_assert ();
+ MHD_gtls_gcert_deinit (&peer_cert);
+ return 0;
+ }
+
+ if (MHD__gnutls_mpi_get_nbits (peer_cert.params[0]) <= 512)
+ {
+ MHD_gtls_gcert_deinit (&peer_cert);
+ return 1;
+ }
+
+ MHD_gtls_gcert_deinit (&peer_cert);
+
+ return 0;
+}
+
+static int
+proc_rsa_export_server_kx (MHD_gtls_session_t session,
+ opaque * data, size_t _data_size)
+{
+ uint16_t n_m, n_e;
+ size_t _n_m, _n_e;
+ uint8_t *data_m;
+ uint8_t *data_e;
+ int i, sigsize;
+ MHD_gnutls_datum_t vparams, signature;
+ int ret;
+ ssize_t data_size = _data_size;
+ cert_auth_info_t info;
+ MHD_gnutls_cert peer_cert;
+
+ info = MHD_gtls_get_auth_info (session);
+ if (info == NULL || info->ncerts == 0)
+ {
+ MHD_gnutls_assert ();
+ /* we need this in order to get peer's certificate */
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+ i = 0;
+
+ DECR_LEN (data_size, 2);
+ n_m = MHD_gtls_read_uint16 (&data[i]);
+ i += 2;
+
+ DECR_LEN (data_size, n_m);
+ data_m = &data[i];
+ i += n_m;
+
+ DECR_LEN (data_size, 2);
+ n_e = MHD_gtls_read_uint16 (&data[i]);
+ i += 2;
+
+ DECR_LEN (data_size, n_e);
+ data_e = &data[i];
+ i += n_e;
+
+ _n_e = n_e;
+ _n_m = n_m;
+
+ if (MHD_gtls_mpi_scan_nz (&session->key->rsa[0], data_m, &_n_m) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ if (MHD_gtls_mpi_scan_nz (&session->key->rsa[1], data_e, &_n_e) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ MHD_gtls_rsa_export_set_pubkey (session, session->key->rsa[1],
+ session->key->rsa[0]);
+
+ /* VERIFY SIGNATURE */
+
+ vparams.size = n_m + n_e + 4;
+ vparams.data = data;
+
+ DECR_LEN (data_size, 2);
+ sigsize = MHD_gtls_read_uint16 (&data[vparams.size]);
+
+ DECR_LEN (data_size, sigsize);
+ signature.data = &data[vparams.size + 2];
+ signature.size = sigsize;
+
+ if ((ret =
+ MHD_gtls_raw_cert_to_gcert (&peer_cert,
+ session->security_parameters.cert_type,
+ &info->raw_certificate_list[0],
+ CERT_NO_COPY)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret =
+ MHD_gtls_verify_sig_params (session, &peer_cert, &vparams, &signature);
+
+ MHD_gtls_gcert_deinit (&peer_cert);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ }
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/debug.c b/lib/libmicrohttpd/src/daemon/https/tls/debug.c
new file mode 100644
index 0000000000..e7e41d0bdb
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/debug.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <gcrypt.h>
+
+const char *
+MHD__gnutls_packet2str (content_type_t packet)
+{
+ switch (packet)
+ {
+ case GNUTLS_CHANGE_CIPHER_SPEC:
+ return "Change Cipher Spec";
+ case GNUTLS_ALERT:
+ return "Alert";
+ case GNUTLS_HANDSHAKE:
+ return "Handshake";
+ case GNUTLS_APPLICATION_DATA:
+ return "Application Data";
+ case GNUTLS_INNER_APPLICATION:
+ return "Inner Application";
+
+ default:
+ return "Unknown Packet";
+ }
+}
+
+const char *
+MHD__gnutls_handshake2str (MHD_gnutls_handshake_description_t handshake)
+{
+
+ switch (handshake)
+ {
+ case GNUTLS_HANDSHAKE_HELLO_REQUEST:
+ return "HELLO REQUEST";
+ break;
+ case GNUTLS_HANDSHAKE_CLIENT_HELLO:
+ return "CLIENT HELLO";
+ break;
+ case GNUTLS_HANDSHAKE_SERVER_HELLO:
+ return "SERVER HELLO";
+ break;
+ case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
+ return "CERTIFICATE";
+ break;
+ case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:
+ return "SERVER KEY EXCHANGE";
+ break;
+ case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
+ return "CERTIFICATE REQUEST";
+ break;
+ case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
+ return "SERVER HELLO DONE";
+ break;
+ case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
+ return "CERTIFICATE VERIFY";
+ break;
+ case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
+ return "CLIENT KEY EXCHANGE";
+ break;
+ case GNUTLS_HANDSHAKE_FINISHED:
+ return "FINISHED";
+ break;
+ case GNUTLS_HANDSHAKE_SUPPLEMENTAL:
+ return "SUPPLEMENTAL";
+ break;
+ default:
+ return "Unknown Handshake packet";
+
+ }
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/debug.h b/lib/libmicrohttpd/src/daemon/https/tls/debug.h
new file mode 100644
index 0000000000..ba1f100609
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/debug.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+const char *MHD__gnutls_packet2str (content_type_t packet);
+const char *MHD__gnutls_handshake2str (MHD_gnutls_handshake_description_t
+ handshake);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/defines.h b/lib/libmicrohttpd/src/daemon/https/tls/defines.h
new file mode 100644
index 0000000000..9a63636058
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/defines.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef DEFINES_H
+# define DEFINES_H
+
+#ifdef HAVE_CONFIG_H
+# include "MHD_config.h"
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdint.h>
+
+#ifdef NO_SSIZE_T
+# define HAVE_SSIZE_T
+typedef int ssize_t;
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#ifndef MINGW
+#include <sys/socket.h>
+#endif
+#include <time.h>
+
+/* TODO check if these should go into config.h */
+#define SIZEOF_UNSIGNED_INT 4
+#define SIZEOF_UNSIGNED_LONG 8
+#define SIZEOF_UNSIGNED_LONG_INT SIZEOF_UNSIGNED_LONG
+
+/* some systems had problems with long long int, thus,
+ * it is not used.
+ */
+typedef struct
+{
+ unsigned char i[8];
+} uint64;
+
+#endif /* defines_h */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.c b/lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.c
new file mode 100644
index 0000000000..1e7966f454
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the code the Certificate Type TLS extension.
+ * This extension is currently gnutls specific.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+#include "ext_cert_type.h"
+#include "gnutls_state.h"
+#include "gnutls_num.h"
+
+inline static int MHD__gnutls_num2cert_type (int num);
+inline static int MHD__gnutls_cert_type2num (int record_size);
+
+/*
+ * In case of a server: if a CERT_TYPE extension type is received then it stores
+ * into the session security parameters the new value. The server may use MHD_gnutls_session_certificate_type_get(),
+ * to access it.
+ *
+ * In case of a client: If a cert_types have been specified then we send the extension.
+ *
+ */
+
+int
+MHD_gtls_cert_type_recv_params (MHD_gtls_session_t session,
+ const opaque * data, size_t _data_size)
+{
+ int new_type = -1, ret, i;
+ ssize_t data_size = _data_size;
+
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ if (data_size > 0)
+ {
+ if (data_size != 1)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ new_type = MHD__gnutls_num2cert_type (data[0]);
+
+ if (new_type < 0)
+ {
+ MHD_gnutls_assert ();
+ return new_type;
+ }
+
+ /* Check if we support this cert_type */
+ if ((ret =
+ MHD_gtls_session_cert_type_supported (session, new_type)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD__gnutls_session_cert_type_set (session, new_type);
+ }
+ }
+ else
+#endif
+
+ { /* SERVER SIDE - we must check if the sent cert type is the right one
+ */
+ if (data_size > 1)
+ {
+ uint8_t len;
+
+ len = data[0];
+ DECR_LEN (data_size, len);
+
+ for (i = 0; i < len; i++)
+ {
+ new_type = MHD__gnutls_num2cert_type (data[i + 1]);
+
+ if (new_type < 0)
+ continue;
+
+ /* Check if we support this cert_type */
+ if ((ret =
+ MHD_gtls_session_cert_type_supported (session,
+ new_type)) < 0)
+ {
+ MHD_gnutls_assert ();
+ continue;
+ }
+ else
+ break;
+ /* new_type is ok */
+ }
+
+ if (new_type < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ if ((ret =
+ MHD_gtls_session_cert_type_supported (session, new_type)) < 0)
+ {
+ MHD_gnutls_assert ();
+ /* The peer has requested unsupported certificate
+ * types. Instead of failing, procceed normally.
+ * (the ciphersuite selection would fail, or a
+ * non certificate ciphersuite will be selected).
+ */
+ return 0;
+ }
+
+ MHD__gnutls_session_cert_type_set (session, new_type);
+ }
+
+
+ }
+
+ return 0;
+}
+
+/* returns data_size or a negative number on failure
+ */
+int
+MHD_gtls_cert_type_send_params (MHD_gtls_session_t session, opaque * data,
+ size_t data_size)
+{
+ unsigned int len;
+
+ /* this function sends the client extension data (dnsname) */
+#if MHD_DEBUG_TLS
+ unsigned int i;
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+
+ if (session->internals.priorities.cert_type.num_algorithms > 0)
+ {
+
+ len = session->internals.priorities.cert_type.num_algorithms;
+
+ if (len == 1 &&
+ session->internals.priorities.cert_type.priority[0] ==
+ MHD_GNUTLS_CRT_X509)
+ {
+ /* We don't use this extension if X.509 certificates
+ * are used.
+ */
+ return 0;
+ }
+
+ if (data_size < len + 1)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ /* this is a vector!
+ */
+ data[0] = (uint8_t) len;
+
+ for (i = 0; i < len; i++)
+ {
+ data[i + 1] =
+ MHD__gnutls_cert_type2num (session->internals.
+ priorities.cert_type.priority[i]);
+ }
+ return len + 1;
+ }
+
+ }
+ else
+#endif
+ { /* server side */
+ if (session->security_parameters.cert_type != DEFAULT_CERT_TYPE)
+ {
+ len = 1;
+ if (data_size < len)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ data[0] =
+ MHD__gnutls_cert_type2num (session->
+ security_parameters.cert_type);
+ return len;
+ }
+
+
+ }
+
+ return 0;
+}
+
+/* Maps numbers to record sizes according to the
+ * extensions draft.
+ */
+inline static int
+MHD__gnutls_num2cert_type (int num)
+{
+ switch (num)
+ {
+ case 0:
+ return MHD_GNUTLS_CRT_X509;
+ default:
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+}
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+inline static int
+MHD__gnutls_cert_type2num (int cert_type)
+{
+ switch (cert_type)
+ {
+ case MHD_GNUTLS_CRT_X509:
+ return 0;
+ default:
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.h b/lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.h
new file mode 100644
index 0000000000..f80f7ba8f5
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/ext_cert_type.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+int MHD_gtls_cert_type_recv_params (MHD_gtls_session_t session,
+ const opaque * data, size_t data_size);
+int MHD_gtls_cert_type_send_params (MHD_gtls_session_t session, opaque * data,
+ size_t);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.c b/lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.c
new file mode 100644
index 0000000000..421a1739a3
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2001, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the code for the Max Record Size TLS extension.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+#include <ext_max_record.h>
+
+/*
+ * In case of a server: if a MAX_RECORD_SIZE extension type is received then it stores
+ * into the session the new value. The server may use MHD_gnutls_get_max_record_size(),
+ * in order to access it.
+ *
+ * In case of a client: If a different max record size (than the default) has
+ * been specified then it sends the extension.
+ *
+ */
+
+int
+MHD_gtls_max_record_recv_params (MHD_gtls_session_t session,
+ const opaque * data, size_t _data_size)
+{
+ ssize_t new_size;
+ ssize_t data_size = _data_size;
+
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ {
+ if (data_size > 0)
+ {
+ DECR_LEN (data_size, 1);
+
+ new_size = MHD_gtls_mre_num2record (data[0]);
+
+ if (new_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return new_size;
+ }
+
+ session->security_parameters.max_record_send_size = new_size;
+ session->security_parameters.max_record_recv_size = new_size;
+ }
+ }
+ else
+ { /* CLIENT SIDE - we must check if the sent record size is the right one
+ */
+ if (data_size > 0)
+ {
+
+ if (data_size != 1)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ new_size = MHD_gtls_mre_num2record (data[0]);
+
+ if (new_size < 0
+ || new_size != session->internals.proposed_record_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+ else
+ {
+ session->security_parameters.max_record_recv_size =
+ session->internals.proposed_record_size;
+ }
+
+ }
+
+
+ }
+
+ return 0;
+}
+
+/* returns data_size or a negative number on failure
+ */
+int
+MHD_gtls_max_record_send_params (MHD_gtls_session_t session, opaque * data,
+ size_t data_size)
+{
+ uint16_t len;
+ /* this function sends the client extension data (dnsname) */
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+
+ if (session->internals.proposed_record_size != DEFAULT_MAX_RECORD_SIZE)
+ {
+ len = 1;
+ if (data_size < len)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ data[0] =
+ (uint8_t) MHD_gtls_mre_record2num (session->internals.
+ proposed_record_size);
+ return len;
+ }
+
+ }
+ else
+#endif
+ { /* server side */
+
+ if (session->security_parameters.max_record_recv_size !=
+ DEFAULT_MAX_RECORD_SIZE)
+ {
+ len = 1;
+ if (data_size < len)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ data[0] =
+ (uint8_t)
+ MHD_gtls_mre_record2num
+ (session->security_parameters.max_record_recv_size);
+ return len;
+ }
+
+
+ }
+
+ return 0;
+}
+
+/* Maps numbers to record sizes according to the
+ * extensions draft.
+ */
+int
+MHD_gtls_mre_num2record (int num)
+{
+ switch (num)
+ {
+ case 1:
+ return 512;
+ case 2:
+ return 1024;
+ case 3:
+ return 2048;
+ case 4:
+ return 4096;
+ default:
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+}
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+int
+MHD_gtls_mre_record2num (uint16_t record_size)
+{
+ switch (record_size)
+ {
+ case 512:
+ return 1;
+ case 1024:
+ return 2;
+ case 2048:
+ return 3;
+ case 4096:
+ return 4;
+ default:
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.h b/lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.h
new file mode 100644
index 0000000000..1468625308
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/ext_max_record.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+int MHD_gtls_mre_num2record (int num);
+int MHD_gtls_mre_record2num (uint16_t record_size);
+int MHD_gtls_max_record_recv_params (MHD_gtls_session_t session,
+ const opaque * data, size_t data_size);
+int MHD_gtls_max_record_send_params (MHD_gtls_session_t session,
+ opaque * data, size_t);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.c b/lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.c
new file mode 100644
index 0000000000..911bd5302d
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+#include <ext_server_name.h>
+
+/*
+ * In case of a server: if a NAME_DNS extension type is received then it stores
+ * into the session the value of NAME_DNS. The server may use MHD_gnutls_ext_get_server_name(),
+ * in order to access it.
+ *
+ * In case of a client: If a proper NAME_DNS extension type is found in the session then
+ * it sends the extension to the peer.
+ *
+ */
+
+int
+MHD_gtls_server_name_recv_params (MHD_gtls_session_t session,
+ const opaque * data, size_t _data_size)
+{
+ int i;
+ const unsigned char *p;
+ uint16_t len, type;
+ ssize_t data_size = _data_size;
+ int server_names = 0;
+
+ DECR_LENGTH_RET (data_size, 2, 0);
+ len = MHD_gtls_read_uint16 (data);
+
+ if (len != data_size)
+ {
+ /* This is unexpected packet length, but
+ * just ignore it, for now.
+ */
+ MHD_gnutls_assert ();
+ return 0;
+ }
+
+ p = data + 2;
+
+ /* Count all server_names in the packet. */
+ while (data_size > 0)
+ {
+ DECR_LENGTH_RET (data_size, 1, 0);
+ p++;
+
+ DECR_LEN (data_size, 2);
+ len = MHD_gtls_read_uint16 (p);
+ p += 2;
+
+ /* make sure supplied server name is not empty */
+ if (len > 0)
+ {
+ DECR_LENGTH_RET (data_size, len, 0);
+ server_names++;
+ p += len;
+ }
+ else
+ {
+#if HAVE_MESSAGES
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Received zero size server name (under attack?)\n",
+ session);
+#endif
+ }
+ }
+
+ /* we cannot accept more server names. */
+ if (server_names > MAX_SERVER_NAME_EXTENSIONS)
+ {
+#if HAVE_MESSAGES
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Too many server names received (under attack?)\n",
+ session);
+#endif
+ server_names = MAX_SERVER_NAME_EXTENSIONS;
+ }
+
+ session->security_parameters.extensions.server_names_size = server_names;
+ if (server_names == 0)
+ return 0; /* no names found */
+
+ p = data + 2;
+ for (i = 0; i < server_names; i++)
+ {
+ type = *p;
+ p++;
+
+ len = MHD_gtls_read_uint16 (p);
+ p += 2;
+
+ switch (type)
+ {
+ case 0: /* NAME_DNS */
+ if (len <= MAX_SERVER_NAME_SIZE)
+ {
+ memcpy (session->security_parameters.extensions.
+ server_names[i].name, p, len);
+ session->security_parameters.extensions.server_names[i].
+ name_length = len;
+ session->security_parameters.extensions.server_names[i].type =
+ GNUTLS_NAME_DNS;
+ break;
+ }
+ }
+
+ /* move to next record */
+ p += len;
+ }
+ return 0;
+}
+
+/* returns data_size or a negative number on failure
+ */
+int
+MHD_gtls_server_name_send_params (MHD_gtls_session_t session,
+ opaque * data, size_t _data_size)
+{
+ int total_size = 0;
+#if MHD_DEBUG_TLS
+ uint16_t len;
+ opaque *p;
+ unsigned i;
+ ssize_t data_size = _data_size;
+
+ /* this function sends the client extension data (dnsname) */
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+
+ if (session->security_parameters.extensions.server_names_size == 0)
+ return 0;
+
+ /* uint16_t
+ */
+ total_size = 2;
+ for (i = 0;
+ i < session->security_parameters.extensions.server_names_size; i++)
+ {
+ /* count the total size
+ */
+ len =
+ session->security_parameters.extensions.server_names[i].
+ name_length;
+
+ /* uint8_t + uint16_t + size
+ */
+ total_size += 1 + 2 + len;
+ }
+
+ p = data;
+
+ /* UINT16: write total size of all names
+ */
+ DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
+ MHD_gtls_write_uint16 (total_size - 2, p);
+ p += 2;
+
+ for (i = 0;
+ i < session->security_parameters.extensions.server_names_size; i++)
+ {
+
+ switch (session->security_parameters.extensions.
+ server_names[i].type)
+ {
+ case GNUTLS_NAME_DNS:
+
+ len =
+ session->security_parameters.extensions.
+ server_names[i].name_length;
+ if (len == 0)
+ break;
+
+ /* UINT8: type of this extension
+ * UINT16: size of the first name
+ * LEN: the actual server name.
+ */
+ DECR_LENGTH_RET (data_size, len + 3,
+ GNUTLS_E_SHORT_MEMORY_BUFFER);
+
+ *p = 0; /* NAME_DNS type */
+ p++;
+
+ MHD_gtls_write_uint16 (len, p);
+ p += 2;
+
+ memcpy (p,
+ session->security_parameters.extensions.
+ server_names[0].name, len);
+ p += len;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+ }
+#endif
+ return total_size;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.h b/lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.h
new file mode 100644
index 0000000000..f74ce1913c
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/ext_server_name.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD_gtls_server_name_recv_params (MHD_gtls_session_t session,
+ const opaque * data, size_t data_size);
+int MHD_gtls_server_name_send_params (MHD_gtls_session_t session,
+ opaque * data, size_t);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_alert.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_alert.c
new file mode 100644
index 0000000000..4925f6e731
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_alert.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_record.h>
+#include <debug.h>
+
+typedef struct
+{
+ MHD_gnutls_alert_description_t alert;
+ const char *desc;
+} MHD_gnutls_alert_entry;
+
+static const MHD_gnutls_alert_entry MHD_gtls_sup_alerts[] = {
+ {GNUTLS_A_CLOSE_NOTIFY, "Close notify"},
+ {GNUTLS_A_UNEXPECTED_MESSAGE, "Unexpected message"},
+ {GNUTLS_A_BAD_RECORD_MAC, "Bad record MAC"},
+ {GNUTLS_A_DECRYPTION_FAILED, "Decryption failed"},
+ {GNUTLS_A_RECORD_OVERFLOW, "Record overflow"},
+ {GNUTLS_A_DECOMPRESSION_FAILURE, "Decompression failed"},
+ {GNUTLS_A_HANDSHAKE_FAILURE, "Handshake failed"},
+ {GNUTLS_A_BAD_CERTIFICATE, "Certificate is bad"},
+ {GNUTLS_A_UNSUPPORTED_CERTIFICATE, "Certificate is not supported"},
+ {GNUTLS_A_CERTIFICATE_REVOKED, "Certificate was revoked"},
+ {GNUTLS_A_CERTIFICATE_EXPIRED, "Certificate is expired"},
+ {GNUTLS_A_CERTIFICATE_UNKNOWN, "Unknown certificate"},
+ {GNUTLS_A_ILLEGAL_PARAMETER, "Illegal parameter"},
+ {GNUTLS_A_UNKNOWN_CA, "CA is unknown"},
+ {GNUTLS_A_ACCESS_DENIED, "Access was denied"},
+ {GNUTLS_A_DECODE_ERROR, "Decode error"},
+ {GNUTLS_A_DECRYPT_ERROR, "Decrypt error"},
+ {GNUTLS_A_EXPORT_RESTRICTION, "Export restriction"},
+ {GNUTLS_A_PROTOCOL_VERSION, "Error in protocol version"},
+ {GNUTLS_A_INSUFFICIENT_SECURITY, "Insufficient security"},
+ {GNUTLS_A_USER_CANCELED, "User canceled"},
+ {GNUTLS_A_INTERNAL_ERROR, "Internal error"},
+ {GNUTLS_A_NO_RENEGOTIATION, "No renegotiation is allowed"},
+ {GNUTLS_A_CERTIFICATE_UNOBTAINABLE,
+ "Could not retrieve the specified certificate"},
+ {GNUTLS_A_UNSUPPORTED_EXTENSION, "An unsupported extension was sent"},
+ {GNUTLS_A_UNRECOGNIZED_NAME,
+ "The server name sent was not recognized"},
+ {GNUTLS_A_UNKNOWN_PSK_IDENTITY,
+ "The SRP/PSK username is missing or not known"},
+};
+
+#define GNUTLS_ALERT_LOOP(b) \
+ const MHD_gnutls_alert_entry *p; \
+ for(p = MHD_gtls_sup_alerts; p->desc != NULL; p++) { b ; }
+
+#define GNUTLS_ALERT_ID_LOOP(a) \
+ GNUTLS_ALERT_LOOP( if(p->alert == alert) { a; break; })
+
+
+/**
+ * MHD__gnutls_alert_get_name - Returns a string describing the alert number given
+ * @alert: is an alert number #MHD_gtls_session_t structure.
+ *
+ * This function will return a string that describes the given alert
+ * number or NULL. See MHD_gnutls_alert_get().
+ *
+ **/
+const char *
+MHD__gnutls_alert_get_name (MHD_gnutls_alert_description_t alert)
+{
+ const char *ret = NULL;
+
+ GNUTLS_ALERT_ID_LOOP (ret = p->desc);
+
+ return ret;
+}
+
+/**
+ * MHD__gnutls_alert_send - This function sends an alert message to the peer
+ * @session: is a #MHD_gtls_session_t structure.
+ * @level: is the level of the alert
+ * @desc: is the alert description
+ *
+ * This function will send an alert to the peer in order to inform
+ * him of something important (eg. his Certificate could not be verified).
+ * If the alert level is Fatal then the peer is expected to close the
+ * connection, otherwise he may ignore the alert and continue.
+ *
+ * The error code of the underlying record send function will be returned,
+ * so you may also receive GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN as well.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+MHD__gnutls_alert_send (MHD_gtls_session_t session,
+ MHD_gnutls_alert_level_t level,
+ MHD_gnutls_alert_description_t desc)
+{
+ uint8_t data[2];
+ int ret;
+ const char *name;
+
+ data[0] = (uint8_t) level;
+ data[1] = (uint8_t) desc;
+
+ name = MHD__gnutls_alert_get_name ((int) data[1]);
+ if (name == NULL)
+ name = "(unknown)";
+ MHD__gnutls_record_log ("REC: Sending Alert[%d|%d] - %s\n", data[0],
+ data[1], name);
+
+ if ((ret = MHD_gtls_send_int (session, GNUTLS_ALERT, -1, data, 2)) >= 0)
+ return 0;
+ else
+ return ret;
+}
+
+/**
+ * MHD_gtls_error_to_alert - This function returns an alert code based on the given error code
+ * @err: is a negative integer
+ * @level: the alert level will be stored there
+ *
+ * Returns an alert depending on the error code returned by a gnutls
+ * function. All alerts sent by this function should be considered fatal.
+ * The only exception is when err == GNUTLS_E_REHANDSHAKE, where a warning
+ * alert should be sent to the peer indicating that no renegotiation will
+ * be performed.
+ *
+ * If there is no mapping to a valid alert the alert to indicate internal error
+ * is returned.
+ *
+ **/
+int
+MHD_gtls_error_to_alert (int err, int *level)
+{
+ int ret, _level = -1;
+
+ switch (err)
+ { /* send appropriate alert */
+ case GNUTLS_E_DECRYPTION_FAILED:
+ /* GNUTLS_A_DECRYPTION_FAILED is not sent, because
+ * it is not defined in SSL3. Note that we must
+ * not distinguish Decryption failures from mac
+ * check failures, due to the possibility of some
+ * attacks.
+ */
+ ret = GNUTLS_A_BAD_RECORD_MAC;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_DECOMPRESSION_FAILED:
+ ret = GNUTLS_A_DECOMPRESSION_FAILURE;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER:
+ case GNUTLS_E_ILLEGAL_SRP_USERNAME:
+ ret = GNUTLS_A_ILLEGAL_PARAMETER;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_ASN1_ELEMENT_NOT_FOUND:
+ case GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND:
+ case GNUTLS_E_ASN1_DER_ERROR:
+ case GNUTLS_E_ASN1_VALUE_NOT_FOUND:
+ case GNUTLS_E_ASN1_GENERIC_ERROR:
+ case GNUTLS_E_ASN1_VALUE_NOT_VALID:
+ case GNUTLS_E_ASN1_TAG_ERROR:
+ case GNUTLS_E_ASN1_TAG_IMPLICIT:
+ case GNUTLS_E_ASN1_TYPE_ANY_ERROR:
+ case GNUTLS_E_ASN1_SYNTAX_ERROR:
+ case GNUTLS_E_ASN1_DER_OVERFLOW:
+ ret = GNUTLS_A_BAD_CERTIFICATE;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_UNKNOWN_CIPHER_SUITE:
+ case GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM:
+ case GNUTLS_E_INSUFFICIENT_CREDENTIALS:
+ case GNUTLS_E_NO_CIPHER_SUITES:
+ case GNUTLS_E_NO_COMPRESSION_ALGORITHMS:
+ ret = GNUTLS_A_HANDSHAKE_FAILURE;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION:
+ ret = GNUTLS_A_UNSUPPORTED_EXTENSION;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_UNEXPECTED_PACKET:
+ case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET:
+ ret = GNUTLS_A_UNEXPECTED_MESSAGE;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_REHANDSHAKE:
+ ret = GNUTLS_A_NO_RENEGOTIATION;
+ _level = GNUTLS_AL_WARNING;
+ break;
+ case GNUTLS_E_UNSUPPORTED_VERSION_PACKET:
+ ret = GNUTLS_A_PROTOCOL_VERSION;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE:
+ ret = GNUTLS_A_UNSUPPORTED_CERTIFICATE;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
+ ret = GNUTLS_A_RECORD_OVERFLOW;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_INTERNAL_ERROR:
+ case GNUTLS_E_NO_TEMPORARY_DH_PARAMS:
+ case GNUTLS_E_NO_TEMPORARY_RSA_PARAMS:
+ ret = GNUTLS_A_INTERNAL_ERROR;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
+ case GNUTLS_E_NO_CERTIFICATE_FOUND:
+ ret = GNUTLS_A_INSUFFICIENT_SECURITY;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ default:
+ ret = GNUTLS_A_INTERNAL_ERROR;
+ _level = GNUTLS_AL_FATAL;
+ break;
+ }
+
+ if (level != NULL)
+ *level = _level;
+
+ return ret;
+}
+
+
+/**
+ * MHD__gnutls_alert_send_appropriate - This function sends an alert to the peer depending on the error code
+ * @session: is a #MHD_gtls_session_t structure.
+ * @err: is an integer
+ *
+ * Sends an alert to the peer depending on the error code returned by a gnutls
+ * function. This function will call MHD_gtls_error_to_alert() to determine
+ * the appropriate alert to send.
+ *
+ * This function may also return GNUTLS_E_AGAIN, or GNUTLS_E_INTERRUPTED.
+ *
+ * If the return value is GNUTLS_E_INVALID_REQUEST, then no alert has
+ * been sent to the peer.
+ *
+ * Returns zero on success.
+ */
+int
+MHD__gnutls_alert_send_appropriate (MHD_gtls_session_t session, int err)
+{
+ int alert;
+ int level;
+
+ alert = MHD_gtls_error_to_alert (err, &level);
+ if (alert < 0)
+ {
+ return alert;
+ }
+
+ return MHD__gnutls_alert_send (session, level, alert);
+}
+
+/**
+ * MHD_gnutls_alert_get - Returns the last alert number received.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function will return the last alert number received. This
+ * function should be called if GNUTLS_E_WARNING_ALERT_RECEIVED or
+ * GNUTLS_E_FATAL_ALERT_RECEIVED has been returned by a gnutls
+ * function. The peer may send alerts if he thinks some things were
+ * not right. Check gnutls.h for the available alert descriptions.
+ *
+ * If no alert has been received the returned value is undefined.
+ *
+ **/
+MHD_gnutls_alert_description_t
+MHD_gnutls_alert_get (MHD_gtls_session_t session)
+{
+ return session->internals.last_alert;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.c
new file mode 100644
index 0000000000..f65ccbac9d
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.c
@@ -0,0 +1,1340 @@
+/*
+ * Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_algorithms.h"
+#include "gnutls_errors.h"
+#include "gnutls_cert.h"
+/* x509 */
+#include "common.h"
+
+/* Cred type mappings to KX algorithms
+ * FIXME: The mappings are not 1-1. Some KX such as SRP_RSA require
+ * more than one credentials type.
+ */
+typedef struct
+{
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm;
+ enum MHD_GNUTLS_CredentialsType client_type;
+ enum MHD_GNUTLS_CredentialsType server_type; /* The type of credentials a server
+ * needs to set */
+} MHD_gnutls_cred_map;
+
+static const MHD_gnutls_cred_map MHD_gtls_cred_mappings[] = {
+ {MHD_GNUTLS_KX_RSA,
+ MHD_GNUTLS_CRD_CERTIFICATE,
+ MHD_GNUTLS_CRD_CERTIFICATE},
+ {MHD_GNUTLS_KX_RSA_EXPORT,
+ MHD_GNUTLS_CRD_CERTIFICATE,
+ MHD_GNUTLS_CRD_CERTIFICATE},
+ {0,
+ 0,
+ 0}
+};
+
+#define GNUTLS_KX_MAP_LOOP(b) \
+ const MHD_gnutls_cred_map *p; \
+ for(p = MHD_gtls_cred_mappings; p->algorithm != 0; p++) { b ; }
+
+#define GNUTLS_KX_MAP_ALG_LOOP_SERVER(a) \
+ GNUTLS_KX_MAP_LOOP( if(p->server_type == type) { a; break; })
+
+#define GNUTLS_KX_MAP_ALG_LOOP_CLIENT(a) \
+ GNUTLS_KX_MAP_LOOP( if(p->client_type == type) { a; break; })
+
+/* KX mappings to PK algorithms */
+typedef struct
+{
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk_algorithm;
+ enum encipher_type encipher_type; /* CIPHER_ENCRYPT if this algorithm is to be used
+ * for encryption, CIPHER_SIGN if signature only,
+ * CIPHER_IGN if this does not apply at all.
+ *
+ * This is useful to certificate cipher suites, which check
+ * against the certificate key usage bits.
+ */
+} MHD_gnutls_pk_map;
+
+/* This table maps the Key exchange algorithms to
+ * the certificate algorithms. Eg. if we have
+ * RSA algorithm in the certificate then we can
+ * use GNUTLS_KX_RSA or GNUTLS_KX_DHE_RSA.
+ */
+static const MHD_gnutls_pk_map MHD_gtls_pk_mappings[] = {
+ {MHD_GNUTLS_KX_RSA,
+ MHD_GNUTLS_PK_RSA,
+ CIPHER_ENCRYPT},
+ {MHD_GNUTLS_KX_RSA_EXPORT,
+ MHD_GNUTLS_PK_RSA,
+ CIPHER_SIGN},
+ {0,
+ 0,
+ 0}
+};
+
+#define GNUTLS_PK_MAP_LOOP(b) \
+ const MHD_gnutls_pk_map *p; \
+ for(p = MHD_gtls_pk_mappings; p->kx_algorithm != 0; p++) { b }
+
+#define GNUTLS_PK_MAP_ALG_LOOP(a) \
+ GNUTLS_PK_MAP_LOOP( if(p->kx_algorithm == kx_algorithm) { a; break; })
+
+/* TLS Versions */
+
+typedef struct
+{
+ const char *name;
+ enum MHD_GNUTLS_Protocol id; /* gnutls internal version number */
+ int major; /* defined by the protocol */
+ int minor; /* defined by the protocol */
+ int supported; /* 0 not supported, > 0 is supported */
+} MHD_gnutls_version_entry;
+
+static const MHD_gnutls_version_entry MHD_gtls_sup_versions[] = {
+ {"SSL3.0",
+ MHD_GNUTLS_PROTOCOL_SSL3,
+ 3,
+ 0,
+ 1},
+ {"TLS1.0",
+ MHD_GNUTLS_PROTOCOL_TLS1_0,
+ 3,
+ 1,
+ 1},
+ {"TLS1.1",
+ MHD_GNUTLS_PROTOCOL_TLS1_1,
+ 3,
+ 2,
+ 1},
+ {"TLS1.2",
+ MHD_GNUTLS_PROTOCOL_TLS1_2,
+ 3,
+ 3,
+ 1},
+ {0,
+ 0,
+ 0,
+ 0,
+ 0}
+};
+
+/* Keep the contents of this struct the same as the previous one. */
+static const enum MHD_GNUTLS_Protocol MHD_gtls_supported_protocols[] =
+{ MHD_GNUTLS_PROTOCOL_SSL3,
+ MHD_GNUTLS_PROTOCOL_TLS1_0,
+ MHD_GNUTLS_PROTOCOL_TLS1_1,
+ MHD_GNUTLS_PROTOCOL_TLS1_2,
+ 0
+};
+
+#define GNUTLS_VERSION_LOOP(b) \
+ const MHD_gnutls_version_entry *p; \
+ for(p = MHD_gtls_sup_versions; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_VERSION_ALG_LOOP(a) \
+ GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; })
+
+struct MHD_gnutls_cipher_entry
+{
+ const char *name;
+ enum MHD_GNUTLS_CipherAlgorithm id;
+ uint16_t blocksize;
+ uint16_t keysize;
+ cipher_type_t block;
+ uint16_t iv;
+ int export_flag; /* 0 non export */
+};
+typedef struct MHD_gnutls_cipher_entry MHD_gnutls_cipher_entry;
+
+/* Note that all algorithms are in CBC or STREAM modes.
+ * Do not add any algorithms in other modes (avoid modified algorithms).
+ * View first: "The order of encryption and authentication for
+ * protecting communications" by Hugo Krawczyk - CRYPTO 2001
+ */
+static const MHD_gnutls_cipher_entry MHD_gtls_algorithms[] = {
+ {"AES-256-CBC",
+ MHD_GNUTLS_CIPHER_AES_256_CBC,
+ 16,
+ 32,
+ CIPHER_BLOCK,
+ 16,
+ 0},
+ {"AES-128-CBC",
+ MHD_GNUTLS_CIPHER_AES_128_CBC,
+ 16,
+ 16,
+ CIPHER_BLOCK,
+ 16,
+ 0},
+ {"3DES-CBC",
+ MHD_GNUTLS_CIPHER_3DES_CBC,
+ 8,
+ 24,
+ CIPHER_BLOCK,
+ 8,
+ 0},
+ {"ARCFOUR-128",
+ MHD_GNUTLS_CIPHER_ARCFOUR_128,
+ 1,
+ 16,
+ CIPHER_STREAM,
+ 0,
+ 0},
+ {"NULL",
+ MHD_GNUTLS_CIPHER_NULL,
+ 1,
+ 0,
+ CIPHER_STREAM,
+ 0,
+ 0},
+ {0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0}
+};
+
+/* Keep the contents of this struct the same as the previous one. */
+static const enum MHD_GNUTLS_CipherAlgorithm MHD_gtls_supported_ciphers[] =
+{ MHD_GNUTLS_CIPHER_AES_256_CBC,
+ MHD_GNUTLS_CIPHER_AES_128_CBC,
+ MHD_GNUTLS_CIPHER_3DES_CBC,
+ MHD_GNUTLS_CIPHER_ARCFOUR_128,
+ MHD_GNUTLS_CIPHER_NULL,
+ 0
+};
+
+#define GNUTLS_LOOP(b) \
+ const MHD_gnutls_cipher_entry *p; \
+ for(p = MHD_gtls_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_ALG_LOOP(a) \
+ GNUTLS_LOOP( if(p->id == algorithm) { a; break; } )
+
+struct MHD_gnutls_hash_entry
+{
+ const char *name;
+ const char *oid;
+ enum MHD_GNUTLS_HashAlgorithm id;
+ size_t key_size; /* in case of mac */
+};
+typedef struct MHD_gnutls_hash_entry MHD_gnutls_hash_entry;
+
+static const MHD_gnutls_hash_entry MHD_gtls_hash_algorithms[] = {
+ {"SHA1",
+ HASH_OID_SHA1,
+ MHD_GNUTLS_MAC_SHA1,
+ 20},
+ {"MD5",
+ HASH_OID_MD5,
+ MHD_GNUTLS_MAC_MD5,
+ 16},
+ {"SHA256",
+ HASH_OID_SHA256,
+ MHD_GNUTLS_MAC_SHA256,
+ 32},
+ {"NULL",
+ NULL,
+ MHD_GNUTLS_MAC_NULL,
+ 0},
+ {0,
+ 0,
+ 0,
+ 0}
+};
+
+/* Keep the contents of this struct the same as the previous one. */
+static const enum MHD_GNUTLS_HashAlgorithm MHD_gtls_supported_macs[] =
+{ MHD_GNUTLS_MAC_SHA1,
+ MHD_GNUTLS_MAC_MD5,
+ MHD_GNUTLS_MAC_SHA256,
+ MHD_GNUTLS_MAC_NULL,
+ 0
+};
+
+#define GNUTLS_HASH_LOOP(b) \
+ const MHD_gnutls_hash_entry *p; \
+ for(p = MHD_gtls_hash_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_HASH_ALG_LOOP(a) \
+ GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } )
+
+/* Compression Section */
+#define GNUTLS_COMPRESSION_ENTRY(name, id, wb, ml, cl) \
+ { #name, name, id, wb, ml, cl}
+
+#define MAX_COMP_METHODS 5
+const int MHD__gnutls_comp_algorithms_size = MAX_COMP_METHODS;
+
+/* the compression entry is defined in MHD_gnutls_algorithms.h */
+
+MHD_gnutls_compression_entry
+ MHD__gnutls_compression_algorithms[MAX_COMP_METHODS] =
+{
+ GNUTLS_COMPRESSION_ENTRY (MHD_GNUTLS_COMP_NULL, 0x00, 0, 0, 0),
+ {
+ 0, 0, 0, 0, 0, 0}
+};
+
+static const enum MHD_GNUTLS_CompressionMethod
+ MHD_gtls_supported_compressions[] =
+{
+ MHD_GNUTLS_COMP_NULL,
+ 0
+};
+
+#define GNUTLS_COMPRESSION_LOOP(b) \
+ const MHD_gnutls_compression_entry *p; \
+ for(p = MHD__gnutls_compression_algorithms; p->name != NULL; p++) { b ; }
+#define GNUTLS_COMPRESSION_ALG_LOOP(a) \
+ GNUTLS_COMPRESSION_LOOP( if(p->id == algorithm) { a; break; } )
+#define GNUTLS_COMPRESSION_ALG_LOOP_NUM(a) \
+ GNUTLS_COMPRESSION_LOOP( if(p->num == num) { a; break; } )
+
+/* Key Exchange Section */
+extern MHD_gtls_mod_auth_st MHD_gtls_rsa_auth_struct;
+extern MHD_gtls_mod_auth_st MHD_rsa_export_auth_struct;
+extern MHD_gtls_mod_auth_st MHD_gtls_dhe_rsa_auth_struct;
+extern MHD_gtls_mod_auth_st MHD_gtls_dhe_dss_auth_struct;
+extern MHD_gtls_mod_auth_st srp_auth_struct;
+extern MHD_gtls_mod_auth_st psk_auth_struct;
+extern MHD_gtls_mod_auth_st dhe_psk_auth_struct;
+extern MHD_gtls_mod_auth_st srp_rsa_auth_struct;
+extern MHD_gtls_mod_auth_st srp_dss_auth_struct;
+
+typedef struct MHD_gtls_kx_algo_entry
+{
+ const char *name;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm;
+ MHD_gtls_mod_auth_st *auth_struct;
+ int needs_dh_params;
+ int needs_rsa_params;
+} MHD_gtls_kx_algo_entry_t;
+
+static const MHD_gtls_kx_algo_entry_t MHD_gtls_kx_algorithms[] = {
+ {"RSA",
+ MHD_GNUTLS_KX_RSA,
+ &MHD_gtls_rsa_auth_struct,
+ 0,
+ 0},
+ {"RSA-EXPORT",
+ MHD_GNUTLS_KX_RSA_EXPORT,
+ &MHD_rsa_export_auth_struct,
+ 0,
+ 1 /* needs RSA params */ },
+ {0,
+ 0,
+ 0,
+ 0,
+ 0}
+};
+
+/* Keep the contents of this struct the same as the previous one. */
+static const enum MHD_GNUTLS_KeyExchangeAlgorithm MHD_gtls_supported_kxs[] =
+{
+ MHD_GNUTLS_KX_RSA,
+ MHD_GNUTLS_KX_RSA_EXPORT,
+ 0
+};
+
+#define GNUTLS_KX_LOOP(b) \
+ const MHD_gtls_kx_algo_entry_t *p; \
+ for(p = MHD_gtls_kx_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_KX_ALG_LOOP(a) \
+ GNUTLS_KX_LOOP( if(p->algorithm == algorithm) { a; break; } )
+
+/* Cipher SUITES */
+#define GNUTLS_CIPHER_SUITE_ENTRY( name, block_algorithm, kx_algorithm, mac_algorithm, version ) \
+ { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, version }
+
+typedef struct
+{
+ const char *name;
+ cipher_suite_st id;
+ enum MHD_GNUTLS_CipherAlgorithm block_algorithm;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
+ enum MHD_GNUTLS_HashAlgorithm mac_algorithm;
+ enum MHD_GNUTLS_Protocol version; /* this cipher suite is supported
+ * from 'version' and above;
+ */
+} MHD_gtls_cipher_suite_entry;
+
+/* RSA with NULL cipher and MD5 MAC
+ * for test purposes.
+ */
+#define GNUTLS_RSA_NULL_MD5 { 0x00, 0x01 }
+
+/* PSK (not in TLS 1.0)
+ * draft-ietf-tls-psk:
+ */
+#define GNUTLS_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8A }
+#define GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8B }
+#define GNUTLS_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x8C }
+#define GNUTLS_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x8D }
+
+#define GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8E }
+#define GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8F }
+#define GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x90 }
+#define GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x91 }
+
+/* SRP (rfc5054)
+ */
+#define GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1A }
+#define GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1B }
+#define GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1 { 0xC0, 0x1C }
+
+#define GNUTLS_SRP_SHA_AES_128_CBC_SHA1 { 0xC0, 0x1D }
+#define GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1 { 0xC0, 0x1E }
+#define GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1 { 0xC0, 0x1F }
+
+#define GNUTLS_SRP_SHA_AES_256_CBC_SHA1 { 0xC0, 0x20 }
+#define GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1 { 0xC0, 0x21 }
+#define GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1 { 0xC0, 0x22 }
+
+/* RSA
+ */
+#define GNUTLS_RSA_ARCFOUR_SHA1 { 0x00, 0x05 }
+#define GNUTLS_RSA_ARCFOUR_MD5 { 0x00, 0x04 }
+#define GNUTLS_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x0A }
+
+/* rfc3268:
+ */
+#define GNUTLS_RSA_AES_128_CBC_SHA1 { 0x00, 0x2F }
+#define GNUTLS_RSA_AES_256_CBC_SHA1 { 0x00, 0x35 }
+
+/* rfc4132 */
+#define GNUTLS_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x41 }
+#define GNUTLS_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x84 }
+
+/* DHE DSS
+ */
+
+#define GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1 { 0x00, 0x13 }
+
+/* draft-ietf-tls-56-bit-ciphersuites-01:
+ */
+#define GNUTLS_DHE_DSS_ARCFOUR_SHA1 { 0x00, 0x66 }
+
+/* rfc3268:
+ */
+#define GNUTLS_DHE_DSS_AES_256_CBC_SHA1 { 0x00, 0x38 }
+#define GNUTLS_DHE_DSS_AES_128_CBC_SHA1 { 0x00, 0x32 }
+
+/* rfc4132 */
+#define GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1 { 0x00,0x44 }
+#define GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1 { 0x00,0x87 }
+
+/* DHE RSA
+ */
+#define GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x16 }
+
+/* rfc3268:
+ */
+#define GNUTLS_DHE_RSA_AES_128_CBC_SHA1 { 0x00, 0x33 }
+#define GNUTLS_DHE_RSA_AES_256_CBC_SHA1 { 0x00, 0x39 }
+
+/* rfc4132 */
+#define GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x45 }
+#define GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x88 }
+
+#define CIPHER_SUITES_COUNT sizeof(MHD_gtls_cs_algorithms)/sizeof(MHD_gtls_cipher_suite_entry)-1
+
+static const MHD_gtls_cipher_suite_entry MHD_gtls_cs_algorithms[] = {
+ /* RSA */
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_MD5,
+ MHD_GNUTLS_CIPHER_NULL,
+ MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_MD5,
+ MHD_GNUTLS_PROTOCOL_SSL3),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_SHA1,
+ MHD_GNUTLS_CIPHER_ARCFOUR_128,
+ MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_SHA1,
+ MHD_GNUTLS_PROTOCOL_SSL3),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_MD5,
+ MHD_GNUTLS_CIPHER_ARCFOUR_128,
+ MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_MD5,
+ MHD_GNUTLS_PROTOCOL_SSL3),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_3DES_EDE_CBC_SHA1,
+ MHD_GNUTLS_CIPHER_3DES_CBC,
+ MHD_GNUTLS_KX_RSA, MHD_GNUTLS_MAC_SHA1,
+ MHD_GNUTLS_PROTOCOL_SSL3),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA1,
+ MHD_GNUTLS_CIPHER_AES_128_CBC, MHD_GNUTLS_KX_RSA,
+ MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA1,
+ MHD_GNUTLS_CIPHER_AES_256_CBC, MHD_GNUTLS_KX_RSA,
+ MHD_GNUTLS_MAC_SHA1, MHD_GNUTLS_PROTOCOL_SSL3),
+ {0,
+ {
+ {0,
+ 0}},
+ 0,
+ 0,
+ 0,
+ 0}
+};
+
+#define GNUTLS_CIPHER_SUITE_LOOP(b) \
+ const MHD_gtls_cipher_suite_entry *p; \
+ for(p = MHD_gtls_cs_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_CIPHER_SUITE_ALG_LOOP(a) \
+ GNUTLS_CIPHER_SUITE_LOOP( if( (p->id.suite[0] == suite->suite[0]) && (p->id.suite[1] == suite->suite[1])) { a; break; } )
+
+/* Generic Functions */
+
+int
+MHD_gtls_mac_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_HashAlgorithm algorithm)
+{ /* actually returns the priority */
+ unsigned int i;
+ for (i = 0; i < session->internals.priorities.mac.num_algorithms; i++)
+ {
+ if (session->internals.priorities.mac.priority[i] == algorithm)
+ return i;
+ }
+ return -1;
+}
+
+
+int
+MHD_gnutls_mac_is_ok (enum MHD_GNUTLS_HashAlgorithm algorithm)
+{
+ ssize_t ret = -1;
+ GNUTLS_HASH_ALG_LOOP (ret = p->id);
+ if (ret >= 0)
+ ret = 0;
+ else
+ ret = 1;
+ return ret;
+}
+
+
+/**
+ * MHD__gnutls_compression_get_name - Returns a string with the name of the specified compression algorithm
+ * @algorithm: is a Compression algorithm
+ *
+ * Returns: a pointer to a string that contains the name of the
+ * specified compression algorithm, or %NULL.
+ **/
+const char *
+MHD_gtls_compression_get_name (enum MHD_GNUTLS_CompressionMethod algorithm)
+{
+ const char *ret = NULL;
+
+ /* avoid prefix */
+ GNUTLS_COMPRESSION_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_COMP_") - 1);
+
+ return ret;
+}
+
+/**
+ * MHD_gtls_compression_get_id - Returns the gnutls id of the specified in string algorithm
+ * @algorithm: is a compression method name
+ *
+ * The names are compared in a case insensitive way.
+ *
+ * Returns: an id of the specified in a string compression method, or
+ * %GNUTLS_COMP_UNKNOWN on error.
+ *
+ **/
+enum MHD_GNUTLS_CompressionMethod
+MHD_gtls_compression_get_id (const char *name)
+{
+ enum MHD_GNUTLS_CompressionMethod ret = MHD_GNUTLS_COMP_UNKNOWN;
+
+ GNUTLS_COMPRESSION_LOOP (if
+ (strcasecmp
+ (p->name + sizeof ("GNUTLS_COMP_") - 1,
+ name) == 0) ret = p->id)
+ ;
+
+ return ret;
+}
+
+
+/* return the tls number of the specified algorithm */
+int
+MHD_gtls_compression_get_num (enum MHD_GNUTLS_CompressionMethod algorithm)
+{
+ int ret = -1;
+
+ /* avoid prefix */
+ GNUTLS_COMPRESSION_ALG_LOOP (ret = p->num);
+
+ return ret;
+}
+
+int
+MHD_gtls_compression_get_wbits (enum MHD_GNUTLS_CompressionMethod algorithm)
+{
+ int ret = -1;
+ /* avoid prefix */
+ GNUTLS_COMPRESSION_ALG_LOOP (ret = p->window_bits);
+ return ret;
+}
+
+int
+MHD_gtls_compression_get_mem_level (enum MHD_GNUTLS_CompressionMethod
+ algorithm)
+{
+ int ret = -1;
+ /* avoid prefix */
+ GNUTLS_COMPRESSION_ALG_LOOP (ret = p->mem_level);
+ return ret;
+}
+
+int
+MHD_gtls_compression_get_comp_level (enum MHD_GNUTLS_CompressionMethod
+ algorithm)
+{
+ int ret = -1;
+ /* avoid prefix */
+ GNUTLS_COMPRESSION_ALG_LOOP (ret = p->comp_level);
+ return ret;
+}
+
+/* returns the gnutls internal ID of the TLS compression
+ * method num
+ */
+enum MHD_GNUTLS_CompressionMethod
+MHD_gtls_compression_get_id_from_int (int num)
+{
+ enum MHD_GNUTLS_CompressionMethod ret = -1;
+
+ /* avoid prefix */
+ GNUTLS_COMPRESSION_ALG_LOOP_NUM (ret = p->id);
+
+ return ret;
+}
+
+int
+MHD_gtls_compression_is_ok (enum MHD_GNUTLS_CompressionMethod algorithm)
+{
+ ssize_t ret = -1;
+ GNUTLS_COMPRESSION_ALG_LOOP (ret = p->id);
+ if (ret >= 0)
+ ret = 0;
+ else
+ ret = 1;
+ return ret;
+}
+
+/* CIPHER functions */
+int
+MHD_gtls_cipher_get_block_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{
+ size_t ret = 0;
+ GNUTLS_ALG_LOOP (ret = p->blocksize);
+ return ret;
+
+}
+
+/* returns the priority */
+int
+MHD_gtls_cipher_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{
+ unsigned int i;
+ for (i = 0; i < session->internals.priorities.cipher.num_algorithms; i++)
+ {
+ if (session->internals.priorities.cipher.priority[i] == algorithm)
+ return i;
+ }
+ return -1;
+}
+
+int
+MHD_gtls_cipher_is_block (enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{
+ size_t ret = 0;
+
+ GNUTLS_ALG_LOOP (ret = p->block);
+ return ret;
+
+}
+
+/**
+ * MHD__gnutls_cipher_get_key_size - Returns the length of the cipher's key size
+ * @algorithm: is an encryption algorithm
+ *
+ * Returns: length (in bytes) of the given cipher's key size, o 0 if
+ * the given cipher is invalid.
+ **/
+size_t
+MHD__gnutls_cipher_get_key_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{ /* In bytes */
+ size_t ret = 0;
+ GNUTLS_ALG_LOOP (ret = p->keysize);
+ return ret;
+
+}
+
+int
+MHD_gtls_cipher_get_iv_size (enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{ /* In bytes */
+ size_t ret = 0;
+ GNUTLS_ALG_LOOP (ret = p->iv);
+ return ret;
+
+}
+
+int
+MHD_gtls_cipher_get_export_flag (enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{ /* In bytes */
+ size_t ret = 0;
+ GNUTLS_ALG_LOOP (ret = p->export_flag);
+ return ret;
+
+}
+
+
+int
+MHD_gtls_cipher_is_ok (enum MHD_GNUTLS_CipherAlgorithm algorithm)
+{
+ ssize_t ret = -1;
+ GNUTLS_ALG_LOOP (ret = p->id);
+ if (ret >= 0)
+ ret = 0;
+ else
+ ret = 1;
+ return ret;
+}
+
+/* Key EXCHANGE functions */
+MHD_gtls_mod_auth_st *
+MHD_gtls_kx_auth_struct (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
+{
+ MHD_gtls_mod_auth_st *ret = NULL;
+ GNUTLS_KX_ALG_LOOP (ret = p->auth_struct);
+ return ret;
+
+}
+
+int
+MHD_gtls_kx_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
+{
+ unsigned int i;
+ for (i = 0; i < session->internals.priorities.kx.num_algorithms; i++)
+ {
+ if (session->internals.priorities.kx.priority[i] == algorithm)
+ return i;
+ }
+ return -1;
+}
+
+
+int
+MHD_gtls_kx_is_ok (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
+{
+ ssize_t ret = -1;
+ GNUTLS_KX_ALG_LOOP (ret = p->algorithm);
+ if (ret >= 0)
+ ret = 0;
+ else
+ ret = 1;
+ return ret;
+}
+
+int
+MHD_gtls_kx_needs_rsa_params (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
+{
+ ssize_t ret = 0;
+ GNUTLS_KX_ALG_LOOP (ret = p->needs_rsa_params);
+ return ret;
+}
+
+int
+MHD_gtls_kx_needs_dh_params (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm)
+{
+ ssize_t ret = 0;
+ GNUTLS_KX_ALG_LOOP (ret = p->needs_dh_params);
+ return ret;
+}
+
+/* Version */
+int
+MHD_gtls_version_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_Protocol version)
+{ /* actually returns the priority */
+ unsigned int i;
+
+ if (session->internals.priorities.protocol.priority == NULL)
+ {
+ MHD_gnutls_assert ();
+ return -1;
+ }
+
+ for (i = 0; i < session->internals.priorities.protocol.num_algorithms; i++)
+ {
+ if (session->internals.priorities.protocol.priority[i] == version)
+ return i;
+ }
+ return -1;
+}
+
+
+enum MHD_GNUTLS_Protocol
+MHD_gtls_version_max (MHD_gtls_session_t session)
+{ /* returns the maximum version supported */
+ unsigned int i, max = 0x00;
+
+ if (session->internals.priorities.protocol.priority == NULL)
+ {
+ return MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN;
+ }
+ else
+ for (i = 0; i < session->internals.priorities.protocol.num_algorithms;
+ i++)
+ {
+ if (session->internals.priorities.protocol.priority[i] > max)
+ max = session->internals.priorities.protocol.priority[i];
+ }
+
+ if (max == 0x00)
+ return MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN; /* unknown version */
+
+ return max;
+}
+
+int
+MHD_gtls_version_get_minor (enum MHD_GNUTLS_Protocol version)
+{
+ int ret = -1;
+
+ GNUTLS_VERSION_ALG_LOOP (ret = p->minor);
+ return ret;
+}
+
+enum MHD_GNUTLS_Protocol
+MHD_gtls_version_get (int major, int minor)
+{
+ int ret = -1;
+
+ GNUTLS_VERSION_LOOP (if ((p->major == major) && (p->minor == minor))
+ ret = p->id)
+ ;
+ return ret;
+}
+
+int
+MHD_gtls_version_get_major (enum MHD_GNUTLS_Protocol version)
+{
+ int ret = -1;
+
+ GNUTLS_VERSION_ALG_LOOP (ret = p->major);
+ return ret;
+}
+
+/* Version Functions */
+
+int
+MHD_gtls_version_is_supported (MHD_gtls_session_t session,
+ const enum MHD_GNUTLS_Protocol version)
+{
+ int ret = 0;
+
+ GNUTLS_VERSION_ALG_LOOP (ret = p->supported);
+ if (ret == 0)
+ return 0;
+
+ if (MHD_gtls_version_priority (session, version) < 0)
+ return 0; /* disabled by the user */
+ else
+ return 1;
+}
+
+enum MHD_GNUTLS_CredentialsType
+MHD_gtls_map_kx_get_cred (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm,
+ int server)
+{
+ enum MHD_GNUTLS_CredentialsType ret = -1;
+ if (server)
+ {
+ GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret = p->server_type)
+ ;
+ }
+ else
+ {
+ GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret = p->client_type)
+ ;
+ }
+
+ return ret;
+}
+
+/* Cipher Suite's functions */
+enum MHD_GNUTLS_CipherAlgorithm
+MHD_gtls_cipher_suite_get_cipher_algo (const cipher_suite_st * suite)
+{
+ int ret = 0;
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->block_algorithm);
+ return ret;
+}
+
+enum MHD_GNUTLS_Protocol
+MHD_gtls_cipher_suite_get_version (const cipher_suite_st * suite)
+{
+ int ret = 0;
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->version);
+ return ret;
+}
+
+enum MHD_GNUTLS_KeyExchangeAlgorithm
+MHD_gtls_cipher_suite_get_kx_algo (const cipher_suite_st * suite)
+{
+ int ret = 0;
+
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->kx_algorithm);
+ return ret;
+
+}
+
+enum MHD_GNUTLS_HashAlgorithm
+MHD_gtls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
+{ /* In bytes */
+ int ret = 0;
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->mac_algorithm);
+ return ret;
+
+}
+
+const char *
+MHD_gtls_cipher_suite_get_name (cipher_suite_st * suite)
+{
+ const char *ret = NULL;
+
+ /* avoid prefix */
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_") - 1);
+
+ return ret;
+}
+
+static inline int
+MHD__gnutls_cipher_suite_is_ok (cipher_suite_st * suite)
+{
+ size_t ret;
+ const char *name = NULL;
+
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (name = p->name);
+ if (name != NULL)
+ ret = 0;
+ else
+ ret = 1;
+ return ret;
+
+}
+
+#define SWAP(x, y) memcpy(tmp,x,size); \
+ memcpy(x,y,size); \
+ memcpy(y,tmp,size);
+
+#define MAX_ELEM_SIZE 4
+static inline int
+MHD__gnutls_partition (MHD_gtls_session_t session,
+ void *_base,
+ size_t nmemb,
+ size_t size,
+ int (*compar) (MHD_gtls_session_t,
+ const void *, const void *))
+{
+ uint8_t *base = _base;
+ uint8_t tmp[MAX_ELEM_SIZE];
+ uint8_t ptmp[MAX_ELEM_SIZE];
+ unsigned int pivot;
+ unsigned int i, j;
+ unsigned int full;
+
+ i = pivot = 0;
+ j = full = (nmemb - 1) * size;
+
+ memcpy (ptmp, &base[0], size); /* set pivot item */
+
+ while (i < j)
+ {
+ while ((compar (session, &base[i], ptmp) <= 0) && (i < full))
+ {
+ i += size;
+ }
+ while ((compar (session, &base[j], ptmp) >= 0) && (j > 0))
+ j -= size;
+
+ if (i < j)
+ {
+ SWAP (&base[j], &base[i]);
+ }
+ }
+
+ if (j > pivot)
+ {
+ SWAP (&base[pivot], &base[j]);
+ pivot = j;
+ }
+ else if (i < pivot)
+ {
+ SWAP (&base[pivot], &base[i]);
+ pivot = i;
+ }
+ return pivot / size;
+}
+
+static void
+MHD__gnutls_qsort (MHD_gtls_session_t session,
+ void *_base,
+ size_t nmemb,
+ size_t size,
+ int (*compar) (MHD_gtls_session_t, const void *,
+ const void *))
+{
+ unsigned int pivot;
+ char *base = _base;
+ size_t snmemb = nmemb;
+
+ if (snmemb <= 1)
+ return;
+ pivot = MHD__gnutls_partition (session, _base, nmemb, size, compar);
+
+ MHD__gnutls_qsort (session, base, pivot < nmemb ? pivot + 1
+ : pivot, size, compar);
+ MHD__gnutls_qsort (session, &base[(pivot + 1) * size], nmemb - pivot - 1,
+ size, compar);
+}
+
+/* a compare function for KX algorithms (using priorities).
+ * For use with qsort
+ */
+static int
+MHD__gnutls_compare_algo (MHD_gtls_session_t session,
+ const void *i_A1, const void *i_A2)
+{
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kA1 =
+ MHD_gtls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A1);
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kA2 =
+ MHD_gtls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A2);
+ enum MHD_GNUTLS_CipherAlgorithm cA1 =
+ MHD_gtls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A1);
+ enum MHD_GNUTLS_CipherAlgorithm cA2 =
+ MHD_gtls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A2);
+ enum MHD_GNUTLS_HashAlgorithm mA1 =
+ MHD_gtls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A1);
+ enum MHD_GNUTLS_HashAlgorithm mA2 =
+ MHD_gtls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A2);
+
+ int p1 = (MHD_gtls_kx_priority (session, kA1) + 1) * 64;
+ int p2 = (MHD_gtls_kx_priority (session, kA2) + 1) * 64;
+ p1 += (MHD_gtls_cipher_priority (session, cA1) + 1) * 8;
+ p2 += (MHD_gtls_cipher_priority (session, cA2) + 1) * 8;
+ p1 += MHD_gtls_mac_priority (session, mA1);
+ p2 += MHD_gtls_mac_priority (session, mA2);
+
+ if (p1 > p2)
+ {
+ return 1;
+ }
+ else
+ {
+ if (p1 == p2)
+ {
+ return 0;
+ }
+ return -1;
+ }
+}
+
+int
+MHD_gtls_supported_ciphersuites_sorted (MHD_gtls_session_t session,
+ cipher_suite_st ** ciphers)
+{
+
+ int count;
+
+ count = MHD_gtls_supported_ciphersuites (session, ciphers);
+ if (count <= 0)
+ {
+ MHD_gnutls_assert ();
+ return count;
+ }
+ MHD__gnutls_qsort (session, *ciphers, count, sizeof (cipher_suite_st),
+ MHD__gnutls_compare_algo);
+
+ return count;
+}
+
+int
+MHD_gtls_supported_ciphersuites (MHD_gtls_session_t session,
+ cipher_suite_st ** _ciphers)
+{
+
+ unsigned int i, ret_count, j;
+ unsigned int count = CIPHER_SUITES_COUNT;
+ cipher_suite_st *tmp_ciphers;
+ cipher_suite_st *ciphers;
+ enum MHD_GNUTLS_Protocol version;
+
+ if (count == 0)
+ {
+ return 0;
+ }
+
+ tmp_ciphers = MHD_gnutls_alloca (count * sizeof (cipher_suite_st));
+ if (tmp_ciphers == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ ciphers = MHD_gnutls_malloc (count * sizeof (cipher_suite_st));
+ if (ciphers == NULL)
+ {
+ MHD_gnutls_afree (tmp_ciphers);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ version = MHD__gnutls_protocol_get_version (session);
+
+ for (i = 0; i < count; i++)
+ {
+ memcpy (&tmp_ciphers[i], &MHD_gtls_cs_algorithms[i].id,
+ sizeof (cipher_suite_st));
+ }
+
+ for (i = j = 0; i < count; i++)
+ {
+ /* remove private cipher suites, if requested.
+ */
+ if (tmp_ciphers[i].suite[0] == 0xFF)
+ continue;
+
+ /* remove cipher suites which do not support the
+ * protocol version used.
+ */
+ if (MHD_gtls_cipher_suite_get_version (&tmp_ciphers[i]) > version)
+ continue;
+
+ if (MHD_gtls_kx_priority (session,
+ MHD_gtls_cipher_suite_get_kx_algo
+ (&tmp_ciphers[i])) < 0)
+ continue;
+ if (MHD_gtls_mac_priority (session,
+ MHD_gtls_cipher_suite_get_mac_algo
+ (&tmp_ciphers[i])) < 0)
+ continue;
+ if (MHD_gtls_cipher_priority (session,
+ MHD_gtls_cipher_suite_get_cipher_algo
+ (&tmp_ciphers[i])) < 0)
+ continue;
+
+ memcpy (&ciphers[j], &tmp_ciphers[i], sizeof (cipher_suite_st));
+ j++;
+ }
+
+ ret_count = j;
+
+ MHD_gnutls_afree (tmp_ciphers);
+
+ /* This function can no longer return 0 cipher suites.
+ * It returns an error code instead.
+ */
+ if (ret_count == 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (ciphers);
+ return GNUTLS_E_NO_CIPHER_SUITES;
+ }
+ *_ciphers = ciphers;
+ return ret_count;
+}
+
+/* For compression */
+
+#define MIN_PRIVATE_COMP_ALGO 0xEF
+
+/* returns the TLS numbers of the compression methods we support
+ */
+#define SUPPORTED_COMPRESSION_METHODS session->internals.priorities.compression.num_algorithms
+int
+MHD_gtls_supported_compression_methods (MHD_gtls_session_t session,
+ uint8_t ** comp)
+{
+ unsigned int i, j;
+
+ *comp =
+ MHD_gnutls_malloc (sizeof (uint8_t) * SUPPORTED_COMPRESSION_METHODS);
+ if (*comp == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ for (i = j = 0; i < SUPPORTED_COMPRESSION_METHODS; i++)
+ {
+ int tmp =
+ MHD_gtls_compression_get_num (session->internals.priorities.
+ compression.priority[i]);
+
+ /* remove private compression algorithms, if requested.
+ */
+ if (tmp == -1 || (tmp >= MIN_PRIVATE_COMP_ALGO))
+ {
+ MHD_gnutls_assert ();
+ continue;
+ }
+
+ (*comp)[j] = (uint8_t) tmp;
+ j++;
+ }
+
+ if (j == 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (*comp);
+ *comp = NULL;
+ return GNUTLS_E_NO_COMPRESSION_ALGORITHMS;
+ }
+ return j;
+}
+
+static const enum MHD_GNUTLS_CertificateType
+ MHD_gtls_supported_certificate_types[] =
+{ MHD_GNUTLS_CRT_X509,
+ 0
+};
+
+
+/* returns the enum MHD_GNUTLS_PublicKeyAlgorithm which is compatible with
+ * the given enum MHD_GNUTLS_KeyExchangeAlgorithm.
+ */
+enum MHD_GNUTLS_PublicKeyAlgorithm
+MHD_gtls_map_pk_get_pk (enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm)
+{
+ enum MHD_GNUTLS_PublicKeyAlgorithm ret = -1;
+
+ GNUTLS_PK_MAP_ALG_LOOP (ret = p->pk_algorithm) return ret;
+}
+
+/* Returns the encipher type for the given key exchange algorithm.
+ * That one of CIPHER_ENCRYPT, CIPHER_SIGN, CIPHER_IGN.
+ *
+ * ex. GNUTLS_KX_RSA requires a certificate able to encrypt... so returns CIPHER_ENCRYPT.
+ */
+enum encipher_type
+MHD_gtls_kx_encipher_type (enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm)
+{
+ int ret = CIPHER_IGN;
+ GNUTLS_PK_MAP_ALG_LOOP (ret = p->encipher_type) return ret;
+
+}
+
+/* signature algorithms;
+ */
+struct MHD_gnutls_sign_entry
+{
+ const char *name;
+ const char *oid;
+ MHD_gnutls_sign_algorithm_t id;
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk;
+ enum MHD_GNUTLS_HashAlgorithm mac;
+};
+typedef struct MHD_gnutls_sign_entry MHD_gnutls_sign_entry;
+
+static const MHD_gnutls_sign_entry MHD_gtls_sign_algorithms[] = {
+ {"RSA-SHA",
+ SIG_RSA_SHA1_OID,
+ GNUTLS_SIGN_RSA_SHA1,
+ MHD_GNUTLS_PK_RSA,
+ MHD_GNUTLS_MAC_SHA1},
+ {"RSA-SHA256",
+ SIG_RSA_SHA256_OID,
+ GNUTLS_SIGN_RSA_SHA256,
+ MHD_GNUTLS_PK_RSA,
+ MHD_GNUTLS_MAC_SHA256},
+ {"RSA-MD5",
+ SIG_RSA_MD5_OID,
+ GNUTLS_SIGN_RSA_MD5,
+ MHD_GNUTLS_PK_RSA,
+ MHD_GNUTLS_MAC_MD5},
+ {"GOST R 34.10-2001",
+ SIG_GOST_R3410_2001_OID,
+ 0,
+ 0,
+ 0},
+ {"GOST R 34.10-94",
+ SIG_GOST_R3410_94_OID,
+ 0,
+ 0,
+ 0},
+ {0,
+ 0,
+ 0,
+ 0,
+ 0}
+};
+
+#define GNUTLS_SIGN_LOOP(b) \
+ do { \
+ const MHD_gnutls_sign_entry *p; \
+ for(p = MHD_gtls_sign_algorithms; p->name != NULL; p++) { b ; } \
+ } while (0)
+
+#define GNUTLS_SIGN_ALG_LOOP(a) \
+ GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
+
+/* pk algorithms;
+ */
+struct MHD_gnutls_pk_entry
+{
+ const char *name;
+ const char *oid;
+ enum MHD_GNUTLS_PublicKeyAlgorithm id;
+};
+typedef struct MHD_gnutls_pk_entry MHD_gnutls_pk_entry;
+
+static const MHD_gnutls_pk_entry MHD_gtls_pk_algorithms[] = {
+ {"RSA",
+ PK_PKIX1_RSA_OID,
+ MHD_GNUTLS_PK_RSA},
+ {"GOST R 34.10-2001",
+ PK_GOST_R3410_2001_OID,
+ 0},
+ {"GOST R 34.10-94",
+ PK_GOST_R3410_94_OID,
+ 0},
+ {0,
+ 0,
+ 0}
+};
+
+enum MHD_GNUTLS_PublicKeyAlgorithm
+MHD_gtls_x509_oid2pk_algorithm (const char *oid)
+{
+ enum MHD_GNUTLS_PublicKeyAlgorithm ret = MHD_GNUTLS_PK_UNKNOWN;
+ const MHD_gnutls_pk_entry *p;
+
+ for (p = MHD_gtls_pk_algorithms; p->name != NULL; p++)
+ if (strcmp (p->oid, oid) == 0)
+ {
+ ret = p->id;
+ break;
+ }
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.h
new file mode 100644
index 0000000000..6a4021c7b3
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_algorithms.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef ALGORITHMS_H
+#define ALGORITHMS_H
+
+#include "gnutls_auth.h"
+
+/* Functions for version handling. */
+enum MHD_GNUTLS_Protocol MHD_gtls_version_max (MHD_gtls_session_t session);
+int MHD_gtls_version_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_Protocol version);
+int MHD_gtls_version_is_supported (MHD_gtls_session_t session,
+ const enum MHD_GNUTLS_Protocol version);
+int MHD_gtls_version_get_major (enum MHD_GNUTLS_Protocol ver);
+int MHD_gtls_version_get_minor (enum MHD_GNUTLS_Protocol ver);
+enum MHD_GNUTLS_Protocol MHD_gtls_version_get (int major, int minor);
+
+/* Functions for MACs. */
+int MHD_gnutls_mac_is_ok (enum MHD_GNUTLS_HashAlgorithm algorithm);
+/* Functions for cipher suites. */
+int MHD_gtls_supported_ciphersuites (MHD_gtls_session_t session,
+ cipher_suite_st ** ciphers);
+int MHD_gtls_supported_ciphersuites_sorted (MHD_gtls_session_t session,
+ cipher_suite_st ** ciphers);
+int MHD_gtls_supported_compression_methods (MHD_gtls_session_t session,
+ uint8_t ** comp);
+const char *MHD_gtls_cipher_suite_get_name (cipher_suite_st * algorithm);
+enum MHD_GNUTLS_CipherAlgorithm MHD_gtls_cipher_suite_get_cipher_algo (const
+ cipher_suite_st
+ *
+ algorithm);
+enum MHD_GNUTLS_KeyExchangeAlgorithm MHD_gtls_cipher_suite_get_kx_algo (const
+ cipher_suite_st
+ *
+ algorithm);
+enum MHD_GNUTLS_HashAlgorithm MHD_gtls_cipher_suite_get_mac_algo (const
+ cipher_suite_st
+ *
+ algorithm);
+enum MHD_GNUTLS_Protocol MHD_gtls_cipher_suite_get_version (const
+ cipher_suite_st *
+ algorithm);
+cipher_suite_st MHD_gtls_cipher_suite_get_suite_name (cipher_suite_st *
+ algorithm);
+
+/* Functions for ciphers. */
+int MHD_gtls_cipher_get_block_size (enum MHD_GNUTLS_CipherAlgorithm
+ algorithm);
+int MHD_gtls_cipher_is_block (enum MHD_GNUTLS_CipherAlgorithm algorithm);
+int MHD_gtls_cipher_is_ok (enum MHD_GNUTLS_CipherAlgorithm algorithm);
+int MHD_gtls_cipher_get_iv_size (enum MHD_GNUTLS_CipherAlgorithm algorithm);
+int MHD_gtls_cipher_get_export_flag (enum MHD_GNUTLS_CipherAlgorithm
+ algorithm);
+
+/* Functions for key exchange. */
+int MHD_gtls_kx_needs_dh_params (enum MHD_GNUTLS_KeyExchangeAlgorithm
+ algorithm);
+int MHD_gtls_kx_needs_rsa_params (enum MHD_GNUTLS_KeyExchangeAlgorithm
+ algorithm);
+MHD_gtls_mod_auth_st *MHD_gtls_kx_auth_struct (enum
+ MHD_GNUTLS_KeyExchangeAlgorithm
+ algorithm);
+int MHD_gtls_kx_is_ok (enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm);
+
+/* Functions for compression. */
+int MHD_gtls_compression_is_ok (enum MHD_GNUTLS_CompressionMethod algorithm);
+int MHD_gtls_compression_get_num (enum MHD_GNUTLS_CompressionMethod
+ algorithm);
+enum MHD_GNUTLS_CompressionMethod MHD_gtls_compression_get_id_from_int (int
+ num);
+int MHD_gtls_compression_get_mem_level (enum MHD_GNUTLS_CompressionMethod
+ algorithm);
+int MHD_gtls_compression_get_comp_level (enum MHD_GNUTLS_CompressionMethod
+ algorithm);
+int MHD_gtls_compression_get_wbits (enum MHD_GNUTLS_CompressionMethod
+ algorithm);
+
+/* Type to KX mappings. */
+enum MHD_GNUTLS_CredentialsType MHD_gtls_map_kx_get_cred (enum
+ MHD_GNUTLS_KeyExchangeAlgorithm
+ algorithm,
+ int server);
+
+/* KX to PK mapping. */
+enum MHD_GNUTLS_PublicKeyAlgorithm MHD_gtls_map_pk_get_pk (enum
+ MHD_GNUTLS_KeyExchangeAlgorithm
+ kx_algorithm);
+enum MHD_GNUTLS_PublicKeyAlgorithm MHD_gtls_x509_oid2pk_algorithm (const char
+ *oid);
+enum encipher_type
+{ CIPHER_ENCRYPT = 0, CIPHER_SIGN = 1, CIPHER_IGN };
+
+enum encipher_type MHD_gtls_kx_encipher_type (enum
+ MHD_GNUTLS_KeyExchangeAlgorithm
+ algorithm);
+
+struct MHD_gtls_compression_entry
+{
+ const char *name;
+ enum MHD_GNUTLS_CompressionMethod id;
+ int num; /* the number reserved in TLS for the specific compression method */
+
+ /* used in zlib compressor */
+ int window_bits;
+ int mem_level;
+ int comp_level;
+};
+typedef struct MHD_gtls_compression_entry MHD_gnutls_compression_entry;
+
+/* Functions for sign algorithms. */
+
+int MHD_gtls_mac_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_HashAlgorithm algorithm);
+int MHD_gtls_cipher_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CipherAlgorithm algorithm);
+int MHD_gtls_kx_priority (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algorithm);
+
+enum MHD_GNUTLS_HashAlgorithm MHD_gtls_mac_get_id (const char *name);
+enum MHD_GNUTLS_CipherAlgorithm MHD_gtls_cipher_get_id (const char *name);
+enum MHD_GNUTLS_KeyExchangeAlgorithm MHD_gtls_kx_get_id (const char *name);
+enum MHD_GNUTLS_Protocol MHD_gtls_protocol_get_id (const char *name);
+enum MHD_GNUTLS_CertificateType MHD_gtls_certificate_type_get_id (const char
+ *name);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_asn1_tab.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_asn1_tab.c
new file mode 100644
index 0000000000..9b51152124
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_asn1_tab.c
@@ -0,0 +1,63 @@
+#if HAVE_CONFIG_H
+#include "MHD_config.h"
+#endif
+
+#include <libtasn1.h>
+
+const ASN1_ARRAY_TYPE MHD_gnutlsMHD__asn1_tab[] = {
+ {"GNUTLS", 536872976, 0},
+ {0, 1073741836, 0},
+ {"RSAPublicKey", 1610612741, 0},
+ {"modulus", 1073741827, 0},
+ {"publicExponent", 3, 0},
+ {"RSAPrivateKey", 1610612741, 0},
+ {"version", 1073741826, "Version"},
+ {"modulus", 1073741827, 0},
+ {"publicExponent", 1073741827, 0},
+ {"privateExponent", 1073741827, 0},
+ {"prime1", 1073741827, 0},
+ {"prime2", 1073741827, 0},
+ {"exponent1", 1073741827, 0},
+ {"exponent2", 1073741827, 0},
+ {"coefficient", 1073741827, 0},
+ {"otherPrimeInfos", 16386, "OtherPrimeInfos"},
+ {"Version", 1610874883, 0},
+ {"two-prime", 1073741825, "0"},
+ {"multi", 1, "1"},
+ {"OtherPrimeInfos", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "OtherPrimeInfo"},
+ {"OtherPrimeInfo", 1610612741, 0},
+ {"prime", 1073741827, 0},
+ {"exponent", 1073741827, 0},
+ {"coefficient", 3, 0},
+ {"AlgorithmIdentifier", 1610612741, 0},
+ {"algorithm", 1073741836, 0},
+ {"parameters", 541081613, 0},
+ {"algorithm", 1, 0},
+ {"DigestInfo", 1610612741, 0},
+ {"digestAlgorithm", 1073741826, "DigestAlgorithmIdentifier"},
+ {"digest", 2, "Digest"},
+ {"DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
+ {"Digest", 1073741831, 0},
+ {"DSAPublicKey", 1073741827, 0},
+ {"DSAParameters", 1610612741, 0},
+ {"p", 1073741827, 0},
+ {"q", 1073741827, 0},
+ {"g", 3, 0},
+ {"DSASignatureValue", 1610612741, 0},
+ {"r", 1073741827, 0},
+ {"s", 3, 0},
+ {"DSAPrivateKey", 1610612741, 0},
+ {"version", 1073741827, 0},
+ {"p", 1073741827, 0},
+ {"q", 1073741827, 0},
+ {"g", 1073741827, 0},
+ {"Y", 1073741827, 0},
+ {"priv", 3, 0},
+ {"DHParameter", 536870917, 0},
+ {"prime", 1073741827, 0},
+ {"base", 1073741827, 0},
+ {"privateValueLength", 16387, 0},
+ {0, 0, 0}
+};
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.c
new file mode 100644
index 0000000000..7c820c4e66
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_auth.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_algorithms.h"
+#include "auth_cert.h"
+#include <gnutls_datum.h>
+
+/* The functions here are used in order for authentication algorithms
+ * to be able to retrieve the needed credentials eg public and private
+ * key etc.
+ */
+
+/**
+ * MHD__gnutls_credentials_clear - Clears all the credentials previously set
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * Clears all the credentials previously set in this session.
+ *
+ **/
+void
+MHD__gnutls_credentials_clear (MHD_gtls_session_t session)
+{
+ if (session->key && session->key->cred)
+ { /* beginning of the list */
+ auth_cred_st *ccred, *ncred;
+ ccred = session->key->cred;
+ while (ccred != NULL)
+ {
+ ncred = ccred->next;
+ MHD_gnutls_free (ccred);
+ ccred = ncred;
+ }
+ session->key->cred = NULL;
+ }
+}
+
+/*
+ * This creates a linked list of the form:
+ * { algorithm, credentials, pointer to next }
+ */
+/**
+ * MHD__gnutls_credentials_set - Sets the needed credentials for the specified authentication algorithm.
+ * @session: is a #MHD_gtls_session_t structure.
+ * @type: is the type of the credentials
+ * @cred: is a pointer to a structure.
+ *
+ * Sets the needed credentials for the specified type.
+ * Eg username, password - or public and private keys etc.
+ * The (void* cred) parameter is a structure that depends on the
+ * specified type and on the current session (client or server).
+ * [ In order to minimize memory usage, and share credentials between
+ * several threads gnutls keeps a pointer to cred, and not the whole cred
+ * structure. Thus you will have to keep the structure allocated until
+ * you call MHD__gnutls_deinit(). ]
+ *
+ * For GNUTLS_CRD_SRP cred should be MHD_gnutls_srp_client_credentials_t
+ * in case of a client, and MHD_gnutls_srp_server_credentials_t, in case
+ * of a server.
+ *
+ * For GNUTLS_CRD_CERTIFICATE cred should be MHD_gtls_cert_credentials_t.
+ *
+ **/
+int
+MHD__gnutls_credentials_set (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CredentialsType type, void *cred)
+{
+ auth_cred_st *ccred = NULL, *pcred = NULL;
+ int exists = 0;
+
+ if (session->key->cred == NULL)
+ { /* beginning of the list */
+
+ session->key->cred = MHD_gnutls_malloc (sizeof (auth_cred_st));
+ if (session->key->cred == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ /* copy credentials locally */
+ session->key->cred->credentials = cred;
+
+ session->key->cred->next = NULL;
+ session->key->cred->algorithm = type;
+ }
+ else
+ {
+ ccred = session->key->cred;
+ while (ccred != NULL)
+ {
+ if (ccred->algorithm == type)
+ {
+ exists = 1;
+ break;
+ }
+ pcred = ccred;
+ ccred = ccred->next;
+ }
+ /* After this, pcred is not null.
+ */
+
+ if (exists == 0)
+ { /* new entry */
+ pcred->next = MHD_gnutls_malloc (sizeof (auth_cred_st));
+ if (pcred->next == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ ccred = pcred->next;
+
+ /* copy credentials locally */
+ ccred->credentials = cred;
+
+ ccred->next = NULL;
+ ccred->algorithm = type;
+ }
+ else
+ { /* modify existing entry */
+ MHD_gnutls_free (ccred->credentials);
+ ccred->credentials = cred;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * MHD_gtls_auth_get_type - Returns the type of credentials for the current authentication schema.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * Returns type of credentials for the current authentication schema.
+ * The returned information is to be used to distinguish the function used
+ * to access authentication data.
+ *
+ * Eg. for CERTIFICATE ciphersuites (key exchange algorithms: KX_RSA, KX_DHE_RSA),
+ * the same function are to be used to access the authentication data.
+ **/
+enum MHD_GNUTLS_CredentialsType
+MHD_gtls_auth_get_type (MHD_gtls_session_t session)
+{
+/* This is not the credentials we must set, but the authentication data
+ * we get by the peer, so it should be reversed.
+ */
+ int server = session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;
+
+ return
+ MHD_gtls_map_kx_get_cred (MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.
+ current_cipher_suite), server);
+}
+
+/*
+ * This returns a pointer to the linked list. Don't
+ * free that!!!
+ */
+const void *
+MHD_gtls_get_kx_cred (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algo, int *err)
+{
+ int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
+
+ return MHD_gtls_get_cred (session->key,
+ MHD_gtls_map_kx_get_cred (algo, server), err);
+}
+
+const void *
+MHD_gtls_get_cred (MHD_gtls_key_st key, enum MHD_GNUTLS_CredentialsType type,
+ int *err)
+{
+ const void *retval = NULL;
+ int _err = -1;
+ auth_cred_st *ccred;
+
+ if (key == NULL)
+ goto out;
+
+ ccred = key->cred;
+ while (ccred != NULL)
+ {
+ if (ccred->algorithm == type)
+ {
+ break;
+ }
+ ccred = ccred->next;
+ }
+ if (ccred == NULL)
+ goto out;
+
+ _err = 0;
+ retval = ccred->credentials;
+
+out:
+ if (err != NULL)
+ *err = _err;
+ return retval;
+}
+
+/*-
+ * MHD_gtls_get_auth_info - Returns a pointer to authentication information.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function must be called after a succesful MHD__gnutls_handshake().
+ * Returns a pointer to authentication information. That information
+ * is data obtained by the handshake protocol, the key exchange algorithm,
+ * and the TLS extensions messages.
+ *
+ * In case of GNUTLS_CRD_CERTIFICATE returns a type of &cert_auth_info_t;
+ * In case of GNUTLS_CRD_SRP returns a type of &srp_(server/client)_auth_info_t;
+ -*/
+void *
+MHD_gtls_get_auth_info (MHD_gtls_session_t session)
+{
+ return session->key->auth_info;
+}
+
+/*-
+ * MHD_gtls_free_auth_info - Frees the auth info structure
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function frees the auth info structure and sets it to
+ * null. It must be called since some structures contain malloced
+ * elements.
+ -*/
+void
+MHD_gtls_free_auth_info (MHD_gtls_session_t session)
+{
+ MHD_gtls_dh_info_st *dh_info;
+ rsa_info_st *rsa_info;
+
+ if (session == NULL || session->key == NULL)
+ {
+ MHD_gnutls_assert ();
+ return;
+ }
+
+ switch (session->key->auth_info_type)
+ {
+ case MHD_GNUTLS_CRD_CERTIFICATE:
+ {
+ unsigned int i;
+ cert_auth_info_t info = MHD_gtls_get_auth_info (session);
+
+ if (info == NULL)
+ break;
+
+ dh_info = &info->dh;
+ rsa_info = &info->rsa_export;
+ for (i = 0; i < info->ncerts; i++)
+ {
+ MHD__gnutls_free_datum (&info->raw_certificate_list[i]);
+ }
+
+ MHD_gnutls_free (info->raw_certificate_list);
+ info->raw_certificate_list = NULL;
+ info->ncerts = 0;
+
+ MHD_gtls_free_dh_info (dh_info);
+ MHD_gtls_free_rsa_info (rsa_info);
+ }
+
+
+ break;
+ default:
+ return;
+
+ }
+
+ MHD_gnutls_free (session->key->auth_info);
+ session->key->auth_info = NULL;
+ session->key->auth_info_size = 0;
+ session->key->auth_info_type = 0;
+
+}
+
+/* This function will set the auth info structure in the key
+ * structure.
+ * If allow change is !=0 then this will allow changing the auth
+ * info structure to a different type.
+ */
+int
+MHD_gtls_auth_info_set (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CredentialsType type, int size,
+ int allow_change)
+{
+ if (session->key->auth_info == NULL)
+ {
+ session->key->auth_info = MHD_gnutls_calloc (1, size);
+ if (session->key->auth_info == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ session->key->auth_info_type = type;
+ session->key->auth_info_size = size;
+ }
+ else
+ {
+ if (allow_change == 0)
+ {
+ /* If the credentials for the current authentication scheme,
+ * are not the one we want to set, then it's an error.
+ * This may happen if a rehandshake is performed an the
+ * ciphersuite which is negotiated has different authentication
+ * schema.
+ */
+ if (MHD_gtls_auth_get_type (session) !=
+ session->key->auth_info_type)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+ }
+ else
+ {
+ /* The new behaviour: Here we reallocate the auth info structure
+ * in order to be able to negotiate different authentication
+ * types. Ie. perform an auth_anon and then authenticate again using a
+ * certificate (in order to prevent revealing the certificate's contents,
+ * to passive eavesdropers.
+ */
+ if (MHD_gtls_auth_get_type (session) !=
+ session->key->auth_info_type)
+ {
+
+ MHD_gtls_free_auth_info (session);
+
+ session->key->auth_info = calloc (1, size);
+ if (session->key->auth_info == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ session->key->auth_info_type = type;
+ session->key->auth_info_size = size;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.h
new file mode 100644
index 0000000000..4956268cc8
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_AUTH_H
+#define GNUTLS_AUTH_H
+
+typedef struct MHD_gtls_mod_auth_st_int
+{
+ const char *name; /* null terminated */
+ int (*MHD_gtls_gen_server_certificate) (MHD_gtls_session_t, opaque **);
+ int (*MHD_gtls_gen_client_certificate) (MHD_gtls_session_t, opaque **);
+ int (*MHD_gtls_gen_server_kx) (MHD_gtls_session_t, opaque **);
+ int (*MHD_gtls_gen_client_kx) (MHD_gtls_session_t, opaque **); /* used in SRP */
+ int (*MHD_gtls_gen_client_cert_vrfy) (MHD_gtls_session_t, opaque **);
+ int (*MHD_gtls_gen_server_certificate_request) (MHD_gtls_session_t,
+ opaque **);
+
+ int (*MHD_gtls_process_server_certificate) (MHD_gtls_session_t, opaque *,
+ size_t);
+ int (*MHD_gtls_process_client_certificate) (MHD_gtls_session_t, opaque *,
+ size_t);
+ int (*MHD_gtls_process_server_kx) (MHD_gtls_session_t, opaque *, size_t);
+ int (*MHD_gtls_process_client_kx) (MHD_gtls_session_t, opaque *, size_t);
+ int (*MHD_gtls_process_client_cert_vrfy) (MHD_gtls_session_t, opaque *,
+ size_t);
+ int (*MHD_gtls_process_server_certificate_request) (MHD_gtls_session_t,
+ opaque *, size_t);
+} MHD_gtls_mod_auth_st;
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth_int.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth_int.h
new file mode 100644
index 0000000000..425dc8a318
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_auth_int.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+const void *MHD_gtls_get_cred (MHD_gtls_key_st key,
+ enum MHD_GNUTLS_CredentialsType kx, int *err);
+const void *MHD_gtls_get_kx_cred (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algo,
+ int *err);
+void *MHD_gtls_get_auth_info (MHD_gtls_session_t session);
+int MHD_gtls_auth_info_set (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CredentialsType type, int size,
+ int allow_change);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.c
new file mode 100644
index 0000000000..c687cb2313
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.c
@@ -0,0 +1,1111 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This is the only file that uses the berkeley sockets API.
+ *
+ * Also holds all the buffering code used in gnutls.
+ * The buffering code works as:
+ *
+ * RECORD LAYER:
+ * 1. uses a buffer to hold data (application/handshake),
+ * we got but they were not requested, yet.
+ * (see MHD_gnutls_record_buffer_put(), MHD_gnutls_record_buffer_get_size() etc.)
+ *
+ * 2. uses a buffer to hold data that were incomplete (ie the read/write
+ * was interrupted)
+ * (see MHD_gtls_io_read_buffered(), MHD_gtls_io_write_buffered() etc.)
+ *
+ * HANDSHAKE LAYER:
+ * 1. Uses a buffer to hold data that was not sent or received
+ * complete. (E.g. sent 10 bytes of a handshake packet that is 20 bytes
+ * long).
+ * (see MHD__gnutls_handshake_send_int(), MHD__gnutls_handshake_recv_int())
+ *
+ * 2. Uses buffer to hold the last received handshake message.
+ * (see MHD_gtls_handshake_buffer_put() etc.)
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+#include <gnutls_record.h>
+#include <gnutls_buffers.h>
+
+#include <errno.h>
+
+#ifdef _WIN32
+# include <winsock2.h>
+#endif
+
+#ifndef EAGAIN
+# define EAGAIN EWOULDBLOCK
+#endif
+
+/* Buffers received packets of type APPLICATION DATA and
+ * HANDSHAKE DATA.
+ */
+int
+MHD_gnutls_record_buffer_put (content_type_t type,
+ MHD_gtls_session_t session, opaque * data,
+ size_t length)
+{
+ MHD_gtls_buffer *buf;
+
+ if (length == 0)
+ return 0;
+
+ switch (type)
+ {
+ case GNUTLS_APPLICATION_DATA:
+ buf = &session->internals.application_data_buffer;
+ MHD__gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n",
+ length, type);
+ break;
+
+ case GNUTLS_HANDSHAKE:
+ buf = &session->internals.handshake_data_buffer;
+ MHD__gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data(%d)\n",
+ length, type);
+ break;
+
+ case GNUTLS_INNER_APPLICATION:
+ buf = &session->internals.ia_data_buffer;
+ MHD__gnutls_buffers_log ("BUF[IA]: Inserted %d bytes of Data(%d)\n",
+ length, type);
+ break;
+
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (MHD_gtls_buffer_append (buf, data, length) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+}
+
+int
+MHD_gnutls_record_buffer_get_size (content_type_t type,
+ MHD_gtls_session_t session)
+{
+ switch (type)
+ {
+ case GNUTLS_APPLICATION_DATA:
+ return session->internals.application_data_buffer.length;
+
+ case GNUTLS_HANDSHAKE:
+ return session->internals.handshake_data_buffer.length;
+
+ case GNUTLS_INNER_APPLICATION:
+ return session->internals.ia_data_buffer.length;
+
+ default:
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+}
+
+int
+MHD_gtls_record_buffer_get (content_type_t type, MHD_gtls_session_t session,
+ opaque * data, size_t length)
+{
+ if (length == 0 || data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ switch (type)
+ {
+ case GNUTLS_APPLICATION_DATA:
+
+ if (length > session->internals.application_data_buffer.length)
+ {
+ length = session->internals.application_data_buffer.length;
+ }
+
+ MHD__gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n",
+ length, type);
+
+ session->internals.application_data_buffer.length -= length;
+ memcpy (data, session->internals.application_data_buffer.data, length);
+
+ /* overwrite buffer */
+ memmove (session->internals.application_data_buffer.data,
+ &session->internals.application_data_buffer.data[length],
+ session->internals.application_data_buffer.length);
+
+ /* we do no longer realloc the application_data_buffer.data,
+ * since it serves no practical reason. It also decreases
+ * performance.
+ */
+ break;
+
+ case GNUTLS_HANDSHAKE:
+ if (length > session->internals.handshake_data_buffer.length)
+ {
+ length = session->internals.handshake_data_buffer.length;
+ }
+
+ MHD__gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n",
+ length, type);
+
+ session->internals.handshake_data_buffer.length -= length;
+ memcpy (data, session->internals.handshake_data_buffer.data, length);
+
+ /* overwrite buffer */
+ memmove (session->internals.handshake_data_buffer.data,
+ &session->internals.handshake_data_buffer.data[length],
+ session->internals.handshake_data_buffer.length);
+
+ break;
+
+ case GNUTLS_INNER_APPLICATION:
+ if (length > session->internals.ia_data_buffer.length)
+ length = session->internals.ia_data_buffer.length;
+
+ MHD__gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n",
+ length, type);
+
+ session->internals.ia_data_buffer.length -= length;
+ memcpy (data, session->internals.ia_data_buffer.data, length);
+
+ /* overwrite buffer */
+ memmove (session->internals.ia_data_buffer.data,
+ &session->internals.ia_data_buffer.data[length],
+ session->internals.ia_data_buffer.length);
+
+ break;
+
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return length;
+}
+
+/* This function is like read. But it does not return -1 on error.
+ * It does return MHD_gnutls_errno instead.
+ *
+ * Flags are only used if the default recv() function is being used.
+ */
+static ssize_t
+MHD__gnutls_read (MHD_gtls_session_t session, void *iptr,
+ size_t sizeOfPtr, int flags)
+{
+ size_t left;
+ ssize_t i = 0;
+ char *ptr = iptr;
+ MHD_gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
+
+ session->internals.direction = 0;
+
+ left = sizeOfPtr;
+ while (left > 0)
+ {
+ session->internals.errnum = 0;
+ if (session->internals.MHD__gnutls_pull_func == NULL)
+ {
+ i =
+ recv (GNUTLS_POINTER_TO_INT (fd), &ptr[sizeOfPtr - left], left,
+ flags);
+#if HAVE_WINSOCK
+ if (i < 0)
+ {
+ int tmperr = WSAGetLastError ();
+ switch (tmperr)
+ {
+ case WSAEWOULDBLOCK:
+ session->internals.errnum = EAGAIN;
+ break;
+
+ case WSAEINTR:
+ session->internals.errnum = EINTR;
+ break;
+
+ default:
+ session->internals.errnum = EIO;
+ break;
+ }
+ WSASetLastError (tmperr);
+ }
+#endif
+ }
+ else
+ i = session->internals.MHD__gnutls_pull_func (fd,
+ &ptr[sizeOfPtr - left],
+ left);
+ if (i < 0)
+ {
+ int err = session->internals.errnum ? session->internals.errnum
+ : errno;
+ if ( (err == EAGAIN) || (err == EINTR) )
+ {
+ if (sizeOfPtr - left > 0)
+ goto finish;
+ MHD_gnutls_assert ();
+ if (err == EAGAIN)
+ return GNUTLS_E_AGAIN;
+ return GNUTLS_E_INTERRUPTED;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PULL_ERROR;
+ }
+ }
+ else
+ {
+ if (i == 0)
+ break; /* EOF */
+ }
+ left -= i;
+ }
+
+finish:
+ return (sizeOfPtr - left);
+}
+
+#define RCVLOWAT session->internals.lowat
+
+/* This function is only used with berkeley style sockets.
+ * Clears the peeked data (read with MSG_PEEK).
+ */
+int
+MHD_gtls_io_clear_peeked_data (MHD_gtls_session_t session)
+{
+ char *peekdata;
+ int ret, sum;
+
+ if (session->internals.have_peeked_data == 0 || RCVLOWAT == 0)
+ return 0;
+
+ peekdata = MHD_gnutls_alloca (RCVLOWAT);
+ if (peekdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* this was already read by using MSG_PEEK - so it shouldn't fail */
+ sum = 0;
+ do
+ { /* we need this to finish now */
+ ret = MHD__gnutls_read (session, peekdata, RCVLOWAT - sum, 0);
+ if (ret > 0)
+ sum += ret;
+ }
+ while ( (ret == GNUTLS_E_INTERRUPTED) ||
+ (ret == GNUTLS_E_AGAIN) ||
+ (sum < RCVLOWAT) );
+
+ MHD_gnutls_afree (peekdata);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ session->internals.have_peeked_data = 0;
+
+ return 0;
+}
+
+void
+MHD_gtls_io_clear_read_buffer (MHD_gtls_session_t session)
+{
+ session->internals.record_recv_buffer.length = 0;
+}
+
+/* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
+ * It does return MHD_gnutls_errno instead.
+ * This function reads data from the socket and keeps them in a buffer, of up to
+ * MAX_RECV_SIZE.
+ *
+ * This is not a general purpose function. It returns EXACTLY the data requested,
+ * which are stored in a local (in the session) buffer. A pointer (iptr) to this buffer is returned.
+ *
+ */
+ssize_t
+MHD_gtls_io_read_buffered (MHD_gtls_session_t session, opaque ** iptr,
+ size_t sizeOfPtr, content_type_t recv_type)
+{
+ ssize_t ret = 0, ret2 = 0;
+ size_t min;
+ int buf_pos;
+ opaque *buf;
+ int recvlowat;
+ int recvdata, alloc_size;
+
+ *iptr = session->internals.record_recv_buffer.data;
+
+ if (sizeOfPtr > MAX_RECV_SIZE || sizeOfPtr == 0)
+ {
+ MHD_gnutls_assert (); /* internal error */
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* If an external pull function is used, then do not leave
+ * any data into the kernel buffer.
+ */
+ if (session->internals.MHD__gnutls_pull_func != NULL)
+ {
+ recvlowat = 0;
+ }
+ else
+ {
+ /* leave peeked data to the kernel space only if application data
+ * is received and we don't have any peeked
+ * data in gnutls session.
+ */
+ if (recv_type != GNUTLS_APPLICATION_DATA
+ && session->internals.have_peeked_data == 0)
+ recvlowat = 0;
+ else
+ recvlowat = RCVLOWAT;
+ }
+
+ /* calculate the actual size, ie. get the minimum of the
+ * buffered data and the requested data.
+ */
+ min = MIN (session->internals.record_recv_buffer.length, sizeOfPtr);
+ if (min > 0)
+ {
+ /* if we have enough buffered data
+ * then just return them.
+ */
+ if (min == sizeOfPtr)
+ {
+ return min;
+ }
+ }
+
+ /* min is over zero. recvdata is the data we must
+ * receive in order to return the requested data.
+ */
+ recvdata = sizeOfPtr - min;
+
+ /* Check if the previously read data plus the new data to
+ * receive are longer than the maximum receive buffer size.
+ */
+ if ((session->internals.record_recv_buffer.length + recvdata)
+ > MAX_RECV_SIZE)
+ {
+ MHD_gnutls_assert (); /* internal error */
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Allocate the data required to store the new packet.
+ */
+ alloc_size = recvdata + session->internals.record_recv_buffer.length;
+ session->internals.record_recv_buffer.data =
+ MHD_gtls_realloc_fast (session->internals.record_recv_buffer.data,
+ alloc_size);
+ if (session->internals.record_recv_buffer.data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ buf_pos = session->internals.record_recv_buffer.length;
+ buf = session->internals.record_recv_buffer.data;
+ *iptr = buf;
+
+ /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer. */
+ if (recvdata - recvlowat > 0)
+ {
+ ret =
+ MHD__gnutls_read (session, &buf[buf_pos], recvdata - recvlowat, 0);
+
+ /* return immediately if we got an interrupt or eagain
+ * error.
+ */
+ if (ret < 0 && MHD_gtls_error_is_fatal (ret) == 0)
+ {
+ return ret;
+ }
+ }
+
+ /* copy fresh data to our buffer.
+ */
+ if (ret > 0)
+ {
+ MHD__gnutls_read_log
+ ("RB: Have %d bytes into buffer. Adding %d bytes.\n",
+ session->internals.record_recv_buffer.length, ret);
+ MHD__gnutls_read_log ("RB: Requested %d bytes\n", sizeOfPtr);
+ session->internals.record_recv_buffer.length += ret;
+ }
+
+ buf_pos = session->internals.record_recv_buffer.length;
+
+ /* This is a hack placed in order for select to work. Just leave recvlowat data,
+ * into the kernel buffer (using a read with MSG_PEEK), thus making
+ * select think, that the socket is ready for reading.
+ * MSG_PEEK is only used with berkeley style sockets.
+ */
+ if (ret == (recvdata - recvlowat) && recvlowat > 0)
+ {
+ ret2 = MHD__gnutls_read (session, &buf[buf_pos], recvlowat, MSG_PEEK);
+
+ if (ret2 < 0 && MHD_gtls_error_is_fatal (ret2) == 0)
+ {
+ return ret2;
+ }
+
+ if (ret2 > 0)
+ {
+ MHD__gnutls_read_log ("RB-PEEK: Read %d bytes in PEEK MODE.\n",
+ ret2);
+ MHD__gnutls_read_log
+ ("RB-PEEK: Have %d bytes into buffer. Adding %d bytes.\nRB: Requested %d bytes\n",
+ session->internals.record_recv_buffer.length, ret2, sizeOfPtr);
+ session->internals.have_peeked_data = 1;
+ session->internals.record_recv_buffer.length += ret2;
+
+ }
+ }
+
+ if (ret < 0 || ret2 < 0)
+ {
+ MHD_gnutls_assert ();
+ /* that's because they are initialized to 0 */
+ return MIN (ret, ret2);
+ }
+
+ ret += ret2;
+
+ if (ret > 0 && ret < recvlowat)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_AGAIN;
+ }
+
+ if (ret == 0)
+ { /* EOF */
+ MHD_gnutls_assert ();
+ return 0;
+ }
+
+ ret = session->internals.record_recv_buffer.length;
+
+ if ((ret > 0) && ((size_t) ret < sizeOfPtr))
+ {
+ /* Short Read */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_AGAIN;
+ }
+ else
+ {
+ return ret;
+ }
+}
+
+/* These two functions are used to insert data to the send buffer of the handshake or
+ * record protocol. The send buffer is kept if a send is interrupted and we need to keep
+ * the data left to sent, in order to send them later.
+ */
+
+#define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y))
+
+inline static int
+MHD__gnutls_buffer_insert (MHD_gtls_buffer * buffer,
+ const opaque * _data, size_t data_size)
+{
+
+ if ((MEMSUB (_data, buffer->data) >= 0)
+ && (MEMSUB (_data, buffer->data) < (ssize_t) buffer->length))
+ {
+ /* the given _data is part of the buffer.
+ */
+ if (data_size > buffer->length)
+ {
+ MHD_gnutls_assert ();
+ /* this shouldn't have happened */
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (_data == buffer->data)
+ { /* then don't even memmove */
+ buffer->length = data_size;
+ return 0;
+ }
+
+ memmove (buffer->data, _data, data_size);
+ buffer->length = data_size;
+
+ return 0;
+
+ }
+
+ if (MHD_gtls_buffer_append (buffer, _data, data_size) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+}
+
+inline static int
+MHD__gnutls_buffer_get (MHD_gtls_buffer * buffer,
+ const opaque ** ptr, size_t * ptr_size)
+{
+ *ptr_size = buffer->length;
+ *ptr = buffer->data;
+
+ return 0;
+}
+
+/* This function is like write. But it does not return -1 on error.
+ * It does return MHD_gnutls_errno instead.
+ *
+ * In case of E_AGAIN and E_INTERRUPTED errors, you must call MHD_gnutls_write_flush(),
+ * until it returns ok (0).
+ *
+ * We need to push exactly the data in n, since we cannot send less
+ * data. In TLS the peer must receive the whole packet in order
+ * to decrypt and verify the integrity.
+ *
+ */
+ssize_t
+MHD_gtls_io_write_buffered (MHD_gtls_session_t session,
+ const void *iptr, size_t n)
+{
+ size_t left;
+ unsigned j, x, sum = 0;
+ ssize_t retval, i;
+ const opaque *ptr;
+ int ret;
+ MHD_gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
+
+ /* to know where the procedure was interrupted.
+ */
+ session->internals.direction = 1;
+
+ ptr = iptr;
+
+ /* In case the previous write was interrupted, check if the
+ * iptr != NULL and we have data in the buffer.
+ * If this is true then return an error.
+ */
+ if (session->internals.record_send_buffer.length > 0 && iptr != NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* If data in the buffer exist
+ */
+ if (iptr == NULL)
+ {
+ /* checking is handled above */
+ ret =
+ MHD__gnutls_buffer_get (&session->internals.record_send_buffer, &ptr,
+ &n);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD__gnutls_write_log
+ ("WRITE: Restoring old write. (%d bytes to send)\n", n);
+ }
+
+ MHD__gnutls_write_log ("WRITE: Will write %d bytes to %d.\n", n, fd);
+
+ i = 0;
+ left = n;
+ while (left > 0)
+ {
+
+ session->internals.errnum = 0;
+
+ if (session->internals.MHD__gnutls_push_func == NULL)
+ {
+ i = send (GNUTLS_POINTER_TO_INT (fd), &ptr[n - left], left, 0);
+#if HAVE_WINSOCK
+ if (i < 0)
+ {
+ int tmperr = WSAGetLastError ();
+ switch (tmperr)
+ {
+ case WSAEWOULDBLOCK:
+ session->internals.errnum = EAGAIN;
+ break;
+
+ case WSAEINTR:
+ session->internals.errnum = EINTR;
+ break;
+
+ default:
+ session->internals.errnum = EIO;
+ break;
+ }
+ WSASetLastError (tmperr);
+ }
+#endif
+ }
+ else
+ i = session->internals.MHD__gnutls_push_func (fd, &ptr[n - left], left);
+ if (i == -1)
+ {
+ int err = session->internals.errnum ? session->internals.errnum
+ : errno;
+
+ if ( (err == EAGAIN) || (err == EINTR) )
+ {
+ session->internals.record_send_buffer_prev_size += n - left;
+
+ retval =
+ MHD__gnutls_buffer_insert (&session->
+ internals.record_send_buffer,
+ &ptr[n - left], left);
+ if (retval < 0)
+ {
+ MHD_gnutls_assert ();
+ return retval;
+ }
+ if (err == EAGAIN)
+ return GNUTLS_E_AGAIN;
+ return GNUTLS_E_INTERRUPTED;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PUSH_ERROR;
+ }
+ }
+ left -= i;
+
+ if (MHD__gnutls_log_level >= 7)
+ {
+ char line[128];
+ char tmp[16];
+
+ MHD__gnutls_write_log
+ ("WRITE: wrote %d bytes to %d. Left %d bytes. Total %d bytes.\n",
+ i, fd, left, n);
+ for (x = 0; x < (unsigned) ((i) / 16) + 1; x++)
+ {
+ line[0] = 0;
+
+ if (sum > n - left)
+ break;
+
+ sprintf (tmp, "%.4x - ", x);
+ MHD_gtls_str_cat (line, sizeof (line), tmp);
+
+ for (j = 0; j < 16; j++)
+ {
+ if (sum < n - left)
+ {
+ sprintf (tmp, "%.2x ", ((unsigned char *) ptr)[sum++]);
+ MHD_gtls_str_cat (line, sizeof (line), tmp);
+ }
+ else
+ break;
+ }
+ MHD__gnutls_write_log ("%s\n", line);
+ }
+ }
+ }
+
+ retval = n + session->internals.record_send_buffer_prev_size;
+
+ session->internals.record_send_buffer.length = 0;
+ session->internals.record_send_buffer_prev_size = 0;
+
+ return retval;
+
+}
+
+/* This function writes the data that are left in the
+ * TLS write buffer (ie. because the previous write was
+ * interrupted.
+ */
+ssize_t
+MHD_gtls_io_write_flush (MHD_gtls_session_t session)
+{
+ ssize_t ret;
+
+ if (session->internals.record_send_buffer.length == 0)
+ return 0; /* done */
+
+ ret = MHD_gtls_io_write_buffered (session, NULL, 0);
+ MHD__gnutls_write_log ("WRITE FLUSH: %d [buffer: %d]\n", ret,
+ session->internals.record_send_buffer.length);
+
+ return ret;
+}
+
+/* This function writes the data that are left in the
+ * Handshake write buffer (ie. because the previous write was
+ * interrupted.
+ */
+ssize_t
+MHD_gtls_handshake_io_write_flush (MHD_gtls_session_t session)
+{
+ ssize_t ret;
+ ret = MHD_gtls_handshake_io_send_int (session, 0, 0, NULL, 0);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD__gnutls_write_log ("HANDSHAKE_FLUSH: written[1] %d bytes\n", ret);
+
+ if (session->internals.handshake_send_buffer.length == 0)
+ {
+ ret = session->internals.handshake_send_buffer_prev_size; /* done */
+ session->internals.handshake_send_buffer_prev_size = 0;
+ }
+
+ return ret;
+}
+
+/* This is a send function for the gnutls handshake
+ * protocol. Just makes sure that all data have been sent.
+ */
+ssize_t
+MHD_gtls_handshake_io_send_int (MHD_gtls_session_t session,
+ content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ const void *iptr, size_t n)
+{
+ size_t left;
+ ssize_t ret = 0;
+ const opaque *ptr;
+ ssize_t retval = 0;
+
+ ptr = iptr;
+
+ if (session->internals.handshake_send_buffer.length > 0 && ptr == NULL && n
+ == 0)
+ {
+ /* resuming previously interrupted write
+ */
+ MHD_gnutls_assert ();
+ ret = MHD__gnutls_buffer_get (&session->internals.handshake_send_buffer,
+ &ptr, &n);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return retval;
+ }
+
+ type = session->internals.handshake_send_buffer_type;
+ htype = session->internals.handshake_send_buffer_htype;
+
+ }
+ else if (session->internals.handshake_send_buffer.length > 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+#ifdef WRITE_DEBUG
+ else
+ {
+ size_t sum = 0, x, j;
+
+ MHD__gnutls_write_log ("HWRITE: will write %d bytes to %d.\n", n,
+ MHD_gnutls_transport_get_ptr (session));
+ for (x = 0; x < ((n) / 16) + 1; x++)
+ {
+ if (sum > n)
+ break;
+
+ MHD__gnutls_write_log ("%.4x - ", x);
+ for (j = 0; j < 16; j++)
+ {
+ if (sum < n)
+ {
+ MHD__gnutls_write_log ("%.2x ",
+ ((unsigned char *) ptr)[sum++]);
+ }
+ else
+ break;
+ }
+ MHD__gnutls_write_log ("\n");
+ }
+ MHD__gnutls_write_log ("\n");
+ }
+#endif
+
+ if (n == 0)
+ { /* if we have no data to send */
+ MHD_gnutls_assert ();
+ return 0;
+ }
+ else if (ptr == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ left = n;
+ while (left > 0)
+ {
+ ret = MHD_gtls_send_int (session, type, htype, &ptr[n - left], left);
+
+ if (ret <= 0)
+ {
+ if (ret == 0)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (left > 0 && (ret == GNUTLS_E_INTERRUPTED || ret
+ == GNUTLS_E_AGAIN))
+ {
+ MHD_gnutls_assert ();
+
+ retval =
+ MHD__gnutls_buffer_insert (&session->internals.
+ handshake_send_buffer,
+ &ptr[n - left], left);
+ if (retval < 0)
+ {
+ MHD_gnutls_assert ();
+ return retval;
+ }
+
+ session->internals.handshake_send_buffer_prev_size += n - left;
+
+ session->internals.handshake_send_buffer_type = type;
+ session->internals.handshake_send_buffer_htype = htype;
+
+ }
+ else
+ {
+ session->internals.handshake_send_buffer_prev_size = 0;
+ session->internals.handshake_send_buffer.length = 0;
+ }
+
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ left -= ret;
+ }
+
+ retval = n + session->internals.handshake_send_buffer_prev_size;
+
+ session->internals.handshake_send_buffer.length = 0;
+ session->internals.handshake_send_buffer_prev_size = 0;
+
+ return retval;
+
+}
+
+/* This is a receive function for the gnutls handshake
+ * protocol. Makes sure that we have received all data.
+ */
+ssize_t
+MHD_gtls_handshake_io_recv_int (MHD_gtls_session_t session,
+ content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ void *iptr, size_t sizeOfPtr)
+{
+ size_t left;
+ ssize_t i;
+ opaque *ptr;
+ size_t dsize;
+
+ ptr = iptr;
+ left = sizeOfPtr;
+
+ if (sizeOfPtr == 0 || iptr == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (session->internals.handshake_recv_buffer.length > 0)
+ {
+ /* if we have already received some data */
+ if (sizeOfPtr <= session->internals.handshake_recv_buffer.length)
+ {
+ /* if requested less data then return it.
+ */
+ MHD_gnutls_assert ();
+ memcpy (iptr, session->internals.handshake_recv_buffer.data,
+ sizeOfPtr);
+
+ session->internals.handshake_recv_buffer.length -= sizeOfPtr;
+
+ memmove (session->internals.handshake_recv_buffer.data,
+ &session->internals.handshake_recv_buffer.data[sizeOfPtr],
+ session->internals.handshake_recv_buffer.length);
+
+ return sizeOfPtr;
+ }
+ MHD_gnutls_assert ();
+ memcpy (iptr, session->internals.handshake_recv_buffer.data,
+ session->internals.handshake_recv_buffer.length);
+
+ htype = session->internals.handshake_recv_buffer_htype;
+ type = session->internals.handshake_recv_buffer_type;
+
+ left -= session->internals.handshake_recv_buffer.length;
+
+ session->internals.handshake_recv_buffer.length = 0;
+ }
+
+ while (left > 0)
+ {
+ dsize = sizeOfPtr - left;
+ i = MHD_gtls_recv_int (session, type, htype, &ptr[dsize], left);
+ if (i < 0)
+ {
+
+ if (dsize > 0 && (i == GNUTLS_E_INTERRUPTED || i == GNUTLS_E_AGAIN))
+ {
+ MHD_gnutls_assert ();
+
+ session->internals.handshake_recv_buffer.data
+ =
+ MHD_gtls_realloc_fast (session->internals.
+ handshake_recv_buffer.data, dsize);
+ if (session->internals.handshake_recv_buffer.data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy (session->internals.handshake_recv_buffer.data, iptr,
+ dsize);
+
+ session->internals.handshake_recv_buffer_htype = htype;
+ session->internals.handshake_recv_buffer_type = type;
+
+ session->internals.handshake_recv_buffer.length = dsize;
+ }
+ else
+ session->internals.handshake_recv_buffer.length = 0;
+
+ MHD_gnutls_assert ();
+
+ return i;
+ }
+ else
+ {
+ if (i == 0)
+ break; /* EOF */
+ }
+
+ left -= i;
+
+ }
+
+ session->internals.handshake_recv_buffer.length = 0;
+
+ return sizeOfPtr - left;
+}
+
+/* Buffer for handshake packets. Keeps the packets in order
+ * for finished messages to use them. Used in HMAC calculation
+ * and finished messages.
+ */
+int
+MHD_gtls_handshake_buffer_put (MHD_gtls_session_t session, opaque * data,
+ size_t length)
+{
+
+ if (length == 0)
+ return 0;
+
+ if ((session->internals.max_handshake_data_buffer_size > 0) && ((length
+ +
+ session->
+ internals.
+ handshake_hash_buffer.
+ length) >
+ session->
+ internals.
+ max_handshake_data_buffer_size))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD__gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", length);
+
+ if (MHD_gtls_buffer_append (&session->internals.handshake_hash_buffer, data,
+ length) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+}
+
+/* this function does not touch the buffer
+ * and returns data from it (peek mode!)
+ */
+int
+MHD_gtls_handshake_buffer_get_ptr (MHD_gtls_session_t session,
+ opaque ** data_ptr, size_t * length)
+{
+ if (length != NULL)
+ *length = session->internals.handshake_hash_buffer.length;
+
+ MHD__gnutls_buffers_log ("BUF[HSK]: Peeked %d bytes of Data\n",
+ session->internals.handshake_hash_buffer.length);
+
+ if (data_ptr != NULL)
+ *data_ptr = session->internals.handshake_hash_buffer.data;
+
+ return 0;
+}
+
+/* Does not free the buffer
+ */
+int
+MHD_gtls_handshake_buffer_empty (MHD_gtls_session_t session)
+{
+
+ MHD__gnutls_buffers_log ("BUF[HSK]: Emptied buffer\n");
+
+ session->internals.handshake_hash_buffer.length = 0;
+
+ return 0;
+}
+
+int
+MHD_gtls_handshake_buffer_clear (MHD_gtls_session_t session)
+{
+ MHD__gnutls_buffers_log ("BUF[HSK]: Cleared Data from buffer\n");
+ MHD_gtls_buffer_clear (&session->internals.handshake_hash_buffer);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.h
new file mode 100644
index 0000000000..e09506ac0d
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_buffers.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD_gnutls_record_buffer_put (content_type_t type,
+ MHD_gtls_session_t session, opaque * data,
+ size_t length);
+int MHD_gnutls_record_buffer_get_size (content_type_t type,
+ MHD_gtls_session_t session);
+int MHD_gtls_record_buffer_get (content_type_t type,
+ MHD_gtls_session_t session, opaque * data,
+ size_t length);
+ssize_t MHD_gtls_io_read_buffered (MHD_gtls_session_t, opaque ** iptr,
+ size_t n, content_type_t);
+void MHD_gtls_io_clear_read_buffer (MHD_gtls_session_t);
+int MHD_gtls_io_clear_peeked_data (MHD_gtls_session_t session);
+
+ssize_t MHD_gtls_io_write_buffered (MHD_gtls_session_t, const void *iptr,
+ size_t n);
+ssize_t MHD_gtls_io_write_buffered2 (MHD_gtls_session_t, const void *iptr,
+ size_t n, const void *iptr2, size_t n2);
+
+int MHD_gtls_handshake_buffer_put (MHD_gtls_session_t session, opaque * data,
+ size_t length);
+int MHD_gtls_handshake_buffer_clear (MHD_gtls_session_t session);
+int MHD_gtls_handshake_buffer_empty (MHD_gtls_session_t session);
+int MHD_gtls_handshake_buffer_get_ptr (MHD_gtls_session_t session,
+ opaque ** data_ptr, size_t * length);
+
+#define MHD__gnutls_handshake_io_buffer_clear( session) \
+ MHD_gtls_buffer_clear( &session->internals.handshake_send_buffer); \
+ MHD_gtls_buffer_clear( &session->internals.handshake_recv_buffer); \
+ session->internals.handshake_send_buffer_prev_size = 0
+
+ssize_t MHD_gtls_handshake_io_recv_int (MHD_gtls_session_t, content_type_t,
+ MHD_gnutls_handshake_description_t,
+ void *, size_t);
+ssize_t MHD_gtls_handshake_io_send_int (MHD_gtls_session_t, content_type_t,
+ MHD_gnutls_handshake_description_t,
+ const void *, size_t);
+ssize_t MHD_gtls_io_write_flush (MHD_gtls_session_t session);
+ssize_t MHD_gtls_handshake_io_write_flush (MHD_gtls_session_t session);
+
+size_t MHD_gtls_record_check_pending (MHD_gtls_session_t session);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.c
new file mode 100644
index 0000000000..c546b60766
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Some of the stuff needed for Certificate authentication is contained
+ * in this file.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <auth_cert.h>
+#include <gnutls_cert.h>
+#include <gnutls_datum.h>
+#include <gnutls_mpi.h>
+#include <gnutls_global.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_dh.h>
+#include <gnutls_str.h>
+#include <gnutls_state.h>
+#include <gnutls_auth_int.h>
+#include <gnutls_x509.h>
+/* x509 */
+#include "x509.h"
+#include "mpi.h"
+
+/**
+ * MHD__gnutls_certificate_free_keys - Used to free all the keys from a MHD_gtls_cert_credentials_t structure
+ * @sc: is an #MHD_gtls_cert_credentials_t structure.
+ *
+ * This function will delete all the keys and the certificates associated
+ * with the given credentials. This function must not be called when a
+ * TLS negotiation that uses the credentials is in progress.
+ *
+ **/
+void
+MHD__gnutls_certificate_free_keys (MHD_gtls_cert_credentials_t sc)
+{
+ unsigned i, j;
+
+ for (i = 0; i < sc->ncerts; i++)
+ {
+ for (j = 0; j < sc->cert_list_length[i]; j++)
+ {
+ MHD_gtls_gcert_deinit (&sc->cert_list[i][j]);
+ }
+ MHD_gnutls_free (sc->cert_list[i]);
+ }
+
+ MHD_gnutls_free (sc->cert_list_length);
+ sc->cert_list_length = NULL;
+
+ MHD_gnutls_free (sc->cert_list);
+ sc->cert_list = NULL;
+
+ for (i = 0; i < sc->ncerts; i++)
+ {
+ MHD_gtls_gkey_deinit (&sc->pkey[i]);
+ }
+
+ MHD_gnutls_free (sc->pkey);
+ sc->pkey = NULL;
+
+ sc->ncerts = 0;
+
+}
+
+/**
+ * MHD__gnutls_certificate_free_cas - Used to free all the CAs from a MHD_gtls_cert_credentials_t structure
+ * @sc: is an #MHD_gtls_cert_credentials_t structure.
+ *
+ * This function will delete all the CAs associated
+ * with the given credentials. Servers that do not use
+ * MHD_gtls_certificate_verify_peers2() may call this to
+ * save some memory.
+ *
+ **/
+void
+MHD__gnutls_certificate_free_cas (MHD_gtls_cert_credentials_t sc)
+{
+ unsigned j;
+
+ for (j = 0; j < sc->x509_ncas; j++)
+ {
+ MHD_gnutls_x509_crt_deinit (sc->x509_ca_list[j]);
+ }
+
+ sc->x509_ncas = 0;
+
+ MHD_gnutls_free (sc->x509_ca_list);
+ sc->x509_ca_list = NULL;
+
+}
+
+/**
+ * MHD__gnutls_certificate_free_ca_names - Used to free all the CA names from a MHD_gtls_cert_credentials_t structure
+ * @sc: is an #MHD_gtls_cert_credentials_t structure.
+ *
+ * This function will delete all the CA name in the
+ * given credentials. Clients may call this to save some memory
+ * since in client side the CA names are not used.
+ *
+ * CA names are used by servers to advertize the CAs they
+ * support to clients.
+ *
+ **/
+void
+MHD__gnutls_certificate_free_ca_names (MHD_gtls_cert_credentials_t sc)
+{
+ MHD__gnutls_free_datum (&sc->x509_rdn_sequence);
+}
+
+/*-
+ * MHD_gtls_certificate_get_rsa_params - Returns the RSA parameters pointer
+ * @rsa_params: holds the RSA parameters or NULL.
+ * @func: function to retrieve the parameters or NULL.
+ * @session: The session.
+ *
+ * This function will return the rsa parameters pointer.
+ *
+ -*/
+MHD_gtls_rsa_params_t
+MHD_gtls_certificate_get_rsa_params (MHD_gtls_rsa_params_t rsa_params,
+ MHD_gnutls_params_function * func,
+ MHD_gtls_session_t session)
+{
+ MHD_gnutls_params_st params;
+ int ret;
+
+ if (session->internals.params.rsa_params)
+ {
+ return session->internals.params.rsa_params;
+ }
+
+ if (rsa_params)
+ {
+ session->internals.params.rsa_params = rsa_params;
+ }
+ else if (func)
+ {
+ ret = func (session, GNUTLS_PARAMS_RSA_EXPORT, &params);
+ if (ret == 0 && params.type == GNUTLS_PARAMS_RSA_EXPORT)
+ {
+ session->internals.params.rsa_params = params.params.rsa_export;
+ session->internals.params.free_rsa_params = params.deinit;
+ }
+ }
+
+ return session->internals.params.rsa_params;
+}
+
+
+/**
+ * MHD__gnutls_certificate_free_credentials - Used to free an allocated MHD_gtls_cert_credentials_t structure
+ * @sc: is an #MHD_gtls_cert_credentials_t structure.
+ *
+ * This structure is complex enough to manipulate directly thus
+ * this helper function is provided in order to free (deallocate) it.
+ *
+ * This function does not free any temporary parameters associated
+ * with this structure (ie RSA and DH parameters are not freed by
+ * this function).
+ **/
+void
+MHD__gnutls_certificate_free_credentials (MHD_gtls_cert_credentials_t sc)
+{
+ MHD__gnutls_certificate_free_keys (sc);
+ MHD__gnutls_certificate_free_cas (sc);
+ MHD__gnutls_certificate_free_ca_names (sc);
+#ifdef KEYRING_HACK
+ MHD__gnutls_free_datum (&sc->keyring);
+#endif
+
+ MHD_gnutls_free (sc);
+}
+
+
+/**
+ * MHD__gnutls_certificate_allocate_credentials - Used to allocate a MHD_gtls_cert_credentials_t structure
+ * @res: is a pointer to an #MHD_gtls_cert_credentials_t structure.
+ *
+ * This structure is complex enough to manipulate directly thus this
+ * helper function is provided in order to allocate it.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+ **/
+int
+MHD__gnutls_certificate_allocate_credentials (MHD_gtls_cert_credentials_t *
+ res)
+{
+ *res = MHD_gnutls_calloc (1, sizeof (MHD_gtls_cert_credentials_st));
+
+ if (*res == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ (*res)->verify_bits = DEFAULT_VERIFY_BITS;
+ (*res)->verify_depth = DEFAULT_VERIFY_DEPTH;
+
+ return 0;
+}
+
+
+/* returns the KX algorithms that are supported by a
+ * certificate. (Eg a certificate with RSA params, supports
+ * GNUTLS_KX_RSA algorithm).
+ * This function also uses the KeyUsage field of the certificate
+ * extensions in order to disable unneded algorithms.
+ */
+int
+MHD_gtls_selected_cert_supported_kx (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm
+ **alg, int *alg_size)
+{
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx;
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kxlist[MAX_ALGOS];
+ MHD_gnutls_cert *cert;
+ int i;
+
+ if (session->internals.selected_cert_list_length == 0)
+ {
+ *alg_size = 0;
+ *alg = NULL;
+ return 0;
+ }
+
+ cert = &session->internals.selected_cert_list[0];
+ i = 0;
+
+ for (kx = 0; kx < MAX_ALGOS; kx++)
+ {
+ pk = MHD_gtls_map_pk_get_pk (kx);
+ if (pk == cert->subject_pk_algorithm)
+ {
+ /* then check key usage */
+ if (MHD__gnutls_check_key_usage (cert, kx) == 0)
+ {
+ kxlist[i] = kx;
+ i++;
+ }
+ }
+ }
+
+ if (i == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ *alg =
+ MHD_gnutls_calloc (1, sizeof (enum MHD_GNUTLS_KeyExchangeAlgorithm) * i);
+ if (*alg == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ *alg_size = i;
+
+ memcpy (*alg, kxlist, i * sizeof (enum MHD_GNUTLS_KeyExchangeAlgorithm));
+
+ return 0;
+}
+
+
+
+int
+MHD_gtls_raw_cert_to_gcert (MHD_gnutls_cert * gcert,
+ enum MHD_GNUTLS_CertificateType type,
+ const MHD_gnutls_datum_t * raw_cert,
+ int flags /* OR of ConvFlags */ )
+{
+ switch (type)
+ {
+ case MHD_GNUTLS_CRT_X509:
+ return MHD_gtls_x509_raw_cert_to_gcert (gcert, raw_cert, flags);
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+}
+
+/* This function will convert a der certificate to a format
+ * (structure) that gnutls can understand and use. Actually the
+ * important thing on this function is that it extracts the
+ * certificate's (public key) parameters.
+ *
+ * The noext flag is used to complete the handshake even if the
+ * extensions found in the certificate are unsupported and critical.
+ * The critical extensions will be catched by the verification functions.
+ */
+int
+MHD_gtls_x509_raw_cert_to_gcert (MHD_gnutls_cert * gcert,
+ const MHD_gnutls_datum_t * derCert,
+ int flags /* OR of ConvFlags */ )
+{
+ int ret;
+ MHD_gnutls_x509_crt_t cert;
+
+ ret = MHD_gnutls_x509_crt_init (&cert);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD_gnutls_x509_crt_import (cert, derCert, GNUTLS_X509_FMT_DER);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_x509_crt_deinit (cert);
+ return ret;
+ }
+
+ ret = MHD_gtls_x509_crt_to_gcert (gcert, cert, flags);
+ MHD_gnutls_x509_crt_deinit (cert);
+
+ return ret;
+}
+
+/* Like above but it accepts a parsed certificate instead.
+ */
+int
+MHD_gtls_x509_crt_to_gcert (MHD_gnutls_cert * gcert,
+ MHD_gnutls_x509_crt_t cert, unsigned int flags)
+{
+ int ret = 0;
+
+ memset (gcert, 0, sizeof (MHD_gnutls_cert));
+ gcert->cert_type = MHD_GNUTLS_CRT_X509;
+
+ if (!(flags & CERT_NO_COPY))
+ {
+#define SMALL_DER 512
+ opaque *der;
+ size_t der_size = SMALL_DER;
+
+ /* initially allocate a bogus size, just in case the certificate
+ * fits in it. That way we minimize the DER encodings performed.
+ */
+ der = MHD_gnutls_malloc (SMALL_DER);
+ if (der == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret =
+ MHD_gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der,
+ &der_size);
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (der);
+ return ret;
+ }
+
+ if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ der = MHD_gnutls_realloc (der, der_size);
+ if (der == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret =
+ MHD_gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_DER, der,
+ &der_size);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (der);
+ return ret;
+ }
+ }
+
+ gcert->raw.data = der;
+ gcert->raw.size = der_size;
+ }
+ else
+ /* now we have 0 or a bitwise or of things to decode */
+ flags ^= CERT_NO_COPY;
+
+
+ if (flags & CERT_ONLY_EXTENSIONS || flags == 0)
+ {
+ MHD_gnutls_x509_crt_get_key_usage (cert, &gcert->key_usage, NULL);
+ gcert->version = MHD_gnutls_x509_crt_get_version (cert);
+ }
+ gcert->subject_pk_algorithm =
+ MHD_gnutls_x509_crt_get_pk_algorithm (cert, NULL);
+
+ if (flags & CERT_ONLY_PUBKEY || flags == 0)
+ {
+ gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
+ ret =
+ MHD__gnutls_x509_crt_get_mpis (cert, gcert->params,
+ &gcert->params_size);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ return 0;
+
+}
+
+void
+MHD_gtls_gcert_deinit (MHD_gnutls_cert * cert)
+{
+ int i;
+
+ if (cert == NULL)
+ return;
+
+ for (i = 0; i < cert->params_size; i++)
+ {
+ MHD_gtls_mpi_release (&cert->params[i]);
+ }
+
+ MHD__gnutls_free_datum (&cert->raw);
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.h
new file mode 100644
index 0000000000..124ac96352
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cert.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_CERT_H
+# define GNUTLS_CERT_H
+
+#include <gnutls_pk.h>
+#include "x509.h"
+
+#define MAX_PUBLIC_PARAMS_SIZE 4 /* ok for RSA and DSA */
+
+/* parameters should not be larger than this limit */
+#define DSA_PUBLIC_PARAMS 4
+#define RSA_PUBLIC_PARAMS 2
+
+/* For key Usage, test as:
+ * if (st.key_usage & KEY_DIGITAL_SIGNATURE) ...
+ */
+#define KEY_DIGITAL_SIGNATURE 128
+#define KEY_NON_REPUDIATION 64
+#define KEY_KEY_ENCIPHERMENT 32
+#define KEY_DATA_ENCIPHERMENT 16
+#define KEY_KEY_AGREEMENT 8
+#define KEY_KEY_CERT_SIGN 4
+#define KEY_CRL_SIGN 2
+#define KEY_ENCIPHER_ONLY 1
+#define KEY_DECIPHER_ONLY 32768
+
+typedef struct MHD_gnutls_cert
+{
+ mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; /* the size of params depends on the public
+ * key algorithm
+ * RSA: [0] is modulus
+ * [1] is public exponent
+ * DSA: [0] is p
+ * [1] is q
+ * [2] is g
+ * [3] is public key
+ */
+ int params_size; /* holds the size of MPI params */
+
+ enum MHD_GNUTLS_PublicKeyAlgorithm subject_pk_algorithm;
+
+ unsigned int key_usage; /* bits from KEY_*
+ */
+
+ unsigned int version;
+ /* holds the type (PGP, X509)
+ */
+ enum MHD_GNUTLS_CertificateType cert_type;
+
+ MHD_gnutls_datum_t raw;
+
+} MHD_gnutls_cert;
+
+typedef struct MHD_gnutls_privkey_int
+{
+ mpi_t params[MAX_PRIV_PARAMS_SIZE]; /* the size of params depends on the public
+ * key algorithm
+ */
+ /*
+ * RSA: [0] is modulus
+ * [1] is public exponent
+ * [2] is private exponent
+ * [3] is prime1 (p)
+ * [4] is prime2 (q)
+ * [5] is coefficient (u == inverse of p mod q)
+ * DSA: [0] is p
+ * [1] is q
+ * [2] is g
+ * [3] is y (public key)
+ * [4] is x (private key)
+ */
+ int params_size; /* holds the number of params */
+
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk_algorithm;
+} MHD_gnutls_privkey;
+
+struct MHD_gtls_session_int; /* because MHD_gtls_session_t is not defined when this file is included */
+
+typedef enum ConvFlags
+{
+ CERT_NO_COPY = 2,
+ CERT_ONLY_PUBKEY = 4,
+ CERT_ONLY_EXTENSIONS = 16
+} ConvFlags;
+
+int MHD_gtls_x509_raw_cert_to_gcert (MHD_gnutls_cert * gcert,
+ const MHD_gnutls_datum_t * derCert,
+ int flags);
+int MHD_gtls_x509_crt_to_gcert (MHD_gnutls_cert * gcert,
+ MHD_gnutls_x509_crt_t cert,
+ unsigned int flags);
+
+void MHD_gtls_gkey_deinit (MHD_gnutls_privkey * key);
+void MHD_gtls_gcert_deinit (MHD_gnutls_cert * cert);
+
+int MHD_gtls_selected_cert_supported_kx (struct MHD_gtls_session_int *session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm
+ **alg, int *alg_size);
+
+int MHD_gtls_raw_cert_to_gcert (MHD_gnutls_cert * gcert,
+ enum MHD_GNUTLS_CertificateType type,
+ const MHD_gnutls_datum_t * raw_cert,
+ int flags /* OR of ConvFlags */ );
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.c
new file mode 100644
index 0000000000..5004d13ce7
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Some high level functions to be used in the record encryption are
+ * included here.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_cipher.h"
+#include "gnutls_algorithms.h"
+#include "gnutls_hash_int.h"
+#include "gnutls_cipher_int.h"
+#include "debug.h"
+#include "gnutls_num.h"
+#include "gnutls_datum.h"
+#include "gnutls_kx.h"
+#include "gnutls_record.h"
+#include "gnutls_constate.h"
+#include <gc.h>
+
+/* returns ciphertext which contains the headers too. This also
+ * calculates the size in the header field.
+ *
+ * If random pad != 0 then the random pad data will be appended.
+ */
+int
+MHD_gtls_encrypt (MHD_gtls_session_t session, const opaque * headers,
+ size_t headers_size, const opaque * data,
+ size_t data_size, opaque * ciphertext,
+ size_t ciphertext_size, content_type_t type, int random_pad)
+{
+ MHD_gnutls_datum_t plain;
+ MHD_gnutls_datum_t comp;
+ int ret;
+ int free_comp = 1;
+
+ plain.data = (opaque *) data;
+ plain.size = data_size;
+
+ comp = plain;
+ free_comp = 0;
+ ret = MHD_gtls_compressed2ciphertext (session, &ciphertext[headers_size],
+ ciphertext_size - headers_size,
+ comp, type, random_pad);
+
+ if (free_comp)
+ MHD__gnutls_free_datum (&comp);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+
+ /* copy the headers */
+ memcpy (ciphertext, headers, headers_size);
+ MHD_gtls_write_uint16 (ret, &ciphertext[3]);
+
+ return ret + headers_size;
+}
+
+/* Decrypts the given data.
+ * Returns the decrypted data length.
+ */
+int
+MHD_gtls_decrypt (MHD_gtls_session_t session, opaque * ciphertext,
+ size_t ciphertext_size, uint8_t * data,
+ size_t max_data_size, content_type_t type)
+{
+ MHD_gnutls_datum_t gcipher;
+
+ if (ciphertext_size == 0)
+ return 0;
+
+ gcipher.size = ciphertext_size;
+ gcipher.data = ciphertext;
+
+ return
+ MHD_gtls_ciphertext2compressed (session, data, max_data_size,
+ gcipher, type);
+}
+
+inline static mac_hd_t
+mac_init (enum MHD_GNUTLS_HashAlgorithm mac, opaque * secret, int secret_size,
+ int ver)
+{
+ mac_hd_t td;
+
+ if (mac == MHD_GNUTLS_MAC_NULL)
+ return GNUTLS_MAC_FAILED;
+
+ if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
+ { /* SSL 3.0 */
+ td = MHD_gnutls_mac_init_ssl3 (mac, secret, secret_size);
+ }
+ else
+ { /* TLS 1.x */
+ td = MHD_gtls_MHD_hmac_init (mac, secret, secret_size);
+ }
+
+ return td;
+}
+
+inline static void
+mac_deinit (mac_hd_t td, opaque * res, int ver)
+{
+ if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
+ { /* SSL 3.0 */
+ MHD_gnutls_mac_deinit_ssl3 (td, res);
+ }
+ else
+ {
+ MHD_gnutls_MHD_hmac_deinit (td, res);
+ }
+}
+
+inline static int
+calc_enc_length (MHD_gtls_session_t session, int data_size,
+ int hash_size, uint8_t * pad, int random_pad,
+ cipher_type_t block_algo, uint16_t blocksize)
+{
+ uint8_t rnd;
+ int length;
+
+ *pad = 0;
+
+ switch (block_algo)
+ {
+ case CIPHER_STREAM:
+ length = data_size + hash_size;
+
+ break;
+ case CIPHER_BLOCK:
+ if (MHD_gc_nonce ((char *) &rnd, 1) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+
+ /* make rnd a multiple of blocksize */
+ if (session->security_parameters.version == MHD_GNUTLS_PROTOCOL_SSL3 ||
+ random_pad == 0)
+ {
+ rnd = 0;
+ }
+ else
+ {
+ rnd = (rnd / blocksize) * blocksize;
+ /* added to avoid the case of pad calculated 0
+ * seen below for pad calculation.
+ */
+ if (rnd > blocksize)
+ rnd -= blocksize;
+ }
+
+ length = data_size + hash_size;
+
+ *pad = (uint8_t) (blocksize - (length % blocksize)) + rnd;
+
+ length += *pad;
+ if (session->security_parameters.version >= MHD_GNUTLS_PROTOCOL_TLS1_1)
+ length += blocksize; /* for the IV */
+
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ return length;
+}
+
+/* This is the actual encryption
+ * Encrypts the given compressed datum, and puts the result to cipher_data,
+ * which has cipher_size size.
+ * return the actual encrypted data length.
+ */
+int
+MHD_gtls_compressed2ciphertext (MHD_gtls_session_t session,
+ opaque * cipher_data, int cipher_size,
+ MHD_gnutls_datum_t compressed,
+ content_type_t _type, int random_pad)
+{
+ uint8_t MAC[MAX_HASH_SIZE];
+ uint16_t c_length;
+ uint8_t pad;
+ int length, ret;
+ mac_hd_t td;
+ uint8_t type = _type;
+ uint8_t major, minor;
+ int hash_size =
+ MHD_gnutls_hash_get_algo_len (session->security_parameters.
+ write_mac_algorithm);
+ enum MHD_GNUTLS_Protocol ver;
+ int blocksize =
+ MHD_gtls_cipher_get_block_size (session->security_parameters.
+ write_bulk_cipher_algorithm);
+ cipher_type_t block_algo =
+ MHD_gtls_cipher_is_block (session->security_parameters.
+ write_bulk_cipher_algorithm);
+ opaque *data_ptr;
+
+
+ ver = MHD__gnutls_protocol_get_version (session);
+ minor = MHD_gtls_version_get_minor (ver);
+ major = MHD_gtls_version_get_major (ver);
+
+
+ /* Initialize MAC */
+ td = mac_init (session->security_parameters.write_mac_algorithm,
+ session->connection_state.write_mac_secret.data,
+ session->connection_state.write_mac_secret.size, ver);
+
+ if (td == GNUTLS_MAC_FAILED
+ && session->security_parameters.write_mac_algorithm !=
+ MHD_GNUTLS_MAC_NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ c_length = MHD_gtls_conv_uint16 (compressed.size);
+
+ if (td != GNUTLS_MAC_FAILED)
+ { /* actually when the algorithm in not the NULL one */
+ MHD_gnutls_hash (td,
+ UINT64DATA (session->connection_state.
+ write_sequence_number), 8);
+
+ MHD_gnutls_hash (td, &type, 1);
+ if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_0)
+ { /* TLS 1.0 or higher */
+ MHD_gnutls_hash (td, &major, 1);
+ MHD_gnutls_hash (td, &minor, 1);
+ }
+ MHD_gnutls_hash (td, &c_length, 2);
+ MHD_gnutls_hash (td, compressed.data, compressed.size);
+ mac_deinit (td, MAC, ver);
+ }
+
+
+ /* Calculate the encrypted length (padding etc.)
+ */
+ length =
+ calc_enc_length (session, compressed.size, hash_size, &pad,
+ random_pad, block_algo, blocksize);
+ if (length < 0)
+ {
+ MHD_gnutls_assert ();
+ return length;
+ }
+
+ /* copy the encrypted data to cipher_data.
+ */
+ if (cipher_size < length)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ data_ptr = cipher_data;
+ if (block_algo == CIPHER_BLOCK &&
+ session->security_parameters.version >= MHD_GNUTLS_PROTOCOL_TLS1_1)
+ {
+ /* copy the random IV.
+ */
+ if (MHD_gc_nonce ((char *) data_ptr, blocksize) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+ data_ptr += blocksize;
+ }
+
+ memcpy (data_ptr, compressed.data, compressed.size);
+ data_ptr += compressed.size;
+
+ if (hash_size > 0)
+ {
+ memcpy (data_ptr, MAC, hash_size);
+ data_ptr += hash_size;
+ }
+ if (block_algo == CIPHER_BLOCK && pad > 0)
+ {
+ memset (data_ptr, pad - 1, pad);
+ }
+
+
+ /* Actual encryption (inplace).
+ */
+ ret =
+ MHD_gtls_cipher_encrypt (session->connection_state.write_cipher_state,
+ cipher_data, length);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return length;
+}
+
+/* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size.
+ * Returns the actual compressed packet size.
+ */
+int
+MHD_gtls_ciphertext2compressed (MHD_gtls_session_t session,
+ opaque * compress_data,
+ int compress_size,
+ MHD_gnutls_datum_t ciphertext, uint8_t type)
+{
+ uint8_t MAC[MAX_HASH_SIZE];
+ uint16_t c_length;
+ uint8_t pad;
+ int length;
+ mac_hd_t td;
+ uint16_t blocksize;
+ int ret, i, pad_failed = 0;
+ uint8_t major, minor;
+ enum MHD_GNUTLS_Protocol ver;
+ int hash_size =
+ MHD_gnutls_hash_get_algo_len (session->security_parameters.
+ read_mac_algorithm);
+
+ ver = MHD__gnutls_protocol_get_version (session);
+ minor = MHD_gtls_version_get_minor (ver);
+ major = MHD_gtls_version_get_major (ver);
+
+ blocksize =
+ MHD_gtls_cipher_get_block_size (session->security_parameters.
+ read_bulk_cipher_algorithm);
+
+ /* initialize MAC
+ */
+ td = mac_init (session->security_parameters.read_mac_algorithm,
+ session->connection_state.read_mac_secret.data,
+ session->connection_state.read_mac_secret.size, ver);
+
+ if (td == GNUTLS_MAC_FAILED
+ && session->security_parameters.read_mac_algorithm !=
+ MHD_GNUTLS_MAC_NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+ /* actual decryption (inplace)
+ */
+ switch (MHD_gtls_cipher_is_block
+ (session->security_parameters.read_bulk_cipher_algorithm))
+ {
+ case CIPHER_STREAM:
+ if ((ret =
+ MHD_gtls_cipher_decrypt (session->connection_state.
+ read_cipher_state, ciphertext.data,
+ ciphertext.size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ length = ciphertext.size - hash_size;
+
+ break;
+ case CIPHER_BLOCK:
+ if ((ciphertext.size < blocksize) || (ciphertext.size % blocksize != 0))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+
+ if ((ret =
+ MHD_gtls_cipher_decrypt (session->connection_state.
+ read_cipher_state, ciphertext.data,
+ ciphertext.size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* ignore the IV in TLS 1.1.
+ */
+ if (session->security_parameters.version >= MHD_GNUTLS_PROTOCOL_TLS1_1)
+ {
+ ciphertext.size -= blocksize;
+ ciphertext.data += blocksize;
+
+ if (ciphertext.size == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ }
+
+ pad = ciphertext.data[ciphertext.size - 1] + 1; /* pad */
+
+ length = ciphertext.size - hash_size - pad;
+
+ if (pad > ciphertext.size - hash_size)
+ {
+ MHD_gnutls_assert ();
+ /* We do not fail here. We check below for the
+ * the pad_failed. If zero means success.
+ */
+ pad_failed = GNUTLS_E_DECRYPTION_FAILED;
+ }
+
+ /* Check the pading bytes (TLS 1.x)
+ */
+ if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_0 && pad_failed == 0)
+ for (i = 2; i < pad; i++)
+ {
+ if (ciphertext.data[ciphertext.size - i] !=
+ ciphertext.data[ciphertext.size - 1])
+ pad_failed = GNUTLS_E_DECRYPTION_FAILED;
+ }
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (length < 0)
+ length = 0;
+ c_length = MHD_gtls_conv_uint16 ((uint16_t) length);
+
+ /* Pass the type, version, length and compressed through
+ * MAC.
+ */
+ if (td != GNUTLS_MAC_FAILED)
+ {
+ MHD_gnutls_hash (td,
+ UINT64DATA (session->connection_state.
+ read_sequence_number), 8);
+
+ MHD_gnutls_hash (td, &type, 1);
+ if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_0)
+ { /* TLS 1.x */
+ MHD_gnutls_hash (td, &major, 1);
+ MHD_gnutls_hash (td, &minor, 1);
+ }
+ MHD_gnutls_hash (td, &c_length, 2);
+
+ if (length > 0)
+ MHD_gnutls_hash (td, ciphertext.data, length);
+
+ mac_deinit (td, MAC, ver);
+ }
+
+ /* This one was introduced to avoid a timing attack against the TLS
+ * 1.0 protocol.
+ */
+ if (pad_failed != 0)
+ return pad_failed;
+
+ /* HMAC was not the same.
+ */
+ if ( (td != GNUTLS_MAC_FAILED) &&
+ (memcmp (MAC, &ciphertext.data[length], hash_size) != 0) )
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+
+ /* copy the decrypted stuff to compress_data.
+ */
+ if (compress_size < length)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_DECOMPRESSION_FAILED;
+ }
+ memcpy (compress_data, ciphertext.data, length);
+
+ return length;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.h
new file mode 100644
index 0000000000..b8dc00701e
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD_gtls_encrypt (MHD_gtls_session_t session, const opaque * headers,
+ size_t headers_size, const opaque * data,
+ size_t data_size, opaque * ciphertext,
+ size_t ciphertext_size, content_type_t type,
+ int random_pad);
+
+int MHD_gtls_decrypt (MHD_gtls_session_t session, opaque * ciphertext,
+ size_t ciphertext_size, uint8_t * data,
+ size_t data_size, content_type_t type);
+int MHD_gtls_compressed2ciphertext (MHD_gtls_session_t session,
+ opaque * cipher_data, int cipher_size,
+ MHD_gnutls_datum_t compressed,
+ content_type_t _type, int random_pad);
+int MHD_gtls_ciphertext2compressed (MHD_gtls_session_t session,
+ opaque * compress_data, int compress_size,
+ MHD_gnutls_datum_t ciphertext,
+ uint8_t type);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.c
new file mode 100644
index 0000000000..7349436a06
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2000, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_cipher_int.h>
+#include <gnutls_datum.h>
+
+cipher_hd_t
+MHD_gtls_cipher_init (enum MHD_GNUTLS_CipherAlgorithm cipher,
+ const MHD_gnutls_datum_t * key,
+ const MHD_gnutls_datum_t * iv)
+{
+ cipher_hd_t ret = NULL;
+ int err = GC_INVALID_CIPHER; /* doesn't matter */
+
+ switch (cipher)
+ {
+ case MHD_GNUTLS_CIPHER_AES_128_CBC:
+ err = MHD_gc_cipher_open (GC_AES128, GC_CBC, &ret);
+ break;
+ case MHD_GNUTLS_CIPHER_AES_256_CBC:
+ err = MHD_gc_cipher_open (GC_AES256, GC_CBC, &ret);
+ break;
+ case MHD_GNUTLS_CIPHER_3DES_CBC:
+ err = MHD_gc_cipher_open (GC_3DES, GC_CBC, &ret);
+ break;
+ case MHD_GNUTLS_CIPHER_ARCFOUR_128:
+ err = MHD_gc_cipher_open (GC_ARCFOUR128, GC_STREAM, &ret);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (err == 0)
+ {
+ MHD_gc_cipher_setkey (ret, key->size, (const char *) key->data);
+ if (iv->data != NULL && iv->size > 0)
+ MHD_gc_cipher_setiv (ret, iv->size, (const char *) iv->data);
+ }
+ else if (cipher != MHD_GNUTLS_CIPHER_NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_x509_log ("Crypto cipher[%d] error: %d\n", cipher, err);
+ /* FIXME: MHD_gc_strerror */
+ }
+
+ return ret;
+}
+
+int
+MHD_gtls_cipher_encrypt (cipher_hd_t handle, void *text, int textlen)
+{
+ if (handle != GNUTLS_CIPHER_FAILED)
+ {
+ if (MHD_gc_cipher_encrypt_inline (handle, textlen, text) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+ return 0;
+}
+
+int
+MHD_gtls_cipher_decrypt (cipher_hd_t handle, void *ciphertext,
+ int ciphertextlen)
+{
+ if (handle != GNUTLS_CIPHER_FAILED)
+ {
+ if (MHD_gc_cipher_decrypt_inline (handle, ciphertextlen, ciphertext) !=
+ 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+ return 0;
+}
+
+void
+MHD_gnutls_cipher_deinit (cipher_hd_t handle)
+{
+ if (handle != GNUTLS_CIPHER_FAILED)
+ {
+ MHD_gc_cipher_close (handle);
+ }
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.h
new file mode 100644
index 0000000000..f00f945f74
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_cipher_int.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_CIPHER_INT
+# define GNUTLS_CIPHER_INT
+
+#define cipher_hd_t MHD_gc_cipher_handle
+#define GNUTLS_CIPHER_FAILED NULL
+
+// TODO MHD_gc_cipher_handle -> void * x3
+void *MHD_gtls_cipher_init (enum MHD_GNUTLS_CipherAlgorithm cipher,
+ const MHD_gnutls_datum_t * key,
+ const MHD_gnutls_datum_t * iv);
+
+int MHD_gtls_cipher_encrypt (void *handle, void *text, int textlen);
+
+int MHD_gtls_cipher_decrypt (void *handle,
+ void *ciphertext, int ciphertextlen);
+
+void MHD_gnutls_cipher_deinit (void *handle);
+
+#endif /* GNUTLS_CIPHER_INT */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.c
new file mode 100644
index 0000000000..845abfe957
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.c
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that are supposed to run after the handshake procedure is
+ * finished. These functions activate the established security parameters.
+ */
+
+#include "MHD_config.h"
+#include <gnutls_int.h>
+#include <gnutls_constate.h>
+#include <gnutls_errors.h>
+#include <gnutls_kx.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_num.h>
+#include <gnutls_datum.h>
+#include <gnutls_state.h>
+
+static const char keyexp[] = "key expansion";
+static const int keyexp_length = sizeof (keyexp) - 1;
+
+static const char ivblock[] = "IV block";
+static const int ivblock_length = sizeof (ivblock) - 1;
+
+static const char cliwrite[] = "client write key";
+static const int cliwrite_length = sizeof (cliwrite) - 1;
+
+static const char servwrite[] = "server write key";
+static const int servwrite_length = sizeof (servwrite) - 1;
+
+#define EXPORT_FINAL_KEY_SIZE 16
+
+/* This function is to be called after handshake, when master_secret,
+ * client_random and server_random have been initialized.
+ * This function creates the keys and stores them into pending session.
+ * (session->cipher_specs)
+ */
+int
+MHD__gnutls_set_keys (MHD_gtls_session_t session, int hash_size, int IV_size,
+ int key_size, int export_flag)
+{
+ opaque *key_block;
+ opaque rnd[2 * TLS_RANDOM_SIZE];
+ opaque rrnd[2 * TLS_RANDOM_SIZE];
+ int pos, ret;
+ int block_size;
+ char buf[65];
+
+ if (session->cipher_specs.generated_keys != 0)
+ {
+ /* keys have already been generated.
+ * reset generated_keys and exit normally.
+ */
+ session->cipher_specs.generated_keys = 0;
+ return 0;
+ }
+
+ block_size = 2 * hash_size + 2 * key_size;
+ if (export_flag == 0)
+ block_size += 2 * IV_size;
+
+ key_block = MHD_gnutls_secure_malloc (block_size);
+ if (key_block == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy (rnd, session->security_parameters.server_random, TLS_RANDOM_SIZE);
+ memcpy (&rnd[TLS_RANDOM_SIZE],
+ session->security_parameters.client_random, TLS_RANDOM_SIZE);
+
+ memcpy (rrnd, session->security_parameters.client_random, TLS_RANDOM_SIZE);
+ memcpy (&rrnd[TLS_RANDOM_SIZE],
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+
+ if (session->security_parameters.version == MHD_GNUTLS_PROTOCOL_SSL3)
+ { /* SSL 3 */
+ ret =
+ MHD_gnutls_ssl3_generate_random
+ (session->security_parameters.master_secret, TLS_MASTER_SIZE, rnd,
+ 2 * TLS_RANDOM_SIZE, block_size, key_block);
+ }
+ else
+ { /* TLS 1.0 */
+ ret =
+ MHD_gtls_PRF (session,
+ (const unsigned char *) session->
+ security_parameters.master_secret, TLS_MASTER_SIZE,
+ keyexp, keyexp_length, rnd, 2 * TLS_RANDOM_SIZE,
+ block_size, key_block);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ return ret;
+ }
+
+ MHD__gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
+ MHD_gtls_bin2hex (key_block, block_size, buf,
+ sizeof (buf)));
+
+ pos = 0;
+ if (hash_size > 0)
+ {
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.client_write_mac_secret,
+ &key_block[pos], hash_size) < 0)
+ {
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ pos += hash_size;
+
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.server_write_mac_secret,
+ &key_block[pos], hash_size) < 0)
+ {
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ pos += hash_size;
+ }
+
+ if (key_size > 0)
+ {
+ opaque *client_write_key, *server_write_key;
+ int client_write_key_size, server_write_key_size;
+ int free_keys = 0;
+
+ if (export_flag == 0)
+ {
+ client_write_key = &key_block[pos];
+ client_write_key_size = key_size;
+
+ pos += key_size;
+
+ server_write_key = &key_block[pos];
+ server_write_key_size = key_size;
+
+ pos += key_size;
+
+ }
+ else
+ { /* export */
+ free_keys = 1;
+
+ client_write_key = MHD_gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE);
+ if (client_write_key == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ server_write_key = MHD_gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE);
+ if (server_write_key == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ MHD_gnutls_free (client_write_key);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* generate the final keys */
+
+ if (session->security_parameters.version ==
+ MHD_GNUTLS_PROTOCOL_SSL3)
+ { /* SSL 3 */
+ ret =
+ MHD_gnutls_ssl3_hash_md5 (&key_block[pos],
+ key_size, rrnd,
+ 2 * TLS_RANDOM_SIZE,
+ EXPORT_FINAL_KEY_SIZE,
+ client_write_key);
+
+ }
+ else
+ { /* TLS 1.0 */
+ ret =
+ MHD_gtls_PRF (session, &key_block[pos], key_size,
+ cliwrite, cliwrite_length,
+ rrnd,
+ 2 * TLS_RANDOM_SIZE,
+ EXPORT_FINAL_KEY_SIZE, client_write_key);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ MHD_gnutls_free (server_write_key);
+ MHD_gnutls_free (client_write_key);
+ return ret;
+ }
+
+ client_write_key_size = EXPORT_FINAL_KEY_SIZE;
+ pos += key_size;
+
+ if (session->security_parameters.version ==
+ MHD_GNUTLS_PROTOCOL_SSL3)
+ { /* SSL 3 */
+ ret =
+ MHD_gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
+ rnd, 2 * TLS_RANDOM_SIZE,
+ EXPORT_FINAL_KEY_SIZE,
+ server_write_key);
+ }
+ else
+ { /* TLS 1.0 */
+ ret =
+ MHD_gtls_PRF (session, &key_block[pos], key_size,
+ servwrite, servwrite_length,
+ rrnd, 2 * TLS_RANDOM_SIZE,
+ EXPORT_FINAL_KEY_SIZE, server_write_key);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ MHD_gnutls_free (server_write_key);
+ MHD_gnutls_free (client_write_key);
+ return ret;
+ }
+
+ server_write_key_size = EXPORT_FINAL_KEY_SIZE;
+ pos += key_size;
+ }
+
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.client_write_key,
+ client_write_key, client_write_key_size) < 0)
+ {
+ MHD_gnutls_free (key_block);
+ MHD_gnutls_free (server_write_key);
+ MHD_gnutls_free (client_write_key);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ MHD__gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
+ client_write_key_size,
+ MHD_gtls_bin2hex (client_write_key,
+ client_write_key_size, buf,
+ sizeof (buf)));
+
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.server_write_key,
+ server_write_key, server_write_key_size) < 0)
+ {
+ MHD_gnutls_free (key_block);
+ MHD_gnutls_free (server_write_key);
+ MHD_gnutls_free (client_write_key);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD__gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
+ server_write_key_size,
+ MHD_gtls_bin2hex (server_write_key,
+ server_write_key_size, buf,
+ sizeof (buf)));
+
+ if (free_keys != 0)
+ {
+ MHD_gnutls_free (server_write_key);
+ MHD_gnutls_free (client_write_key);
+ }
+ }
+
+
+ /* IV generation in export and non export ciphers.
+ */
+ if (IV_size > 0 && export_flag == 0)
+ {
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.client_write_IV, &key_block[pos],
+ IV_size) < 0)
+ {
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ pos += IV_size;
+
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.server_write_IV, &key_block[pos],
+ IV_size) < 0)
+ {
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ pos += IV_size;
+
+ }
+ else if (IV_size > 0 && export_flag != 0)
+ {
+ opaque *iv_block = MHD_gnutls_alloca (IV_size * 2);
+ if (iv_block == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (session->security_parameters.version == MHD_GNUTLS_PROTOCOL_SSL3)
+ { /* SSL 3 */
+ ret = MHD_gnutls_ssl3_hash_md5 ("", 0,
+ rrnd, TLS_RANDOM_SIZE * 2,
+ IV_size, iv_block);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (key_block);
+ MHD_gnutls_afree (iv_block);
+ return ret;
+ }
+
+ ret = MHD_gnutls_ssl3_hash_md5 ("", 0, rnd,
+ TLS_RANDOM_SIZE * 2,
+ IV_size, &iv_block[IV_size]);
+
+ }
+ else
+ { /* TLS 1.0 */
+ ret = MHD_gtls_PRF (session, (const unsigned char *) "", 0,
+ ivblock, ivblock_length, rrnd,
+ 2 * TLS_RANDOM_SIZE, IV_size * 2, iv_block);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (iv_block);
+ MHD_gnutls_free (key_block);
+ return ret;
+ }
+
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.client_write_IV, iv_block, IV_size) < 0)
+ {
+ MHD_gnutls_afree (iv_block);
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (MHD__gnutls_sset_datum
+ (&session->cipher_specs.server_write_IV,
+ &iv_block[IV_size], IV_size) < 0)
+ {
+ MHD_gnutls_afree (iv_block);
+ MHD_gnutls_free (key_block);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD_gnutls_afree (iv_block);
+ }
+
+ MHD_gnutls_free (key_block);
+
+ session->cipher_specs.generated_keys = 1;
+
+ return 0;
+}
+
+int
+MHD__gnutls_set_read_keys (MHD_gtls_session_t session)
+{
+ int hash_size;
+ int IV_size;
+ int key_size, export_flag;
+ enum MHD_GNUTLS_CipherAlgorithm algo;
+ enum MHD_GNUTLS_HashAlgorithm mac_algo;
+
+ mac_algo = session->security_parameters.read_mac_algorithm;
+ algo = session->security_parameters.read_bulk_cipher_algorithm;
+
+ hash_size = MHD_gnutls_hash_get_algo_len (mac_algo);
+ IV_size = MHD_gtls_cipher_get_iv_size (algo);
+ key_size = MHD__gnutls_cipher_get_key_size (algo);
+ export_flag = MHD_gtls_cipher_get_export_flag (algo);
+
+ return MHD__gnutls_set_keys (session, hash_size, IV_size, key_size,
+ export_flag);
+}
+
+int
+MHD__gnutls_set_write_keys (MHD_gtls_session_t session)
+{
+ int hash_size;
+ int IV_size;
+ int key_size, export_flag;
+ enum MHD_GNUTLS_CipherAlgorithm algo;
+ enum MHD_GNUTLS_HashAlgorithm mac_algo;
+
+ mac_algo = session->security_parameters.write_mac_algorithm;
+ algo = session->security_parameters.write_bulk_cipher_algorithm;
+
+ hash_size = MHD_gnutls_hash_get_algo_len (mac_algo);
+ IV_size = MHD_gtls_cipher_get_iv_size (algo);
+ key_size = MHD__gnutls_cipher_get_key_size (algo);
+ export_flag = MHD_gtls_cipher_get_export_flag (algo);
+
+ return MHD__gnutls_set_keys (session, hash_size, IV_size, key_size,
+ export_flag);
+}
+
+#define CPY_COMMON dst->entity = src->entity; \
+ dst->kx_algorithm = src->kx_algorithm; \
+ memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(cipher_suite_st)); \
+ memcpy( dst->master_secret, src->master_secret, TLS_MASTER_SIZE); \
+ memcpy( dst->client_random, src->client_random, TLS_RANDOM_SIZE); \
+ memcpy( dst->server_random, src->server_random, TLS_RANDOM_SIZE); \
+ memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
+ dst->session_id_size = src->session_id_size; \
+ dst->cert_type = src->cert_type; \
+ dst->timestamp = src->timestamp; \
+ dst->max_record_recv_size = src->max_record_recv_size; \
+ dst->max_record_send_size = src->max_record_send_size; \
+ dst->version = src->version; \
+ memcpy( &dst->extensions, &src->extensions, sizeof(MHD_gtls_ext_st)); \
+ memcpy( &dst->inner_secret, &src->inner_secret, TLS_MASTER_SIZE);
+
+static void
+MHD__gnutls_cpy_read_security_parameters (MHD_gtls_security_param_st *
+ dst,
+ MHD_gtls_security_param_st * src)
+{
+ CPY_COMMON;
+
+ dst->read_bulk_cipher_algorithm = src->read_bulk_cipher_algorithm;
+ dst->read_mac_algorithm = src->read_mac_algorithm;
+ dst->read_compression_algorithm = src->read_compression_algorithm;
+}
+
+static void
+MHD__gnutls_cpy_write_security_parameters (MHD_gtls_security_param_st *
+ dst,
+ MHD_gtls_security_param_st * src)
+{
+ CPY_COMMON;
+
+ dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm;
+ dst->write_mac_algorithm = src->write_mac_algorithm;
+ dst->write_compression_algorithm = src->write_compression_algorithm;
+}
+
+/* Sets the current connection session to conform with the
+ * Security parameters(pending session), and initializes encryption.
+ * Actually it initializes and starts encryption ( so it needs
+ * secrets and random numbers to have been negotiated)
+ * This is to be called after sending the Change Cipher Spec packet.
+ */
+int
+MHD_gtls_connection_state_init (MHD_gtls_session_t session)
+{
+ int ret;
+
+/* Setup the master secret
+ */
+ if ((ret = MHD_gtls_generate_master (session, 0), 0) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+
+ return 0;
+}
+
+
+/* Initializes the read connection session
+ * (read encrypted data)
+ */
+int
+MHD_gtls_read_connection_state_init (MHD_gtls_session_t session)
+{
+ int mac_size;
+ int rc;
+
+ MHD__gnutls_uint64zero (session->connection_state.read_sequence_number);
+
+/* Update internals from CipherSuite selected.
+ * If we are resuming just copy the connection session
+ */
+ if (session->internals.resumed == RESUME_FALSE)
+ {
+ rc = MHD_gtls_set_read_cipher (session,
+ MHD_gtls_cipher_suite_get_cipher_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (rc < 0)
+ return rc;
+ rc = MHD_gtls_set_read_mac (session,
+ MHD_gtls_cipher_suite_get_mac_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (rc < 0)
+ return rc;
+
+ rc = MHD_gtls_set_kx (session,
+ MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (rc < 0)
+ return rc;
+
+ rc = MHD_gtls_set_read_compression (session,
+ session->internals.
+ compression_method);
+ if (rc < 0)
+ return rc;
+ }
+ else
+ { /* RESUME_TRUE */
+ MHD__gnutls_cpy_read_security_parameters (&session->security_parameters,
+ &session->internals.
+ resumed_security_parameters);
+ }
+
+
+ rc = MHD__gnutls_set_read_keys (session);
+ if (rc < 0)
+ return rc;
+
+ MHD__gnutls_handshake_log ("HSK[%x]: Cipher Suite: %s\n",
+ session,
+ MHD_gtls_cipher_suite_get_name
+ (&session->security_parameters.
+ current_cipher_suite));
+
+ if (MHD_gtls_compression_is_ok
+ (session->security_parameters.read_compression_algorithm) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+ }
+
+ if (MHD_gnutls_mac_is_ok
+ (session->security_parameters.read_mac_algorithm) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* Free all the previous keys/ sessions etc.
+ */
+ if (session->connection_state.read_mac_secret.data != NULL)
+ MHD__gnutls_free_datum (&session->connection_state.read_mac_secret);
+
+ if (session->connection_state.read_cipher_state != NULL)
+ MHD_gnutls_cipher_deinit (session->connection_state.read_cipher_state);
+
+ mac_size =
+ MHD_gnutls_hash_get_algo_len (session->security_parameters.
+ read_mac_algorithm);
+
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Initializing internal [read] cipher sessions\n", session);
+
+ switch (session->security_parameters.entity)
+ {
+ case GNUTLS_SERVER:
+ /* initialize cipher session
+ */
+ session->connection_state.read_cipher_state =
+ MHD_gtls_cipher_init (session->security_parameters.
+ read_bulk_cipher_algorithm,
+ &session->cipher_specs.client_write_key,
+ &session->cipher_specs.client_write_IV);
+ if (session->connection_state.read_cipher_state == GNUTLS_CIPHER_FAILED
+ && session->security_parameters.read_bulk_cipher_algorithm !=
+ MHD_GNUTLS_CIPHER_NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* copy mac secrets from cipherspecs, to connection
+ * session.
+ */
+ if (mac_size > 0)
+ {
+ if (MHD__gnutls_sset_datum
+ (&session->connection_state.read_mac_secret,
+ session->cipher_specs.client_write_mac_secret.data,
+ session->cipher_specs.client_write_mac_secret.size) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ }
+
+ break;
+#if MHD_DEBUG_TLS
+ case GNUTLS_CLIENT:
+ session->connection_state.read_cipher_state =
+ MHD_gtls_cipher_init (session->security_parameters.
+ read_bulk_cipher_algorithm,
+ &session->cipher_specs.server_write_key,
+ &session->cipher_specs.server_write_IV);
+
+ if (session->connection_state.read_cipher_state ==
+ GNUTLS_CIPHER_FAILED
+ && session->security_parameters.read_bulk_cipher_algorithm !=
+ MHD_GNUTLS_CIPHER_NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+ /* copy mac secret to connection session
+ */
+ if (mac_size > 0)
+ {
+ if (MHD__gnutls_sset_datum
+ (&session->connection_state.read_mac_secret,
+ session->cipher_specs.server_write_mac_secret.data,
+ session->cipher_specs.server_write_mac_secret.size) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ }
+
+ break;
+#endif
+ default: /* this check is useless */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ return 0;
+}
+
+
+
+/* Initializes the write connection session
+ * (write encrypted data)
+ */
+int
+MHD_gtls_write_connection_state_init (MHD_gtls_session_t session)
+{
+ int mac_size;
+ int rc;
+
+ MHD__gnutls_uint64zero (session->connection_state.write_sequence_number);
+
+/* Update internals from CipherSuite selected.
+ * If we are resuming just copy the connection session
+ */
+ if (session->internals.resumed == RESUME_FALSE)
+ {
+ rc = MHD_gtls_set_write_cipher (session,
+ MHD_gtls_cipher_suite_get_cipher_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (rc < 0)
+ return rc;
+ rc = MHD_gtls_set_write_mac (session,
+ MHD_gtls_cipher_suite_get_mac_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (rc < 0)
+ return rc;
+
+ rc = MHD_gtls_set_kx (session,
+ MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (rc < 0)
+ return rc;
+
+ rc = MHD_gtls_set_write_compression (session,
+ session->internals.
+ compression_method);
+ if (rc < 0)
+ return rc;
+ }
+ else
+ { /* RESUME_TRUE */
+ MHD__gnutls_cpy_write_security_parameters
+ (&session->security_parameters,
+ &session->internals.resumed_security_parameters);
+ }
+
+ rc = MHD__gnutls_set_write_keys (session);
+ if (rc < 0)
+ return rc;
+
+ MHD__gnutls_handshake_log ("HSK[%x]: Cipher Suite: %s\n", session,
+ MHD_gtls_cipher_suite_get_name
+ (&session->security_parameters.
+ current_cipher_suite));
+
+ if (MHD_gtls_compression_is_ok
+ (session->security_parameters.write_compression_algorithm) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+ }
+
+ if (MHD_gnutls_mac_is_ok
+ (session->security_parameters.write_mac_algorithm) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+
+ /* Free all the previous keys/ sessions etc.
+ */
+ if (session->connection_state.write_mac_secret.data != NULL)
+ MHD__gnutls_free_datum (&session->connection_state.write_mac_secret);
+
+ if (session->connection_state.write_cipher_state != NULL)
+ MHD_gnutls_cipher_deinit (session->connection_state.write_cipher_state);
+
+ mac_size =
+ MHD_gnutls_hash_get_algo_len (session->security_parameters.
+ write_mac_algorithm);
+
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Initializing internal [write] cipher sessions\n", session);
+
+ switch (session->security_parameters.entity)
+ {
+ case GNUTLS_SERVER:
+ /* initialize cipher session
+ */
+ session->connection_state.write_cipher_state =
+ MHD_gtls_cipher_init (session->security_parameters.
+ write_bulk_cipher_algorithm,
+ &session->cipher_specs.server_write_key,
+ &session->cipher_specs.server_write_IV);
+
+ if (session->connection_state.write_cipher_state ==
+ GNUTLS_CIPHER_FAILED
+ && session->security_parameters.write_bulk_cipher_algorithm !=
+ MHD_GNUTLS_CIPHER_NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+ /* copy mac secrets from cipherspecs, to connection
+ * session.
+ */
+ if (mac_size > 0)
+ {
+ if (MHD__gnutls_sset_datum
+ (&session->connection_state.write_mac_secret,
+ session->cipher_specs.server_write_mac_secret.data,
+ session->cipher_specs.server_write_mac_secret.size) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ }
+
+
+ break;
+#if MHD_DEBUG_TLS
+ case GNUTLS_CLIENT:
+ session->connection_state.write_cipher_state =
+ MHD_gtls_cipher_init (session->security_parameters.
+ write_bulk_cipher_algorithm,
+ &session->cipher_specs.client_write_key,
+ &session->cipher_specs.client_write_IV);
+
+ if (session->connection_state.write_cipher_state ==
+ GNUTLS_CIPHER_FAILED
+ && session->security_parameters.write_bulk_cipher_algorithm !=
+ MHD_GNUTLS_CIPHER_NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* copy mac secret to connection session
+ */
+ if (mac_size > 0)
+ {
+ if (MHD__gnutls_sset_datum
+ (&session->connection_state.write_mac_secret,
+ session->cipher_specs.client_write_mac_secret.data,
+ session->cipher_specs.client_write_mac_secret.size) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ }
+
+ break;
+#endif
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+ return 0;
+}
+
+/* Sets the specified cipher into the pending session
+ */
+int
+MHD_gtls_set_read_cipher (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CipherAlgorithm algo)
+{
+
+ if (MHD_gtls_cipher_is_ok (algo) == 0)
+ {
+ if (MHD_gtls_cipher_priority (session, algo) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNWANTED_ALGORITHM;
+ }
+
+ session->security_parameters.read_bulk_cipher_algorithm = algo;
+
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ return 0;
+
+}
+
+int
+MHD_gtls_set_write_cipher (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CipherAlgorithm algo)
+{
+
+ if (MHD_gtls_cipher_is_ok (algo) == 0)
+ {
+ if (MHD_gtls_cipher_priority (session, algo) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNWANTED_ALGORITHM;
+ }
+
+ session->security_parameters.write_bulk_cipher_algorithm = algo;
+
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ return 0;
+
+}
+
+
+/* Sets the specified algorithm into pending compression session
+ */
+int
+MHD_gtls_set_read_compression (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CompressionMethod algo)
+{
+
+ if (MHD_gtls_compression_is_ok (algo) == 0)
+ {
+ session->security_parameters.read_compression_algorithm = algo;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+ }
+ return 0;
+
+}
+
+int
+MHD_gtls_set_write_compression (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CompressionMethod algo)
+{
+
+ if (MHD_gtls_compression_is_ok (algo) == 0)
+ {
+ session->security_parameters.write_compression_algorithm = algo;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+ }
+ return 0;
+
+}
+
+/* Sets the specified kx algorithm into pending session
+ */
+int
+MHD_gtls_set_kx (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algo)
+{
+
+ if (MHD_gtls_kx_is_ok (algo) == 0)
+ {
+ session->security_parameters.kx_algorithm = algo;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ if (MHD_gtls_kx_priority (session, algo) < 0)
+ {
+ MHD_gnutls_assert ();
+ /* we shouldn't get here */
+ return GNUTLS_E_UNWANTED_ALGORITHM;
+ }
+
+ return 0;
+
+}
+
+/* Sets the specified mac algorithm into pending session */
+int
+MHD_gtls_set_read_mac (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_HashAlgorithm algo)
+{
+
+ if (MHD_gnutls_mac_is_ok (algo) == 0)
+ {
+ session->security_parameters.read_mac_algorithm = algo;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ if (MHD_gtls_mac_priority (session, algo) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNWANTED_ALGORITHM;
+ }
+
+
+ return 0;
+
+}
+
+int
+MHD_gtls_set_write_mac (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_HashAlgorithm algo)
+{
+
+ if (MHD_gnutls_mac_is_ok (algo) == 0)
+ {
+ session->security_parameters.write_mac_algorithm = algo;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ if (MHD_gtls_mac_priority (session, algo) < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNWANTED_ALGORITHM;
+ }
+
+
+ return 0;
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.h
new file mode 100644
index 0000000000..59b67249d4
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_constate.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD_gtls_connection_state_init (MHD_gtls_session_t session);
+int MHD_gtls_read_connection_state_init (MHD_gtls_session_t session);
+int MHD_gtls_write_connection_state_init (MHD_gtls_session_t session);
+int MHD_gtls_set_write_cipher (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CipherAlgorithm algo);
+int MHD_gtls_set_write_mac (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_HashAlgorithm algo);
+int MHD_gtls_set_read_cipher (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CipherAlgorithm algo);
+int MHD_gtls_set_read_mac (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_HashAlgorithm algo);
+int MHD_gtls_set_read_compression (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CompressionMethod algo);
+int MHD_gtls_set_write_compression (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CompressionMethod algo);
+int MHD_gtls_set_kx (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm algo);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.c
new file mode 100644
index 0000000000..2f03da3bf2
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* contains functions that make it easier to
+ * write vectors of <size|data>. The destination size
+ * should be preallocated (datum.size+(bits/8))
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_num.h>
+#include <gnutls_datum.h>
+#include <gnutls_errors.h>
+
+
+void
+MHD_gtls_write_datum16 (opaque * dest, MHD_gnutls_datum_t dat)
+{
+ MHD_gtls_write_uint16 (dat.size, dest);
+ if (dat.data != NULL)
+ memcpy (&dest[2], dat.data, dat.size);
+}
+
+void
+MHD_gtls_write_datum24 (opaque * dest, MHD_gnutls_datum_t dat)
+{
+ MHD_gtls_write_uint24 (dat.size, dest);
+ if (dat.data != NULL)
+ memcpy (&dest[3], dat.data, dat.size);
+}
+
+int
+MHD_gtls_set_datum_m (MHD_gnutls_datum_t * dat, const void *data,
+ size_t data_size, MHD_gnutls_alloc_function galloc_func)
+{
+ if (data_size == 0 || data == NULL)
+ {
+ dat->data = NULL;
+ dat->size = 0;
+ return 0;
+ }
+
+ dat->data = galloc_func (data_size);
+ if (dat->data == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ dat->size = data_size;
+ memcpy (dat->data, data, data_size);
+
+ return 0;
+}
+
+void
+MHD_gtls_free_datum_m (MHD_gnutls_datum_t * dat,
+ MHD_gnutls_free_function gfree_func)
+{
+ if (dat->data != NULL)
+ gfree_func (dat->data);
+
+ dat->data = NULL;
+ dat->size = 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.h
new file mode 100644
index 0000000000..c6813216f8
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_datum.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+#include "gnutls_int.h"
+
+void MHD_gtls_write_datum16 (opaque * dest, MHD_gnutls_datum_t dat);
+void MHD_gtls_write_datum24 (opaque * dest, MHD_gnutls_datum_t dat);
+
+int MHD_gtls_set_datum_m (MHD_gnutls_datum_t * dat, const void *data,
+ size_t data_size, MHD_gnutls_alloc_function);
+#define MHD__gnutls_set_datum( x, y, z) MHD_gtls_set_datum_m(x,y,z, MHD_gnutls_malloc)
+#define MHD__gnutls_sset_datum( x, y, z) MHD_gtls_set_datum_m(x,y,z, MHD_gnutls_secure_malloc)
+
+#define MHD__gnutls_datum_append(x,y,z) MHD_gtls_datum_append_m(x,y,z, MHD_gnutls_realloc)
+
+void MHD_gtls_free_datum_m (MHD_gnutls_datum_t * dat,
+ MHD_gnutls_free_function);
+#define MHD__gnutls_free_datum(x) MHD_gtls_free_datum_m(x, MHD_gnutls_free)
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.c
new file mode 100644
index 0000000000..d9dd43442c
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+
+
+/*
+ --Example--
+ you: X = g ^ x mod p;
+ peer:Y = g ^ y mod p;
+
+ your_key = Y ^ x mod p;
+ his_key = X ^ y mod p;
+
+// generate our secret and the public value (X) for it
+ X = MHD_gtls_calc_dh_secret(&x, g, p);
+// now we can calculate the shared secret
+ key = MHD_gtls_calc_dh_key(Y, x, g, p);
+ MHD_gtls_mpi_release(x);
+ MHD_gtls_mpi_release(g);
+*/
+
+#define MAX_BITS 18000
+
+/* returns the public value (X), and the secret (ret_x).
+ */
+mpi_t
+MHD_gtls_calc_dh_secret (mpi_t * ret_x, mpi_t g, mpi_t prime)
+{
+ mpi_t e, x;
+ int x_size = MHD__gnutls_mpi_get_nbits (prime) - 1;
+ /* The size of the secret key is less than
+ * prime/2
+ */
+
+ if (x_size > MAX_BITS || x_size <= 0)
+ {
+ MHD_gnutls_assert ();
+ return NULL;
+ }
+
+ x = MHD__gnutls_mpi_new (x_size);
+ if (x == NULL)
+ {
+ MHD_gnutls_assert ();
+ if (ret_x)
+ *ret_x = NULL;
+
+ return NULL;
+ }
+
+ /* FIXME: (x_size/8)*8 is there to overcome a bug in libgcrypt
+ * which does not really check the bits given but the bytes.
+ */
+ do
+ {
+ MHD__gnutls_mpi_randomize (x, (x_size / 8) * 8, GCRY_STRONG_RANDOM);
+ /* Check whether x is zero.
+ */
+ }
+ while (MHD__gnutls_mpi_cmp_ui (x, 0) == 0);
+
+ e = MHD__gnutls_mpi_alloc_like (prime);
+ if (e == NULL)
+ {
+ MHD_gnutls_assert ();
+ if (ret_x)
+ *ret_x = NULL;
+
+ MHD_gtls_mpi_release (&x);
+ return NULL;
+ }
+
+ MHD__gnutls_mpi_powm (e, g, x, prime);
+
+ if (ret_x)
+ *ret_x = x;
+ else
+ MHD_gtls_mpi_release (&x);
+ return e;
+}
+
+
+mpi_t
+MHD_gtls_calc_dh_key (mpi_t f, mpi_t x, mpi_t prime)
+{
+ mpi_t k;
+ int bits;
+
+ bits = MHD__gnutls_mpi_get_nbits (prime);
+ if (bits <= 0 || bits > MAX_BITS)
+ {
+ MHD_gnutls_assert ();
+ return NULL;
+ }
+
+ k = MHD__gnutls_mpi_alloc_like (prime);
+ if (k == NULL)
+ return NULL;
+ MHD__gnutls_mpi_powm (k, f, x, prime);
+ return k;
+}
+
+/*-
+ * MHD_gtls_get_dh_params - Returns the DH parameters pointer
+ * @dh_params: is an DH parameters structure, or NULL.
+ * @func: is a callback function to receive the parameters or NULL.
+ * @session: a gnutls session.
+ *
+ * This function will return the dh parameters pointer.
+ *
+ -*/
+MHD_gtls_dh_params_t
+MHD_gtls_get_dh_params (MHD_gtls_dh_params_t dh_params,
+ MHD_gnutls_params_function * func,
+ MHD_gtls_session_t session)
+{
+ MHD_gnutls_params_st params;
+ int ret;
+
+ /* if cached return the cached */
+ if (session->internals.params.dh_params)
+ return session->internals.params.dh_params;
+
+ if (dh_params)
+ {
+ session->internals.params.dh_params = dh_params;
+ }
+ else if (func)
+ {
+ ret = func (session, GNUTLS_PARAMS_DH, &params);
+ if (ret == 0 && params.type == GNUTLS_PARAMS_DH)
+ {
+ session->internals.params.dh_params = params.params.dh;
+ session->internals.params.free_dh_params = params.deinit;
+ }
+ }
+
+ return session->internals.params.dh_params;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.h
new file mode 100644
index 0000000000..5d7341fc42
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_DH_H
+# define GNUTLS_DH_H
+
+const mpi_t *MHD_gtls_dh_params_to_mpi (MHD_gtls_dh_params_t);
+mpi_t MHD_gtls_calc_dh_secret (mpi_t * ret_x, mpi_t g, mpi_t prime);
+mpi_t MHD_gtls_calc_dh_key (mpi_t f, mpi_t x, mpi_t prime);
+int MHD_gtls_dh_generate_prime (mpi_t * ret_g, mpi_t * ret_n, unsigned bits);
+
+MHD_gtls_dh_params_t
+MHD_gtls_get_dh_params (MHD_gtls_dh_params_t dh_params,
+ MHD_gnutls_params_function * func,
+ MHD_gtls_session_t session);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh_primes.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh_primes.c
new file mode 100644
index 0000000000..a25759b0a5
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_dh_primes.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <x509_b64.h> /* for PKCS3 PEM decoding */
+#include <gnutls_global.h>
+#include <gnutls_dh.h>
+#include "debug.h"
+/* x509 */
+#include "mpi.h"
+
+
+/* returns the prime and the generator of DH params.
+ */
+const mpi_t *
+MHD_gtls_dh_params_to_mpi (MHD_gtls_dh_params_t dh_primes)
+{
+ if (dh_primes == NULL || dh_primes->params[1] == NULL
+ || dh_primes->params[0] == NULL)
+ {
+ return NULL;
+ }
+
+ return dh_primes->params;
+}
+
+int
+MHD_gtls_dh_generate_prime (mpi_t * ret_g, mpi_t * ret_n, unsigned int bits)
+{
+ mpi_t g = NULL, prime = NULL;
+ gcry_error_t err;
+ int result, times = 0, qbits;
+ mpi_t *factors = NULL;
+
+ /* Calculate the size of a prime factor of (prime-1)/2.
+ * This is an emulation of the values in "Selecting Cryptographic Key Sizes" paper.
+ */
+ if (bits < 256)
+ qbits = bits / 2;
+ else
+ {
+ qbits = (bits / 40) + 105;
+ }
+
+ if (qbits & 1) /* better have an even number */
+ qbits++;
+
+ /* find a prime number of size bits.
+ */
+ do
+ {
+
+ if (times)
+ {
+ MHD_gtls_mpi_release (&prime);
+ gcry_prime_release_factors (factors);
+ }
+
+ err = gcry_prime_generate (&prime, bits, qbits, &factors, NULL, NULL,
+ GCRY_STRONG_RANDOM,
+ GCRY_PRIME_FLAG_SPECIAL_FACTOR);
+
+ if (err != 0)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+
+ err = gcry_prime_check (prime, 0);
+
+ times++;
+ }
+ while (err != 0 && times < 10);
+
+ if (err != 0)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+
+ /* generate the group generator.
+ */
+ err = gcry_prime_group_generator (&g, prime, factors, NULL);
+ if (err != 0)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+
+ gcry_prime_release_factors (factors);
+ factors = NULL;
+
+ if (ret_g)
+ *ret_g = g;
+ else
+ MHD_gtls_mpi_release (&g);
+ if (ret_n)
+ *ret_n = prime;
+ else
+ MHD_gtls_mpi_release (&prime);
+
+ return 0;
+
+cleanup:gcry_prime_release_factors (factors);
+ MHD_gtls_mpi_release (&g);
+ MHD_gtls_mpi_release (&prime);
+
+ return result;
+
+}
+
+/* Replaces the prime in the static DH parameters, with a randomly
+ * generated one.
+ */
+/**
+ * MHD__gnutls_dh_params_init - This function will initialize the DH parameters
+ * @dh_params: Is a structure that will hold the prime numbers
+ *
+ * This function will initialize the DH parameters structure.
+ *
+ **/
+int
+MHD__gnutls_dh_params_init (MHD_gtls_dh_params_t * dh_params)
+{
+
+ (*dh_params) = MHD_gnutls_calloc (1, sizeof (MHD_gtls_dh_params_st));
+ if (*dh_params == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+
+}
+
+/**
+ * MHD__gnutls_dh_params_deinit - This function will deinitialize the DH parameters
+ * @dh_params: Is a structure that holds the prime numbers
+ *
+ * This function will deinitialize the DH parameters structure.
+ *
+ **/
+void
+MHD__gnutls_dh_params_deinit (MHD_gtls_dh_params_t dh_params)
+{
+ if (dh_params == NULL)
+ return;
+
+ MHD_gtls_mpi_release (&dh_params->params[0]);
+ MHD_gtls_mpi_release (&dh_params->params[1]);
+
+ MHD_gnutls_free (dh_params);
+
+}
+
+/**
+ * MHD__gnutls_dh_params_generate2 - This function will generate new DH parameters
+ * @params: Is the structure that the DH parameters will be stored
+ * @bits: is the prime's number of bits
+ *
+ * This function will generate a new pair of prime and generator for use in
+ * the Diffie-Hellman key exchange. The new parameters will be allocated using
+ * MHD_gnutls_malloc() and will be stored in the appropriate datum.
+ * This function is normally slow.
+ *
+ * Note that the bits value should be one of 768, 1024, 2048, 3072 or 4096.
+ * Also note that the DH parameters are only useful to servers.
+ * Since clients use the parameters sent by the server, it's of
+ * no use to call this in client side.
+ *
+ **/
+int
+MHD__gnutls_dh_params_generate2 (MHD_gtls_dh_params_t params,
+ unsigned int bits)
+{
+ int ret;
+
+ ret =
+ MHD_gtls_dh_generate_prime (&params->params[1], &params->params[0], bits);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.c
new file mode 100644
index 0000000000..48b8a562da
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include "gnutls_errors.h"
+#include <libtasn1.h>
+#ifdef STDC_HEADERS
+# include <stdarg.h>
+#endif
+
+/* I18n of error codes. */
+#define _(String) (String)
+#define N_(String) (String)
+
+extern LOG_FUNC MHD__gnutls_log_func;
+
+#define ERROR_ENTRY(desc, name, fatal) \
+ { desc, #name, name, fatal}
+
+struct MHD_gnutls_error_entry
+{
+ const char *desc;
+ const char *_name;
+ int number;
+ int fatal;
+};
+typedef struct MHD_gnutls_error_entry MHD_gnutls_error_entry;
+
+static const MHD_gnutls_error_entry MHD_gtls_error_algorithms[] = {
+ /* "Short Description", Error code define, critical (0,1) -- 1 in most cases */
+ ERROR_ENTRY (N_("Success."), GNUTLS_E_SUCCESS, 0),
+ ERROR_ENTRY (N_("Could not negotiate a supported cipher suite."),
+ GNUTLS_E_UNKNOWN_CIPHER_SUITE, 1),
+ ERROR_ENTRY (N_("The cipher type is unsupported."),
+ GNUTLS_E_UNKNOWN_CIPHER_TYPE, 1),
+ ERROR_ENTRY (N_("The certificate and the given key do not match."),
+ GNUTLS_E_CERTIFICATE_KEY_MISMATCH, 1),
+ ERROR_ENTRY (N_("Could not negotiate a supported compression method."),
+ GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM, 1),
+ ERROR_ENTRY (N_("An unknown public key algorithm was encountered."),
+ GNUTLS_E_UNKNOWN_PK_ALGORITHM, 1),
+
+ ERROR_ENTRY (N_("An algorithm that is not enabled was negotiated."),
+ GNUTLS_E_UNWANTED_ALGORITHM, 1),
+ ERROR_ENTRY (N_("A large TLS record packet was received."),
+ GNUTLS_E_LARGE_PACKET, 1),
+ ERROR_ENTRY (N_("A record packet with illegal version was received."),
+ GNUTLS_E_UNSUPPORTED_VERSION_PACKET, 1),
+ ERROR_ENTRY (N_
+ ("The Diffie Hellman prime sent by the server is not acceptable (not long enough)."),
+ GNUTLS_E_DH_PRIME_UNACCEPTABLE, 1),
+ ERROR_ENTRY (N_("A TLS packet with unexpected length was received."),
+ GNUTLS_E_UNEXPECTED_PACKET_LENGTH, 1),
+ ERROR_ENTRY (N_
+ ("The specified session has been invalidated for some reason."),
+ GNUTLS_E_INVALID_SESSION, 1),
+
+ ERROR_ENTRY (N_("GnuTLS internal error."), GNUTLS_E_INTERNAL_ERROR, 1),
+ ERROR_ENTRY (N_("An illegal TLS extension was received."),
+ GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION, 1),
+ ERROR_ENTRY (N_("A TLS fatal alert has been received."),
+ GNUTLS_E_FATAL_ALERT_RECEIVED, 1),
+ ERROR_ENTRY (N_("An unexpected TLS packet was received."),
+ GNUTLS_E_UNEXPECTED_PACKET, 1),
+ ERROR_ENTRY (N_("A TLS warning alert has been received."),
+ GNUTLS_E_WARNING_ALERT_RECEIVED, 0),
+ ERROR_ENTRY (N_
+ ("An error was encountered at the TLS Finished packet calculation."),
+ GNUTLS_E_ERROR_IN_FINISHED_PACKET, 1),
+ ERROR_ENTRY (N_("The peer did not send any certificate."),
+ GNUTLS_E_NO_CERTIFICATE_FOUND, 1),
+
+ ERROR_ENTRY (N_("No temporary RSA parameters were found."),
+ GNUTLS_E_NO_TEMPORARY_RSA_PARAMS, 1),
+ ERROR_ENTRY (N_("No temporary DH parameters were found."),
+ GNUTLS_E_NO_TEMPORARY_DH_PARAMS, 1),
+ ERROR_ENTRY (N_("An unexpected TLS handshake packet was received."),
+ GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET, 1),
+ ERROR_ENTRY (N_("The scanning of a large integer has failed."),
+ GNUTLS_E_MPI_SCAN_FAILED, 1),
+ ERROR_ENTRY (N_("Could not export a large integer."),
+ GNUTLS_E_MPI_PRINT_FAILED, 1),
+ ERROR_ENTRY (N_("Decryption has failed."), GNUTLS_E_DECRYPTION_FAILED, 1),
+ ERROR_ENTRY (N_("Encryption has failed."), GNUTLS_E_ENCRYPTION_FAILED, 1),
+ ERROR_ENTRY (N_("Public key decryption has failed."),
+ GNUTLS_E_PK_DECRYPTION_FAILED, 1),
+ ERROR_ENTRY (N_("Public key encryption has failed."),
+ GNUTLS_E_PK_ENCRYPTION_FAILED, 1),
+ ERROR_ENTRY (N_("Public key signing has failed."), GNUTLS_E_PK_SIGN_FAILED,
+ 1),
+ ERROR_ENTRY (N_("Public key signature verification has failed."),
+ GNUTLS_E_PK_SIG_VERIFY_FAILED, 1),
+ ERROR_ENTRY (N_("Decompression of the TLS record packet has failed."),
+ GNUTLS_E_DECOMPRESSION_FAILED, 1),
+ ERROR_ENTRY (N_("Compression of the TLS record packet has failed."),
+ GNUTLS_E_COMPRESSION_FAILED, 1),
+
+ ERROR_ENTRY (N_("Internal error in memory allocation."),
+ GNUTLS_E_MEMORY_ERROR, 1),
+ ERROR_ENTRY (N_("An unimplemented or disabled feature has been requested."),
+ GNUTLS_E_UNIMPLEMENTED_FEATURE, 1),
+ ERROR_ENTRY (N_("Insufficient credentials for that request."),
+ GNUTLS_E_INSUFFICIENT_CREDENTIALS, 1),
+ ERROR_ENTRY (N_("Error in password file."), GNUTLS_E_SRP_PWD_ERROR, 1),
+ ERROR_ENTRY (N_("Wrong padding in PKCS1 packet."), GNUTLS_E_PKCS1_WRONG_PAD,
+ 1),
+ ERROR_ENTRY (N_("The requested session has expired."), GNUTLS_E_EXPIRED, 1),
+ ERROR_ENTRY (N_("Hashing has failed."), GNUTLS_E_HASH_FAILED, 1),
+ ERROR_ENTRY (N_("Base64 decoding error."), GNUTLS_E_BASE64_DECODING_ERROR,
+ 1),
+ ERROR_ENTRY (N_("Base64 unexpected header error."),
+ GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR,
+ 1),
+ ERROR_ENTRY (N_("Base64 encoding error."), GNUTLS_E_BASE64_ENCODING_ERROR,
+ 1),
+ ERROR_ENTRY (N_("Parsing error in password file."),
+ GNUTLS_E_SRP_PWD_PARSING_ERROR, 1),
+ ERROR_ENTRY (N_("The requested data were not available."),
+ GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE, 0),
+ ERROR_ENTRY (N_("Error in the pull function."), GNUTLS_E_PULL_ERROR, 1),
+ ERROR_ENTRY (N_("Error in the push function."), GNUTLS_E_PUSH_ERROR, 1),
+ ERROR_ENTRY (N_
+ ("The upper limit of record packet sequence numbers has been reached. Wow!"),
+ GNUTLS_E_RECORD_LIMIT_REACHED, 1),
+ ERROR_ENTRY (N_("Error in the certificate."), GNUTLS_E_CERTIFICATE_ERROR,
+ 1),
+ ERROR_ENTRY (N_("Unknown Subject Alternative name in X.509 certificate."),
+ GNUTLS_E_X509_UNKNOWN_SAN, 1),
+
+ ERROR_ENTRY (N_("Unsupported critical extension in X.509 certificate."),
+ GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION, 1),
+ ERROR_ENTRY (N_("Key usage violation in certificate has been detected."),
+ GNUTLS_E_KEY_USAGE_VIOLATION, 1),
+ ERROR_ENTRY (N_("Function was interrupted."), GNUTLS_E_AGAIN, 0),
+ ERROR_ENTRY (N_("Function was interrupted."), GNUTLS_E_INTERRUPTED, 0),
+ ERROR_ENTRY (N_("Rehandshake was requested by the peer."),
+ GNUTLS_E_REHANDSHAKE, 0),
+ ERROR_ENTRY (N_
+ ("TLS Application data were received, while expecting handshake data."),
+ GNUTLS_E_GOT_APPLICATION_DATA, 1),
+ ERROR_ENTRY (N_("Error in Database backend."), GNUTLS_E_DB_ERROR, 1),
+ ERROR_ENTRY (N_("The certificate type is not supported."),
+ GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE, 1),
+ ERROR_ENTRY (N_("The given memory buffer is too short to hold parameters."),
+ GNUTLS_E_SHORT_MEMORY_BUFFER, 1),
+ ERROR_ENTRY (N_("The request is invalid."), GNUTLS_E_INVALID_REQUEST, 1),
+ ERROR_ENTRY (N_("An illegal parameter has been received."),
+ GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1),
+ ERROR_ENTRY (N_("Error while reading file."), GNUTLS_E_FILE_ERROR, 1),
+
+ ERROR_ENTRY (N_("ASN1 parser: Element was not found."),
+ GNUTLS_E_ASN1_ELEMENT_NOT_FOUND, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Identifier was not found"),
+ GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Error in DER parsing."),
+ GNUTLS_E_ASN1_DER_ERROR, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Value was not found."),
+ GNUTLS_E_ASN1_VALUE_NOT_FOUND, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Generic parsing error."),
+ GNUTLS_E_ASN1_GENERIC_ERROR, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Value is not valid."),
+ GNUTLS_E_ASN1_VALUE_NOT_VALID, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Error in TAG."), GNUTLS_E_ASN1_TAG_ERROR, 1),
+ ERROR_ENTRY (N_("ASN1 parser: error in implicit tag"),
+ GNUTLS_E_ASN1_TAG_IMPLICIT, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Error in type 'ANY'."),
+ GNUTLS_E_ASN1_TYPE_ANY_ERROR, 1),
+ ERROR_ENTRY (N_("ASN1 parser: Syntax error."), GNUTLS_E_ASN1_SYNTAX_ERROR,
+ 1),
+ ERROR_ENTRY (N_("ASN1 parser: Overflow in DER parsing."),
+ GNUTLS_E_ASN1_DER_OVERFLOW, 1),
+
+ ERROR_ENTRY (N_("Too many empty record packets have been received."),
+ GNUTLS_E_TOO_MANY_EMPTY_PACKETS, 1),
+ ERROR_ENTRY (N_("The initialization of GnuTLS-extra has failed."),
+ GNUTLS_E_INIT_LIBEXTRA, 1),
+ ERROR_ENTRY (N_
+ ("The GnuTLS library version does not match the GnuTLS-extra library version."),
+ GNUTLS_E_LIBRARY_VERSION_MISMATCH, 1),
+ ERROR_ENTRY (N_("The gcrypt library version is too old."),
+ GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY, 1),
+
+ ERROR_ENTRY (N_("The tasn1 library version is too old."),
+ GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY, 1),
+
+ ERROR_ENTRY (N_("The initialization of LZO has failed."),
+ GNUTLS_E_LZO_INIT_FAILED, 1),
+ ERROR_ENTRY (N_("No supported compression algorithms have been found."),
+ GNUTLS_E_NO_COMPRESSION_ALGORITHMS, 1),
+ ERROR_ENTRY (N_("No supported cipher suites have been found."),
+ GNUTLS_E_NO_CIPHER_SUITES, 1),
+ ERROR_ENTRY (N_("The SRP username supplied is illegal."),
+ GNUTLS_E_ILLEGAL_SRP_USERNAME, 1),
+
+ ERROR_ENTRY (N_("The certificate has unsupported attributes."),
+ GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE, 1),
+ ERROR_ENTRY (N_("The OID is not supported."), GNUTLS_E_X509_UNSUPPORTED_OID,
+ 1),
+ ERROR_ENTRY (N_("The hash algorithm is unknown."),
+ GNUTLS_E_UNKNOWN_HASH_ALGORITHM, 1),
+ ERROR_ENTRY (N_("The PKCS structure's content type is unknown."),
+ GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE, 1),
+ ERROR_ENTRY (N_("The PKCS structure's bag type is unknown."),
+ GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE, 1),
+ ERROR_ENTRY (N_("The given password contains invalid characters."),
+ GNUTLS_E_INVALID_PASSWORD, 1),
+ ERROR_ENTRY (N_("The Message Authentication Code verification failed."),
+ GNUTLS_E_MAC_VERIFY_FAILED, 1),
+ ERROR_ENTRY (N_("Some constraint limits were reached."),
+ GNUTLS_E_CONSTRAINT_ERROR, 1),
+ ERROR_ENTRY (N_("Failed to acquire random data."), GNUTLS_E_RANDOM_FAILED,
+ 1),
+
+ ERROR_ENTRY (N_("Received a TLS/IA Intermediate Phase Finished message"),
+ GNUTLS_E_WARNING_IA_IPHF_RECEIVED, 0),
+ ERROR_ENTRY (N_("Received a TLS/IA Final Phase Finished message"),
+ GNUTLS_E_WARNING_IA_FPHF_RECEIVED, 0),
+ ERROR_ENTRY (N_("Verifying TLS/IA phase checksum failed"),
+ GNUTLS_E_IA_VERIFY_FAILED, 1),
+
+ ERROR_ENTRY (N_("The specified algorithm or protocol is unknown."),
+ GNUTLS_E_UNKNOWN_ALGORITHM, 1),
+
+ {NULL, NULL, 0, 0}
+};
+
+#define GNUTLS_ERROR_LOOP(b) \
+ const MHD_gnutls_error_entry *p; \
+ for(p = MHD_gtls_error_algorithms; p->desc != NULL; p++) { b ; }
+
+#define GNUTLS_ERROR_ALG_LOOP(a) \
+ GNUTLS_ERROR_LOOP( if(p->number == error) { a; break; } )
+
+
+
+/**
+ * MHD_gtls_error_is_fatal - Returns non-zero in case of a fatal error
+ * @error: is an error returned by a gnutls function. Error should be a negative value.
+ *
+ * If a function returns a negative value you may feed that value
+ * to this function to see if it is fatal. Returns 1 for a fatal
+ * error 0 otherwise. However you may want to check the
+ * error code manually, since some non-fatal errors to the protocol
+ * may be fatal for you (your program).
+ *
+ * This is only useful if you are dealing with errors from the
+ * record layer or the handshake layer.
+ *
+ * For positive @error values, 0 is returned.
+ *
+ **/
+int
+MHD_gtls_error_is_fatal (int error)
+{
+ int ret = 1;
+
+ /* Input sanitzation. Positive values are not errors at all, and
+ definitely not fatal. */
+ if (error > 0)
+ return 0;
+
+ GNUTLS_ERROR_ALG_LOOP (ret = p->fatal);
+
+ return ret;
+}
+
+/**
+ * MHD_gtls_perror - prints a string to stderr with a description of an error
+ * @error: is an error returned by a gnutls function. Error is always a negative value.
+ *
+ * This function is like perror(). The only difference is that it accepts an
+ * error number returned by a gnutls function.
+ **/
+void
+MHD_gtls_perror (int error)
+{
+ const char *ret = NULL;
+
+ /* avoid prefix */
+ GNUTLS_ERROR_ALG_LOOP (ret = p->desc);
+ if (ret == NULL)
+ ret = "(unknown)";
+ fprintf (stderr, "GNUTLS ERROR: %s\n", _(ret));
+}
+
+
+/**
+ * MHD_gtls_strerror - Returns a string with a description of an error
+ * @error: is an error returned by a gnutls function. Error is always a negative value.
+ *
+ * This function is similar to strerror(). Differences: it accepts an error
+ * number returned by a gnutls function; In case of an unknown error
+ * a descriptive string is sent instead of NULL.
+ **/
+const char *
+MHD_gtls_strerror (int error)
+{
+ const char *ret = NULL;
+
+ /* avoid prefix */
+ GNUTLS_ERROR_ALG_LOOP (ret = p->desc);
+ if (ret == NULL)
+ return "(unknown error code)";
+ return _(ret);
+}
+
+/* This will print the actual define of the
+ * given error code.
+ */
+const char *
+MHD__gnutls_strerror (int error)
+{
+ const char *ret = NULL;
+
+ /* avoid prefix */
+ GNUTLS_ERROR_ALG_LOOP (ret = p->_name);
+
+ return _(ret);
+}
+
+int
+MHD_gtls_asn2err (int asn_err)
+{
+ switch (asn_err)
+ {
+ case ASN1_FILE_NOT_FOUND:
+ return GNUTLS_E_FILE_ERROR;
+ case ASN1_ELEMENT_NOT_FOUND:
+ return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
+ case ASN1_IDENTIFIER_NOT_FOUND:
+ return GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND;
+ case ASN1_DER_ERROR:
+ return GNUTLS_E_ASN1_DER_ERROR;
+ case ASN1_VALUE_NOT_FOUND:
+ return GNUTLS_E_ASN1_VALUE_NOT_FOUND;
+ case ASN1_GENERIC_ERROR:
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ case ASN1_VALUE_NOT_VALID:
+ return GNUTLS_E_ASN1_VALUE_NOT_VALID;
+ case ASN1_TAG_ERROR:
+ return GNUTLS_E_ASN1_TAG_ERROR;
+ case ASN1_TAG_IMPLICIT:
+ return GNUTLS_E_ASN1_TAG_IMPLICIT;
+ case ASN1_ERROR_TYPE_ANY:
+ return GNUTLS_E_ASN1_TYPE_ANY_ERROR;
+ case ASN1_SYNTAX_ERROR:
+ return GNUTLS_E_ASN1_SYNTAX_ERROR;
+ case ASN1_MEM_ERROR:
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ case ASN1_MEM_ALLOC_ERROR:
+ return GNUTLS_E_MEMORY_ERROR;
+ case ASN1_DER_OVERFLOW:
+ return GNUTLS_E_ASN1_DER_OVERFLOW;
+ default:
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+}
+
+
+/* this function will output a message using the
+ * caller provided function
+ */
+void
+MHD_gtls_log (int level, const char *fmt, ...)
+{
+ va_list args;
+ char str[MAX_LOG_SIZE];
+ void (*log_func) (int, const char *) = MHD__gnutls_log_func;
+
+ if (MHD__gnutls_log_func == NULL)
+ return;
+
+ va_start (args, fmt);
+ vsnprintf (str, MAX_LOG_SIZE - 1, fmt, args); /* Flawfinder: ignore */
+ va_end (args);
+
+ log_func (level, str);
+}
+
+void
+MHD__gnutls_null_log (void *n, ...)
+{
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.h
new file mode 100644
index 0000000000..ecde580b11
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_errors.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <defines.h>
+
+#define GNUTLS_E_INT_RET_0 -1251
+
+#ifdef __FILE__
+# ifdef __LINE__
+# define MHD_gnutls_assert() MHD__gnutls_debug_log( "ASSERT: %s:%d\n", __FILE__,__LINE__);
+# else
+# define MHD_gnutls_assert()
+# endif
+#else /* __FILE__ not defined */
+# define MHD_gnutls_assert()
+#endif
+
+int MHD_gtls_asn2err (int asn_err);
+void MHD_gtls_log (int, const char *fmt, ...);
+
+extern int MHD__gnutls_log_level;
+
+#ifdef C99_MACROS
+#define LEVEL(l, ...) if (MHD__gnutls_log_level >= l || MHD__gnutls_log_level > 9) \
+ MHD_gtls_log( l, __VA_ARGS__)
+
+#define LEVEL_EQ(l, ...) if (MHD__gnutls_log_level == l || MHD__gnutls_log_level > 9) \
+ MHD_gtls_log( l, __VA_ARGS__)
+
+# define MHD__gnutls_debug_log(...) LEVEL(2, __VA_ARGS__)
+# define MHD__gnutls_handshake_log(...) LEVEL(3, __VA_ARGS__)
+# define MHD__gnutls_buffers_log(...) LEVEL_EQ(6, __VA_ARGS__)
+# define MHD__gnutls_hard_log(...) LEVEL(9, __VA_ARGS__)
+# define MHD__gnutls_record_log(...) LEVEL(4, __VA_ARGS__)
+# define MHD__gnutls_read_log(...) LEVEL_EQ(7, __VA_ARGS__)
+# define MHD__gnutls_write_log(...) LEVEL_EQ(7, __VA_ARGS__)
+# define MHD__gnutls_x509_log(...) LEVEL(1, __VA_ARGS__)
+#else
+# define MHD__gnutls_debug_log MHD__gnutls_null_log
+# define MHD__gnutls_handshake_log MHD__gnutls_null_log
+# define MHD__gnutls_buffers_log MHD__gnutls_null_log
+# define MHD__gnutls_hard_log MHD__gnutls_null_log
+# define MHD__gnutls_record_log MHD__gnutls_null_log
+# define MHD__gnutls_read_log MHD__gnutls_null_log
+# define MHD__gnutls_write_log MHD__gnutls_null_log
+# define MHD__gnutls_x509_log MHD__gnutls_null_log
+
+void MHD__gnutls_null_log (void *, ...);
+
+#endif /* C99_MACROS */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.c
new file mode 100644
index 0000000000..8ee96c6594
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that relate to the TLS hello extension parsing.
+ * Hello extensions are packets appended in the TLS hello packet, and
+ * allow for extra functionality.
+ */
+
+#include "MHD_config.h"
+#include "gnutls_int.h"
+#include "gnutls_extensions.h"
+#include "gnutls_errors.h"
+#include "ext_max_record.h"
+#include <ext_cert_type.h>
+#include <ext_server_name.h>
+#include <gnutls_num.h>
+
+/* Key Exchange Section */
+#define GNUTLS_EXTENSION_ENTRY(type, parse_type, ext_func_recv, ext_func_send) \
+ { #type, type, parse_type, ext_func_recv, ext_func_send }
+
+
+#define MAX_EXT_SIZE 10
+const int MHD_gtls_extensions_size = MAX_EXT_SIZE;
+
+MHD_gtls_extension_entry MHD_gtls_extensions[MAX_EXT_SIZE] = {
+ GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_MAX_RECORD_SIZE,
+ EXTENSION_TLS,
+ MHD_gtls_max_record_recv_params,
+ MHD_gtls_max_record_send_params),
+ GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_CERT_TYPE,
+ EXTENSION_TLS,
+ MHD_gtls_cert_type_recv_params,
+ MHD_gtls_cert_type_send_params),
+ GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_SERVER_NAME,
+ EXTENSION_APPLICATION,
+ MHD_gtls_server_name_recv_params,
+ MHD_gtls_server_name_send_params),
+ {0, 0, 0, 0}
+};
+
+#define GNUTLS_EXTENSION_LOOP2(b) \
+ MHD_gtls_extension_entry *p; \
+ for(p = MHD_gtls_extensions; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_EXTENSION_LOOP(a) \
+ GNUTLS_EXTENSION_LOOP2( if(p->type == type) { a; break; } )
+
+
+/* EXTENSION functions */
+
+MHD_gtls_ext_recv_func
+MHD_gtls_ext_func_recv (uint16_t type, MHD_gtls_ext_parse_type_t parse_type)
+{
+ MHD_gtls_ext_recv_func ret = NULL;
+ GNUTLS_EXTENSION_LOOP (if
+ (parse_type == EXTENSION_ANY
+ || p->parse_type == parse_type) ret =
+ p->MHD_gnutls_ext_func_recv);
+ return ret;
+
+}
+
+MHD_gtls_ext_send_func
+MHD_gtls_ext_func_send (uint16_t type)
+{
+ MHD_gtls_ext_send_func ret = NULL;
+ GNUTLS_EXTENSION_LOOP (ret = p->MHD_gnutls_ext_func_send);
+ return ret;
+
+}
+
+const char *
+MHD_gtls_extension_get_name (uint16_t type)
+{
+ const char *ret = NULL;
+
+ /* avoid prefix */
+ GNUTLS_EXTENSION_LOOP (ret = p->name + sizeof ("GNUTLS_EXTENSION_") - 1);
+
+ return ret;
+}
+
+/* Checks if the extension we just received is one of the
+ * requested ones. Otherwise it's a fatal error.
+ */
+static int
+MHD__gnutls_extension_list_check (MHD_gtls_session_t session, uint16_t type)
+{
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ int i;
+ for (i = 0; i < session->internals.extensions_sent_size; i++)
+ {
+ if (type == session->internals.extensions_sent[i])
+ return 0; /* ok found */
+ }
+ return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
+ }
+#endif
+ return 0;
+}
+
+int
+MHD_gtls_parse_extensions (MHD_gtls_session_t session,
+ MHD_gtls_ext_parse_type_t parse_type,
+ const opaque * data, int data_size)
+{
+ int next, ret;
+ int pos = 0;
+ uint16_t type;
+ const opaque *sdata;
+ MHD_gtls_ext_recv_func ext_recv;
+ uint16_t size;
+
+#if MHD_DEBUG_TLS
+ int i;
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ for (i = 0; i < session->internals.extensions_sent_size; i++)
+ {
+ MHD__gnutls_debug_log ("EXT[%d]: expecting extension '%s'\n",
+ session,
+ MHD_gtls_extension_get_name
+ (session->internals.extensions_sent[i]));
+ }
+#endif
+
+ DECR_LENGTH_RET (data_size, 2, 0);
+ next = MHD_gtls_read_uint16 (data);
+ pos += 2;
+
+ DECR_LENGTH_RET (data_size, next, 0);
+
+ do
+ {
+ DECR_LENGTH_RET (next, 2, 0);
+ type = MHD_gtls_read_uint16 (&data[pos]);
+ pos += 2;
+
+ MHD__gnutls_debug_log ("EXT[%x]: Received extension '%s/%d'\n", session,
+ MHD_gtls_extension_get_name (type), type);
+
+ if ((ret = MHD__gnutls_extension_list_check (session, type)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ DECR_LENGTH_RET (next, 2, 0);
+ size = MHD_gtls_read_uint16 (&data[pos]);
+ pos += 2;
+
+ DECR_LENGTH_RET (next, size, 0);
+ sdata = &data[pos];
+ pos += size;
+
+ ext_recv = MHD_gtls_ext_func_recv (type, parse_type);
+ if (ext_recv == NULL)
+ continue;
+ if ((ret = ext_recv (session, sdata, size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ }
+ while (next > 2);
+
+ return 0;
+
+}
+
+/* Adds the extension we want to send in the extensions list.
+ * This list is used to check whether the (later) received
+ * extensions are the ones we requested.
+ */
+static void
+MHD__gnutls_extension_list_add (MHD_gtls_session_t session, uint16_t type)
+{
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ if (session->internals.extensions_sent_size < MAX_EXT_TYPES)
+ {
+ session->internals.extensions_sent[session->internals.
+ extensions_sent_size] = type;
+ session->internals.extensions_sent_size++;
+ }
+ else
+ {
+ MHD__gnutls_debug_log ("extensions: Increase MAX_EXT_TYPES\n");
+ }
+ }
+#endif
+}
+
+int
+MHD_gtls_gen_extensions (MHD_gtls_session_t session, opaque * data,
+ size_t data_size)
+{
+ int size;
+ uint16_t pos = 0;
+ opaque *sdata;
+ int sdata_size;
+ MHD_gtls_ext_send_func ext_send;
+ MHD_gtls_extension_entry *p;
+
+ if (data_size < 2)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* allocate enough data for each extension.
+ */
+ sdata_size = data_size;
+ sdata = MHD_gnutls_malloc (sdata_size);
+ if (sdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ pos += 2;
+ for (p = MHD_gtls_extensions; p->name != NULL; p++)
+ {
+ ext_send = MHD_gtls_ext_func_send (p->type);
+ if (ext_send == NULL)
+ continue;
+ size = ext_send (session, sdata, sdata_size);
+ if (size > 0)
+ {
+ if (data_size < pos + (size_t) size + 4)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (sdata);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* write extension type */
+ MHD_gtls_write_uint16 (p->type, &data[pos]);
+ pos += 2;
+
+ /* write size */
+ MHD_gtls_write_uint16 (size, &data[pos]);
+ pos += 2;
+
+ memcpy (&data[pos], sdata, size);
+ pos += size;
+
+ /* add this extension to the extension list
+ */
+ MHD__gnutls_extension_list_add (session, p->type);
+
+ MHD__gnutls_debug_log ("EXT[%x]: Sending extension %s\n", session,
+ MHD_gtls_extension_get_name (p->type));
+ }
+ else if (size < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (sdata);
+ return size;
+ }
+ }
+
+ size = pos;
+ pos -= 2; /* remove the size of the size header! */
+
+ MHD_gtls_write_uint16 (pos, data);
+
+ if (size == 2)
+ { /* empty */
+ size = 0;
+ }
+
+ MHD_gnutls_free (sdata);
+ return size;
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.h
new file mode 100644
index 0000000000..9623b39b43
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_extensions.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+
+const char *MHD_gtls_extension_get_name (uint16_t type);
+int MHD_gtls_parse_extensions (MHD_gtls_session_t, MHD_gtls_ext_parse_type_t,
+ const opaque *, int);
+int MHD_gtls_gen_extensions (MHD_gtls_session_t session, opaque * data,
+ size_t data_size);
+
+typedef int (*MHD_gtls_ext_recv_func) (MHD_gtls_session_t, const opaque *, size_t); /* recv data */
+typedef int (*MHD_gtls_ext_send_func) (MHD_gtls_session_t, opaque *, size_t); /* send data */
+
+MHD_gtls_ext_send_func MHD_gtls_ext_func_send (uint16_t type);
+MHD_gtls_ext_recv_func MHD_gtls_ext_func_recv (uint16_t type,
+ MHD_gtls_ext_parse_type_t);
+
+typedef struct
+{
+ const char *name;
+ uint16_t type;
+ MHD_gtls_ext_parse_type_t parse_type;
+ MHD_gtls_ext_recv_func MHD_gnutls_ext_func_recv;
+ MHD_gtls_ext_send_func MHD_gnutls_ext_func_send;
+} MHD_gtls_extension_entry;
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.c
new file mode 100644
index 0000000000..818a92a100
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <libtasn1.h>
+#include <gnutls_dh.h>
+
+/* this is used in order to make the multi-threaded initialization call to libgcrypt */
+#include <pthread.h>
+#include <gcrypt.h>
+
+/* used to set the MHD_tls logging function */
+#include "internal.h"
+
+/* TODO fix : needed by GCRY_THREAD_OPTION_PTHREAD_IMPL but missing otherwise */
+#define ENOMEM 12 /* Out of memory */
+
+#ifdef HAVE_WINSOCK
+# include <winsock2.h>
+#endif
+
+
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+
+#define MHD_gnutls_log_func LOG_FUNC
+
+/* created by asn1c */
+extern const ASN1_ARRAY_TYPE MHD_gnutlsMHD__asn1_tab[];
+extern const ASN1_ARRAY_TYPE MHD_pkix_asn1_tab[];
+
+LOG_FUNC MHD__gnutls_log_func;
+int MHD__gnutls_log_level = 0; /* default log level */
+
+ASN1_TYPE MHD__gnutls_pkix1_asn;
+ASN1_TYPE MHD__gnutlsMHD__gnutls_asn;
+
+/**
+ * MHD_gtls_global_set_log_function - This function sets the logging function
+ * @log_func: it's a log function
+ *
+ * This is the function where you set the logging function gnutls
+ * is going to use. This function only accepts a character array.
+ * Normally you may not use this function since it is only used
+ * for debugging purposes.
+ *
+ * MHD_gnutls_log_func is of the form,
+ * void (*MHD_gnutls_log_func)( int level, const char*);
+ **/
+void
+MHD_gtls_global_set_log_function (MHD_gnutls_log_func log_func)
+{
+ MHD__gnutls_log_func = log_func;
+}
+
+/**
+ * MHD_gtls_global_set_log_level - This function sets the logging level
+ * @level: it's an integer from 0 to 9.
+ *
+ * This is the function that allows you to set the log level.
+ * The level is an integer between 0 and 9. Higher values mean
+ * more verbosity. The default value is 0. Larger values should
+ * only be used with care, since they may reveal sensitive information.
+ *
+ * Use a log level over 10 to enable all debugging options.
+ *
+ **/
+void
+MHD_gtls_global_set_log_level (int level)
+{
+ MHD__gnutls_log_level = level;
+}
+
+int MHD__gnutls_is_secure_mem_null (const void *);
+
+static int MHD__gnutls_init_level = 0;
+
+/**
+ * MHD__gnutls_global_init - This function initializes the global data to defaults.
+ *
+ * This function initializes the global data to defaults.
+ * Every gnutls application has a global data which holds common parameters
+ * shared by gnutls session structures.
+ * You must call MHD__gnutls_global_deinit() when gnutls usage is no longer needed
+ * Returns zero on success.
+ *
+ * Note that this function will also initialize libgcrypt, if it has not
+ * been initialized before. Thus if you want to manually initialize libgcrypt
+ * you must do it before calling this function. This is useful in cases you
+ * want to disable libgcrypt's internal lockings etc.
+ *
+ * This function increment a global counter, so that
+ * MHD__gnutls_global_deinit() only releases resources when it has been
+ * called as many times as MHD__gnutls_global_init(). This is useful when
+ * GnuTLS is used by more than one library in an application. This
+ * function can be called many times, but will only do something the
+ * first time.
+ *
+ * Note! This function is not thread safe. If two threads call this
+ * function simultaneously, they can cause a race between checking
+ * the global counter and incrementing it, causing both threads to
+ * execute the library initialization code. That would lead to a
+ * memory leak. To handle this, your application could invoke this
+ * function after aquiring a thread mutex. To ignore the potential
+ * memory leak is also an option.
+ *
+ **/
+int
+MHD__gnutls_global_init ()
+{
+ int result = 0;
+ int res;
+
+ if (MHD__gnutls_init_level++)
+ return 0;
+
+#if HAVE_WINSOCK
+ {
+ WORD requested;
+ WSADATA data;
+ int err;
+
+ requested = MAKEWORD (1, 1);
+ err = WSAStartup (requested, &data);
+ if (err != 0)
+ {
+ MHD__gnutls_debug_log ("WSAStartup failed: %d.\n", err);
+ return GNUTLS_E_LIBRARY_VERSION_MISMATCH;
+ }
+
+ if (data.wVersion < requested)
+ {
+ MHD__gnutls_debug_log ("WSAStartup version check failed (%d < %d).\n",
+ data.wVersion, requested);
+ WSACleanup ();
+ return GNUTLS_E_LIBRARY_VERSION_MISMATCH;
+ }
+ }
+#endif
+
+ /* bindtextdomain("mhd", "./"); */
+
+ if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
+ {
+ const char *p;
+
+ /* to enable multi-threading this call must precede any other call made to libgcrypt */
+ gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+
+ /* set p to point at the required version of gcrypt */
+ p = strchr (MHD_GCRYPT_VERSION, ':');
+ if (p == NULL)
+ p = MHD_GCRYPT_VERSION;
+ else
+ p++;
+
+ /* this call initializes libgcrypt */
+ if (gcry_check_version (p) == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_debug_log ("Checking for libgcrypt failed '%s'\n", p);
+ return GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY;
+ }
+
+ /* for gcrypt in order to be able to allocate memory */
+ gcry_set_allocation_handler (MHD_gnutls_malloc,
+ MHD_gnutls_secure_malloc,
+ MHD__gnutls_is_secure_memory,
+ MHD_gnutls_realloc, MHD_gnutls_free);
+
+ /* gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING, NULL, 0); */
+
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
+
+ }
+
+ if (MHD_gc_init () != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_debug_log ("Initializing crypto backend failed\n");
+ return GNUTLS_E_INCOMPATIBLE_CRYPTO_LIBRARY;
+ }
+
+ /* initialize parser
+ * This should not deal with files in the final
+ * version.
+ */
+ res =
+ MHD__asn1_array2tree (MHD_pkix_asn1_tab, &MHD__gnutls_pkix1_asn, NULL);
+ if (res != ASN1_SUCCESS)
+ {
+ result = MHD_gtls_asn2err (res);
+ return result;
+ }
+
+ res =
+ MHD__asn1_array2tree (MHD_gnutlsMHD__asn1_tab,
+ &MHD__gnutlsMHD__gnutls_asn, NULL);
+ if (res != ASN1_SUCCESS)
+ {
+ MHD__asn1_delete_structure (&MHD__gnutls_pkix1_asn);
+ result = MHD_gtls_asn2err (res);
+ return result;
+ }
+
+ return result;
+}
+
+/**
+ * MHD__gnutls_global_deinit - This function deinitializes the global data
+ *
+ * This function deinitializes the global data, that were initialized
+ * using MHD__gnutls_global_init().
+ *
+ * Note! This function is not thread safe. See the discussion for
+ * MHD__gnutls_global_init() for more information.
+ *
+ **/
+void
+MHD__gnutls_global_deinit ()
+{
+ if (MHD__gnutls_init_level == 1)
+ {
+#if HAVE_WINSOCK
+ WSACleanup ();
+#endif
+ MHD__asn1_delete_structure (&MHD__gnutlsMHD__gnutls_asn);
+ MHD__asn1_delete_structure (&MHD__gnutls_pkix1_asn);
+ MHD_gc_done ();
+ }
+ MHD__gnutls_init_level--;
+}
+
+/* These functions should be elsewere. Kept here for
+ * historical reasons.
+ */
+
+/**
+ * MHD__gnutls_transport_set_pull_function - This function sets a read like function
+ * @pull_func: a callback function similar to read()
+ * @session: gnutls session
+ *
+ * This is the function where you set a function for gnutls
+ * to receive data. Normally, if you use berkeley style sockets,
+ * do not need to use this function since the default (recv(2)) will
+ * probably be ok.
+ *
+ * PULL_FUNC is of the form,
+ * ssize_t (*MHD_gtls_pull_func)(MHD_gnutls_transport_ptr_t, void*, size_t);
+ **/
+void
+MHD__gnutls_transport_set_pull_function (MHD_gtls_session_t session,
+ MHD_gtls_pull_func pull_func)
+{
+ session->internals.MHD__gnutls_pull_func = pull_func;
+}
+
+/**
+ * MHD__gnutls_transport_set_push_function - This function sets the function to send data
+ * @push_func: a callback function similar to write()
+ * @session: gnutls session
+ *
+ * This is the function where you set a push function for gnutls
+ * to use in order to send data. If you are going to use berkeley style
+ * sockets, you do not need to use this function since
+ * the default (send(2)) will probably be ok. Otherwise you should
+ * specify this function for gnutls to be able to send data.
+ *
+ * PUSH_FUNC is of the form,
+ * ssize_t (*MHD_gtls_push_func)(MHD_gnutls_transport_ptr_t, const void*, size_t);
+ **/
+void
+MHD__gnutls_transport_set_push_function (MHD_gtls_session_t session,
+ MHD_gtls_push_func push_func)
+{
+ session->internals.MHD__gnutls_push_func = push_func;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.h
new file mode 100644
index 0000000000..50d6131c3d
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_global.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_GLOBAL_H
+#define GNUTLS_GLOBAL_H
+
+#include "MHD_config.h"
+#include <libtasn1.h>
+#undef HAVE_CONFIG_H
+#include <pthread.h>
+#define HAVE_CONFIG_H 1
+
+/* this mutex is used to synchronize threads attempting to call MHD__gnutls_global_init / MHD__gnutls_global_deinit */
+extern pthread_mutex_t MHD_gnutls_init_mutex;
+
+int MHD_gnutls_is_secure_memory (const void *mem);
+
+extern ASN1_TYPE MHD__gnutls_pkix1_asn;
+extern ASN1_TYPE MHD__gnutlsMHD__gnutls_asn;
+
+#if !HAVE_MEMMEM
+extern void *memmem (void const *__haystack, size_t __haystack_len,
+ void const *__needle, size_t __needle_len);
+#endif
+
+/* removed const from node_asn* to
+ * prevent warnings, since libtasn1 doesn't
+ * use the const keywork in its functions.
+ */
+#define MHD__gnutls_getMHD__gnutls_asn() ((node_asn*) MHD__gnutlsMHD__gnutls_asn)
+#define MHD__gnutls_get_pkix() ((node_asn*) MHD__gnutls_pkix1_asn)
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.c
new file mode 100644
index 0000000000..f12f4015c0
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.c
@@ -0,0 +1,2804 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that relate to the TLS handshake procedure.
+ */
+
+#include "MHD_config.h"
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "debug.h"
+#include "gnutls_algorithms.h"
+#include "gnutls_cipher.h"
+#include "gnutls_buffers.h"
+#include "gnutls_kx.h"
+#include "gnutls_handshake.h"
+#include "gnutls_num.h"
+#include "gnutls_hash_int.h"
+#include "gnutls_extensions.h"
+#include "gnutls_supplemental.h"
+#include "gnutls_auth_int.h"
+#include "auth_cert.h"
+#include "gnutls_cert.h"
+#include "gnutls_constate.h"
+#include "gnutls_record.h"
+#include "gnutls_state.h"
+#include "gnutls_rsa_export.h" /* for MHD_gnutls_get_rsa_params() */
+#include "gc.h"
+
+#ifdef HANDSHAKE_DEBUG
+#define ERR(x, y) MHD__gnutls_handshake_log( "HSK[%x]: %s (%d)\n", session, x,y)
+#else
+#define ERR(x, y)
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+
+/* This should be sufficient by now. It should hold all the extensions
+ * plus the headers in a hello message.
+ */
+#define MAX_EXT_DATA_LENGTH 1024
+
+
+static int MHD_gtls_remove_unwanted_ciphersuites (MHD_gtls_session_t session,
+ cipher_suite_st **
+ cipherSuites,
+ int numCipherSuites,
+ enum
+ MHD_GNUTLS_PublicKeyAlgorithm);
+static int MHD_gtls_server_select_suite (MHD_gtls_session_t session,
+ opaque * data, int datalen);
+
+static int MHD_gtls_generate_session_id (opaque * session_id, uint8_t * len);
+
+static int MHD_gtls_handshake_common (MHD_gtls_session_t session);
+
+static int MHD_gtls_handshake_server (MHD_gtls_session_t session);
+
+#if MHD_DEBUG_TLS
+static int MHD_gtls_handshake_client (MHD_gtls_session_t session);
+#endif
+
+
+static int MHD__gnutls_server_select_comp_method (MHD_gtls_session_t session,
+ opaque * data, int datalen);
+
+
+/* Clears the handshake hash buffers and handles.
+ */
+static void
+MHD__gnutls_handshake_hash_buffers_clear (MHD_gtls_session_t session)
+{
+ MHD_gnutls_hash_deinit (session->internals.handshake_mac_handle_md5, NULL);
+ MHD_gnutls_hash_deinit (session->internals.handshake_mac_handle_sha, NULL);
+ session->internals.handshake_mac_handle_md5 = NULL;
+ session->internals.handshake_mac_handle_sha = NULL;
+ MHD_gtls_handshake_buffer_clear (session);
+}
+
+/**
+ * gnutls_handshake_set_max_packet_length - This function will set the maximum length of a handshake message
+ * @session: is a #gnutls_session_t structure.
+ * @max: is the maximum number.
+ *
+ * This function will set the maximum size of a handshake message.
+ * Handshake messages over this size are rejected.
+ * The default value is 16kb which is large enough. Set this to 0 if you do not want
+ * to set an upper limit.
+ *
+ **/
+void
+MHD__gnutls_handshake_set_max_packet_length (MHD_gtls_session_t session,
+ size_t max)
+{
+ session->internals.max_handshake_data_buffer_size = max;
+}
+
+
+static void
+MHD_gtls_set_server_random (MHD_gtls_session_t session, uint8_t * rnd)
+{
+ memcpy (session->security_parameters.server_random, rnd, TLS_RANDOM_SIZE);
+}
+
+static void
+MHD_gtls_set_client_random (MHD_gtls_session_t session, uint8_t * rnd)
+{
+ memcpy (session->security_parameters.client_random, rnd, TLS_RANDOM_SIZE);
+}
+
+/* Calculate The SSL3 Finished message */
+#define SSL3_CLIENT_MSG "CLNT"
+#define SSL3_SERVER_MSG "SRVR"
+#define SSL_MSG_LEN 4
+static int
+MHD__gnutls_ssl3_finished (MHD_gtls_session_t session, int type, opaque * ret)
+{
+ const int siz = SSL_MSG_LEN;
+ mac_hd_t td_md5;
+ mac_hd_t td_sha;
+ const char *mesg;
+
+ td_md5 = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
+ if (td_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
+ if (td_sha == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_hash_deinit (td_md5, NULL);
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ if (type == GNUTLS_SERVER)
+ {
+ mesg = SSL3_SERVER_MSG;
+ }
+ else
+ {
+ mesg = SSL3_CLIENT_MSG;
+ }
+
+ MHD_gnutls_hash (td_md5, mesg, siz);
+ MHD_gnutls_hash (td_sha, mesg, siz);
+
+ MHD_gnutls_mac_deinit_ssl3_handshake (td_md5, ret,
+ session->security_parameters.
+ master_secret, TLS_MASTER_SIZE);
+ MHD_gnutls_mac_deinit_ssl3_handshake (td_sha, &ret[16],
+ session->security_parameters.
+ master_secret, TLS_MASTER_SIZE);
+
+ return 0;
+}
+
+/* Hash the handshake messages as required by TLS 1.0 */
+#define SERVER_MSG "server finished"
+#define CLIENT_MSG "client finished"
+#define TLS_MSG_LEN 15
+static int
+MHD__gnutls_finished (MHD_gtls_session_t session, int type, void *ret)
+{
+ const int siz = TLS_MSG_LEN;
+ opaque concat[36];
+ size_t len;
+ const char *mesg;
+ mac_hd_t td_md5 = NULL;
+ mac_hd_t td_sha;
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ td_md5 =
+ MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
+ if (td_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+ }
+
+ td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
+ if (td_sha == NULL)
+ {
+ MHD_gnutls_assert ();
+ if (td_md5 != NULL)
+ MHD_gnutls_hash_deinit (td_md5, NULL);
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ MHD_gnutls_hash_deinit (td_md5, concat);
+ MHD_gnutls_hash_deinit (td_sha, &concat[16]);
+ len = 20 + 16;
+ }
+ else
+ {
+ MHD_gnutls_hash_deinit (td_sha, concat);
+ len = 20;
+ }
+
+ if (type == GNUTLS_SERVER)
+ {
+ mesg = SERVER_MSG;
+ }
+ else
+ {
+ mesg = CLIENT_MSG;
+ }
+
+ return MHD_gtls_PRF (session, session->security_parameters.master_secret,
+ TLS_MASTER_SIZE, mesg, siz, concat, len, 12, ret);
+}
+
+/* this function will produce TLS_RANDOM_SIZE==32 bytes of random data
+ * and put it to dst.
+ */
+static int
+MHD_gtls_tls_create_random (opaque * dst)
+{
+ uint32_t tim;
+
+ /* Use weak random numbers for the most of the
+ * buffer except for the first 4 that are the
+ * system's time.
+ */
+
+ tim = time (NULL);
+ /* generate server random value */
+ MHD_gtls_write_uint32 (tim, dst);
+
+ if (MHD_gc_nonce ((char *) &dst[4], TLS_RANDOM_SIZE - 4) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+
+ return 0;
+}
+
+/* returns the 0 on success or a negative value.
+ */
+static int
+MHD_gtls_negotiate_version (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_Protocol adv_version)
+{
+ int ret;
+
+ /* if we do not support that version */
+ if (MHD_gtls_version_is_supported (session, adv_version) == 0)
+ {
+ /* If he requested something we do not support
+ * then we send him the highest we support.
+ */
+ ret = MHD_gtls_version_max (session);
+ }
+ else
+ {
+ ret = adv_version;
+ }
+ MHD_gtls_set_current_version (session, ret);
+
+ return ret;
+}
+
+/* Read a client hello packet.
+ * A client hello must be a known version client hello
+ * or version 2.0 client hello (only for compatibility
+ * since SSL version 2.0 is not supported).
+ */
+static int
+MHD__gnutls_read_client_hello (MHD_gtls_session_t session, opaque * data,
+ int datalen)
+{
+ uint8_t session_id_len;
+ int pos = 0, ret = 0;
+ uint16_t suite_size, comp_size;
+ enum MHD_GNUTLS_Protocol adv_version;
+ int neg_version;
+ int len = datalen;
+ opaque rnd[TLS_RANDOM_SIZE], *suite_ptr, *comp_ptr;
+
+ DECR_LEN (len, 2);
+
+ MHD__gnutls_handshake_log ("HSK[%x]: Client's version: %d.%d\n", session,
+ data[pos], data[pos + 1]);
+
+ adv_version = MHD_gtls_version_get (data[pos], data[pos + 1]);
+ set_adv_version (session, data[pos], data[pos + 1]);
+ pos += 2;
+
+ neg_version = MHD_gtls_negotiate_version (session, adv_version);
+ if (neg_version < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* Read client random value.
+ */
+ DECR_LEN (len, TLS_RANDOM_SIZE);
+ MHD_gtls_set_client_random (session, &data[pos]);
+ pos += TLS_RANDOM_SIZE;
+
+ MHD_gtls_tls_create_random (rnd);
+ MHD_gtls_set_server_random (session, rnd);
+
+ session->security_parameters.timestamp = time (NULL);
+
+ DECR_LEN (len, 1);
+ session_id_len = data[pos++];
+
+ /* RESUME SESSION */
+ if (session_id_len > TLS_MAX_SESSION_ID_SIZE)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ DECR_LEN (len, session_id_len);
+
+ pos += session_id_len;
+
+ MHD_gtls_generate_session_id (session->security_parameters.session_id,
+ &session->security_parameters.
+ session_id_size);
+
+ session->internals.resumed = RESUME_FALSE;
+ /* Remember ciphersuites for later
+ */
+ DECR_LEN (len, 2);
+ suite_size = MHD_gtls_read_uint16 (&data[pos]);
+ pos += 2;
+
+ DECR_LEN (len, suite_size);
+ suite_ptr = &data[pos];
+ pos += suite_size;
+
+ /* Point to the compression methods
+ */
+ DECR_LEN (len, 1);
+ comp_size = data[pos++]; /* z is the number of compression methods */
+
+ DECR_LEN (len, comp_size);
+ comp_ptr = &data[pos];
+ pos += comp_size;
+
+ /* Parse the extensions (if any)
+ */
+ if (neg_version >= MHD_GNUTLS_PROTOCOL_TLS1_0)
+ {
+ ret = MHD_gtls_parse_extensions (session, EXTENSION_APPLICATION, &data[pos], len); /* len is the rest of the parsed length */
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ if (neg_version >= MHD_GNUTLS_PROTOCOL_TLS1_0)
+ {
+ ret = MHD_gtls_parse_extensions (session, EXTENSION_TLS, &data[pos], len); /* len is the rest of the parsed length */
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ /* select an appropriate cipher suite
+ */
+ ret = MHD_gtls_server_select_suite (session, suite_ptr, suite_size);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* select appropriate compression method */
+ ret = MHD__gnutls_server_select_comp_method (session, comp_ptr, comp_size);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return 0;
+}
+
+/* here we hash all pending data.
+ */
+static int
+MHD__gnutls_handshake_hash_pending (MHD_gtls_session_t session)
+{
+ size_t siz;
+ int ret;
+ opaque *data;
+
+ if (session->internals.handshake_mac_handle_sha == NULL ||
+ session->internals.handshake_mac_handle_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* We check if there are pending data to hash.
+ */
+ if ((ret = MHD_gtls_handshake_buffer_get_ptr (session, &data, &siz)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (siz > 0)
+ {
+ MHD_gnutls_hash (session->internals.handshake_mac_handle_sha, data,
+ siz);
+ MHD_gnutls_hash (session->internals.handshake_mac_handle_md5, data,
+ siz);
+ }
+
+ MHD_gtls_handshake_buffer_empty (session);
+
+ return 0;
+}
+
+
+/* This is to be called after sending CHANGE CIPHER SPEC packet
+ * and initializing encryption. This is the first encrypted message
+ * we send.
+ */
+static int
+MHD__gnutls_send_finished (MHD_gtls_session_t session, int again)
+{
+ uint8_t data[36];
+ int ret;
+ int data_size = 0;
+
+
+ if (again == 0)
+ {
+
+ /* This is needed in order to hash all the required
+ * messages.
+ */
+ if ((ret = MHD__gnutls_handshake_hash_pending (session)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (MHD__gnutls_protocol_get_version (session) ==
+ MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ ret =
+ MHD__gnutls_ssl3_finished (session,
+ session->security_parameters.entity,
+ data);
+ data_size = 36;
+ }
+ else
+ { /* TLS 1.0 */
+ ret =
+ MHD__gnutls_finished (session,
+ session->security_parameters.entity, data);
+ data_size = 12;
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ }
+
+ ret =
+ MHD_gtls_send_handshake (session, data, data_size,
+ GNUTLS_HANDSHAKE_FINISHED);
+
+ return ret;
+}
+
+/* This is to be called after sending our finished message. If everything
+ * went fine we have negotiated a secure connection
+ */
+static int
+MHD__gnutls_recv_finished (MHD_gtls_session_t session)
+{
+ uint8_t data[36], *vrfy;
+ int data_size;
+ int ret;
+ int vrfysize;
+
+ ret =
+ MHD_gtls_recv_handshake (session, &vrfy, &vrfysize,
+ GNUTLS_HANDSHAKE_FINISHED, MANDATORY_PACKET);
+ if (ret < 0)
+ {
+ ERR ("recv finished int", ret);
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+
+ if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ data_size = 36;
+ }
+ else
+ {
+ data_size = 12;
+ }
+
+ if (vrfysize != data_size)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (vrfy);
+ return GNUTLS_E_ERROR_IN_FINISHED_PACKET;
+ }
+
+ if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ ret =
+ MHD__gnutls_ssl3_finished (session,
+ (session->security_parameters.entity +
+ 1) % 2, data);
+ }
+ else
+ { /* TLS 1.0 */
+ ret =
+ MHD__gnutls_finished (session,
+ (session->security_parameters.entity +
+ 1) % 2, data);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (vrfy);
+ return ret;
+ }
+
+ if (memcmp (vrfy, data, data_size) != 0)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
+ }
+ MHD_gnutls_free (vrfy);
+
+ return ret;
+}
+
+/* returns PK_RSA if the given cipher suite list only supports,
+ * RSA algorithms, PK_DSA if DSS, and PK_ANY for both or PK_NONE for none.
+ */
+static int
+MHD__gnutls_server_find_pk_algos_in_ciphersuites (const opaque *
+ data, int datalen)
+{
+ int j;
+ enum MHD_GNUTLS_PublicKeyAlgorithm algo = GNUTLS_PK_NONE, prev_algo = 0;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx;
+ cipher_suite_st cs;
+
+ if (datalen % 2 != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ for (j = 0; j < datalen; j += 2)
+ {
+ memcpy (&cs.suite, &data[j], 2);
+ kx = MHD_gtls_cipher_suite_get_kx_algo (&cs);
+
+ if (MHD_gtls_map_kx_get_cred (kx, 1) == MHD_GNUTLS_CRD_CERTIFICATE)
+ {
+ algo = MHD_gtls_map_pk_get_pk (kx);
+
+ if (algo != prev_algo && prev_algo != 0)
+ return GNUTLS_PK_ANY;
+ prev_algo = algo;
+ }
+ }
+
+ return algo;
+}
+
+
+/* This selects the best supported ciphersuite from the given ones. Then
+ * it adds the suite to the session and performs some checks.
+ */
+static int
+MHD_gtls_server_select_suite (MHD_gtls_session_t session, opaque * data,
+ int datalen)
+{
+ int x, i, j;
+ cipher_suite_st *ciphers, cs;
+ int retval, err;
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk_algo; /* will hold the pk algorithms
+ * supported by the peer.
+ */
+
+ pk_algo = MHD__gnutls_server_find_pk_algos_in_ciphersuites (data, datalen);
+
+ x = MHD_gtls_supported_ciphersuites (session, &ciphers);
+ if (x < 0)
+ { /* the case x==0 is handled within the function. */
+ MHD_gnutls_assert ();
+ return x;
+ }
+
+ /* Here we remove any ciphersuite that does not conform
+ * the certificate requested, or to the
+ * authentication requested (e.g. SRP).
+ */
+ x = MHD_gtls_remove_unwanted_ciphersuites (session, &ciphers, x, pk_algo);
+ if (x <= 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (ciphers);
+ if (x < 0)
+ return x;
+ else
+ return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
+ }
+
+ /* Data length should be zero mod 2 since
+ * every ciphersuite is 2 bytes. (this check is needed
+ * see below).
+ */
+ if (datalen % 2 != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ memset (session->security_parameters.current_cipher_suite.suite, '\0', 2);
+
+ retval = GNUTLS_E_UNKNOWN_CIPHER_SUITE;
+
+ for (j = 0; j < datalen; j += 2)
+ {
+ for (i = 0; i < x; i++)
+ {
+ if (memcmp (ciphers[i].suite, &data[j], 2) == 0)
+ {
+ memcpy (&cs.suite, &data[j], 2);
+
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Selected cipher suite: %s\n", session,
+ MHD_gtls_cipher_suite_get_name (&cs));
+ memcpy (session->security_parameters.current_cipher_suite.suite,
+ ciphers[i].suite, 2);
+ retval = 0;
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ MHD_gnutls_free (ciphers);
+
+ if (retval != 0)
+ {
+ MHD_gnutls_assert ();
+ return retval;
+ }
+
+ /* check if the credentials (username, public key etc.) are ok
+ */
+ if (MHD_gtls_get_kx_cred
+ (session,
+ MHD_gtls_cipher_suite_get_kx_algo (&session->security_parameters.
+ current_cipher_suite), &err) == NULL
+ && err != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+
+ /* set the MHD_gtls_mod_auth_st to the appropriate struct
+ * according to the KX algorithm. This is needed since all the
+ * handshake functions are read from there;
+ */
+ session->internals.auth_struct =
+ MHD_gtls_kx_auth_struct (MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+ if (session->internals.auth_struct == NULL)
+ {
+
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Cannot find the appropriate handler for the KX algorithm\n",
+ session);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ return 0;
+
+}
+
+
+/* This selects the best supported compression method from the ones provided
+ */
+static int
+MHD__gnutls_server_select_comp_method (MHD_gtls_session_t session,
+ opaque * data, int datalen)
+{
+ int x, i, j;
+ uint8_t *comps;
+
+ x = MHD_gtls_supported_compression_methods (session, &comps);
+ if (x < 0)
+ {
+ MHD_gnutls_assert ();
+ return x;
+ }
+
+ memset (&session->internals.compression_method, 0,
+ sizeof (enum MHD_GNUTLS_CompressionMethod));
+
+ for (j = 0; j < datalen; j++)
+ {
+ for (i = 0; i < x; i++)
+ {
+ if (comps[i] == data[j])
+ {
+ enum MHD_GNUTLS_CompressionMethod method =
+ MHD_gtls_compression_get_id_from_int (comps[i]);
+
+ session->internals.compression_method = method;
+ MHD_gnutls_free (comps);
+ return 0;
+ }
+ }
+ }
+
+ /* we were not able to find a compatible compression
+ * algorithm
+ */
+ MHD_gnutls_free (comps);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+
+}
+
+/* This function sends an empty handshake packet. (like hello request).
+ * If the previous MHD__gnutls_send_empty_handshake() returned
+ * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again
+ * (until it returns ok), with NULL parameters.
+ */
+static int
+MHD__gnutls_send_empty_handshake (MHD_gtls_session_t session,
+ MHD_gnutls_handshake_description_t type,
+ int again)
+{
+ opaque data = 0;
+ opaque *ptr;
+
+ if (again == 0)
+ ptr = &data;
+ else
+ ptr = NULL;
+
+ return MHD_gtls_send_handshake (session, ptr, 0, type);
+}
+
+
+/* This function will hash the handshake message we sent. */
+static int
+MHD__gnutls_handshake_hash_add_sent (MHD_gtls_session_t session,
+ MHD_gnutls_handshake_description_t type,
+ opaque * dataptr, uint32_t datalen)
+{
+ int ret;
+
+ if ((ret = MHD__gnutls_handshake_hash_pending (session)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
+ {
+ MHD_gnutls_hash (session->internals.handshake_mac_handle_sha, dataptr,
+ datalen);
+ MHD_gnutls_hash (session->internals.handshake_mac_handle_md5, dataptr,
+ datalen);
+ }
+
+ return 0;
+}
+
+
+/* This function sends a handshake message of type 'type' containing the
+ * data specified here. If the previous MHD_gtls_send_handshake() returned
+ * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again
+ * (until it returns ok), with NULL parameters.
+ */
+int
+MHD_gtls_send_handshake (MHD_gtls_session_t session, void *i_data,
+ uint32_t i_datasize,
+ MHD_gnutls_handshake_description_t type)
+{
+ int ret;
+ uint8_t *data;
+ uint32_t datasize;
+ int pos = 0;
+
+ if (i_data == NULL && i_datasize == 0)
+ {
+ /* we are resuming a previously interrupted
+ * send.
+ */
+ ret = MHD_gtls_handshake_io_write_flush (session);
+ return ret;
+
+ }
+
+ if (i_data == NULL && i_datasize > 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* first run */
+ datasize = i_datasize + HANDSHAKE_HEADER_SIZE;
+ data = MHD_gnutls_alloca (datasize);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ data[pos++] = (uint8_t) type;
+ MHD_gtls_write_uint24 (i_datasize, &data[pos]);
+ pos += 3;
+
+ if (i_datasize > 0)
+ memcpy (&data[pos], i_data, i_datasize);
+
+ /* Here we keep the handshake messages in order to hash them...
+ */
+ if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
+ if ((ret =
+ MHD__gnutls_handshake_hash_add_sent (session, type, data,
+ datasize)) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (data);
+ return ret;
+ }
+
+ session->internals.last_handshake_out = type;
+
+ ret =
+ MHD_gtls_handshake_io_send_int (session, GNUTLS_HANDSHAKE, type,
+ data, datasize);
+
+ MHD__gnutls_handshake_log ("HSK[%x]: %s was sent [%ld bytes]\n",
+ session, MHD__gnutls_handshake2str (type),
+ (long) datasize);
+
+ MHD_gnutls_afree (data);
+
+ return ret;
+}
+
+/* This function will read the handshake header and return it to the caller. If the
+ * received handshake packet is not the one expected then it buffers the header, and
+ * returns UNEXPECTED_HANDSHAKE_PACKET.
+ *
+ * FIXME: This function is complex.
+ */
+#define SSL2_HEADERS 1
+static int
+MHD__gnutls_recv_handshake_header (MHD_gtls_session_t session,
+ MHD_gnutls_handshake_description_t type,
+ MHD_gnutls_handshake_description_t *
+ recv_type)
+{
+ int ret;
+ uint32_t length32 = 0;
+ uint8_t *dataptr = NULL; /* for realloc */
+ size_t handshake_header_size = HANDSHAKE_HEADER_SIZE;
+
+ /* if we have data into the buffer then return them, do not read the next packet.
+ * In order to return we need a full TLS handshake header, or in case of a version 2
+ * packet, then we return the first byte.
+ */
+ if (session->internals.handshake_header_buffer.header_size ==
+ handshake_header_size || (session->internals.v2_hello != 0
+ && type == GNUTLS_HANDSHAKE_CLIENT_HELLO
+ && session->internals.
+ handshake_header_buffer.packet_length > 0))
+ {
+
+ *recv_type = session->internals.handshake_header_buffer.recv_type;
+
+ return session->internals.handshake_header_buffer.packet_length;
+ }
+
+ /* Note: SSL2_HEADERS == 1 */
+
+ dataptr = session->internals.handshake_header_buffer.header;
+
+ /* If we haven't already read the handshake headers.
+ */
+ if (session->internals.handshake_header_buffer.header_size < SSL2_HEADERS)
+ {
+ ret =
+ MHD_gtls_handshake_io_recv_int (session, GNUTLS_HANDSHAKE,
+ type, dataptr, SSL2_HEADERS);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* The case ret==0 is caught here.
+ */
+ if (ret != SSL2_HEADERS)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ session->internals.handshake_header_buffer.header_size = SSL2_HEADERS;
+ }
+
+ if (session->internals.v2_hello == 0
+ || type != GNUTLS_HANDSHAKE_CLIENT_HELLO)
+ {
+ ret =
+ MHD_gtls_handshake_io_recv_int (session, GNUTLS_HANDSHAKE,
+ type,
+ &dataptr
+ [session->internals.
+ handshake_header_buffer.header_size],
+ HANDSHAKE_HEADER_SIZE -
+ session->internals.
+ handshake_header_buffer.header_size);
+ if (ret <= 0)
+ {
+ MHD_gnutls_assert ();
+ return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ if ((size_t) ret !=
+ HANDSHAKE_HEADER_SIZE -
+ session->internals.handshake_header_buffer.header_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ *recv_type = dataptr[0];
+
+ /* we do not use DECR_LEN because we know
+ * that the packet has enough data.
+ */
+ length32 = MHD_gtls_read_uint24 (&dataptr[1]);
+ handshake_header_size = HANDSHAKE_HEADER_SIZE;
+
+ MHD__gnutls_handshake_log ("HSK[%x]: %s was received [%ld bytes]\n",
+ session,
+ MHD__gnutls_handshake2str (dataptr[0]),
+ length32 + HANDSHAKE_HEADER_SIZE);
+
+ }
+ else
+ { /* v2 hello */
+ length32 = session->internals.v2_hello - SSL2_HEADERS; /* we've read the first byte */
+
+ handshake_header_size = SSL2_HEADERS; /* we've already read one byte */
+
+ *recv_type = dataptr[0];
+
+ MHD__gnutls_handshake_log ("HSK[%x]: %s(v2) was received [%ld bytes]\n",
+ session,
+ MHD__gnutls_handshake2str (*recv_type),
+ length32 + handshake_header_size);
+
+ if (*recv_type != GNUTLS_HANDSHAKE_CLIENT_HELLO)
+ { /* it should be one or nothing */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
+ }
+ }
+
+ /* put the packet into the buffer */
+ session->internals.handshake_header_buffer.header_size =
+ handshake_header_size;
+ session->internals.handshake_header_buffer.packet_length = length32;
+ session->internals.handshake_header_buffer.recv_type = *recv_type;
+
+ if (*recv_type != type)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
+ }
+
+ return length32;
+}
+
+#define MHD__gnutls_handshake_header_buffer_clear( session) session->internals.handshake_header_buffer.header_size = 0
+
+/* This function will hash the handshake headers and the
+ * handshake data.
+ */
+static int
+MHD__gnutls_handshake_hash_add_recvd (MHD_gtls_session_t session,
+ MHD_gnutls_handshake_description_t
+ recv_type, opaque * header,
+ uint16_t header_size, opaque * dataptr,
+ uint32_t datalen)
+{
+ int ret;
+
+ /* The idea here is to hash the previous message we received,
+ * and add the one we just received into the handshake_hash_buffer.
+ */
+
+ if ((ret = MHD__gnutls_handshake_hash_pending (session)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* here we buffer the handshake messages - needed at Finished message */
+ if (recv_type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
+ {
+
+ if ((ret =
+ MHD_gtls_handshake_buffer_put (session, header, header_size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (datalen > 0)
+ {
+ if ((ret =
+ MHD_gtls_handshake_buffer_put (session, dataptr, datalen)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* This function will receive handshake messages of the given types,
+ * and will pass the message to the right place in order to be processed.
+ * E.g. for the SERVER_HELLO message (if it is expected), it will be
+ * passed to MHD_gtls_recv_hello().
+ */
+int
+MHD_gtls_recv_handshake (MHD_gtls_session_t session, uint8_t ** data,
+ int *datalen,
+ MHD_gnutls_handshake_description_t type,
+ Optional optional)
+{
+ int ret;
+ uint32_t length32 = 0;
+ opaque *dataptr = NULL;
+ MHD_gnutls_handshake_description_t recv_type;
+
+ ret = MHD__gnutls_recv_handshake_header (session, type, &recv_type);
+ if (ret < 0)
+ {
+
+ if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET
+ && optional == OPTIONAL_PACKET)
+ {
+ if (datalen != NULL)
+ *datalen = 0;
+ if (data != NULL)
+ *data = NULL;
+ return 0; /* ok just ignore the packet */
+ }
+
+ return ret;
+ }
+
+ session->internals.last_handshake_in = recv_type;
+
+ length32 = ret;
+
+ if (length32 > 0)
+ dataptr = MHD_gnutls_malloc (length32);
+ else if (recv_type != GNUTLS_HANDSHAKE_SERVER_HELLO_DONE)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ if (dataptr == NULL && length32 > 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (datalen != NULL)
+ *datalen = length32;
+
+ if (length32 > 0)
+ {
+ ret =
+ MHD_gtls_handshake_io_recv_int (session, GNUTLS_HANDSHAKE,
+ type, dataptr, length32);
+ if (ret <= 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (dataptr);
+ return (ret == 0) ? GNUTLS_E_UNEXPECTED_PACKET_LENGTH : ret;
+ }
+ }
+
+ if (data != NULL && length32 > 0)
+ *data = dataptr;
+
+
+ ret = MHD__gnutls_handshake_hash_add_recvd (session, recv_type,
+ session->internals.
+ handshake_header_buffer.header,
+ session->internals.
+ handshake_header_buffer.header_size,
+ dataptr, length32);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_handshake_header_buffer_clear (session);
+ return ret;
+ }
+
+ /* If we fail before this then we will reuse the handshake header
+ * have have received above. if we get here the we clear the handshake
+ * header we received.
+ */
+ MHD__gnutls_handshake_header_buffer_clear (session);
+
+ switch (recv_type)
+ {
+ case GNUTLS_HANDSHAKE_CLIENT_HELLO:
+ case GNUTLS_HANDSHAKE_SERVER_HELLO:
+ ret = MHD_gtls_recv_hello (session, dataptr, length32);
+ /* dataptr is freed because the caller does not
+ * need it */
+ MHD_gnutls_free (dataptr);
+ if (data != NULL)
+ *data = NULL;
+ break;
+ case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
+ if (length32 == 0)
+ ret = 0;
+ else
+ ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ break;
+ case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
+ case GNUTLS_HANDSHAKE_FINISHED:
+ case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:
+ case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
+ case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
+ case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
+ case GNUTLS_HANDSHAKE_SUPPLEMENTAL:
+ ret = length32;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (dataptr);
+ if (data != NULL)
+ *data = NULL;
+ ret = GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
+ }
+
+ return ret;
+}
+
+#if MHD_DEBUG_TLS
+/* This function checks if the given cipher suite is supported, and sets it
+ * to the session;
+ */
+static int
+MHD__gnutls_client_set_ciphersuite (MHD_gtls_session_t session,
+ opaque suite[2])
+{
+ uint8_t z;
+ cipher_suite_st *cipher_suites;
+ int cipher_suite_num;
+ int i, err;
+
+ z = 1;
+ cipher_suite_num =
+ MHD_gtls_supported_ciphersuites (session, &cipher_suites);
+ if (cipher_suite_num < 0)
+ {
+ MHD_gnutls_assert ();
+ return cipher_suite_num;
+ }
+
+ for (i = 0; i < cipher_suite_num; i++)
+ {
+ if (memcmp (&cipher_suites[i], suite, 2) == 0)
+ {
+ z = 0;
+ break;
+ }
+ }
+
+ MHD_gnutls_free (cipher_suites);
+
+ if (z != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
+ }
+
+ memcpy (session->security_parameters.current_cipher_suite.suite, suite, 2);
+
+ MHD__gnutls_handshake_log ("HSK[%x]: Selected cipher suite: %s\n", session,
+ MHD_gtls_cipher_suite_get_name
+ (&session->security_parameters.
+ current_cipher_suite));
+
+
+ /* check if the credentials (username, public key etc.) are ok.
+ * Actually checks if they exist.
+ */
+ if (MHD_gtls_get_kx_cred
+ (session,
+ MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.current_cipher_suite), &err) == NULL
+ && err != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+
+ /* set the MHD_gtls_mod_auth_st to the appropriate struct
+ * according to the KX algorithm. This is needed since all the
+ * handshake functions are read from there;
+ */
+ session->internals.auth_struct =
+ MHD_gtls_kx_auth_struct (MHD_gtls_cipher_suite_get_kx_algo
+ (&session->security_parameters.
+ current_cipher_suite));
+
+ if (session->internals.auth_struct == NULL)
+ {
+
+ MHD__gnutls_handshake_log
+ ("HSK[%x]: Cannot find the appropriate handler for the KX algorithm\n",
+ session);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+
+ return 0;
+}
+
+
+/* This function sets the given comp method to the session.
+ */
+static int
+MHD__gnutls_client_set_comp_method (MHD_gtls_session_t session,
+ opaque comp_method)
+{
+ int comp_methods_num;
+ uint8_t *compression_methods;
+ int i;
+
+ comp_methods_num = MHD_gtls_supported_compression_methods (session,
+ &compression_methods);
+ if (comp_methods_num < 0)
+ {
+ MHD_gnutls_assert ();
+ return comp_methods_num;
+ }
+
+ for (i = 0; i < comp_methods_num; i++)
+ {
+ if (compression_methods[i] == comp_method)
+ {
+ comp_methods_num = 0;
+ break;
+ }
+ }
+
+ MHD_gnutls_free (compression_methods);
+
+ if (comp_methods_num != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+ }
+
+ session->internals.compression_method =
+ MHD_gtls_compression_get_id_from_int (comp_method);
+
+
+ return 0;
+}
+
+/* This function returns 0 if we are resuming a session or -1 otherwise.
+ * This also sets the variables in the session. Used only while reading a server
+ * hello.
+ */
+static int
+MHD__gnutls_client_check_if_resuming (MHD_gtls_session_t session,
+ opaque * session_id, int session_id_len)
+{
+ opaque buf[2 * TLS_MAX_SESSION_ID_SIZE + 1];
+
+ MHD__gnutls_handshake_log ("HSK[%x]: SessionID length: %d\n", session,
+ session_id_len);
+ MHD__gnutls_handshake_log ("HSK[%x]: SessionID: %s\n", session,
+ MHD_gtls_bin2hex (session_id, session_id_len,
+ (char *) buf, sizeof (buf)));
+
+ if (session_id_len > 0 &&
+ session->internals.resumed_security_parameters.session_id_size ==
+ session_id_len
+ && memcmp (session_id,
+ session->internals.resumed_security_parameters.session_id,
+ session_id_len) == 0)
+ {
+ /* resume session */
+ memcpy (session->internals.resumed_security_parameters.server_random,
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+ memcpy (session->internals.resumed_security_parameters.client_random,
+ session->security_parameters.client_random, TLS_RANDOM_SIZE);
+ session->internals.resumed = RESUME_TRUE; /* we are resuming */
+
+ return 0;
+ }
+ else
+ {
+ /* keep the new session id */
+ session->internals.resumed = RESUME_FALSE; /* we are not resuming */
+ session->security_parameters.session_id_size = session_id_len;
+ memcpy (session->security_parameters.session_id,
+ session_id, session_id_len);
+
+ return -1;
+ }
+}
+
+/* This function reads and parses the server hello handshake message.
+ * This function also restores resumed parameters if we are resuming a
+ * session.
+ */
+static int
+MHD__gnutls_read_server_hello (MHD_gtls_session_t session,
+ opaque * data, int datalen)
+{
+ uint8_t session_id_len = 0;
+ int pos = 0;
+ int ret = 0;
+ enum MHD_GNUTLS_Protocol version;
+ int len = datalen;
+
+ if (datalen < 38)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ MHD__gnutls_handshake_log ("HSK[%x]: Server's version: %d.%d\n",
+ session, data[pos], data[pos + 1]);
+
+ DECR_LEN (len, 2);
+ version = MHD_gtls_version_get (data[pos], data[pos + 1]);
+ if (MHD_gtls_version_is_supported (session, version) == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+ }
+ else
+ {
+ MHD_gtls_set_current_version (session, version);
+ }
+
+ pos += 2;
+
+ DECR_LEN (len, TLS_RANDOM_SIZE);
+ MHD_gtls_set_server_random (session, &data[pos]);
+ pos += TLS_RANDOM_SIZE;
+
+
+ /* Read session ID
+ */
+ DECR_LEN (len, 1);
+ session_id_len = data[pos++];
+
+ if (len < session_id_len)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+ }
+ DECR_LEN (len, session_id_len);
+
+
+ /* check if we are resuming and set the appropriate
+ * values;
+ */
+ if (MHD__gnutls_client_check_if_resuming
+ (session, &data[pos], session_id_len) == 0)
+ return 0;
+ pos += session_id_len;
+
+
+ /* Check if the given cipher suite is supported and copy
+ * it to the session.
+ */
+
+ DECR_LEN (len, 2);
+ ret = MHD__gnutls_client_set_ciphersuite (session, &data[pos]);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ pos += 2;
+
+
+
+ /* move to compression */
+ DECR_LEN (len, 1);
+
+ ret = MHD__gnutls_client_set_comp_method (session, data[pos++]);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
+ }
+
+ /* Parse extensions.
+ */
+ if (version >= MHD_GNUTLS_PROTOCOL_TLS1_0)
+ {
+ ret = MHD_gtls_parse_extensions (session, EXTENSION_ANY, &data[pos], len); /* len is the rest of the parsed length */
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ return ret;
+}
+
+
+/* This function copies the appropriate ciphersuites to a locally allocated buffer
+ * Needed in client hello messages. Returns the new data length.
+ */
+int
+MHD__gnutls_copy_ciphersuites (MHD_gtls_session_t session,
+ opaque * ret_data, size_t ret_data_size)
+{
+ int ret, i;
+ cipher_suite_st *cipher_suites;
+ uint16_t cipher_num;
+ int datalen, pos;
+
+ ret = MHD_gtls_supported_ciphersuites_sorted (session, &cipher_suites);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* Here we remove any ciphersuite that does not conform
+ * the certificate requested, or to the
+ * authentication requested (eg SRP).
+ */
+ ret =
+ MHD_gtls_remove_unwanted_ciphersuites (session, &cipher_suites, ret, -1);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (cipher_suites);
+ return ret;
+ }
+
+ /* If no cipher suites were enabled.
+ */
+ if (ret == 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (cipher_suites);
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ cipher_num = ret;
+
+ cipher_num *= sizeof (uint16_t); /* in order to get bytes */
+
+ datalen = pos = 0;
+
+ datalen += sizeof (uint16_t) + cipher_num;
+
+ if ((size_t) datalen > ret_data_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ MHD_gtls_write_uint16 (cipher_num, ret_data);
+ pos += 2;
+
+ for (i = 0; i < (cipher_num / 2); i++)
+ {
+ memcpy (&ret_data[pos], cipher_suites[i].suite, 2);
+ pos += 2;
+ }
+ MHD_gnutls_free (cipher_suites);
+
+ return datalen;
+}
+
+/* This function copies the appropriate compression methods, to a locally allocated buffer
+ * Needed in hello messages. Returns the new data length.
+ */
+static int
+MHD__gnutls_copy_comp_methods (MHD_gtls_session_t session,
+ opaque * ret_data, size_t ret_data_size)
+{
+ int ret, i;
+ uint8_t *compression_methods, comp_num;
+ int datalen, pos;
+
+ ret =
+ MHD_gtls_supported_compression_methods (session, &compression_methods);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ comp_num = ret;
+
+ datalen = pos = 0;
+ datalen += comp_num + 1;
+
+ if ((size_t) datalen > ret_data_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ret_data[pos++] = comp_num; /* put the number of compression methods */
+
+ for (i = 0; i < comp_num; i++)
+ {
+ ret_data[pos++] = compression_methods[i];
+ }
+
+ MHD_gnutls_free (compression_methods);
+
+ return datalen;
+}
+
+static void
+MHD_gtls_set_adv_version (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_Protocol ver)
+{
+ set_adv_version (session, MHD_gtls_version_get_major (ver),
+ MHD_gtls_version_get_minor (ver));
+}
+
+/* This function sends the client hello handshake message.
+ */
+static int
+MHD__gnutls_send_client_hello (MHD_gtls_session_t session, int again)
+{
+ opaque *data = NULL;
+ int extdatalen;
+ int pos = 0;
+ int datalen = 0, ret = 0;
+ opaque rnd[TLS_RANDOM_SIZE];
+ enum MHD_GNUTLS_Protocol hver;
+ opaque extdata[MAX_EXT_DATA_LENGTH];
+
+ opaque *SessionID =
+ session->internals.resumed_security_parameters.session_id;
+ uint8_t session_id_len =
+ session->internals.resumed_security_parameters.session_id_size;
+
+ if (SessionID == NULL)
+ session_id_len = 0;
+ else if (session_id_len == 0)
+ SessionID = NULL;
+
+ if (again == 0)
+ {
+
+ datalen = 2 + (session_id_len + 1) + TLS_RANDOM_SIZE;
+ /* 2 for version, (4 for unix time + 28 for random bytes==TLS_RANDOM_SIZE)
+ */
+
+ data = MHD_gnutls_malloc (datalen);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* if we are resuming a session then we set the
+ * version number to the previously established.
+ */
+ if (SessionID == NULL)
+ hver = MHD_gtls_version_max (session);
+ else
+ { /* we are resuming a session */
+ hver = session->internals.resumed_security_parameters.version;
+ }
+
+ if (hver == MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN || hver == 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (data);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ data[pos++] = MHD_gtls_version_get_major (hver);
+ data[pos++] = MHD_gtls_version_get_minor (hver);
+
+ /* Set the version we advertized as maximum
+ * (RSA uses it).
+ */
+ MHD_gtls_set_adv_version (session, hver);
+
+ /* Some old implementations do not interoperate if we send a
+ * different version in the record layer.
+ * It seems they prefer to read the record's version
+ * as the one we actually requested.
+ * The proper behaviour is to use the one in the client hello
+ * handshake packet and ignore the one in the packet's record
+ * header.
+ */
+ MHD_gtls_set_current_version (session, hver);
+
+ /* In order to know when this session was initiated.
+ */
+ session->security_parameters.timestamp = time (NULL);
+
+ /* Generate random data
+ */
+ MHD_gtls_tls_create_random (rnd);
+ MHD_gtls_set_client_random (session, rnd);
+
+ memcpy (&data[pos], rnd, TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+
+ /* Copy the Session ID */
+ data[pos++] = session_id_len;
+
+ if (session_id_len > 0)
+ {
+ memcpy (&data[pos], SessionID, session_id_len);
+ pos += session_id_len;
+ }
+
+
+ /* Copy the ciphersuites.
+ */
+ extdatalen =
+ MHD__gnutls_copy_ciphersuites (session, extdata, sizeof (extdata));
+ if (extdatalen > 0)
+ {
+ datalen += extdatalen;
+ data = MHD_gtls_realloc_fast (data, datalen);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy (&data[pos], extdata, extdatalen);
+ pos += extdatalen;
+
+ }
+ else
+ {
+ if (extdatalen == 0)
+ extdatalen = GNUTLS_E_INTERNAL_ERROR;
+ MHD_gnutls_free (data);
+ MHD_gnutls_assert ();
+ return extdatalen;
+ }
+
+
+ /* Copy the compression methods.
+ */
+ extdatalen =
+ MHD__gnutls_copy_comp_methods (session, extdata, sizeof (extdata));
+ if (extdatalen > 0)
+ {
+ datalen += extdatalen;
+ data = MHD_gtls_realloc_fast (data, datalen);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy (&data[pos], extdata, extdatalen);
+ pos += extdatalen;
+
+ }
+ else
+ {
+ if (extdatalen == 0)
+ extdatalen = GNUTLS_E_INTERNAL_ERROR;
+ MHD_gnutls_free (data);
+ MHD_gnutls_assert ();
+ return extdatalen;
+ }
+
+ /* Generate and copy TLS extensions.
+ */
+ if (hver >= MHD_GNUTLS_PROTOCOL_TLS1_0)
+ {
+ extdatalen =
+ MHD_gtls_gen_extensions (session, extdata, sizeof (extdata));
+
+ if (extdatalen > 0)
+ {
+ datalen += extdatalen;
+ data = MHD_gtls_realloc_fast (data, datalen);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy (&data[pos], extdata, extdatalen);
+ }
+ else if (extdatalen < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (data);
+ return extdatalen;
+ }
+ }
+ }
+
+ ret =
+ MHD_gtls_send_handshake (session, data, datalen,
+ GNUTLS_HANDSHAKE_CLIENT_HELLO);
+ MHD_gnutls_free (data);
+
+ return ret;
+}
+#endif
+
+static int
+MHD__gnutls_send_server_hello (MHD_gtls_session_t session, int again)
+{
+ opaque *data = NULL;
+ opaque extdata[MAX_EXT_DATA_LENGTH];
+ int extdatalen;
+ int pos = 0;
+ int datalen, ret = 0;
+ uint8_t comp;
+ opaque *SessionID = session->security_parameters.session_id;
+ uint8_t session_id_len = session->security_parameters.session_id_size;
+ opaque buf[2 * TLS_MAX_SESSION_ID_SIZE + 1];
+
+ if (SessionID == NULL)
+ session_id_len = 0;
+
+ datalen = 0;
+
+ if (again == 0)
+ {
+ datalen = 2 + session_id_len + 1 + TLS_RANDOM_SIZE + 3;
+ extdatalen =
+ MHD_gtls_gen_extensions (session, extdata, sizeof (extdata));
+
+ if (extdatalen < 0)
+ {
+ MHD_gnutls_assert ();
+ return extdatalen;
+ }
+
+ data = MHD_gnutls_alloca (datalen + extdatalen);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ data[pos++] =
+ MHD_gtls_version_get_major (session->security_parameters.version);
+ data[pos++] =
+ MHD_gtls_version_get_minor (session->security_parameters.version);
+
+ memcpy (&data[pos],
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+
+ data[pos++] = session_id_len;
+ if (session_id_len > 0)
+ {
+ memcpy (&data[pos], SessionID, session_id_len);
+ }
+ pos += session_id_len;
+
+ MHD__gnutls_handshake_log ("HSK[%x]: SessionID: %s\n", session,
+ MHD_gtls_bin2hex (SessionID, session_id_len,
+ (char *) buf,
+ sizeof (buf)));
+
+ memcpy (&data[pos],
+ session->security_parameters.current_cipher_suite.suite, 2);
+ pos += 2;
+
+ comp =
+ (uint8_t) MHD_gtls_compression_get_num (session->
+ internals.compression_method);
+ data[pos++] = comp;
+
+
+ if (extdatalen > 0)
+ {
+ datalen += extdatalen;
+
+ memcpy (&data[pos], extdata, extdatalen);
+ }
+ }
+
+ ret =
+ MHD_gtls_send_handshake (session, data, datalen,
+ GNUTLS_HANDSHAKE_SERVER_HELLO);
+ MHD_gnutls_afree (data);
+
+ return ret;
+}
+
+int
+MHD_gtls_send_hello (MHD_gtls_session_t session, int again)
+{
+ int ret;
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ ret = MHD__gnutls_send_client_hello (session, again);
+
+ }
+ else
+#endif
+ { /* SERVER */
+ ret = MHD__gnutls_send_server_hello (session, again);
+ }
+
+ return ret;
+}
+
+/* RECEIVE A HELLO MESSAGE. This should be called from MHD_gnutls_recv_handshake_int only if a
+ * hello message is expected. It uses the security_parameters.current_cipher_suite
+ * and internals.compression_method.
+ */
+int
+MHD_gtls_recv_hello (MHD_gtls_session_t session, opaque * data, int datalen)
+{
+ int ret;
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ ret = MHD__gnutls_read_server_hello (session, data, datalen);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ else
+#endif
+ { /* Server side reading a client hello */
+
+ ret = MHD__gnutls_read_client_hello (session, data, datalen);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+/* The packets in MHD__gnutls_handshake (it's more broad than original TLS handshake)
+ *
+ * Client Server
+ *
+ * ClientHello -------->
+ * <-------- ServerHello
+ *
+ * Certificate*
+ * ServerKeyExchange*
+ * <-------- CertificateRequest*
+ *
+ * <-------- ServerHelloDone
+ * Certificate*
+ * ClientKeyExchange
+ * CertificateVerify*
+ * [ChangeCipherSpec]
+ * Finished -------->
+ * [ChangeCipherSpec]
+ * <-------- Finished
+ *
+ * (*): means optional packet.
+ */
+
+/**
+ * MHD__gnutls_rehandshake - This function will renegotiate security parameters
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function will renegotiate security parameters with the
+ * client. This should only be called in case of a server.
+ *
+ * This message informs the peer that we want to renegotiate
+ * parameters (perform a handshake).
+ *
+ * If this function succeeds (returns 0), you must call the
+ * MHD__gnutls_handshake() function in order to negotiate the new
+ * parameters.
+ *
+ * If the client does not wish to renegotiate parameters he will
+ * should with an alert message, thus the return code will be
+ * %GNUTLS_E_WARNING_ALERT_RECEIVED and the alert will be
+ * %GNUTLS_A_NO_RENEGOTIATION. A client may also choose to ignore
+ * this message.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ *
+ **/
+int
+MHD__gnutls_rehandshake (MHD_gtls_session_t session)
+{
+ int ret;
+
+ ret =
+ MHD__gnutls_send_empty_handshake (session, GNUTLS_HANDSHAKE_HELLO_REQUEST,
+ AGAIN (STATE50));
+ STATE = STATE50;
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ STATE = STATE0;
+
+ return 0;
+}
+
+inline static int
+MHD__gnutls_abort_handshake (MHD_gtls_session_t session, int ret)
+{
+ if (((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) &&
+ (MHD_gnutls_alert_get (session) == GNUTLS_A_NO_RENEGOTIATION))
+ || ret == GNUTLS_E_GOT_APPLICATION_DATA)
+ return 0;
+
+ /* this doesn't matter */
+ return GNUTLS_E_INTERNAL_ERROR;
+}
+
+/* This function initialized the handshake hash session.
+ * required for finished messages.
+ */
+inline static int
+MHD__gnutls_handshake_hash_init (MHD_gtls_session_t session)
+{
+
+ if (session->internals.handshake_mac_handle_md5 == NULL)
+ {
+ session->internals.handshake_mac_handle_md5 =
+ MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
+
+ if (session->internals.handshake_mac_handle_md5 == GNUTLS_HASH_FAILED)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ }
+
+ if (session->internals.handshake_mac_handle_sha == NULL)
+ {
+ session->internals.handshake_mac_handle_sha =
+ MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
+ if (session->internals.handshake_mac_handle_sha == GNUTLS_HASH_FAILED)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ }
+
+ return 0;
+}
+
+static int
+MHD__gnutls_send_supplemental (MHD_gtls_session_t session, int again)
+{
+ int ret = 0;
+
+ MHD__gnutls_debug_log ("EXT[%x]: Sending supplemental data\n", session);
+
+ if (again)
+ ret = MHD_gtls_send_handshake (session, NULL, 0,
+ GNUTLS_HANDSHAKE_SUPPLEMENTAL);
+ else
+ {
+ MHD_gtls_buffer buf;
+ MHD_gtls_buffer_init (&buf);
+
+ ret = MHD__gnutls_gen_supplemental (session, &buf);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD_gtls_send_handshake (session, buf.data, buf.length,
+ GNUTLS_HANDSHAKE_SUPPLEMENTAL);
+ MHD_gtls_buffer_clear (&buf);
+ }
+
+ return ret;
+}
+
+static int
+MHD__gnutls_recv_supplemental (MHD_gtls_session_t session)
+{
+ uint8_t *data = NULL;
+ int datalen = 0;
+ int ret;
+
+ MHD__gnutls_debug_log ("EXT[%x]: Expecting supplemental data\n", session);
+
+ ret = MHD_gtls_recv_handshake (session, &data, &datalen,
+ GNUTLS_HANDSHAKE_SUPPLEMENTAL,
+ OPTIONAL_PACKET);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD__gnutls_parse_supplemental (session, data, datalen);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gnutls_free (data);
+
+ return ret;
+}
+
+/**
+ * MHD__gnutls_handshake - This is the main function in the handshake protocol.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function does the handshake of the TLS/SSL protocol, and
+ * initializes the TLS connection.
+ *
+ * This function will fail if any problem is encountered, and will
+ * return a negative error code. In case of a client, if the client
+ * has asked to resume a session, but the server couldn't, then a
+ * full handshake will be performed.
+ *
+ * The non-fatal errors such as %GNUTLS_E_AGAIN and
+ * %GNUTLS_E_INTERRUPTED interrupt the handshake procedure, which
+ * should be later be resumed. Call this function again, until it
+ * returns 0; cf. MHD__gnutls_record_get_direction() and
+ * MHD_gtls_error_is_fatal().
+ *
+ * If this function is called by a server after a rehandshake request
+ * then %GNUTLS_E_GOT_APPLICATION_DATA or
+ * %GNUTLS_E_WARNING_ALERT_RECEIVED may be returned. Note that these
+ * are non fatal errors, only in the specific case of a rehandshake.
+ * Their meaning is that the client rejected the rehandshake request.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ *
+ **/
+int
+MHD__gnutls_handshake (MHD_gtls_session_t session)
+{
+ int ret;
+
+ if ((ret = MHD__gnutls_handshake_hash_init (session)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+#if MHD_DEBUG_TLS
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ ret = MHD_gtls_handshake_client (session);
+ }
+ else
+#endif
+ {
+ ret = MHD_gtls_handshake_server (session);
+ }
+
+ if (ret < 0)
+ {
+ /* In the case of a rehandshake abort
+ * we should reset the handshake's internal state.
+ */
+ if (MHD__gnutls_abort_handshake (session, ret) == 0)
+ STATE = STATE0;
+
+ return ret;
+ }
+
+ ret = MHD_gtls_handshake_common (session);
+
+ if (ret < 0)
+ {
+ if (MHD__gnutls_abort_handshake (session, ret) == 0)
+ STATE = STATE0;
+
+ return ret;
+ }
+
+ STATE = STATE0;
+
+ MHD__gnutls_handshake_io_buffer_clear (session);
+ MHD_gtls_handshake_internal_state_clear (session);
+
+ return 0;
+}
+
+#define IMED_RET( str, ret) do { \
+ if (ret < 0) { \
+ if (MHD_gtls_error_is_fatal(ret)==0) return ret; \
+ MHD_gnutls_assert(); \
+ ERR( str, ret); \
+ MHD__gnutls_handshake_hash_buffers_clear(session); \
+ return ret; \
+ } } while (0)
+
+
+#if MHD_DEBUG_TLS
+/*
+ * MHD_gtls_handshake_client
+ * This function performs the client side of the handshake of the TLS/SSL protocol.
+ */
+static int
+MHD_gtls_handshake_client (MHD_gtls_session_t session)
+{
+ int ret = 0;
+
+ switch (STATE)
+ {
+ case STATE0:
+ case STATE1:
+ ret = MHD_gtls_send_hello (session, AGAIN (STATE1));
+ STATE = STATE1;
+ IMED_RET ("send hello", ret);
+
+ case STATE2:
+ /* receive the server hello */
+ ret =
+ MHD_gtls_recv_handshake (session, NULL, NULL,
+ GNUTLS_HANDSHAKE_SERVER_HELLO,
+ MANDATORY_PACKET);
+ STATE = STATE2;
+ IMED_RET ("recv hello", ret);
+
+ case STATE70:
+ if (session->security_parameters.extensions.do_recv_supplemental)
+ {
+ ret = MHD__gnutls_recv_supplemental (session);
+ STATE = STATE70;
+ IMED_RET ("recv supplemental", ret);
+ }
+
+ case STATE3:
+ /* RECV CERTIFICATE */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_recv_server_certificate (session);
+ STATE = STATE3;
+ IMED_RET ("recv server certificate", ret);
+
+ case STATE4:
+ /* receive the server key exchange */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_recv_server_kx_message (session);
+ STATE = STATE4;
+ IMED_RET ("recv server kx message", ret);
+
+ case STATE5:
+ /* receive the server certificate request - if any
+ */
+
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_recv_server_certificate_request (session);
+ STATE = STATE5;
+ IMED_RET ("recv server certificate request message", ret);
+
+ case STATE6:
+ /* receive the server hello done */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret =
+ MHD_gtls_recv_handshake (session, NULL, NULL,
+ GNUTLS_HANDSHAKE_SERVER_HELLO_DONE,
+ MANDATORY_PACKET);
+ STATE = STATE6;
+ IMED_RET ("recv server hello done", ret);
+
+ case STATE71:
+ if (session->security_parameters.extensions.do_send_supplemental)
+ {
+ ret = MHD__gnutls_send_supplemental (session, AGAIN (STATE71));
+ STATE = STATE71;
+ IMED_RET ("send supplemental", ret);
+ }
+
+ case STATE7:
+ /* send our certificate - if any and if requested
+ */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_send_client_certificate (session, AGAIN (STATE7));
+ STATE = STATE7;
+ IMED_RET ("send client certificate", ret);
+
+ case STATE8:
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_send_client_kx_message (session, AGAIN (STATE8));
+ STATE = STATE8;
+ IMED_RET ("send client kx", ret);
+
+ case STATE9:
+ /* send client certificate verify */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret =
+ MHD_gtls_send_client_certificate_verify (session, AGAIN (STATE9));
+ STATE = STATE9;
+ IMED_RET ("send client certificate verify", ret);
+
+ STATE = STATE0;
+ default:
+ break;
+ }
+
+
+ return 0;
+}
+#endif
+
+/* This function sends the final handshake packets and initializes connection
+ */
+static int
+MHD__gnutls_send_handshake_final (MHD_gtls_session_t session, int init)
+{
+ int ret = 0;
+
+ /* Send the CHANGE CIPHER SPEC PACKET */
+
+ switch (STATE)
+ {
+ case STATE0:
+ case STATE20:
+ ret = MHD_gtls_send_change_cipher_spec (session, AGAIN (STATE20));
+ STATE = STATE20;
+ if (ret < 0)
+ {
+ ERR ("send ChangeCipherSpec", ret);
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* Initialize the connection session (start encryption) - in case of client
+ */
+ if (init == TRUE)
+ {
+ ret = MHD_gtls_connection_state_init (session);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ ret = MHD_gtls_write_connection_state_init (session);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ case STATE21:
+ /* send the finished message */
+ ret = MHD__gnutls_send_finished (session, AGAIN (STATE21));
+ STATE = STATE21;
+ if (ret < 0)
+ {
+ ERR ("send Finished", ret);
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ STATE = STATE0;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* This function receives the final handshake packets
+ * And executes the appropriate function to initialize the
+ * read session.
+ */
+static int
+MHD__gnutls_recv_handshake_final (MHD_gtls_session_t session, int init)
+{
+ int ret = 0;
+ uint8_t ch;
+
+ switch (STATE)
+ {
+ case STATE0:
+ case STATE30:
+ ret =
+ MHD_gtls_recv_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, &ch, 1);
+ STATE = STATE30;
+ if (ret <= 0)
+ {
+ ERR ("recv ChangeCipherSpec", ret);
+ MHD_gnutls_assert ();
+ return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ /* Initialize the connection session (start encryption) - in case of server */
+ if (init == TRUE)
+ {
+ ret = MHD_gtls_connection_state_init (session);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ ret = MHD_gtls_read_connection_state_init (session);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ case STATE31:
+ ret = MHD__gnutls_recv_finished (session);
+ STATE = STATE31;
+ if (ret < 0)
+ {
+ ERR ("recv finished", ret);
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ STATE = STATE0;
+ default:
+ break;
+ }
+
+
+ return 0;
+}
+
+ /*
+ * MHD_gtls_handshake_server
+ * This function does the server stuff of the handshake protocol.
+ */
+
+static int
+MHD_gtls_handshake_server (MHD_gtls_session_t session)
+{
+ int ret = 0;
+
+ switch (STATE)
+ {
+ case STATE0:
+ case STATE1:
+ ret =
+ MHD_gtls_recv_handshake (session, NULL, NULL,
+ GNUTLS_HANDSHAKE_CLIENT_HELLO,
+ MANDATORY_PACKET);
+ STATE = STATE1;
+ IMED_RET ("recv hello", ret);
+
+ case STATE2:
+ ret = MHD_gtls_send_hello (session, AGAIN (STATE2));
+ STATE = STATE2;
+ IMED_RET ("send hello", ret);
+
+ case STATE70:
+ if (session->security_parameters.extensions.do_send_supplemental)
+ {
+ ret = MHD__gnutls_send_supplemental (session, AGAIN (STATE70));
+ STATE = STATE70;
+ IMED_RET ("send supplemental data", ret);
+ }
+
+ /* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */
+ case STATE3:
+ /* NOTE: these should not be send if we are resuming */
+
+ if (session->internals.resumed == RESUME_FALSE)
+ ret = MHD_gtls_send_server_certificate (session, AGAIN (STATE3));
+ STATE = STATE3;
+ IMED_RET ("send server certificate", ret);
+
+ case STATE4:
+ /* send server key exchange (A) */
+ if (session->internals.resumed == RESUME_FALSE)
+ ret = MHD_gtls_send_server_kx_message (session, AGAIN (STATE4));
+ STATE = STATE4;
+ IMED_RET ("send server kx", ret);
+
+ case STATE5:
+ /* Send certificate request - if requested to */
+ if (session->internals.resumed == RESUME_FALSE)
+ ret =
+ MHD_gtls_send_server_certificate_request (session, AGAIN (STATE5));
+ STATE = STATE5;
+ IMED_RET ("send server cert request", ret);
+
+ case STATE6:
+ /* send the server hello done */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret =
+ MHD__gnutls_send_empty_handshake (session,
+ GNUTLS_HANDSHAKE_SERVER_HELLO_DONE,
+ AGAIN (STATE6));
+ STATE = STATE6;
+ IMED_RET ("send server hello done", ret);
+
+ case STATE71:
+ if (session->security_parameters.extensions.do_recv_supplemental)
+ {
+ ret = MHD__gnutls_recv_supplemental (session);
+ STATE = STATE71;
+ IMED_RET ("recv client supplemental", ret);
+ }
+
+ /* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */
+ case STATE7:
+ /* receive the client certificate message */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_recv_client_certificate (session);
+ STATE = STATE7;
+ IMED_RET ("recv client certificate", ret);
+
+ case STATE8:
+ /* receive the client key exchange message */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_recv_client_kx_message (session);
+ STATE = STATE8;
+ IMED_RET ("recv client kx", ret);
+
+ case STATE9:
+ /* receive the client certificate verify message */
+ if (session->internals.resumed == RESUME_FALSE) /* if we are not resuming */
+ ret = MHD_gtls_recv_client_certificate_verify_message (session);
+ STATE = STATE9;
+ IMED_RET ("recv client certificate verify", ret);
+
+ STATE = STATE0; /* finished thus clear session */
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int
+MHD_gtls_handshake_common (MHD_gtls_session_t session)
+{
+ int ret = 0;
+
+ /* send and recv the change cipher spec and finished messages */
+ if ((session->internals.resumed == RESUME_TRUE
+ && session->security_parameters.entity == GNUTLS_CLIENT)
+ || (session->internals.resumed == RESUME_FALSE
+ && session->security_parameters.entity == GNUTLS_SERVER))
+ {
+ /* if we are a client resuming - or we are a server not resuming */
+
+ ret = MHD__gnutls_recv_handshake_final (session, TRUE);
+ IMED_RET ("recv handshake final", ret);
+
+ ret = MHD__gnutls_send_handshake_final (session, FALSE);
+ IMED_RET ("send handshake final", ret);
+ }
+ else
+ { /* if we are a client not resuming - or we are a server resuming */
+
+ ret = MHD__gnutls_send_handshake_final (session, TRUE);
+ IMED_RET ("send handshake final 2", ret);
+
+ ret = MHD__gnutls_recv_handshake_final (session, FALSE);
+ IMED_RET ("recv handshake final 2", ret);
+ }
+
+ /* clear handshake buffer */
+ MHD__gnutls_handshake_hash_buffers_clear (session);
+ return ret;
+
+}
+
+static int
+MHD_gtls_generate_session_id (opaque * session_id, uint8_t * len)
+{
+ *len = TLS_MAX_SESSION_ID_SIZE;
+
+ if (MHD_gc_nonce ((char *) session_id, *len) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+
+ return 0;
+}
+
+int
+MHD_gtls_recv_hello_request (MHD_gtls_session_t session, void *data,
+ uint32_t data_size)
+{
+ uint8_t type;
+
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET;
+ }
+ if (data_size < 1)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ type = ((uint8_t *) data)[0];
+ if (type == GNUTLS_HANDSHAKE_HELLO_REQUEST)
+ return GNUTLS_E_REHANDSHAKE;
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET;
+ }
+}
+
+/* Returns 1 if the given KX has not the corresponding parameters
+ * (DH or RSA) set up. Otherwise returns 0.
+ */
+inline static int
+check_server_params (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm *alg, int alg_size)
+{
+ int cred_type;
+ MHD_gtls_dh_params_t dh_params = NULL;
+ MHD_gtls_rsa_params_t rsa_params = NULL;
+ int j;
+
+ cred_type = MHD_gtls_map_kx_get_cred (kx, 1);
+
+ /* Read the Diffie Hellman parameters, if any.
+ */
+ if (cred_type == MHD_GNUTLS_CRD_CERTIFICATE)
+ {
+ int delete;
+ MHD_gtls_cert_credentials_t x509_cred =
+ (MHD_gtls_cert_credentials_t) MHD_gtls_get_cred (session->key,
+ cred_type, NULL);
+
+ if (x509_cred != NULL)
+ {
+ dh_params =
+ MHD_gtls_get_dh_params (x509_cred->dh_params,
+ x509_cred->params_func, session);
+ rsa_params =
+ MHD_gtls_certificate_get_rsa_params (x509_cred->rsa_params,
+ x509_cred->params_func,
+ session);
+ }
+
+ /* Check also if the certificate supports the
+ * KX method.
+ */
+ delete = 1;
+ for (j = 0; j < alg_size; j++)
+ {
+ if (alg[j] == kx)
+ {
+ delete = 0;
+ break;
+ }
+ }
+
+ if (delete == 1)
+ return 1;
+
+ }
+ else
+ return 0; /* no need for params */
+
+
+ /* If the key exchange method needs RSA or DH params,
+ * but they are not set then remove it.
+ */
+ if (MHD_gtls_kx_needs_rsa_params (kx) != 0)
+ {
+ /* needs rsa params. */
+ if (MHD__gnutls_rsa_params_to_mpi (rsa_params) == NULL)
+ {
+ MHD_gnutls_assert ();
+ return 1;
+ }
+ }
+
+ if (MHD_gtls_kx_needs_dh_params (kx) != 0)
+ {
+ /* needs DH params. */
+ if (MHD_gtls_dh_params_to_mpi (dh_params) == NULL)
+ {
+ MHD_gnutls_assert ();
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* This function will remove algorithms that are not supported by
+ * the requested authentication method. We remove an algorithm if
+ * we have a certificate with keyUsage bits set.
+ *
+ * This does a more high level check than MHD_gnutls_supported_ciphersuites(),
+ * by checking certificates etc.
+ */
+static int
+MHD_gtls_remove_unwanted_ciphersuites (MHD_gtls_session_t session,
+ cipher_suite_st ** cipherSuites,
+ int numCipherSuites,
+ enum MHD_GNUTLS_PublicKeyAlgorithm
+ requested_pk_algo)
+{
+
+ int ret = 0;
+ cipher_suite_st *newSuite, cs;
+ int newSuiteSize = 0, i;
+ MHD_gtls_cert_credentials_t cert_cred;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx;
+ int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm *alg = NULL;
+ int alg_size = 0;
+
+ /* if we should use a specific certificate,
+ * we should remove all algorithms that are not supported
+ * by that certificate and are on the same authentication
+ * method (CERTIFICATE).
+ */
+
+ cert_cred =
+ (MHD_gtls_cert_credentials_t) MHD_gtls_get_cred (session->key,
+ MHD_GNUTLS_CRD_CERTIFICATE,
+ NULL);
+
+ /* If there are certificate credentials, find an appropriate certificate
+ * or disable them;
+ */
+ if (session->security_parameters.entity == GNUTLS_SERVER
+ && cert_cred != NULL)
+ {
+ ret = MHD_gtls_server_select_cert (session, requested_pk_algo);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_x509_log
+ ("Could not find an appropriate certificate: %s\n",
+ MHD_gtls_strerror (ret));
+ cert_cred = NULL;
+ }
+ }
+
+ /* get all the key exchange algorithms that are
+ * supported by the X509 certificate parameters.
+ */
+ if ((ret =
+ MHD_gtls_selected_cert_supported_kx (session, &alg, &alg_size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ newSuite = MHD_gnutls_malloc (numCipherSuites * sizeof (cipher_suite_st));
+ if (newSuite == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (alg);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* now removes ciphersuites based on the KX algorithm
+ */
+ for (i = 0; i < numCipherSuites; i++)
+ {
+ int delete = 0;
+
+ /* finds the key exchange algorithm in
+ * the ciphersuite
+ */
+ kx = MHD_gtls_cipher_suite_get_kx_algo (&(*cipherSuites)[i]);
+
+ /* if it is defined but had no credentials
+ */
+ if (MHD_gtls_get_kx_cred (session, kx, NULL) == NULL)
+ {
+ delete = 1;
+ }
+ else
+ {
+ delete = 0;
+
+ if (server)
+ delete = check_server_params (session, kx, alg, alg_size);
+ }
+ memcpy (&cs.suite, &(*cipherSuites)[i].suite, 2);
+
+ if (delete == 0)
+ {
+
+ MHD__gnutls_handshake_log ("HSK[%x]: Keeping ciphersuite: %s\n",
+ session,
+ MHD_gtls_cipher_suite_get_name (&cs));
+
+ memcpy (newSuite[newSuiteSize].suite, (*cipherSuites)[i].suite, 2);
+ newSuiteSize++;
+ }
+ else
+ {
+ MHD__gnutls_handshake_log ("HSK[%x]: Removing ciphersuite: %s\n",
+ session,
+ MHD_gtls_cipher_suite_get_name (&cs));
+
+ }
+ }
+
+ MHD_gnutls_free (alg);
+ MHD_gnutls_free (*cipherSuites);
+ *cipherSuites = newSuite;
+
+ ret = newSuiteSize;
+
+ return ret;
+
+}
+
+enum MHD_GNUTLS_Protocol
+MHD_gtls_get_adv_version (MHD_gtls_session_t session)
+{
+ return MHD_gtls_version_get (MHD__gnutls_get_adv_version_major (session),
+ MHD__gnutls_get_adv_version_minor (session));
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.h
new file mode 100644
index 0000000000..58c95a84fe
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_handshake.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+typedef enum Optional
+{ OPTIONAL_PACKET, MANDATORY_PACKET } Optional;
+
+int MHD_gtls_send_handshake (MHD_gtls_session_t session, void *i_data,
+ uint32_t i_datasize,
+ MHD_gnutls_handshake_description_t type);
+int MHD_gtls_recv_hello_request (MHD_gtls_session_t session, void *data,
+ uint32_t data_size);
+int MHD_gtls_send_hello (MHD_gtls_session_t session, int again);
+int MHD_gtls_recv_hello (MHD_gtls_session_t session, opaque * data,
+ int datalen);
+int MHD_gtls_recv_handshake (MHD_gtls_session_t session, uint8_t **, int *,
+ MHD_gnutls_handshake_description_t,
+ Optional optional);
+void
+MHD__gnutls_handshake_set_max_packet_length (MHD_gtls_session_t session,
+ size_t max);
+
+#define STATE session->internals.handshake_state
+/* This returns true if we have got there
+ * before (and not finished due to an interrupt).
+ */
+#define AGAIN(target) STATE==target?1:0
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.c
new file mode 100644
index 0000000000..cc61203d11
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2000, 2001, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file handles all the internal functions that cope with hashes
+ * and HMACs.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_hash_int.h>
+#include <gnutls_errors.h>
+
+static inline Gc_hash
+MHD__gnutls_mac2gc (enum MHD_GNUTLS_HashAlgorithm mac)
+{
+ switch (mac)
+ {
+ case MHD_GNUTLS_MAC_NULL:
+ return -1;
+ break;
+ case MHD_GNUTLS_MAC_SHA1:
+ return GC_SHA1;
+ break;
+ case MHD_GNUTLS_MAC_SHA256:
+ return GC_SHA256;
+ break;
+ case MHD_GNUTLS_MAC_MD5:
+ return GC_MD5;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return -1;
+ }
+ return -1;
+}
+
+GNUTLS_HASH_HANDLE
+MHD_gtls_hash_init (enum MHD_GNUTLS_HashAlgorithm algorithm)
+{
+ mac_hd_t ret;
+ int result;
+
+ ret = MHD_gnutls_malloc (sizeof (mac_hd_st));
+ if (ret == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_HASH_FAILED;
+ }
+
+ ret->algorithm = algorithm;
+
+ result = MHD_gc_hash_open (MHD__gnutls_mac2gc (algorithm), 0, &ret->handle);
+ if (result)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (ret);
+ ret = GNUTLS_HASH_FAILED;
+ }
+
+ return ret;
+}
+
+int
+MHD_gnutls_hash_get_algo_len (enum MHD_GNUTLS_HashAlgorithm algorithm)
+{
+ int ret;
+
+ ret = MHD_gc_hash_digest_length (MHD__gnutls_mac2gc (algorithm));
+
+ return ret;
+
+}
+
+int
+MHD_gnutls_hash (GNUTLS_HASH_HANDLE handle, const void *text, size_t textlen)
+{
+ if (textlen > 0)
+ MHD_gc_hash_write (handle->handle, textlen, text);
+ return 0;
+}
+
+GNUTLS_HASH_HANDLE
+MHD_gnutls_hash_copy (GNUTLS_HASH_HANDLE handle)
+{
+ GNUTLS_HASH_HANDLE ret;
+ int result;
+
+ ret = MHD_gnutls_malloc (sizeof (mac_hd_st));
+
+ if (ret == NULL)
+ return GNUTLS_HASH_FAILED;
+
+ ret->algorithm = handle->algorithm;
+ ret->key = NULL; /* it's a hash anyway */
+ ret->keysize = 0;
+
+ result = MHD_gc_hash_clone (handle->handle, &ret->handle);
+
+ if (result)
+ {
+ MHD_gnutls_free (ret);
+ return GNUTLS_HASH_FAILED;
+ }
+
+ return ret;
+}
+
+void
+MHD_gnutls_hash_deinit (GNUTLS_HASH_HANDLE handle, void *digest)
+{
+ const opaque *mac;
+ int maclen;
+
+ maclen = MHD_gnutls_hash_get_algo_len (handle->algorithm);
+
+ mac = (unsigned char *) MHD_gc_hash_read (handle->handle);
+ if (digest != NULL)
+ memcpy (digest, mac, maclen);
+
+ MHD_gc_hash_close (handle->handle);
+
+ MHD_gnutls_free (handle);
+}
+
+
+mac_hd_t
+MHD_gtls_MHD_hmac_init (enum MHD_GNUTLS_HashAlgorithm algorithm,
+ const void *key, int keylen)
+{
+ mac_hd_t ret;
+ int result;
+
+ ret = MHD_gnutls_malloc (sizeof (mac_hd_st));
+ if (ret == NULL)
+ return GNUTLS_MAC_FAILED;
+
+ result =
+ MHD_gc_hash_open (MHD__gnutls_mac2gc (algorithm), GC_HMAC, &ret->handle);
+ if (result)
+ {
+ MHD_gnutls_free (ret);
+ return GNUTLS_MAC_FAILED;
+ }
+
+ MHD_gc_hash_MHD_hmac_setkey (ret->handle, keylen, key);
+
+ ret->algorithm = algorithm;
+ ret->key = key;
+ ret->keysize = keylen;
+
+ return ret;
+}
+
+void
+MHD_gnutls_MHD_hmac_deinit (mac_hd_t handle, void *digest)
+{
+ const opaque *mac;
+ int maclen;
+
+ maclen = MHD_gnutls_hash_get_algo_len (handle->algorithm);
+
+ mac = (unsigned char *) MHD_gc_hash_read (handle->handle);
+
+ if (digest != NULL)
+ memcpy (digest, mac, maclen);
+
+ MHD_gc_hash_close (handle->handle);
+
+ MHD_gnutls_free (handle);
+}
+
+inline static int
+get_padsize (enum MHD_GNUTLS_HashAlgorithm algorithm)
+{
+ switch (algorithm)
+ {
+ case MHD_GNUTLS_MAC_MD5:
+ return 48;
+ case MHD_GNUTLS_MAC_SHA1:
+ return 40;
+ default:
+ return 0;
+ }
+}
+
+mac_hd_t
+MHD_gnutls_mac_init_ssl3 (enum MHD_GNUTLS_HashAlgorithm algorithm, void *key,
+ int keylen)
+{
+ mac_hd_t ret;
+ opaque ipad[48];
+ int padsize;
+
+ padsize = get_padsize (algorithm);
+ if (padsize == 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_MAC_FAILED;
+ }
+
+ memset (ipad, 0x36, padsize);
+
+ ret = MHD_gtls_hash_init (algorithm);
+ if (ret != GNUTLS_HASH_FAILED)
+ {
+ ret->key = key;
+ ret->keysize = keylen;
+
+ if (keylen > 0)
+ MHD_gnutls_hash (ret, key, keylen);
+ MHD_gnutls_hash (ret, ipad, padsize);
+ }
+
+ return ret;
+}
+
+void
+MHD_gnutls_mac_deinit_ssl3 (mac_hd_t handle, void *digest)
+{
+ opaque ret[MAX_HASH_SIZE];
+ mac_hd_t td;
+ opaque opad[48];
+ int padsize;
+ int block;
+
+ padsize = get_padsize (handle->algorithm);
+ if (padsize == 0)
+ {
+ MHD_gnutls_assert ();
+ return;
+ }
+
+ memset (opad, 0x5C, padsize);
+
+ td = MHD_gtls_hash_init (handle->algorithm);
+ if (td != GNUTLS_MAC_FAILED)
+ {
+ if (handle->keysize > 0)
+ MHD_gnutls_hash (td, handle->key, handle->keysize);
+
+ MHD_gnutls_hash (td, opad, padsize);
+ block = MHD_gnutls_hash_get_algo_len (handle->algorithm);
+ MHD_gnutls_hash_deinit (handle, ret); /* get the previous hash */
+ MHD_gnutls_hash (td, ret, block);
+
+ MHD_gnutls_hash_deinit (td, digest);
+ }
+}
+
+void
+MHD_gnutls_mac_deinit_ssl3_handshake (mac_hd_t handle,
+ void *digest, opaque * key,
+ uint32_t key_size)
+{
+ opaque ret[MAX_HASH_SIZE];
+ mac_hd_t td;
+ opaque opad[48];
+ opaque ipad[48];
+ int padsize;
+ int block;
+
+ padsize = get_padsize (handle->algorithm);
+ if (padsize == 0)
+ {
+ MHD_gnutls_assert ();
+ return;
+ }
+
+ memset (opad, 0x5C, padsize);
+ memset (ipad, 0x36, padsize);
+
+ td = MHD_gtls_hash_init (handle->algorithm);
+ if (td != GNUTLS_HASH_FAILED)
+ {
+ if (key_size > 0)
+ MHD_gnutls_hash (td, key, key_size);
+
+ MHD_gnutls_hash (td, opad, padsize);
+ block = MHD_gnutls_hash_get_algo_len (handle->algorithm);
+
+ if (key_size > 0)
+ MHD_gnutls_hash (handle, key, key_size);
+ MHD_gnutls_hash (handle, ipad, padsize);
+ MHD_gnutls_hash_deinit (handle, ret); /* get the previous hash */
+
+ MHD_gnutls_hash (td, ret, block);
+
+ MHD_gnutls_hash_deinit (td, digest);
+ }
+}
+
+static int
+ssl3_sha (int i, opaque * secret, int secret_len,
+ opaque * rnd, int rnd_len, void *digest)
+{
+ int j;
+ opaque text1[26];
+
+ GNUTLS_HASH_HANDLE td;
+
+ for (j = 0; j < i + 1; j++)
+ {
+ text1[j] = 65 + i; /* A==65 */
+ }
+
+ td = MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
+ if (td == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td, text1, i + 1);
+ MHD_gnutls_hash (td, secret, secret_len);
+ MHD_gnutls_hash (td, rnd, rnd_len);
+
+ MHD_gnutls_hash_deinit (td, digest);
+ return 0;
+}
+
+static int
+ssl3_md5 (int i, opaque * secret, int secret_len,
+ opaque * rnd, int rnd_len, void *digest)
+{
+ opaque tmp[MAX_HASH_SIZE];
+ mac_hd_t td;
+ int ret;
+
+ td = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
+ if (td == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td, secret, secret_len);
+
+ ret = ssl3_sha (i, secret, secret_len, rnd, rnd_len, tmp);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_hash_deinit (td, digest);
+ return ret;
+ }
+
+ MHD_gnutls_hash (td, tmp,
+ MHD_gnutls_hash_get_algo_len (MHD_GNUTLS_MAC_SHA1));
+
+ MHD_gnutls_hash_deinit (td, digest);
+ return 0;
+}
+
+int
+MHD_gnutls_ssl3_hash_md5 (void *first, int first_len,
+ void *second, int second_len, int ret_len,
+ opaque * ret)
+{
+ opaque digest[MAX_HASH_SIZE];
+ mac_hd_t td;
+ int block = MHD_gnutls_hash_get_algo_len (MHD_GNUTLS_MAC_MD5);
+
+ td = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
+ if (td == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td, first, first_len);
+ MHD_gnutls_hash (td, second, second_len);
+
+ MHD_gnutls_hash_deinit (td, digest);
+
+ if (ret_len > block)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ memcpy (ret, digest, ret_len);
+
+ return 0;
+
+}
+
+int
+MHD_gnutls_ssl3_generate_random (void *secret, int secret_len,
+ void *rnd, int rnd_len,
+ int ret_bytes, opaque * ret)
+{
+ int i = 0, copy, output_bytes;
+ opaque digest[MAX_HASH_SIZE];
+ int block = MHD_gnutls_hash_get_algo_len (MHD_GNUTLS_MAC_MD5);
+ int result, times;
+
+ output_bytes = 0;
+ do
+ {
+ output_bytes += block;
+ }
+ while (output_bytes < ret_bytes);
+
+ times = output_bytes / block;
+
+ for (i = 0; i < times; i++)
+ {
+
+ result = ssl3_md5 (i, secret, secret_len, rnd, rnd_len, digest);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ if ((1 + i) * block < ret_bytes)
+ {
+ copy = block;
+ }
+ else
+ {
+ copy = ret_bytes - (i) * block;
+ }
+
+ memcpy (&ret[i * block], digest, copy);
+ }
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.h
new file mode 100644
index 0000000000..bd3dec2987
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_hash_int.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_HASH_INT_H
+# define GNUTLS_HASH_INT_H
+
+#include <gnutls_int.h>
+
+/* for message digests */
+
+typedef struct
+{
+ MHD_gc_hash_handle handle;
+ enum MHD_GNUTLS_HashAlgorithm algorithm;
+ const void *key;
+ int keysize;
+} mac_hd_st;
+typedef mac_hd_st *mac_hd_t;
+typedef mac_hd_t GNUTLS_HASH_HANDLE;
+
+#define GNUTLS_HASH_FAILED NULL
+#define GNUTLS_MAC_FAILED NULL
+
+mac_hd_t MHD_gtls_MHD_hmac_init (enum MHD_GNUTLS_HashAlgorithm algorithm,
+ const void *key, int keylen);
+
+void MHD_gnutls_MHD_hmac_deinit (mac_hd_t handle, void *digest);
+
+mac_hd_t MHD_gnutls_mac_init_ssl3 (enum MHD_GNUTLS_HashAlgorithm algorithm,
+ void *key, int keylen);
+void MHD_gnutls_mac_deinit_ssl3 (mac_hd_t handle, void *digest);
+
+GNUTLS_HASH_HANDLE MHD_gtls_hash_init (enum MHD_GNUTLS_HashAlgorithm
+ algorithm);
+int MHD_gnutls_hash_get_algo_len (enum MHD_GNUTLS_HashAlgorithm algorithm);
+int MHD_gnutls_hash (GNUTLS_HASH_HANDLE handle, const void *text,
+ size_t textlen);
+void MHD_gnutls_hash_deinit (GNUTLS_HASH_HANDLE handle, void *digest);
+
+int MHD_gnutls_ssl3_generate_random (void *secret, int secret_len,
+ void *rnd, int random_len, int bytes,
+ opaque * ret);
+int MHD_gnutls_ssl3_hash_md5 (void *first, int first_len, void *second,
+ int second_len, int ret_len, opaque * ret);
+
+void MHD_gnutls_mac_deinit_ssl3_handshake (mac_hd_t handle, void *digest,
+ opaque * key, uint32_t key_size);
+
+GNUTLS_HASH_HANDLE MHD_gnutls_hash_copy (GNUTLS_HASH_HANDLE handle);
+
+#endif /* GNUTLS_HASH_INT_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_int.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_int.h
new file mode 100644
index 0000000000..25a861ed21
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_int.h
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_INT_H
+#define GNUTLS_INT_H
+
+#include <defines.h>
+
+#include "gnutls.h"
+#include "microhttpd.h"
+
+#include "gnutls_mem.h"
+
+/* FIXME: delete this once opencdk has reentrant keyring functions
+ */
+#define KEYRING_HACK
+
+#ifndef MAX
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+#endif
+
+#define MAX32 4294967295
+#define MAX24 16777215
+#define MAX16 65535
+
+/* The size of a handshake message should not
+ * be larger than this value.
+ */
+#define MAX_HANDSHAKE_PACKET_SIZE 48*1024
+
+#define TLS_RANDOM_SIZE 32
+#define TLS_MAX_SESSION_ID_SIZE 32
+#define TLS_MASTER_SIZE 48
+
+/* The maximum digest size of hash algorithms.
+ */
+#define MAX_HASH_SIZE 64
+
+#define MAX_LOG_SIZE 1024 /* maximum size of log message */
+#define MAX_SERVER_NAME_SIZE 128
+
+/* we can receive up to MAX_EXT_TYPES extensions.
+ */
+#define MAX_EXT_TYPES 64
+
+/* The initial size of the receive
+ * buffer size. This will grow if larger
+ * packets are received.
+ */
+#define INITIAL_RECV_BUFFER_SIZE 256
+
+/* the default for TCP */
+#define DEFAULT_LOWAT 1
+
+/* expire time for resuming sessions */
+#define DEFAULT_EXPIRE_TIME 3600
+
+/* the maximum size of encrypted packets */
+#define DEFAULT_MAX_RECORD_SIZE 16384
+#define RECORD_HEADER_SIZE 5
+#define MAX_RECORD_SEND_SIZE (size_t)session->security_parameters.max_record_send_size
+#define MAX_RECORD_RECV_SIZE (size_t)session->security_parameters.max_record_recv_size
+#define MAX_PAD_SIZE 255
+#define EXTRA_COMP_SIZE 2048
+#define MAX_RECORD_OVERHEAD MAX_PAD_SIZE+EXTRA_COMP_SIZE
+#define MAX_RECV_SIZE MAX_RECORD_OVERHEAD+MAX_RECORD_RECV_SIZE+RECORD_HEADER_SIZE
+
+#define HANDSHAKE_HEADER_SIZE 4
+
+/* defaults for verification functions
+ */
+#define DEFAULT_VERIFY_DEPTH 32
+#define DEFAULT_VERIFY_BITS 16*1024
+
+#define DECR_LEN(len, x) do { len-=x; if (len<0) {MHD_gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} } while (0)
+#define DECR_LENGTH_RET(len, x, RET) do { len-=x; if (len<0) {MHD_gnutls_assert(); return RET;} } while (0)
+#define DECR_LENGTH_COM(len, x, COM) do { len-=x; if (len<0) {MHD_gnutls_assert(); COM;} } while (0)
+
+#define HASH2MAC(x) ((enum MHD_GNUTLS_HashAlgorithm)x)
+
+/* TODO rm */
+/* Additional cast to bring void* to a type castable to int. */
+#define GNUTLS_POINTER_TO_INT_CAST (long)
+
+#define GNUTLS_POINTER_TO_INT(_) ((int) GNUTLS_POINTER_TO_INT_CAST (_))
+#define GNUTLS_INT_TO_POINTER(_) ((void*) GNUTLS_POINTER_TO_INT_CAST (_))
+
+typedef unsigned char opaque;
+typedef struct
+{
+ opaque pint[3];
+} uint24;
+
+#include <gnutls_mpi.h>
+
+typedef enum change_cipher_spec_t
+{
+ GNUTLS_TYPE_CHANGE_CIPHER_SPEC = 1
+} change_cipher_spec_t;
+
+typedef enum handshake_state_t
+{
+ STATE0 = 0, STATE1, STATE2,
+ STATE3, STATE4, STATE5,
+ STATE6, STATE7, STATE8, STATE9, STATE20 = 20, STATE21,
+ STATE30 = 30, STATE31, STATE50 = 50, STATE60 = 60, STATE61, STATE62,
+ STATE70, STATE71
+} handshake_state_t;
+
+#include <gnutls_str.h>
+
+typedef MHD_gtls_string MHD_gtls_buffer;
+
+#define MHD_gtls_buffer_init(buf) MHD_gtls_string_init(buf, MHD_gnutls_malloc, MHD_gnutls_realloc, MHD_gnutls_free);
+#define MHD_gtls_buffer_clear MHD_gtls_string_clear
+#define MHD_gtls_buffer_append MHD_gtls_string_append_data
+
+/* This is the maximum number of algorithms (ciphers or macs etc).
+ * keep it synced with GNUTLS_MAX_ALGORITHM_NUM in gnutls.h
+ */
+#define MAX_ALGOS 16
+
+#define MAX_CIPHERSUITES 256
+
+typedef enum extensions_t
+{ GNUTLS_EXTENSION_SERVER_NAME = 0,
+ GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1,
+ GNUTLS_EXTENSION_CERT_TYPE = 9,
+ GNUTLS_EXTENSION_SRP = 12,
+ GNUTLS_EXTENSION_INNER_APPLICATION = 37703
+} extensions_t;
+
+typedef enum
+{ CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;
+
+typedef enum valid_session_t
+{ VALID_TRUE, VALID_FALSE } valid_session_t;
+typedef enum resumable_session_t
+{ RESUME_TRUE,
+ RESUME_FALSE
+} resumable_session_t;
+
+/* Record Protocol */
+typedef enum content_type_t
+{
+ GNUTLS_CHANGE_CIPHER_SPEC = 20, GNUTLS_ALERT,
+ GNUTLS_HANDSHAKE, GNUTLS_APPLICATION_DATA,
+ GNUTLS_INNER_APPLICATION = 24
+} content_type_t;
+
+#define GNUTLS_PK_ANY (enum MHD_GNUTLS_PublicKeyAlgorithm)-1
+#define GNUTLS_PK_NONE (enum MHD_GNUTLS_PublicKeyAlgorithm)-2
+
+/* STATE (stop) */
+
+typedef void (*LOG_FUNC) (int, const char *);
+
+/* Store & Retrieve functions defines: */
+typedef struct MHD_gtls_auth_cred_st
+{
+ enum MHD_GNUTLS_CredentialsType algorithm;
+
+ /* the type of credentials depends on algorithm
+ */
+ void *credentials;
+ struct MHD_gtls_auth_cred_st *next;
+} auth_cred_st;
+
+struct MHD_gtls_key
+{
+ /* For DH KX */
+ MHD_gnutls_datum_t key;
+ mpi_t KEY;
+ mpi_t client_Y;
+ mpi_t client_g;
+ mpi_t client_p;
+ mpi_t dh_secret;
+ /* for SRP */
+ mpi_t A;
+ mpi_t B;
+ mpi_t u;
+ mpi_t b;
+ mpi_t a;
+ mpi_t x;
+ /* RSA: e, m
+ */
+ mpi_t rsa[2];
+
+ /* this is used to hold the peers authentication data
+ */
+ /* auth_info_t structures SHOULD NOT contain malloced
+ * elements. Check MHD_gnutls_session_pack.c, and MHD_gnutls_auth.c.
+ * Rememember that this should be calloced!
+ */
+ void *auth_info;
+ enum MHD_GNUTLS_CredentialsType auth_info_type;
+ int auth_info_size; /* needed in order to store to db for restoring
+ */
+ uint8_t crypt_algo;
+
+ auth_cred_st *cred; /* used to specify keys/certificates etc */
+
+ int certificate_requested;
+ /* some ciphersuites use this
+ * to provide client authentication.
+ * 1 if client auth was requested
+ * by the peer, 0 otherwise
+ *** In case of a server this
+ * holds 1 if we should wait
+ * for a client certificate verify
+ */
+};
+typedef struct MHD_gtls_key *MHD_gtls_key_st;
+
+/* STATE (cont) */
+#include <gnutls_hash_int.h>
+#include <gnutls_cipher_int.h>
+#include <gnutls_cert.h>
+
+typedef struct
+{
+ uint8_t suite[2];
+} cipher_suite_st;
+
+/* This structure holds parameters got from TLS extension
+ * mechanism. (some extensions may hold parameters in auth_info_t
+ * structures also - see SRP).
+ */
+typedef struct
+{
+ opaque name[MAX_SERVER_NAME_SIZE];
+ unsigned name_length;
+ MHD_gnutls_server_name_type_t type;
+} server_name_st;
+
+#define MAX_SERVER_NAME_EXTENSIONS 3
+typedef struct
+{
+ server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS];
+ /* limit server_name extensions */
+ unsigned server_names_size;
+
+ /* TLS/IA data. */
+ int MHD_gnutls_ia_enable, MHD_gnutls_ia_peer_enable;
+ int MHD_gnutls_ia_allowskip, MHD_gnutls_ia_peer_allowskip;
+
+ /* Used by extensions that enable supplemental data. */
+ int do_recv_supplemental, do_send_supplemental;
+
+} MHD_gtls_ext_st;
+
+/* This flag indicates for an extension whether
+ * it is useful to application level or TLS level only.
+ * This is used to parse the application level extensions
+ * before the user_hello callback is called.
+ */
+typedef enum tls_ext_parse_type_t
+{
+ EXTENSION_ANY,
+ EXTENSION_APPLICATION,
+ EXTENSION_TLS
+} MHD_gtls_ext_parse_type_t;
+
+/* auth_info_t structures now MAY contain malloced
+ * elements.
+ */
+
+/* This structure and auth_info_t, are stored in the resume database,
+ * and are restored, in case of resume.
+ * Holds all the required parameters to resume the current
+ * session.
+ */
+
+/* if you add anything in Security_Parameters struct, then
+ * also modify CPY_COMMON in MHD_gnutls_constate.c
+ */
+
+/* Note that the security parameters structure is set up after the
+ * handshake has finished. The only value you may depend on while
+ * the handshake is in progress is the cipher suite value.
+ */
+typedef struct
+{
+ MHD_gnutls_connection_end_t entity;
+ enum MHD_GNUTLS_KeyExchangeAlgorithm kx_algorithm;
+ /* we've got separate write/read bulk/macs because
+ * there is a time in handshake where the peer has
+ * null cipher and we don't
+ */
+ enum MHD_GNUTLS_CipherAlgorithm read_bulk_cipher_algorithm;
+ enum MHD_GNUTLS_HashAlgorithm read_mac_algorithm;
+ enum MHD_GNUTLS_CompressionMethod read_compression_algorithm;
+
+ enum MHD_GNUTLS_CipherAlgorithm write_bulk_cipher_algorithm;
+ enum MHD_GNUTLS_HashAlgorithm write_mac_algorithm;
+ enum MHD_GNUTLS_CompressionMethod write_compression_algorithm;
+
+ /* this is the ciphersuite we are going to use
+ * moved here from internals in order to be restored
+ * on resume;
+ */
+ cipher_suite_st current_cipher_suite;
+ opaque master_secret[TLS_MASTER_SIZE];
+ opaque client_random[TLS_RANDOM_SIZE];
+ opaque server_random[TLS_RANDOM_SIZE];
+ opaque session_id[TLS_MAX_SESSION_ID_SIZE];
+ uint8_t session_id_size;
+ time_t timestamp;
+ MHD_gtls_ext_st extensions;
+
+ /* The send size is the one requested by the programmer.
+ * The recv size is the one negotiated with the peer.
+ */
+ uint16_t max_record_send_size;
+ uint16_t max_record_recv_size;
+ /* holds the negotiated certificate type */
+ enum MHD_GNUTLS_CertificateType cert_type;
+ enum MHD_GNUTLS_Protocol version; /* moved here */
+ /* For TLS/IA. XXX: Move to IA credential? */
+ opaque inner_secret[TLS_MASTER_SIZE];
+} MHD_gtls_security_param_st;
+
+/* This structure holds the generated keys
+ */
+typedef struct
+{
+ MHD_gnutls_datum_t server_write_mac_secret;
+ MHD_gnutls_datum_t client_write_mac_secret;
+ MHD_gnutls_datum_t server_write_IV;
+ MHD_gnutls_datum_t client_write_IV;
+ MHD_gnutls_datum_t server_write_key;
+ MHD_gnutls_datum_t client_write_key;
+ int generated_keys; /* zero if keys have not
+ * been generated. Non zero
+ * otherwise.
+ */
+} MHD_gtls_cipher_specs_st;
+
+typedef struct
+{
+ cipher_hd_t write_cipher_state;
+ cipher_hd_t read_cipher_state;
+ MHD_gnutls_datum_t read_mac_secret;
+ MHD_gnutls_datum_t write_mac_secret;
+ uint64 read_sequence_number;
+ uint64 write_sequence_number;
+} MHD_gtls_conn_stat_st;
+
+typedef struct
+{
+ unsigned int priority[MAX_ALGOS];
+ unsigned int num_algorithms;
+} MHD_gtls_priority_st;
+
+/* For the external api */
+struct MHD_gtls_priority_st
+{
+ MHD_gtls_priority_st cipher;
+ MHD_gtls_priority_st mac;
+ MHD_gtls_priority_st kx;
+ MHD_gtls_priority_st compression;
+ MHD_gtls_priority_st protocol;
+
+ /* certificate type : x509, OpenPGP, etc. */
+ MHD_gtls_priority_st cert_type;
+
+ /* to disable record padding */
+ int no_padding;
+};
+
+/* DH and RSA parameters types.
+ */
+typedef struct MHD_gtls_dh_params_int
+{
+ /* [0] is the prime, [1] is the generator.
+ */
+ mpi_t params[2];
+} MHD_gtls_dh_params_st;
+
+typedef struct
+{
+ MHD_gtls_dh_params_t dh_params;
+ int free_dh_params;
+ MHD_gtls_rsa_params_t rsa_params;
+ int free_rsa_params;
+} MHD_gtls_internal_params_st;
+
+typedef struct
+{
+ opaque header[HANDSHAKE_HEADER_SIZE];
+ /* this holds the number of bytes in the handshake_header[] */
+ size_t header_size;
+ /* this holds the length of the handshake packet */
+ size_t packet_length;
+ MHD_gnutls_handshake_description_t recv_type;
+} MHD_gtls_handshake_header_buffer_st;
+
+typedef struct
+{
+ MHD_gtls_buffer application_data_buffer; /* holds data to be delivered to application layer */
+ MHD_gtls_buffer handshake_hash_buffer; /* used to keep the last received handshake
+ * message */
+ mac_hd_t handshake_mac_handle_sha; /* hash of the handshake messages */
+ mac_hd_t handshake_mac_handle_md5; /* hash of the handshake messages */
+
+ MHD_gtls_buffer handshake_data_buffer; /* this is a buffer that holds the current handshake message */
+ MHD_gtls_buffer ia_data_buffer; /* holds inner application data (TLS/IA) */
+ resumable_session_t resumable; /* TRUE or FALSE - if we can resume that session */
+ handshake_state_t handshake_state; /* holds
+ * a number which indicates where
+ * the handshake procedure has been
+ * interrupted. If it is 0 then
+ * no interruption has happened.
+ */
+
+ valid_session_t valid_connection; /* true or FALSE - if this session is valid */
+
+ int may_not_read; /* if it's 0 then we can read/write, otherwise it's forbiden to read/write
+ */
+ int may_not_write;
+ int read_eof; /* non-zero if we have received a closure alert. */
+
+ int last_alert; /* last alert received */
+ int last_alert_level; /* last alert level */
+
+ /* The last handshake messages sent or received.
+ */
+ int last_handshake_in;
+ int last_handshake_out;
+
+ /* this is the compression method we are going to use */
+ enum MHD_GNUTLS_CompressionMethod compression_method;
+
+ /* priorities */
+ struct MHD_gtls_priority_st priorities;
+
+ /* resumed session */
+ resumable_session_t resumed; /* RESUME_TRUE or FALSE - if we are resuming a session */
+ MHD_gtls_security_param_st resumed_security_parameters;
+
+ /* sockets internals */
+ int lowat;
+
+ /* These buffers are used in the handshake
+ * protocol only. freed using MHD__gnutls_handshake_io_buffer_clear();
+ */
+ MHD_gtls_buffer handshake_send_buffer;
+ size_t handshake_send_buffer_prev_size;
+ content_type_t handshake_send_buffer_type;
+ MHD_gnutls_handshake_description_t handshake_send_buffer_htype;
+ content_type_t handshake_recv_buffer_type;
+ MHD_gnutls_handshake_description_t handshake_recv_buffer_htype;
+ MHD_gtls_buffer handshake_recv_buffer;
+
+ /* this buffer holds a record packet -mostly used for
+ * non blocking IO.
+ */
+ MHD_gtls_buffer record_recv_buffer;
+ MHD_gtls_buffer record_send_buffer; /* holds cached data
+ * for the MHD_gnutls_io_write_buffered()
+ * function.
+ */
+ size_t record_send_buffer_prev_size; /* holds the
+ * data written in the previous runs.
+ */
+ size_t record_send_buffer_user_size; /* holds the
+ * size of the user specified data to
+ * send.
+ */
+
+ /* 0 if no peeked data was kept, 1 otherwise.
+ */
+ int have_peeked_data;
+
+ int expire_time; /* after expire_time seconds this session will expire */
+ struct MHD_gtls_mod_auth_st_int *auth_struct; /* used in handshake packets and KX algorithms */
+
+ /* TODO rm */
+ int v2_hello; /* 0 if the client hello is v3+.
+ * non-zero if we got a v2 hello.
+ */
+ /* keeps the headers of the handshake packet
+ */
+ MHD_gtls_handshake_header_buffer_st handshake_header_buffer;
+
+ /* this is the highest version available
+ * to the peer. (advertized version).
+ * This is obtained by the Handshake Client Hello
+ * message. (some implementations read the Record version)
+ */
+ uint8_t adv_version_major;
+ uint8_t adv_version_minor;
+
+ /* if this is non zero a certificate request message
+ * will be sent to the client. - only if the ciphersuite
+ * supports it.
+ */
+ int send_cert_req;
+
+ /* bits to use for DHE and DHA
+ * use MHD__gnutls_dh_get_prime_bits() and MHD__gnutls_dh_set_prime_bits()
+ * to access it.
+ */
+ uint16_t dh_prime_bits;
+
+ size_t max_handshake_data_buffer_size;
+
+ /* PUSH & PULL functions.
+ */
+ MHD_gtls_pull_func MHD__gnutls_pull_func;
+ MHD_gtls_push_func MHD__gnutls_push_func;
+ /* Holds the first argument of PUSH and PULL
+ * functions;
+ */
+ MHD_gnutls_transport_ptr_t transport_recv_ptr;
+ MHD_gnutls_transport_ptr_t transport_send_ptr;
+
+ /* Holds the record size requested by the
+ * user.
+ */
+ uint16_t proposed_record_size;
+
+ /* holds the selected certificate and key.
+ * use MHD_gtls_selected_certs_deinit() and MHD_gtls_selected_certs_set()
+ * to change them.
+ */
+ MHD_gnutls_cert *selected_cert_list;
+ int selected_cert_list_length;
+ MHD_gnutls_privkey *selected_key;
+ int selected_need_free;
+
+ /* holds the extensions we sent to the peer
+ * (in case of a client)
+ */
+ uint16_t extensions_sent[MAX_EXT_TYPES];
+ uint16_t extensions_sent_size;
+
+ /* This holds the default version that our first
+ * record packet will have. */
+ opaque default_record_version[2];
+
+ void *user_ptr;
+
+ /* Holds 0 if the last called function was interrupted while
+ * receiving, and non zero otherwise.
+ */
+ int direction;
+
+ /* If non zero the server will not advertize the CA's he
+ * trusts (do not send an RDN sequence).
+ */
+ int ignore_rdn_sequence;
+
+ /* This is used to set an arbitary version in the RSA
+ * PMS secret. Can be used by clients to test whether the
+ * server checks that version. (** only used in gnutls-cli-debug)
+ */
+ opaque rsa_pms_version[2];
+
+ /* Here we cache the DH or RSA parameters got from the
+ * credentials structure, or from a callback. That is to
+ * minimize external calls.
+ */
+ MHD_gtls_internal_params_st params;
+
+ /* This buffer is used by the record recv functions,
+ * as a temporary store buffer.
+ */
+ MHD_gnutls_datum_t recv_buffer;
+
+ /* To avoid using global variables, and especially on Windows where
+ * the application may use a different errno variable than GnuTLS,
+ * it is possible to use MHD__gnutls_transport_set_errno to set a
+ * session-specific errno variable in the user-replaceable push/pull
+ * functions. This value is used by the send/recv functions. (The
+ * strange name of this variable is because 'errno' is typically
+ * #define'd.)
+ */
+ int errnum;
+
+ /* Function used to perform public-key signing operation during
+ handshake. Used by MHD_gnutls_sig.c:MHD__gnutls_tls_sign(), see also
+ MHD_gtls_sign_callback_set(). */
+ MHD_gnutls_sign_func sign_func;
+ void *sign_func_userdata;
+
+ /* If you add anything here, check MHD_gtls_handshake_internal_state_clear().
+ */
+} MHD_gtls_internals_st;
+
+struct MHD_gtls_session_int
+{
+ MHD_gtls_security_param_st security_parameters;
+ MHD_gtls_cipher_specs_st cipher_specs;
+ MHD_gtls_conn_stat_st connection_state;
+ MHD_gtls_internals_st internals;
+ MHD_gtls_key_st key;
+};
+
+/* functions */
+void MHD_gtls_set_current_version (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_Protocol version);
+
+void MHD_gtls_free_auth_info (MHD_gtls_session_t session);
+
+/* These two macros return the advertized TLS version of
+ * the peer.
+ */
+#define MHD__gnutls_get_adv_version_major( session) \
+ session->internals.adv_version_major
+
+#define MHD__gnutls_get_adv_version_minor( session) \
+ session->internals.adv_version_minor
+
+#define set_adv_version( session, major, minor) \
+ session->internals.adv_version_major = major; \
+ session->internals.adv_version_minor = minor
+
+enum MHD_GNUTLS_Protocol MHD_gtls_get_adv_version (MHD_gtls_session_t);
+
+#endif /* GNUTLS_INT_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.c
new file mode 100644
index 0000000000..a4041e390a
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.c
@@ -0,0 +1,726 @@
+/*
+ * Copyright (C) 2000, 2001, 2004, 2005, 2006 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains functions which are wrappers for the key exchange
+ * part of TLS. They are called by the handshake functions (MHD__gnutls_handshake)
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_handshake.h"
+#include "gnutls_kx.h"
+#include "gnutls_dh.h"
+#include "gnutls_errors.h"
+#include "gnutls_algorithms.h"
+#include "debug.h"
+#include "gnutls_mpi.h"
+#include <gnutls_state.h>
+#include <gnutls_datum.h>
+#include <gnutls_rsa_export.h>
+
+/* This file contains important thing for the TLS handshake procedure.
+ */
+
+#define MASTER_SECRET "master secret"
+static int generate_normal_master (MHD_gtls_session_t session, int);
+
+int
+MHD_gtls_generate_master (MHD_gtls_session_t session, int keep_premaster)
+{
+ if (session->internals.resumed == RESUME_FALSE)
+ return generate_normal_master (session, keep_premaster);
+ return 0;
+}
+
+/* here we generate the TLS Master secret.
+ */
+#define PREMASTER session->key->key
+static int
+generate_normal_master (MHD_gtls_session_t session, int keep_premaster)
+{
+ int ret = 0;
+ char buf[512];
+
+ MHD__gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size,
+ MHD_gtls_bin2hex (PREMASTER.data, PREMASTER.size, buf,
+ sizeof (buf)));
+ MHD__gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32,
+ MHD_gtls_bin2hex (session->security_parameters.
+ client_random, 32, buf,
+ sizeof (buf)));
+ MHD__gnutls_hard_log ("INT: SERVER RANDOM[%d]: %s\n", 32,
+ MHD_gtls_bin2hex (session->security_parameters.
+ server_random, 32, buf,
+ sizeof (buf)));
+
+ if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ opaque rnd[2 * TLS_RANDOM_SIZE + 1];
+
+ memcpy (rnd, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ memcpy (&rnd[TLS_RANDOM_SIZE],
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+
+ ret =
+ MHD_gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size,
+ rnd, 2 * TLS_RANDOM_SIZE,
+ TLS_MASTER_SIZE,
+ session->security_parameters.
+ master_secret);
+
+ }
+ else
+ {
+ opaque rnd[2 * TLS_RANDOM_SIZE + 1];
+
+ memcpy (rnd, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ memcpy (&rnd[TLS_RANDOM_SIZE],
+ session->security_parameters.server_random, TLS_RANDOM_SIZE);
+
+ ret =
+ MHD_gtls_PRF (session, PREMASTER.data, PREMASTER.size,
+ MASTER_SECRET, strlen (MASTER_SECRET),
+ rnd, 2 * TLS_RANDOM_SIZE, TLS_MASTER_SIZE,
+ session->security_parameters.master_secret);
+ }
+
+ /* TLS/IA inner secret is derived from the master secret. */
+ memcpy (session->security_parameters.inner_secret,
+ session->security_parameters.master_secret, TLS_MASTER_SIZE);
+
+ if (!keep_premaster)
+ MHD__gnutls_free_datum (&PREMASTER);
+
+ if (ret < 0)
+ return ret;
+
+ MHD__gnutls_hard_log ("INT: MASTER SECRET: %s\n",
+ MHD_gtls_bin2hex (session->security_parameters.
+ master_secret, TLS_MASTER_SIZE, buf,
+ sizeof (buf)));
+
+ return ret;
+}
+
+
+/* This is called when we want to receive the key exchange message of the
+ * server. It does nothing if this type of message is not required
+ * by the selected ciphersuite.
+ */
+int
+MHD_gtls_send_server_kx_message (MHD_gtls_session_t session, int again)
+{
+ uint8_t *data = NULL;
+ int data_size = 0;
+ int ret = 0;
+
+ if (session->internals.auth_struct->MHD_gtls_gen_server_kx == NULL)
+ return 0;
+
+ data = NULL;
+ data_size = 0;
+
+ if (again == 0)
+ {
+ data_size =
+ session->internals.auth_struct->MHD_gtls_gen_server_kx (session,
+ &data);
+
+ if (data_size == GNUTLS_E_INT_RET_0)
+ {
+ MHD_gnutls_assert ();
+ return 0;
+ }
+
+ if (data_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return data_size;
+ }
+ }
+
+ ret =
+ MHD_gtls_send_handshake (session, data, data_size,
+ GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE);
+ MHD_gnutls_free (data);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ return data_size;
+}
+
+/* This function sends a certificate request message to the
+ * client.
+ */
+int
+MHD_gtls_send_server_certificate_request (MHD_gtls_session_t session,
+ int again)
+{
+ uint8_t *data = NULL;
+ int data_size = 0;
+ int ret = 0;
+
+ if (session->internals.auth_struct->
+ MHD_gtls_gen_server_certificate_request == NULL)
+ return 0;
+
+ if (session->internals.send_cert_req <= 0)
+ return 0;
+
+ data = NULL;
+ data_size = 0;
+
+ if (again == 0)
+ {
+ data_size =
+ session->internals.auth_struct->
+ MHD_gtls_gen_server_certificate_request (session, &data);
+
+ if (data_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return data_size;
+ }
+ }
+ ret =
+ MHD_gtls_send_handshake (session, data, data_size,
+ GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST);
+ MHD_gnutls_free (data);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ return data_size;
+}
+
+
+/* This is the function for the client to send the key
+ * exchange message
+ */
+int
+MHD_gtls_send_client_kx_message (MHD_gtls_session_t session, int again)
+{
+ uint8_t *data;
+ int data_size;
+ int ret = 0;
+
+ if (session->internals.auth_struct->MHD_gtls_gen_client_kx == NULL)
+ return 0;
+
+
+ data = NULL;
+ data_size = 0;
+
+ if (again == 0)
+ {
+ data_size =
+ session->internals.auth_struct->MHD_gtls_gen_client_kx (session,
+ &data);
+ if (data_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return data_size;
+ }
+ }
+ ret =
+ MHD_gtls_send_handshake (session, data, data_size,
+ GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE);
+ MHD_gnutls_free (data);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return ret;
+}
+
+
+/* This is the function for the client to send the certificate
+ * verify message
+ */
+int
+MHD_gtls_send_client_certificate_verify (MHD_gtls_session_t session,
+ int again)
+{
+ uint8_t *data;
+ int ret = 0;
+ int data_size;
+
+ /* This is a packet that is only sent by the client
+ */
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ return 0;
+
+ /* if certificate verify is not needed just exit
+ */
+ if (session->key->certificate_requested == 0)
+ return 0;
+
+ if (session->internals.auth_struct->MHD_gtls_gen_client_cert_vrfy == NULL)
+ {
+ MHD_gnutls_assert ();
+ return 0; /* this algorithm does not support cli_cert_vrfy
+ */
+ }
+
+ data = NULL;
+ data_size = 0;
+
+ if (again == 0)
+ {
+ data_size =
+ session->internals.auth_struct->
+ MHD_gtls_gen_client_cert_vrfy (session, &data);
+ if (data_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return data_size;
+ }
+ if (data_size == 0)
+ return 0;
+
+ }
+ ret =
+ MHD_gtls_send_handshake (session, data,
+ data_size, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY);
+ MHD_gnutls_free (data);
+
+ return ret;
+}
+
+
+int
+MHD_gtls_recv_server_kx_message (MHD_gtls_session_t session)
+{
+ uint8_t *data = NULL;
+ int datasize;
+ int ret = 0;
+
+ if (session->internals.auth_struct->MHD_gtls_process_server_kx != NULL)
+ {
+
+ /* EXCEPTION FOR RSA_EXPORT cipher suite
+ */
+ if (MHD_gtls_session_is_export (session) != 0 &&
+ MHD__gnutls_peers_cert_less_512 (session) != 0)
+ {
+ MHD_gnutls_assert ();
+ return 0;
+ }
+
+ ret =
+ MHD_gtls_recv_handshake (session, &data,
+ &datasize,
+ GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE,
+ MANDATORY_PACKET);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret =
+ session->internals.auth_struct->MHD_gtls_process_server_kx (session,
+ data,
+ datasize);
+ MHD_gnutls_free (data);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ }
+ return ret;
+}
+
+int
+MHD_gtls_recv_server_certificate_request (MHD_gtls_session_t session)
+{
+ uint8_t *data;
+ int datasize;
+ int ret = 0;
+
+ if (session->internals.auth_struct->
+ MHD_gtls_process_server_certificate_request != NULL)
+ {
+
+ ret =
+ MHD_gtls_recv_handshake (session, &data,
+ &datasize,
+ GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST,
+ OPTIONAL_PACKET);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0 && datasize == 0)
+ return 0; /* ignored */
+
+ ret =
+ session->internals.auth_struct->
+ MHD_gtls_process_server_certificate_request (session, data, datasize);
+ MHD_gnutls_free (data);
+ if (ret < 0)
+ return ret;
+
+ }
+ return ret;
+}
+
+int
+MHD_gtls_recv_client_kx_message (MHD_gtls_session_t session)
+{
+ uint8_t *data;
+ int datasize;
+ int ret = 0;
+
+
+ /* Do key exchange only if the algorithm permits it */
+ if (session->internals.auth_struct->MHD_gtls_process_client_kx != NULL)
+ {
+
+ ret =
+ MHD_gtls_recv_handshake (session, &data,
+ &datasize,
+ GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE,
+ MANDATORY_PACKET);
+ if (ret < 0)
+ return ret;
+
+ ret =
+ session->internals.auth_struct->MHD_gtls_process_client_kx (session,
+ data,
+ datasize);
+ MHD_gnutls_free (data);
+ if (ret < 0)
+ return ret;
+
+ }
+
+ return ret;
+}
+
+
+/* This is called when we want send our certificate
+ */
+int
+MHD_gtls_send_client_certificate (MHD_gtls_session_t session, int again)
+{
+ uint8_t *data = NULL;
+ int data_size = 0;
+ int ret = 0;
+
+
+ if (session->key->certificate_requested == 0)
+ return 0;
+
+ if (session->internals.auth_struct->MHD_gtls_gen_client_certificate == NULL)
+ return 0;
+
+ data = NULL;
+ data_size = 0;
+
+ if (again == 0)
+ {
+ if (MHD__gnutls_protocol_get_version (session) !=
+ MHD_GNUTLS_PROTOCOL_SSL3
+ || session->internals.selected_cert_list_length > 0)
+ {
+ /* TLS 1.0 or SSL 3.0 with a valid certificate
+ */
+ data_size =
+ session->internals.auth_struct->
+ MHD_gtls_gen_client_certificate (session, &data);
+
+ if (data_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return data_size;
+ }
+ }
+ }
+
+ /* In the SSL 3.0 protocol we need to send a
+ * no certificate alert instead of an
+ * empty certificate.
+ */
+ if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3
+ && session->internals.selected_cert_list_length == 0)
+ {
+ ret =
+ MHD__gnutls_alert_send (session, GNUTLS_AL_WARNING,
+ GNUTLS_A_SSL3_NO_CERTIFICATE);
+
+ }
+ else
+ { /* TLS 1.0 or SSL 3.0 with a valid certificate
+ */
+ ret =
+ MHD_gtls_send_handshake (session, data, data_size,
+ GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
+ MHD_gnutls_free (data);
+ }
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return data_size;
+}
+
+
+/* This is called when we want send our certificate
+ */
+int
+MHD_gtls_send_server_certificate (MHD_gtls_session_t session, int again)
+{
+ uint8_t *data = NULL;
+ int data_size = 0;
+ int ret = 0;
+
+
+ if (session->internals.auth_struct->MHD_gtls_gen_server_certificate == NULL)
+ return 0;
+
+ data = NULL;
+ data_size = 0;
+
+ if (again == 0)
+ {
+ data_size =
+ session->internals.auth_struct->
+ MHD_gtls_gen_server_certificate (session, &data);
+
+ if (data_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return data_size;
+ }
+ }
+ ret =
+ MHD_gtls_send_handshake (session, data, data_size,
+ GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
+ MHD_gnutls_free (data);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return data_size;
+}
+
+
+int
+MHD_gtls_recv_client_certificate (MHD_gtls_session_t session)
+{
+ int datasize;
+ opaque *data;
+ int ret = 0;
+ int optional;
+
+ if (session->internals.auth_struct->MHD_gtls_process_client_certificate !=
+ NULL)
+ {
+
+ /* if we have not requested a certificate then just return
+ */
+ if (session->internals.send_cert_req == 0)
+ {
+ return 0;
+ }
+
+ if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
+ optional = MANDATORY_PACKET;
+ else
+ optional = OPTIONAL_PACKET;
+
+ ret =
+ MHD_gtls_recv_handshake (session, &data,
+ &datasize,
+ GNUTLS_HANDSHAKE_CERTIFICATE_PKT, optional);
+
+ if (ret < 0)
+ {
+ /* Handle the case of old SSL3 clients who send
+ * a warning alert instead of an empty certificate to indicate
+ * no certificate.
+ */
+ if (optional == OPTIONAL_PACKET &&
+ ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
+ MHD__gnutls_protocol_get_version (session) ==
+ MHD_GNUTLS_PROTOCOL_SSL3
+ && MHD_gnutls_alert_get (session) ==
+ GNUTLS_A_SSL3_NO_CERTIFICATE)
+ {
+
+ /* SSL3 does not send an empty certificate,
+ * but this alert. So we just ignore it.
+ */
+ MHD_gnutls_assert ();
+ return 0;
+ }
+
+ /* certificate was required
+ */
+ if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED
+ || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
+ && optional == MANDATORY_PACKET)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ return ret;
+ }
+
+ if (ret == 0 && datasize == 0 && optional == OPTIONAL_PACKET)
+ {
+ /* Client has not sent the certificate message.
+ * well I'm not sure we should accept this
+ * behaviour.
+ */
+ MHD_gnutls_assert ();
+ return 0;
+ }
+ ret =
+ session->internals.auth_struct->
+ MHD_gtls_process_client_certificate (session, data, datasize);
+
+ MHD_gnutls_free (data);
+ if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* ok we should expect a certificate verify message now
+ */
+ if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional == OPTIONAL_PACKET)
+ ret = 0;
+ else
+ session->key->certificate_requested = 1;
+
+ }
+
+ return ret;
+}
+
+int
+MHD_gtls_recv_server_certificate (MHD_gtls_session_t session)
+{
+ int datasize;
+ opaque *data;
+ int ret = 0;
+
+ if (session->internals.auth_struct->MHD_gtls_process_server_certificate !=
+ NULL)
+ {
+
+ ret =
+ MHD_gtls_recv_handshake (session, &data,
+ &datasize,
+ GNUTLS_HANDSHAKE_CERTIFICATE_PKT,
+ MANDATORY_PACKET);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret =
+ session->internals.auth_struct->
+ MHD_gtls_process_server_certificate (session, data, datasize);
+ MHD_gnutls_free (data);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+
+/* Recv the client certificate verify. This packet may not
+ * arrive if the peer did not send us a certificate.
+ */
+int
+MHD_gtls_recv_client_certificate_verify_message (MHD_gtls_session_t session)
+{
+ uint8_t *data;
+ int datasize;
+ int ret = 0;
+
+
+ if (session->internals.auth_struct->MHD_gtls_process_client_cert_vrfy !=
+ NULL)
+ {
+
+ if (session->internals.send_cert_req == 0 ||
+ session->key->certificate_requested == 0)
+ {
+ return 0;
+ }
+
+ ret =
+ MHD_gtls_recv_handshake (session, &data,
+ &datasize,
+ GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY,
+ OPTIONAL_PACKET);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0 && datasize == 0
+ && session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
+ {
+ /* certificate was required */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ ret =
+ session->internals.auth_struct->
+ MHD_gtls_process_client_cert_vrfy (session, data, datasize);
+ MHD_gnutls_free (data);
+ if (ret < 0)
+ return ret;
+
+ }
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.h
new file mode 100644
index 0000000000..92144615f5
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_kx.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD_gtls_send_server_kx_message (MHD_gtls_session_t session, int again);
+int MHD_gtls_send_client_kx_message (MHD_gtls_session_t session, int again);
+int MHD_gtls_recv_server_kx_message (MHD_gtls_session_t session);
+int MHD_gtls_recv_client_kx_message (MHD_gtls_session_t session);
+int MHD_gtls_send_client_certificate_verify (MHD_gtls_session_t session,
+ int again);
+int MHD_gtls_send_server_certificate (MHD_gtls_session_t session, int again);
+int MHD_gtls_generate_master (MHD_gtls_session_t session, int keep_premaster);
+int MHD_gtls_recv_client_certificate (MHD_gtls_session_t session);
+int MHD_gtls_recv_server_certificate (MHD_gtls_session_t session);
+int MHD_gtls_send_client_certificate (MHD_gtls_session_t session, int again);
+int MHD_gtls_recv_server_certificate_request (MHD_gtls_session_t session);
+int MHD_gtls_send_server_certificate_request (MHD_gtls_session_t session,
+ int again);
+int MHD_gtls_recv_client_certificate_verify_message (MHD_gtls_session_t
+ session);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.c
new file mode 100644
index 0000000000..44f1ccf5fc
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+
+MHD_gnutls_alloc_function MHD_gnutls_secure_malloc = malloc;
+MHD_gnutls_alloc_function MHD_gnutls_malloc = malloc;
+MHD_gnutls_free_function MHD_gnutls_free = free;
+MHD_gnutls_realloc_function MHD_gnutls_realloc = realloc;
+
+void *(*MHD_gnutls_calloc) (size_t, size_t) = calloc;
+
+int
+MHD__gnutls_is_secure_mem_null (const void *ign)
+{
+ return 0;
+}
+
+int (*MHD__gnutls_is_secure_memory) (const void *) =
+ MHD__gnutls_is_secure_mem_null;
+
+
+
+/* This realloc will free ptr in case realloc
+ * fails.
+ */
+void *
+MHD_gtls_realloc_fast (void *ptr, size_t size)
+{
+ void *ret;
+
+ if (size == 0)
+ return ptr;
+
+ ret = MHD_gnutls_realloc (ptr, size);
+ if (ret == NULL)
+ {
+ MHD_gnutls_free (ptr);
+ }
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.h
new file mode 100644
index 0000000000..0ea84a1089
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mem.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_MEM_H
+# define GNUTLS_MEM_H
+
+#ifdef USE_DMALLOC
+# include <dmalloc.h>
+#endif
+
+typedef void svoid; /* for functions that allocate using MHD_gnutls_secure_malloc */
+
+#ifdef HAVE_ALLOCA
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# endif
+# ifndef MHD_gnutls_alloca
+# define MHD_gnutls_alloca alloca
+# define MHD_gnutls_afree(x)
+# endif
+#else
+# ifndef MHD_gnutls_alloca
+# define MHD_gnutls_alloca MHD_gnutls_malloc
+# define MHD_gnutls_afree MHD_gnutls_free
+# endif
+#endif /* HAVE_ALLOCA */
+
+extern int (*MHD__gnutls_is_secure_memory) (const void *);
+
+/* this realloc function will return ptr if size==0, and
+ * will free the ptr if the new allocation failed.
+ */
+void *MHD_gtls_realloc_fast (void *ptr, size_t size);
+
+svoid *MHD_gtls_secure_calloc (size_t nmemb, size_t size);
+
+void *MHD_gtls_calloc (size_t nmemb, size_t size);
+char *MHD_gtls_strdup (const char *);
+
+#endif /* GNUTLS_MEM_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.c
new file mode 100644
index 0000000000..5a4e25a4c4
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Here lie everything that has to do with large numbers, libgcrypt and
+ * other stuff that didn't fit anywhere else.
+ */
+
+#include <gnutls_int.h>
+#include <libtasn1.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+
+/* Functions that refer to the libgcrypt library.
+ */
+
+void
+MHD_gtls_mpi_release (mpi_t * x)
+{
+ if (*x == NULL)
+ return;
+ gcry_mpi_release (*x);
+ *x = NULL;
+}
+
+/* returns zero on success
+ */
+int
+MHD_gtls_mpi_scan (mpi_t * ret_mpi, const opaque * buffer, size_t * nbytes)
+{
+ int ret;
+
+ ret = gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, buffer, *nbytes, nbytes);
+ if (ret)
+ return GNUTLS_E_MPI_SCAN_FAILED;
+
+ return 0;
+}
+
+/* returns zero on success. Fails if the number is zero.
+ */
+int
+MHD_gtls_mpi_scan_nz (mpi_t * ret_mpi, const opaque * buffer, size_t * nbytes)
+{
+ int ret;
+
+ ret = gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, buffer, *nbytes, nbytes);
+ if (ret)
+ return GNUTLS_E_MPI_SCAN_FAILED;
+
+ /* MPIs with 0 bits are illegal
+ */
+ if (MHD__gnutls_mpi_get_nbits (*ret_mpi) == 0)
+ {
+ MHD_gtls_mpi_release (ret_mpi);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ return 0;
+}
+
+int
+MHD_gtls_mpi_print (void *buffer, size_t * nbytes, const mpi_t a)
+{
+ int ret;
+
+ if (nbytes == NULL || a == NULL)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ ret = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, *nbytes, nbytes, a);
+ if (!ret)
+ return 0;
+
+ return GNUTLS_E_MPI_PRINT_FAILED;
+}
+
+/* Always has the first bit zero */
+static int
+MHD_gtls_mpi_print_lz (void *buffer, size_t * nbytes, const mpi_t a)
+{
+ int ret;
+
+ if (nbytes == NULL || a == NULL)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ ret = gcry_mpi_print (GCRYMPI_FMT_STD, buffer, *nbytes, nbytes, a);
+ if (!ret)
+ return 0;
+
+ return GNUTLS_E_MPI_PRINT_FAILED;
+}
+
+/* Always has the first bit zero */
+int
+MHD_gtls_mpi_dprint_lz (MHD_gnutls_datum_t * dest, const mpi_t a)
+{
+ int ret;
+ opaque *buf = NULL;
+ size_t bytes = 0;
+
+ if (dest == NULL || a == NULL)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &bytes, a);
+
+ if (bytes != 0)
+ buf = MHD_gnutls_malloc (bytes);
+ if (buf == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ ret = gcry_mpi_print (GCRYMPI_FMT_STD, buf, bytes, &bytes, a);
+ if (!ret)
+ {
+ dest->data = buf;
+ dest->size = bytes;
+ return 0;
+ }
+
+ MHD_gnutls_free (buf);
+ return GNUTLS_E_MPI_PRINT_FAILED;
+}
+
+int
+MHD_gtls_mpi_dprint (MHD_gnutls_datum_t * dest, const mpi_t a)
+{
+ int ret;
+ opaque *buf = NULL;
+ size_t bytes = 0;
+
+ if (dest == NULL || a == NULL)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &bytes, a);
+
+ if (bytes != 0)
+ buf = MHD_gnutls_malloc (bytes);
+ if (buf == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ ret = gcry_mpi_print (GCRYMPI_FMT_USG, buf, bytes, &bytes, a);
+ if (!ret)
+ {
+ dest->data = buf;
+ dest->size = bytes;
+ return 0;
+ }
+
+ MHD_gnutls_free (buf);
+ return GNUTLS_E_MPI_PRINT_FAILED;
+}
+
+
+/* this function reads an integer
+ * from asn1 structs. Combines the read and mpi_scan
+ * steps.
+ */
+int
+MHD__gnutls_x509_read_int (ASN1_TYPE node, const char *value, mpi_t * ret_mpi)
+{
+ int result;
+ size_t s_len;
+ opaque *tmpstr = NULL;
+ int tmpstr_size;
+
+ tmpstr_size = 0;
+ result = MHD__asn1_read_value (node, value, NULL, &tmpstr_size);
+ if (result != ASN1_MEM_ERROR)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ tmpstr = MHD_gnutls_alloca (tmpstr_size);
+ if (tmpstr == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ result = MHD__asn1_read_value (node, value, tmpstr, &tmpstr_size);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (tmpstr);
+ return MHD_gtls_asn2err (result);
+ }
+
+ s_len = tmpstr_size;
+ if (MHD_gtls_mpi_scan (ret_mpi, tmpstr, &s_len) != 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (tmpstr);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ MHD_gnutls_afree (tmpstr);
+
+ return 0;
+}
+
+/* Writes the specified integer into the specified node.
+ */
+int
+MHD__gnutls_x509_write_int (ASN1_TYPE node, const char *value, mpi_t mpi,
+ int lz)
+{
+ opaque *tmpstr;
+ size_t s_len;
+ int result;
+
+ s_len = 0;
+ if (lz)
+ result = MHD_gtls_mpi_print_lz (NULL, &s_len, mpi);
+ else
+ result = MHD_gtls_mpi_print (NULL, &s_len, mpi);
+
+ tmpstr = MHD_gnutls_alloca (s_len);
+ if (tmpstr == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (lz)
+ result = MHD_gtls_mpi_print_lz (tmpstr, &s_len, mpi);
+ else
+ result = MHD_gtls_mpi_print (tmpstr, &s_len, mpi);
+
+ if (result != 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (tmpstr);
+ return GNUTLS_E_MPI_PRINT_FAILED;
+ }
+
+ result = MHD__asn1_write_value (node, value, tmpstr, s_len);
+
+ MHD_gnutls_afree (tmpstr);
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.h
new file mode 100644
index 0000000000..77b7c9e4ac
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_mpi.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_MPI_H
+#define GNUTLS_MPI_H
+
+# include <gnutls_int.h>
+# include <gcrypt.h>
+# include "gc.h"
+
+typedef gcry_mpi_t mpi_t;
+
+#define MHD__gnutls_mpi_cmp gcry_mpi_cmp
+#define MHD__gnutls_mpi_cmp_ui gcry_mpi_cmp_ui
+#define MHD__gnutls_mpi_new gcry_mpi_new
+#define MHD__gnutls_mpi_snew gcry_mpi_snew
+#define MHD__gnutls_mpi_copy gcry_mpi_copy
+#define MHD__gnutls_mpi_randomize gcry_mpi_randomize
+#define MHD__gnutls_mpi_get_nbits gcry_mpi_get_nbits
+#define MHD__gnutls_mpi_powm gcry_mpi_powm
+#define MHD__gnutls_mpi_invm gcry_mpi_invm
+#define MHD__gnutls_mpi_alloc_like(x) MHD__gnutls_mpi_new(MHD__gnutls_mpi_get_nbits(x))
+
+void MHD_gtls_mpi_release (mpi_t * x);
+
+int MHD_gtls_mpi_scan_nz (mpi_t * ret_mpi, const opaque * buffer,
+ size_t * nbytes);
+int MHD_gtls_mpi_scan (mpi_t * ret_mpi, const opaque * buffer,
+ size_t * nbytes);
+int MHD_gtls_mpi_print (void *buffer, size_t * nbytes, const mpi_t a);
+int MHD_gtls_mpi_dprint_lz (MHD_gnutls_datum_t * dest, const mpi_t a);
+int MHD_gtls_mpi_dprint (MHD_gnutls_datum_t * dest, const mpi_t a);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.c
new file mode 100644
index 0000000000..06d2e4eb20
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the functions needed for 64 bit integer support in
+ * TLS, and functions which ease the access to TLS vectors (data of given size).
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_num.h>
+#include <gnutls_errors.h>
+
+/* This function will add one to uint64 x.
+ * Returns 0 on success, or -1 if the uint64 max limit
+ * has been reached.
+ */
+int
+MHD_gtls_uint64pp (uint64 * x)
+{
+ register int i, y = 0;
+
+ for (i = 7; i >= 0; i--)
+ {
+ y = 0;
+ if (x->i[i] == 0xff)
+ {
+ x->i[i] = 0;
+ y = 1;
+ }
+ else
+ x->i[i]++;
+
+ if (y == 0)
+ break;
+ }
+ if (y != 0)
+ return -1; /* over 64 bits! WOW */
+
+ return 0;
+}
+
+uint32_t
+MHD_gtls_uint24touint32 (uint24 num)
+{
+ uint32_t ret = 0;
+
+ ((uint8_t *) & ret)[1] = num.pint[0];
+ ((uint8_t *) & ret)[2] = num.pint[1];
+ ((uint8_t *) & ret)[3] = num.pint[2];
+ return ret;
+}
+
+uint24
+MHD_gtls_uint32touint24 (uint32_t num)
+{
+ uint24 ret;
+
+ ret.pint[0] = ((uint8_t *) & num)[1];
+ ret.pint[1] = ((uint8_t *) & num)[2];
+ ret.pint[2] = ((uint8_t *) & num)[3];
+ return ret;
+
+}
+
+/* data should be at least 3 bytes */
+uint32_t
+MHD_gtls_read_uint24 (const opaque * data)
+{
+ uint32_t res;
+ uint24 num;
+
+ num.pint[0] = data[0];
+ num.pint[1] = data[1];
+ num.pint[2] = data[2];
+
+ res = MHD_gtls_uint24touint32 (num);
+#ifndef WORDS_BIGENDIAN
+ res = byteswap32 (res);
+#endif
+ return res;
+}
+
+void
+MHD_gtls_write_uint24 (uint32_t num, opaque * data)
+{
+ uint24 tmp;
+
+#ifndef WORDS_BIGENDIAN
+ num = byteswap32 (num);
+#endif
+ tmp = MHD_gtls_uint32touint24 (num);
+
+ data[0] = tmp.pint[0];
+ data[1] = tmp.pint[1];
+ data[2] = tmp.pint[2];
+}
+
+uint32_t
+MHD_gtls_read_uint32 (const opaque * data)
+{
+ uint32_t res;
+
+ memcpy (&res, data, sizeof (uint32_t));
+#ifndef WORDS_BIGENDIAN
+ res = byteswap32 (res);
+#endif
+ return res;
+}
+
+void
+MHD_gtls_write_uint32 (uint32_t num, opaque * data)
+{
+
+#ifndef WORDS_BIGENDIAN
+ num = byteswap32 (num);
+#endif
+ memcpy (data, &num, sizeof (uint32_t));
+}
+
+uint16_t
+MHD_gtls_read_uint16 (const opaque * data)
+{
+ uint16_t res;
+ memcpy (&res, data, sizeof (uint16_t));
+#ifndef WORDS_BIGENDIAN
+ res = byteswap16 (res);
+#endif
+ return res;
+}
+
+void
+MHD_gtls_write_uint16 (uint16_t num, opaque * data)
+{
+
+#ifndef WORDS_BIGENDIAN
+ num = byteswap16 (num);
+#endif
+ memcpy (data, &num, sizeof (uint16_t));
+}
+
+uint32_t
+MHD_gtls_conv_uint32 (uint32_t data)
+{
+#ifndef WORDS_BIGENDIAN
+ return byteswap32 (data);
+#else
+ return data;
+#endif
+}
+
+uint16_t
+MHD_gtls_conv_uint16 (uint16_t data)
+{
+#ifndef WORDS_BIGENDIAN
+ return byteswap16 (data);
+#else
+ return data;
+#endif
+}
+
+uint32_t
+MHD_gtls_uint64touint32 (const uint64 * num)
+{
+ uint32_t ret;
+
+ memcpy (&ret, &num->i[4], 4);
+#ifndef WORDS_BIGENDIAN
+ ret = byteswap32 (ret);
+#endif
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.h
new file mode 100644
index 0000000000..3a0f1f88d5
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_num.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+
+#define rotl32(x,n) (((x) << ((uint16_t)(n))) | ((x) >> (32 - (uint16_t)(n))))
+#define rotr32(x,n) (((x) >> ((uint16_t)(n))) | ((x) << (32 - (uint16_t)(n))))
+#define rotl16(x,n) (((x) << ((uint16_t)(n))) | ((x) >> (16 - (uint16_t)(n))))
+#define rotr16(x,n) (((x) >> ((uint16_t)(n))) | ((x) << (16 - (uint16_t)(n))))
+
+#define byteswap16(x) ((rotl16(x, 8) & 0x00ff) | (rotr16(x, 8) & 0xff00))
+#define byteswap32(x) ((rotl32(x, 8) & 0x00ff00ffUL) | (rotr32(x, 8) & 0xff00ff00UL))
+
+uint32_t MHD_gtls_uint24touint32 (uint24 num);
+uint24 MHD_gtls_uint32touint24 (uint32_t num);
+uint32_t MHD_gtls_read_uint32 (const opaque * data);
+uint16_t MHD_gtls_read_uint16 (const opaque * data);
+uint32_t MHD_gtls_conv_uint32 (uint32_t data);
+uint16_t MHD_gtls_conv_uint16 (uint16_t data);
+uint32_t MHD_gtls_read_uint24 (const opaque * data);
+void MHD_gtls_write_uint24 (uint32_t num, opaque * data);
+void MHD_gtls_write_uint32 (uint32_t num, opaque * data);
+void MHD_gtls_write_uint16 (uint16_t num, opaque * data);
+uint32_t MHD_gtls_uint64touint32 (const uint64 *);
+
+int MHD_gtls_uint64pp (uint64 *);
+#define MHD__gnutls_uint64zero(x) x.i[0] = x.i[1] = x.i[2] = x.i[3] = x.i[4] = x.i[5] = x.i[6] = x.i[7] = 0
+#define UINT64DATA(x) x.i
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.c
new file mode 100644
index 0000000000..f8514cae8a
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the functions needed for RSA/DSA public key
+ * encryption and signatures.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_mpi.h>
+#include <gnutls_pk.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_num.h>
+#include "debug.h"
+#include <gc.h>
+
+/* x509 */
+#include "common.h"
+#include "mpi.h"
+
+static int MHD__gnutls_pk_encrypt (int algo, mpi_t * resarr, mpi_t data,
+ mpi_t * pkey, int pkey_len);
+static int MHD__gnutls_pk_sign (int algo, mpi_t * data, mpi_t hash,
+ mpi_t * pkey, int);
+static int MHD__gnutls_pk_decrypt (int algo, mpi_t * resarr, mpi_t data,
+ mpi_t * pkey, int);
+
+
+/* Do PKCS-1 RSA encryption.
+ * params is modulus, public exp.
+ */
+int
+MHD_gtls_pkcs1_rsa_encrypt (MHD_gnutls_datum_t * ciphertext,
+ const MHD_gnutls_datum_t * plaintext,
+ mpi_t * params, unsigned params_len,
+ unsigned btype)
+{
+ unsigned int i, pad;
+ int ret;
+ mpi_t m, res;
+ opaque *edata, *ps;
+ size_t k, psize;
+ size_t mod_bits;
+
+ mod_bits = MHD__gnutls_mpi_get_nbits (params[0]);
+ k = mod_bits / 8;
+ if (mod_bits % 8 != 0)
+ k++;
+
+ if (plaintext->size > k - 11)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PK_ENCRYPTION_FAILED;
+ }
+
+ edata = MHD_gnutls_alloca (k);
+ if (edata == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* EB = 00||BT||PS||00||D
+ * (use block type 'btype')
+ */
+
+ edata[0] = 0;
+ edata[1] = btype;
+ psize = k - 3 - plaintext->size;
+
+ ps = &edata[2];
+ switch (btype)
+ {
+ case 2:
+ /* using public key */
+ if (params_len < RSA_PUBLIC_PARAMS)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (MHD_gc_pseudo_random ((char *) ps, psize) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+ for (i = 0; i < psize; i++)
+ while (ps[i] == 0)
+ {
+ if (MHD_gc_pseudo_random ((char *) &ps[i], 1) != GC_OK)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_RANDOM_FAILED;
+ }
+ }
+ break;
+ case 1:
+ /* using private key */
+
+ if (params_len < RSA_PRIVATE_PARAMS)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ for (i = 0; i < psize; i++)
+ ps[i] = 0xff;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ps[psize] = 0;
+ memcpy (&ps[psize + 1], plaintext->data, plaintext->size);
+
+ if (MHD_gtls_mpi_scan_nz (&m, edata, &k) != 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+ MHD_gnutls_afree (edata);
+
+ if (btype == 2) /* encrypt */
+ ret = MHD__gnutls_pk_encrypt (GCRY_PK_RSA, &res, m, params, params_len);
+ else /* sign */
+ ret = MHD__gnutls_pk_sign (GCRY_PK_RSA, &res, m, params, params_len);
+
+ MHD_gtls_mpi_release (&m);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gtls_mpi_print (NULL, &psize, res);
+
+ if (psize < k)
+ {
+ /* padding psize */
+ pad = k - psize;
+ psize = k;
+ }
+ else if (psize == k)
+ {
+ pad = 0;
+ }
+ else
+ { /* psize > k !!! */
+ /* This is an impossible situation */
+ MHD_gnutls_assert ();
+ MHD_gtls_mpi_release (&res);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ciphertext->data = MHD_gnutls_malloc (psize);
+ if (ciphertext->data == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gtls_mpi_release (&res);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ MHD_gtls_mpi_print (&ciphertext->data[pad], &psize, res);
+ for (i = 0; i < pad; i++)
+ ciphertext->data[i] = 0;
+
+ ciphertext->size = k;
+
+ MHD_gtls_mpi_release (&res);
+
+ return 0;
+}
+
+
+/* Do PKCS-1 RSA decryption.
+ * params is modulus, public exp., private key
+ * Can decrypt block type 1 and type 2 packets.
+ */
+int
+MHD_gtls_pkcs1_rsa_decrypt (MHD_gnutls_datum_t * plaintext,
+ const MHD_gnutls_datum_t * ciphertext,
+ mpi_t * params, unsigned params_len,
+ unsigned btype)
+{
+ unsigned k, i;
+ int ret;
+ mpi_t c, res;
+ opaque *edata;
+ size_t esize, mod_bits;
+
+ mod_bits = MHD__gnutls_mpi_get_nbits (params[0]);
+ k = mod_bits / 8;
+ if (mod_bits % 8 != 0)
+ k++;
+
+ esize = ciphertext->size;
+
+ if (esize != k)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PK_DECRYPTION_FAILED;
+ }
+
+ if (MHD_gtls_mpi_scan_nz (&c, ciphertext->data, &esize) != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ /* we can use btype to see if the private key is
+ * available.
+ */
+ if (btype == 2)
+ ret = MHD__gnutls_pk_decrypt (GCRY_PK_RSA, &res, c, params, params_len);
+ else
+ {
+ ret = MHD__gnutls_pk_encrypt (GCRY_PK_RSA, &res, c, params, params_len);
+ }
+ MHD_gtls_mpi_release (&c);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gtls_mpi_print (NULL, &esize, res);
+ edata = MHD_gnutls_alloca (esize + 1);
+ if (edata == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gtls_mpi_release (&res);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ MHD_gtls_mpi_print (&edata[1], &esize, res);
+
+ MHD_gtls_mpi_release (&res);
+
+ /* EB = 00||BT||PS||00||D
+ * (use block type 'btype')
+ *
+ * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
+ * avoid attacks similar to the one described by Bleichenbacher in:
+ * "Chosen Ciphertext Attacks against Protocols Based on RSA
+ * Encryption Standard PKCS #1".
+ */
+
+
+ edata[0] = 0;
+ esize++;
+
+ if (edata[0] != 0 || edata[1] != btype)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+
+ ret = GNUTLS_E_DECRYPTION_FAILED;
+ switch (btype)
+ {
+ case 2:
+ for (i = 2; i < esize; i++)
+ {
+ if (edata[i] == 0)
+ {
+ ret = 0;
+ break;
+ }
+ }
+ break;
+ case 1:
+ for (i = 2; i < esize; i++)
+ {
+ if (edata[i] == 0 && i > 2)
+ {
+ ret = 0;
+ break;
+ }
+ if (edata[i] != 0xff)
+ {
+ MHD__gnutls_handshake_log ("PKCS #1 padding error");
+ /* PKCS #1 padding error. Don't use
+ GNUTLS_E_PKCS1_WRONG_PAD here. */
+ break;
+ }
+ }
+ break;
+ default:
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+ i++;
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+
+ if (MHD__gnutls_sset_datum (plaintext, &edata[i], esize - i) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_afree (edata);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD_gnutls_afree (edata);
+
+ return 0;
+}
+
+
+int
+MHD_gtls_rsa_verify (const MHD_gnutls_datum_t * vdata,
+ const MHD_gnutls_datum_t * ciphertext, mpi_t * params,
+ int params_len, int btype)
+{
+
+ MHD_gnutls_datum_t plain;
+ int ret;
+
+ /* decrypt signature */
+ if ((ret =
+ MHD_gtls_pkcs1_rsa_decrypt (&plain, ciphertext, params, params_len,
+ btype)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (plain.size != vdata->size)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_free_datum (&plain);
+ return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+ }
+
+ if (memcmp (plain.data, vdata->data, plain.size) != 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_free_datum (&plain);
+ return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+ }
+
+ MHD__gnutls_free_datum (&plain);
+
+ return 0; /* ok */
+}
+
+
+/* this is taken from gnupg
+ */
+
+/****************
+ * Emulate our old PK interface here - sometime in the future we might
+ * change the internal design to directly fit to libgcrypt.
+ */
+static int
+MHD__gnutls_pk_encrypt (int algo, mpi_t * resarr, mpi_t data,
+ mpi_t * pkey, int pkey_len)
+{
+ gcry_sexp_t s_ciph, s_data, s_pkey;
+ int rc = -1;
+
+ /* make a sexp from pkey */
+ switch (algo)
+ {
+ case GCRY_PK_RSA:
+ if (pkey_len >= 2)
+ rc = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(rsa(n%m)(e%m)))",
+ pkey[0], pkey[1]);
+ break;
+
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (rc != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* put the data into a simple list */
+ if (gcry_sexp_build (&s_data, NULL, "%m", data))
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_pkey);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* pass it to libgcrypt */
+ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+ gcry_sexp_release (s_data);
+ gcry_sexp_release (s_pkey);
+
+ if (rc != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PK_ENCRYPTION_FAILED;
+
+ }
+ else
+ { /* add better error handling or make gnupg use S-Exp directly */
+ gcry_sexp_t list = gcry_sexp_find_token (s_ciph, "a", 0);
+ if (list == NULL)
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_ciph);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ resarr[0] = gcry_sexp_nth_mpi (list, 1, 0);
+ gcry_sexp_release (list);
+
+ if (resarr[0] == NULL)
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_ciph);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+
+ gcry_sexp_release (s_ciph);
+ return rc;
+}
+
+static int
+MHD__gnutls_pk_decrypt (int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey,
+ int pkey_len)
+{
+ gcry_sexp_t s_plain, s_data, s_pkey;
+ int rc = -1;
+
+ /* make a sexp from pkey */
+ switch (algo)
+ {
+ case GCRY_PK_RSA:
+ if (pkey_len >= 6)
+ rc = gcry_sexp_build (&s_pkey, NULL,
+ "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
+ pkey[0], pkey[1], pkey[2], pkey[3],
+ pkey[4], pkey[5]);
+ break;
+
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (rc != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* put the data into a simple list */
+ if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data))
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_pkey);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* pass it to libgcrypt */
+ rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey);
+ gcry_sexp_release (s_data);
+ gcry_sexp_release (s_pkey);
+
+ if (rc != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PK_DECRYPTION_FAILED;
+
+ }
+ else
+ { /* add better error handling or make gnupg use S-Exp directly */
+ resarr[0] = gcry_sexp_nth_mpi (s_plain, 0, 0);
+
+ if (resarr[0] == NULL)
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_plain);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+
+ gcry_sexp_release (s_plain);
+ return rc;
+}
+
+
+/* in case of DSA puts into data, r,s
+ */
+static int
+MHD__gnutls_pk_sign (int algo, mpi_t * data, mpi_t hash, mpi_t * pkey,
+ int pkey_len)
+{
+ gcry_sexp_t s_hash, s_key, s_sig;
+ int rc = -1;
+
+ /* make a sexp from pkey */
+ switch (algo)
+ {
+ case GCRY_PK_DSA:
+ if (pkey_len >= 5)
+ rc = gcry_sexp_build (&s_key, NULL,
+ "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
+ pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]);
+ else
+ {
+ MHD_gnutls_assert ();
+ }
+
+ break;
+ case GCRY_PK_RSA:
+ if (pkey_len >= 6)
+ rc = gcry_sexp_build (&s_key, NULL,
+ "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
+ pkey[0], pkey[1], pkey[2], pkey[3],
+ pkey[4], pkey[5]);
+ else
+ {
+ MHD_gnutls_assert ();
+ }
+ break;
+
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (rc != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* put the data into a simple list */
+ if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* pass it to libgcrypt */
+ rc = gcry_pk_sign (&s_sig, s_hash, s_key);
+ gcry_sexp_release (s_hash);
+ gcry_sexp_release (s_key);
+
+ if (rc != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_PK_SIGN_FAILED;
+
+ }
+ else
+ {
+ gcry_sexp_t list;
+
+ if (algo == GCRY_PK_DSA)
+ {
+ list = gcry_sexp_find_token (s_sig, "r", 0);
+ if (list == NULL)
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_sig);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ data[0] = gcry_sexp_nth_mpi (list, 1, 0);
+ gcry_sexp_release (list);
+
+ list = gcry_sexp_find_token (s_sig, "s", 0);
+ if (list == NULL)
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_sig);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ data[1] = gcry_sexp_nth_mpi (list, 1, 0);
+ gcry_sexp_release (list);
+ }
+ else
+ { /* GCRY_PK_RSA */
+ list = gcry_sexp_find_token (s_sig, "s", 0);
+ if (list == NULL)
+ {
+ MHD_gnutls_assert ();
+ gcry_sexp_release (s_sig);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ data[0] = gcry_sexp_nth_mpi (list, 1, 0);
+ gcry_sexp_release (list);
+ }
+ }
+
+ gcry_sexp_release (s_sig);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.h
new file mode 100644
index 0000000000..4653e76e1c
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_pk.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_PK_H
+#define GNUTLS_PK_H
+
+int MHD_gtls_pkcs1_rsa_encrypt (MHD_gnutls_datum_t * ciphertext,
+ const MHD_gnutls_datum_t * plaintext,
+ mpi_t * params, unsigned params_len,
+ unsigned btype);
+int MHD_gtls_pkcs1_rsa_decrypt (MHD_gnutls_datum_t * plaintext,
+ const MHD_gnutls_datum_t * ciphertext,
+ mpi_t * params, unsigned params_len,
+ unsigned btype);
+int MHD_gtls_rsa_verify (const MHD_gnutls_datum_t * vdata,
+ const MHD_gnutls_datum_t * ciphertext,
+ mpi_t * params, int params_len, int btype);
+
+#endif /* GNUTLS_PK_H */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_priority.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_priority.c
new file mode 100644
index 0000000000..035c53dc4c
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_priority.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Here lies the code of the MHD_gnutls_*_set_priority() functions.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_algorithms.h"
+#include "gnutls_errors.h"
+#include <gnutls_num.h>
+
+#define MAX_ELEMENTS 48
+
+static int
+_set_priority (MHD_gtls_priority_st * st, const int *list)
+{
+ int num = 0;
+
+ while ((list[num] != 0) && (num < MAX_ALGOS))
+ num++;
+ st->num_algorithms = num;
+ memcpy (st->priority, list, num * sizeof (int));
+ return 0;
+}
+
+static const int MHD_gtls_protocol_priority[] = { MHD_GNUTLS_PROTOCOL_TLS1_1,
+ MHD_GNUTLS_PROTOCOL_TLS1_0,
+ MHD_GNUTLS_PROTOCOL_SSL3,
+ 0
+};
+
+static const int MHD_gtls_cipher_priority_secure256[] =
+ { MHD_GNUTLS_CIPHER_AES_256_CBC,
+ 0
+};
+
+static const int MHD_gtls_kx_priority_secure[] = { MHD_GNUTLS_KX_RSA,
+ 0
+};
+
+static const int MHD_gtls_mac_priority_secure[] = { MHD_GNUTLS_MAC_SHA1,
+ 0
+};
+
+static int MHD_gtls_cert_type_priority[] = { MHD_GNUTLS_CRT_X509,
+ 0
+};
+
+static const int MHD_gtls_comp_priority[] = { MHD_GNUTLS_COMP_NULL,
+ 0
+};
+
+/**
+ * MHD__gnutls_priority_set - Sets priorities for the cipher suites supported by gnutls.
+ * @session: is a #MHD_gtls_session_t structure.
+ * @priority: is a #MHD_gnutls_priority_t structure.
+ *
+ * Sets the priorities to use on the ciphers, key exchange methods,
+ * macs and compression methods.
+ *
+ * On success 0 is returned.
+ *
+ **/
+int
+MHD__gnutls_priority_set (MHD_gtls_session_t session,
+ MHD_gnutls_priority_t priority)
+{
+ if (priority == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_NO_CIPHER_SUITES;
+ }
+
+ memcpy (&session->internals.priorities, priority,
+ sizeof (struct MHD_gtls_priority_st));
+
+ return 0;
+}
+
+/**
+ * MHD_tls_set_default_priority - Sets priorities for the cipher suites supported by gnutls.
+ * @priority_cache: is a #MHD_gnutls_prioritity_t structure.
+ * @priorities: is a string describing priorities
+ * @err_pos: In case of an error this will have the position in the string the error occured
+ *
+ * Sets priorities for the ciphers, key exchange methods, macs and
+ * compression methods. This is to avoid using the
+ * MHD_gnutls_*_priority() functions.
+ *
+ * The #priorities option allows you to specify a semi-colon
+ * separated list of the cipher priorities to enable.
+ *
+ * Unless the first keyword is "NONE" the defaults are:
+ * Protocols: TLS1.1, TLS1.0, and SSL3.0.
+ * Compression: NULL.
+ * Certificate types: X.509, OpenPGP.
+ *
+ * You can also use predefined sets of ciphersuites: "PERFORMANCE"
+ * all the "secure" ciphersuites are enabled, limited to 128 bit
+ * ciphers and sorted by terms of speed performance.
+ *
+ * "NORMAL" option enables all "secure" ciphersuites. The 256-bit ciphers
+ * are included as a fallback only. The ciphers are sorted by security margin.
+ *
+ * "SECURE128" flag enables all "secure" ciphersuites with ciphers up to
+ * 128 bits, sorted by security margin.
+ *
+ * "SECURE256" flag enables all "secure" ciphersuites including the 256 bit
+ * ciphers, sorted by security margin.
+ *
+ * "EXPORT" all the ciphersuites are enabled, including the
+ * low-security 40 bit ciphers.
+ *
+ * "NONE" nothing is enabled. This disables even protocols and
+ * compression methods.
+ *
+ * Special keywords:
+ * '!' or '-' appended with an algorithm will remove this algorithm.
+ * '+' appended with an algorithm will add this algorithm.
+ * '%COMPAT' will enable compatibility features for a server.
+ *
+ * To avoid collisions in order to specify a compression algorithm in
+ * this string you have to prefix it with "COMP-", protocol versions
+ * with "VERS-" and certificate types with "CTYPE-". All other
+ * algorithms don't need a prefix.
+ *
+ * For key exchange algorithms when in NORMAL or SECURE levels the
+ * perfect forward secrecy algorithms take precendence of the other
+ * protocols. In all cases all the supported key exchange algorithms
+ * are enabled (except for the RSA-EXPORT which is only enabled in
+ * EXPORT level).
+ *
+ * Note that although one can select very long key sizes (such as 256 bits)
+ * for symmetric algorithms, to actually increase security the public key
+ * algorithms have to use longer key sizes as well.
+ *
+ * Examples: "NORMAL:!AES-128-CBC",
+ * "EXPORT:!VERS-TLS1.0:+COMP-DEFLATE:+CTYPE-OPENPGP",
+ * "NONE:+VERS-TLS1.0:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL", "NORMAL",
+ * "NORMAL:%COMPAT".
+ *
+ * Returns: On syntax error GNUTLS_E_INVALID_REQUEST is returned and
+ * 0 on success.
+ **/
+int
+MHD_tls_set_default_priority (MHD_gnutls_priority_t * priority_cache,
+ const char *priorities, const char **err_pos)
+{
+ *priority_cache =
+ MHD_gnutls_calloc (1, sizeof (struct MHD_gtls_priority_st));
+ if (*priority_cache == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* set mode to "SECURE256" */
+ _set_priority (&(*priority_cache)->protocol, MHD_gtls_protocol_priority);
+ _set_priority (&(*priority_cache)->cipher,
+ MHD_gtls_cipher_priority_secure256);
+ _set_priority (&(*priority_cache)->kx, MHD_gtls_kx_priority_secure);
+ _set_priority (&(*priority_cache)->mac, MHD_gtls_mac_priority_secure);
+ _set_priority (&(*priority_cache)->cert_type, MHD_gtls_cert_type_priority);
+ _set_priority (&(*priority_cache)->compression, MHD_gtls_comp_priority);
+
+ (*priority_cache)->no_padding = 0;
+ return 0;
+}
+
+/**
+ * MHD__gnutls_priority_deinit - Deinitialize the priorities cache for the cipher suites supported by gnutls.
+ * @priority_cache: is a #MHD_gnutls_prioritity_t structure.
+ *
+ * Deinitializes the priority cache.
+ *
+ **/
+void
+MHD__gnutls_priority_deinit (MHD_gnutls_priority_t priority_cache)
+{
+ MHD_gnutls_free (priority_cache);
+}
+
+/**
+ * MHD__gnutls_priority_set_direct - Sets priorities for the cipher suites supported by gnutls.
+ * @session: is a #MHD_gtls_session_t structure.
+ * @priorities: is a string describing priorities
+ * @err_pos: In case of an error this will have the position in the string the error occured
+ *
+ * Sets the priorities to use on the ciphers, key exchange methods,
+ * macs and compression methods. This function avoids keeping a
+ * priority cache and is used to directly set string priorities to a
+ * TLS session. For documentation check the MHD_tls_set_default_priority().
+ *
+ * On syntax error GNUTLS_E_INVALID_REQUEST is returned and 0 on success.
+ *
+ **/
+int
+MHD__gnutls_priority_set_direct (MHD_gtls_session_t session,
+ const char *priorities, const char **err_pos)
+{
+ MHD_gnutls_priority_t prio;
+ int ret;
+
+ ret = MHD_tls_set_default_priority (&prio, priorities, err_pos);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD__gnutls_priority_set (session, prio);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD__gnutls_priority_deinit (prio);
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.c
new file mode 100644
index 0000000000..07a7b46c47
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.c
@@ -0,0 +1,1087 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that are record layer specific, are included in this file.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "debug.h"
+#include "gnutls_cipher.h"
+#include "gnutls_buffers.h"
+#include "gnutls_handshake.h"
+#include "gnutls_hash_int.h"
+#include "gnutls_cipher_int.h"
+#include "gnutls_algorithms.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_num.h"
+#include "gnutls_record.h"
+#include "gnutls_datum.h"
+#include "ext_max_record.h"
+#include <gnutls_state.h>
+#include <gnutls_dh.h>
+
+/**
+ * MHD__gnutls_protocol_get_version - Returns the version of the currently used protocol
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * Returns: the version of the currently used protocol.
+ **/
+enum MHD_GNUTLS_Protocol
+MHD__gnutls_protocol_get_version (MHD_gtls_session_t session)
+{
+ return session->security_parameters.version;
+}
+
+void
+MHD_gtls_set_current_version (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_Protocol version)
+{
+ session->security_parameters.version = version;
+}
+
+/**
+ * MHD__gnutls_transport_set_lowat - Used to set the lowat value in order for select to check for pending data.
+ * @session: is a #MHD_gtls_session_t structure.
+ * @num: is the low water value.
+ *
+ * Used to set the lowat value in order for select to check if there
+ * are pending data to socket buffer. Used only if you have changed
+ * the default low water value (default is 1). Normally you will not
+ * need that function. This function is only useful if using
+ * berkeley style sockets. Otherwise it must be called and set lowat
+ * to zero.
+ **/
+void
+MHD__gnutls_transport_set_lowat (MHD_gtls_session_t session, int num)
+{
+ session->internals.lowat = num;
+}
+
+/**
+ * MHD__gnutls_transport_set_ptr - Used to set first argument of the transport functions
+ * @session: is a #MHD_gtls_session_t structure.
+ * @ptr: is the value.
+ *
+ * Used to set the first argument of the transport function (like
+ * PUSH and PULL). In berkeley style sockets this function will set
+ * the connection handle.
+ **/
+void
+MHD__gnutls_transport_set_ptr (MHD_gtls_session_t session,
+ MHD_gnutls_transport_ptr_t ptr)
+{
+ session->internals.transport_recv_ptr = ptr;
+ session->internals.transport_send_ptr = ptr;
+}
+
+/**
+ * MHD__gnutls_bye - This function terminates the current TLS/SSL connection.
+ * @session: is a #MHD_gtls_session_t structure.
+ * @how: is an integer
+ *
+ * Terminates the current TLS/SSL connection. The connection should
+ * have been initiated using MHD__gnutls_handshake(). @how should be one
+ * of %GNUTLS_SHUT_RDWR, %GNUTLS_SHUT_WR.
+ *
+ * In case of %GNUTLS_SHUT_RDWR then the TLS connection gets
+ * terminated and further receives and sends will be disallowed. If
+ * the return value is zero you may continue using the connection.
+ * %GNUTLS_SHUT_RDWR actually sends an alert containing a close
+ * request and waits for the peer to reply with the same message.
+ *
+ * In case of %GNUTLS_SHUT_WR then the TLS connection gets terminated
+ * and further sends will be disallowed. In order to reuse the
+ * connection you should wait for an EOF from the peer.
+ * %GNUTLS_SHUT_WR sends an alert containing a close request.
+ *
+ * Note that not all implementations will properly terminate a TLS
+ * connection. Some of them, usually for performance reasons, will
+ * terminate only the underlying transport layer, thus causing a
+ * transmission error to the peer. This error cannot be
+ * distinguished from a malicious party prematurely terminating the
+ * session, thus this behavior is not recommended.
+ *
+ * This function may also return %GNUTLS_E_AGAIN or
+ * %GNUTLS_E_INTERRUPTED; cf. MHD__gnutls_record_get_direction().
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code, see
+ * function documentation for entire semantics.
+ **/
+int
+MHD__gnutls_bye (MHD_gtls_session_t session, MHD_gnutls_close_request_t how)
+{
+ int ret = 0;
+
+ switch (STATE)
+ {
+ case STATE0:
+ case STATE60:
+ ret = MHD_gtls_io_write_flush (session);
+ STATE = STATE60;
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ case STATE61:
+ ret =
+ MHD__gnutls_alert_send (session, GNUTLS_AL_WARNING,
+ GNUTLS_A_CLOSE_NOTIFY);
+ STATE = STATE61;
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ case STATE62:
+ STATE = STATE62;
+ if (how == GNUTLS_SHUT_RDWR)
+ {
+ do
+ {
+ MHD_gtls_io_clear_peeked_data (session);
+ ret = MHD_gtls_recv_int (session, GNUTLS_ALERT, -1, NULL, 0);
+ }
+ while (ret == GNUTLS_E_GOT_APPLICATION_DATA);
+
+ if (ret >= 0)
+ session->internals.may_not_read = 1;
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ STATE = STATE62;
+
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ STATE = STATE0;
+
+ session->internals.may_not_write = 1;
+ return 0;
+}
+
+inline static void
+session_invalidate (MHD_gtls_session_t session)
+{
+ session->internals.valid_connection = VALID_FALSE;
+}
+
+inline static void
+session_unresumable (MHD_gtls_session_t session)
+{
+ session->internals.resumable = RESUME_FALSE;
+}
+
+/* returns 0 if session is valid
+ */
+inline static int
+session_is_valid (MHD_gtls_session_t session)
+{
+ if (session->internals.valid_connection == VALID_FALSE)
+ return GNUTLS_E_INVALID_SESSION;
+
+ return 0;
+}
+
+/* Copies the record version into the headers. The
+ * version must have 2 bytes at least.
+ */
+inline static void
+copy_record_version (MHD_gtls_session_t session,
+ MHD_gnutls_handshake_description_t htype,
+ opaque version[2])
+{
+ enum MHD_GNUTLS_Protocol lver;
+
+ if (htype != GNUTLS_HANDSHAKE_CLIENT_HELLO
+ || session->internals.default_record_version[0] == 0)
+ {
+ lver = MHD__gnutls_protocol_get_version (session);
+
+ version[0] = MHD_gtls_version_get_major (lver);
+ version[1] = MHD_gtls_version_get_minor (lver);
+ }
+ else
+ {
+ version[0] = session->internals.default_record_version[0];
+ version[1] = session->internals.default_record_version[1];
+ }
+}
+
+/* This function behaves exactly like write(). The only difference is
+ * that it accepts, the MHD_gtls_session_t and the content_type_t of data to
+ * send (if called by the user the Content is specific)
+ * It is intended to transfer data, under the current session.
+ *
+ * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
+ * This makes the function much easier to read, and more error resistant
+ * (there were cases were the old function could mess everything up).
+ * --nmav
+ *
+ * This function may accept a NULL pointer for data, and 0 for size, if
+ * and only if the previous send was interrupted for some reason.
+ *
+ */
+ssize_t
+MHD_gtls_send_int (MHD_gtls_session_t session,
+ content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ const void *_data, size_t sizeofdata)
+{
+ uint8_t *cipher;
+ int cipher_size;
+ int retval, ret;
+ int data2send_size;
+ uint8_t headers[5];
+ const uint8_t *data = _data;
+
+ /* Do not allow null pointer if the send buffer is empty.
+ * If the previous send was interrupted then a null pointer is
+ * ok, and means to resume.
+ */
+ if (session->internals.record_send_buffer.length == 0 && (sizeofdata == 0
+ && _data == NULL))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (type != GNUTLS_ALERT) /* alert messages are sent anyway */
+ if (session_is_valid (session) || session->internals.may_not_write != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_SESSION;
+ }
+
+ headers[0] = type;
+
+ /* Use the default record version, if it is
+ * set.
+ */
+ copy_record_version (session, htype, &headers[1]);
+
+ MHD__gnutls_record_log
+ ("REC[%x]: Sending Packet[%d] %s(%d) with length: %d\n", session,
+ (int) MHD_gtls_uint64touint32 (&session->connection_state.
+ write_sequence_number),
+ MHD__gnutls_packet2str (type), type, sizeofdata);
+
+ if (sizeofdata > MAX_RECORD_SEND_SIZE)
+ data2send_size = MAX_RECORD_SEND_SIZE;
+ else
+ data2send_size = sizeofdata;
+
+ /* Only encrypt if we don't have data to send
+ * from the previous run. - probably interrupted.
+ */
+ if (session->internals.record_send_buffer.length > 0)
+ {
+ ret = MHD_gtls_io_write_flush (session);
+ if (ret > 0)
+ cipher_size = ret;
+ else
+ cipher_size = 0;
+
+ cipher = NULL;
+
+ retval = session->internals.record_send_buffer_user_size;
+ }
+ else
+ {
+ /* now proceed to packet encryption
+ */
+ cipher_size = data2send_size + MAX_RECORD_OVERHEAD;
+ cipher = MHD_gnutls_malloc (cipher_size);
+ if (cipher == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ cipher_size =
+ MHD_gtls_encrypt (session, headers, RECORD_HEADER_SIZE, data,
+ data2send_size, cipher, cipher_size, type,
+ (session->internals.priorities.no_padding ==
+ 0) ? 1 : 0);
+ if (cipher_size <= 0)
+ {
+ MHD_gnutls_assert ();
+ if (cipher_size == 0)
+ cipher_size = GNUTLS_E_ENCRYPTION_FAILED;
+ MHD_gnutls_free (cipher);
+ return cipher_size; /* error */
+ }
+
+ retval = data2send_size;
+ session->internals.record_send_buffer_user_size = data2send_size;
+
+ /* increase sequence number
+ */
+ if (MHD_gtls_uint64pp
+ (&session->connection_state.write_sequence_number) != 0)
+ {
+ session_invalidate (session);
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (cipher);
+ return GNUTLS_E_RECORD_LIMIT_REACHED;
+ }
+
+ ret = MHD_gtls_io_write_buffered (session, cipher, cipher_size);
+ MHD_gnutls_free (cipher);
+ }
+
+ if (ret != cipher_size)
+ {
+ if (ret < 0 && MHD_gtls_error_is_fatal (ret) == 0)
+ {
+ /* If we have sent any data then just return
+ * the error value. Do not invalidate the session.
+ */
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (ret > 0)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ }
+ session_unresumable (session);
+ session->internals.may_not_write = 1;
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ session->internals.record_send_buffer_user_size = 0;
+
+ MHD__gnutls_record_log ("REC[%x]: Sent Packet[%d] %s(%d) with length: %d\n",
+ session,
+ (int)
+ MHD_gtls_uint64touint32
+ (&session->connection_state.write_sequence_number),
+ MHD__gnutls_packet2str (type), type, cipher_size);
+
+ return retval;
+}
+
+/* This function is to be called if the handshake was successfully
+ * completed. This sends a Change Cipher Spec packet to the peer.
+ */
+ssize_t
+MHD_gtls_send_change_cipher_spec (MHD_gtls_session_t session, int again)
+{
+ static const opaque data[1] = {
+ GNUTLS_TYPE_CHANGE_CIPHER_SPEC
+ };
+
+ MHD__gnutls_handshake_log ("REC[%x]: Sent ChangeCipherSpec\n", session);
+
+ if (again == 0)
+ return MHD_gtls_send_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, data,
+ 1);
+ else
+ {
+ return MHD_gtls_io_write_flush (session);
+ }
+}
+
+inline static int
+check_recv_type (content_type_t recv_type)
+{
+ switch (recv_type)
+ {
+ case GNUTLS_CHANGE_CIPHER_SPEC:
+ case GNUTLS_ALERT:
+ case GNUTLS_HANDSHAKE:
+ case GNUTLS_APPLICATION_DATA:
+ case GNUTLS_INNER_APPLICATION:
+ return 0;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_A_UNEXPECTED_MESSAGE;
+ }
+
+}
+
+/* Checks if there are pending data in the record buffers. If there are
+ * then it copies the data.
+ */
+static int
+check_buffers (MHD_gtls_session_t session,
+ content_type_t type, opaque * data, int sizeofdata)
+{
+ if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE || type
+ == GNUTLS_INNER_APPLICATION)
+ && MHD_gnutls_record_buffer_get_size (type, session) > 0)
+ {
+ int ret, ret2;
+ ret = MHD_gtls_record_buffer_get (type, session, data, sizeofdata);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* if the buffer just got empty */
+ if (MHD_gnutls_record_buffer_get_size (type, session) == 0)
+ {
+ if ((ret2 = MHD_gtls_io_clear_peeked_data (session)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret2;
+ }
+ }
+
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Checks the record headers and returns the length, version and
+ * content type.
+ */
+static int
+record_check_headers (MHD_gtls_session_t session,
+ uint8_t headers[RECORD_HEADER_SIZE],
+ content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ /*output */ content_type_t * recv_type,
+ opaque version[2],
+ uint16_t * length, uint16_t * header_size)
+{
+
+ /* Read the first two bytes to determine if this is a
+ * version 2 message
+ */
+
+ if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO && type == GNUTLS_HANDSHAKE
+ && headers[0] > 127)
+ {
+
+ /* if msb set and expecting handshake message
+ * it should be SSL 2 hello
+ */
+ version[0] = 3; /* assume SSL 3.0 */
+ version[1] = 0;
+
+ *length = (((headers[0] & 0x7f) << 8)) | headers[1];
+
+ /* SSL 2.0 headers */
+ *header_size = 2;
+ *recv_type = GNUTLS_HANDSHAKE; /* we accept only v2 client hello
+ */
+
+ /* in order to assist the handshake protocol.
+ * V2 compatibility is a mess.
+ */
+ session->internals.v2_hello = *length;
+
+ MHD__gnutls_record_log ("REC[%x]: V2 packet received. Length: %d\n",
+ session, *length);
+
+ }
+ else
+ {
+ /* version 3.x */
+ *recv_type = headers[0];
+ version[0] = headers[1];
+ version[1] = headers[2];
+
+ /* No DECR_LEN, since headers has enough size.
+ */
+ *length = MHD_gtls_read_uint16 (&headers[3]);
+ }
+
+ return 0;
+}
+
+/* Here we check if the advertized version is the one we
+ * negotiated in the handshake.
+ */
+inline static int
+record_check_version (MHD_gtls_session_t session,
+ MHD_gnutls_handshake_description_t htype,
+ opaque version[2])
+{
+ if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO)
+ {
+ /* Reject hello packets with major version higher than 3.
+ */
+ if (version[0] > 3)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_record_log
+ ("REC[%x]: INVALID VERSION PACKET: (%d) %d.%d\n", session,
+ htype, version[0], version[1]);
+ return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+ }
+ }
+ else if (htype != GNUTLS_HANDSHAKE_SERVER_HELLO
+ && MHD__gnutls_protocol_get_version (session)
+ != MHD_gtls_version_get (version[0], version[1]))
+ {
+ /* Reject record packets that have a different version than the
+ * one negotiated. Note that this version is not protected by any
+ * mac. I don't really think that this check serves any purpose.
+ */
+ MHD_gnutls_assert ();
+ MHD__gnutls_record_log ("REC[%x]: INVALID VERSION PACKET: (%d) %d.%d\n",
+ session, htype, version[0], version[1]);
+
+ return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
+ }
+
+ return 0;
+}
+
+/* This function will check if the received record type is
+ * the one we actually expect.
+ */
+static int
+record_check_type (MHD_gtls_session_t session,
+ content_type_t recv_type,
+ content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ opaque * data, int data_size)
+{
+
+ int ret;
+
+ if ((recv_type == type) && (type == GNUTLS_APPLICATION_DATA || type
+ == GNUTLS_HANDSHAKE
+ || type == GNUTLS_INNER_APPLICATION))
+ {
+ MHD_gnutls_record_buffer_put (type, session, (void *) data, data_size);
+ }
+ else
+ {
+ switch (recv_type)
+ {
+ case GNUTLS_ALERT:
+
+ MHD__gnutls_record_log
+ ("REC[%x]: Alert[%d|%d] - %s - was received\n", session,
+ data[0], data[1], MHD__gnutls_alert_get_name ((int) data[1]));
+
+ session->internals.last_alert = data[1];
+ session->internals.last_alert_level = data[0];
+
+ /* if close notify is received and
+ * the alert is not fatal
+ */
+ if (data[1] == GNUTLS_A_CLOSE_NOTIFY && data[0] != GNUTLS_AL_FATAL)
+ {
+ /* If we have been expecting for an alert do
+ */
+ session->internals.read_eof = 1;
+ return GNUTLS_E_INT_RET_0; /* EOF */
+ }
+ else
+ {
+
+ /* if the alert is FATAL or WARNING
+ * return the apropriate message
+ */
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
+ if (data[0] == GNUTLS_AL_FATAL)
+ {
+ session_unresumable (session);
+ session_invalidate (session);
+ ret = GNUTLS_E_FATAL_ALERT_RECEIVED;
+ }
+
+ return ret;
+ }
+ break;
+
+ case GNUTLS_CHANGE_CIPHER_SPEC:
+ /* this packet is now handled in the recv_int()
+ * function
+ */
+ MHD_gnutls_assert ();
+
+ return GNUTLS_E_UNEXPECTED_PACKET;
+
+ case GNUTLS_APPLICATION_DATA:
+ /* even if data is unexpected put it into the buffer */
+ if ((ret =
+ MHD_gnutls_record_buffer_put (recv_type, session,
+ (void *) data, data_size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* the got_application data is only returned
+ * if expecting client hello (for rehandshake
+ * reasons). Otherwise it is an unexpected packet
+ */
+ if (type == GNUTLS_ALERT || (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO
+ && type == GNUTLS_HANDSHAKE))
+ return GNUTLS_E_GOT_APPLICATION_DATA;
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET;
+ }
+
+ break;
+ case GNUTLS_HANDSHAKE:
+ /* This is legal if HELLO_REQUEST is received - and we are a client.
+ * If we are a server, a client may initiate a renegotiation at any time.
+ */
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_REHANDSHAKE;
+ }
+
+ /* If we are already in a handshake then a Hello
+ * Request is illegal. But here we don't really care
+ * since this message will never make it up here.
+ */
+
+ /* So we accept it */
+ return MHD_gtls_recv_hello_request (session, data, data_size);
+
+ break;
+ case GNUTLS_INNER_APPLICATION:
+ /* even if data is unexpected put it into the buffer */
+ if ((ret =
+ MHD_gnutls_record_buffer_put (recv_type, session,
+ (void *) data, data_size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET;
+ break;
+ default:
+
+ MHD__gnutls_record_log
+ ("REC[%x]: Received Unknown packet %d expecting %d\n",
+ session, recv_type, type);
+
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+
+ return 0;
+
+}
+
+/* This function will return the internal (per session) temporary
+ * recv buffer. If the buffer was not initialized before it will
+ * also initialize it.
+ */
+inline static int
+get_temp_recv_buffer (MHD_gtls_session_t session, MHD_gnutls_datum_t * tmp)
+{
+ size_t max_record_size;
+
+ max_record_size = MAX_RECORD_RECV_SIZE;
+
+ /* We allocate MAX_RECORD_RECV_SIZE length
+ * because we cannot predict the output data by the record
+ * packet length (due to compression).
+ */
+
+ if (max_record_size > session->internals.recv_buffer.size
+ || session->internals.recv_buffer.data == NULL)
+ {
+
+ /* Initialize the internal buffer.
+ */
+ session->internals.recv_buffer.data
+ =
+ MHD_gnutls_realloc (session->internals.recv_buffer.data,
+ max_record_size);
+
+ if (session->internals.recv_buffer.data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ session->internals.recv_buffer.size = max_record_size;
+ }
+
+ tmp->data = session->internals.recv_buffer.data;
+ tmp->size = session->internals.recv_buffer.size;
+
+ return 0;
+}
+
+#define MAX_EMPTY_PACKETS_SEQUENCE 4
+
+/* This function behaves exactly like read(). The only difference is
+ * that it accepts the MHD_gtls_session_t and the content_type_t of data to
+ * receive (if called by the user the Content is Userdata only)
+ * It is intended to receive data, under the current session.
+ *
+ * The MHD_gnutls_handshake_description_t was introduced to support SSL V2.0 client hellos.
+ */
+ssize_t
+MHD_gtls_recv_int (MHD_gtls_session_t session,
+ content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ opaque * data, size_t sizeofdata)
+{
+ MHD_gnutls_datum_t tmp;
+ int decrypted_length;
+ opaque version[2];
+ uint8_t *headers;
+ content_type_t recv_type;
+ uint16_t length;
+ uint8_t *ciphertext;
+ uint8_t *recv_data;
+ int ret, ret2;
+ uint16_t header_size;
+ int empty_packet = 0;
+
+ if (type != GNUTLS_ALERT && (sizeofdata == 0 || data == NULL))
+ {
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+begin:
+
+ if (empty_packet > MAX_EMPTY_PACKETS_SEQUENCE)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_TOO_MANY_EMPTY_PACKETS;
+ }
+
+ if (session->internals.read_eof != 0)
+ {
+ /* if we have already read an EOF
+ */
+ return 0;
+ }
+ else if (session_is_valid (session) != 0 || session->internals.may_not_read
+ != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_SESSION;
+ }
+
+ /* If we have enough data in the cache do not bother receiving
+ * a new packet. (in order to flush the cache)
+ */
+ ret = check_buffers (session, type, data, sizeofdata);
+ if (ret != 0)
+ return ret;
+
+ /* default headers for TLS 1.0
+ */
+ header_size = RECORD_HEADER_SIZE;
+
+ if ((ret = MHD_gtls_io_read_buffered (session, &headers, header_size, -1))
+ != header_size)
+ {
+ if (ret < 0 && MHD_gtls_error_is_fatal (ret) == 0)
+ return ret;
+
+ session_invalidate (session);
+ if (type == GNUTLS_ALERT)
+ {
+ MHD_gnutls_assert ();
+ return 0; /* we were expecting close notify */
+ }
+ session_unresumable (session);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ if ((ret = record_check_headers (session, headers, type, htype, &recv_type,
+ version, &length, &header_size)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* Here we check if the Type of the received packet is
+ * ok.
+ */
+ if ((ret = check_recv_type (recv_type)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* Here we check if the advertized version is the one we
+ * negotiated in the handshake.
+ */
+ if ((ret = record_check_version (session, htype, version)) < 0)
+ {
+ MHD_gnutls_assert ();
+ session_invalidate (session);
+ return ret;
+ }
+
+ MHD__gnutls_record_log
+ ("REC[%x]: Expected Packet[%d] %s(%d) with length: %d\n", session,
+ (int) MHD_gtls_uint64touint32 (&session->connection_state.
+ read_sequence_number),
+ MHD__gnutls_packet2str (type), type, sizeofdata);
+ MHD__gnutls_record_log
+ ("REC[%x]: Received Packet[%d] %s(%d) with length: %d\n", session,
+ (int) MHD_gtls_uint64touint32 (&session->connection_state.
+ read_sequence_number),
+ MHD__gnutls_packet2str (recv_type), recv_type, length);
+
+ if (length > MAX_RECV_SIZE)
+ {
+ MHD__gnutls_record_log
+ ("REC[%x]: FATAL ERROR: Received packet with length: %d\n",
+ session, length);
+
+ session_unresumable (session);
+ session_invalidate (session);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ /* check if we have that data into buffer.
+ */
+ if ((ret = MHD_gtls_io_read_buffered (session, &recv_data,
+ header_size + length, recv_type))
+ != header_size + length)
+ {
+ if (ret < 0 && MHD_gtls_error_is_fatal (ret) == 0)
+ return ret;
+
+ session_unresumable (session);
+ session_invalidate (session);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+
+ /* ok now we are sure that we can read all the data - so
+ * move on !
+ */
+ MHD_gtls_io_clear_read_buffer (session);
+ ciphertext = &recv_data[header_size];
+
+ ret = get_temp_recv_buffer (session, &tmp);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* decrypt the data we got. */
+ ret = MHD_gtls_decrypt (session, ciphertext, length, tmp.data, tmp.size,
+ recv_type);
+ if (ret < 0)
+ {
+ session_unresumable (session);
+ session_invalidate (session);
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ decrypted_length = ret;
+
+ /* Check if this is a CHANGE_CIPHER_SPEC
+ */
+ if (type == GNUTLS_CHANGE_CIPHER_SPEC && recv_type
+ == GNUTLS_CHANGE_CIPHER_SPEC)
+ {
+
+ MHD__gnutls_record_log
+ ("REC[%x]: ChangeCipherSpec Packet was received\n", session);
+
+ if ((size_t) ret != sizeofdata)
+ { /* sizeofdata should be 1 */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ }
+ memcpy (data, tmp.data, sizeofdata);
+
+ return ret;
+ }
+
+ MHD__gnutls_record_log
+ ("REC[%x]: Decrypted Packet[%d] %s(%d) with length: %d\n", session,
+ (int) MHD_gtls_uint64touint32 (&session->connection_state.
+ read_sequence_number),
+ MHD__gnutls_packet2str (recv_type), recv_type, decrypted_length);
+
+ /* increase sequence number
+ */
+ if (MHD_gtls_uint64pp (&session->connection_state.read_sequence_number) !=
+ 0)
+ {
+ session_invalidate (session);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RECORD_LIMIT_REACHED;
+ }
+
+ /* check type - this will also invalidate sessions if a fatal alert has been received */
+ ret = record_check_type (session, recv_type, type, htype, tmp.data,
+ decrypted_length);
+ if (ret < 0)
+ {
+ if (ret == GNUTLS_E_INT_RET_0)
+ return 0;
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* Get Application data from buffer
+ */
+ if ((recv_type == type) && (type == GNUTLS_APPLICATION_DATA || type
+ == GNUTLS_HANDSHAKE
+ || type == GNUTLS_INNER_APPLICATION))
+ {
+
+ ret = MHD_gtls_record_buffer_get (type, session, data, sizeofdata);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* if the buffer just got empty
+ */
+ if (MHD_gnutls_record_buffer_get_size (type, session) == 0)
+ {
+ if ((ret2 = MHD_gtls_io_clear_peeked_data (session)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret2;
+ }
+ }
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_UNEXPECTED_PACKET;
+ /* we didn't get what we wanted to
+ */
+ }
+
+ /* (originally for) TLS 1.0 CBC protection.
+ * Actually this code is called if we just received
+ * an empty packet. An empty TLS packet is usually
+ * sent to protect some vulnerabilities in the CBC mode.
+ * In that case we go to the beginning and start reading
+ * the next packet.
+ */
+ if (ret == 0)
+ {
+ empty_packet++;
+ goto begin;
+ }
+
+ return ret;
+}
+
+/**
+ * MHD__gnutls_record_send - sends to the peer the specified data
+ * @session: is a #MHD_gtls_session_t structure.
+ * @data: contains the data to send
+ * @sizeofdata: is the length of the data
+ *
+ * This function has the similar semantics with send(). The only
+ * difference is that is accepts a GNUTLS session, and uses different
+ * error codes.
+ *
+ * Note that if the send buffer is full, send() will block this
+ * function. See the send() documentation for full information. You
+ * can replace the default push function by using
+ * MHD__gnutls_transport_set_ptr2() with a call to send() with a
+ * MSG_DONTWAIT flag if blocking is a problem.
+ *
+ * If the EINTR is returned by the internal push function (the
+ * default is send()} then %GNUTLS_E_INTERRUPTED will be returned. If
+ * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
+ * call this function again, with the same parameters; alternatively
+ * you could provide a %NULL pointer for data, and 0 for
+ * size. cf. MHD__gnutls_record_get_direction().
+ *
+ * Returns: the number of bytes sent, or a negative error code. The
+ * number of bytes sent might be less than @sizeofdata. The maximum
+ * number of bytes this function can send in a single call depends on
+ * the negotiated maximum record size.
+ **/
+ssize_t
+MHD__gnutls_record_send (MHD_gtls_session_t session,
+ const void *data, size_t sizeofdata)
+{
+ return MHD_gtls_send_int (session, GNUTLS_APPLICATION_DATA, -1, data,
+ sizeofdata);
+}
+
+/**
+ * MHD__gnutls_record_recv - reads data from the TLS record protocol
+ * @session: is a #MHD_gtls_session_t structure.
+ * @data: the buffer that the data will be read into
+ * @sizeofdata: the number of requested bytes
+ *
+ * This function has the similar semantics with recv(). The only
+ * difference is that is accepts a GNUTLS session, and uses different
+ * error codes.
+ *
+ * In the special case that a server requests a renegotiation, the
+ * client may receive an error code of %GNUTLS_E_REHANDSHAKE. This
+ * message may be simply ignored, replied with an alert containing
+ * NO_RENEGOTIATION, or replied with a new handshake, depending on
+ * the client's will.
+ *
+ * If %EINTR is returned by the internal push function (the default
+ * is recv()) then %GNUTLS_E_INTERRUPTED will be returned. If
+ * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
+ * call this function again to get the data. See also
+ * MHD__gnutls_record_get_direction().
+ *
+ * A server may also receive %GNUTLS_E_REHANDSHAKE when a client has
+ * initiated a handshake. In that case the server can only initiate a
+ * handshake or terminate the connection.
+ *
+ * Returns: the number of bytes received and zero on EOF. A negative
+ * error code is returned in case of an error. The number of bytes
+ * received might be less than @sizeofdata.
+ **/
+ssize_t
+MHD__gnutls_record_recv (MHD_gtls_session_t session, void *data,
+ size_t sizeofdata)
+{
+ return MHD_gtls_recv_int (session, GNUTLS_APPLICATION_DATA, -1, data,
+ sizeofdata);
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.h
new file mode 100644
index 0000000000..fe7300b62b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_record.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+ssize_t MHD_gtls_send_int (MHD_gtls_session_t session, content_type_t type,
+ MHD_gnutls_handshake_description_t htype,
+ const void *data, size_t sizeofdata);
+ssize_t MHD_gtls_recv_int (MHD_gtls_session_t session, content_type_t type,
+ MHD_gnutls_handshake_description_t, opaque * data,
+ size_t sizeofdata);
+ssize_t MHD_gtls_send_change_cipher_spec (MHD_gtls_session_t session,
+ int again);
+void MHD__gnutls_transport_set_lowat (MHD_gtls_session_t session, int num);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.c
new file mode 100644
index 0000000000..65f97c76a1
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains code for RSA temporary keys. These keys are
+ * only used in export cipher suites.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <gnutls_rsa_export.h>
+#include "debug.h"
+/* x509 */
+#include "x509.h"
+#include "privkey.h"
+
+/* returns e and m, depends on the requested bits.
+ * We only support limited key sizes.
+ */
+const mpi_t *
+MHD__gnutls_rsa_params_to_mpi (MHD_gtls_rsa_params_t rsa_params)
+{
+ if (rsa_params == NULL)
+ {
+ return NULL;
+ }
+ return rsa_params->params;
+}
+
+
+/**
+ * MHD__gnutls_rsa_params_deinit - This function will deinitialize the RSA parameters
+ * @rsa_params: Is a structure that holds the parameters
+ *
+ * This function will deinitialize the RSA parameters structure.
+ *
+ **/
+void
+MHD__gnutls_rsa_params_deinit (MHD_gtls_rsa_params_t rsa_params)
+{
+ MHD_gnutls_x509_privkey_deinit (rsa_params);
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.h
new file mode 100644
index 0000000000..a28f429733
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_rsa_export.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+const mpi_t *MHD__gnutls_rsa_params_to_mpi (MHD_gtls_rsa_params_t);
+int MHD__gnutls_peers_cert_less_512 (MHD_gtls_session_t session);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.c
new file mode 100644
index 0000000000..e27c468413
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2001, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <x509_b64.h>
+#include <auth_cert.h>
+#include <gnutls_cert.h>
+#include <gnutls_datum.h>
+#include <gnutls_mpi.h>
+#include <gnutls_global.h>
+#include <gnutls_pk.h>
+#include <debug.h>
+#include <gnutls_buffers.h>
+#include <gnutls_sig.h>
+#include <gnutls_kx.h>
+
+static int MHD__gnutls_tls_sign (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_privkey * pkey,
+ const MHD_gnutls_datum_t * hash_concat,
+ MHD_gnutls_datum_t * signature);
+
+/* Generates a signature of all the previous sent packets in the
+ * handshake procedure. (20040227: now it works for SSL 3.0 as well)
+ */
+int
+MHD_gtls_tls_sign_hdata (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_privkey * pkey,
+ MHD_gnutls_datum_t * signature)
+{
+ MHD_gnutls_datum_t dconcat;
+ int ret;
+ opaque concat[36];
+ mac_hd_t td_md5;
+ mac_hd_t td_sha;
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
+ if (td_sha == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ ret = MHD_gtls_generate_master (session, 1);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gnutls_mac_deinit_ssl3_handshake (td_sha, &concat[16],
+ session->security_parameters.
+ master_secret, TLS_MASTER_SIZE);
+ }
+ else
+ MHD_gnutls_hash_deinit (td_sha, &concat[16]);
+
+ switch (cert->subject_pk_algorithm)
+ {
+ case MHD_GNUTLS_PK_RSA:
+ td_md5 =
+ MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
+ if (td_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
+ MHD_gnutls_mac_deinit_ssl3_handshake (td_md5, concat,
+ session->security_parameters.
+ master_secret, TLS_MASTER_SIZE);
+ else
+ MHD_gnutls_hash_deinit (td_md5, concat);
+
+ dconcat.data = concat;
+ dconcat.size = 36;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ ret = MHD__gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ }
+
+ return ret;
+}
+
+/* Generates a signature of all the random data and the parameters.
+ * Used in DHE_* ciphersuites.
+ */
+int
+MHD_gtls_tls_sign_params (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_privkey * pkey,
+ MHD_gnutls_datum_t * params,
+ MHD_gnutls_datum_t * signature)
+{
+ MHD_gnutls_datum_t dconcat;
+ int ret;
+ mac_hd_t td_sha;
+ opaque concat[36];
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ td_sha = MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
+ if (td_sha == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td_sha, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_sha, session->security_parameters.server_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_sha, params->data, params->size);
+
+ switch (cert->subject_pk_algorithm)
+ {
+ case MHD_GNUTLS_PK_RSA:
+ if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ mac_hd_t td_md5 = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
+ if (td_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td_md5, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_md5, session->security_parameters.server_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_md5, params->data, params->size);
+
+ MHD_gnutls_hash_deinit (td_md5, concat);
+ MHD_gnutls_hash_deinit (td_sha, &concat[16]);
+
+ dconcat.size = 36;
+ }
+ else
+ {
+#if 1
+ /* Use NULL parameters. */
+ memcpy (concat,
+ "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
+ 15);
+ MHD_gnutls_hash_deinit (td_sha, &concat[15]);
+ dconcat.size = 35;
+#else
+ /* No parameters field. */
+ memcpy (concat,
+ "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
+ MHD_gnutls_hash_deinit (td_sha, &concat[13]);
+ dconcat.size = 33;
+#endif
+ }
+ dconcat.data = concat;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ MHD_gnutls_hash_deinit (td_sha, NULL);
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ ret = MHD__gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ }
+
+ return ret;
+
+}
+
+/* This will create a PKCS1 or DSA signature, using the given parameters, and the
+ * given data. The output will be allocated and be put in signature.
+ */
+static int
+MHD_gtls_sign (enum MHD_GNUTLS_PublicKeyAlgorithm algo,
+ mpi_t * params,
+ int params_size,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_datum_t * signature)
+{
+ int ret;
+
+ switch (algo)
+ {
+ case MHD_GNUTLS_PK_RSA:
+ /* encrypt */
+ if ((ret =
+ MHD_gtls_pkcs1_rsa_encrypt (signature, data, params, params_size,
+ 1)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ break;
+ }
+
+ return 0;
+}
+
+/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
+ * Cert is the certificate of the corresponding private key. It is only checked if
+ * it supports signing.
+ */
+static int
+MHD__gnutls_tls_sign (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_privkey * pkey,
+ const MHD_gnutls_datum_t * hash_concat,
+ MHD_gnutls_datum_t * signature)
+{
+
+ /* If our certificate supports signing
+ */
+
+ if (cert != NULL)
+ if (cert->key_usage != 0)
+ if (!(cert->key_usage & KEY_DIGITAL_SIGNATURE))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+
+ /* External signing. */
+ if (!pkey || pkey->params_size == 0)
+ {
+ if (!session->internals.sign_func)
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+
+ return (*session->internals.sign_func) (session,
+ session->internals.
+ sign_func_userdata,
+ cert->cert_type, &cert->raw,
+ hash_concat, signature);
+ }
+
+ return MHD_gtls_sign (pkey->pk_algorithm, pkey->params, pkey->params_size,
+ hash_concat, signature);
+}
+
+static int
+MHD__gnutls_verify_sig (MHD_gnutls_cert * cert,
+ const MHD_gnutls_datum_t * hash_concat,
+ MHD_gnutls_datum_t * signature, size_t sha1pos)
+{
+ int ret;
+ MHD_gnutls_datum_t vdata;
+
+ if ((cert == NULL) || (cert->version == 0))
+ { /* this is the only way to check
+ * if it is initialized
+ */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+
+ /* If the certificate supports signing continue.
+ */
+ if (cert != NULL)
+ if (cert->key_usage != 0)
+ if (!(cert->key_usage & KEY_DIGITAL_SIGNATURE))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+
+ switch (cert->subject_pk_algorithm)
+ {
+ case MHD_GNUTLS_PK_RSA:
+
+ vdata.data = hash_concat->data;
+ vdata.size = hash_concat->size;
+
+ /* verify signature */
+ if ((ret = MHD_gtls_rsa_verify (&vdata, signature, cert->params,
+ cert->params_size, 1)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ return 0;
+}
+
+/* Verifies a TLS signature (like the one in the client certificate
+ * verify message).
+ */
+int
+MHD_gtls_verify_sig_hdata (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_datum_t * signature)
+{
+ int ret;
+ opaque concat[36];
+ mac_hd_t td_md5;
+ mac_hd_t td_sha;
+ MHD_gnutls_datum_t dconcat;
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ td_md5 = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
+ if (td_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
+ if (td_sha == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_hash_deinit (td_md5, NULL);
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ ret = MHD_gtls_generate_master (session, 1);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ MHD_gnutls_mac_deinit_ssl3_handshake (td_md5, concat,
+ session->security_parameters.
+ master_secret, TLS_MASTER_SIZE);
+ MHD_gnutls_mac_deinit_ssl3_handshake (td_sha, &concat[16],
+ session->security_parameters.
+ master_secret, TLS_MASTER_SIZE);
+ }
+ else
+ {
+ MHD_gnutls_hash_deinit (td_md5, concat);
+ MHD_gnutls_hash_deinit (td_sha, &concat[16]);
+ }
+
+ dconcat.data = concat;
+ dconcat.size = 20 + 16; /* md5+ sha */
+
+ ret = MHD__gnutls_verify_sig (cert, &dconcat, signature, 16);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return ret;
+
+}
+
+/* Generates a signature of all the random data and the parameters.
+ * Used in DHE_* ciphersuites.
+ */
+int
+MHD_gtls_verify_sig_params (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ const MHD_gnutls_datum_t * params,
+ MHD_gnutls_datum_t * signature)
+{
+ MHD_gnutls_datum_t dconcat;
+ int ret;
+ mac_hd_t td_md5 = NULL;
+ mac_hd_t td_sha;
+ opaque concat[36];
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ td_md5 = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
+ if (td_md5 == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td_md5, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_md5, session->security_parameters.server_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_md5, params->data, params->size);
+ }
+
+ td_sha = MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
+ if (td_sha == NULL)
+ {
+ MHD_gnutls_assert ();
+ if (td_md5)
+ MHD_gnutls_hash_deinit (td_md5, NULL);
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ MHD_gnutls_hash (td_sha, session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_sha, session->security_parameters.server_random,
+ TLS_RANDOM_SIZE);
+ MHD_gnutls_hash (td_sha, params->data, params->size);
+
+ if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ MHD_gnutls_hash_deinit (td_md5, concat);
+ MHD_gnutls_hash_deinit (td_sha, &concat[16]);
+ dconcat.size = 36;
+ }
+ else
+ {
+#if 1
+ /* Use NULL parameters. */
+ memcpy (concat,
+ "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
+ 15);
+ MHD_gnutls_hash_deinit (td_sha, &concat[15]);
+ dconcat.size = 35;
+#else
+ /* No parameters field. */
+ memcpy (concat,
+ "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
+ MHD_gnutls_hash_deinit (td_sha, &concat[13]);
+ dconcat.size = 33;
+#endif
+ }
+
+ dconcat.data = concat;
+
+ ret = MHD__gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return ret;
+
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.h
new file mode 100644
index 0000000000..020ef48988
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_sig.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_SIG_H
+# define GNUTLS_SIG_H
+
+int MHD_gtls_tls_sign_hdata (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_privkey * pkey,
+ MHD_gnutls_datum_t * signature);
+
+int MHD_gtls_tls_sign_params (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_privkey * pkey,
+ MHD_gnutls_datum_t * params,
+ MHD_gnutls_datum_t * signature);
+
+int MHD_gtls_verify_sig_hdata (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ MHD_gnutls_datum_t * signature);
+
+int MHD_gtls_verify_sig_params (MHD_gtls_session_t session,
+ MHD_gnutls_cert * cert,
+ const MHD_gnutls_datum_t * params,
+ MHD_gnutls_datum_t * signature);
+
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.c
new file mode 100644
index 0000000000..01f51abc7d
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.c
@@ -0,0 +1,804 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions to manipulate the session (MHD_gnutls_int.h), and some other stuff
+ * are included here. The file's name is traditionally MHD_gnutls_state even if the
+ * state has been renamed to session.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_auth_int.h>
+#include <gnutls_num.h>
+#include <gnutls_datum.h>
+#include <gnutls_record.h>
+#include <gnutls_handshake.h>
+#include <gnutls_dh.h>
+#include <gnutls_buffers.h>
+#include <gnutls_state.h>
+#include <auth_cert.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_rsa_export.h>
+
+void
+MHD__gnutls_session_cert_type_set (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CertificateType ct)
+{
+ session->security_parameters.cert_type = ct;
+}
+
+/**
+ * MHD_gnutls_cipher_get - Returns the currently used cipher.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * Returns: the currently used cipher.
+ **/
+enum MHD_GNUTLS_CipherAlgorithm
+MHD_gnutls_cipher_get (MHD_gtls_session_t session)
+{
+ return session->security_parameters.read_bulk_cipher_algorithm;
+}
+
+/**
+ * MHD_gnutls_certificate_type_get - Returns the currently used certificate type.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * The certificate type is by default X.509, unless it is negotiated
+ * as a TLS extension.
+ *
+ * Returns: the currently used %enum MHD_GNUTLS_CertificateType certificate
+ * type.
+ **/
+enum MHD_GNUTLS_CertificateType
+MHD_gnutls_certificate_type_get (MHD_gtls_session_t session)
+{
+ return session->security_parameters.cert_type;
+}
+
+/**
+ * MHD_gnutls_kx_get - Returns the key exchange algorithm.
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * Returns: the key exchange algorithm used in the last handshake.
+ **/
+enum MHD_GNUTLS_KeyExchangeAlgorithm
+MHD_gnutls_kx_get (MHD_gtls_session_t session)
+{
+ return session->security_parameters.kx_algorithm;
+}
+
+/* Check if the given certificate type is supported.
+ * This means that it is enabled by the priority functions,
+ * and a matching certificate exists.
+ */
+int
+MHD_gtls_session_cert_type_supported (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CertificateType
+ cert_type)
+{
+ unsigned i;
+ unsigned cert_found = 0;
+ MHD_gtls_cert_credentials_t cred;
+
+ if (session->security_parameters.entity == GNUTLS_SERVER)
+ {
+ cred
+ = (MHD_gtls_cert_credentials_t) MHD_gtls_get_cred (session->key,
+ MHD_GNUTLS_CRD_CERTIFICATE,
+ NULL);
+
+ if (cred == NULL)
+ return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
+
+ if (cred->server_get_cert_callback == NULL)
+ {
+ for (i = 0; i < cred->ncerts; i++)
+ {
+ if (cred->cert_list[i][0].cert_type == cert_type)
+ {
+ cert_found = 1;
+ break;
+ }
+ }
+
+ if (cert_found == 0)
+ /* no certificate is of that type.
+ */
+ return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
+ }
+ }
+
+ if (session->internals.priorities.cert_type.num_algorithms == 0 && cert_type
+ == DEFAULT_CERT_TYPE)
+ return 0;
+
+ for (i = 0; i < session->internals.priorities.cert_type.num_algorithms; i++)
+ {
+ if (session->internals.priorities.cert_type.priority[i] == cert_type)
+ {
+ return 0; /* ok */
+ }
+ }
+
+ return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
+}
+
+/* this function deinitializes all the internal parameters stored
+ * in a session struct.
+ */
+inline static void
+deinit_internal_params (MHD_gtls_session_t session)
+{
+ if (session->internals.params.free_dh_params)
+ MHD__gnutls_dh_params_deinit (session->internals.params.dh_params);
+
+ if (session->internals.params.free_rsa_params)
+ MHD__gnutls_rsa_params_deinit (session->internals.params.rsa_params);
+
+ memset (&session->internals.params, 0, sizeof (session->internals.params));
+}
+
+/* This function will clear all the variables in internals
+ * structure within the session, which depend on the current handshake.
+ * This is used to allow further handshakes.
+ */
+void
+MHD_gtls_handshake_internal_state_clear (MHD_gtls_session_t session)
+{
+ session->internals.extensions_sent_size = 0;
+
+ /* by default no selected certificate */
+ session->internals.proposed_record_size = DEFAULT_MAX_RECORD_SIZE;
+ session->internals.adv_version_major = 0;
+ session->internals.adv_version_minor = 0;
+ session->internals.v2_hello = 0;
+ memset (&session->internals.handshake_header_buffer, 0,
+ sizeof (MHD_gtls_handshake_header_buffer_st));
+ session->internals.adv_version_minor = 0;
+ session->internals.adv_version_minor = 0;
+ session->internals.direction = 0;
+
+ /* use out of band data for the last
+ * handshake messages received.
+ */
+ session->internals.last_handshake_in = -1;
+ session->internals.last_handshake_out = -1;
+
+ session->internals.resumable = RESUME_TRUE;
+ MHD__gnutls_free_datum (&session->internals.recv_buffer);
+
+ deinit_internal_params (session);
+
+}
+
+#define MIN_DH_BITS 727
+/**
+ * MHD__gnutls_init - This function initializes the session to null (null encryption etc...).
+ * @con_end: indicate if this session is to be used for server or client.
+ * @session: is a pointer to a #MHD_gtls_session_t structure.
+ *
+ * This function initializes the current session to null. Every
+ * session must be initialized before use, so internal structures can
+ * be allocated. This function allocates structures which can only
+ * be free'd by calling MHD__gnutls_deinit(). Returns zero on success.
+ *
+ * @con_end can be one of %GNUTLS_CLIENT and %GNUTLS_SERVER.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+ **/
+
+/* TODO rm redundent pointer ref */
+int
+MHD__gnutls_init (MHD_gtls_session_t * session,
+ MHD_gnutls_connection_end_t con_end)
+{
+ *session = MHD_gnutls_calloc (1, sizeof (struct MHD_gtls_session_int));
+ if (*session == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ (*session)->security_parameters.entity = con_end;
+
+ /* the default certificate type for TLS */
+ (*session)->security_parameters.cert_type = DEFAULT_CERT_TYPE;
+
+ /* Set the defaults for initial handshake */
+ (*session)->security_parameters.read_bulk_cipher_algorithm =
+ (*session)->security_parameters.write_bulk_cipher_algorithm =
+ MHD_GNUTLS_CIPHER_NULL;
+
+ (*session)->security_parameters.read_mac_algorithm =
+ (*session)->security_parameters.write_mac_algorithm = MHD_GNUTLS_MAC_NULL;
+
+ /* Initialize buffers */
+ MHD_gtls_buffer_init (&(*session)->internals.application_data_buffer);
+ MHD_gtls_buffer_init (&(*session)->internals.handshake_data_buffer);
+ MHD_gtls_buffer_init (&(*session)->internals.handshake_hash_buffer);
+ MHD_gtls_buffer_init (&(*session)->internals.ia_data_buffer);
+
+ MHD_gtls_buffer_init (&(*session)->internals.record_send_buffer);
+ MHD_gtls_buffer_init (&(*session)->internals.record_recv_buffer);
+
+ MHD_gtls_buffer_init (&(*session)->internals.handshake_send_buffer);
+ MHD_gtls_buffer_init (&(*session)->internals.handshake_recv_buffer);
+
+ (*session)->key = MHD_gnutls_calloc (1, sizeof (struct MHD_gtls_key));
+ if ((*session)->key == NULL)
+ {
+ cleanup_session:MHD_gnutls_free (*session);
+ *session = NULL;
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ (*session)->internals.expire_time = DEFAULT_EXPIRE_TIME; /* one hour default */
+
+ MHD__gnutls_dh_set_prime_bits ((*session), MIN_DH_BITS);
+
+ MHD__gnutls_transport_set_lowat ((*session), DEFAULT_LOWAT); /* the default for tcp */
+
+ MHD__gnutls_handshake_set_max_packet_length ((*session),
+ MAX_HANDSHAKE_PACKET_SIZE);
+
+ /* Allocate a minimum size for recv_data
+ * This is allocated in order to avoid small messages, making
+ * the receive procedure slow.
+ */
+ (*session)->internals.record_recv_buffer.data
+ = MHD_gnutls_malloc (INITIAL_RECV_BUFFER_SIZE);
+ if ((*session)->internals.record_recv_buffer.data == NULL)
+ {
+ MHD_gnutls_free ((*session)->key);
+ goto cleanup_session;
+ }
+
+ /* set the socket pointers to -1; */
+ (*session)->internals.transport_recv_ptr = (MHD_gnutls_transport_ptr_t) - 1;
+ (*session)->internals.transport_send_ptr = (MHD_gnutls_transport_ptr_t) - 1;
+
+ /* set the default maximum record size for TLS
+ */
+ (*session)->security_parameters.max_record_recv_size
+ = DEFAULT_MAX_RECORD_SIZE;
+ (*session)->security_parameters.max_record_send_size
+ = DEFAULT_MAX_RECORD_SIZE;
+
+ /* everything else not initialized here is initialized
+ * as NULL or 0. This is why calloc is used.
+ */
+
+ MHD_gtls_handshake_internal_state_clear (*session);
+
+ return 0;
+}
+
+
+/**
+ * MHD__gnutls_deinit - This function clears all buffers associated with a session
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function clears all buffers associated with the @session.
+ * This function will also remove session data from the session
+ * database if the session was terminated abnormally.
+ **/
+void
+MHD__gnutls_deinit (MHD_gtls_session_t session)
+{
+
+ if (session == NULL)
+ return;
+
+ /* remove auth info firstly */
+ MHD_gtls_free_auth_info (session);
+
+ MHD_gtls_handshake_internal_state_clear (session);
+ MHD__gnutls_handshake_io_buffer_clear (session);
+
+ MHD__gnutls_free_datum (&session->connection_state.read_mac_secret);
+ MHD__gnutls_free_datum (&session->connection_state.write_mac_secret);
+
+ MHD_gtls_buffer_clear (&session->internals.ia_data_buffer);
+ MHD_gtls_buffer_clear (&session->internals.handshake_hash_buffer);
+ MHD_gtls_buffer_clear (&session->internals.handshake_data_buffer);
+ MHD_gtls_buffer_clear (&session->internals.application_data_buffer);
+ MHD_gtls_buffer_clear (&session->internals.record_recv_buffer);
+ MHD_gtls_buffer_clear (&session->internals.record_send_buffer);
+
+ MHD__gnutls_credentials_clear (session);
+ MHD_gtls_selected_certs_deinit (session);
+
+ if (session->connection_state.read_cipher_state != NULL)
+ MHD_gnutls_cipher_deinit (session->connection_state.read_cipher_state);
+ if (session->connection_state.write_cipher_state != NULL)
+ MHD_gnutls_cipher_deinit (session->connection_state.write_cipher_state);
+
+ MHD__gnutls_free_datum (&session->cipher_specs.server_write_mac_secret);
+ MHD__gnutls_free_datum (&session->cipher_specs.client_write_mac_secret);
+ MHD__gnutls_free_datum (&session->cipher_specs.server_write_IV);
+ MHD__gnutls_free_datum (&session->cipher_specs.client_write_IV);
+ MHD__gnutls_free_datum (&session->cipher_specs.server_write_key);
+ MHD__gnutls_free_datum (&session->cipher_specs.client_write_key);
+
+ if (session->key != NULL)
+ {
+ MHD_gtls_mpi_release (&session->key->KEY);
+ MHD_gtls_mpi_release (&session->key->client_Y);
+ MHD_gtls_mpi_release (&session->key->client_p);
+ MHD_gtls_mpi_release (&session->key->client_g);
+
+ MHD_gtls_mpi_release (&session->key->u);
+ MHD_gtls_mpi_release (&session->key->a);
+ MHD_gtls_mpi_release (&session->key->x);
+ MHD_gtls_mpi_release (&session->key->A);
+ MHD_gtls_mpi_release (&session->key->B);
+ MHD_gtls_mpi_release (&session->key->b);
+
+ /* RSA */
+ MHD_gtls_mpi_release (&session->key->rsa[0]);
+ MHD_gtls_mpi_release (&session->key->rsa[1]);
+
+ MHD_gtls_mpi_release (&session->key->dh_secret);
+ MHD_gnutls_free (session->key);
+
+ session->key = NULL;
+ }
+
+ memset (session, 0, sizeof (struct MHD_gtls_session_int));
+ MHD_gnutls_free (session);
+}
+
+/* Returns the minimum prime bits that are acceptable.
+ */
+int
+MHD_gtls_dh_get_allowed_prime_bits (MHD_gtls_session_t session)
+{
+ return session->internals.dh_prime_bits;
+}
+
+int
+MHD_gtls_dh_set_peer_public (MHD_gtls_session_t session, mpi_t public)
+{
+ MHD_gtls_dh_info_st *dh;
+ int ret;
+
+ switch (MHD_gtls_auth_get_type (session))
+ {
+ case MHD_GNUTLS_CRD_CERTIFICATE:
+ {
+ cert_auth_info_t info;
+
+ info = MHD_gtls_get_auth_info (session);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ dh = &info->dh;
+ break;
+ }
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ret = MHD_gtls_mpi_dprint_lz (&dh->public_key, public);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+MHD_gtls_dh_set_secret_bits (MHD_gtls_session_t session, unsigned bits)
+{
+ switch (MHD_gtls_auth_get_type (session))
+ {
+ case MHD_GNUTLS_CRD_CERTIFICATE:
+ {
+ cert_auth_info_t info;
+
+ info = MHD_gtls_get_auth_info (session);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ info->dh.secret_bits = bits;
+ break;
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+
+ return 0;
+}
+
+/* This function will set in the auth info structure the
+ * RSA exponent and the modulus.
+ */
+int
+MHD_gtls_rsa_export_set_pubkey (MHD_gtls_session_t session,
+ mpi_t exponent, mpi_t modulus)
+{
+ cert_auth_info_t info;
+ int ret;
+
+ info = MHD_gtls_get_auth_info (session);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ ret = MHD_gtls_mpi_dprint_lz (&info->rsa_export.modulus, modulus);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD_gtls_mpi_dprint_lz (&info->rsa_export.exponent, exponent);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_free_datum (&info->rsa_export.modulus);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Sets the prime and the generator in the auth info structure.
+ */
+int
+MHD_gtls_dh_set_group (MHD_gtls_session_t session, mpi_t gen, mpi_t prime)
+{
+ MHD_gtls_dh_info_st *dh;
+ int ret;
+
+ switch (MHD_gtls_auth_get_type (session))
+ {
+ case MHD_GNUTLS_CRD_CERTIFICATE:
+ {
+ cert_auth_info_t info;
+
+ info = MHD_gtls_get_auth_info (session);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ dh = &info->dh;
+ break;
+ }
+ default:
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* prime
+ */
+ ret = MHD_gtls_mpi_dprint_lz (&dh->prime, prime);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* generator
+ */
+ ret = MHD_gtls_mpi_dprint_lz (&dh->generator, gen);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_free_datum (&dh->prime);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * MHD__gnutls_certificate_send_x509_rdn_sequence - This function will order gnutls to send or not the x.509 rdn sequence
+ * @session: is a pointer to a #MHD_gtls_session_t structure.
+ * @status: is 0 or 1
+ *
+ * If status is non zero, this function will order gnutls not to send
+ * the rdnSequence in the certificate request message. That is the
+ * server will not advertize it's trusted CAs to the peer. If status
+ * is zero then the default behaviour will take effect, which is to
+ * advertize the server's trusted CAs.
+ *
+ * This function has no effect in clients, and in authentication
+ * methods other than certificate with X.509 certificates.
+ **/
+void
+MHD__gnutls_certificate_send_x509_rdn_sequence (MHD_gtls_session_t session,
+ int status)
+{
+ session->internals.ignore_rdn_sequence = status;
+}
+
+/*-
+ * MHD__gnutls_record_set_default_version - Used to set the default version for the first record packet
+ * @session: is a #MHD_gtls_session_t structure.
+ * @major: is a tls major version
+ * @minor: is a tls minor version
+ *
+ * This function sets the default version that we will use in the first
+ * record packet (client hello). This function is only useful to people
+ * that know TLS internals and want to debug other implementations.
+ *
+ -*/
+void
+MHD__gnutls_record_set_default_version (MHD_gtls_session_t session,
+ unsigned char major,
+ unsigned char minor)
+{
+ session->internals.default_record_version[0] = major;
+ session->internals.default_record_version[1] = minor;
+}
+
+inline static int
+MHD__gnutls_cal_PRF_A (enum MHD_GNUTLS_HashAlgorithm algorithm,
+ const void *secret,
+ int secret_size,
+ const void *seed, int seed_size, void *result)
+{
+ mac_hd_t td1;
+
+ td1 = MHD_gtls_MHD_hmac_init (algorithm, secret, secret_size);
+ if (td1 == GNUTLS_MAC_FAILED)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ MHD_gnutls_hash (td1, seed, seed_size);
+ MHD_gnutls_MHD_hmac_deinit (td1, result);
+
+ return 0;
+}
+
+#define MAX_SEED_SIZE 200
+
+/* Produces "total_bytes" bytes using the hash algorithm specified.
+ * (used in the PRF function)
+ */
+static int
+MHD__gnutls_P_hash (enum MHD_GNUTLS_HashAlgorithm algorithm,
+ const opaque * secret,
+ int secret_size,
+ const opaque * seed,
+ int seed_size, int total_bytes, opaque * ret)
+{
+
+ mac_hd_t td2;
+ int i, times, how, blocksize, A_size;
+ opaque final[20], Atmp[MAX_SEED_SIZE];
+ int output_bytes, result;
+
+ if (seed_size > MAX_SEED_SIZE || total_bytes <= 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ blocksize = MHD_gnutls_hash_get_algo_len (algorithm);
+
+ output_bytes = 0;
+ do
+ {
+ output_bytes += blocksize;
+ }
+ while (output_bytes < total_bytes);
+
+ /* calculate A(0) */
+
+ memcpy (Atmp, seed, seed_size);
+ A_size = seed_size;
+
+ times = output_bytes / blocksize;
+
+ for (i = 0; i < times; i++)
+ {
+ td2 = MHD_gtls_MHD_hmac_init (algorithm, secret, secret_size);
+ if (td2 == GNUTLS_MAC_FAILED)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ /* here we calculate A(i+1) */
+ if ((result =
+ MHD__gnutls_cal_PRF_A (algorithm, secret, secret_size, Atmp,
+ A_size, Atmp)) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_MHD_hmac_deinit (td2, final);
+ return result;
+ }
+
+ A_size = blocksize;
+
+ MHD_gnutls_hash (td2, Atmp, A_size);
+ MHD_gnutls_hash (td2, seed, seed_size);
+ MHD_gnutls_MHD_hmac_deinit (td2, final);
+
+ if ((1 + i) * blocksize < total_bytes)
+ {
+ how = blocksize;
+ }
+ else
+ {
+ how = total_bytes - (i) * blocksize;
+ }
+
+ if (how > 0)
+ {
+ memcpy (&ret[i * blocksize], final, how);
+ }
+ }
+
+ return 0;
+}
+
+/* Xor's two buffers and puts the output in the first one.
+ */
+inline static void
+MHD__gnutls_xor (opaque * o1, opaque * o2, int length)
+{
+ int i;
+ for (i = 0; i < length; i++)
+ {
+ o1[i] ^= o2[i];
+ }
+}
+
+#define MAX_PRF_BYTES 200
+
+/* The PRF function expands a given secret
+ * needed by the TLS specification. ret must have a least total_bytes
+ * available.
+ */
+int
+MHD_gtls_PRF (MHD_gtls_session_t session,
+ const opaque * secret,
+ int secret_size,
+ const char *label,
+ int label_size,
+ const opaque * seed, int seed_size, int total_bytes, void *ret)
+{
+ int l_s, s_seed_size;
+ const opaque *s1, *s2;
+ opaque s_seed[MAX_SEED_SIZE];
+ opaque o1[MAX_PRF_BYTES], o2[MAX_PRF_BYTES];
+ int result;
+ enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
+
+ if (total_bytes > MAX_PRF_BYTES)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ /* label+seed = s_seed */
+ s_seed_size = seed_size + label_size;
+
+ if (s_seed_size > MAX_SEED_SIZE)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ memcpy (s_seed, label, label_size);
+ memcpy (&s_seed[label_size], seed, seed_size);
+
+ if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_2)
+ {
+ result =
+ MHD__gnutls_P_hash (MHD_GNUTLS_MAC_SHA1, secret, secret_size, s_seed,
+ s_seed_size, total_bytes, ret);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+ }
+ else
+ {
+ l_s = secret_size / 2;
+
+ s1 = &secret[0];
+ s2 = &secret[l_s];
+
+ if (secret_size % 2 != 0)
+ {
+ l_s++;
+ }
+
+ result =
+ MHD__gnutls_P_hash (MHD_GNUTLS_MAC_MD5, s1, l_s, s_seed, s_seed_size,
+ total_bytes, o1);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ result =
+ MHD__gnutls_P_hash (MHD_GNUTLS_MAC_SHA1, s2, l_s, s_seed, s_seed_size,
+ total_bytes, o2);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ MHD__gnutls_xor (o1, o2, total_bytes);
+
+ memcpy (ret, o1, total_bytes);
+ }
+
+ return 0; /* ok */
+
+}
+
+
+/*-
+ * MHD_gtls_session_is_export - Used to check whether this session is of export grade
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function will return non zero if this session is of export grade.
+ *
+ -*/
+int
+MHD_gtls_session_is_export (MHD_gtls_session_t session)
+{
+ enum MHD_GNUTLS_CipherAlgorithm cipher;
+
+ cipher =
+ MHD_gtls_cipher_suite_get_cipher_algo (&session->security_parameters.
+ current_cipher_suite);
+
+ if (MHD_gtls_cipher_get_export_flag (cipher) != 0)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * MHD__gnutls_record_get_direction - This function will return the direction of the last interrupted function call
+ * @session: is a #MHD_gtls_session_t structure.
+ *
+ * This function provides information about the internals of the
+ * record protocol and is only useful if a prior gnutls function call
+ * (e.g. MHD__gnutls_handshake()) was interrupted for some reason, that
+ * is, if a function returned %GNUTLS_E_INTERRUPTED or
+ * %GNUTLS_E_AGAIN. In such a case, you might want to call select()
+ * or poll() before calling the interrupted gnutls function again.
+ * To tell you whether a file descriptor should be selected for
+ * either reading or writing, MHD__gnutls_record_get_direction() returns 0
+ * if the interrupted function was trying to read data, and 1 if it
+ * was trying to write data.
+ *
+ * Returns: 0 if trying to read data, 1 if trying to write data.
+ **/
+int
+MHD__gnutls_record_get_direction (MHD_gtls_session_t session)
+{
+ return session->internals.direction;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.h
new file mode 100644
index 0000000000..a6ff58929f
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_state.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_STATE_H
+# define GNUTLS_STATE_H
+
+#include <gnutls_int.h>
+
+void MHD__gnutls_session_cert_type_set (MHD_gtls_session_t session,
+ enum MHD_GNUTLS_CertificateType);
+enum MHD_GNUTLS_KeyExchangeAlgorithm MHD_gnutls_kx_get (MHD_gtls_session_t
+ session);
+enum MHD_GNUTLS_CipherAlgorithm MHD_gnutls_cipher_get (MHD_gtls_session_t
+ session);
+enum MHD_GNUTLS_CertificateType
+MHD_gnutls_certificate_type_get (MHD_gtls_session_t);
+
+#include <gnutls_auth_int.h>
+
+#define CHECK_AUTH(auth, ret) if (MHD_gtls_auth_get_type(session) != auth) { \
+ MHD_gnutls_assert(); \
+ return ret; \
+ }
+
+#endif
+
+int MHD_gtls_session_cert_type_supported (MHD_gtls_session_t,
+ enum MHD_GNUTLS_CertificateType);
+
+int MHD_gtls_dh_set_secret_bits (MHD_gtls_session_t session, unsigned bits);
+
+int MHD_gtls_dh_set_peer_public (MHD_gtls_session_t session, mpi_t public);
+int MHD_gtls_dh_set_group (MHD_gtls_session_t session, mpi_t gen,
+ mpi_t prime);
+
+int MHD_gtls_dh_get_allowed_prime_bits (MHD_gtls_session_t session);
+void MHD_gtls_handshake_internal_state_clear (MHD_gtls_session_t);
+
+int MHD_gtls_rsa_export_set_pubkey (MHD_gtls_session_t session,
+ mpi_t exponent, mpi_t modulus);
+
+int MHD_gtls_session_is_resumable (MHD_gtls_session_t session);
+int MHD_gtls_session_is_export (MHD_gtls_session_t session);
+
+int MHD_gtls_openpgp_send_fingerprint (MHD_gtls_session_t session);
+
+int MHD_gtls_PRF (MHD_gtls_session_t session,
+ const opaque * secret, int secret_size,
+ const char *label, int label_size,
+ const opaque * seed, int seed_size,
+ int total_bytes, void *ret);
+
+int MHD__gnutls_init (MHD_gtls_session_t * session,
+ MHD_gnutls_connection_end_t con_end);
+
+#define DEFAULT_CERT_TYPE MHD_GNUTLS_CRT_X509
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.c
new file mode 100644
index 0000000000..c8f17c2558
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+#include <gnutls_str.h>
+
+/* These function are like strcat, strcpy. They only
+ * do bound checking (they shouldn't cause buffer overruns),
+ * and they always produce null terminated strings.
+ *
+ * They should be used only with null terminated strings.
+ */
+void
+MHD_gtls_str_cat (char *dest, size_t dest_tot_size, const char *src)
+{
+ size_t str_size = strlen (src);
+ size_t dest_size = strlen (dest);
+
+ if (dest_tot_size - dest_size > str_size)
+ {
+ strcat (dest, src);
+ }
+ else
+ {
+ if (dest_tot_size - dest_size > 0)
+ {
+ strncat (dest, src, (dest_tot_size - dest_size) - 1);
+ dest[dest_tot_size - 1] = 0;
+ }
+ }
+}
+
+void
+MHD_gtls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
+{
+ size_t str_size = strlen (src);
+
+ if (dest_tot_size > str_size)
+ {
+ strcpy (dest, src);
+ }
+ else
+ {
+ if (dest_tot_size > 0)
+ {
+ strncpy (dest, src, (dest_tot_size) - 1);
+ dest[dest_tot_size - 1] = 0;
+ }
+ }
+}
+
+void
+MHD_gtls_string_init (MHD_gtls_string * str,
+ MHD_gnutls_alloc_function alloc_func,
+ MHD_gnutls_realloc_function realloc_func,
+ MHD_gnutls_free_function free_func)
+{
+ str->data = NULL;
+ str->max_length = 0;
+ str->length = 0;
+
+ str->alloc_func = alloc_func;
+ str->free_func = free_func;
+ str->realloc_func = realloc_func;
+}
+
+void
+MHD_gtls_string_clear (MHD_gtls_string * str)
+{
+ if (str == NULL || str->data == NULL)
+ return;
+ str->free_func (str->data);
+
+ str->data = NULL;
+ str->max_length = 0;
+ str->length = 0;
+}
+
+#define MIN_CHUNK 256
+
+
+int
+MHD_gtls_string_append_data (MHD_gtls_string * dest,
+ const void *data, size_t data_size)
+{
+ size_t tot_len = data_size + dest->length;
+
+ if (dest->max_length >= tot_len)
+ {
+ memcpy (&dest->data[dest->length], data, data_size);
+ dest->length = tot_len;
+
+ return tot_len;
+ }
+ else
+ {
+ size_t new_len =
+ MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
+ dest->data = dest->realloc_func (dest->data, new_len);
+ if (dest->data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ dest->max_length = new_len;
+
+ memcpy (&dest->data[dest->length], data, data_size);
+ dest->length = tot_len;
+
+ return tot_len;
+ }
+}
+
+/* Converts the given string (old) to hex. A buffer must be provided
+ * to hold the new hex string. The new string will be null terminated.
+ * If the buffer does not have enough space to hold the string, a
+ * truncated hex string is returned (always null terminated).
+ */
+char *
+MHD_gtls_bin2hex (const void *_old,
+ size_t oldlen, char *buffer, size_t buffer_size)
+{
+ unsigned int i, j;
+ const opaque *old = _old;
+
+ for (i = j = 0; i < oldlen && j + 2 < buffer_size; j += 2)
+ {
+ sprintf (&buffer[j], "%.2x", old[i]);
+ i++;
+ }
+ buffer[j] = '\0';
+
+ return buffer;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.h
new file mode 100644
index 0000000000..51ed1bd155
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_str.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef GNUTLS_STR_H
+#define GNUTLS_STR_H
+
+#include <gnutls_int.h>
+
+void MHD_gtls_str_cpy (char *dest, size_t dest_tot_size, const char *src);
+void MHD_gtls_str_cat (char *dest, size_t dest_tot_size, const char *src);
+
+typedef struct
+{
+ opaque *data;
+ size_t max_length;
+ size_t length;
+ MHD_gnutls_realloc_function realloc_func;
+ MHD_gnutls_alloc_function alloc_func;
+ MHD_gnutls_free_function free_func;
+} MHD_gtls_string;
+
+void MHD_gtls_string_init (MHD_gtls_string *, MHD_gnutls_alloc_function,
+ MHD_gnutls_realloc_function,
+ MHD_gnutls_free_function);
+void MHD_gtls_string_clear (MHD_gtls_string *);
+
+int MHD_gtls_string_append_data (MHD_gtls_string *, const void *data,
+ size_t data_size);
+char *MHD_gtls_bin2hex (const void *old, size_t oldlen, char *buffer,
+ size_t buffer_size);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.c
new file mode 100644
index 0000000000..3b9641d4e4
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2007 Free Software Foundation
+ *
+ * Author: Simon Josefsson
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains support functions for 'TLS Handshake Message for
+ * Supplemental Data' (RFC 4680).
+ *
+ * The idea here is simple. MHD__gnutls_handshake() in gnuts_handshake.c
+ * will call MHD__gnutls_gen_supplemental and MHD__gnutls_parse_supplemental
+ * when some extension requested that supplemental data be sent or
+ * received. Extension request this by setting the flags
+ * do_recv_supplemental or do_send_supplemental in the session.
+ *
+ * The functions in this file iterate through the MHD__gnutls_supplemental
+ * array, and calls the send/recv functions for each respective data
+ * type.
+ *
+ * The receive function of each data type is responsible for decoding
+ * its own data. If the extension did not expect to receive
+ * supplemental data, it should return GNUTLS_E_UNEXPECTED_PACKET.
+ * Otherwise, it just parse the data as normal.
+ *
+ * The send function needs to append the 2-byte data format type, and
+ * append the 2-byte length of its data, and the data. If it doesn't
+ * want to send any data, it is fine to return without doing anything.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_supplemental.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+
+typedef int (*supp_recv_func) (MHD_gtls_session_t session,
+ const opaque * data, size_t data_size);
+typedef int (*supp_send_func) (MHD_gtls_session_t session,
+ MHD_gtls_buffer * buf);
+
+typedef struct
+{
+ const char *name;
+ MHD_gnutls_supplemental_data_format_type_t type;
+ supp_recv_func supp_recv_func;
+ supp_send_func supp_send_func;
+} MHD_gnutls_supplemental_entry;
+
+MHD_gnutls_supplemental_entry MHD__gnutls_supplemental[] = {
+ {0, 0, 0, 0}
+};
+
+
+static supp_recv_func
+get_supp_func_recv (MHD_gnutls_supplemental_data_format_type_t type)
+{
+ MHD_gnutls_supplemental_entry *p;
+
+ for (p = MHD__gnutls_supplemental; p->name != NULL; p++)
+ if (p->type == type)
+ return p->supp_recv_func;
+
+ return NULL;
+}
+
+int
+MHD__gnutls_gen_supplemental (MHD_gtls_session_t session,
+ MHD_gtls_buffer * buf)
+{
+ MHD_gnutls_supplemental_entry *p;
+ int ret;
+
+ /* Make room for 3 byte length field. */
+ ret = MHD_gtls_buffer_append (buf, "\0\0\0", 3);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ for (p = MHD__gnutls_supplemental; p->name; p++)
+ {
+ supp_send_func supp_send = p->supp_send_func;
+ size_t sizepos = buf->length;
+ int ret;
+
+ /* Make room for supplement type and length byte length field. */
+ ret = MHD_gtls_buffer_append (buf, "\0\0\0\0", 4);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = supp_send (session, buf);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ /* If data were added, store type+length, otherwise reset. */
+ if (buf->length > sizepos + 4)
+ {
+ buf->data[sizepos] = 0;
+ buf->data[sizepos + 1] = p->type;
+ buf->data[sizepos + 2] = ((buf->length - sizepos - 4) >> 8) & 0xFF;
+ buf->data[sizepos + 3] = (buf->length - sizepos - 4) & 0xFF;
+ }
+ else
+ buf->length -= 4;
+ }
+
+ buf->data[0] = ((buf->length - 3) >> 16) & 0xFF;
+ buf->data[1] = ((buf->length - 3) >> 8) & 0xFF;
+ buf->data[2] = (buf->length - 3) & 0xFF;
+
+ MHD__gnutls_debug_log ("EXT[%x]: Sending %d bytes of supplemental data\n",
+ session, buf->length);
+
+ return buf->length;
+}
+
+int
+MHD__gnutls_parse_supplemental (MHD_gtls_session_t session,
+ const uint8_t * data, int datalen)
+{
+ const opaque *p = data;
+ ssize_t dsize = datalen;
+ size_t total_size;
+
+ DECR_LEN (dsize, 3);
+ total_size = MHD_gtls_read_uint24 (p);
+ p += 3;
+
+ if (dsize != total_size)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ do
+ {
+ uint16_t supp_data_type;
+ uint16_t supp_data_length;
+ supp_recv_func recv_func;
+
+ DECR_LEN (dsize, 2);
+ supp_data_type = MHD_gtls_read_uint16 (p);
+ p += 2;
+
+ DECR_LEN (dsize, 2);
+ supp_data_length = MHD_gtls_read_uint16 (p);
+ p += 2;
+
+ MHD__gnutls_debug_log
+ ("EXT[%x]: Got supplemental type=%02x length=%d\n", session,
+ supp_data_type, supp_data_length);
+
+ recv_func = get_supp_func_recv (supp_data_type);
+ if (recv_func)
+ {
+ int ret = recv_func (session, p, supp_data_length);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ DECR_LEN (dsize, supp_data_length);
+ p += supp_data_length;
+ }
+ while (dsize > 0);
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.h
new file mode 100644
index 0000000000..b7ad0c2923
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_supplemental.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 Free Software Foundation
+ *
+ * Author: Simon Josefsson
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+
+int MHD__gnutls_parse_supplemental (MHD_gtls_session_t session,
+ const uint8_t * data, int data_size);
+int MHD__gnutls_gen_supplemental (MHD_gtls_session_t session,
+ MHD_gtls_buffer * buf);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_ui.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_ui.c
new file mode 100644
index 0000000000..5a1bfd3d18
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_ui.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains certificate authentication functions to be exported in the
+ * API and did not fit elsewhere.
+ */
+
+#include <gnutls_int.h>
+#include <auth_cert.h>
+#include <gnutls_errors.h>
+#include <gnutls_auth_int.h>
+#include <gnutls_state.h>
+#include <gnutls_datum.h>
+
+/* ANON & DHE */
+
+/**
+ * MHD__gnutls_dh_set_prime_bits - Used to set the bits for a DH ciphersuite
+ * @session: is a #MHD_gtls_session_t structure.
+ * @bits: is the number of bits
+ *
+ * This function sets the number of bits, for use in an
+ * Diffie Hellman key exchange. This is used both in DH ephemeral and
+ * DH anonymous cipher suites. This will set the
+ * minimum size of the prime that will be used for the handshake.
+ *
+ * In the client side it sets the minimum accepted number of bits.
+ * If a server sends a prime with less bits than that
+ * GNUTLS_E_DH_PRIME_UNACCEPTABLE will be returned by the
+ * handshake.
+ *
+ **/
+void
+MHD__gnutls_dh_set_prime_bits (MHD_gtls_session_t session, unsigned int bits)
+{
+ session->internals.dh_prime_bits = bits;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.c b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.c
new file mode 100644
index 0000000000..685c9642bf
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include "gnutls_auth_int.h"
+#include "gnutls_errors.h"
+#include <gnutls_cert.h>
+#include <auth_cert.h>
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "gnutls_datum.h"
+#include <gnutls_pk.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_global.h>
+#include <gnutls_record.h>
+#include <gnutls_sig.h>
+#include <gnutls_state.h>
+#include <gnutls_pk.h>
+#include <gnutls_str.h>
+#include <debug.h>
+#include <x509_b64.h>
+#include <gnutls_x509.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* x509 */
+#include "common.h"
+#include "x509.h"
+#include "mpi.h"
+#include "privkey.h"
+
+
+/*
+ * some x509 certificate parsing functions.
+ */
+
+/* Check if the number of bits of the key in the certificate
+ * is unacceptable.
+ */
+inline static int
+check_bits (MHD_gnutls_x509_crt_t crt, unsigned int max_bits)
+{
+ int ret;
+ unsigned int bits;
+
+ ret = MHD_gnutls_x509_crt_get_pk_algorithm (crt, &bits);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ if (bits > max_bits && max_bits > 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_CONSTRAINT_ERROR;
+ }
+
+ return 0;
+}
+
+
+#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) { \
+ if (peer_certificate_list[x]) \
+ MHD_gnutls_x509_crt_deinit(peer_certificate_list[x]); \
+ } \
+ MHD_gnutls_free( peer_certificate_list)
+
+/*
+ * Read certificates and private keys, from memory etc.
+ */
+
+/* returns error if the certificate has different algorithm than
+ * the given key parameters.
+ */
+static int
+MHD__gnutls_check_key_cert_match (MHD_gtls_cert_credentials_t res)
+{
+ MHD_gnutls_datum_t cid;
+ MHD_gnutls_datum_t kid;
+ unsigned pk = res->cert_list[res->ncerts - 1][0].subject_pk_algorithm;
+
+ if (res->pkey[res->ncerts - 1].pk_algorithm != pk)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
+ }
+
+ MHD__gnutls_x509_write_rsa_params (res->pkey[res->ncerts - 1].params,
+ res->pkey[res->ncerts -
+ 1].params_size, &kid);
+
+
+ MHD__gnutls_x509_write_rsa_params (res->
+ cert_list[res->ncerts - 1][0].params,
+ res->cert_list[res->ncerts -
+ 1][0].params_size, &cid);
+
+ if (cid.size != kid.size)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_free_datum (&kid);
+ MHD__gnutls_free_datum (&cid);
+ return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
+ }
+
+ if (memcmp (kid.data, cid.data, kid.size) != 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_free_datum (&kid);
+ MHD__gnutls_free_datum (&cid);
+ return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
+ }
+
+ MHD__gnutls_free_datum (&kid);
+ MHD__gnutls_free_datum (&cid);
+ return 0;
+}
+
+/* Reads a DER encoded certificate list from memory and stores it to
+ * a MHD_gnutls_cert structure.
+ * Returns the number of certificates parsed.
+ */
+static int
+parse_crt_mem (MHD_gnutls_cert ** cert_list, unsigned *ncerts,
+ MHD_gnutls_x509_crt_t cert)
+{
+ int i;
+ int ret;
+
+ i = *ncerts + 1;
+
+ *cert_list =
+ (MHD_gnutls_cert *) MHD_gtls_realloc_fast (*cert_list,
+ i * sizeof (MHD_gnutls_cert));
+
+ if (*cert_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret = MHD_gtls_x509_crt_to_gcert (&cert_list[0][i - 1], cert, 0);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ *ncerts = i;
+
+ return 1; /* one certificate parsed */
+}
+
+/* Reads a DER encoded certificate list from memory and stores it to
+ * a MHD_gnutls_cert structure.
+ * Returns the number of certificates parsed.
+ */
+static int
+parse_der_cert_mem (MHD_gnutls_cert ** cert_list, unsigned *ncerts,
+ const void *input_cert, int input_cert_size)
+{
+ MHD_gnutls_datum_t tmp;
+ MHD_gnutls_x509_crt_t cert;
+ int ret;
+
+ ret = MHD_gnutls_x509_crt_init (&cert);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ tmp.data = (opaque *) input_cert;
+ tmp.size = input_cert_size;
+
+ ret = MHD_gnutls_x509_crt_import (cert, &tmp, GNUTLS_X509_FMT_DER);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_x509_crt_deinit (cert);
+ return ret;
+ }
+
+ ret = parse_crt_mem (cert_list, ncerts, cert);
+ MHD_gnutls_x509_crt_deinit (cert);
+
+ return ret;
+}
+
+/* Reads a base64 encoded certificate list from memory and stores it to
+ * a MHD_gnutls_cert structure. Returns the number of certificate parsed.
+ */
+static int
+parse_pem_cert_mem (MHD_gnutls_cert ** cert_list, unsigned *ncerts,
+ const char *input_cert, int input_cert_size)
+{
+ int size, siz2, i;
+ const char *ptr;
+ opaque *ptr2;
+ MHD_gnutls_datum_t tmp;
+ int ret, count;
+
+ /* move to the certificate
+ */
+ ptr = memmem (input_cert, input_cert_size,
+ PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
+ if (ptr == NULL)
+ ptr = memmem (input_cert, input_cert_size,
+ PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1);
+
+ if (ptr == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+ size = input_cert_size - (ptr - input_cert);
+
+ i = *ncerts + 1;
+ count = 0;
+
+ do
+ {
+
+ siz2 =
+ MHD__gnutls_fbase64_decode (NULL, (const unsigned char *) ptr, size,
+ &ptr2);
+
+ if (siz2 < 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+
+ *cert_list =
+ (MHD_gnutls_cert *) MHD_gtls_realloc_fast (*cert_list,
+ i *
+ sizeof (MHD_gnutls_cert));
+
+ if (*cert_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ tmp.data = ptr2;
+ tmp.size = siz2;
+
+ ret = MHD_gtls_x509_raw_cert_to_gcert (&cert_list[0][i - 1], &tmp, 0);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ MHD__gnutls_free_datum (&tmp); /* free ptr2 */
+
+ /* now we move ptr after the pem header
+ */
+ ptr++;
+ /* find the next certificate (if any)
+ */
+ size = input_cert_size - (ptr - input_cert);
+
+ if (size > 0)
+ {
+ char *ptr3;
+
+ ptr3 = memmem (ptr, size, PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
+ if (ptr3 == NULL)
+ ptr3 = memmem (ptr, size, PEM_CERT_SEP2,
+ sizeof (PEM_CERT_SEP2) - 1);
+
+ ptr = ptr3;
+ }
+ else
+ ptr = NULL;
+
+ i++;
+ count++;
+
+ }
+ while (ptr != NULL);
+
+ *ncerts = i - 1;
+
+ return count;
+}
+
+
+
+/* Reads a DER or PEM certificate from memory
+ */
+static int
+read_cert_mem (MHD_gtls_cert_credentials_t res, const void *cert,
+ int cert_size, MHD_gnutls_x509_crt_fmt_t type)
+{
+ int ret;
+
+ /* allocate space for the certificate to add
+ */
+ res->cert_list = MHD_gtls_realloc_fast (res->cert_list,
+ (1 +
+ res->ncerts) *
+ sizeof (MHD_gnutls_cert *));
+ if (res->cert_list == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list_length = MHD_gtls_realloc_fast (res->cert_list_length,
+ (1 +
+ res->ncerts) *
+ sizeof (int));
+ if (res->cert_list_length == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list[res->ncerts] = NULL; /* for realloc */
+ res->cert_list_length[res->ncerts] = 0;
+
+ if (type == GNUTLS_X509_FMT_DER)
+ ret = parse_der_cert_mem (&res->cert_list[res->ncerts],
+ &res->cert_list_length[res->ncerts],
+ cert, cert_size);
+ else
+ ret =
+ parse_pem_cert_mem (&res->cert_list[res->ncerts],
+ &res->cert_list_length[res->ncerts], cert,
+ cert_size);
+
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return ret;
+}
+
+
+int
+MHD__gnutls_x509_privkey_to_gkey (MHD_gnutls_privkey * dest,
+ MHD_gnutls_x509_privkey_t src)
+{
+ int i, ret;
+
+ memset (dest, 0, sizeof (MHD_gnutls_privkey));
+
+ for (i = 0; i < src->params_size; i++)
+ {
+ dest->params[i] = MHD__gnutls_mpi_copy (src->params[i]);
+ if (dest->params[i] == NULL)
+ {
+ MHD_gnutls_assert ();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+ }
+
+ dest->pk_algorithm = src->pk_algorithm;
+ dest->params_size = src->params_size;
+
+ return 0;
+
+cleanup:
+
+ for (i = 0; i < src->params_size; i++)
+ {
+ MHD_gtls_mpi_release (&dest->params[i]);
+ }
+ return ret;
+}
+
+void
+MHD_gtls_gkey_deinit (MHD_gnutls_privkey * key)
+{
+ int i;
+ if (key == NULL)
+ return;
+
+ for (i = 0; i < key->params_size; i++)
+ {
+ MHD_gtls_mpi_release (&key->params[i]);
+ }
+}
+
+int
+MHD__gnutls_x509_raw_privkey_to_gkey (MHD_gnutls_privkey * privkey,
+ const MHD_gnutls_datum_t * raw_key,
+ MHD_gnutls_x509_crt_fmt_t type)
+{
+ MHD_gnutls_x509_privkey_t tmpkey;
+ int ret;
+
+ ret = MHD_gnutls_x509_privkey_init (&tmpkey);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ ret = MHD_gnutls_x509_privkey_import (tmpkey, raw_key, type);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_x509_privkey_deinit (tmpkey);
+ return ret;
+ }
+
+ ret = MHD__gnutls_x509_privkey_to_gkey (privkey, tmpkey);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_x509_privkey_deinit (tmpkey);
+ return ret;
+ }
+
+ MHD_gnutls_x509_privkey_deinit (tmpkey);
+
+ return 0;
+}
+
+/* Reads a PEM encoded PKCS-1 RSA/DSA private key from memory. Type
+ * indicates the certificate format. KEY can be NULL, to indicate
+ * that GnuTLS doesn't know the private key.
+ */
+static int
+read_key_mem (MHD_gtls_cert_credentials_t res,
+ const void *key, int key_size, MHD_gnutls_x509_crt_fmt_t type)
+{
+ int ret;
+ MHD_gnutls_datum_t tmp;
+
+ /* allocate space for the pkey list
+ */
+ res->pkey =
+ MHD_gtls_realloc_fast (res->pkey,
+ (res->ncerts + 1) * sizeof (MHD_gnutls_privkey));
+ if (res->pkey == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (key)
+ {
+ tmp.data = (opaque *) key;
+ tmp.size = key_size;
+
+ ret =
+ MHD__gnutls_x509_raw_privkey_to_gkey (&res->pkey[res->ncerts], &tmp,
+ type);
+ if (ret < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+ }
+ else
+ memset (&res->pkey[res->ncerts], 0, sizeof (MHD_gnutls_privkey));
+
+ return 0;
+}
+
+/**
+ * MHD__gnutls_certificate_set_x509_key_mem - Used to set keys in a MHD_gtls_cert_credentials_t structure
+ * @res: is an #MHD_gtls_cert_credentials_t structure.
+ * @cert: contains a certificate list (path) for the specified private key
+ * @key: is the private key, or %NULL
+ * @type: is PEM or DER
+ *
+ * This function sets a certificate/private key pair in the
+ * MHD_gtls_cert_credentials_t structure. This function may be called
+ * more than once (in case multiple keys/certificates exist for the
+ * server).
+ *
+ * Currently are supported: RSA PKCS-1 encoded private keys,
+ * DSA private keys.
+ *
+ * DSA private keys are encoded the OpenSSL way, which is an ASN.1
+ * DER sequence of 6 INTEGERs - version, p, q, g, pub, priv.
+ *
+ * Note that the keyUsage (2.5.29.15) PKIX extension in X.509 certificates
+ * is supported. This means that certificates intended for signing cannot
+ * be used for ciphersuites that require encryption.
+ *
+ * If the certificate and the private key are given in PEM encoding
+ * then the strings that hold their values must be null terminated.
+ *
+ * The @key may be %NULL if you are using a sign callback, see
+ * MHD_gtls_sign_callback_set().
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+ **/
+int
+MHD__gnutls_certificate_set_x509_key_mem (MHD_gtls_cert_credentials_t
+ res,
+ const MHD_gnutls_datum_t * cert,
+ const MHD_gnutls_datum_t * key,
+ MHD_gnutls_x509_crt_fmt_t type)
+{
+ int ret;
+
+ /* this should be first
+ */
+ if ((ret = read_key_mem (res, key ? key->data : NULL,
+ key ? key->size : 0, type)) < 0)
+ return ret;
+
+ if ((ret = read_cert_mem (res, cert->data, cert->size, type)) < 0)
+ return ret;
+
+ res->ncerts++;
+
+ if (key && (ret = MHD__gnutls_check_key_cert_match (res)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Returns 0 if it's ok to use the enum MHD_GNUTLS_KeyExchangeAlgorithm with this
+ * certificate (uses the KeyUsage field).
+ */
+int
+MHD__gnutls_check_key_usage (const MHD_gnutls_cert * cert,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm alg)
+{
+ unsigned int key_usage = 0;
+ int encipher_type;
+
+ if (cert == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if (MHD_gtls_map_kx_get_cred (alg, 1) == MHD_GNUTLS_CRD_CERTIFICATE ||
+ MHD_gtls_map_kx_get_cred (alg, 0) == MHD_GNUTLS_CRD_CERTIFICATE)
+ {
+
+ key_usage = cert->key_usage;
+
+ encipher_type = MHD_gtls_kx_encipher_type (alg);
+
+ if (key_usage != 0 && encipher_type != CIPHER_IGN)
+ {
+ /* If key_usage has been set in the certificate
+ */
+
+ if (encipher_type == CIPHER_ENCRYPT)
+ {
+ /* If the key exchange method requires an encipher
+ * type algorithm, and key's usage does not permit
+ * encipherment, then fail.
+ */
+ if (!(key_usage & KEY_KEY_ENCIPHERMENT))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+ }
+
+ if (encipher_type == CIPHER_SIGN)
+ {
+ /* The same as above, but for sign only keys
+ */
+ if (!(key_usage & KEY_DIGITAL_SIGNATURE))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_KEY_USAGE_VIOLATION;
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.h b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.h
new file mode 100644
index 0000000000..0726932807
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/gnutls_x509.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <libtasn1.h>
+
+int MHD__gnutls_x509_cert_verify_peers (MHD_gtls_session_t session,
+ unsigned int *status);
+
+#define PEM_CERT_SEP2 "-----BEGIN X509 CERTIFICATE"
+#define PEM_CERT_SEP "-----BEGIN CERTIFICATE"
+
+#define PEM_CRL_SEP "-----BEGIN X509 CRL"
+
+#define PEM_KEY_RSA_SEP "-----BEGIN RSA"
+#define PEM_KEY_DSA_SEP "-----BEGIN DSA"
+
+int MHD__gnutls_check_key_usage (const MHD_gnutls_cert * cert,
+ enum MHD_GNUTLS_KeyExchangeAlgorithm alg);
+
+int MHD__gnutls_x509_read_rsa_params (opaque * der, int dersize,
+ mpi_t * params);
+int MHD__gnutls_x509_read_dsa_pubkey (opaque * der, int dersize,
+ mpi_t * params);
+
+int MHD__gnutls_x509_raw_privkey_to_gkey (MHD_gnutls_privkey * privkey,
+ const MHD_gnutls_datum_t * raw_key,
+ MHD_gnutls_x509_crt_fmt_t type);
+int MHD__gnutls_x509_privkey_to_gkey (MHD_gnutls_privkey * privkey,
+ MHD_gnutls_x509_privkey_t);
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/memmem.c b/lib/libmicrohttpd/src/daemon/https/tls/memmem.c
new file mode 100644
index 0000000000..77143a7e1f
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/memmem.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 1991,92,93,94,96,97,98,2000,2004,2007,2008 Free Software
+ Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This particular implementation was written by Eric Blake, 2008. */
+
+/* Specification of memmem. */
+#include "gnutls_global.h"
+#include <string.h>
+
+#if !HAVE_MEMMEM
+
+#ifndef _LIBC
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+#define RETURN_TYPE void *
+#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l))
+#include "str-two-way.h"
+
+/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK
+ if NEEDLE_LEN is 0, otherwise NULL if NEEDLE is not found in
+ HAYSTACK. */
+void *
+memmem (const void *haystack_start, size_t haystack_len,
+ const void *needle_start, size_t needle_len)
+{
+ /* Abstract memory is considered to be an array of 'unsigned char' values,
+ not an array of 'char' values. See ISO C 99 section 6.2.6.1. */
+ const unsigned char *haystack = (const unsigned char *) haystack_start;
+ const unsigned char *needle = (const unsigned char *) needle_start;
+
+ if (needle_len == 0)
+ /* The first occurrence of the empty string is deemed to occur at
+ the beginning of the string. */
+ return (void *) haystack;
+
+ /* Sanity check, otherwise the loop might search through the whole
+ memory. */
+ if (__builtin_expect (haystack_len < needle_len, 0))
+ return NULL;
+
+ /* Use optimizations in memchr when possible, to reduce the search
+ size of haystack using a linear algorithm with a smaller
+ coefficient. However, avoid memchr for long needles, since we
+ can often achieve sublinear performance. */
+ if (needle_len < LONG_NEEDLE_THRESHOLD)
+ {
+ haystack = memchr (haystack, *needle, haystack_len);
+ if (!haystack || __builtin_expect (needle_len == 1, 0))
+ return (void *) haystack;
+ haystack_len -= haystack - (const unsigned char *) haystack_start;
+ if (haystack_len < needle_len)
+ return NULL;
+ return two_way_short_needle (haystack, haystack_len, needle,
+ needle_len);
+ }
+ else
+ return two_way_long_needle (haystack, haystack_len, needle, needle_len);
+}
+
+#undef LONG_NEEDLE_THRESHOLD
+
+#endif /* !HAVE_MEMMEM */
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/pkix_asn1_tab.c b/lib/libmicrohttpd/src/daemon/https/tls/pkix_asn1_tab.c
new file mode 100644
index 0000000000..30b5ddd1c1
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/pkix_asn1_tab.c
@@ -0,0 +1,1130 @@
+#if HAVE_CONFIG_H
+#include "MHD_config.h"
+#endif
+
+#include <libtasn1.h>
+
+const ASN1_ARRAY_TYPE MHD_pkix_asn1_tab[] = {
+ {"PKIX1", 536875024, 0},
+ {0, 1073741836, 0},
+ {"id-ce", 1879048204, 0},
+ {"joint-iso-ccitt", 1073741825, "2"},
+ {"ds", 1073741825, "5"},
+ {0, 1, "29"},
+ {"id-ce-authorityKeyIdentifier", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "35"},
+ {"AuthorityKeyIdentifier", 1610612741, 0},
+ {"keyIdentifier", 1610637314, "KeyIdentifier"},
+ {0, 4104, "0"},
+ {"authorityCertIssuer", 1610637314, "GeneralNames"},
+ {0, 4104, "1"},
+ {"authorityCertSerialNumber", 536895490, "CertificateSerialNumber"},
+ {0, 4104, "2"},
+ {"KeyIdentifier", 1073741831, 0},
+ {"id-ce-subjectKeyIdentifier", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "14"},
+ {"SubjectKeyIdentifier", 1073741826, "KeyIdentifier"},
+ {"id-ce-keyUsage", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "15"},
+ {"KeyUsage", 1610874886, 0},
+ {"digitalSignature", 1073741825, "0"},
+ {"nonRepudiation", 1073741825, "1"},
+ {"keyEncipherment", 1073741825, "2"},
+ {"dataEncipherment", 1073741825, "3"},
+ {"keyAgreement", 1073741825, "4"},
+ {"keyCertSign", 1073741825, "5"},
+ {"cRLSign", 1073741825, "6"},
+ {"encipherOnly", 1073741825, "7"},
+ {"decipherOnly", 1, "8"},
+ {"id-ce-privateKeyUsagePeriod", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "16"},
+ {"PrivateKeyUsagePeriod", 1610612741, 0},
+ {"notBefore", 1619025937, 0},
+ {0, 4104, "0"},
+ {"notAfter", 545284113, 0},
+ {0, 4104, "1"},
+ {"id-ce-certificatePolicies", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "32"},
+ {"CertificatePolicies", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "PolicyInformation"},
+ {"PolicyInformation", 1610612741, 0},
+ {"policyIdentifier", 1073741826, "CertPolicyId"},
+ {"policyQualifiers", 538984459, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "PolicyQualifierInfo"},
+ {"CertPolicyId", 1073741836, 0},
+ {"PolicyQualifierInfo", 1610612741, 0},
+ {"policyQualifierId", 1073741826, "PolicyQualifierId"},
+ {"qualifier", 541065229, 0},
+ {"policyQualifierId", 1, 0},
+ {"PolicyQualifierId", 1073741836, 0},
+ {"CPSuri", 1073741826, "IA5String"},
+ {"UserNotice", 1610612741, 0},
+ {"noticeRef", 1073758210, "NoticeReference"},
+ {"explicitText", 16386, "DisplayText"},
+ {"NoticeReference", 1610612741, 0},
+ {"organization", 1073741826, "DisplayText"},
+ {"noticeNumbers", 536870923, 0},
+ {0, 3, 0},
+ {"DisplayText", 1610612754, 0},
+ {"visibleString", 1612709890, "VisibleString"},
+ {"200", 524298, "1"},
+ {"bmpString", 1612709890, "BMPString"},
+ {"200", 524298, "1"},
+ {"utf8String", 538968066, "UTF8String"},
+ {"200", 524298, "1"},
+ {"id-ce-policyMappings", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "33"},
+ {"PolicyMappings", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 536870917, 0},
+ {"issuerDomainPolicy", 1073741826, "CertPolicyId"},
+ {"subjectDomainPolicy", 2, "CertPolicyId"},
+ {"DirectoryString", 1610612754, 0},
+ {"teletexString", 1612709890, "TeletexString"},
+ {"MAX", 524298, "1"},
+ {"printableString", 1612709890, "PrintableString"},
+ {"MAX", 524298, "1"},
+ {"universalString", 1612709890, "UniversalString"},
+ {"MAX", 524298, "1"},
+ {"utf8String", 1612709890, "UTF8String"},
+ {"MAX", 524298, "1"},
+ {"bmpString", 1612709890, "BMPString"},
+ {"MAX", 524298, "1"},
+ {"ia5String", 538968066, "IA5String"},
+ {"MAX", 524298, "1"},
+ {"id-ce-subjectAltName", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "17"},
+ {"SubjectAltName", 1073741826, "GeneralNames"},
+ {"GeneralNames", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "GeneralName"},
+ {"GeneralName", 1610612754, 0},
+ {"otherName", 1610620930, "AnotherName"},
+ {0, 4104, "0"},
+ {"rfc822Name", 1610620930, "IA5String"},
+ {0, 4104, "1"},
+ {"dNSName", 1610620930, "IA5String"},
+ {0, 4104, "2"},
+ {"x400Address", 1610620930, "ORAddress"},
+ {0, 4104, "3"},
+ {"directoryName", 1610620930, "RDNSequence"},
+ {0, 2056, "4"},
+ {"ediPartyName", 1610620930, "EDIPartyName"},
+ {0, 4104, "5"},
+ {"uniformResourceIdentifier", 1610620930, "IA5String"},
+ {0, 4104, "6"},
+ {"iPAddress", 1610620935, 0},
+ {0, 4104, "7"},
+ {"registeredID", 536879116, 0},
+ {0, 4104, "8"},
+ {"AnotherName", 1610612741, 0},
+ {"type-id", 1073741836, 0},
+ {"value", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"type-id", 1, 0},
+ {"EDIPartyName", 1610612741, 0},
+ {"nameAssigner", 1610637314, "DirectoryString"},
+ {0, 4104, "0"},
+ {"partyName", 536879106, "DirectoryString"},
+ {0, 4104, "1"},
+ {"id-ce-issuerAltName", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "18"},
+ {"IssuerAltName", 1073741826, "GeneralNames"},
+ {"id-ce-subjectDirectoryAttributes", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "9"},
+ {"SubjectDirectoryAttributes", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "Attribute"},
+ {"id-ce-basicConstraints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "19"},
+ {"BasicConstraints", 1610612741, 0},
+ {"cA", 1610645508, 0},
+ {0, 131081, 0},
+ {"pathLenConstraint", 537411587, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-nameConstraints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "30"},
+ {"NameConstraints", 1610612741, 0},
+ {"permittedSubtrees", 1610637314, "GeneralSubtrees"},
+ {0, 4104, "0"},
+ {"excludedSubtrees", 536895490, "GeneralSubtrees"},
+ {0, 4104, "1"},
+ {"GeneralSubtrees", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "GeneralSubtree"},
+ {"GeneralSubtree", 1610612741, 0},
+ {"base", 1073741826, "GeneralName"},
+ {"minimum", 1610653698, "BaseDistance"},
+ {0, 1073741833, "0"},
+ {0, 4104, "0"},
+ {"maximum", 536895490, "BaseDistance"},
+ {0, 4104, "1"},
+ {"BaseDistance", 1611137027, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-policyConstraints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "36"},
+ {"PolicyConstraints", 1610612741, 0},
+ {"requireExplicitPolicy", 1610637314, "SkipCerts"},
+ {0, 4104, "0"},
+ {"inhibitPolicyMapping", 536895490, "SkipCerts"},
+ {0, 4104, "1"},
+ {"SkipCerts", 1611137027, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-cRLDistributionPoints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "31"},
+ {"CRLDistributionPoints", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "DistributionPoint"},
+ {"DistributionPoint", 1610612741, 0},
+ {"distributionPoint", 1610637314, "DistributionPointName"},
+ {0, 2056, "0"},
+ {"reasons", 1610637314, "ReasonFlags"},
+ {0, 4104, "1"},
+ {"cRLIssuer", 536895490, "GeneralNames"},
+ {0, 4104, "2"},
+ {"DistributionPointName", 1610612754, 0},
+ {"fullName", 1610620930, "GeneralNames"},
+ {0, 4104, "0"},
+ {"nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"},
+ {0, 4104, "1"},
+ {"ReasonFlags", 1610874886, 0},
+ {"unused", 1073741825, "0"},
+ {"keyCompromise", 1073741825, "1"},
+ {"cACompromise", 1073741825, "2"},
+ {"affiliationChanged", 1073741825, "3"},
+ {"superseded", 1073741825, "4"},
+ {"cessationOfOperation", 1073741825, "5"},
+ {"certificateHold", 1073741825, "6"},
+ {"privilegeWithdrawn", 1073741825, "7"},
+ {"aACompromise", 1, "8"},
+ {"id-ce-extKeyUsage", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "37"},
+ {"ExtKeyUsageSyntax", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "KeyPurposeId"},
+ {"KeyPurposeId", 1073741836, 0},
+ {"id-kp-serverAuth", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "1"},
+ {"id-kp-clientAuth", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "2"},
+ {"id-kp-codeSigning", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "3"},
+ {"id-kp-emailProtection", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "4"},
+ {"id-kp-ipsecEndSystem", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "5"},
+ {"id-kp-ipsecTunnel", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "6"},
+ {"id-kp-ipsecUser", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "7"},
+ {"id-kp-timeStamping", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "8"},
+ {"id-pe-authorityInfoAccess", 1879048204, 0},
+ {0, 1073741825, "id-pe"},
+ {0, 1, "1"},
+ {"AuthorityInfoAccessSyntax", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "AccessDescription"},
+ {"AccessDescription", 1610612741, 0},
+ {"accessMethod", 1073741836, 0},
+ {"accessLocation", 2, "GeneralName"},
+ {"id-ce-cRLNumber", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "20"},
+ {"CRLNumber", 1611137027, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-issuingDistributionPoint", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "28"},
+ {"IssuingDistributionPoint", 1610612741, 0},
+ {"distributionPoint", 1610637314, "DistributionPointName"},
+ {0, 4104, "0"},
+ {"onlyContainsUserCerts", 1610653700, 0},
+ {0, 1073872905, 0},
+ {0, 4104, "1"},
+ {"onlyContainsCACerts", 1610653700, 0},
+ {0, 1073872905, 0},
+ {0, 4104, "2"},
+ {"onlySomeReasons", 1610637314, "ReasonFlags"},
+ {0, 4104, "3"},
+ {"indirectCRL", 536911876, 0},
+ {0, 1073872905, 0},
+ {0, 4104, "4"},
+ {"id-ce-deltaCRLIndicator", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "27"},
+ {"BaseCRLNumber", 1073741826, "CRLNumber"},
+ {"id-ce-cRLReasons", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "21"},
+ {"CRLReason", 1610874901, 0},
+ {"unspecified", 1073741825, "0"},
+ {"keyCompromise", 1073741825, "1"},
+ {"cACompromise", 1073741825, "2"},
+ {"affiliationChanged", 1073741825, "3"},
+ {"superseded", 1073741825, "4"},
+ {"cessationOfOperation", 1073741825, "5"},
+ {"certificateHold", 1073741825, "6"},
+ {"removeFromCRL", 1, "8"},
+ {"id-ce-certificateIssuer", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "29"},
+ {"CertificateIssuer", 1073741826, "GeneralNames"},
+ {"id-ce-holdInstructionCode", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "23"},
+ {"HoldInstructionCode", 1073741836, 0},
+ {"holdInstruction", 1879048204, 0},
+ {"joint-iso-itu-t", 1073741825, "2"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"x9cm", 1073741825, "10040"},
+ {0, 1, "2"},
+ {"id-holdinstruction-none", 1879048204, 0},
+ {0, 1073741825, "holdInstruction"},
+ {0, 1, "1"},
+ {"id-holdinstruction-callissuer", 1879048204, 0},
+ {0, 1073741825, "holdInstruction"},
+ {0, 1, "2"},
+ {"id-holdinstruction-reject", 1879048204, 0},
+ {0, 1073741825, "holdInstruction"},
+ {0, 1, "3"},
+ {"id-ce-invalidityDate", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "24"},
+ {"InvalidityDate", 1082130449, 0},
+ {"VisibleString", 1610620935, 0},
+ {0, 4360, "26"},
+ {"NumericString", 1610620935, 0},
+ {0, 4360, "18"},
+ {"IA5String", 1610620935, 0},
+ {0, 4360, "22"},
+ {"TeletexString", 1610620935, 0},
+ {0, 4360, "20"},
+ {"PrintableString", 1610620935, 0},
+ {0, 4360, "19"},
+ {"UniversalString", 1610620935, 0},
+ {0, 4360, "28"},
+ {"BMPString", 1610620935, 0},
+ {0, 4360, "30"},
+ {"UTF8String", 1610620935, 0},
+ {0, 4360, "12"},
+ {"id-pkix", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"identified-organization", 1073741825, "3"},
+ {"dod", 1073741825, "6"},
+ {"internet", 1073741825, "1"},
+ {"security", 1073741825, "5"},
+ {"mechanisms", 1073741825, "5"},
+ {"pkix", 1, "7"},
+ {"id-pe", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "1"},
+ {"id-qt", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "2"},
+ {"id-kp", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "3"},
+ {"id-ad", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "48"},
+ {"id-qt-cps", 1879048204, 0},
+ {0, 1073741825, "id-qt"},
+ {0, 1, "1"},
+ {"id-qt-unotice", 1879048204, 0},
+ {0, 1073741825, "id-qt"},
+ {0, 1, "2"},
+ {"id-ad-ocsp", 1879048204, 0},
+ {0, 1073741825, "id-ad"},
+ {0, 1, "1"},
+ {"id-ad-caIssuers", 1879048204, 0},
+ {0, 1073741825, "id-ad"},
+ {0, 1, "2"},
+ {"Attribute", 1610612741, 0},
+ {"type", 1073741826, "AttributeType"},
+ {"values", 536870927, 0},
+ {0, 2, "AttributeValue"},
+ {"AttributeType", 1073741836, 0},
+ {"AttributeValue", 1614807053, 0},
+ {"type", 1, 0},
+ {"AttributeTypeAndValue", 1610612741, 0},
+ {"type", 1073741826, "AttributeType"},
+ {"value", 2, "AttributeValue"},
+ {"id-at", 1879048204, 0},
+ {"joint-iso-ccitt", 1073741825, "2"},
+ {"ds", 1073741825, "5"},
+ {0, 1, "4"},
+ {"id-at-initials", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "43"},
+ {"X520initials", 1073741826, "DirectoryString"},
+ {"id-at-generationQualifier", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "44"},
+ {"X520generationQualifier", 1073741826, "DirectoryString"},
+ {"id-at-surname", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "4"},
+ {"X520surName", 1073741826, "DirectoryString"},
+ {"id-at-givenName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "42"},
+ {"X520givenName", 1073741826, "DirectoryString"},
+ {"id-at-name", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "41"},
+ {"X520name", 1073741826, "DirectoryString"},
+ {"id-at-commonName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "3"},
+ {"X520CommonName", 1073741826, "DirectoryString"},
+ {"id-at-localityName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "7"},
+ {"X520LocalityName", 1073741826, "DirectoryString"},
+ {"id-at-stateOrProvinceName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "8"},
+ {"X520StateOrProvinceName", 1073741826, "DirectoryString"},
+ {"id-at-organizationName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "10"},
+ {"X520OrganizationName", 1073741826, "DirectoryString"},
+ {"id-at-organizationalUnitName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "11"},
+ {"X520OrganizationalUnitName", 1073741826, "DirectoryString"},
+ {"id-at-title", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "12"},
+ {"X520Title", 1073741826, "DirectoryString"},
+ {"id-at-description", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "13"},
+ {"X520Description", 1073741826, "DirectoryString"},
+ {"id-at-dnQualifier", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "46"},
+ {"X520dnQualifier", 1073741826, "PrintableString"},
+ {"id-at-countryName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "6"},
+ {"X520countryName", 1612709890, "PrintableString"},
+ {0, 1048586, "2"},
+ {"id-at-serialNumber", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "5"},
+ {"X520serialNumber", 1073741826, "PrintableString"},
+ {"id-at-telephoneNumber", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "20"},
+ {"X520telephoneNumber", 1073741826, "PrintableString"},
+ {"id-at-facsimileTelephoneNumber", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "23"},
+ {"X520facsimileTelephoneNumber", 1073741826, "PrintableString"},
+ {"id-at-pseudonym", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "65"},
+ {"X520pseudonym", 1073741826, "DirectoryString"},
+ {"id-at-name", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "41"},
+ {"X520name", 1073741826, "DirectoryString"},
+ {"id-at-streetAddress", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "9"},
+ {"X520streetAddress", 1073741826, "DirectoryString"},
+ {"id-at-postalAddress", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "16"},
+ {"X520postalAddress", 1073741826, "PostalAddress"},
+ {"PostalAddress", 1610612747, 0},
+ {0, 2, "DirectoryString"},
+ {"pkcs", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {"pkcs", 1, "1"},
+ {"pkcs-9", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "9"},
+ {"emailAddress", 1880096780, "AttributeType"},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "1"},
+ {"Pkcs9email", 1612709890, "IA5String"},
+ {"ub-emailaddress-length", 524298, "1"},
+ {"Name", 1610612754, 0},
+ {"rdnSequence", 2, "RDNSequence"},
+ {"RDNSequence", 1610612747, 0},
+ {0, 2, "RelativeDistinguishedName"},
+ {"DistinguishedName", 1073741826, "RDNSequence"},
+ {"RelativeDistinguishedName", 1612709903, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "AttributeTypeAndValue"},
+ {"Certificate", 1610612741, 0},
+ {"tbsCertificate", 1073741826, "TBSCertificate"},
+ {"signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"signature", 6, 0},
+ {"TBSCertificate", 1610612741, 0},
+ {"version", 1610653698, "Version"},
+ {0, 1073741833, "v1"},
+ {0, 2056, "0"},
+ {"serialNumber", 1073741826, "CertificateSerialNumber"},
+ {"signature", 1073741826, "AlgorithmIdentifier"},
+ {"issuer", 1073741826, "Name"},
+ {"validity", 1073741826, "Validity"},
+ {"subject", 1073741826, "Name"},
+ {"subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"},
+ {"issuerUniqueID", 1610637314, "UniqueIdentifier"},
+ {0, 4104, "1"},
+ {"subjectUniqueID", 1610637314, "UniqueIdentifier"},
+ {0, 4104, "2"},
+ {"extensions", 536895490, "Extensions"},
+ {0, 2056, "3"},
+ {"Version", 1610874883, 0},
+ {"v1", 1073741825, "0"},
+ {"v2", 1073741825, "1"},
+ {"v3", 1, "2"},
+ {"CertificateSerialNumber", 1073741827, 0},
+ {"Validity", 1610612741, 0},
+ {"notBefore", 1073741826, "Time"},
+ {"notAfter", 2, "Time"},
+ {"Time", 1610612754, 0},
+ {"utcTime", 1090519057, 0},
+ {"generalTime", 8388625, 0},
+ {"UniqueIdentifier", 1073741830, 0},
+ {"SubjectPublicKeyInfo", 1610612741, 0},
+ {"algorithm", 1073741826, "AlgorithmIdentifier"},
+ {"subjectPublicKey", 6, 0},
+ {"Extensions", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "Extension"},
+ {"Extension", 1610612741, 0},
+ {"extnID", 1073741836, 0},
+ {"critical", 1610645508, 0},
+ {0, 131081, 0},
+ {"extnValue", 7, 0},
+ {"CertificateList", 1610612741, 0},
+ {"tbsCertList", 1073741826, "TBSCertList"},
+ {"signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"signature", 6, 0},
+ {"TBSCertList", 1610612741, 0},
+ {"version", 1073758210, "Version"},
+ {"signature", 1073741826, "AlgorithmIdentifier"},
+ {"issuer", 1073741826, "Name"},
+ {"thisUpdate", 1073741826, "Time"},
+ {"nextUpdate", 1073758210, "Time"},
+ {"revokedCertificates", 1610629131, 0},
+ {0, 536870917, 0},
+ {"userCertificate", 1073741826, "CertificateSerialNumber"},
+ {"revocationDate", 1073741826, "Time"},
+ {"crlEntryExtensions", 16386, "Extensions"},
+ {"crlExtensions", 536895490, "Extensions"},
+ {0, 2056, "0"},
+ {"AlgorithmIdentifier", 1610612741, 0},
+ {"algorithm", 1073741836, 0},
+ {"parameters", 541081613, 0},
+ {"algorithm", 1, 0},
+ {"pkcs-1", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "1"},
+ {"rsaEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "1"},
+ {"md2WithRSAEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "2"},
+ {"md5WithRSAEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "4"},
+ {"sha1WithRSAEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "5"},
+ {"id-dsa-with-sha1", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"x9-57", 1073741825, "10040"},
+ {"x9algorithm", 1073741825, "4"},
+ {0, 1, "3"},
+ {"Dss-Sig-Value", 1610612741, 0},
+ {"r", 1073741827, 0},
+ {"s", 3, 0},
+ {"dhpublicnumber", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"ansi-x942", 1073741825, "10046"},
+ {"number-type", 1073741825, "2"},
+ {0, 1, "1"},
+ {"DomainParameters", 1610612741, 0},
+ {"p", 1073741827, 0},
+ {"g", 1073741827, 0},
+ {"q", 1073741827, 0},
+ {"j", 1073758211, 0},
+ {"validationParms", 16386, "ValidationParms"},
+ {"ValidationParms", 1610612741, 0},
+ {"seed", 1073741830, 0},
+ {"pgenCounter", 3, 0},
+ {"id-dsa", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"x9-57", 1073741825, "10040"},
+ {"x9algorithm", 1073741825, "4"},
+ {0, 1, "1"},
+ {"Dss-Parms", 1610612741, 0},
+ {"p", 1073741827, 0},
+ {"q", 1073741827, 0},
+ {"g", 3, 0},
+ {"ORAddress", 1610612741, 0},
+ {"built-in-standard-attributes", 1073741826, "BuiltInStandardAttributes"},
+ {"built-in-domain-defined-attributes", 1073758210,
+ "BuiltInDomainDefinedAttributes"},
+ {"extension-attributes", 16386, "ExtensionAttributes"},
+ {"BuiltInStandardAttributes", 1610612741, 0},
+ {"country-name", 1073758210, "CountryName"},
+ {"administration-domain-name", 1073758210, "AdministrationDomainName"},
+ {"network-address", 1610637314, "NetworkAddress"},
+ {0, 2056, "0"},
+ {"terminal-identifier", 1610637314, "TerminalIdentifier"},
+ {0, 2056, "1"},
+ {"private-domain-name", 1610637314, "PrivateDomainName"},
+ {0, 2056, "2"},
+ {"organization-name", 1610637314, "OrganizationName"},
+ {0, 2056, "3"},
+ {"numeric-user-identifier", 1610637314, "NumericUserIdentifier"},
+ {0, 2056, "4"},
+ {"personal-name", 1610637314, "PersonalName"},
+ {0, 2056, "5"},
+ {"organizational-unit-names", 536895490, "OrganizationalUnitNames"},
+ {0, 2056, "6"},
+ {"CountryName", 1610620946, 0},
+ {0, 1073746952, "1"},
+ {"x121-dcc-code", 1612709890, "NumericString"},
+ {0, 1048586, "ub-country-name-numeric-length"},
+ {"iso-3166-alpha2-code", 538968066, "PrintableString"},
+ {0, 1048586, "ub-country-name-alpha-length"},
+ {"AdministrationDomainName", 1610620946, 0},
+ {0, 1073744904, "2"},
+ {"numeric", 1612709890, "NumericString"},
+ {"ub-domain-name-length", 524298, "0"},
+ {"printable", 538968066, "PrintableString"},
+ {"ub-domain-name-length", 524298, "0"},
+ {"NetworkAddress", 1073741826, "X121Address"},
+ {"X121Address", 1612709890, "NumericString"},
+ {"ub-x121-address-length", 524298, "1"},
+ {"TerminalIdentifier", 1612709890, "PrintableString"},
+ {"ub-terminal-id-length", 524298, "1"},
+ {"PrivateDomainName", 1610612754, 0},
+ {"numeric", 1612709890, "NumericString"},
+ {"ub-domain-name-length", 524298, "1"},
+ {"printable", 538968066, "PrintableString"},
+ {"ub-domain-name-length", 524298, "1"},
+ {"OrganizationName", 1612709890, "PrintableString"},
+ {"ub-organization-name-length", 524298, "1"},
+ {"NumericUserIdentifier", 1612709890, "NumericString"},
+ {"ub-numeric-user-id-length", 524298, "1"},
+ {"PersonalName", 1610612750, 0},
+ {"surname", 1814044674, "PrintableString"},
+ {0, 1073745928, "0"},
+ {"ub-surname-length", 524298, "1"},
+ {"given-name", 1814061058, "PrintableString"},
+ {0, 1073745928, "1"},
+ {"ub-given-name-length", 524298, "1"},
+ {"initials", 1814061058, "PrintableString"},
+ {0, 1073745928, "2"},
+ {"ub-initials-length", 524298, "1"},
+ {"generation-qualifier", 740319234, "PrintableString"},
+ {0, 1073745928, "3"},
+ {"ub-generation-qualifier-length", 524298, "1"},
+ {"OrganizationalUnitNames", 1612709899, 0},
+ {"ub-organizational-units", 1074266122, "1"},
+ {0, 2, "OrganizationalUnitName"},
+ {"OrganizationalUnitName", 1612709890, "PrintableString"},
+ {"ub-organizational-unit-name-length", 524298, "1"},
+ {"BuiltInDomainDefinedAttributes", 1612709899, 0},
+ {"ub-domain-defined-attributes", 1074266122, "1"},
+ {0, 2, "BuiltInDomainDefinedAttribute"},
+ {"BuiltInDomainDefinedAttribute", 1610612741, 0},
+ {"type", 1612709890, "PrintableString"},
+ {"ub-domain-defined-attribute-type-length", 524298, "1"},
+ {"value", 538968066, "PrintableString"},
+ {"ub-domain-defined-attribute-value-length", 524298, "1"},
+ {"ExtensionAttributes", 1612709903, 0},
+ {"ub-extension-attributes", 1074266122, "1"},
+ {0, 2, "ExtensionAttribute"},
+ {"ExtensionAttribute", 1610612741, 0},
+ {"extension-attribute-type", 1611145219, 0},
+ {0, 1073743880, "0"},
+ {"0", 10, "ub-extension-attributes"},
+ {"extension-attribute-value", 541073421, 0},
+ {0, 1073743880, "1"},
+ {"extension-attribute-type", 1, 0},
+ {"common-name", 1342177283, "1"},
+ {"CommonName", 1612709890, "PrintableString"},
+ {"ub-common-name-length", 524298, "1"},
+ {"teletex-common-name", 1342177283, "2"},
+ {"TeletexCommonName", 1612709890, "TeletexString"},
+ {"ub-common-name-length", 524298, "1"},
+ {"teletex-organization-name", 1342177283, "3"},
+ {"TeletexOrganizationName", 1612709890, "TeletexString"},
+ {"ub-organization-name-length", 524298, "1"},
+ {"teletex-personal-name", 1342177283, "4"},
+ {"TeletexPersonalName", 1610612750, 0},
+ {"surname", 1814044674, "TeletexString"},
+ {0, 1073743880, "0"},
+ {"ub-surname-length", 524298, "1"},
+ {"given-name", 1814061058, "TeletexString"},
+ {0, 1073743880, "1"},
+ {"ub-given-name-length", 524298, "1"},
+ {"initials", 1814061058, "TeletexString"},
+ {0, 1073743880, "2"},
+ {"ub-initials-length", 524298, "1"},
+ {"generation-qualifier", 740319234, "TeletexString"},
+ {0, 1073743880, "3"},
+ {"ub-generation-qualifier-length", 524298, "1"},
+ {"teletex-organizational-unit-names", 1342177283, "5"},
+ {"TeletexOrganizationalUnitNames", 1612709899, 0},
+ {"ub-organizational-units", 1074266122, "1"},
+ {0, 2, "TeletexOrganizationalUnitName"},
+ {"TeletexOrganizationalUnitName", 1612709890, "TeletexString"},
+ {"ub-organizational-unit-name-length", 524298, "1"},
+ {"pds-name", 1342177283, "7"},
+ {"PDSName", 1612709890, "PrintableString"},
+ {"ub-pds-name-length", 524298, "1"},
+ {"physical-delivery-country-name", 1342177283, "8"},
+ {"PhysicalDeliveryCountryName", 1610612754, 0},
+ {"x121-dcc-code", 1612709890, "NumericString"},
+ {0, 1048586, "ub-country-name-numeric-length"},
+ {"iso-3166-alpha2-code", 538968066, "PrintableString"},
+ {0, 1048586, "ub-country-name-alpha-length"},
+ {"postal-code", 1342177283, "9"},
+ {"PostalCode", 1610612754, 0},
+ {"numeric-code", 1612709890, "NumericString"},
+ {"ub-postal-code-length", 524298, "1"},
+ {"printable-code", 538968066, "PrintableString"},
+ {"ub-postal-code-length", 524298, "1"},
+ {"physical-delivery-office-name", 1342177283, "10"},
+ {"PhysicalDeliveryOfficeName", 1073741826, "PDSParameter"},
+ {"physical-delivery-office-number", 1342177283, "11"},
+ {"PhysicalDeliveryOfficeNumber", 1073741826, "PDSParameter"},
+ {"extension-OR-address-components", 1342177283, "12"},
+ {"ExtensionORAddressComponents", 1073741826, "PDSParameter"},
+ {"physical-delivery-personal-name", 1342177283, "13"},
+ {"PhysicalDeliveryPersonalName", 1073741826, "PDSParameter"},
+ {"physical-delivery-organization-name", 1342177283, "14"},
+ {"PhysicalDeliveryOrganizationName", 1073741826, "PDSParameter"},
+ {"extension-physical-delivery-address-components", 1342177283, "15"},
+ {"ExtensionPhysicalDeliveryAddressComponents", 1073741826, "PDSParameter"},
+ {"unformatted-postal-address", 1342177283, "16"},
+ {"UnformattedPostalAddress", 1610612750, 0},
+ {"printable-address", 1814052875, 0},
+ {"ub-pds-physical-address-lines", 1074266122, "1"},
+ {0, 538968066, "PrintableString"},
+ {"ub-pds-parameter-length", 524298, "1"},
+ {"teletex-string", 740311042, "TeletexString"},
+ {"ub-unformatted-address-length", 524298, "1"},
+ {"street-address", 1342177283, "17"},
+ {"StreetAddress", 1073741826, "PDSParameter"},
+ {"post-office-box-address", 1342177283, "18"},
+ {"PostOfficeBoxAddress", 1073741826, "PDSParameter"},
+ {"poste-restante-address", 1342177283, "19"},
+ {"PosteRestanteAddress", 1073741826, "PDSParameter"},
+ {"unique-postal-name", 1342177283, "20"},
+ {"UniquePostalName", 1073741826, "PDSParameter"},
+ {"local-postal-attributes", 1342177283, "21"},
+ {"LocalPostalAttributes", 1073741826, "PDSParameter"},
+ {"PDSParameter", 1610612750, 0},
+ {"printable-string", 1814052866, "PrintableString"},
+ {"ub-pds-parameter-length", 524298, "1"},
+ {"teletex-string", 740311042, "TeletexString"},
+ {"ub-pds-parameter-length", 524298, "1"},
+ {"extended-network-address", 1342177283, "22"},
+ {"ExtendedNetworkAddress", 1610612754, 0},
+ {"e163-4-address", 1610612741, 0},
+ {"number", 1612718082, "NumericString"},
+ {0, 1073743880, "0"},
+ {"ub-e163-4-number-length", 524298, "1"},
+ {"sub-address", 538992642, "NumericString"},
+ {0, 1073743880, "1"},
+ {"ub-e163-4-sub-address-length", 524298, "1"},
+ {"psap-address", 536879106, "PresentationAddress"},
+ {0, 2056, "0"},
+ {"PresentationAddress", 1610612741, 0},
+ {"pSelector", 1610637319, 0},
+ {0, 2056, "0"},
+ {"sSelector", 1610637319, 0},
+ {0, 2056, "1"},
+ {"tSelector", 1610637319, 0},
+ {0, 2056, "2"},
+ {"nAddresses", 538976271, 0},
+ {0, 1073743880, "3"},
+ {"MAX", 1074266122, "1"},
+ {0, 7, 0},
+ {"terminal-type", 1342177283, "23"},
+ {"TerminalType", 1610874883, 0},
+ {"telex", 1073741825, "3"},
+ {"teletex", 1073741825, "4"},
+ {"g3-facsimile", 1073741825, "5"},
+ {"g4-facsimile", 1073741825, "6"},
+ {"ia5-terminal", 1073741825, "7"},
+ {"videotex", 1, "8"},
+ {"teletex-domain-defined-attributes", 1342177283, "6"},
+ {"TeletexDomainDefinedAttributes", 1612709899, 0},
+ {"ub-domain-defined-attributes", 1074266122, "1"},
+ {0, 2, "TeletexDomainDefinedAttribute"},
+ {"TeletexDomainDefinedAttribute", 1610612741, 0},
+ {"type", 1612709890, "TeletexString"},
+ {"ub-domain-defined-attribute-type-length", 524298, "1"},
+ {"value", 538968066, "TeletexString"},
+ {"ub-domain-defined-attribute-value-length", 524298, "1"},
+ {"ub-name", 1342177283, "32768"},
+ {"ub-common-name", 1342177283, "64"},
+ {"ub-locality-name", 1342177283, "128"},
+ {"ub-state-name", 1342177283, "128"},
+ {"ub-organization-name", 1342177283, "64"},
+ {"ub-organizational-unit-name", 1342177283, "64"},
+ {"ub-title", 1342177283, "64"},
+ {"ub-match", 1342177283, "128"},
+ {"ub-emailaddress-length", 1342177283, "128"},
+ {"ub-common-name-length", 1342177283, "64"},
+ {"ub-country-name-alpha-length", 1342177283, "2"},
+ {"ub-country-name-numeric-length", 1342177283, "3"},
+ {"ub-domain-defined-attributes", 1342177283, "4"},
+ {"ub-domain-defined-attribute-type-length", 1342177283, "8"},
+ {"ub-domain-defined-attribute-value-length", 1342177283, "128"},
+ {"ub-domain-name-length", 1342177283, "16"},
+ {"ub-extension-attributes", 1342177283, "256"},
+ {"ub-e163-4-number-length", 1342177283, "15"},
+ {"ub-e163-4-sub-address-length", 1342177283, "40"},
+ {"ub-generation-qualifier-length", 1342177283, "3"},
+ {"ub-given-name-length", 1342177283, "16"},
+ {"ub-initials-length", 1342177283, "5"},
+ {"ub-integer-options", 1342177283, "256"},
+ {"ub-numeric-user-id-length", 1342177283, "32"},
+ {"ub-organization-name-length", 1342177283, "64"},
+ {"ub-organizational-unit-name-length", 1342177283, "32"},
+ {"ub-organizational-units", 1342177283, "4"},
+ {"ub-pds-name-length", 1342177283, "16"},
+ {"ub-pds-parameter-length", 1342177283, "30"},
+ {"ub-pds-physical-address-lines", 1342177283, "6"},
+ {"ub-postal-code-length", 1342177283, "16"},
+ {"ub-surname-length", 1342177283, "40"},
+ {"ub-terminal-id-length", 1342177283, "24"},
+ {"ub-unformatted-address-length", 1342177283, "180"},
+ {"ub-x121-address-length", 1342177283, "16"},
+ {"pkcs-7-ContentInfo", 1610612741, 0},
+ {"contentType", 1073741826, "pkcs-7-ContentType"},
+ {"content", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"contentType", 1, 0},
+ {"pkcs-7-DigestInfo", 1610612741, 0},
+ {"digestAlgorithm", 1073741826, "pkcs-7-DigestAlgorithmIdentifier"},
+ {"digest", 2, "pkcs-7-Digest"},
+ {"pkcs-7-Digest", 1073741831, 0},
+ {"pkcs-7-ContentType", 1073741836, 0},
+ {"pkcs-7-SignedData", 1610612741, 0},
+ {"version", 1073741826, "pkcs-7-CMSVersion"},
+ {"digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"},
+ {"encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"},
+ {"certificates", 1610637314, "pkcs-7-CertificateSet"},
+ {0, 4104, "0"},
+ {"crls", 1610637314, "pkcs-7-CertificateRevocationLists"},
+ {0, 4104, "1"},
+ {"signerInfos", 2, "pkcs-7-SignerInfos"},
+ {"pkcs-7-CMSVersion", 1610874883, 0},
+ {"v0", 1073741825, "0"},
+ {"v1", 1073741825, "1"},
+ {"v2", 1073741825, "2"},
+ {"v3", 1073741825, "3"},
+ {"v4", 1, "4"},
+ {"pkcs-7-DigestAlgorithmIdentifiers", 1610612751, 0},
+ {0, 2, "pkcs-7-DigestAlgorithmIdentifier"},
+ {"pkcs-7-DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
+ {"pkcs-7-EncapsulatedContentInfo", 1610612741, 0},
+ {"eContentType", 1073741826, "pkcs-7-ContentType"},
+ {"eContent", 536895495, 0},
+ {0, 2056, "0"},
+ {"pkcs-7-CertificateRevocationLists", 1610612751, 0},
+ {0, 13, 0},
+ {"pkcs-7-CertificateChoices", 1610612754, 0},
+ {"certificate", 13, 0},
+ {"pkcs-7-CertificateSet", 1610612751, 0},
+ {0, 2, "pkcs-7-CertificateChoices"},
+ {"pkcs-7-SignerInfos", 1610612751, 0},
+ {0, 13, 0},
+ {"pkcs-10-CertificationRequestInfo", 1610612741, 0},
+ {"version", 1610874883, 0},
+ {"v1", 1, "0"},
+ {"subject", 1073741826, "Name"},
+ {"subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"},
+ {"attributes", 536879106, "Attributes"},
+ {0, 4104, "0"},
+ {"Attributes", 1610612751, 0},
+ {0, 2, "Attribute"},
+ {"pkcs-10-CertificationRequest", 1610612741, 0},
+ {"certificationRequestInfo", 1073741826,
+ "pkcs-10-CertificationRequestInfo"},
+ {"signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"signature", 6, 0},
+ {"pkcs-9-ub-challengePassword", 1342177283, "255"},
+ {"pkcs-9-certTypes", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "22"},
+ {"pkcs-9-crlTypes", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "23"},
+ {"pkcs-9-at-challengePassword", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "7"},
+ {"pkcs-9-challengePassword", 1610612754, 0},
+ {"printableString", 1612709890, "PrintableString"},
+ {"pkcs-9-ub-challengePassword", 524298, "1"},
+ {"utf8String", 538968066, "UTF8String"},
+ {"pkcs-9-ub-challengePassword", 524298, "1"},
+ {"pkcs-9-at-localKeyId", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "21"},
+ {"pkcs-9-localKeyId", 1073741831, 0},
+ {"pkcs-9-at-friendlyName", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "20"},
+ {"pkcs-9-friendlyName", 1612709890, "BMPString"},
+ {"255", 524298, "1"},
+ {"pkcs-8-PrivateKeyInfo", 1610612741, 0},
+ {"version", 1073741826, "pkcs-8-Version"},
+ {"privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"privateKey", 1073741826, "pkcs-8-PrivateKey"},
+ {"attributes", 536895490, "Attributes"},
+ {0, 4104, "0"},
+ {"pkcs-8-Version", 1610874883, 0},
+ {"v1", 1, "0"},
+ {"pkcs-8-PrivateKey", 1073741831, 0},
+ {"pkcs-8-Attributes", 1610612751, 0},
+ {0, 2, "Attribute"},
+ {"pkcs-8-EncryptedPrivateKeyInfo", 1610612741, 0},
+ {"encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"encryptedData", 2, "pkcs-8-EncryptedData"},
+ {"pkcs-8-EncryptedData", 1073741831, 0},
+ {"pkcs-5", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "5"},
+ {"pkcs-5-encryptionAlgorithm", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {0, 1, "3"},
+ {"pkcs-5-des-EDE3-CBC", 1879048204, 0},
+ {0, 1073741825, "pkcs-5-encryptionAlgorithm"},
+ {0, 1, "7"},
+ {"pkcs-5-des-EDE3-CBC-params", 1612709895, 0},
+ {0, 1048586, "8"},
+ {"pkcs-5-id-PBES2", 1879048204, 0},
+ {0, 1073741825, "pkcs-5"},
+ {0, 1, "13"},
+ {"pkcs-5-PBES2-params", 1610612741, 0},
+ {"keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
+ {"encryptionScheme", 2, "AlgorithmIdentifier"},
+ {"pkcs-5-id-PBKDF2", 1879048204, 0},
+ {0, 1073741825, "pkcs-5"},
+ {0, 1, "12"},
+ {"pkcs-5-PBKDF2-params", 1610612741, 0},
+ {"salt", 1610612754, 0},
+ {"specified", 1073741831, 0},
+ {"otherSource", 2, "AlgorithmIdentifier"},
+ {"iterationCount", 1611137027, 0},
+ {"1", 10, "MAX"},
+ {"keyLength", 1611153411, 0},
+ {"1", 10, "MAX"},
+ {"prf", 16386, "AlgorithmIdentifier"},
+ {"pkcs-12", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "12"},
+ {"pkcs-12-PFX", 1610612741, 0},
+ {"version", 1610874883, 0},
+ {"v3", 1, "3"},
+ {"authSafe", 1073741826, "pkcs-7-ContentInfo"},
+ {"macData", 16386, "pkcs-12-MacData"},
+ {"pkcs-12-PbeParams", 1610612741, 0},
+ {"salt", 1073741831, 0},
+ {"iterations", 3, 0},
+ {"pkcs-12-MacData", 1610612741, 0},
+ {"mac", 1073741826, "pkcs-7-DigestInfo"},
+ {"macSalt", 1073741831, 0},
+ {"iterations", 536903683, 0},
+ {0, 9, "1"},
+ {"pkcs-12-AuthenticatedSafe", 1610612747, 0},
+ {0, 2, "pkcs-7-ContentInfo"},
+ {"pkcs-12-SafeContents", 1610612747, 0},
+ {0, 2, "pkcs-12-SafeBag"},
+ {"pkcs-12-SafeBag", 1610612741, 0},
+ {"bagId", 1073741836, 0},
+ {"bagValue", 1614815245, 0},
+ {0, 1073743880, "0"},
+ {"badId", 1, 0},
+ {"bagAttributes", 536887311, 0},
+ {0, 2, "pkcs-12-PKCS12Attribute"},
+ {"pkcs-12-bagtypes", 1879048204, 0},
+ {0, 1073741825, "pkcs-12"},
+ {0, 1073741825, "10"},
+ {0, 1, "1"},
+ {"pkcs-12-keyBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "1"},
+ {"pkcs-12-pkcs8ShroudedKeyBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "2"},
+ {"pkcs-12-certBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "3"},
+ {"pkcs-12-crlBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "4"},
+ {"pkcs-12-KeyBag", 1073741826, "pkcs-8-PrivateKeyInfo"},
+ {"pkcs-12-PKCS8ShroudedKeyBag", 1073741826,
+ "pkcs-8-EncryptedPrivateKeyInfo"},
+ {"pkcs-12-CertBag", 1610612741, 0},
+ {"certId", 1073741836, 0},
+ {"certValue", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"certId", 1, 0},
+ {"pkcs-12-CRLBag", 1610612741, 0},
+ {"crlId", 1073741836, 0},
+ {"crlValue", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"crlId", 1, 0},
+ {"pkcs-12-PKCS12Attribute", 1073741826, "Attribute"},
+ {"pkcs-7-data", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {"pkcs", 1073741825, "1"},
+ {"pkcs7", 1073741825, "7"},
+ {0, 1, "1"},
+ {"pkcs-7-encryptedData", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {"pkcs", 1073741825, "1"},
+ {"pkcs7", 1073741825, "7"},
+ {0, 1, "6"},
+ {"pkcs-7-Data", 1073741831, 0},
+ {"pkcs-7-EncryptedData", 1610612741, 0},
+ {"version", 1073741826, "pkcs-7-CMSVersion"},
+ {"encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"},
+ {"unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"},
+ {0, 4104, "1"},
+ {"pkcs-7-EncryptedContentInfo", 1610612741, 0},
+ {"contentType", 1073741826, "pkcs-7-ContentType"},
+ {"contentEncryptionAlgorithm", 1073741826,
+ "pkcs-7-ContentEncryptionAlgorithmIdentifier"},
+ {"encryptedContent", 536895490, "pkcs-7-EncryptedContent"},
+ {0, 4104, "0"},
+ {"pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826,
+ "AlgorithmIdentifier"},
+ {"pkcs-7-EncryptedContent", 1073741831, 0},
+ {"pkcs-7-UnprotectedAttributes", 1612709903, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "Attribute"},
+ {"id-at-ldap-DC", 1880096780, "AttributeType"},
+ {0, 1073741825, "0"},
+ {0, 1073741825, "9"},
+ {0, 1073741825, "2342"},
+ {0, 1073741825, "19200300"},
+ {0, 1073741825, "100"},
+ {0, 1073741825, "1"},
+ {0, 1, "25"},
+ {"ldap-DC", 1073741826, "IA5String"},
+ {"id-at-ldap-UID", 1880096780, "AttributeType"},
+ {0, 1073741825, "0"},
+ {0, 1073741825, "9"},
+ {0, 1073741825, "2342"},
+ {0, 1073741825, "19200300"},
+ {0, 1073741825, "100"},
+ {0, 1073741825, "1"},
+ {0, 1, "1"},
+ {"ldap-UID", 1073741826, "DirectoryString"},
+ {"id-pda", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "9"},
+ {"id-pda-dateOfBirth", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "1"},
+ {"DateOfBirth", 1082130449, 0},
+ {"id-pda-placeOfBirth", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "2"},
+ {"PlaceOfBirth", 1073741826, "DirectoryString"},
+ {"id-pda-gender", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "3"},
+ {"Gender", 1612709890, "PrintableString"},
+ {0, 1048586, "1"},
+ {"id-pda-countryOfCitizenship", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "4"},
+ {"CountryOfCitizenship", 1612709890, "PrintableString"},
+ {0, 1048586, "2"},
+ {"id-pda-countryOfResidence", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "5"},
+ {"CountryOfResidence", 1612709890, "PrintableString"},
+ {0, 1048586, "2"},
+ {"id-pe-proxyCertInfo", 1879048204, 0},
+ {0, 1073741825, "id-pe"},
+ {0, 1, "14"},
+ {"id-ppl-inheritAll", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1073741825, "21"},
+ {0, 1, "1"},
+ {"id-ppl-independent", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1073741825, "21"},
+ {0, 1, "2"},
+ {"ProxyCertInfo", 1610612741, 0},
+ {"pCPathLenConstraint", 1611153411, 0},
+ {"0", 10, "MAX"},
+ {"proxyPolicy", 2, "ProxyPolicy"},
+ {"ProxyPolicy", 1610612741, 0},
+ {"policyLanguage", 1073741836, 0},
+ {"policy", 16391, 0},
+ {"id-on", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "8"},
+ {"id-on-xmppAddr", 1879048204, 0},
+ {0, 1073741825, "id-on"},
+ {0, 1, "5"},
+ {"XmppAddr", 2, "UTF8String"},
+ {0, 0, 0}
+};
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/str-two-way.h b/lib/libmicrohttpd/src/daemon/https/tls/str-two-way.h
new file mode 100644
index 0000000000..29bb09f6a0
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/str-two-way.h
@@ -0,0 +1,429 @@
+/* Byte-wise substring search, using the Two-Way algorithm.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Eric Blake <ebb9@byu.net>, 2008.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Before including this file, you need to include <config.h> and
+ <string.h>, and define:
+ RESULT_TYPE A macro that expands to the return type.
+ AVAILABLE(h, h_l, j, n_l)
+ A macro that returns nonzero if there are
+ at least N_L bytes left starting at H[J].
+ H is 'unsigned char *', H_L, J, and N_L
+ are 'size_t'; H_L is an lvalue. For
+ NUL-terminated searches, H_L can be
+ modified each iteration to avoid having
+ to compute the end of H up front.
+
+ For case-insensitivity, you may optionally define:
+ CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L
+ characters of P1 and P2 are equal.
+ CANON_ELEMENT(c) A macro that canonicalizes an element right after
+ it has been fetched from one of the two strings.
+ The argument is an 'unsigned char'; the result
+ must be an 'unsigned char' as well.
+
+ This file undefines the macros documented above, and defines
+ LONG_NEEDLE_THRESHOLD.
+*/
+
+#include <limits.h>
+#include <stdint.h>
+
+/* We use the Two-Way string matching algorithm, which guarantees
+ linear complexity with constant space. Additionally, for long
+ needles, we also use a bad character shift table similar to the
+ Boyer-Moore algorithm to achieve improved (potentially sub-linear)
+ performance.
+
+ See http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260
+ and http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm
+*/
+
+/* Point at which computing a bad-byte shift table is likely to be
+ worthwhile. Small needles should not compute a table, since it
+ adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a
+ speedup no greater than a factor of NEEDLE_LEN. The larger the
+ needle, the better the potential performance gain. On the other
+ hand, on non-POSIX systems with CHAR_BIT larger than eight, the
+ memory required for the table is prohibitive. */
+#if CHAR_BIT < 10
+# define LONG_NEEDLE_THRESHOLD 32U
+#else
+# define LONG_NEEDLE_THRESHOLD SIZE_MAX
+#endif
+
+#ifndef MAX
+# define MAX(a, b) ((a < b) ? (b) : (a))
+#endif
+
+#ifndef CANON_ELEMENT
+# define CANON_ELEMENT(c) c
+#endif
+#ifndef CMP_FUNC
+# define CMP_FUNC memcmp
+#endif
+
+/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
+ Return the index of the first byte in the right half, and set
+ *PERIOD to the global period of the right half.
+
+ The global period of a string is the smallest index (possibly its
+ length) at which all remaining bytes in the string are repetitions
+ of the prefix (the last repetition may be a subset of the prefix).
+
+ When NEEDLE is factored into two halves, a local period is the
+ length of the smallest word that shares a suffix with the left half
+ and shares a prefix with the right half. All factorizations of a
+ non-empty NEEDLE have a local period of at least 1 and no greater
+ than NEEDLE_LEN.
+
+ A critical factorization has the property that the local period
+ equals the global period. All strings have at least one critical
+ factorization with the left half smaller than the global period.
+
+ Given an ordered alphabet, a critical factorization can be computed
+ in linear time, with 2 * NEEDLE_LEN comparisons, by computing the
+ larger of two ordered maximal suffixes. The ordered maximal
+ suffixes are determined by lexicographic comparison of
+ periodicity. */
+static size_t
+critical_factorization (const unsigned char *needle, size_t needle_len,
+ size_t * period)
+{
+ /* Index of last byte of left half, or SIZE_MAX. */
+ size_t max_suffix, max_suffix_rev;
+ size_t j; /* Index into NEEDLE for current candidate suffix. */
+ size_t k; /* Offset into current period. */
+ size_t p; /* Intermediate period. */
+ unsigned char a, b; /* Current comparison bytes. */
+
+ /* Invariants:
+ 0 <= j < NEEDLE_LEN - 1
+ -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed)
+ min(max_suffix, max_suffix_rev) < global period of NEEDLE
+ 1 <= p <= global period of NEEDLE
+ p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j]
+ 1 <= k <= p
+ */
+
+ /* Perform lexicographic search. */
+ max_suffix = SIZE_MAX;
+ j = 0;
+ k = p = 1;
+ while (j + k < needle_len)
+ {
+ a = CANON_ELEMENT (needle[j + k]);
+ b = CANON_ELEMENT (needle[max_suffix + k]);
+ if (a < b)
+ {
+ /* Suffix is smaller, period is entire prefix so far. */
+ j += k;
+ k = 1;
+ p = j - max_suffix;
+ }
+ else if (a == b)
+ {
+ /* Advance through repetition of the current period. */
+ if (k != p)
+ ++k;
+ else
+ {
+ j += p;
+ k = 1;
+ }
+ }
+ else /* b < a */
+ {
+ /* Suffix is larger, start over from current location. */
+ max_suffix = j++;
+ k = p = 1;
+ }
+ }
+ *period = p;
+
+ /* Perform reverse lexicographic search. */
+ max_suffix_rev = SIZE_MAX;
+ j = 0;
+ k = p = 1;
+ while (j + k < needle_len)
+ {
+ a = CANON_ELEMENT (needle[j + k]);
+ b = CANON_ELEMENT (needle[max_suffix_rev + k]);
+ if (b < a)
+ {
+ /* Suffix is smaller, period is entire prefix so far. */
+ j += k;
+ k = 1;
+ p = j - max_suffix_rev;
+ }
+ else if (a == b)
+ {
+ /* Advance through repetition of the current period. */
+ if (k != p)
+ ++k;
+ else
+ {
+ j += p;
+ k = 1;
+ }
+ }
+ else /* a < b */
+ {
+ /* Suffix is larger, start over from current location. */
+ max_suffix_rev = j++;
+ k = p = 1;
+ }
+ }
+
+ /* Choose the longer suffix. Return the first byte of the right
+ half, rather than the last byte of the left half. */
+ if (max_suffix_rev + 1 < max_suffix + 1)
+ return max_suffix + 1;
+ *period = p;
+ return max_suffix_rev + 1;
+}
+
+/* Return the first location of non-empty NEEDLE within HAYSTACK, or
+ NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
+ method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD.
+ Performance is guaranteed to be linear, with an initialization cost
+ of 2 * NEEDLE_LEN comparisons.
+
+ If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
+ most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
+ If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
+ HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */
+static RETURN_TYPE
+two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
+ const unsigned char *needle, size_t needle_len)
+{
+ size_t i; /* Index into current byte of NEEDLE. */
+ size_t j; /* Index into current window of HAYSTACK. */
+ size_t period; /* The period of the right half of needle. */
+ size_t suffix; /* The index of the right half of needle. */
+
+ /* Factor the needle into two halves, such that the left half is
+ smaller than the global period, and the right half is
+ periodic (with a period as large as NEEDLE_LEN - suffix). */
+ suffix = critical_factorization (needle, needle_len, &period);
+
+ /* Perform the search. Each iteration compares the right half
+ first. */
+ if (CMP_FUNC (needle, needle + period, suffix) == 0)
+ {
+ /* Entire needle is periodic; a mismatch can only advance by the
+ period, so use memory to avoid rescanning known occurrences
+ of the period. */
+ size_t memory = 0;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Scan for matches in right half. */
+ i = MAX (suffix, memory);
+ while (i < needle_len && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (memory < i + 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i + 1 < memory + 1)
+ return (RETURN_TYPE) (haystack + j);
+ /* No match, so remember how many repetitions of period
+ on the right half were scanned. */
+ j += period;
+ memory = needle_len - period;
+ }
+ else
+ {
+ j += i - suffix + 1;
+ memory = 0;
+ }
+ }
+ }
+ else
+ {
+ /* The two halves of needle are distinct; no extra memory is
+ required, and any mismatch results in a maximal shift. */
+ period = MAX (suffix, needle_len - suffix) + 1;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Scan for matches in right half. */
+ i = suffix;
+ while (i < needle_len && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i == SIZE_MAX)
+ return (RETURN_TYPE) (haystack + j);
+ j += period;
+ }
+ else
+ j += i - suffix + 1;
+ }
+ }
+ return NULL;
+}
+
+/* Return the first location of non-empty NEEDLE within HAYSTACK, or
+ NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
+ method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN.
+ Performance is guaranteed to be linear, with an initialization cost
+ of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations.
+
+ If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
+ most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching,
+ and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
+ If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
+ HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
+ sublinear performance is not possible. */
+static RETURN_TYPE
+two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
+ const unsigned char *needle, size_t needle_len)
+{
+ size_t i; /* Index into current byte of NEEDLE. */
+ size_t j; /* Index into current window of HAYSTACK. */
+ size_t period; /* The period of the right half of needle. */
+ size_t suffix; /* The index of the right half of needle. */
+ size_t shift_table[1U << CHAR_BIT]; /* See below. */
+
+ /* Factor the needle into two halves, such that the left half is
+ smaller than the global period, and the right half is
+ periodic (with a period as large as NEEDLE_LEN - suffix). */
+ suffix = critical_factorization (needle, needle_len, &period);
+
+ /* Populate shift_table. For each possible byte value c,
+ shift_table[c] is the distance from the last occurrence of c to
+ the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE.
+ shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */
+ for (i = 0; i < 1U << CHAR_BIT; i++)
+ shift_table[i] = needle_len;
+ for (i = 0; i < needle_len; i++)
+ shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1;
+
+ /* Perform the search. Each iteration compares the right half
+ first. */
+ if (CMP_FUNC (needle, needle + period, suffix) == 0)
+ {
+ /* Entire needle is periodic; a mismatch can only advance by the
+ period, so use memory to avoid rescanning known occurrences
+ of the period. */
+ size_t memory = 0;
+ size_t shift;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Check the last byte first; if it does not match, then
+ shift to the next possible match location. */
+ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
+ if (0 < shift)
+ {
+ if (memory && shift < period)
+ {
+ /* Since needle is periodic, but the last period has
+ a byte out of place, there can be no match until
+ after the mismatch. */
+ shift = needle_len - period;
+ memory = 0;
+ }
+ j += shift;
+ continue;
+ }
+ /* Scan for matches in right half. The last byte has
+ already been matched, by virtue of the shift table. */
+ i = MAX (suffix, memory);
+ while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len - 1 <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (memory < i + 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i + 1 < memory + 1)
+ return (RETURN_TYPE) (haystack + j);
+ /* No match, so remember how many repetitions of period
+ on the right half were scanned. */
+ j += period;
+ memory = needle_len - period;
+ }
+ else
+ {
+ j += i - suffix + 1;
+ memory = 0;
+ }
+ }
+ }
+ else
+ {
+ /* The two halves of needle are distinct; no extra memory is
+ required, and any mismatch results in a maximal shift. */
+ size_t shift;
+ period = MAX (suffix, needle_len - suffix) + 1;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Check the last byte first; if it does not match, then
+ shift to the next possible match location. */
+ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
+ if (0 < shift)
+ {
+ j += shift;
+ continue;
+ }
+ /* Scan for matches in right half. The last byte has
+ already been matched, by virtue of the shift table. */
+ i = suffix;
+ while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len - 1 <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i == SIZE_MAX)
+ return (RETURN_TYPE) (haystack + j);
+ j += period;
+ }
+ else
+ j += i - suffix + 1;
+ }
+ }
+ return NULL;
+}
+
+#undef AVAILABLE
+#undef CANON_ELEMENT
+#undef CMP_FUNC
+#undef MAX
+#undef RETURN_TYPE
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/x509_b64.c b/lib/libmicrohttpd/src/daemon/https/tls/x509_b64.c
new file mode 100644
index 0000000000..152f740943
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/x509_b64.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that relate to base64 encoding and decoding.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include <gnutls_datum.h>
+#include <x509_b64.h>
+
+static const uint8_t b64table[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const uint8_t asciitable[128] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+ 0xff, 0xf1, 0xff, 0xff, 0xff, 0x00, /* 0xf1 for '=' */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
+ 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+ 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
+ 0xff, 0xff
+};
+
+#define INCR(what, size) \
+ do { \
+ what+=size; \
+ if (what > ret) { \
+ MHD_gnutls_assert(); \
+ MHD_gnutls_free( (*result)); *result = NULL; \
+ return GNUTLS_E_INTERNAL_ERROR; \
+ } \
+ } while(0)
+
+
+inline static int
+encode (char *result, const uint8_t * data, int left)
+{
+
+ int data_len;
+
+ if (left > 3)
+ data_len = 3;
+ else
+ data_len = left;
+
+ switch (data_len)
+ {
+ case 3:
+ result[0] = b64table[(data[0] >> 2)];
+ result[1] =
+ b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
+ (data[1] >> 4))];
+ result[2] =
+ b64table[((((data[1] & 0x0f) << 2) & 0xff) | (data[2] >> 6))];
+ result[3] = b64table[(((data[2] << 2) & 0xff) >> 2)];
+ break;
+ case 2:
+ result[0] = b64table[(data[0] >> 2)];
+ result[1] =
+ b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
+ (data[1] >> 4))];
+ result[2] = b64table[(((data[1] << 4) & 0xff) >> 2)];
+ result[3] = '=';
+ break;
+ case 1:
+ result[0] = b64table[(data[0] >> 2)];
+ result[1] = b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff))];
+ result[2] = '=';
+ result[3] = '=';
+ break;
+ default:
+ return -1;
+ }
+
+ return 4;
+
+}
+
+/* data must be 4 bytes
+ * result should be 3 bytes
+ */
+#define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
+inline static int
+decode (uint8_t * result, const opaque * data)
+{
+ uint8_t a1, a2;
+ int ret = 3;
+
+ a1 = TOASCII (data[0]);
+ a2 = TOASCII (data[1]);
+ if (a1 == 0xff || a2 == 0xff)
+ return -1;
+ result[0] = ((a1 << 2) & 0xff) | ((a2 >> 4) & 0xff);
+
+ a1 = a2;
+ a2 = TOASCII (data[2]);
+ if (a2 == 0xff)
+ return -1;
+ result[1] = ((a1 << 4) & 0xff) | ((a2 >> 2) & 0xff);
+
+ a1 = a2;
+ a2 = TOASCII (data[3]);
+ if (a2 == 0xff)
+ return -1;
+ result[2] = ((a1 << 6) & 0xff) | (a2 & 0xff);
+
+ if (data[2] == '=')
+ ret--;
+
+ if (data[3] == '=')
+ ret--;
+ return ret;
+}
+
+/* encodes data and puts the result into result (locally allocated)
+ * The result_size (including the null terminator) is the return value.
+ */
+int
+MHD__gnutls_fbase64_encode (const char *msg, const uint8_t * data,
+ int data_size, uint8_t ** result)
+{
+ int i, ret, tmp, j;
+ char tmpres[4];
+ uint8_t *ptr;
+ uint8_t top[80];
+ uint8_t bottom[80];
+ int pos, bytes, top_len, bottom_len;
+ size_t msglen = strlen (msg);
+
+ if (msglen > 50)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_ENCODING_ERROR;
+ }
+
+ memset (bottom, 0, sizeof (bottom));
+ memset (top, 0, sizeof (top));
+
+ strcat ((char *) top, "-----BEGIN "); /* Flawfinder: ignore */
+ strcat ((char *) top, msg); /* Flawfinder: ignore */
+ strcat ((char *) top, "-----"); /* Flawfinder: ignore */
+
+ strcat ((char *) bottom, "\n-----END "); /* Flawfinder: ignore */
+ strcat ((char *) bottom, msg); /* Flawfinder: ignore */
+ strcat ((char *) bottom, "-----\n"); /* Flawfinder: ignore */
+
+ top_len = strlen ((char *) top);
+ bottom_len = strlen ((char *) bottom);
+
+ ret = B64FSIZE (msglen, data_size);
+
+ (*result) = MHD_gnutls_calloc (1, ret + 1);
+ if ((*result) == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ bytes = pos = 0;
+ INCR (bytes, top_len);
+ pos = top_len;
+
+ strcpy ((char *) *result, (char *) top); /* Flawfinder: ignore */
+
+ for (i = j = 0; i < data_size; i += 3, j += 4)
+ {
+
+ tmp = encode (tmpres, &data[i], data_size - i);
+ if (tmp == -1)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free ((*result));
+ *result = NULL;
+ return GNUTLS_E_BASE64_ENCODING_ERROR;
+ }
+
+ INCR (bytes, 4);
+ ptr = &(*result)[j + pos];
+
+ if ((j) % 64 == 0)
+ {
+ INCR (bytes, 1);
+ pos++;
+ *ptr++ = '\n';
+ }
+ *ptr++ = tmpres[0];
+
+ if ((j + 1) % 64 == 0)
+ {
+ INCR (bytes, 1);
+ pos++;
+ *ptr++ = '\n';
+ }
+ *ptr++ = tmpres[1];
+
+ if ((j + 2) % 64 == 0)
+ {
+ INCR (bytes, 1);
+ pos++;
+ *ptr++ = '\n';
+ }
+ *ptr++ = tmpres[2];
+
+ if ((j + 3) % 64 == 0)
+ {
+ INCR (bytes, 1);
+ pos++;
+ *ptr++ = '\n';
+ }
+ *ptr++ = tmpres[3];
+ }
+
+ INCR (bytes, bottom_len);
+
+ memcpy (&(*result)[bytes - bottom_len], bottom, bottom_len);
+ (*result)[bytes] = 0;
+
+ return ret + 1;
+}
+
+/* decodes data and puts the result into result (locally allocated)
+ * The result_size is the return value
+ */
+int
+MHD__gnutls_base64_decode (const uint8_t * data, size_t data_size,
+ uint8_t ** result)
+{
+ unsigned int i, j;
+ int ret, tmp, est;
+ uint8_t tmpres[3];
+
+ est = ((data_size * 3) / 4) + 1;
+ (*result) = MHD_gnutls_malloc (est);
+ if ((*result) == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ ret = 0;
+ for (i = j = 0; i < data_size; i += 4, j += 3)
+ {
+ tmp = decode (tmpres, &data[i]);
+ if (tmp < 0)
+ {
+ MHD_gnutls_free (*result);
+ *result = NULL;
+ return tmp;
+ }
+ memcpy (&(*result)[j], tmpres, tmp);
+ ret += tmp;
+ }
+ return ret;
+}
+
+/* copies data to result but removes newlines and <CR>
+ * returns the size of the data copied.
+ */
+inline static int
+cpydata (const uint8_t * data, int data_size, uint8_t ** result)
+{
+ int i, j;
+
+ (*result) = MHD_gnutls_malloc (data_size);
+ if (*result == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ for (j = i = 0; i < data_size; i++)
+ {
+ if (data[i] == '\n' || data[i] == '\r')
+ continue;
+ (*result)[j] = data[i];
+ j++;
+ }
+ return j;
+}
+
+/* Searches the given string for ONE PEM encoded certificate, and
+ * stores it in the result.
+ *
+ * The result_size is the return value
+ */
+#define ENDSTR "-----\n"
+#define ENDSTR2 "-----\r"
+int
+MHD__gnutls_fbase64_decode (const char *header, const opaque * data,
+ size_t data_size, uint8_t ** result)
+{
+ int ret;
+ static const char top[] = "-----BEGIN ";
+ static const char bottom[] = "\n-----END ";
+ uint8_t *rdata;
+ int rdata_size;
+ uint8_t *kdata;
+ int kdata_size;
+ char pem_header[128];
+
+ MHD_gtls_str_cpy (pem_header, sizeof (pem_header), top);
+ if (header != NULL)
+ MHD_gtls_str_cat (pem_header, sizeof (pem_header), header);
+
+ rdata = memmem (data, data_size, pem_header, strlen (pem_header));
+
+ if (rdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_debug_log ("Could not find '%s'\n", pem_header);
+ return GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR;
+ }
+
+ data_size -= (unsigned long int) rdata - (unsigned long int) data;
+
+ if (data_size < 4 + strlen (bottom))
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+
+ kdata = memmem (rdata, data_size, ENDSTR, sizeof (ENDSTR) - 1);
+ /* allow CR as well.
+ */
+ if (kdata == NULL)
+ kdata = memmem (rdata, data_size, ENDSTR2, sizeof (ENDSTR2) - 1);
+
+ if (kdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ MHD__gnutls_x509_log ("Could not find '%s'\n", ENDSTR);
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+ data_size -= strlen (ENDSTR);
+ data_size -= (unsigned long int) kdata - (unsigned long int) rdata;
+
+ rdata = kdata + strlen (ENDSTR);
+
+ /* position is now after the ---BEGIN--- headers */
+
+ kdata = memmem (rdata, data_size, bottom, strlen (bottom));
+ if (kdata == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+
+ /* position of kdata is before the ----END--- footer
+ */
+ rdata_size = (unsigned long int) kdata - (unsigned long int) rdata;
+
+ if (rdata_size < 4)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+
+ kdata_size = cpydata (rdata, rdata_size, &kdata);
+
+ if (kdata_size < 0)
+ {
+ MHD_gnutls_assert ();
+ return kdata_size;
+ }
+
+ if (kdata_size < 4)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (kdata);
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+
+ if ((ret = MHD__gnutls_base64_decode (kdata, kdata_size, result)) < 0)
+ {
+ MHD_gnutls_free (kdata);
+ MHD_gnutls_assert ();
+ return GNUTLS_E_BASE64_DECODING_ERROR;
+ }
+ MHD_gnutls_free (kdata);
+
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/tls/x509_b64.h b/lib/libmicrohttpd/src/daemon/https/tls/x509_b64.h
new file mode 100644
index 0000000000..ebb48639f9
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/tls/x509_b64.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD__gnutls_fbase64_encode (const char *msg, const uint8_t * data,
+ int data_size, uint8_t ** result);
+int MHD__gnutls_base64_decode (const uint8_t * data, size_t data_size,
+ uint8_t ** result);
+int MHD__gnutls_fbase64_decode (const char *header, const uint8_t * data,
+ size_t data_size, uint8_t ** result);
+
+#define B64SIZE( data_size) ((data_size%3==0)?((data_size*4)/3):(4+((data_size/3)*4)))
+
+/* The size for B64 encoding + newlines plus header
+ */
+
+#define HEADSIZE( hsize) \
+ sizeof("-----BEGIN ")-1+sizeof("-----")-1+ \
+ sizeof("\n-----END ")-1+sizeof("-----\n")-1+hsize+hsize
+
+#define B64FSIZE( hsize, dsize) \
+ (B64SIZE(dsize) + HEADSIZE(hsize) + /*newlines*/ \
+ B64SIZE(dsize)/64 + (((B64SIZE(dsize) % 64) > 0) ? 1 : 0))
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/Makefile.am b/lib/libmicrohttpd/src/daemon/https/x509/Makefile.am
new file mode 100644
index 0000000000..78844a11e0
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/Makefile.am
@@ -0,0 +1,24 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https \
+ -I$(top_srcdir)/src/daemon/https/minitasn1 \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/tls \
+ -I$(top_srcdir)/src/daemon/https/x509 \
+ @LIBGCRYPT_CFLAGS@
+
+noinst_LTLIBRARIES = libx509.la
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+
+libx509_la_SOURCES = \
+ common.c common.h \
+ extensions.c extensions.h \
+ mpi.c mpi.h \
+ x509_privkey.c privkey.h \
+ x509.c x509.h
+libx509_la_LIBADD = @LIBGCRYPT_LIBS@
+
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/Makefile.in b/lib/libmicrohttpd/src/daemon/https/x509/Makefile.in
new file mode 100644
index 0000000000..3cba9132d6
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/Makefile.in
@@ -0,0 +1,509 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/daemon/https/x509
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libx509_la_DEPENDENCIES =
+am_libx509_la_OBJECTS = common.lo extensions.lo mpi.lo x509_privkey.lo \
+ x509.lo
+libx509_la_OBJECTS = $(am_libx509_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libx509_la_SOURCES)
+DIST_SOURCES = $(libx509_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https \
+ -I$(top_srcdir)/src/daemon/https/minitasn1 \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/tls \
+ -I$(top_srcdir)/src/daemon/https/x509 \
+ @LIBGCRYPT_CFLAGS@
+
+noinst_LTLIBRARIES = libx509.la
+@USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage
+libx509_la_SOURCES = \
+ common.c common.h \
+ extensions.c extensions.h \
+ mpi.c mpi.h \
+ x509_privkey.c privkey.h \
+ x509.c x509.h
+
+libx509_la_LIBADD = @LIBGCRYPT_LIBS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/daemon/https/x509/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/daemon/https/x509/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libx509.la: $(libx509_la_OBJECTS) $(libx509_la_DEPENDENCIES)
+ $(LINK) $(libx509_la_OBJECTS) $(libx509_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extensions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509_privkey.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/common.c b/lib/libmicrohttpd/src/daemon/https/x509/common.c
new file mode 100644
index 0000000000..0c8410d1b3
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/common.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <libtasn1.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <gnutls_str.h>
+#include <gnutls_x509.h>
+#include <gnutls_num.h>
+#include <x509_b64.h>
+#include <common.h>
+#include <mpi.h>
+#include <time.h>
+
+/* A generic export function. Will export the given ASN.1 encoded data
+ * to PEM or DER raw data.
+ */
+int
+MHD__gnutls_x509_export_int (ASN1_TYPE MHD__asn1_data,
+ MHD_gnutls_x509_crt_fmt_t format,
+ char *pem_header,
+ unsigned char *output_data,
+ size_t * output_data_size)
+{
+ int result, len;
+
+ if (format == GNUTLS_X509_FMT_DER)
+ {
+
+ if (output_data == NULL)
+ *output_data_size = 0;
+
+ len = *output_data_size;
+
+ if ((result =
+ MHD__asn1_der_coding (MHD__asn1_data, "", output_data, &len,
+ NULL)) != ASN1_SUCCESS)
+ {
+ *output_data_size = len;
+ if (result == ASN1_MEM_ERROR)
+ {
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ *output_data_size = len;
+
+ }
+ else
+ { /* PEM */
+ opaque *out;
+ MHD_gnutls_datum_t tmp;
+
+ result = MHD__gnutls_x509_der_encode (MHD__asn1_data, "", &tmp, 0);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ result =
+ MHD__gnutls_fbase64_encode (pem_header, tmp.data, tmp.size, &out);
+
+ MHD__gnutls_free_datum (&tmp);
+
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ if (result == 0)
+ { /* oooops */
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ if ((unsigned) result > *output_data_size)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (out);
+ *output_data_size = result;
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ *output_data_size = result;
+
+ if (output_data)
+ {
+ memcpy (output_data, out, result);
+
+ /* do not include the null character into output size.
+ */
+ *output_data_size = result - 1;
+ }
+ MHD_gnutls_free (out);
+
+ }
+
+ return 0;
+}
+
+/* Decodes an octet string. Leave string_type null for a normal
+ * octet string. Otherwise put something like BMPString, PrintableString
+ * etc.
+ */
+static int
+MHD__gnutls_x509_decode_octet_string (const char *string_type,
+ const opaque * der,
+ size_t der_size,
+ opaque * output, size_t * output_size)
+{
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ int result, tmp_output_size;
+ char strname[64];
+
+ if (string_type == NULL)
+ MHD_gtls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data");
+ else
+ {
+ MHD_gtls_str_cpy (strname, sizeof (strname), "PKIX1.");
+ MHD_gtls_str_cat (strname, sizeof (strname), string_type);
+ }
+
+ if ((result =
+ MHD__asn1_create_element (MHD__gnutls_get_pkix (), strname,
+ &c2)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ result = MHD__asn1_der_decoding (&c2, der, der_size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ tmp_output_size = *output_size;
+ result = MHD__asn1_read_value (c2, "", output, &tmp_output_size);
+ *output_size = tmp_output_size;
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:if (c2)
+ MHD__asn1_delete_structure (&c2);
+
+ return result;
+}
+
+/* Reads a value from an ASN1 tree, and puts the output
+ * in an allocated variable in the given datum.
+ * flags == 0 do nothing with the DER output
+ * flags == 1 parse the DER output as OCTET STRING
+ * flags == 2 the value is a BIT STRING
+ */
+int
+MHD__gnutls_x509_read_value (ASN1_TYPE c,
+ const char *root, MHD_gnutls_datum_t * ret,
+ int flags)
+{
+ int len = 0, result;
+ size_t slen;
+ opaque *tmp = NULL;
+
+ result = MHD__asn1_read_value (c, root, NULL, &len);
+ if (result != ASN1_MEM_ERROR)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ return result;
+ }
+
+ if (flags == 2)
+ len /= 8;
+
+ tmp = MHD_gnutls_malloc (len);
+ if (tmp == NULL)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ result = MHD__asn1_read_value (c, root, tmp, &len);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ if (flags == 2)
+ len /= 8;
+
+ /* Extract the OCTET STRING.
+ */
+
+ if (flags == 1)
+ {
+ slen = len;
+ result =
+ MHD__gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+ len = slen;
+ }
+
+ ret->data = tmp;
+ ret->size = len;
+
+ return 0;
+
+cleanup:MHD_gnutls_free (tmp);
+ return result;
+
+}
+
+/* DER Encodes the src ASN1_TYPE and stores it to
+ * the given datum. If str is non null then the data are encoded as
+ * an OCTET STRING.
+ */
+int
+MHD__gnutls_x509_der_encode (ASN1_TYPE src,
+ const char *src_name, MHD_gnutls_datum_t * res,
+ int str)
+{
+ int size, result;
+ int asize;
+ opaque *data = NULL;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+ size = 0;
+ result = MHD__asn1_der_coding (src, src_name, NULL, &size, NULL);
+ if (result != ASN1_MEM_ERROR)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ /* allocate data for the der
+ */
+
+ if (str)
+ size += 16; /* for later to include the octet tags */
+ asize = size;
+
+ data = MHD_gnutls_malloc (size);
+ if (data == NULL)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ result = MHD__asn1_der_coding (src, src_name, data, &size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ if (str)
+ {
+ if ((result =
+ MHD__asn1_create_element (MHD__gnutls_get_pkix (),
+ "PKIX1.pkcs-7-Data",
+ &c2)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ result = MHD__asn1_write_value (c2, "", data, size);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ result = MHD__asn1_der_coding (c2, "", data, &asize, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ result = MHD_gtls_asn2err (result);
+ goto cleanup;
+ }
+
+ size = asize;
+
+ MHD__asn1_delete_structure (&c2);
+ }
+
+ res->data = data;
+ res->size = size;
+ return 0;
+
+cleanup:MHD_gnutls_free (data);
+ MHD__asn1_delete_structure (&c2);
+ return result;
+
+}
+
+/* Reads and returns the PK algorithm of the given certificate-like
+ * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo".
+ */
+int
+MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src,
+ const char *src_name, unsigned int *bits)
+{
+ int result;
+ opaque *str = NULL;
+ int algo;
+ char oid[64];
+ int len;
+ mpi_t params[MAX_PUBLIC_PARAMS_SIZE];
+ char name[128];
+
+ MHD_gtls_str_cpy (name, sizeof (name), src_name);
+ MHD_gtls_str_cat (name, sizeof (name), ".algorithm.algorithm");
+
+ len = sizeof (oid);
+ result = MHD__asn1_read_value (src, name, oid, &len);
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ algo = MHD_gtls_x509_oid2pk_algorithm (oid);
+
+ if (bits == NULL)
+ {
+ MHD_gnutls_free (str);
+ return algo;
+ }
+
+ /* Now read the parameters' bits
+ */
+ MHD_gtls_str_cpy (name, sizeof (name), src_name);
+ MHD_gtls_str_cat (name, sizeof (name), ".subjectPublicKey");
+
+ len = 0;
+ result = MHD__asn1_read_value (src, name, NULL, &len);
+ if (result != ASN1_MEM_ERROR)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ if (len % 8 != 0)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+
+ len /= 8;
+
+ str = MHD_gnutls_malloc (len);
+ if (str == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ MHD_gtls_str_cpy (name, sizeof (name), src_name);
+ MHD_gtls_str_cat (name, sizeof (name), ".subjectPublicKey");
+
+ result = MHD__asn1_read_value (src, name, str, &len);
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (str);
+ return MHD_gtls_asn2err (result);
+ }
+
+ len /= 8;
+
+ switch (algo)
+ {
+ case MHD_GNUTLS_PK_RSA:
+ {
+ if ((result =
+ MHD__gnutls_x509_read_rsa_params (str, len, params)) < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ bits[0] = MHD__gnutls_mpi_get_nbits (params[0]);
+
+ MHD_gtls_mpi_release (&params[0]);
+ MHD_gtls_mpi_release (&params[1]);
+ }
+ break;
+ default:
+ MHD__gnutls_x509_log
+ ("MHD__gnutls_x509_get_pk_algorithm: unhandled algorithm %d\n", algo);
+ }
+
+ MHD_gnutls_free (str);
+ return algo;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/common.h b/lib/libmicrohttpd/src/daemon/https/x509/common.h
new file mode 100644
index 0000000000..d78c7cc28b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/common.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef COMMON_H
+# define COMMON_H
+
+#include <gnutls.h>
+#include <gnutls_algorithms.h>
+
+#define MAX_STRING_LEN 512
+
+#define GNUTLS_XML_SHOW_ALL 1
+
+#define PEM_CRL "X509 CRL"
+#define PEM_X509_CERT "X509 CERTIFICATE"
+#define PEM_X509_CERT2 "CERTIFICATE"
+#define PEM_PKCS7 "PKCS7"
+#define PEM_PKCS12 "PKCS12"
+
+/* public key algorithm's OIDs
+ */
+#define PK_PKIX1_RSA_OID "1.2.840.113549.1.1.1"
+#define PK_DSA_OID "1.2.840.10040.4.1"
+#define PK_GOST_R3410_94_OID "1.2.643.2.2.20"
+#define PK_GOST_R3410_2001_OID "1.2.643.2.2.19"
+
+/* signature OIDs
+ */
+#define SIG_DSA_SHA1_OID "1.2.840.10040.4.3"
+#define SIG_RSA_MD5_OID "1.2.840.113549.1.1.4"
+#define SIG_RSA_MD2_OID "1.2.840.113549.1.1.2"
+#define SIG_RSA_SHA1_OID "1.2.840.113549.1.1.5"
+#define SIG_RSA_SHA256_OID "1.2.840.113549.1.1.11"
+#define SIG_RSA_SHA384_OID "1.2.840.113549.1.1.12"
+#define SIG_RSA_SHA512_OID "1.2.840.113549.1.1.13"
+#define SIG_RSA_RMD160_OID "1.3.36.3.3.1.2"
+#define SIG_GOST_R3410_94_OID "1.2.643.2.2.4"
+#define SIG_GOST_R3410_2001_OID "1.2.643.2.2.3"
+
+int MHD__gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name,
+ MHD_gnutls_datum_t * res, int str);
+
+int MHD__gnutls_x509_export_int (ASN1_TYPE MHD__asn1_data,
+ MHD_gnutls_x509_crt_fmt_t format,
+ char *pem_header, unsigned char *output_data,
+ size_t * output_data_size);
+
+int MHD__gnutls_x509_read_value (ASN1_TYPE c, const char *root,
+ MHD_gnutls_datum_t * ret, int str);
+
+int MHD__gnutls_x509_decode_and_read_attribute (ASN1_TYPE MHD__asn1_struct,
+ const char *where, char *oid,
+ int oid_size,
+ MHD_gnutls_datum_t * value,
+ int multi, int octet);
+
+int MHD__gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name,
+ unsigned int *bits);
+
+int MHD__gnutls_asn1_copy_node (ASN1_TYPE * dst, const char *dst_name,
+ ASN1_TYPE src, const char *src_name);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/extensions.c b/lib/libmicrohttpd/src/daemon/https/x509/extensions.c
new file mode 100644
index 0000000000..82fddc5d78
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/extensions.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that relate to the X.509 extension parsing.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_global.h>
+#include <mpi.h>
+#include <libtasn1.h>
+#include <common.h>
+#include <x509.h>
+#include <extensions.h>
+#include <gnutls_datum.h>
+
+/* This function will attempt to return the requested extension found in
+ * the given X509v3 certificate. The return value is allocated and stored into
+ * ret.
+ *
+ * Critical will be either 0 or 1.
+ *
+ * If the extension does not exist, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
+ * be returned.
+ */
+int
+MHD__gnutls_x509_crt_get_extension (MHD_gnutls_x509_crt_t cert,
+ const char *extension_id, int indx,
+ MHD_gnutls_datum_t * ret,
+ unsigned int *_critical)
+{
+ int k, result, len;
+ char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
+ char str[1024];
+ char str_critical[10];
+ int critical = 0;
+ char extnID[128];
+ MHD_gnutls_datum_t value;
+ int indx_counter = 0;
+
+ ret->data = NULL;
+ ret->size = 0;
+
+ k = 0;
+ do
+ {
+ k++;
+
+ snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u", k);
+
+ len = sizeof (str) - 1;
+ result = MHD__asn1_read_value (cert->cert, name, str, &len);
+
+ /* move to next
+ */
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ {
+ break;
+ }
+
+ do
+ {
+
+ MHD_gtls_str_cpy (name2, sizeof (name2), name);
+ MHD_gtls_str_cat (name2, sizeof (name2), ".extnID");
+
+ len = sizeof (extnID) - 1;
+ result = MHD__asn1_read_value (cert->cert, name2, extnID, &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ {
+ MHD_gnutls_assert ();
+ break;
+ }
+ else if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ /* Handle Extension
+ */
+ if (strcmp (extnID, extension_id) == 0 && indx == indx_counter++)
+ {
+ /* extension was found
+ */
+
+ /* read the critical status.
+ */
+ MHD_gtls_str_cpy (name2, sizeof (name2), name);
+ MHD_gtls_str_cat (name2, sizeof (name2), ".critical");
+
+ len = sizeof (str_critical);
+ result =
+ MHD__asn1_read_value (cert->cert, name2, str_critical, &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ {
+ MHD_gnutls_assert ();
+ break;
+ }
+ else if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ if (str_critical[0] == 'T')
+ critical = 1;
+ else
+ critical = 0;
+
+ /* read the value.
+ */
+ MHD_gtls_str_cpy (name2, sizeof (name2), name);
+ MHD_gtls_str_cat (name2, sizeof (name2), ".extnValue");
+
+ result =
+ MHD__gnutls_x509_read_value (cert->cert, name2, &value, 0);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ ret->data = value.data;
+ ret->size = value.size;
+
+ if (_critical)
+ *_critical = critical;
+
+ return 0;
+ }
+
+
+ }
+ while (0);
+ }
+ while (1);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ {
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+ else
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+}
+
+/* Here we only extract the KeyUsage field, from the DER encoded
+ * extension.
+ */
+int
+MHD__gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage,
+ opaque * extnValue, int extnValueLen)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ int len, result;
+ uint8_t str[2];
+
+ str[0] = str[1] = 0;
+ *keyUsage = 0;
+
+ if ((result = MHD__asn1_create_element
+ (MHD__gnutls_get_pkix (), "PKIX1.KeyUsage", &ext)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ result = MHD__asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ MHD__asn1_delete_structure (&ext);
+ return MHD_gtls_asn2err (result);
+ }
+
+ len = sizeof (str);
+ result = MHD__asn1_read_value (ext, "", str, &len);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ MHD__asn1_delete_structure (&ext);
+ return 0;
+ }
+
+ *keyUsage = str[0] | (str[1] << 8);
+
+ MHD__asn1_delete_structure (&ext);
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/extensions.h b/lib/libmicrohttpd/src/daemon/https/x509/extensions.h
new file mode 100644
index 0000000000..5a945cb15b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/extensions.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+int MHD__gnutls_x509_crt_get_extension (MHD_gnutls_x509_crt_t cert,
+ const char *extension_id, int indx,
+ MHD_gnutls_datum_t * ret,
+ unsigned int *critical);
+
+int MHD__gnutls_x509_crt_get_extension_oid (MHD_gnutls_x509_crt_t cert,
+ int indx, void *ret,
+ size_t * ret_size);
+int MHD__gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage,
+ opaque * extnValue,
+ int extnValueLen);
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/mpi.c b/lib/libmicrohttpd/src/daemon/https/x509/mpi.c
new file mode 100644
index 0000000000..4a54070204
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/mpi.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_global.h>
+#include <libtasn1.h>
+#include <gnutls_datum.h>
+#include "common.h"
+#include "x509.h"
+#include <gnutls_num.h>
+#include "mpi.h"
+
+/*
+ * some x509 certificate parsing functions that relate to MPI parameter
+ * extraction. This reads the BIT STRING subjectPublicKey.
+ * Returns 2 parameters (m,e).
+ */
+int
+MHD__gnutls_x509_read_rsa_params (opaque * der, int dersize, mpi_t * params)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+ if ((result =
+ MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
+ "GNUTLS.RSAPublicKey",
+ &spk)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ result = MHD__asn1_der_decoding (&spk, der, dersize, NULL);
+
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ MHD__asn1_delete_structure (&spk);
+ return MHD_gtls_asn2err (result);
+ }
+
+ if ((result = MHD__gnutls_x509_read_int (spk, "modulus", &params[0])) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD__asn1_delete_structure (&spk);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ if ((result =
+ MHD__gnutls_x509_read_int (spk, "publicExponent", &params[1])) < 0)
+ {
+ MHD_gnutls_assert ();
+ MHD_gtls_mpi_release (&params[0]);
+ MHD__asn1_delete_structure (&spk);
+ return GNUTLS_E_ASN1_GENERIC_ERROR;
+ }
+
+ MHD__asn1_delete_structure (&spk);
+
+ return 0;
+
+}
+
+
+/* Extracts DSA and RSA parameters from a certificate.
+ */
+int
+MHD__gnutls_x509_crt_get_mpis (MHD_gnutls_x509_crt_t cert,
+ mpi_t * params, int *params_size)
+{
+ int result;
+ int pk_algorithm;
+ MHD_gnutls_datum_t tmp = { NULL, 0 };
+
+ /* Read the algorithm's OID
+ */
+ pk_algorithm = MHD_gnutls_x509_crt_get_pk_algorithm (cert, NULL);
+
+ /* Read the algorithm's parameters
+ */
+ result
+ = MHD__gnutls_x509_read_value (cert->cert,
+ "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
+ &tmp, 2);
+
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ switch (pk_algorithm)
+ {
+ case MHD_GNUTLS_PK_RSA:
+ /* params[0] is the modulus,
+ * params[1] is the exponent
+ */
+ if (*params_size < RSA_PUBLIC_PARAMS)
+ {
+ MHD_gnutls_assert ();
+ /* internal error. Increase the mpi_ts in params */
+ result = GNUTLS_E_INTERNAL_ERROR;
+ goto error;
+ }
+
+ if ((result =
+ MHD__gnutls_x509_read_rsa_params (tmp.data, tmp.size, params)) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+ *params_size = RSA_PUBLIC_PARAMS;
+
+ break;
+ default:
+ /* other types like DH
+ * currently not supported
+ */
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_X509_CERTIFICATE_ERROR;
+ goto error;
+ }
+
+ result = 0;
+
+error:MHD__gnutls_free_datum (&tmp);
+ return result;
+}
+
+/*
+ * some x509 certificate functions that relate to MPI parameter
+ * setting. This writes the BIT STRING subjectPublicKey.
+ * Needs 2 parameters (m,e).
+ *
+ * Allocates the space used to store the DER data.
+ */
+int
+MHD__gnutls_x509_write_rsa_params (mpi_t * params,
+ int params_size, MHD_gnutls_datum_t * der)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+ der->data = NULL;
+ der->size = 0;
+
+ if (params_size < 2)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ if ((result =
+ MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
+ "GNUTLS.RSAPublicKey",
+ &spk)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ result = MHD__gnutls_x509_write_int (spk, "modulus", params[0], 0);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ result = MHD__gnutls_x509_write_int (spk, "publicExponent", params[1], 0);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ result = MHD__gnutls_x509_der_encode (spk, "", der, 0);
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ MHD__asn1_delete_structure (&spk);
+ return 0;
+
+cleanup:MHD__asn1_delete_structure (&spk);
+
+ return result;
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/mpi.h b/lib/libmicrohttpd/src/daemon/https/x509/mpi.h
new file mode 100644
index 0000000000..ff9fdc1912
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/mpi.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include "x509.h"
+
+int MHD__gnutls_x509_crt_get_mpis (MHD_gnutls_x509_crt_t cert,
+ mpi_t * params, int *params_size);
+int MHD__gnutls_x509_read_rsa_params (opaque * der, int dersize,
+ mpi_t * params);
+int MHD__gnutls_x509_write_rsa_params (mpi_t * params, int params_size,
+ MHD_gnutls_datum_t * der);
+int MHD__gnutls_x509_read_int (ASN1_TYPE node, const char *value,
+ mpi_t * ret_mpi);
+int MHD__gnutls_x509_write_int (ASN1_TYPE node, const char *value, mpi_t mpi,
+ int lz);
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/privkey.h b/lib/libmicrohttpd/src/daemon/https/x509/privkey.h
new file mode 100644
index 0000000000..37c6870350
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/privkey.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include "x509.h"
+
+ASN1_TYPE MHD__gnutls_privkey_decode_pkcs1_rsa_key (const MHD_gnutls_datum_t *
+ raw_key,
+ MHD_gnutls_x509_privkey_t
+ pkey);
+
+int MHD__gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params);
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/x509.c b/lib/libmicrohttpd/src/daemon/https/x509/x509.c
new file mode 100644
index 0000000000..ff0d21e816
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/x509.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ * Author: Nikos Mavrogiannopoulos, Simon Josefsson, Howard Chu
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions on X.509 Certificate parsing
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <common.h>
+#include <gnutls_x509.h>
+#include <x509_b64.h>
+#include <x509.h>
+#include <extensions.h>
+#include <libtasn1.h>
+#include <mpi.h>
+#include <privkey.h>
+
+/**
+ * MHD_gnutls_x509_crt_init - This function initializes a MHD_gnutls_x509_crt_t structure
+ * @cert: The structure to be initialized
+ *
+ * This function will initialize an X.509 certificate structure.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+MHD_gnutls_x509_crt_init (MHD_gnutls_x509_crt_t * cert)
+{
+ MHD_gnutls_x509_crt_t tmp =
+ MHD_gnutls_calloc (1, sizeof (MHD_gnutls_x509_crt_int));
+ int result;
+
+ if (!tmp)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
+ "PKIX1.Certificate", &tmp->cert);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ MHD_gnutls_free (tmp);
+ return MHD_gtls_asn2err (result);
+ }
+
+ *cert = tmp;
+
+ return 0; /* success */
+}
+
+/**
+ * MHD_gnutls_x509_crt_deinit - This function deinitializes memory used by a MHD_gnutls_x509_crt_t structure
+ * @cert: The structure to be initialized
+ *
+ * This function will deinitialize a CRL structure.
+ *
+ **/
+void
+MHD_gnutls_x509_crt_deinit (MHD_gnutls_x509_crt_t cert)
+{
+ if (!cert)
+ return;
+
+ if (cert->cert)
+ MHD__asn1_delete_structure (&cert->cert);
+
+ MHD_gnutls_free (cert);
+}
+
+/**
+ * MHD_gnutls_x509_crt_import - This function will import a DER or PEM encoded Certificate
+ * @cert: The structure to store the parsed certificate.
+ * @data: The DER or PEM encoded certificate.
+ * @format: One of DER or PEM
+ *
+ * This function will convert the given DER or PEM encoded Certificate
+ * to the native MHD_gnutls_x509_crt_t format. The output will be stored in @cert.
+ *
+ * If the Certificate is PEM encoded it should have a header of "X509 CERTIFICATE", or
+ * "CERTIFICATE".
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+MHD_gnutls_x509_crt_import (MHD_gnutls_x509_crt_t cert,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_x509_crt_fmt_t format)
+{
+ int result = 0, need_free = 0;
+ MHD_gnutls_datum_t _data;
+ opaque *signature = NULL;
+
+ if (cert == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ _data.data = data->data;
+ _data.size = data->size;
+
+ /* If the Certificate is in PEM format then decode it
+ */
+ if (format == GNUTLS_X509_FMT_PEM)
+ {
+ opaque *out;
+
+ /* Try the first header */
+ result =
+ MHD__gnutls_fbase64_decode (PEM_X509_CERT2, data->data, data->size,
+ &out);
+
+ if (result <= 0)
+ {
+ /* try for the second header */
+ result = MHD__gnutls_fbase64_decode (PEM_X509_CERT, data->data,
+ data->size, &out);
+
+ if (result <= 0)
+ {
+ if (result == 0)
+ result = GNUTLS_E_INTERNAL_ERROR;
+ MHD_gnutls_assert ();
+ return result;
+ }
+ }
+
+ _data.data = out;
+ _data.size = result;
+
+ need_free = 1;
+ }
+
+ result = MHD__asn1_der_decoding (&cert->cert, _data.data, _data.size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ result = MHD_gtls_asn2err (result);
+ MHD_gnutls_assert ();
+ goto cleanup;
+ }
+
+ /* Since we do not want to disable any extension
+ */
+ cert->use_extensions = 1;
+ if (need_free)
+ MHD__gnutls_free_datum (&_data);
+
+ return 0;
+
+cleanup:MHD_gnutls_free (signature);
+ if (need_free)
+ MHD__gnutls_free_datum (&_data);
+ return result;
+}
+
+/**
+ * MHD_gnutls_x509_crt_get_version - This function returns the Certificate's version number
+ * @cert: should contain a MHD_gnutls_x509_crt_t structure
+ *
+ * This function will return the version of the specified Certificate.
+ *
+ * Returns a negative value on error.
+ *
+ **/
+int
+MHD_gnutls_x509_crt_get_version (MHD_gnutls_x509_crt_t cert)
+{
+ opaque version[5];
+ int len, result;
+
+ if (cert == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ len = sizeof (version);
+ if ((result =
+ MHD__asn1_read_value (cert->cert, "tbsCertificate.version", version,
+ &len)) != ASN1_SUCCESS)
+ {
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ return 1; /* the DEFAULT version */
+ MHD_gnutls_assert ();
+ return MHD_gtls_asn2err (result);
+ }
+
+ return (int) version[0] + 1;
+}
+
+/**
+ * MHD_gnutls_x509_crt_get_pk_algorithm - This function returns the certificate's PublicKey algorithm
+ * @cert: should contain a MHD_gnutls_x509_crt_t structure
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of an X.509
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public
+ * exponent.
+ *
+ * Returns a member of the enum MHD_GNUTLS_PublicKeyAlgorithm enumeration on success,
+ * or a negative value on error.
+ *
+ **/
+int
+MHD_gnutls_x509_crt_get_pk_algorithm (MHD_gnutls_x509_crt_t cert,
+ unsigned int *bits)
+{
+ int result;
+
+ if (cert == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ result = MHD__gnutls_x509_get_pk_algorithm (cert->cert,
+ "tbsCertificate.subjectPublicKeyInfo",
+ bits);
+
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ return result;
+
+}
+
+inline static int
+is_type_printable (int type)
+{
+ if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME || type
+ == GNUTLS_SAN_URI)
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * MHD_gnutls_x509_crt_get_key_usage - This function returns the certificate's key usage
+ * @cert: should contain a MHD_gnutls_x509_crt_t structure
+ * @key_usage: where the key usage bits will be stored
+ * @critical: will be non zero if the extension is marked as critical
+ *
+ * This function will return certificate's key usage, by reading the
+ * keyUsage X.509 extension (2.5.29.15). The key usage value will ORed values of the:
+ * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_NON_REPUDIATION,
+ * GNUTLS_KEY_KEY_ENCIPHERMENT, GNUTLS_KEY_DATA_ENCIPHERMENT,
+ * GNUTLS_KEY_KEY_AGREEMENT, GNUTLS_KEY_KEY_CERT_SIGN,
+ * GNUTLS_KEY_CRL_SIGN, GNUTLS_KEY_ENCIPHER_ONLY,
+ * GNUTLS_KEY_DECIPHER_ONLY.
+ *
+ * A negative value may be returned in case of parsing error.
+ * If the certificate does not contain the keyUsage extension
+ * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
+ *
+ **/
+int
+MHD_gnutls_x509_crt_get_key_usage (MHD_gnutls_x509_crt_t cert,
+ unsigned int *key_usage,
+ unsigned int *critical)
+{
+ int result;
+ MHD_gnutls_datum_t keyUsage;
+ uint16_t _usage;
+
+ if (cert == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if ((result =
+ MHD__gnutls_x509_crt_get_extension (cert, "2.5.29.15", 0, &keyUsage,
+ critical)) < 0)
+ {
+ return result;
+ }
+
+ if (keyUsage.size == 0 || keyUsage.data == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ result = MHD__gnutls_x509_ext_extract_keyUsage (&_usage, keyUsage.data,
+ keyUsage.size);
+ MHD__gnutls_free_datum (&keyUsage);
+
+ *key_usage = _usage;
+
+ if (result < 0)
+ {
+ MHD_gnutls_assert ();
+ return result;
+ }
+
+ return 0;
+}
+
+
+/**
+ * MHD_gnutls_x509_crt_export - This function will export the certificate
+ * @cert: Holds the certificate
+ * @format: the format of output params. One of PEM or DER.
+ * @output_data: will contain a certificate PEM or DER encoded
+ * @output_data_size: holds the size of output_data (and will be
+ * replaced by the actual size of parameters)
+ *
+ * This function will export the certificate to DER or PEM format.
+ *
+ * If the buffer provided is not long enough to hold the output, then
+ * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
+ * be returned.
+ *
+ * If the structure is PEM encoded, it will have a header
+ * of "BEGIN CERTIFICATE".
+ *
+ * Return value: In case of failure a negative value will be
+ * returned, and 0 on success.
+ **/
+int
+MHD_gnutls_x509_crt_export (MHD_gnutls_x509_crt_t cert,
+ MHD_gnutls_x509_crt_fmt_t format,
+ void *output_data, size_t * output_data_size)
+{
+ if (cert == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return MHD__gnutls_x509_export_int (cert->cert, format, "CERTIFICATE",
+ output_data, output_data_size);
+}
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/x509.h b/lib/libmicrohttpd/src/daemon/https/x509/x509.h
new file mode 100644
index 0000000000..9a01d95b93
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/x509.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef X509_H
+#define X509_H
+
+#ifndef MIN
+#define MIN(X,Y) ((X) > (Y) ? (Y) : (X));
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <gnutls.h>
+#include <libtasn1.h>
+#include "gnutls_mpi.h"
+
+/* Some OIDs usually found in Distinguished names, or
+ * in Subject Directory Attribute extensions.
+ */
+#define GNUTLS_OID_X520_COUNTRY_NAME "2.5.4.6"
+#define GNUTLS_OID_X520_ORGANIZATION_NAME "2.5.4.10"
+#define GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME "2.5.4.11"
+#define GNUTLS_OID_X520_COMMON_NAME "2.5.4.3"
+#define GNUTLS_OID_X520_LOCALITY_NAME "2.5.4.7"
+#define GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME "2.5.4.8"
+
+#define GNUTLS_OID_X520_INITIALS "2.5.4.43"
+#define GNUTLS_OID_X520_GENERATION_QUALIFIER "2.5.4.44"
+#define GNUTLS_OID_X520_SURNAME "2.5.4.4"
+#define GNUTLS_OID_X520_GIVEN_NAME "2.5.4.42"
+#define GNUTLS_OID_X520_TITLE "2.5.4.12"
+#define GNUTLS_OID_X520_DN_QUALIFIER "2.5.4.46"
+#define GNUTLS_OID_X520_PSEUDONYM "2.5.4.65"
+
+#define GNUTLS_OID_LDAP_DC "0.9.2342.19200300.100.1.25"
+#define GNUTLS_OID_LDAP_UID "0.9.2342.19200300.100.1.1"
+
+/* The following should not be included in DN.
+ */
+#define GNUTLS_OID_PKCS9_EMAIL "1.2.840.113549.1.9.1"
+
+#define GNUTLS_OID_PKIX_DATE_OF_BIRTH "1.3.6.1.5.5.7.9.1"
+#define GNUTLS_OID_PKIX_PLACE_OF_BIRTH "1.3.6.1.5.5.7.9.2"
+#define GNUTLS_OID_PKIX_GENDER "1.3.6.1.5.5.7.9.3"
+#define GNUTLS_OID_PKIX_COUNTRY_OF_CITIZENSHIP "1.3.6.1.5.5.7.9.4"
+#define GNUTLS_OID_PKIX_COUNTRY_OF_RESIDENCE "1.3.6.1.5.5.7.9.5"
+
+/* Key purpose Object Identifiers.
+ */
+#define GNUTLS_KP_TLS_WWW_SERVER "1.3.6.1.5.5.7.3.1"
+#define GNUTLS_KP_TLS_WWW_CLIENT "1.3.6.1.5.5.7.3.2"
+#define GNUTLS_KP_CODE_SIGNING "1.3.6.1.5.5.7.3.3"
+#define GNUTLS_KP_EMAIL_PROTECTION "1.3.6.1.5.5.7.3.4"
+#define GNUTLS_KP_TIME_STAMPING "1.3.6.1.5.5.7.3.8"
+#define GNUTLS_KP_OCSP_SIGNING "1.3.6.1.5.5.7.3.9"
+#define GNUTLS_KP_ANY "2.5.29.37.0"
+
+/* Certificate handling functions.
+ */
+ typedef enum MHD_gnutls_certificate_import_flags
+ {
+ /* Fail if the certificates in the buffer are more than the space
+ * allocated for certificates. The error code will be
+ * GNUTLS_E_SHORT_MEMORY_BUFFER.
+ */
+ GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED = 1
+ } MHD_gnutls_certificate_import_flags;
+
+ int MHD_gnutls_x509_crt_init (MHD_gnutls_x509_crt_t * cert);
+ void MHD_gnutls_x509_crt_deinit (MHD_gnutls_x509_crt_t cert);
+ int MHD_gnutls_x509_crt_import (MHD_gnutls_x509_crt_t cert,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_x509_crt_fmt_t format);
+ int MHD_gnutls_x509_crt_export (MHD_gnutls_x509_crt_t cert,
+ MHD_gnutls_x509_crt_fmt_t format,
+ void *output_data,
+ size_t * output_data_size);
+ int MHD_gnutls_x509_crt_get_version (MHD_gnutls_x509_crt_t cert);
+
+#define GNUTLS_CRL_REASON_UNUSED 128
+#define GNUTLS_CRL_REASON_KEY_COMPROMISE 64
+#define GNUTLS_CRL_REASON_CA_COMPROMISE 32
+#define GNUTLS_CRL_REASON_AFFILIATION_CHANGED 16
+#define GNUTLS_CRL_REASON_SUPERSEEDED 8
+#define GNUTLS_CRL_REASON_CESSATION_OF_OPERATION 4
+#define GNUTLS_CRL_REASON_CERTIFICATE_HOLD 2
+#define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1
+#define GNUTLS_CRL_REASON_AA_COMPROMISE 32768
+
+ int MHD_gnutls_x509_crt_get_pk_algorithm (MHD_gnutls_x509_crt_t cert,
+ unsigned int *bits);
+ int MHD_gnutls_x509_crt_get_ca_status (MHD_gnutls_x509_crt_t cert,
+ unsigned int *critical);
+/* The key_usage flags are defined in gnutls.h. They are the
+ * GNUTLS_KEY_* definitions.
+ */
+ int MHD_gnutls_x509_crt_get_key_usage (MHD_gnutls_x509_crt_t cert,
+ unsigned int *key_usage,
+ unsigned int *critical);
+ int MHD_gnutls_x509_crt_set_key_usage (MHD_gnutls_x509_crt_t crt,
+ unsigned int usage);
+
+/* Read extensions by sequence number. */
+ int MHD_gnutls_x509_crt_set_extension_by_oid (MHD_gnutls_x509_crt_t crt,
+ const char *oid,
+ const void *buf,
+ size_t sizeof_buf,
+ unsigned int critical);
+
+/* X.509 Certificate writing.
+ */
+ int MHD_gnutls_x509_crt_set_dn_by_oid (MHD_gnutls_x509_crt_t crt,
+ const char *oid,
+ unsigned int raw_flag,
+ const void *name,
+ unsigned int sizeof_name);
+ int MHD_gnutls_x509_crt_set_issuer_dn_by_oid (MHD_gnutls_x509_crt_t crt,
+ const char *oid,
+ unsigned int raw_flag,
+ const void *name,
+ unsigned int sizeof_name);
+ int MHD_gnutls_x509_crt_set_version (MHD_gnutls_x509_crt_t crt,
+ unsigned int version);
+ int MHD_gnutls_x509_crt_set_key (MHD_gnutls_x509_crt_t crt,
+ MHD_gnutls_x509_privkey_t key);
+ int MHD_gnutls_x509_crt_set_ca_status (MHD_gnutls_x509_crt_t crt,
+ unsigned int ca);
+ int MHD_gnutls_x509_crt_set_basic_constraints (MHD_gnutls_x509_crt_t crt,
+ unsigned int ca,
+ int pathLenConstraint);
+ int MHD_gnutls_x509_crt_set_subject_alternative_name (MHD_gnutls_x509_crt_t
+ crt,
+ MHD_gnutls_x509_subject_alt_name_t
+ type,
+ const char
+ *data_string);
+ int MHD_gnutls_x509_crt_sign (MHD_gnutls_x509_crt_t crt,
+ MHD_gnutls_x509_crt_t issuer,
+ MHD_gnutls_x509_privkey_t issuer_key);
+ int MHD_gnutls_x509_crt_sign2 (MHD_gnutls_x509_crt_t crt,
+ MHD_gnutls_x509_crt_t issuer,
+ MHD_gnutls_x509_privkey_t issuer_key,
+ enum MHD_GNUTLS_HashAlgorithm,
+ unsigned int flags);
+ int MHD_gnutls_x509_crt_set_serial (MHD_gnutls_x509_crt_t cert,
+ const void *serial, size_t serial_size);
+
+ int MHD_gnutls_x509_crt_set_subject_key_id (MHD_gnutls_x509_crt_t cert,
+ const void *id, size_t id_size);
+
+ int MHD_gnutls_x509_crt_set_proxy_dn (MHD_gnutls_x509_crt_t crt,
+ MHD_gnutls_x509_crt_t eecrt,
+ unsigned int raw_flag,
+ const void *name,
+ unsigned int sizeof_name);
+ int MHD_gnutls_x509_crt_set_proxy (MHD_gnutls_x509_crt_t crt,
+ int pathLenConstraint,
+ const char *policyLanguage,
+ const char *policy,
+ size_t sizeof_policy);
+
+ typedef enum MHD_gnutls_certificate_print_formats
+ {
+ GNUTLS_X509_CRT_FULL,
+ GNUTLS_X509_CRT_ONELINE,
+ GNUTLS_X509_CRT_UNSIGNED_FULL
+ } MHD_gnutls_certificate_print_formats_t;
+
+ int MHD_gnutls_x509_crt_print (MHD_gnutls_x509_crt_t cert,
+ MHD_gnutls_certificate_print_formats_t
+ format, MHD_gnutls_datum_t * out);
+/* Access to internal Certificate fields.
+ */
+
+ typedef void *MHD_gnutls_x509_dn_t;
+
+/* X.509 Certificate verification functions.
+ */
+ typedef enum MHD_gnutls_certificate_verify_flags
+ {
+ /* If set a signer does not have to be a certificate authority. This
+ * flag should normaly be disabled, unless you know what this means.
+ */
+ GNUTLS_VERIFY_DISABLE_CA_SIGN = 1,
+
+ /* Allow only trusted CA certificates that have version 1. This is
+ * safer than GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT, and should be
+ * used instead. That way only signers in your trusted list will be
+ * allowed to have certificates of version 1.
+ */
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT = 2,
+
+ /* If a certificate is not signed by anyone trusted but exists in
+ * the trusted CA list do not treat it as trusted.
+ */
+ GNUTLS_VERIFY_DO_NOT_ALLOW_SAME = 4,
+
+ /* Allow CA certificates that have version 1 (both root and
+ * intermediate). This might be dangerous since those haven't the
+ * basicConstraints extension. Must be used in combination with
+ * GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT.
+ */
+ GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT = 8,
+
+ /* Allow certificates to be signed using the broken MD2 algorithm.
+ */
+ GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2 = 16,
+
+ /* Allow certificates to be signed using the broken MD5 algorithm.
+ */
+ GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 = 32
+ } MHD_gnutls_certificate_verify_flags;
+
+
+/* Flags for the MHD_gnutls_x509_privkey_export_pkcs8() function.
+ */
+ typedef enum MHD_gnutls_pkcs_encrypt_flags_t
+ {
+ GNUTLS_PKCS_PLAIN = 1, /* if set the private key will not
+ * be encrypted.
+ */
+ GNUTLS_PKCS_USE_PKCS12_3DES = 2,
+ GNUTLS_PKCS_USE_PKCS12_ARCFOUR = 4,
+ GNUTLS_PKCS_USE_PKCS12_RC2_40 = 8,
+ GNUTLS_PKCS_USE_PBES2_3DES = 16
+ } MHD_gnutls_pkcs_encrypt_flags_t;
+
+#define GNUTLS_PKCS8_PLAIN GNUTLS_PKCS_PLAIN
+#define GNUTLS_PKCS8_USE_PKCS12_3DES GNUTLS_PKCS_USE_PKCS12_3DES
+#define GNUTLS_PKCS8_USE_PKCS12_ARCFOUR GNUTLS_PKCS_USE_PKCS12_ARCFOUR
+#define GNUTLS_PKCS8_USE_PKCS12_RC2_40 GNUTLS_PKCS_USE_PKCS12_RC2_40
+
+ int MHD_gnutls_x509_privkey_init (MHD_gnutls_x509_privkey_t * key);
+ void MHD_gnutls_x509_privkey_deinit (MHD_gnutls_x509_privkey_t key);
+ int MHD_gnutls_x509_privkey_import (MHD_gnutls_x509_privkey_t key,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_x509_crt_fmt_t format);
+ int MHD_gnutls_x509_privkey_get_key_id (MHD_gnutls_x509_privkey_t key,
+ unsigned int flags,
+ unsigned char *output_data,
+ size_t * output_data_size);
+
+ int MHD_gnutls_x509_privkey_export (MHD_gnutls_x509_privkey_t key,
+ MHD_gnutls_x509_crt_fmt_t format,
+ void *output_data,
+ size_t * output_data_size);
+ int MHD_gnutls_x509_privkey_export_pkcs8 (MHD_gnutls_x509_privkey_t key,
+ MHD_gnutls_x509_crt_fmt_t format,
+ const char *password,
+ unsigned int flags,
+ void *output_data,
+ size_t * output_data_size);
+ int MHD_gnutls_x509_privkey_export_rsa_raw (MHD_gnutls_x509_privkey_t key,
+ MHD_gnutls_datum_t * m,
+ MHD_gnutls_datum_t * e,
+ MHD_gnutls_datum_t * d,
+ MHD_gnutls_datum_t * p,
+ MHD_gnutls_datum_t * q,
+ MHD_gnutls_datum_t * u);
+
+ int MHD_gnutls_x509_privkey_verify_data (MHD_gnutls_x509_privkey_t key,
+ unsigned int flags,
+ const MHD_gnutls_datum_t * data,
+ const MHD_gnutls_datum_t *
+ signature);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define HASH_OID_SHA1 "1.3.14.3.2.26"
+#define HASH_OID_MD5 "1.2.840.113549.2.5"
+#define HASH_OID_MD2 "1.2.840.113549.2.2"
+#define HASH_OID_RMD160 "1.3.36.3.2.1"
+#define HASH_OID_SHA256 "2.16.840.1.101.3.4.2.1"
+#define HASH_OID_SHA384 "2.16.840.1.101.3.4.2.2"
+#define HASH_OID_SHA512 "2.16.840.1.101.3.4.2.3"
+
+typedef struct MHD_gnutls_x509_crt_int
+{
+ ASN1_TYPE cert;
+ int use_extensions;
+} MHD_gnutls_x509_crt_int;
+
+#define MAX_PRIV_PARAMS_SIZE 6 /* ok for RSA and DSA */
+
+/* parameters should not be larger than this limit */
+#define DSA_PRIVATE_PARAMS 5
+#define DSA_PUBLIC_PARAMS 4
+#define RSA_PRIVATE_PARAMS 6
+#define RSA_PUBLIC_PARAMS 2
+
+#if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0
+# error INCREASE MAX_PRIV_PARAMS
+#endif
+
+#if MAX_PRIV_PARAMS_SIZE - DSA_PRIVATE_PARAMS < 0
+# error INCREASE MAX_PRIV_PARAMS
+#endif
+
+typedef struct MHD_gtls_x509_privkey_int
+{
+ mpi_t params[MAX_PRIV_PARAMS_SIZE]; /* the size of params depends on the public
+ * key algorithm
+ */
+ /*
+ * RSA: [0] is modulus
+ * [1] is public exponent
+ * [2] is private exponent
+ * [3] is prime1 (p)
+ * [4] is prime2 (q)
+ * [5] is coefficient (u == inverse of p mod q)
+ * note that other packages used inverse of q mod p,
+ * so we need to perform conversions.
+ * DSA: [0] is p
+ * [1] is q
+ * [2] is g
+ * [3] is y (public key)
+ * [4] is x (private key)
+ */
+ int params_size; /* holds the number of params */
+
+ enum MHD_GNUTLS_PublicKeyAlgorithm pk_algorithm;
+
+ int crippled; /* The crippled keys will not use the ASN1_TYPE key.
+ * The encoding will only be performed at the export
+ * phase, to optimize copying etc. Cannot be used with
+ * the exported API (used internally only).
+ */
+ ASN1_TYPE key;
+} MHD_gnutls_x509_privkey_int;
+
+int MHD_gnutls_x509_crt_get_pk_algorithm (MHD_gnutls_x509_crt_t cert,
+ unsigned int *bits);
+
+int MHD_gnutls_x509_crt_get_serial (MHD_gnutls_x509_crt_t cert,
+ void *result, size_t * result_size);
+
+int MHD_gnutls_x509_crt_init (MHD_gnutls_x509_crt_t * cert);
+void MHD_gnutls_x509_crt_deinit (MHD_gnutls_x509_crt_t cert);
+int MHD_gnutls_x509_crt_import (MHD_gnutls_x509_crt_t cert,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_x509_crt_fmt_t format);
+int MHD_gnutls_x509_crt_export (MHD_gnutls_x509_crt_t cert,
+ MHD_gnutls_x509_crt_fmt_t format,
+ void *output_data, size_t * output_data_size);
+
+int MHD_gnutls_x509_crt_get_key_usage (MHD_gnutls_x509_crt_t cert,
+ unsigned int *key_usage,
+ unsigned int *critical);
+int MHD_gnutls_x509_crt_get_version (MHD_gnutls_x509_crt_t cert);
+
+int MHD_gnutls_x509_privkey_init (MHD_gnutls_x509_privkey_t * key);
+void MHD_gnutls_x509_privkey_deinit (MHD_gnutls_x509_privkey_t key);
+
+int MHD_gnutls_x509_privkey_generate (MHD_gnutls_x509_privkey_t key,
+ enum MHD_GNUTLS_PublicKeyAlgorithm algo,
+ unsigned int bits, unsigned int flags);
+
+int MHD_gnutls_x509_privkey_import (MHD_gnutls_x509_privkey_t key,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_x509_crt_fmt_t format);
+int MHD_gnutls_x509_privkey_export_rsa_raw (MHD_gnutls_x509_privkey_t key,
+ MHD_gnutls_datum_t * m,
+ MHD_gnutls_datum_t * e,
+ MHD_gnutls_datum_t * d,
+ MHD_gnutls_datum_t * p,
+ MHD_gnutls_datum_t * q,
+ MHD_gnutls_datum_t * u);
+int MHD_gnutls_x509_privkey_export (MHD_gnutls_x509_privkey_t key,
+ MHD_gnutls_x509_crt_fmt_t format,
+ void *output_data,
+ size_t * output_data_size);
+
+#define GNUTLS_CRL_REASON_UNUSED 128
+#define GNUTLS_CRL_REASON_KEY_COMPROMISE 64
+#define GNUTLS_CRL_REASON_CA_COMPROMISE 32
+#define GNUTLS_CRL_REASON_AFFILIATION_CHANGED 16
+#define GNUTLS_CRL_REASON_SUPERSEEDED 8
+#define GNUTLS_CRL_REASON_CESSATION_OF_OPERATION 4
+#define GNUTLS_CRL_REASON_CERTIFICATE_HOLD 2
+#define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1
+#define GNUTLS_CRL_REASON_AA_COMPROMISE 32768
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/https/x509/x509_privkey.c b/lib/libmicrohttpd/src/daemon/https/x509/x509_privkey.c
new file mode 100644
index 0000000000..e22da040b0
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/https/x509/x509_privkey.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <gnutls_rsa_export.h>
+#include <gnutls_sig.h>
+#include <common.h>
+#include <gnutls_x509.h>
+#include <x509_b64.h>
+#include <x509.h>
+#include <mpi.h>
+#include <extensions.h>
+
+/* remove this when libgcrypt can handle the PKCS #1 coefficients from
+ * rsa keys
+ */
+#define CALC_COEFF 1
+
+/**
+ * MHD_gnutls_x509_privkey_init - This function initializes a MHD_gnutls_crl structure
+ * @key: The structure to be initialized
+ *
+ * This function will initialize an private key structure.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+MHD_gnutls_x509_privkey_init (MHD_gnutls_x509_privkey_t * key)
+{
+ *key = MHD_gnutls_calloc (1, sizeof (MHD_gnutls_x509_privkey_int));
+
+ if (*key)
+ {
+ (*key)->key = ASN1_TYPE_EMPTY;
+ (*key)->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
+ return 0; /* success */
+ }
+
+ return GNUTLS_E_MEMORY_ERROR;
+}
+
+/**
+ * MHD_gnutls_x509_privkey_deinit - This function deinitializes memory used by a MHD_gnutls_x509_privkey_t structure
+ * @key: The structure to be initialized
+ *
+ * This function will deinitialize a private key structure.
+ *
+ **/
+void
+MHD_gnutls_x509_privkey_deinit (MHD_gnutls_x509_privkey_t key)
+{
+ int i;
+
+ if (!key)
+ return;
+
+ for (i = 0; i < key->params_size; i++)
+ {
+ MHD_gtls_mpi_release (&key->params[i]);
+ }
+
+ MHD__asn1_delete_structure (&key->key);
+ MHD_gnutls_free (key);
+}
+
+
+/* Converts an RSA PKCS#1 key to
+ * an internal structure (MHD_gnutls_private_key)
+ */
+ASN1_TYPE
+MHD__gnutls_privkey_decode_pkcs1_rsa_key (const MHD_gnutls_datum_t * raw_key,
+ MHD_gnutls_x509_privkey_t pkey)
+{
+ int result;
+ ASN1_TYPE pkey_asn;
+
+ if ((result = MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
+ "GNUTLS.RSAPrivateKey",
+ &pkey_asn)) != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ return NULL;
+ }
+
+ if ((sizeof (pkey->params) / sizeof (mpi_t)) < RSA_PRIVATE_PARAMS)
+ {
+ MHD_gnutls_assert ();
+ /* internal error. Increase the mpi_ts in params */
+ return NULL;
+ }
+
+ result =
+ MHD__asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ if ((result =
+ MHD__gnutls_x509_read_int (pkey_asn, "modulus", &pkey->params[0])) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ if ((result = MHD__gnutls_x509_read_int (pkey_asn, "publicExponent",
+ &pkey->params[1])) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ if ((result = MHD__gnutls_x509_read_int (pkey_asn, "privateExponent",
+ &pkey->params[2])) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ if ((result =
+ MHD__gnutls_x509_read_int (pkey_asn, "prime1", &pkey->params[3])) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ if ((result =
+ MHD__gnutls_x509_read_int (pkey_asn, "prime2", &pkey->params[4])) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+#ifdef CALC_COEFF
+ /* Calculate the coefficient. This is because the gcrypt
+ * library is uses the p,q in the reverse order.
+ */
+ pkey->params[5] =
+ MHD__gnutls_mpi_snew (MHD__gnutls_mpi_get_nbits (pkey->params[0]));
+
+ if (pkey->params[5] == NULL)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+
+ MHD__gnutls_mpi_invm (pkey->params[5], pkey->params[3], pkey->params[4]);
+ /* p, q */
+#else
+ if ((result = MHD__gnutls_x509_read_int (pkey_asn, "coefficient",
+ &pkey->params[5])) < 0)
+ {
+ MHD_gnutls_assert ();
+ goto error;
+ }
+#endif
+ pkey->params_size = 6;
+
+ return pkey_asn;
+
+error:MHD__asn1_delete_structure (&pkey_asn);
+ MHD_gtls_mpi_release (&pkey->params[0]);
+ MHD_gtls_mpi_release (&pkey->params[1]);
+ MHD_gtls_mpi_release (&pkey->params[2]);
+ MHD_gtls_mpi_release (&pkey->params[3]);
+ MHD_gtls_mpi_release (&pkey->params[4]);
+ MHD_gtls_mpi_release (&pkey->params[5]);
+ return NULL;
+
+}
+
+#define PEM_KEY_RSA "RSA PRIVATE KEY"
+
+/**
+ * MHD_gnutls_x509_privkey_import - This function will import a DER or PEM encoded key
+ * @key: The structure to store the parsed key
+ * @data: The DER or PEM encoded certificate.
+ * @format: One of DER or PEM
+ *
+ * This function will convert the given DER or PEM encoded key
+ * to the native MHD_gnutls_x509_privkey_t format. The output will be stored in @key .
+ *
+ * If the key is PEM encoded it should have a header of "RSA PRIVATE KEY", or
+ * "DSA PRIVATE KEY".
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+MHD_gnutls_x509_privkey_import (MHD_gnutls_x509_privkey_t key,
+ const MHD_gnutls_datum_t * data,
+ MHD_gnutls_x509_crt_fmt_t format)
+{
+ int result = 0, need_free = 0;
+ MHD_gnutls_datum_t _data;
+
+ if (key == NULL)
+ {
+ MHD_gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ _data.data = data->data;
+ _data.size = data->size;
+
+ key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
+
+ /* If the Certificate is in PEM format then decode it */
+ if (format == GNUTLS_X509_FMT_PEM)
+ {
+ opaque *out;
+
+ /* Try the first header */
+ result
+ =
+ MHD__gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size,
+ &out);
+ key->pk_algorithm = MHD_GNUTLS_PK_RSA;
+
+ _data.data = out;
+ _data.size = result;
+
+ need_free = 1;
+ }
+
+ if (key->pk_algorithm == MHD_GNUTLS_PK_RSA)
+ {
+ key->key = MHD__gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
+ if (key->key == NULL)
+ MHD_gnutls_assert ();
+ }
+ else
+ {
+ /* Try decoding with both, and accept the one that succeeds. */
+ key->pk_algorithm = MHD_GNUTLS_PK_RSA;
+ key->key = MHD__gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
+
+ // TODO rm
+// if (key->key == NULL)
+// {
+// key->pk_algorithm = GNUTLS_PK_DSA;
+// key->key = decode_dsa_key(&_data, key);
+// if (key->key == NULL)
+// MHD_gnutls_assert();
+// }
+ }
+
+ if (key->key == NULL)
+ {
+ MHD_gnutls_assert ();
+ result = GNUTLS_E_ASN1_DER_ERROR;
+ key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
+ return result;
+ }
+
+ if (need_free)
+ MHD__gnutls_free_datum (&_data);
+
+ /* The key has now been decoded.
+ */
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/daemon/internal.c b/lib/libmicrohttpd/src/daemon/internal.c
new file mode 100644
index 0000000000..f30cc09a3a
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/internal.c
@@ -0,0 +1,159 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file internal.h
+ * @brief internal shared structures
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#include "internal.h"
+
+#if HAVE_MESSAGES
+/**
+ * State to string dictionary.
+ */
+char *
+MHD_state_to_string (enum MHD_CONNECTION_STATE state)
+{
+ switch (state)
+ {
+ case MHD_CONNECTION_INIT:
+ return "connection init";
+ case MHD_CONNECTION_URL_RECEIVED:
+ return "connection url received";
+ case MHD_CONNECTION_HEADER_PART_RECEIVED:
+ return "header partially received";
+ case MHD_CONNECTION_HEADERS_RECEIVED:
+ return "headers received";
+ case MHD_CONNECTION_HEADERS_PROCESSED:
+ return "headers processed";
+ case MHD_CONNECTION_CONTINUE_SENDING:
+ return "continue sending";
+ case MHD_CONNECTION_CONTINUE_SENT:
+ return "continue sent";
+ case MHD_CONNECTION_BODY_RECEIVED:
+ return "body received";
+ case MHD_CONNECTION_FOOTER_PART_RECEIVED:
+ return "footer partially received";
+ case MHD_CONNECTION_FOOTERS_RECEIVED:
+ return "footers received";
+ case MHD_CONNECTION_HEADERS_SENDING:
+ return "headers sending";
+ case MHD_CONNECTION_HEADERS_SENT:
+ return "headers sent";
+ case MHD_CONNECTION_NORMAL_BODY_READY:
+ return "normal body ready";
+ case MHD_CONNECTION_NORMAL_BODY_UNREADY:
+ return "normal body unready";
+ case MHD_CONNECTION_CHUNKED_BODY_READY:
+ return "chunked body ready";
+ case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
+ return "chunked body unready";
+ case MHD_CONNECTION_BODY_SENT:
+ return "body sent";
+ case MHD_CONNECTION_FOOTERS_SENDING:
+ return "footers sending";
+ case MHD_CONNECTION_FOOTERS_SENT:
+ return "footers sent";
+ case MHD_CONNECTION_CLOSED:
+ return "closed";
+ case MHD_TLS_CONNECTION_INIT:
+ return "secure connection init";
+ case MHD_TLS_HELLO_REQUEST:
+ return "secure hello request";
+ case MHD_TLS_HANDSHAKE_FAILED:
+ return "secure handshake failed";
+ case MHD_TLS_HANDSHAKE_COMPLETE:
+ return "secure handshake _complete";
+ default:
+ return "unrecognized connection state";
+ }
+}
+#endif
+
+#if HAVE_MESSAGES
+/**
+ * fprintf-like helper function for logging debug
+ * messages.
+ */
+void
+MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...)
+{
+ va_list va;
+
+ if ((daemon->options & MHD_USE_DEBUG) == 0)
+ return;
+ va_start (va, format);
+ daemon->custom_error_log (daemon->custom_error_log_cls, format, va);
+ va_end (va);
+}
+#endif
+
+void
+MHD_tls_log_func (int level, const char *str)
+{
+#ifdef HAVE_MESSAGES
+ FPRINTF (stderr, "|<%d>| %s", level, str);
+#endif
+}
+
+/**
+ * Process escape sequences ('+'=space, %HH)
+ */
+size_t
+MHD_http_unescape (char *val)
+{
+ char *rpos = val;
+ char *wpos = val;
+ unsigned int num;
+
+ while ('\0' != *rpos)
+ {
+ switch (*rpos)
+ {
+ case '+':
+ *wpos = ' ';
+ wpos++;
+ rpos++;
+ break;
+ case '%':
+ if ( (1 == SSCANF (&rpos[1],
+ "%2x", &num)) ||
+ (1 == SSCANF (&rpos[1],
+ "%2X", &num)) )
+ {
+ *wpos = (unsigned char) num;
+ wpos++;
+ rpos += 3;
+ break;
+ }
+ /* intentional fall through! */
+ default:
+ *wpos = *rpos;
+ wpos++;
+ rpos++;
+ }
+ }
+ *wpos = '\0'; /* add 0-terminator */
+ return wpos - val; /* = strlen(val) */
+}
+
+/* end of internal.c */
diff --git a/lib/libmicrohttpd/src/daemon/internal.h b/lib/libmicrohttpd/src/daemon/internal.h
new file mode 100644
index 0000000000..4c1feba06b
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/internal.h
@@ -0,0 +1,855 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file internal.h
+ * @brief internal shared structures
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#ifndef INTERNAL_H
+#define INTERNAL_H
+
+#include "platform.h"
+#include "microhttpd.h"
+#if HTTPS_SUPPORT
+#include "gnutls.h"
+#endif
+
+#define EXTRA_CHECKS MHD_YES
+
+#define MHD_MAX(a,b) ((a)<(b)) ? (b) : (a)
+#define MHD_MIN(a,b) ((a)<(b)) ? (a) : (b)
+
+/**
+ * Size by which MHD usually tries to increment read/write buffers.
+ * TODO: we should probably get rid of this magic constant and
+ * put in code to automatically determine a good value.
+ */
+#define MHD_BUF_INC_SIZE 2048
+
+/**
+ * Handler for fatal errors.
+ */
+extern MHD_PanicCallback mhd_panic;
+
+/**
+ * Closure argument for "mhd_panic".
+ */
+extern void *mhd_panic_cls;
+
+/**
+ * Events we care about with respect to poll/select
+ * for file descriptors.
+ */
+enum MHD_PollActions
+ {
+ /**
+ * No event interests us.
+ */
+ MHD_POLL_ACTION_NOTHING = 0,
+
+ /**
+ * We would like to read.
+ */
+ MHD_POLL_ACTION_IN = 1,
+
+ /**
+ * We would like to write.
+ */
+ MHD_POLL_ACTION_OUT = 2
+ };
+
+
+/**
+ * Socket descriptor and events we care about.
+ */
+struct MHD_Pollfd {
+ /**
+ * Socket descriptor.
+ */
+ int fd;
+
+ /**
+ * Which events do we care about for this socket?
+ */
+ enum MHD_PollActions events;
+};
+
+
+#if HAVE_MESSAGES
+/**
+ * fprintf-like helper function for logging debug
+ * messages.
+ */
+void MHD_DLOG (const struct MHD_Daemon *daemon, const char *format, ...);
+
+#endif
+void MHD_tls_log_func (int level, const char *str);
+
+/**
+ * Process escape sequences ('+'=space, %HH).
+ * Updates val in place.
+ *
+ * @return length of the resulting val (strlen(val) maybe
+ * shorter afterwards due to elimination of escape sequences)
+ */
+size_t MHD_http_unescape (char *val);
+
+/**
+ * Header or cookie in HTTP request or response.
+ */
+struct MHD_HTTP_Header
+{
+ /**
+ * Headers are kept in a linked list.
+ */
+ struct MHD_HTTP_Header *next;
+
+ /**
+ * The name of the header (key), without
+ * the colon.
+ */
+ char *header;
+
+ /**
+ * The value of the header.
+ */
+ char *value;
+
+ /**
+ * Type of the header (where in the HTTP
+ * protocol is this header from).
+ */
+ enum MHD_ValueKind kind;
+
+};
+
+/**
+ * Representation of a response.
+ */
+struct MHD_Response
+{
+
+ /**
+ * Headers to send for the response. Initially
+ * the linked list is created in inverse order;
+ * the order should be inverted before sending!
+ */
+ struct MHD_HTTP_Header *first_header;
+
+ /**
+ * Buffer pointing to data that we are supposed
+ * to send as a response.
+ */
+ char *data;
+
+ /**
+ * Closure to give to the content reader
+ * free callback.
+ */
+ void *crc_cls;
+
+ /**
+ * How do we get more data? NULL if we are
+ * given all of the data up front.
+ */
+ MHD_ContentReaderCallback crc;
+
+ /**
+ * NULL if data must not be freed, otherwise
+ * either user-specified callback or "&free".
+ */
+ MHD_ContentReaderFreeCallback crfc;
+
+ /**
+ * Mutex to synchronize access to data/size and
+ * reference counts.
+ */
+ pthread_mutex_t mutex;
+
+ /**
+ * Reference count for this response. Free
+ * once the counter hits zero.
+ */
+ unsigned int reference_count;
+
+ /**
+ * Set to -1 if size is not known.
+ */
+ uint64_t total_size;
+
+ /**
+ * Size of data.
+ */
+ size_t data_size;
+
+ /**
+ * Size of the data buffer.
+ */
+ size_t data_buffer_size;
+
+ /**
+ * At what offset in the stream is the
+ * beginning of data located?
+ */
+ uint64_t data_start;
+
+};
+
+/**
+ * States in a state machine for a connection.
+ *
+ * Transitions are any-state to CLOSED, any state to state+1,
+ * FOOTERS_SENT to INIT. CLOSED is the terminal state and
+ * INIT the initial state.
+ *
+ * Note that transitions for *reading* happen only after
+ * the input has been processed; transitions for
+ * *writing* happen after the respective data has been
+ * put into the write buffer (the write does not have
+ * to be completed yet). A transition to CLOSED or INIT
+ * requires the write to be complete.
+ */
+enum MHD_CONNECTION_STATE
+{
+ /**
+ * Connection just started (no headers received).
+ * Waiting for the line with the request type, URL and version.
+ */
+ MHD_CONNECTION_INIT = 0,
+
+ /**
+ * 1: We got the URL (and request type and version). Wait for a header line.
+ */
+ MHD_CONNECTION_URL_RECEIVED = MHD_CONNECTION_INIT + 1,
+
+ /**
+ * 2: We got part of a multi-line request header. Wait for the rest.
+ */
+ MHD_CONNECTION_HEADER_PART_RECEIVED = MHD_CONNECTION_URL_RECEIVED + 1,
+
+ /**
+ * 3: We got the request headers. Process them.
+ */
+ MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_HEADER_PART_RECEIVED + 1,
+
+ /**
+ * 4: We have processed the request headers. Send 100 continue.
+ */
+ MHD_CONNECTION_HEADERS_PROCESSED = MHD_CONNECTION_HEADERS_RECEIVED + 1,
+
+ /**
+ * 5: We have processed the headers and need to send 100 CONTINUE.
+ */
+ MHD_CONNECTION_CONTINUE_SENDING = MHD_CONNECTION_HEADERS_PROCESSED + 1,
+
+ /**
+ * 6: We have sent 100 CONTINUE (or do not need to). Read the message body.
+ */
+ MHD_CONNECTION_CONTINUE_SENT = MHD_CONNECTION_CONTINUE_SENDING + 1,
+
+ /**
+ * 7: We got the request body. Wait for a line of the footer.
+ */
+ MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_CONTINUE_SENT + 1,
+
+ /**
+ * 8: We got part of a line of the footer. Wait for the
+ * rest.
+ */
+ MHD_CONNECTION_FOOTER_PART_RECEIVED = MHD_CONNECTION_BODY_RECEIVED + 1,
+
+ /**
+ * 9: We received the entire footer. Wait for a response to be queued
+ * and prepare the response headers.
+ */
+ MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTER_PART_RECEIVED + 1,
+
+ /**
+ * 10: We have prepared the response headers in the writ buffer.
+ * Send the response headers.
+ */
+ MHD_CONNECTION_HEADERS_SENDING = MHD_CONNECTION_FOOTERS_RECEIVED + 1,
+
+ /**
+ * 11: We have sent the response headers. Get ready to send the body.
+ */
+ MHD_CONNECTION_HEADERS_SENT = MHD_CONNECTION_HEADERS_SENDING + 1,
+
+ /**
+ * 12: We are ready to send a part of a non-chunked body. Send it.
+ */
+ MHD_CONNECTION_NORMAL_BODY_READY = MHD_CONNECTION_HEADERS_SENT + 1,
+
+ /**
+ * 13: We are waiting for the client to provide more
+ * data of a non-chunked body.
+ */
+ MHD_CONNECTION_NORMAL_BODY_UNREADY = MHD_CONNECTION_NORMAL_BODY_READY + 1,
+
+ /**
+ * 14: We are ready to send a chunk.
+ */
+ MHD_CONNECTION_CHUNKED_BODY_READY = MHD_CONNECTION_NORMAL_BODY_UNREADY + 1,
+
+ /**
+ * 15: We are waiting for the client to provide a chunk of the body.
+ */
+ MHD_CONNECTION_CHUNKED_BODY_UNREADY = MHD_CONNECTION_CHUNKED_BODY_READY + 1,
+
+ /**
+ * 16: We have sent the response body. Prepare the footers.
+ */
+ MHD_CONNECTION_BODY_SENT = MHD_CONNECTION_CHUNKED_BODY_UNREADY + 1,
+
+ /**
+ * 17: We have prepared the response footer. Send it.
+ */
+ MHD_CONNECTION_FOOTERS_SENDING = MHD_CONNECTION_BODY_SENT + 1,
+
+ /**
+ * 18: We have sent the response footer. Shutdown or restart.
+ */
+ MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1,
+
+ /**
+ * 19: This connection is closed (no more activity
+ * allowed).
+ */
+ MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1,
+
+ /*
+ * SSL/TLS connection states
+ */
+
+ /**
+ * The initial connection state for all secure connectoins
+ * Handshake messages will be processed in this state & while
+ * in the 'MHD_TLS_HELLO_REQUEST' state
+ */
+ MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_CLOSED + 1,
+
+ /**
+ * This state indicates the server has send a 'Hello Request' to
+ * the client & a renegotiation of the handshake is in progress.
+ *
+ * Handshake messages will processed in this state & while
+ * in the 'MHD_TLS_CONNECTION_INIT' state
+ */
+ MHD_TLS_HELLO_REQUEST,
+
+ MHD_TLS_HANDSHAKE_FAILED,
+
+ MHD_TLS_HANDSHAKE_COMPLETE
+
+};
+
+/**
+ * Should all state transitions be printed to stderr?
+ */
+#define DEBUG_STATES MHD_NO
+
+#if HAVE_MESSAGES
+char *MHD_state_to_string (enum MHD_CONNECTION_STATE state);
+#endif
+
+/**
+ * Function to receive plaintext data.
+ *
+ * @param conn the connection struct
+ * @param write_to where to write received data
+ * @param max_bytes maximum number of bytes to receive
+ * @return number of bytes written to write_to
+ */
+typedef ssize_t (*ReceiveCallback) (struct MHD_Connection * conn,
+ void *write_to, size_t max_bytes);
+
+
+/**
+ * Function to transmit plaintext data.
+ *
+ * @param conn the connection struct
+ * @param read_from where to read data to transmit
+ * @param max_bytes maximum number of bytes to transmit
+ * @return number of bytes transmitted
+ */
+typedef ssize_t (*TransmitCallback) (struct MHD_Connection * conn,
+ const void *write_to, size_t max_bytes);
+
+
+/**
+ * State kept for each HTTP request.
+ */
+struct MHD_Connection
+{
+
+ /**
+ * This is a linked list.
+ */
+ struct MHD_Connection *next;
+
+ /**
+ * Reference to the MHD_Daemon struct.
+ */
+ struct MHD_Daemon *daemon;
+
+ /**
+ * Linked list of parsed headers.
+ */
+ struct MHD_HTTP_Header *headers_received;
+
+ /**
+ * Response to transmit (initially NULL).
+ */
+ struct MHD_Response *response;
+
+ /**
+ * The memory pool is created whenever we first read
+ * from the TCP stream and destroyed at the end of
+ * each request (and re-created for the next request).
+ * In the meantime, this pointer is NULL. The
+ * pool is used for all connection-related data
+ * except for the response (which maybe shared between
+ * connections) and the IP address (which persists
+ * across individual requests).
+ */
+ struct MemoryPool *pool;
+
+ /**
+ * We allow the main application to associate some
+ * pointer with the connection. Here is where we
+ * store it. (MHD does not know or care what it
+ * is).
+ */
+ void *client_context;
+
+ /**
+ * Request method. Should be GET/POST/etc. Allocated
+ * in pool.
+ */
+ char *method;
+
+ /**
+ * Requested URL (everything after "GET" only). Allocated
+ * in pool.
+ */
+ char *url;
+
+ /**
+ * HTTP version string (i.e. http/1.1). Allocated
+ * in pool.
+ */
+ char *version;
+
+ /**
+ * Buffer for reading requests. Allocated
+ * in pool. Actually one byte larger than
+ * read_buffer_size (if non-NULL) to allow for
+ * 0-termination.
+ */
+ char *read_buffer;
+
+ /**
+ * Buffer for writing response (headers only). Allocated
+ * in pool.
+ */
+ char *write_buffer;
+
+ /**
+ * Last incomplete header line during parsing of headers.
+ * Allocated in pool. Only valid if state is
+ * either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
+ */
+ char *last;
+
+ /**
+ * Position after the colon on the last incomplete header
+ * line during parsing of headers.
+ * Allocated in pool. Only valid if state is
+ * either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
+ */
+ char *colon;
+
+ /**
+ * Foreign address (of length addr_len). MALLOCED (not
+ * in pool!).
+ */
+ struct sockaddr_in *addr;
+
+ /**
+ * Thread for this connection (if we are using
+ * one thread per connection).
+ */
+ pthread_t pid;
+
+ /**
+ * Size of read_buffer (in bytes). This value indicates
+ * how many bytes we're willing to read into the buffer;
+ * the real buffer is one byte longer to allow for
+ * adding zero-termination (when needed).
+ */
+ size_t read_buffer_size;
+
+ /**
+ * Position where we currently append data in
+ * read_buffer (last valid position).
+ */
+ size_t read_buffer_offset;
+
+ /**
+ * Size of write_buffer (in bytes).
+ */
+ size_t write_buffer_size;
+
+ /**
+ * Offset where we are with sending from write_buffer.
+ */
+ size_t write_buffer_send_offset;
+
+ /**
+ * Last valid location in write_buffer (where do we
+ * append and up to where is it safe to send?)
+ */
+ size_t write_buffer_append_offset;
+
+ /**
+ * How many more bytes of the body do we expect
+ * to read? "-1" for unknown.
+ */
+ uint64_t remaining_upload_size;
+
+ /**
+ * Current write position in the actual response
+ * (excluding headers, content only; should be 0
+ * while sending headers).
+ */
+ uint64_t response_write_position;
+
+ /**
+ * Position in the 100 CONTINUE message that
+ * we need to send when receiving http 1.1 requests.
+ */
+ size_t continue_message_write_offset;
+
+ /**
+ * Length of the foreign address.
+ */
+ socklen_t addr_len;
+
+ /**
+ * Last time this connection had any activity
+ * (reading or writing).
+ */
+ time_t last_activity;
+
+ /**
+ * Did we ever call the "default_handler" on this connection?
+ * (this flag will determine if we call the 'notify_completed'
+ * handler when the connection closes down).
+ */
+ int client_aware;
+
+ /**
+ * Socket for this connection. Set to -1 if
+ * this connection has died (daemon should clean
+ * up in that case).
+ */
+ int socket_fd;
+
+ /**
+ * Has this socket been closed for reading (i.e.
+ * other side closed the connection)? If so,
+ * we must completely close the connection once
+ * we are done sending our response (and stop
+ * trying to read from this socket).
+ */
+ int read_closed;
+
+ /**
+ * State in the FSM for this connection.
+ */
+ enum MHD_CONNECTION_STATE state;
+
+ /**
+ * HTTP response code. Only valid if response object
+ * is already set.
+ */
+ unsigned int responseCode;
+
+ /**
+ * Set to MHD_YES if the response's content reader
+ * callback failed to provide data the last time
+ * we tried to read from it. In that case, the
+ * write socket should be marked as unready until
+ * the CRC call succeeds.
+ */
+ int response_unready;
+
+ /**
+ * Are we sending with chunked encoding?
+ */
+ int have_chunked_response;
+
+ /**
+ * Are we receiving with chunked encoding? This will be set to
+ * MHD_YES after we parse the headers and are processing the body
+ * with chunks. After we are done with the body and we are
+ * processing the footers; once the footers are also done, this will
+ * be set to MHD_NO again (before the final call to the handler).
+ */
+ int have_chunked_upload;
+
+ /**
+ * If we are receiving with chunked encoding, where are we right
+ * now? Set to 0 if we are waiting to receive the chunk size;
+ * otherwise, this is the size of the current chunk. A value of
+ * zero is also used when we're at the end of the chunks.
+ */
+ unsigned int current_chunk_size;
+
+ /**
+ * If we are receiving with chunked encoding, where are we currently
+ * with respect to the current chunk (at what offset / position)?
+ */
+ unsigned int current_chunk_offset;
+
+ /**
+ * Handler used for processing read connection operations
+ */
+ int (*read_handler) (struct MHD_Connection * connection);
+
+ /**
+ * Handler used for processing write connection operations
+ */
+ int (*write_handler) (struct MHD_Connection * connection);
+
+ /**
+ * Handler used for processing idle connection operations
+ */
+ int (*idle_handler) (struct MHD_Connection * connection);
+
+ /**
+ * Function used for reading HTTP request stream.
+ */
+ ReceiveCallback recv_cls;
+
+ /**
+ * Function used for writing HTTP response stream.
+ */
+ TransmitCallback send_cls;
+
+#if HTTPS_SUPPORT
+ /**
+ * State required for HTTPS/SSL/TLS support.
+ */
+ MHD_gtls_session_t tls_session;
+#endif
+};
+
+typedef void * (*LogCallback)(void * cls, const char * uri);
+
+/**
+ * State kept for each MHD daemon.
+ */
+struct MHD_Daemon
+{
+
+ /**
+ * Callback function for all requests.
+ */
+ MHD_AccessHandlerCallback default_handler;
+
+ /**
+ * Closure argument to default_handler.
+ */
+ void *default_handler_cls;
+
+ /**
+ * Linked list of our current connections.
+ */
+ struct MHD_Connection *connections;
+
+ /**
+ * Function to call to check if we should
+ * accept or reject an incoming request.
+ * May be NULL.
+ */
+ MHD_AcceptPolicyCallback apc;
+
+ /**
+ * Closure argument to apc.
+ */
+ void *apc_cls;
+
+ /**
+ * Function to call when we are done processing
+ * a particular request. May be NULL.
+ */
+ MHD_RequestCompletedCallback notify_completed;
+
+ /**
+ * Closure argument to notify_completed.
+ */
+ void *notify_completed_cls;
+
+ /**
+ * Function to call with the full URI at the
+ * beginning of request processing. May be NULL.
+ * <p>
+ * Returns the initial pointer to internal state
+ * kept by the client for the request.
+ */
+ LogCallback uri_log_callback;
+
+ /**
+ * Closure argument to uri_log_callback.
+ */
+ void *uri_log_callback_cls;
+
+#if HAVE_MESSAGES
+ /**
+ * Function for logging error messages (if we
+ * support error reporting).
+ */
+ void (*custom_error_log) (void *cls, const char *fmt, va_list va);
+
+ /**
+ * Closure argument to custom_error_log.
+ */
+ void *custom_error_log_cls;
+#endif
+
+ /**
+ * PID of the select thread (if we have internal select)
+ */
+ pthread_t pid;
+
+ /**
+ * Listen socket.
+ */
+ int socket_fd;
+
+ /**
+ * Are we shutting down?
+ */
+ int shutdown;
+
+ /**
+ * Size of the per-connection memory pools.
+ */
+ size_t pool_size;
+
+ /**
+ * Limit on the number of parallel connections.
+ */
+ unsigned int max_connections;
+
+ /**
+ * After how many seconds of inactivity should
+ * connections time out? Zero for no timeout.
+ */
+ unsigned int connection_timeout;
+
+ /**
+ * Maximum number of connections per IP, or 0 for
+ * unlimited.
+ */
+ unsigned int per_ip_connection_limit;
+
+ /**
+ * Table storing number of connections per IP
+ */
+ void *per_ip_connection_count;
+
+ /**
+ * Mutex for per-IP connection counts
+ */
+ pthread_mutex_t per_ip_connection_mutex;
+
+ /**
+ * Daemon's options.
+ */
+ enum MHD_OPTION options;
+
+ /**
+ * Listen port.
+ */
+ unsigned short port;
+
+#if HTTPS_SUPPORT
+ /**
+ * What kind of credentials are we offering
+ * for SSL/TLS?
+ */
+ enum MHD_GNUTLS_CredentialsType cred_type;
+
+ /**
+ * Server x509 credentials
+ */
+ MHD_gtls_cert_credentials_t x509_cred;
+
+ /**
+ * Cipher priority cache
+ */
+ MHD_gnutls_priority_t priority_cache;
+
+ /**
+ * Diffie-Hellman parameters
+ */
+ MHD_gtls_dh_params_t dh_params;
+
+ /**
+ * Pointer to our SSL/TLS key (in ASCII) in memory.
+ */
+ const char *https_mem_key;
+
+ /**
+ * Pointer to our SSL/TLS certificate (in ASCII) in memory.
+ */
+ const char *https_mem_cert;
+#endif
+
+ /**
+ * Pointer to master daemon (NULL if this is the master)
+ */
+ struct MHD_Daemon *master;
+
+ /**
+ * Worker daemons (one per thread)
+ */
+ struct MHD_Daemon *worker_pool;
+
+ /**
+ * Number of worker daemons
+ */
+ unsigned int worker_pool_size;
+};
+
+
+#if EXTRA_CHECKS
+#define EXTRA_CHECK(a) if (!(a)) abort();
+#else
+#define EXTRA_CHECK(a)
+#endif
+
+
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/memorypool.c b/lib/libmicrohttpd/src/daemon/memorypool.c
new file mode 100644
index 0000000000..6df5cb5fd8
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/memorypool.c
@@ -0,0 +1,241 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file memorypool.c
+ * @brief memory pool
+ * @author Christian Grothoff
+ */
+#include "memorypool.h"
+
+/* define MAP_ANONYMOUS for Mac OS X */
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void*)-1)
+#endif
+
+/**
+ * Align to 2x word size (as GNU libc does).
+ */
+#define ALIGN_SIZE (2 * sizeof(void*))
+
+/**
+ * Round up 'n' to a multiple of ALIGN_SIZE.
+ */
+#define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1)))
+
+struct MemoryPool
+{
+
+ /**
+ * Pointer to the pool's memory
+ */
+ char *memory;
+
+ /**
+ * Size of the pool.
+ */
+ size_t size;
+
+ /**
+ * Offset of the first unallocated byte.
+ */
+ size_t pos;
+
+ /**
+ * Offset of the last unallocated byte.
+ */
+ size_t end;
+
+ /**
+ * MHD_NO if pool was malloc'ed, MHD_YES if mmapped.
+ */
+ int is_mmap;
+};
+
+/**
+ * Create a memory pool.
+ *
+ * @param max maximum size of the pool
+ */
+struct MemoryPool *
+MHD_pool_create (size_t max)
+{
+ struct MemoryPool *pool;
+
+ pool = malloc (sizeof (struct MemoryPool));
+ if (pool == NULL)
+ return NULL;
+#ifdef MAP_ANONYMOUS
+ pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS, -1, 0);
+#else
+ pool->memory = MAP_FAILED;
+#endif
+ if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
+ {
+ pool->memory = malloc (max);
+ if (pool->memory == NULL)
+ {
+ free (pool);
+ return NULL;
+ }
+ pool->is_mmap = MHD_NO;
+ }
+ else
+ {
+ pool->is_mmap = MHD_YES;
+ }
+ pool->pos = 0;
+ pool->end = max;
+ pool->size = max;
+ return pool;
+}
+
+/**
+ * Destroy a memory pool.
+ */
+void
+MHD_pool_destroy (struct MemoryPool *pool)
+{
+ if (pool == NULL)
+ return;
+ if (pool->is_mmap == MHD_NO)
+ free (pool->memory);
+ else
+ MUNMAP (pool->memory, pool->size);
+ free (pool);
+}
+
+/**
+ * Allocate size bytes from the pool.
+ * @return NULL if the pool cannot support size more
+ * bytes
+ */
+void *
+MHD_pool_allocate (struct MemoryPool *pool,
+ size_t size, int from_end)
+{
+ void *ret;
+
+ size = ROUND_TO_ALIGN (size);
+ if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
+ return NULL;
+ if (from_end == MHD_YES)
+ {
+ ret = &pool->memory[pool->end - size];
+ pool->end -= size;
+ }
+ else
+ {
+ ret = &pool->memory[pool->pos];
+ pool->pos += size;
+ }
+ return ret;
+}
+
+/**
+ * Reallocate a block of memory obtained from the pool.
+ * This is particularly efficient when growing or
+ * shrinking the block that was last (re)allocated.
+ * If the given block is not the most recenlty
+ * (re)allocated block, the memory of the previous
+ * allocation may be leaked until the pool is
+ * destroyed (and copying the data maybe required).
+ *
+ * @param old the existing block
+ * @param old_size the size of the existing block
+ * @param new_size the new size of the block
+ * @return new address of the block, or
+ * NULL if the pool cannot support new_size
+ * bytes (old continues to be valid for old_size)
+ */
+void *
+MHD_pool_reallocate (struct MemoryPool *pool,
+ void *old,
+ size_t old_size,
+ size_t new_size)
+{
+ void *ret;
+
+ new_size = ROUND_TO_ALIGN (new_size);
+ if ((pool->end < old_size) || (pool->end < new_size))
+ return NULL; /* unsatisfiable or bogus request */
+
+ if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
+ {
+ /* was the previous allocation - optimize! */
+ if (pool->pos + new_size - old_size <= pool->end)
+ {
+ /* fits */
+ pool->pos += new_size - old_size;
+ if (new_size < old_size) /* shrinking - zero again! */
+ memset (&pool->memory[pool->pos], 0, old_size - new_size);
+ return old;
+ }
+ /* does not fit */
+ return NULL;
+ }
+ if (new_size <= old_size)
+ return old; /* cannot shrink, no need to move */
+ if ((pool->pos + new_size >= pool->pos) &&
+ (pool->pos + new_size <= pool->end))
+ {
+ /* fits */
+ ret = &pool->memory[pool->pos];
+ memcpy (ret, old, old_size);
+ pool->pos += new_size;
+ return ret;
+ }
+ /* does not fit */
+ return NULL;
+}
+
+/**
+ * Clear all entries from the memory pool except
+ * for "keep" of the given "size".
+ *
+ * @param keep pointer to the entry to keep (maybe NULL)
+ * @param size how many bytes need to be kept at this address
+ * @return addr new address of "keep" (if it had to change)
+ */
+void *
+MHD_pool_reset (struct MemoryPool *pool,
+ void *keep,
+ size_t size)
+{
+ size = ROUND_TO_ALIGN (size);
+ if (keep != NULL)
+ {
+ if (keep != pool->memory)
+ {
+ memmove (pool->memory, keep, size);
+ keep = pool->memory;
+ }
+ pool->pos = size;
+ }
+ pool->end = pool->size;
+ return keep;
+}
+
+
+
+/* end of memorypool.c */
diff --git a/lib/libmicrohttpd/src/daemon/memorypool.h b/lib/libmicrohttpd/src/daemon/memorypool.h
new file mode 100644
index 0000000000..51f8167489
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/memorypool.h
@@ -0,0 +1,97 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file memorypool.h
+ * @brief memory pool; mostly used for efficient (de)allocation
+ * for each connection and bounding memory use for each
+ * request
+ * @author Christian Grothoff
+ */
+
+#ifndef MEMORYPOOL_H
+#define MEMORYPOOL_H
+
+#include "internal.h"
+
+/**
+ * Opaque handle for a memory pool.
+ * Pools are not reentrant and must not be used
+ * by multiple threads.
+ */
+struct MemoryPool;
+
+/**
+ * Create a memory pool.
+ *
+ * @param max maximum size of the pool
+ */
+struct MemoryPool *MHD_pool_create (size_t max);
+
+/**
+ * Destroy a memory pool.
+ */
+void MHD_pool_destroy (struct MemoryPool *pool);
+
+/**
+ * Allocate size bytes from the pool.
+ *
+ * @param from_end allocate from end of pool (set to MHD_YES);
+ * use this for small, persistent allocations that
+ * will never be reallocated
+ * @return NULL if the pool cannot support size more
+ * bytes
+ */
+void *MHD_pool_allocate (struct MemoryPool *pool,
+ size_t size, int from_end);
+
+/**
+ * Reallocate a block of memory obtained from the pool.
+ * This is particularly efficient when growing or
+ * shrinking the block that was last (re)allocated.
+ * If the given block is not the most recenlty
+ * (re)allocated block, the memory of the previous
+ * allocation may be leaked until the pool is
+ * destroyed (and copying the data maybe required).
+ *
+ * @param old the existing block
+ * @param old_size the size of the existing block
+ * @param new_size the new size of the block
+ * @return new address of the block, or
+ * NULL if the pool cannot support new_size
+ * bytes (old continues to be valid for old_size)
+ */
+void *MHD_pool_reallocate (struct MemoryPool *pool,
+ void *old,
+ size_t old_size,
+ size_t new_size);
+
+/**
+ * Clear all entries from the memory pool except
+ * for "keep" of the given "size".
+ *
+ * @param keep pointer to the entry to keep (maybe NULL)
+ * @param size how many bytes need to be kept at this address
+ * @return addr new address of "keep" (if it had to change)
+ */
+void *MHD_pool_reset (struct MemoryPool *pool,
+ void *keep,
+ size_t size);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/postprocessor.c b/lib/libmicrohttpd/src/daemon/postprocessor.c
new file mode 100644
index 0000000000..735c8d3687
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/postprocessor.c
@@ -0,0 +1,1044 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file postprocessor.c
+ * @brief Methods for parsing POST data
+ * @author Christian Grothoff
+ */
+
+#include "internal.h"
+
+/**
+ * Size of on-stack buffer that we use for un-escaping of the value.
+ */
+#define XBUF_SIZE 1024
+
+/**
+ * States in the PP parser's state machine.
+ */
+enum PP_State
+{
+ /* general states */
+ PP_Error,
+ PP_Done,
+ PP_Init,
+
+ /* url encoding-states */
+ PP_ProcessValue,
+ PP_ExpectNewLine,
+
+ /* post encoding-states */
+ PP_ProcessEntryHeaders,
+ PP_PerformCheckMultipart,
+ PP_ProcessValueToBoundary,
+ PP_PerformCleanup,
+
+ /* nested post-encoding states */
+ PP_Nested_Init,
+ PP_Nested_PerformMarking,
+ PP_Nested_ProcessEntryHeaders,
+ PP_Nested_ProcessValueToBoundary,
+ PP_Nested_PerformCleanup,
+
+};
+
+enum RN_State
+{
+ /**
+ * No RN-preprocessing in this state.
+ */
+ RN_Inactive = 0,
+
+ /**
+ * If the next character is '\n', skip it. Otherwise,
+ * just go inactive.
+ */
+ RN_OptN = 1,
+
+ /**
+ * Expect '\r\n' (and only '\r\n'). As always, we also
+ * expect only '\r' or only '\n'.
+ */
+ RN_Full = 2,
+
+ /**
+ * Expect either '\r\n' or '--\r\n'. If '--\r\n', transition into dash-state
+ * for the main state machine
+ */
+ RN_Dash = 3,
+
+ /**
+ * Got a single dash, expect second dash.
+ */
+ RN_Dash2 = 4,
+};
+
+/**
+ * Bits for the globally known fields that
+ * should not be deleted when we exit the
+ * nested state.
+ */
+enum NE_State
+{
+ NE_none = 0,
+ NE_content_name = 1,
+ NE_content_type = 2,
+ NE_content_filename = 4,
+ NE_content_transfer_encoding = 8,
+};
+
+/**
+ * Internal state of the post-processor. Note that the fields
+ * are sorted by type to enable optimal packing by the compiler.
+ */
+struct MHD_PostProcessor
+{
+
+ /**
+ * The connection for which we are doing
+ * POST processing.
+ */
+ struct MHD_Connection *connection;
+
+ /**
+ * Function to call with POST data.
+ */
+ MHD_PostDataIterator ikvi;
+
+ /**
+ * Extra argument to ikvi.
+ */
+ void *cls;
+
+ /**
+ * Encoding as given by the headers of the
+ * connection.
+ */
+ const char *encoding;
+
+ /**
+ * Primary boundary (points into encoding string)
+ */
+ const char *boundary;
+
+ /**
+ * Nested boundary (if we have multipart/mixed encoding).
+ */
+ char *nested_boundary;
+
+ /**
+ * Pointer to the name given in disposition.
+ */
+ char *content_name;
+
+ /**
+ * Pointer to the (current) content type.
+ */
+ char *content_type;
+
+ /**
+ * Pointer to the (current) filename.
+ */
+ char *content_filename;
+
+ /**
+ * Pointer to the (current) encoding.
+ */
+ char *content_transfer_encoding;
+
+ /**
+ * Unprocessed value bytes due to escape
+ * sequences (URL-encoding only).
+ */
+ char xbuf[8];
+
+ /**
+ * Size of our buffer for the key.
+ */
+ size_t buffer_size;
+
+ /**
+ * Current position in the key buffer.
+ */
+ size_t buffer_pos;
+
+ /**
+ * Current position in xbuf.
+ */
+ size_t xbuf_pos;
+
+ /**
+ * Current offset in the value being processed.
+ */
+ uint64_t value_offset;
+
+ /**
+ * strlen(boundary) -- if boundary != NULL.
+ */
+ size_t blen;
+
+ /**
+ * strlen(nested_boundary) -- if nested_boundary != NULL.
+ */
+ size_t nlen;
+
+ /**
+ * State of the parser.
+ */
+ enum PP_State state;
+
+ /**
+ * Side-state-machine: skip '\r\n' (or just '\n').
+ * Set to 0 if we are not in skip mode. Set to 2
+ * if a '\r\n' is expected, set to 1 if a '\n' should
+ * be skipped if it is the next character.
+ */
+ enum RN_State skip_rn;
+
+ /**
+ * If we are in skip_rn with "dash" mode and
+ * do find 2 dashes, what state do we go into?
+ */
+ enum PP_State dash_state;
+
+ /**
+ * Which headers are global? (used to tell which
+ * headers were only valid for the nested multipart).
+ */
+ enum NE_State have;
+
+};
+
+
+/**
+ * Create a PostProcessor.
+ *
+ * A PostProcessor can be used to (incrementally)
+ * parse the data portion of a POST request.
+ *
+ * @param connection the connection on which the POST is
+ * happening (used to determine the POST format)
+ * @param buffer_size maximum number of bytes to use for
+ * internal buffering (used only for the parsing,
+ * specifically the parsing of the keys). A
+ * tiny value (256-1024) should be sufficient.
+ * Do NOT use 0.
+ * @param ikvi iterator to be called with the parsed data
+ * @param cls first argument to ikvi
+ * @return NULL on error (out of memory, unsupported encoding),
+ * otherwise a PP handle
+ */
+struct MHD_PostProcessor *
+MHD_create_post_processor (struct MHD_Connection *connection,
+ size_t buffer_size,
+ MHD_PostDataIterator ikvi, void *cls)
+{
+ struct MHD_PostProcessor *ret;
+ const char *encoding;
+ const char *boundary;
+ size_t blen;
+
+ if ((buffer_size < 256) || (connection == NULL) || (ikvi == NULL))
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
+ encoding = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_CONTENT_TYPE);
+ if (encoding == NULL)
+ return NULL;
+ boundary = NULL;
+ if (0 != strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding,
+ strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
+ {
+ if (0 !=
+ strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding,
+ strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
+ return NULL;
+ boundary =
+ &encoding[strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)];
+ /* Q: should this be "strcasestr"? */
+ if (NULL != strstr (boundary, "boundary="))
+ boundary = strstr (boundary, "boundary=") + strlen ("boundary=");
+ else
+ return NULL; /* failed to determine boundary */
+ blen = strlen (boundary);
+ if ((blen == 0) || (blen * 2 + 2 > buffer_size))
+ return NULL; /* (will be) out of memory or invalid boundary */
+ }
+ else
+ blen = 0;
+ ret = malloc (sizeof (struct MHD_PostProcessor) + buffer_size + 1);
+ if (ret == NULL)
+ return NULL;
+ memset (ret, 0, sizeof (struct MHD_PostProcessor) + buffer_size + 1);
+ ret->connection = connection;
+ ret->ikvi = ikvi;
+ ret->cls = cls;
+ ret->encoding = encoding;
+ ret->buffer_size = buffer_size;
+ ret->state = PP_Init;
+ ret->blen = blen;
+ ret->boundary = boundary;
+ ret->skip_rn = RN_Inactive;
+ return ret;
+}
+
+/**
+ * Process url-encoded POST data.
+ */
+static int
+post_process_urlencoded (struct MHD_PostProcessor *pp,
+ const char *post_data,
+ size_t post_data_len)
+{
+ size_t equals;
+ size_t amper;
+ size_t poff;
+ size_t xoff;
+ size_t delta;
+ int end_of_value_found;
+ char *buf;
+ char xbuf[XBUF_SIZE + 1];
+
+ buf = (char *) &pp[1];
+ poff = 0;
+ while (poff < post_data_len)
+ {
+ switch (pp->state)
+ {
+ case PP_Error:
+ return MHD_NO;
+ case PP_Done:
+ /* did not expect to receive more data */
+ pp->state = PP_Error;
+ return MHD_NO;
+ case PP_Init:
+ equals = 0;
+ while ((equals + poff < post_data_len) &&
+ (post_data[equals + poff] != '='))
+ equals++;
+ if (equals + pp->buffer_pos > pp->buffer_size)
+ {
+ pp->state = PP_Error; /* out of memory */
+ return MHD_NO;
+ }
+ memcpy (&buf[pp->buffer_pos], &post_data[poff], equals);
+ pp->buffer_pos += equals;
+ if (equals + poff == post_data_len)
+ return MHD_YES; /* no '=' yet */
+ buf[pp->buffer_pos] = '\0'; /* 0-terminate key */
+ pp->buffer_pos = 0; /* reset for next key */
+ MHD_http_unescape (buf);
+ poff += equals + 1;
+ pp->state = PP_ProcessValue;
+ pp->value_offset = 0;
+ break;
+ case PP_ProcessValue:
+ /* obtain rest of value from previous iteration */
+ memcpy (xbuf, pp->xbuf, pp->xbuf_pos);
+ xoff = pp->xbuf_pos;
+ pp->xbuf_pos = 0;
+
+ /* find last position in input buffer that is part of the value */
+ amper = 0;
+ while ((amper + poff < post_data_len) &&
+ (amper < XBUF_SIZE) &&
+ (post_data[amper + poff] != '&') &&
+ (post_data[amper + poff] != '\n') &&
+ (post_data[amper + poff] != '\r'))
+ amper++;
+ end_of_value_found = ((amper + poff < post_data_len) &&
+ ((post_data[amper + poff] == '&') ||
+ (post_data[amper + poff] == '\n') ||
+ (post_data[amper + poff] == '\r')));
+ /* compute delta, the maximum number of bytes that we will be able to
+ process right now (either amper-limited of xbuf-size limited) */
+ delta = amper;
+ if (delta > XBUF_SIZE - xoff)
+ delta = XBUF_SIZE - xoff;
+
+ /* move input into processing buffer */
+ memcpy (&xbuf[xoff], &post_data[poff], delta);
+ xoff += delta;
+ poff += delta;
+
+ /* find if escape sequence is at the end of the processing buffer;
+ if so, exclude those from processing (reduce delta to point at
+ end of processed region) */
+ delta = xoff;
+ if ((delta > 0) && (xbuf[delta - 1] == '%'))
+ delta--;
+ else if ((delta > 1) && (xbuf[delta - 2] == '%'))
+ delta -= 2;
+
+ /* if we have an incomplete escape sequence, save it to
+ pp->xbuf for later */
+ if (delta < xoff)
+ {
+ memcpy (pp->xbuf, &xbuf[delta], xoff - delta);
+ pp->xbuf_pos = xoff - delta;
+ xoff = delta;
+ }
+
+ /* If we have nothing to do (delta == 0) and
+ not just because the value is empty (are
+ waiting for more data), go for next iteration */
+ if ((xoff == 0) && (poff == post_data_len))
+ continue;
+
+ /* unescape */
+ xbuf[xoff] = '\0'; /* 0-terminate in preparation */
+ xoff = MHD_http_unescape (xbuf);
+ /* finally: call application! */
+ if (MHD_NO == pp->ikvi (pp->cls, MHD_POSTDATA_KIND, (const char *) &pp[1], /* key */
+ NULL, NULL, NULL, xbuf, pp->value_offset,
+ xoff))
+ {
+ pp->state = PP_Error;
+ return MHD_NO;
+ }
+ pp->value_offset += xoff;
+
+ /* are we done with the value? */
+ if (end_of_value_found)
+ {
+ /* we found the end of the value! */
+ if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
+ {
+ pp->state = PP_ExpectNewLine;
+ }
+ else
+ {
+ poff++; /* skip '&' */
+ pp->state = PP_Init;
+ }
+ }
+ break;
+ case PP_ExpectNewLine:
+ if ((post_data[poff] == '\n') || (post_data[poff] == '\r'))
+ {
+ poff++;
+ /* we are done, report error if we receive any more... */
+ pp->state = PP_Done;
+ return MHD_YES;
+ }
+ return MHD_NO;
+ default:
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */
+ }
+ }
+ return MHD_YES;
+}
+
+/**
+ * If the given line matches the prefix, strdup the
+ * rest of the line into the suffix ptr.
+ *
+ * @return MHD_YES if there was a match, MHD_NO if not
+ */
+static int
+try_match_header (const char *prefix, char *line, char **suffix)
+{
+ if (NULL != *suffix)
+ return MHD_NO;
+ while (*line != 0)
+ {
+ if (0 == strncasecmp (prefix, line, strlen (prefix)))
+ {
+ *suffix = strdup (&line[strlen (prefix)]);
+ return MHD_YES;
+ }
+ ++line;
+ }
+ return MHD_NO;
+}
+
+static int
+find_boundary (struct MHD_PostProcessor *pp,
+ const char *boundary,
+ size_t blen,
+ size_t *ioffptr,
+ enum PP_State next_state, enum PP_State next_dash_state)
+{
+ char *buf = (char *) &pp[1];
+
+ if (pp->buffer_pos < 2 + blen)
+ {
+ if (pp->buffer_pos == pp->buffer_size)
+ pp->state = PP_Error; /* out of memory */
+ return MHD_NO; /* not enough data */
+ }
+ if ((0 != memcmp ("--", buf, 2)) || (0 != memcmp (&buf[2], boundary, blen)))
+ {
+ pp->state = PP_Error;
+ return MHD_NO; /* expected boundary */
+ }
+ /* remove boundary from buffer */
+ (*ioffptr) += 2 + blen;
+ /* next: start with headers */
+ pp->skip_rn = RN_Dash;
+ pp->state = next_state;
+ pp->dash_state = next_dash_state;
+ return MHD_YES;
+}
+
+/**
+ * In buf, there maybe an expression
+ * '$key="$value"'. If that is the case,
+ * copy a copy of $value to destination.
+ *
+ * If destination is already non-NULL,
+ * do nothing.
+ */
+static void
+try_get_value (const char *buf, const char *key, char **destination)
+{
+ const char *spos;
+ const char *bpos;
+ const char *endv;
+ size_t klen;
+ size_t vlen;
+
+ if (NULL != *destination)
+ return;
+ bpos = buf;
+ klen = strlen (key);
+ while (NULL != (spos = strstr (bpos, key)))
+ {
+ if ((spos[klen] != '=') || ((spos != buf) && (spos[-1] != ' ')))
+ {
+ /* no match */
+ bpos = spos + 1;
+ continue;
+ }
+ if (spos[klen + 1] != '"')
+ return; /* not quoted */
+ if (NULL == (endv = strstr (&spos[klen + 2], "\"")))
+ return; /* no end-quote */
+ vlen = endv - spos - klen - 1;
+ *destination = malloc (vlen);
+ if (NULL == *destination)
+ return; /* out of memory */
+ (*destination)[vlen - 1] = '\0';
+ memcpy (*destination, &spos[klen + 2], vlen - 1);
+ return; /* success */
+ }
+}
+
+/**
+ * Go over the headers of the part and update
+ * the fields in "pp" according to what we find.
+ * If we are at the end of the headers (as indicated
+ * by an empty line), transition into next_state.
+ *
+ * @param ioffptr set to how many bytes have been
+ * processed
+ * @return MHD_YES if we can continue processing,
+ * MHD_NO on error or if we do not have
+ * enough data yet
+ */
+static int
+process_multipart_headers (struct MHD_PostProcessor *pp,
+ size_t *ioffptr, enum PP_State next_state)
+{
+ char *buf = (char *) &pp[1];
+ size_t newline;
+
+ newline = 0;
+ while ((newline < pp->buffer_pos) &&
+ (buf[newline] != '\r') && (buf[newline] != '\n'))
+ newline++;
+ if (newline == pp->buffer_size)
+ {
+ pp->state = PP_Error;
+ return MHD_NO; /* out of memory */
+ }
+ if (newline == pp->buffer_pos)
+ return MHD_NO; /* will need more data */
+ if (newline == 0)
+ {
+ /* empty line - end of headers */
+ pp->skip_rn = RN_Full;
+ pp->state = next_state;
+ return MHD_YES;
+ }
+ /* got an actual header */
+ if (buf[newline] == '\r')
+ pp->skip_rn = RN_OptN;
+ buf[newline] = '\0';
+ if (0 == strncasecmp ("Content-disposition: ",
+ buf, strlen ("Content-disposition: ")))
+ {
+ try_get_value (&buf[strlen ("Content-disposition: ")],
+ "name", &pp->content_name);
+ try_get_value (&buf[strlen ("Content-disposition: ")],
+ "filename", &pp->content_filename);
+ }
+ else
+ {
+ try_match_header ("Content-type: ", buf, &pp->content_type);
+ try_match_header ("Content-Transfer-Encoding: ",
+ buf, &pp->content_transfer_encoding);
+ }
+ (*ioffptr) += newline + 1;
+ return MHD_YES;
+}
+
+/**
+ * We have the value until we hit the given boundary;
+ * process accordingly.
+ *
+ * @param boundary the boundary to look for
+ * @param blen strlen(boundary)
+ * @param next_state what state to go into after the
+ * boundary was found
+ * @param next_dash_state state to go into if the next
+ * boundary ends with "--"
+ * @return MHD_YES if we can continue processing,
+ * MHD_NO on error or if we do not have
+ * enough data yet
+ */
+static int
+process_value_to_boundary (struct MHD_PostProcessor *pp,
+ size_t *ioffptr,
+ const char *boundary,
+ size_t blen,
+ enum PP_State next_state,
+ enum PP_State next_dash_state)
+{
+ char *buf = (char *) &pp[1];
+ size_t newline;
+
+ /* all data in buf until the boundary
+ (\r\n--+boundary) is part of the value */
+ newline = 0;
+ while (1)
+ {
+ while ((newline + 4 < pp->buffer_pos) &&
+ (0 != memcmp ("\r\n--", &buf[newline], 4)))
+ newline++;
+ if (newline + pp->blen + 4 <= pp->buffer_pos)
+ {
+ /* can check boundary */
+ if (0 != memcmp (&buf[newline + 4], boundary, pp->blen))
+ {
+ /* no boundary, "\r\n--" is part of content, skip */
+ newline += 4;
+ continue;
+ }
+ else
+ {
+ /* boundary found, process until newline then
+ skip boundary and go back to init */
+ pp->skip_rn = RN_Dash;
+ pp->state = next_state;
+ pp->dash_state = next_dash_state;
+ (*ioffptr) += pp->blen + 4; /* skip boundary as well */
+ break;
+ }
+ }
+ else
+ {
+ /* cannot check for boundary, process content that
+ we have and check again later; except, if we have
+ no content, abort (out of memory) */
+ if ((newline == 0) && (pp->buffer_pos == pp->buffer_size))
+ {
+ pp->state = PP_Error;
+ return MHD_NO;
+ }
+ break;
+ }
+ }
+ /* newline is either at beginning of boundary or
+ at least at the last character that we are sure
+ is not part of the boundary */
+ if (MHD_NO == pp->ikvi (pp->cls,
+ MHD_POSTDATA_KIND,
+ pp->content_name,
+ pp->content_filename,
+ pp->content_type,
+ pp->content_transfer_encoding,
+ buf, pp->value_offset, newline))
+ {
+ pp->state = PP_Error;
+ return MHD_NO;
+ }
+ pp->value_offset += newline;
+ (*ioffptr) += newline;
+ return MHD_YES;
+}
+
+static void
+free_unmarked (struct MHD_PostProcessor *pp)
+{
+ if ((pp->content_name != NULL) && (0 == (pp->have & NE_content_name)))
+ {
+ free (pp->content_name);
+ pp->content_name = NULL;
+ }
+ if ((pp->content_type != NULL) && (0 == (pp->have & NE_content_type)))
+ {
+ free (pp->content_type);
+ pp->content_type = NULL;
+ }
+ if ((pp->content_filename != NULL) &&
+ (0 == (pp->have & NE_content_filename)))
+ {
+ free (pp->content_filename);
+ pp->content_filename = NULL;
+ }
+ if ((pp->content_transfer_encoding != NULL) &&
+ (0 == (pp->have & NE_content_transfer_encoding)))
+ {
+ free (pp->content_transfer_encoding);
+ pp->content_transfer_encoding = NULL;
+ }
+}
+
+/**
+ * Decode multipart POST data.
+ */
+static int
+post_process_multipart (struct MHD_PostProcessor *pp,
+ const char *post_data,
+ size_t post_data_len)
+{
+ char *buf;
+ size_t max;
+ size_t ioff;
+ size_t poff;
+ int state_changed;
+
+ buf = (char *) &pp[1];
+ ioff = 0;
+ poff = 0;
+ state_changed = 1;
+ while ((poff < post_data_len) ||
+ ((pp->buffer_pos > 0) && (state_changed != 0)))
+ {
+ /* first, move as much input data
+ as possible to our internal buffer */
+ max = pp->buffer_size - pp->buffer_pos;
+ if (max > post_data_len - poff)
+ max = post_data_len - poff;
+ memcpy (&buf[pp->buffer_pos], &post_data[poff], max);
+ poff += max;
+ pp->buffer_pos += max;
+ if ((max == 0) && (state_changed == 0) && (poff < post_data_len))
+ {
+ pp->state = PP_Error;
+ return MHD_NO; /* out of memory */
+ }
+ state_changed = 0;
+
+ /* first state machine for '\r'-'\n' and '--' handling */
+ switch (pp->skip_rn)
+ {
+ case RN_Inactive:
+ break;
+ case RN_OptN:
+ if (buf[0] == '\n')
+ {
+ ioff++;
+ pp->skip_rn = RN_Inactive;
+ goto AGAIN;
+ }
+ case RN_Dash:
+ if (buf[0] == '-')
+ {
+ ioff++;
+ pp->skip_rn = RN_Dash2;
+ goto AGAIN;
+ }
+ pp->skip_rn = RN_Full;
+ /* fall-through! */
+ case RN_Full:
+ if (buf[0] == '\r')
+ {
+ if ((pp->buffer_pos > 1) && (buf[1] == '\n'))
+ {
+ pp->skip_rn = RN_Inactive;
+ ioff += 2;
+ }
+ else
+ {
+ pp->skip_rn = RN_OptN;
+ ioff++;
+ }
+ goto AGAIN;
+ }
+ if (buf[0] == '\n')
+ {
+ ioff++;
+ pp->skip_rn = RN_Inactive;
+ goto AGAIN;
+ }
+ pp->skip_rn = RN_Inactive;
+ pp->state = PP_Error;
+ return MHD_NO; /* no '\r\n' */
+ case RN_Dash2:
+ if (buf[0] == '-')
+ {
+ ioff++;
+ pp->skip_rn = RN_Full;
+ pp->state = pp->dash_state;
+ goto AGAIN;
+ }
+ pp->state = PP_Error;
+ break;
+ }
+
+ /* main state engine */
+ switch (pp->state)
+ {
+ case PP_Error:
+ return MHD_NO;
+ case PP_Done:
+ /* did not expect to receive more data */
+ pp->state = PP_Error;
+ return MHD_NO;
+ case PP_Init:
+ if (MHD_NO == find_boundary (pp,
+ pp->boundary,
+ pp->blen,
+ &ioff,
+ PP_ProcessEntryHeaders, PP_Done))
+ {
+ if (pp->state == PP_Error)
+ return MHD_NO;
+ goto END;
+ }
+ break;
+ case PP_ProcessEntryHeaders:
+ if (MHD_NO ==
+ process_multipart_headers (pp, &ioff, PP_PerformCheckMultipart))
+ {
+ if (pp->state == PP_Error)
+ return MHD_NO;
+ else
+ goto END;
+ }
+ state_changed = 1;
+ break;
+ case PP_PerformCheckMultipart:
+ if ((pp->content_type != NULL) &&
+ (0 == strncasecmp (pp->content_type,
+ "multipart/mixed",
+ strlen ("multipart/mixed"))))
+ {
+ pp->nested_boundary = strstr (pp->content_type, "boundary=");
+ if (pp->nested_boundary == NULL)
+ {
+ pp->state = PP_Error;
+ return MHD_NO;
+ }
+ pp->nested_boundary =
+ strdup (&pp->nested_boundary[strlen ("boundary=")]);
+ if (pp->nested_boundary == NULL)
+ {
+ /* out of memory */
+ pp->state = PP_Error;
+ return MHD_NO;
+ }
+ /* free old content type, we will need that field
+ for the content type of the nested elements */
+ free (pp->content_type);
+ pp->content_type = NULL;
+ pp->nlen = strlen (pp->nested_boundary);
+ pp->state = PP_Nested_Init;
+ state_changed = 1;
+ break;
+ }
+ pp->state = PP_ProcessValueToBoundary;
+ pp->value_offset = 0;
+ state_changed = 1;
+ break;
+ case PP_ProcessValueToBoundary:
+ if (MHD_NO == process_value_to_boundary (pp,
+ &ioff,
+ pp->boundary,
+ pp->blen,
+ PP_PerformCleanup,
+ PP_Done))
+ {
+ if (pp->state == PP_Error)
+ return MHD_NO;
+ break;
+ }
+ break;
+ case PP_PerformCleanup:
+ /* clean up state of one multipart form-data element! */
+ pp->have = NE_none;
+ free_unmarked (pp);
+ if (pp->nested_boundary != NULL)
+ {
+ free (pp->nested_boundary);
+ pp->nested_boundary = NULL;
+ }
+ pp->state = PP_ProcessEntryHeaders;
+ state_changed = 1;
+ break;
+ case PP_Nested_Init:
+ if (pp->nested_boundary == NULL)
+ {
+ pp->state = PP_Error;
+ return MHD_NO;
+ }
+ if (MHD_NO == find_boundary (pp,
+ pp->nested_boundary,
+ pp->nlen,
+ &ioff,
+ PP_Nested_PerformMarking,
+ PP_Init /* or PP_Error? */ ))
+ {
+ if (pp->state == PP_Error)
+ return MHD_NO;
+ goto END;
+ }
+ break;
+ case PP_Nested_PerformMarking:
+ /* remember what headers were given
+ globally */
+ pp->have = NE_none;
+ if (pp->content_name != NULL)
+ pp->have |= NE_content_name;
+ if (pp->content_type != NULL)
+ pp->have |= NE_content_type;
+ if (pp->content_filename != NULL)
+ pp->have |= NE_content_filename;
+ if (pp->content_transfer_encoding != NULL)
+ pp->have |= NE_content_transfer_encoding;
+ pp->state = PP_Nested_ProcessEntryHeaders;
+ state_changed = 1;
+ break;
+ case PP_Nested_ProcessEntryHeaders:
+ pp->value_offset = 0;
+ if (MHD_NO ==
+ process_multipart_headers (pp, &ioff,
+ PP_Nested_ProcessValueToBoundary))
+ {
+ if (pp->state == PP_Error)
+ return MHD_NO;
+ else
+ goto END;
+ }
+ state_changed = 1;
+ break;
+ case PP_Nested_ProcessValueToBoundary:
+ if (MHD_NO == process_value_to_boundary (pp,
+ &ioff,
+ pp->nested_boundary,
+ pp->nlen,
+ PP_Nested_PerformCleanup,
+ PP_Init))
+ {
+ if (pp->state == PP_Error)
+ return MHD_NO;
+ break;
+ }
+ break;
+ case PP_Nested_PerformCleanup:
+ free_unmarked (pp);
+ pp->state = PP_Nested_ProcessEntryHeaders;
+ state_changed = 1;
+ break;
+ default:
+ mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* should never happen! */
+ }
+ AGAIN:
+ if (ioff > 0)
+ {
+ memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
+ pp->buffer_pos -= ioff;
+ ioff = 0;
+ state_changed = 1;
+ }
+ }
+END:
+ if (ioff != 0)
+ {
+ memmove (buf, &buf[ioff], pp->buffer_pos - ioff);
+ pp->buffer_pos -= ioff;
+ }
+ if (poff < post_data_len)
+ {
+ pp->state = PP_Error;
+ return MHD_NO; /* serious error */
+ }
+ return MHD_YES;
+}
+
+/**
+ * Parse and process POST data.
+ * Call this function when POST data is available
+ * (usually during an MHD_AccessHandlerCallback)
+ * with the upload_data and upload_data_size.
+ * Whenever possible, this will then cause calls
+ * to the MHD_IncrementalKeyValueIterator.
+ *
+ * @param pp the post processor
+ * @param post_data post_data_len bytes of POST data
+ * @param post_data_len length of post_data
+ * @return MHD_YES on success, MHD_NO on error
+ * (out-of-memory, iterator aborted, parse error)
+ */
+int
+MHD_post_process (struct MHD_PostProcessor *pp,
+ const char *post_data, size_t post_data_len)
+{
+ if (post_data_len == 0)
+ return MHD_YES;
+ if (pp == NULL)
+ return MHD_NO;
+ if (0 == strncasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, pp->encoding,
+ strlen(MHD_HTTP_POST_ENCODING_FORM_URLENCODED)))
+ return post_process_urlencoded (pp, post_data, post_data_len);
+ if (0 ==
+ strncasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, pp->encoding,
+ strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA)))
+ return post_process_multipart (pp, post_data, post_data_len);
+ /* this should never be reached */
+ return MHD_NO;
+}
+
+/**
+ * Release PostProcessor resources.
+ */
+int
+MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
+{
+ int ret;
+
+ /* These internal strings need cleaning up since
+ the post-processing may have been interrupted
+ at any stage */
+ if ((pp->xbuf_pos > 0) || (pp->state != PP_Done))
+ ret = MHD_NO;
+ else
+ ret = MHD_YES;
+ pp->have = NE_none;
+ free_unmarked (pp);
+ if (pp->nested_boundary != NULL)
+ free (pp->nested_boundary);
+ free (pp);
+ return ret;
+}
+
+/* end of postprocessor.c */
diff --git a/lib/libmicrohttpd/src/daemon/postprocessor_large_test.c b/lib/libmicrohttpd/src/daemon/postprocessor_large_test.c
new file mode 100644
index 0000000000..6c1ea14566
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/postprocessor_large_test.c
@@ -0,0 +1,105 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file postprocessor_large_test.c
+ * @brief Testcase with very large input for postprocessor
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include "internal.h"
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int
+value_checker (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *data, uint64_t off, size_t size)
+{
+ unsigned int *pos = cls;
+#if 0
+ fprintf (stderr,
+ "VC: %llu %u `%s' `%s' `%s' `%s' `%.*s'\n",
+ off, size,
+ key, filename, content_type, transfer_encoding, size, data);
+#endif
+ if (size == 0)
+ return MHD_YES;
+ *pos += size;
+ return MHD_YES;
+
+}
+
+
+static int
+test_simple_large ()
+{
+ struct MHD_Connection connection;
+ struct MHD_HTTP_Header header;
+ struct MHD_PostProcessor *pp;
+ int i;
+ int delta;
+ size_t size;
+ char data[102400];
+ unsigned int pos;
+
+ pos = 0;
+ memset (data, 'A', sizeof (data));
+ memcpy (data, "key=", 4);
+ data[sizeof (data) - 1] = '\0';
+ memset (&connection, 0, sizeof (struct MHD_Connection));
+ memset (&header, 0, sizeof (struct MHD_HTTP_Header));
+ connection.headers_received = &header;
+ header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
+ header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
+ header.kind = MHD_HEADER_KIND;
+ pp = MHD_create_post_processor (&connection, 1024, &value_checker, &pos);
+ i = 0;
+ size = strlen (data);
+ while (i < size)
+ {
+ delta = 1 + RANDOM () % (size - i);
+ MHD_post_process (pp, &data[i], delta);
+ i += delta;
+ }
+ MHD_destroy_post_processor (pp);
+ if (pos != sizeof (data) - 5) /* minus 0-termination and 'key=' */
+ return 1;
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ errorCount += test_simple_large ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/daemon/postprocessor_test.c b/lib/libmicrohttpd/src/daemon/postprocessor_test.c
new file mode 100644
index 0000000000..f476dae6b8
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/postprocessor_test.c
@@ -0,0 +1,226 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file postprocessor_test.c
+ * @brief Testcase for postprocessor
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include "internal.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+/**
+ * Array of values that the value checker "wants".
+ * Each series of checks should be terminated by
+ * five NULL-entries.
+ */
+const char *want[] = {
+#define URL_DATA "abc=def&x=5"
+#define URL_START 0
+ "abc", NULL, NULL, NULL, "def",
+ "x", NULL, NULL, NULL, "5",
+#define URL_END (URL_START + 10)
+ NULL, NULL, NULL, NULL, NULL,
+#define FORM_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJoe Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata\r\n--AaB03x--\r\n"
+#define FORM_START (URL_END + 5)
+ "field1", NULL, NULL, NULL, "Joe Blow",
+ "pics", "file1.txt", "text/plain", "binary", "filedata",
+#define FORM_END (FORM_START + 10)
+ NULL, NULL, NULL, NULL, NULL,
+#define FORM_NESTED_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJane Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"\r\nContent-type: multipart/mixed, boundary=BbC04y\r\n\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\n\r\nfiledata1\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file2.gif\"\r\nContent-type: image/gif\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata2\r\n--BbC04y--\r\n--AaB03x--"
+#define FORM_NESTED_START (FORM_END + 5)
+ "field1", NULL, NULL, NULL, "Jane Blow",
+ "pics", "file1.txt", "text/plain", NULL, "filedata1",
+ "pics", "file2.gif", "image/gif", "binary", "filedata2",
+#define FORM_NESTED_END (FORM_NESTED_START + 15)
+ NULL, NULL, NULL, NULL, NULL,
+};
+
+static int
+mismatch (const char *a, const char *b)
+{
+ if (a == b)
+ return 0;
+ if ((a == NULL) || (b == NULL))
+ return 1;
+ return 0 != strcmp (a, b);
+}
+
+static int
+value_checker (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *data, uint64_t off, size_t size)
+{
+ int *want_off = cls;
+ int idx = *want_off;
+
+#if 0
+ fprintf (stderr,
+ "VC: `%s' `%s' `%s' `%s' `%.*s'\n",
+ key, filename, content_type, transfer_encoding, size, data);
+#endif
+ if (size == 0)
+ return MHD_YES;
+ if ((idx < 0) ||
+ (want[idx] == NULL) ||
+ (0 != strcmp (key, want[idx])) ||
+ (mismatch (filename, want[idx + 1])) ||
+ (mismatch (content_type, want[idx + 2])) ||
+ (mismatch (transfer_encoding, want[idx + 3])) ||
+ (0 != memcmp (data, &want[idx + 4][off], size)))
+ {
+ *want_off = -1;
+ return MHD_NO;
+ }
+ if (off + size == strlen (want[idx + 4]))
+ *want_off = idx + 5;
+ return MHD_YES;
+
+}
+
+
+static int
+test_urlencoding ()
+{
+ struct MHD_Connection connection;
+ struct MHD_HTTP_Header header;
+ struct MHD_PostProcessor *pp;
+ unsigned int want_off = URL_START;
+ int i;
+ int delta;
+ size_t size;
+
+ memset (&connection, 0, sizeof (struct MHD_Connection));
+ memset (&header, 0, sizeof (struct MHD_HTTP_Header));
+ connection.headers_received = &header;
+ header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
+ header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
+ header.kind = MHD_HEADER_KIND;
+ pp = MHD_create_post_processor (&connection,
+ 1024, &value_checker, &want_off);
+ i = 0;
+ size = strlen (URL_DATA);
+ while (i < size)
+ {
+ delta = 1 + RANDOM () % (size - i);
+ MHD_post_process (pp, &URL_DATA[i], delta);
+ i += delta;
+ }
+ MHD_destroy_post_processor (pp);
+ if (want_off != URL_END)
+ return 1;
+ return 0;
+}
+
+
+static int
+test_multipart ()
+{
+ struct MHD_Connection connection;
+ struct MHD_HTTP_Header header;
+ struct MHD_PostProcessor *pp;
+ unsigned int want_off = FORM_START;
+ int i;
+ int delta;
+ size_t size;
+
+ memset (&connection, 0, sizeof (struct MHD_Connection));
+ memset (&header, 0, sizeof (struct MHD_HTTP_Header));
+ connection.headers_received = &header;
+ header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
+ header.value =
+ MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
+ header.kind = MHD_HEADER_KIND;
+ pp = MHD_create_post_processor (&connection,
+ 1024, &value_checker, &want_off);
+ i = 0;
+ size = strlen (FORM_DATA);
+ while (i < size)
+ {
+ delta = 1 + RANDOM () % (size - i);
+ MHD_post_process (pp, &FORM_DATA[i], delta);
+ i += delta;
+ }
+ MHD_destroy_post_processor (pp);
+ if (want_off != FORM_END)
+ return 2;
+ return 0;
+}
+
+
+static int
+test_nested_multipart ()
+{
+ struct MHD_Connection connection;
+ struct MHD_HTTP_Header header;
+ struct MHD_PostProcessor *pp;
+ unsigned int want_off = FORM_NESTED_START;
+ int i;
+ int delta;
+ size_t size;
+
+ memset (&connection, 0, sizeof (struct MHD_Connection));
+ memset (&header, 0, sizeof (struct MHD_HTTP_Header));
+ connection.headers_received = &header;
+ header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
+ header.value =
+ MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
+ header.kind = MHD_HEADER_KIND;
+ pp = MHD_create_post_processor (&connection,
+ 1024, &value_checker, &want_off);
+ i = 0;
+ size = strlen (FORM_NESTED_DATA);
+ while (i < size)
+ {
+ delta = 1 + RANDOM () % (size - i);
+ MHD_post_process (pp, &FORM_NESTED_DATA[i], delta);
+ i += delta;
+ }
+ MHD_destroy_post_processor (pp);
+ if (want_off != FORM_NESTED_END)
+ return 4;
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ errorCount += test_urlencoding ();
+ errorCount += test_multipart ();
+ errorCount += test_nested_multipart ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/daemon/reason_phrase.c b/lib/libmicrohttpd/src/daemon/reason_phrase.c
new file mode 100644
index 0000000000..c02a0965da
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/reason_phrase.c
@@ -0,0 +1,128 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Lymba
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file reason_phrase.c
+ * @brief Tables of the string response phrases
+ * @author Elliot Glaysher
+ * @author Christian Grothoff (minor code clean up)
+ */
+
+#include "reason_phrase.h"
+
+#ifndef NULL
+#define NULL (void*)0
+#endif // !NULL
+
+static const char *invalid_hundred[] = { NULL };
+
+static const char *one_hundred[] = {
+ "Continue",
+ "Switching Protocols",
+ "Processing"
+};
+
+static const char *two_hundred[] = {
+ "OK",
+ "Created",
+ "Accepted",
+ "Non-Authoritative Information",
+ "No Content",
+ "Reset Content",
+ "Partial Content",
+ "Multi Status"
+};
+
+static const char *three_hundred[] = {
+ "Multiple Choices",
+ "Moved Permanently",
+ "Moved Temporarily",
+ "See Other",
+ "Not Modified",
+ "Use Proxy",
+ "Switch Proxy",
+ "Temporary Redirect"
+};
+
+static const char *four_hundred[] = {
+ "Bad Request",
+ "Unauthorized",
+ "Payment Required",
+ "Forbidden",
+ "Not Found",
+ "Method Not Allowed",
+ "Not Acceptable",
+ "Proxy Authentication Required",
+ "Request Time-out",
+ "Conflict",
+ "Gone",
+ "Length Required",
+ "Precondition Failed",
+ "Request Entity Too Large",
+ "Request-URI Too Large",
+ "Unsupported Media Type",
+ "Requested Range Not Satisfiable",
+ "Expectation Failed",
+ "Unprocessable Entity",
+ "Locked",
+ "Failed Dependency",
+ "Unordered Collection",
+ "Upgrade Required",
+ "Retry With"
+};
+
+static const char *five_hundred[] = {
+ "Internal Server Error",
+ "Not Implemented",
+ "Bad Gateway",
+ "Service Unavailable",
+ "Gateway Time-out",
+ "HTTP Version not supported",
+ "Variant Also Negotiates",
+ "Insufficient Storage",
+ "Bandwidth Limit Exceeded",
+ "Not Extended"
+};
+
+
+struct MHD_Reason_Block
+{
+ unsigned int max;
+ const char **data;
+};
+
+#define BLOCK(m) { (sizeof(m) / sizeof(char*)), m }
+
+static const struct MHD_Reason_Block reasons[] = {
+ BLOCK (invalid_hundred),
+ BLOCK (one_hundred),
+ BLOCK (two_hundred),
+ BLOCK (three_hundred),
+ BLOCK (four_hundred),
+ BLOCK (five_hundred),
+};
+
+const char *
+MHD_get_reason_phrase_for (unsigned int code)
+{
+ if ((code >= 100 && code < 600) && (reasons[code / 100].max > code % 100))
+ return reasons[code / 100].data[code % 100];
+ return "Unknown";
+}
diff --git a/lib/libmicrohttpd/src/daemon/reason_phrase.h b/lib/libmicrohttpd/src/daemon/reason_phrase.h
new file mode 100644
index 0000000000..20c11d52c7
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/reason_phrase.h
@@ -0,0 +1,37 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Lymba
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file reason_phrase.c
+ * @brief Tables of the string response phrases
+ * @author Elliot Glaysher
+ */
+
+#ifndef REASON_PHRASE_H
+#define REASON_PHRASE_H
+
+/**
+ * Returns the string reason phrase for a response code.
+ *
+ * If we don't have a string for a status code, we give the first
+ * message in that status code class.
+ */
+const char *MHD_get_reason_phrase_for (unsigned int code);
+
+#endif
diff --git a/lib/libmicrohttpd/src/daemon/response.c b/lib/libmicrohttpd/src/daemon/response.c
new file mode 100644
index 0000000000..a10dbc4fd0
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/response.c
@@ -0,0 +1,303 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file response.c
+ * @brief Methods for managing response objects
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#include "internal.h"
+#include "response.h"
+
+/**
+ * Add a header line to the response.
+ *
+ * @return MHD_NO on error (i.e. invalid header or content format).
+ */
+int
+MHD_add_response_header (struct MHD_Response *response,
+ const char *header, const char *content)
+{
+ struct MHD_HTTP_Header *hdr;
+
+ if ((response == NULL) ||
+ (header == NULL) ||
+ (content == NULL) ||
+ (strlen (header) == 0) ||
+ (strlen (content) == 0) ||
+ (NULL != strstr (header, "\t")) ||
+ (NULL != strstr (header, "\r")) ||
+ (NULL != strstr (header, "\n")) ||
+ (NULL != strstr (content, "\t")) ||
+ (NULL != strstr (content, "\r")) || (NULL != strstr (content, "\n")))
+ return MHD_NO;
+ hdr = malloc (sizeof (struct MHD_HTTP_Header));
+ if (hdr == NULL)
+ return MHD_NO;
+ hdr->header = strdup (header);
+ if (hdr->header == NULL)
+ {
+ free (hdr);
+ return MHD_NO;
+ }
+ hdr->value = strdup (content);
+ if (hdr->value == NULL)
+ {
+ free (hdr->header);
+ free (hdr);
+ return MHD_NO;
+ }
+ hdr->kind = MHD_HEADER_KIND;
+ hdr->next = response->first_header;
+ response->first_header = hdr;
+ return MHD_YES;
+}
+
+/**
+ * Delete a header line from the response.
+ *
+ * @return MHD_NO on error (no such header known)
+ */
+int
+MHD_del_response_header (struct MHD_Response *response,
+ const char *header, const char *content)
+{
+ struct MHD_HTTP_Header *pos;
+ struct MHD_HTTP_Header *prev;
+
+ if ((header == NULL) || (content == NULL))
+ return MHD_NO;
+ prev = NULL;
+ pos = response->first_header;
+ while (pos != NULL)
+ {
+ if ((0 == strcmp (header, pos->header)) &&
+ (0 == strcmp (content, pos->value)))
+ {
+ free (pos->header);
+ free (pos->value);
+ if (prev == NULL)
+ response->first_header = pos->next;
+ else
+ prev->next = pos->next;
+ free (pos);
+ return MHD_YES;
+ }
+ prev = pos;
+ pos = pos->next;
+ }
+ return MHD_NO;
+}
+
+/**
+ * Get all of the headers added to a response.
+ *
+ * @param iterator callback to call on each header;
+ * maybe NULL (then just count headers)
+ * @param iterator_cls extra argument to iterator
+ * @return number of entries iterated over
+ */
+int
+MHD_get_response_headers (struct MHD_Response *response,
+ MHD_KeyValueIterator iterator, void *iterator_cls)
+{
+ struct MHD_HTTP_Header *pos;
+ int numHeaders = 0;
+ pos = response->first_header;
+ while (pos != NULL)
+ {
+ numHeaders++;
+ if ((iterator != NULL) &&
+ (MHD_YES != iterator (iterator_cls,
+ pos->kind, pos->header, pos->value)))
+ break;
+ pos = pos->next;
+ }
+ return numHeaders;
+}
+
+
+/**
+ * Get a particular header from the response.
+ *
+ * @param key which header to get
+ * @return NULL if header does not exist
+ */
+const char *
+MHD_get_response_header (struct MHD_Response *response, const char *key)
+{
+ struct MHD_HTTP_Header *pos;
+
+ if (key == NULL)
+ return NULL;
+ pos = response->first_header;
+ while (pos != NULL)
+ {
+ if (0 == strcmp (key, pos->header))
+ return pos->value;
+ pos = pos->next;
+ }
+ return NULL;
+}
+
+
+/**
+ * Create a response object. The response object can be extended with
+ * header information and then be used any number of times.
+ *
+ * @param size size of the data portion of the response, -1 for unknown
+ * @param block_size preferred block size for querying crc (advisory only,
+ * MHD may still call crc using smaller chunks); this
+ * is essentially the buffer size used for IO, clients
+ * should pick a value that is appropriate for IO and
+ * memory performance requirements
+ * @param crc callback to use to obtain response data
+ * @param crc_cls extra argument to crc
+ * @param crfc callback to call to free crc_cls resources
+ * @return NULL on error (i.e. invalid arguments, out of memory)
+ */
+struct MHD_Response *
+MHD_create_response_from_callback (uint64_t size,
+ size_t block_size,
+ MHD_ContentReaderCallback crc,
+ void *crc_cls,
+ MHD_ContentReaderFreeCallback crfc)
+{
+ struct MHD_Response *retVal;
+
+ if ((crc == NULL) || (block_size == 0))
+ return NULL;
+ retVal = malloc (sizeof (struct MHD_Response) + block_size);
+ if (retVal == NULL)
+ return NULL;
+ memset (retVal, 0, sizeof (struct MHD_Response));
+ retVal->data = (void *) &retVal[1];
+ retVal->data_buffer_size = block_size;
+ if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
+ {
+ free (retVal);
+ return NULL;
+ }
+ retVal->crc = crc;
+ retVal->crfc = crfc;
+ retVal->crc_cls = crc_cls;
+ retVal->reference_count = 1;
+ retVal->total_size = size;
+ return retVal;
+}
+
+/**
+ * Create a response object. The response object can be extended with
+ * header information and then be used any number of times.
+ *
+ * @param size size of the data portion of the response
+ * @param data the data itself
+ * @param must_free libmicrohttpd should free data when done
+ * @param must_copy libmicrohttpd must make a copy of data
+ * right away, the data maybe released anytime after
+ * this call returns
+ * @return NULL on error (i.e. invalid arguments, out of memory)
+ */
+struct MHD_Response *
+MHD_create_response_from_data (size_t size,
+ void *data, int must_free, int must_copy)
+{
+ struct MHD_Response *retVal;
+ void *tmp;
+
+ if ((data == NULL) && (size > 0))
+ return NULL;
+ retVal = malloc (sizeof (struct MHD_Response));
+ if (retVal == NULL)
+ return NULL;
+ memset (retVal, 0, sizeof (struct MHD_Response));
+ if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
+ {
+ free (retVal);
+ return NULL;
+ }
+ if ((must_copy) && (size > 0))
+ {
+ tmp = malloc (size);
+ if (tmp == NULL)
+ {
+ free (retVal);
+ return NULL;
+ }
+ memcpy (tmp, data, size);
+ must_free = 1;
+ data = tmp;
+ }
+ retVal->crc = NULL;
+ retVal->crfc = must_free ? &free : NULL;
+ retVal->crc_cls = must_free ? data : NULL;
+ retVal->reference_count = 1;
+ retVal->total_size = size;
+ retVal->data = data;
+ retVal->data_size = size;
+ return retVal;
+}
+
+/**
+ * Destroy a response object and associated resources. Note that
+ * libmicrohttpd may keep some of the resources around if the response
+ * is still in the queue for some clients, so the memory may not
+ * necessarily be freed immediatley.
+ */
+void
+MHD_destroy_response (struct MHD_Response *response)
+{
+ struct MHD_HTTP_Header *pos;
+
+ if (response == NULL)
+ return;
+ pthread_mutex_lock (&response->mutex);
+ if (0 != --response->reference_count)
+ {
+ pthread_mutex_unlock (&response->mutex);
+ return;
+ }
+ pthread_mutex_unlock (&response->mutex);
+ pthread_mutex_destroy (&response->mutex);
+ if (response->crfc != NULL)
+ response->crfc (response->crc_cls);
+ while (response->first_header != NULL)
+ {
+ pos = response->first_header;
+ response->first_header = pos->next;
+ free (pos->header);
+ free (pos->value);
+ free (pos);
+ }
+ free (response);
+}
+
+
+void
+MHD_increment_response_rc (struct MHD_Response *response)
+{
+ pthread_mutex_lock (&response->mutex);
+ response->reference_count++;
+ pthread_mutex_unlock (&response->mutex);
+}
+
+
+/* end of response.c */
diff --git a/lib/libmicrohttpd/src/daemon/response.h b/lib/libmicrohttpd/src/daemon/response.h
new file mode 100644
index 0000000000..ec1b387805
--- /dev/null
+++ b/lib/libmicrohttpd/src/daemon/response.h
@@ -0,0 +1,37 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file response.h
+ * @brief Methods for managing response objects
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#ifndef RESPONSE_H
+#define RESPONSE_H
+
+/**
+ * Increment response RC. Should this be part of the
+ * public API?
+ */
+void MHD_increment_response_rc (struct MHD_Response *response);
+
+
+#endif
diff --git a/lib/libmicrohttpd/src/examples/Makefile.am b/lib/libmicrohttpd/src/examples/Makefile.am
new file mode 100644
index 0000000000..9ed9aaafe8
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/Makefile.am
@@ -0,0 +1,70 @@
+SUBDIRS = .
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https \
+ @LIBGCRYPT_CFLAGS@
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage
+endif
+
+# example programs
+noinst_PROGRAMS = \
+authorization_example \
+minimal_example \
+minimal_example_comet \
+querystring_example \
+fileserver_example \
+fileserver_example_dirs \
+fileserver_example_external_select \
+refuse_post_example
+
+if ENABLE_HTTPS
+noinst_PROGRAMS += https_fileserver_example
+endif
+
+minimal_example_SOURCES = \
+ minimal_example.c
+minimal_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+minimal_example_comet_SOURCES = \
+ minimal_example_comet.c
+minimal_example_comet_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+authorization_example_SOURCES = \
+ authorization_example.c
+authorization_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+refuse_post_example_SOURCES = \
+ refuse_post_example.c
+refuse_post_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+querystring_example_SOURCES = \
+ querystring_example.c
+querystring_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+fileserver_example_SOURCES = \
+ fileserver_example.c
+fileserver_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+fileserver_example_dirs_SOURCES = \
+ fileserver_example_dirs.c
+fileserver_example_dirs_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+fileserver_example_external_select_SOURCES = \
+ fileserver_example_external_select.c
+fileserver_example_external_select_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+https_fileserver_example_SOURCES = \
+https_fileserver_example.c
+https_fileserver_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
diff --git a/lib/libmicrohttpd/src/examples/Makefile.in b/lib/libmicrohttpd/src/examples/Makefile.in
new file mode 100644
index 0000000000..26cc59aa99
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/Makefile.in
@@ -0,0 +1,791 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = authorization_example$(EXEEXT) \
+ minimal_example$(EXEEXT) minimal_example_comet$(EXEEXT) \
+ querystring_example$(EXEEXT) fileserver_example$(EXEEXT) \
+ fileserver_example_dirs$(EXEEXT) \
+ fileserver_example_external_select$(EXEEXT) \
+ refuse_post_example$(EXEEXT) $(am__EXEEXT_1)
+@ENABLE_HTTPS_TRUE@am__append_1 = https_fileserver_example
+subdir = src/examples
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@ENABLE_HTTPS_TRUE@am__EXEEXT_1 = https_fileserver_example$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+am_authorization_example_OBJECTS = authorization_example.$(OBJEXT)
+authorization_example_OBJECTS = $(am_authorization_example_OBJECTS)
+authorization_example_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_fileserver_example_OBJECTS = fileserver_example.$(OBJEXT)
+fileserver_example_OBJECTS = $(am_fileserver_example_OBJECTS)
+fileserver_example_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_fileserver_example_dirs_OBJECTS = \
+ fileserver_example_dirs.$(OBJEXT)
+fileserver_example_dirs_OBJECTS = \
+ $(am_fileserver_example_dirs_OBJECTS)
+fileserver_example_dirs_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_fileserver_example_external_select_OBJECTS = \
+ fileserver_example_external_select.$(OBJEXT)
+fileserver_example_external_select_OBJECTS = \
+ $(am_fileserver_example_external_select_OBJECTS)
+fileserver_example_external_select_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_https_fileserver_example_OBJECTS = \
+ https_fileserver_example.$(OBJEXT)
+https_fileserver_example_OBJECTS = \
+ $(am_https_fileserver_example_OBJECTS)
+https_fileserver_example_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_minimal_example_OBJECTS = minimal_example.$(OBJEXT)
+minimal_example_OBJECTS = $(am_minimal_example_OBJECTS)
+minimal_example_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_minimal_example_comet_OBJECTS = minimal_example_comet.$(OBJEXT)
+minimal_example_comet_OBJECTS = $(am_minimal_example_comet_OBJECTS)
+minimal_example_comet_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_querystring_example_OBJECTS = querystring_example.$(OBJEXT)
+querystring_example_OBJECTS = $(am_querystring_example_OBJECTS)
+querystring_example_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_refuse_post_example_OBJECTS = refuse_post_example.$(OBJEXT)
+refuse_post_example_OBJECTS = $(am_refuse_post_example_OBJECTS)
+refuse_post_example_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(authorization_example_SOURCES) \
+ $(fileserver_example_SOURCES) \
+ $(fileserver_example_dirs_SOURCES) \
+ $(fileserver_example_external_select_SOURCES) \
+ $(https_fileserver_example_SOURCES) $(minimal_example_SOURCES) \
+ $(minimal_example_comet_SOURCES) \
+ $(querystring_example_SOURCES) $(refuse_post_example_SOURCES)
+DIST_SOURCES = $(authorization_example_SOURCES) \
+ $(fileserver_example_SOURCES) \
+ $(fileserver_example_dirs_SOURCES) \
+ $(fileserver_example_external_select_SOURCES) \
+ $(https_fileserver_example_SOURCES) $(minimal_example_SOURCES) \
+ $(minimal_example_comet_SOURCES) \
+ $(querystring_example_SOURCES) $(refuse_post_example_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https \
+ @LIBGCRYPT_CFLAGS@
+
+@USE_COVERAGE_TRUE@AM_CFLAGS = --coverage
+minimal_example_SOURCES = \
+ minimal_example.c
+
+minimal_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+minimal_example_comet_SOURCES = \
+ minimal_example_comet.c
+
+minimal_example_comet_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+authorization_example_SOURCES = \
+ authorization_example.c
+
+authorization_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+refuse_post_example_SOURCES = \
+ refuse_post_example.c
+
+refuse_post_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+querystring_example_SOURCES = \
+ querystring_example.c
+
+querystring_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+fileserver_example_SOURCES = \
+ fileserver_example.c
+
+fileserver_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+fileserver_example_dirs_SOURCES = \
+ fileserver_example_dirs.c
+
+fileserver_example_dirs_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+fileserver_example_external_select_SOURCES = \
+ fileserver_example_external_select.c
+
+fileserver_example_external_select_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+https_fileserver_example_SOURCES = \
+https_fileserver_example.c
+
+https_fileserver_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/examples/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/examples/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+authorization_example$(EXEEXT): $(authorization_example_OBJECTS) $(authorization_example_DEPENDENCIES)
+ @rm -f authorization_example$(EXEEXT)
+ $(LINK) $(authorization_example_OBJECTS) $(authorization_example_LDADD) $(LIBS)
+fileserver_example$(EXEEXT): $(fileserver_example_OBJECTS) $(fileserver_example_DEPENDENCIES)
+ @rm -f fileserver_example$(EXEEXT)
+ $(LINK) $(fileserver_example_OBJECTS) $(fileserver_example_LDADD) $(LIBS)
+fileserver_example_dirs$(EXEEXT): $(fileserver_example_dirs_OBJECTS) $(fileserver_example_dirs_DEPENDENCIES)
+ @rm -f fileserver_example_dirs$(EXEEXT)
+ $(LINK) $(fileserver_example_dirs_OBJECTS) $(fileserver_example_dirs_LDADD) $(LIBS)
+fileserver_example_external_select$(EXEEXT): $(fileserver_example_external_select_OBJECTS) $(fileserver_example_external_select_DEPENDENCIES)
+ @rm -f fileserver_example_external_select$(EXEEXT)
+ $(LINK) $(fileserver_example_external_select_OBJECTS) $(fileserver_example_external_select_LDADD) $(LIBS)
+https_fileserver_example$(EXEEXT): $(https_fileserver_example_OBJECTS) $(https_fileserver_example_DEPENDENCIES)
+ @rm -f https_fileserver_example$(EXEEXT)
+ $(LINK) $(https_fileserver_example_OBJECTS) $(https_fileserver_example_LDADD) $(LIBS)
+minimal_example$(EXEEXT): $(minimal_example_OBJECTS) $(minimal_example_DEPENDENCIES)
+ @rm -f minimal_example$(EXEEXT)
+ $(LINK) $(minimal_example_OBJECTS) $(minimal_example_LDADD) $(LIBS)
+minimal_example_comet$(EXEEXT): $(minimal_example_comet_OBJECTS) $(minimal_example_comet_DEPENDENCIES)
+ @rm -f minimal_example_comet$(EXEEXT)
+ $(LINK) $(minimal_example_comet_OBJECTS) $(minimal_example_comet_LDADD) $(LIBS)
+querystring_example$(EXEEXT): $(querystring_example_OBJECTS) $(querystring_example_DEPENDENCIES)
+ @rm -f querystring_example$(EXEEXT)
+ $(LINK) $(querystring_example_OBJECTS) $(querystring_example_LDADD) $(LIBS)
+refuse_post_example$(EXEEXT): $(refuse_post_example_OBJECTS) $(refuse_post_example_DEPENDENCIES)
+ @rm -f refuse_post_example$(EXEEXT)
+ $(LINK) $(refuse_post_example_OBJECTS) $(refuse_post_example_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authorization_example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileserver_example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileserver_example_dirs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileserver_example_external_select.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/https_fileserver_example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimal_example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimal_example_comet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/querystring_example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refuse_post_example.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-noinstPROGRAMS ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/examples/authorization_example.c b/lib/libmicrohttpd/src/examples/authorization_example.c
new file mode 100644
index 0000000000..b271053eee
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/authorization_example.c
@@ -0,0 +1,102 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file authorization_example.c
+ * @brief example for how to use libmicrohttpd with HTTP authentication
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+
+#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
+
+#define DENIED "<html><head><title>Access denied</title></head><body>Access denied</body></html>"
+
+
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+ int code;
+ const char *auth;
+
+ if (0 != strcmp (method, "GET"))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ auth = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_AUTHORIZATION);
+ if ((auth == NULL) ||
+ (0 != strcmp (auth, "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==")))
+ {
+ /* require: "Aladdin" with password "open sesame" */
+ response = MHD_create_response_from_data (strlen (DENIED),
+ (void *) DENIED, MHD_NO,
+ MHD_NO);
+ MHD_add_response_header (response, MHD_HTTP_HEADER_WWW_AUTHENTICATE,
+ "Basic realm=\"TestRealm\"");
+ code = MHD_HTTP_UNAUTHORIZED;
+ }
+ else
+ {
+ response = MHD_create_response_from_data (strlen (me),
+ (void *) me, MHD_NO, MHD_NO);
+ code = MHD_HTTP_OK;
+ }
+ ret = MHD_queue_response (connection, code, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/fileserver_example.c b/lib/libmicrohttpd/src/examples/fileserver_example.c
new file mode 100644
index 0000000000..76a10f2f09
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/fileserver_example.c
@@ -0,0 +1,106 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file fileserver_example.c
+ * @brief minimal example for how to use libmicrohttpd to serve files
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+#include <unistd.h>
+
+#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
+
+static int
+file_reader (void *cls, uint64_t pos, char *buf, int max)
+{
+ FILE *file = cls;
+
+ fseek (file, pos, SEEK_SET);
+ return fread (buf, 1, max, file);
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ struct MHD_Response *response;
+ int ret;
+ FILE *file;
+ struct stat buf;
+
+ if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ file = fopen (&url[1], "rb");
+ if (file == NULL)
+ {
+ response = MHD_create_response_from_data (strlen (PAGE),
+ (void *) PAGE,
+ MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
+ MHD_destroy_response (response);
+ }
+ else
+ {
+ stat (&url[1], &buf);
+ response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
+ &file_reader,
+ file,
+ (MHD_ContentReaderFreeCallback)
+ & fclose);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ }
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/fileserver_example_dirs.c b/lib/libmicrohttpd/src/examples/fileserver_example_dirs.c
new file mode 100644
index 0000000000..04519c63ea
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/fileserver_example_dirs.c
@@ -0,0 +1,129 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file fileserver_example.c
+ * @brief example for how to use libmicrohttpd to serve files (with directory support)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <dirent.h>
+#include <microhttpd.h>
+#include <unistd.h>
+
+#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
+
+static int
+file_reader (void *cls, uint64_t pos, char *buf, int max)
+{
+ FILE *file = cls;
+
+ fseek (file, pos, SEEK_SET);
+ return fread (buf, 1, max, file);
+}
+
+
+static int
+dir_reader (void *cls, uint64_t pos, char *buf, int max)
+{
+ struct dirent *e;
+ if (max < 512)
+ return 0;
+ do
+ {
+ e = readdir (cls);
+ if (e == NULL)
+ return -1;
+ } while (e->d_name[0] == '.');
+ return snprintf (buf, max,
+ "<a href=\"/%s\">%s</a><br>",
+ e->d_name,
+ e->d_name);
+}
+
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ struct MHD_Response *response;
+ int ret;
+ FILE *file;
+ struct stat buf;
+
+ if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ file = fopen (&url[1], "rb");
+ if (file == NULL)
+ {
+ response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
+ 32 * 1024,
+ &dir_reader,
+ opendir ("."),
+ (MHD_ContentReaderFreeCallback) &closedir);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ }
+ else
+ {
+ stat (&url[1], &buf);
+ response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
+ &file_reader,
+ file,
+ (MHD_ContentReaderFreeCallback)
+ & fclose);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ }
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 2)
+ {
+ printf ("%s PORT\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ while (1) sleep (1);
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/fileserver_example_external_select.c b/lib/libmicrohttpd/src/examples/fileserver_example_external_select.c
new file mode 100644
index 0000000000..6867335b1b
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/fileserver_example_external_select.c
@@ -0,0 +1,136 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ * @file fileserver_example_external_select.c
+ * @brief minimal example for how to use libmicrohttpd to server files
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
+
+static int
+file_reader (void *cls, uint64_t pos, char *buf, int max)
+{
+ FILE *file = cls;
+
+ fseek (file, pos, SEEK_SET);
+ return fread (buf, 1, max, file);
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ struct MHD_Response *response;
+ int ret;
+ FILE *file;
+ struct stat buf;
+
+ if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ file = fopen (&url[1], "rb");
+ if (file == NULL)
+ {
+ response = MHD_create_response_from_data (strlen (PAGE),
+ (void *) PAGE,
+ MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
+ MHD_destroy_response (response);
+ }
+ else
+ {
+ stat (&url[1], &buf);
+ response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k page size */
+ &file_reader,
+ file,
+ (MHD_ContentReaderFreeCallback)
+ & fclose);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ }
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+ time_t end;
+ time_t t;
+ struct timeval tv;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ unsigned long long mhd_timeout;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ end = time (NULL) + atoi (argv[2]);
+ while ((t = time (NULL)) < end)
+ {
+ tv.tv_sec = end - t;
+ tv.tv_usec = 0;
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ break; /* fatal internal error */
+ if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)
+
+ {
+ if (tv.tv_sec * 1000 < mhd_timeout)
+ {
+ tv.tv_sec = mhd_timeout / 1000;
+ tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
+ }
+ }
+ select (max + 1, &rs, &ws, &es, &tv);
+ MHD_run (d);
+ }
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/https_fileserver_example.c b/lib/libmicrohttpd/src/examples/https_fileserver_example.c
new file mode 100644
index 0000000000..9f9728ddc6
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/https_fileserver_example.c
@@ -0,0 +1,194 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ * @file https_server_example.c
+ * @brief a simple HTTPS file server using TLS.
+ *
+ * Usage :
+ *
+ * 'http_fileserver_example HTTP-PORT SECONDS-TO-RUN'
+ *
+ * The certificate & key are required by the server to operate, Omitting the
+ * path arguments will cause the server to use the hard coded example certificate & key.
+ *
+ * 'certtool' may be used to generate these if required.
+ *
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+#include <sys/stat.h>
+
+#include "gnutls.h"
+#include <gcrypt.h>
+
+#define BUF_SIZE 1024
+#define MAX_URL_LEN 255
+
+// TODO remove if unused
+#define CAFILE "ca.pem"
+#define CRLFILE "crl.pem"
+
+#define EMPTY_PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
+
+/* Test Certificate */
+const char cert_pem[] =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIICpjCCAZCgAwIBAgIESEPtjjALBgkqhkiG9w0BAQUwADAeFw0wODA2MDIxMjU0\n"
+ "MzhaFw0wOTA2MDIxMjU0NDZaMAAwggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKC\n"
+ "AQC03TyUvK5HmUAirRp067taIEO4bibh5nqolUoUdo/LeblMQV+qnrv/RNAMTx5X\n"
+ "fNLZ45/kbM9geF8qY0vsPyQvP4jumzK0LOJYuIwmHaUm9vbXnYieILiwCuTgjaud\n"
+ "3VkZDoQ9fteIo+6we9UTpVqZpxpbLulBMh/VsvX0cPJ1VFC7rT59o9hAUlFf9jX/\n"
+ "GmKdYI79MtgVx0OPBjmmSD6kicBBfmfgkO7bIGwlRtsIyMznxbHu6VuoX/eVxrTv\n"
+ "rmCwgEXLWRZ6ru8MQl5YfqeGXXRVwMeXU961KefbuvmEPccgCxm8FZ1C1cnDHFXh\n"
+ "siSgAzMBjC/b6KVhNQ4KnUdZAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0O\n"
+ "BBYEFJcUvpjvE5fF/yzUshkWDpdYiQh/MAsGCSqGSIb3DQEBBQOCAQEARP7eKSB2\n"
+ "RNd6XjEjK0SrxtoTnxS3nw9sfcS7/qD1+XHdObtDFqGNSjGYFB3Gpx8fpQhCXdoN\n"
+ "8QUs3/5ZVa5yjZMQewWBgz8kNbnbH40F2y81MHITxxCe1Y+qqHWwVaYLsiOTqj2/\n"
+ "0S3QjEJ9tvklmg7JX09HC4m5QRYfWBeQLD1u8ZjA1Sf1xJriomFVyRLI2VPO2bNe\n"
+ "JDMXWuP+8kMC7gEvUnJ7A92Y2yrhu3QI3bjPk8uSpHea19Q77tul1UVBJ5g+zpH3\n"
+ "OsF5p0MyaVf09GTzcLds5nE/osTdXGUyHJapWReVmPm3Zn6gqYlnzD99z+DPIgIV\n"
+ "RhZvQx74NQnS6g==\n" "-----END CERTIFICATE-----\n";
+
+const char key_pem[] =
+ "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIIEowIBAAKCAQEAtN08lLyuR5lAIq0adOu7WiBDuG4m4eZ6qJVKFHaPy3m5TEFf\n"
+ "qp67/0TQDE8eV3zS2eOf5GzPYHhfKmNL7D8kLz+I7psytCziWLiMJh2lJvb2152I\n"
+ "niC4sArk4I2rnd1ZGQ6EPX7XiKPusHvVE6VamacaWy7pQTIf1bL19HDydVRQu60+\n"
+ "faPYQFJRX/Y1/xpinWCO/TLYFcdDjwY5pkg+pInAQX5n4JDu2yBsJUbbCMjM58Wx\n"
+ "7ulbqF/3lca0765gsIBFy1kWeq7vDEJeWH6nhl10VcDHl1PetSnn27r5hD3HIAsZ\n"
+ "vBWdQtXJwxxV4bIkoAMzAYwv2+ilYTUOCp1HWQIDAQABAoIBAArOQv3R7gmqDspj\n"
+ "lDaTFOz0C4e70QfjGMX0sWnakYnDGn6DU19iv3GnX1S072ejtgc9kcJ4e8VUO79R\n"
+ "EmqpdRR7k8dJr3RTUCyjzf/C+qiCzcmhCFYGN3KRHA6MeEnkvRuBogX4i5EG1k5l\n"
+ "/5t+YBTZBnqXKWlzQLKoUAiMLPg0eRWh+6q7H4N7kdWWBmTpako7TEqpIwuEnPGx\n"
+ "u3EPuTR+LN6lF55WBePbCHccUHUQaXuav18NuDkcJmCiMArK9SKb+h0RqLD6oMI/\n"
+ "dKD6n8cZXeMBkK+C8U/K0sN2hFHACsu30b9XfdnljgP9v+BP8GhnB0nCB6tNBCPo\n"
+ "32srOwECgYEAxWh3iBT4lWqL6bZavVbnhmvtif4nHv2t2/hOs/CAq8iLAw0oWGZc\n"
+ "+JEZTUDMvFRlulr0kcaWra+4fN3OmJnjeuFXZq52lfMgXBIKBmoSaZpIh2aDY1Rd\n"
+ "RbEse7nQl9hTEPmYspiXLGtnAXW7HuWqVfFFP3ya8rUS3t4d07Hig8ECgYEA6ou6\n"
+ "OHiBRTbtDqLIv8NghARc/AqwNWgEc9PelCPe5bdCOLBEyFjqKiT2MttnSSUc2Zob\n"
+ "XhYkHC6zN1Mlq30N0e3Q61YK9LxMdU1vsluXxNq2rfK1Scb1oOlOOtlbV3zA3VRF\n"
+ "hV3t1nOA9tFmUrwZi0CUMWJE/zbPAyhwWotKyZkCgYEAh0kFicPdbABdrCglXVae\n"
+ "SnfSjVwYkVuGd5Ze0WADvjYsVkYBHTvhgRNnRJMg+/vWz3Sf4Ps4rgUbqK8Vc20b\n"
+ "AU5G6H6tlCvPRGm0ZxrwTWDHTcuKRVs+pJE8C/qWoklE/AAhjluWVoGwUMbPGuiH\n"
+ "6Gf1bgHF6oj/Sq7rv/VLZ8ECgYBeq7ml05YyLuJutuwa4yzQ/MXfghzv4aVyb0F3\n"
+ "QCdXR6o2IYgR6jnSewrZKlA9aPqFJrwHNR6sNXlnSmt5Fcf/RWO/qgJQGLUv3+rG\n"
+ "7kuLTNDR05azSdiZc7J89ID3Bkb+z2YkV+6JUiPq/Ei1+nDBEXb/m+/HqALU/nyj\n"
+ "P3gXeQKBgBusb8Rbd+KgxSA0hwY6aoRTPRt8LNvXdsB9vRcKKHUFQvxUWiUSS+L9\n"
+ "/Qu1sJbrUquKOHqksV5wCnWnAKyJNJlhHuBToqQTgKXjuNmVdYSe631saiI7PHyC\n"
+ "eRJ6DxULPxABytJrYCRrNqmXi5TCiqR2mtfalEMOPxz8rUU8dYyx\n"
+ "-----END RSA PRIVATE KEY-----\n";
+
+static int
+file_reader (void *cls, uint64_t pos, char *buf, int max)
+{
+ FILE *file = cls;
+
+ fseek (file, pos, SEEK_SET);
+ return fread (buf, 1, max, file);
+}
+
+/* HTTP access handler call back */
+static int
+http_ahc (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ struct MHD_Response *response;
+ int ret;
+ FILE *file;
+ struct stat buf;
+
+ if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+
+ file = fopen (&url[1], "rb");
+ if (file == NULL)
+ {
+ response = MHD_create_response_from_data (strlen (EMPTY_PAGE),
+ (void *) EMPTY_PAGE,
+ MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
+ MHD_destroy_response (response);
+ }
+ else
+ {
+ stat (url, &buf);
+ response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
+ &file_reader, file,
+ (MHD_ContentReaderFreeCallback)
+ & fclose);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ }
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *TLS_daemon;
+
+ if (argc == 3)
+ {
+ /* TODO check if this is truly necessary - disallow usage of the blocking /dev/random */
+ /* gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); */
+ TLS_daemon =
+ MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG |
+ MHD_USE_SSL, atoi (argv[1]), NULL, NULL, &http_ahc,
+ NULL, MHD_OPTION_CONNECTION_TIMEOUT, 256,
+ MHD_OPTION_HTTPS_MEM_KEY, key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
+ MHD_OPTION_END);
+ }
+ else
+ {
+ printf ("Usage: %s HTTP-PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+
+ if (TLS_daemon == NULL)
+ {
+ fprintf (stderr, "Error: failed to start TLS_daemon\n");
+ return 1;
+ }
+ else
+ {
+ printf ("MHD daemon listening on port %d\n", atoi (argv[1]));
+ }
+
+ sleep (atoi (argv[2]));
+
+ MHD_stop_daemon (TLS_daemon);
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/minimal_example.c b/lib/libmicrohttpd/src/examples/minimal_example.c
new file mode 100644
index 0000000000..4c73d6f216
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/minimal_example.c
@@ -0,0 +1,77 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ * @file minimal_example.c
+ * @brief minimal example for how to use libmicrohttpd
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+
+#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (method, "GET"))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ response = MHD_create_response_from_data (strlen (me),
+ (void *) me, MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/minimal_example_comet.c b/lib/libmicrohttpd/src/examples/minimal_example_comet.c
new file mode 100644
index 0000000000..03607f325a
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/minimal_example_comet.c
@@ -0,0 +1,85 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ * @file minimal_example.c
+ * @brief minimal example for how to generate an infinite stream with libmicrohttpd
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+
+static int
+data_generator (void *cls, uint64_t pos, char *buf, int max)
+{
+ if (max < 80)
+ return 0;
+ memset (buf, 'A', max - 1);
+ buf[79] = '\n';
+ return 80;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (method, "GET"))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ response = MHD_create_response_from_callback (-1,
+ 80,
+ &data_generator, NULL, NULL);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/querystring_example.c b/lib/libmicrohttpd/src/examples/querystring_example.c
new file mode 100644
index 0000000000..210d9149e4
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/querystring_example.c
@@ -0,0 +1,84 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ * @file querystring_example.c
+ * @brief example for how to get the query string from libmicrohttpd
+ * Call with an URI ending with something like "?q=QUERY"
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <microhttpd.h>
+
+#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>Query string for &quot;%s&quot; was &quot;%s&quot;</body></html>"
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ const char *fmt = cls;
+ const char *val;
+ char *me;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (method, "GET"))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+ val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "q");
+ me = malloc (snprintf (NULL, 0, fmt, "q", val) + 1);
+ if (me == NULL)
+ return MHD_NO;
+ sprintf (me, fmt, "q", val);
+ response = MHD_create_response_from_data (strlen (me), me, MHD_YES, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+ MHD_stop_daemon (d);
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/examples/refuse_post_example.c b/lib/libmicrohttpd/src/examples/refuse_post_example.c
new file mode 100644
index 0000000000..db6a13e922
--- /dev/null
+++ b/lib/libmicrohttpd/src/examples/refuse_post_example.c
@@ -0,0 +1,99 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ * @file refuse_post_example.c
+ * @brief example for how to refuse a POST request properly
+ * @author Christian Grothoff and Sebastian Gerhardt
+ */
+#include "platform.h"
+#include <microhttpd.h>
+
+const char *askpage = "<html><body>\n\
+ Upload a file, please!<br>\n\
+ <form action=\"/filepost\" method=\"post\" enctype=\"multipart/form-data\">\n\
+ <input name=\"file\" type=\"file\">\n\
+ <input type=\"submit\" value=\" Send \"></form>\n\
+ </body></html>";
+
+#define BUSYPAGE "<html><head><title>Webserver busy</title></head><body>We are too busy to process POSTs right now.</body></html>"
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if ((0 != strcmp (method, "GET")) && (0 != strcmp (method, "POST")))
+ return MHD_NO; /* unexpected method */
+
+ if (&aptr != *ptr)
+ {
+ *ptr = &aptr;
+
+ /* always to busy for POST requests */
+ if (0 == strcmp (method, "POST"))
+ {
+ response = MHD_create_response_from_data (strlen (BUSYPAGE),
+ (void *) BUSYPAGE, MHD_NO,
+ MHD_NO);
+ ret =
+ MHD_queue_response (connection, MHD_HTTP_SERVICE_UNAVAILABLE,
+ response);
+ MHD_destroy_response (response);
+ return ret;
+ }
+ }
+
+ *ptr = NULL; /* reset when done */
+ response = MHD_create_response_from_data (strlen (me),
+ (void *) me, MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ struct MHD_Daemon *d;
+
+ if (argc != 3)
+ {
+ printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+ return 1;
+ }
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ atoi (argv[1]),
+ NULL, NULL, &ahc_echo, (void *) askpage,
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ sleep (atoi (argv[2]));
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+/* end of refuse_post_example.c */
diff --git a/lib/libmicrohttpd/src/include/Makefile.am b/lib/libmicrohttpd/src/include/Makefile.am
new file mode 100644
index 0000000000..f76fe3b087
--- /dev/null
+++ b/lib/libmicrohttpd/src/include/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = .
+include_HEADERS = microhttpd.h
+
+EXTRA_DIST = platform.h plibc.h
diff --git a/lib/libmicrohttpd/src/include/Makefile.in b/lib/libmicrohttpd/src/include/Makefile.in
new file mode 100644
index 0000000000..d208ee9660
--- /dev/null
+++ b/lib/libmicrohttpd/src/include/Makefile.in
@@ -0,0 +1,625 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/include
+DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(includedir)"
+HEADERS = $(include_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+include_HEADERS = microhttpd.h
+EXTRA_DIST = platform.h plibc.h
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/include/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(includedir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-includeHEADERS install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-includeHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/include/microhttpd.h b/lib/libmicrohttpd/src/include/microhttpd.h
new file mode 100644
index 0000000000..33a33ee0a3
--- /dev/null
+++ b/lib/libmicrohttpd/src/include/microhttpd.h
@@ -0,0 +1,1312 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file microhttpd.h
+ * @brief public interface to libmicrohttpd
+ * @author Christian Grothoff
+ * @author Chris GauthierDickey
+ *
+ * All symbols defined in this header start with MHD. MHD is a small
+ * HTTP daemon library. As such, it does not have any API for logging
+ * errors (you can only enable or disable logging to stderr). Also,
+ * it may not support all of the HTTP features directly, where
+ * applicable, portions of HTTP may have to be handled by clients of
+ * the library.<p>
+ *
+ * The library is supposed to handle everything that it must handle
+ * (because the API would not allow clients to do this), such as basic
+ * connection management; however, detailed interpretations of headers
+ * -- such as range requests -- and HTTP methods are left to clients.
+ * The library does understand HEAD and will only send the headers of
+ * the response and not the body, even if the client supplied a body.
+ * The library also understands headers that control connection
+ * management (specifically, "Connection: close" and "Expect: 100
+ * continue" are understood and handled automatically).<p>
+ *
+ * MHD understands POST data and is able to decode certain formats
+ * (at the moment only "application/x-www-form-urlencoded") if the
+ * entire data fits into the allowed amount of memory for the
+ * connection. Unsupported encodings and large POST submissions are
+ * provided as a stream to the main application (and thus can be
+ * processed, just not conveniently by MHD).<p>
+ *
+ * The header file defines various constants used by the HTTP protocol.
+ * This does not mean that MHD actually interprets all of these
+ * values. The provided constants are exported as a convenience
+ * for users of the library. MHD does not verify that transmitted
+ * HTTP headers are part of the standard specification; users of the
+ * library are free to define their own extensions of the HTTP
+ * standard and use those with MHD.<p>
+ *
+ * All functions are guaranteed to be completely reentrant and
+ * thread-safe (with the exception of 'MHD_set_connection_value',
+ * which must only be used in a particular context).<p>
+ *
+ * NEW: Before including "microhttpd.h" you should add the necessary
+ * includes to define the "uint64_t", "size_t", "fd_set", "socklen_t"
+ * and "struct sockaddr" data types (which headers are needed may
+ * depend on your platform; for possible suggestions consult
+ * "platform.h" in the MHD distribution).
+ *
+ */
+
+#ifndef MHD_MICROHTTPD_H
+#define MHD_MICROHTTPD_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+/**
+ * Current version of the library.
+ */
+#define MHD_VERSION 0x00040500
+
+/**
+ * MHD-internal return code for "YES".
+ */
+#define MHD_YES 1
+
+/**
+ * MHD-internal return code for "NO".
+ */
+#define MHD_NO 0
+
+/**
+ * Constant used to indicate unknown size (use when
+ * creating a response).
+ */
+#define MHD_SIZE_UNKNOWN ((uint64_t) -1LL)
+
+/**
+ * HTTP response codes.
+ */
+#define MHD_HTTP_CONTINUE 100
+#define MHD_HTTP_SWITCHING_PROTOCOLS 101
+#define MHD_HTTP_PROCESSING 102
+
+#define MHD_HTTP_OK 200
+#define MHD_HTTP_CREATED 201
+#define MHD_HTTP_ACCEPTED 202
+#define MHD_HTTP_NON_AUTHORITATIVE_INFORMATION 203
+#define MHD_HTTP_NO_CONTENT 204
+#define MHD_HTTP_RESET_CONTENT 205
+#define MHD_HTTP_PARTIAL_CONTENT 206
+#define MHD_HTTP_MULTI_STATUS 207
+
+#define MHD_HTTP_MULTIPLE_CHOICES 300
+#define MHD_HTTP_MOVED_PERMANENTLY 301
+#define MHD_HTTP_FOUND 302
+#define MHD_HTTP_SEE_OTHER 303
+#define MHD_HTTP_NOT_MODIFIED 304
+#define MHD_HTTP_USE_PROXY 305
+#define MHD_HTTP_SWITCH_PROXY 306
+#define MHD_HTTP_TEMPORARY_REDIRECT 307
+
+#define MHD_HTTP_BAD_REQUEST 400
+#define MHD_HTTP_UNAUTHORIZED 401
+#define MHD_HTTP_PAYMENT_REQUIRED 402
+#define MHD_HTTP_FORBIDDEN 403
+#define MHD_HTTP_NOT_FOUND 404
+#define MHD_HTTP_METHOD_NOT_ALLOWED 405
+#define MHD_HTTP_METHOD_NOT_ACCEPTABLE 406
+#define MHD_HTTP_PROXY_AUTHENTICATION_REQUIRED 407
+#define MHD_HTTP_REQUEST_TIMEOUT 408
+#define MHD_HTTP_CONFLICT 409
+#define MHD_HTTP_GONE 410
+#define MHD_HTTP_LENGTH_REQUIRED 411
+#define MHD_HTTP_PRECONDITION_FAILED 412
+#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE 413
+#define MHD_HTTP_REQUEST_URI_TOO_LONG 414
+#define MHD_HTTP_UNSUPPORTED_MEDIA_TYPE 415
+#define MHD_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE 416
+#define MHD_HTTP_EXPECTATION_FAILED 417
+#define MHD_HTTP_UNPROCESSABLE_ENTITY 422
+#define MHD_HTTP_LOCKED 423
+#define MHD_HTTP_FAILED_DEPENDENCY 424
+#define MHD_HTTP_UNORDERED_COLLECTION 425
+#define MHD_HTTP_UPGRADE_REQUIRED 426
+#define MHD_HTTP_RETRY_WITH 449
+
+#define MHD_HTTP_INTERNAL_SERVER_ERROR 500
+#define MHD_HTTP_NOT_IMPLEMENTED 501
+#define MHD_HTTP_BAD_GATEWAY 502
+#define MHD_HTTP_SERVICE_UNAVAILABLE 503
+#define MHD_HTTP_GATEWAY_TIMEOUT 504
+#define MHD_HTTP_HTTP_VERSION_NOT_SUPPORTED 505
+#define MHD_HTTP_VARIANT_ALSO_NEGOTIATES 506
+#define MHD_HTTP_INSUFFICIENT_STORAGE 507
+#define MHD_HTTP_BANDWIDTH_LIMIT_EXCEEDED 509
+#define MHD_HTTP_NOT_EXTENDED 510
+
+/* See also: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html */
+#define MHD_HTTP_HEADER_ACCEPT "Accept"
+#define MHD_HTTP_HEADER_ACCEPT_CHARSET "Accept-Charset"
+#define MHD_HTTP_HEADER_ACCEPT_ENCODING "Accept-Encoding"
+#define MHD_HTTP_HEADER_ACCEPT_LANGUAGE "Accept-Language"
+#define MHD_HTTP_HEADER_ACCEPT_RANGES "Accept-Ranges"
+#define MHD_HTTP_HEADER_AGE "Age"
+#define MHD_HTTP_HEADER_ALLOW "Allow"
+#define MHD_HTTP_HEADER_AUTHORIZATION "Authorization"
+#define MHD_HTTP_HEADER_CACHE_CONTROL "Cache-Control"
+#define MHD_HTTP_HEADER_CONNECTION "Connection"
+#define MHD_HTTP_HEADER_CONTENT_ENCODING "Content-Encoding"
+#define MHD_HTTP_HEADER_CONTENT_LANGUAGE "Content-Language"
+#define MHD_HTTP_HEADER_CONTENT_LENGTH "Content-Length"
+#define MHD_HTTP_HEADER_CONTENT_LOCATION "Content-Location"
+#define MHD_HTTP_HEADER_CONTENT_MD5 "Content-MD5"
+#define MHD_HTTP_HEADER_CONTENT_RANGE "Content-Range"
+#define MHD_HTTP_HEADER_CONTENT_TYPE "Content-Type"
+#define MHD_HTTP_HEADER_COOKIE "Cookie"
+#define MHD_HTTP_HEADER_DATE "Date"
+#define MHD_HTTP_HEADER_ETAG "ETag"
+#define MHD_HTTP_HEADER_EXPECT "Expect"
+#define MHD_HTTP_HEADER_EXPIRES "Expires"
+#define MHD_HTTP_HEADER_FROM "From"
+#define MHD_HTTP_HEADER_HOST "Host"
+#define MHD_HTTP_HEADER_IF_MATCH "If-Match"
+#define MHD_HTTP_HEADER_IF_MODIFIED_SINCE "If-Modified-Since"
+#define MHD_HTTP_HEADER_IF_NONE_MATCH "If-None-Match"
+#define MHD_HTTP_HEADER_IF_RANGE "If-Range"
+#define MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE "If-Unmodified-Since"
+#define MHD_HTTP_HEADER_LAST_MODIFIED "Last-Modified"
+#define MHD_HTTP_HEADER_LOCATION "Location"
+#define MHD_HTTP_HEADER_MAX_FORWARDS "Max-Forwards"
+#define MHD_HTTP_HEADER_PRAGMA "Pragma"
+#define MHD_HTTP_HEADER_PROXY_AUTHENTICATE "Proxy-Authenticate"
+#define MHD_HTTP_HEADER_PROXY_AUTHORIZATION "Proxy-Authorization"
+#define MHD_HTTP_HEADER_RANGE "Range"
+#define MHD_HTTP_HEADER_REFERER "Referer"
+#define MHD_HTTP_HEADER_RETRY_AFTER "Retry-After"
+#define MHD_HTTP_HEADER_SERVER "Server"
+#define MHD_HTTP_HEADER_SET_COOKIE "Set-Cookie"
+#define MHD_HTTP_HEADER_SET_COOKIE2 "Set-Cookie2"
+#define MHD_HTTP_HEADER_TE "TE"
+#define MHD_HTTP_HEADER_TRAILER "Trailer"
+#define MHD_HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding"
+#define MHD_HTTP_HEADER_UPGRADE "Upgrade"
+#define MHD_HTTP_HEADER_USER_AGENT "User-Agent"
+#define MHD_HTTP_HEADER_VARY "Vary"
+#define MHD_HTTP_HEADER_VIA "Via"
+#define MHD_HTTP_HEADER_WARNING "Warning"
+#define MHD_HTTP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate"
+
+/**
+ * HTTP versions (used to match against the first line of the
+ * HTTP header as well as in the response code).
+ */
+#define MHD_HTTP_VERSION_1_0 "HTTP/1.0"
+#define MHD_HTTP_VERSION_1_1 "HTTP/1.1"
+
+/**
+ * HTTP methods
+ */
+#define MHD_HTTP_METHOD_CONNECT "CONNECT"
+#define MHD_HTTP_METHOD_DELETE "DELETE"
+#define MHD_HTTP_METHOD_GET "GET"
+#define MHD_HTTP_METHOD_HEAD "HEAD"
+#define MHD_HTTP_METHOD_OPTIONS "OPTIONS"
+#define MHD_HTTP_METHOD_POST "POST"
+#define MHD_HTTP_METHOD_PUT "PUT"
+#define MHD_HTTP_METHOD_TRACE "TRACE"
+
+/**
+ * HTTP POST encodings, see also
+ * http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4
+ */
+#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED "application/x-www-form-urlencoded"
+#define MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data"
+
+/**
+ * Options for the MHD daemon. Note that if neither
+ * MHD_USER_THREAD_PER_CONNECTION nor MHD_USE_SELECT_INTERNALLY are
+ * used, the client wants control over the process and will call the
+ * appropriate microhttpd callbacks.<p>
+ *
+ * Starting the daemon may also fail if a particular option is not
+ * implemented or not supported on the target platform (i.e. no
+ * support for SSL, threads or IPv6).
+ */
+enum MHD_FLAG
+{
+ /**
+ * No options selected.
+ */
+ MHD_NO_FLAG = 0,
+
+ /**
+ * Run in debug mode. If this flag is used, the
+ * library should print error messages and warnings
+ * to stderr.
+ */
+ MHD_USE_DEBUG = 1,
+
+ /**
+ * Run in https mode.
+ */
+ MHD_USE_SSL = 2,
+
+ /**
+ * Run using one thread per connection.
+ */
+ MHD_USE_THREAD_PER_CONNECTION = 4,
+
+ /**
+ * Run using an internal thread doing SELECT.
+ */
+ MHD_USE_SELECT_INTERNALLY = 8,
+
+ /**
+ * Run using the IPv6 protocol (otherwise, MHD will
+ * just support IPv4).
+ */
+ MHD_USE_IPv6 = 16,
+
+ /**
+ * Be pedantic about the protocol (as opposed to as tolerant as
+ * possible). Specifically, at the moment, this flag causes MHD to
+ * reject http 1.1 connections without a "Host" header. This is
+ * required by the standard, but of course in violation of the "be
+ * as liberal as possible in what you accept" norm. It is
+ * recommended to turn this ON if you are testing clients against
+ * MHD, and OFF in production.
+ */
+ MHD_USE_PEDANTIC_CHECKS = 32,
+
+ /**
+ * Use poll instead of select. This allows sockets with fd >= FD_SETSIZE.
+ * This option only works in conjunction with MHD_USE_THREAD_PER_CONNECTION
+ * (at this point).
+ */
+ MHD_USE_POLL = 64
+};
+
+/**
+ * MHD options. Passed in the varargs portion
+ * of MHD_start_daemon.
+ */
+enum MHD_OPTION
+{
+
+ /**
+ * No more options / last option. This is used
+ * to terminate the VARARGs list.
+ */
+ MHD_OPTION_END = 0,
+
+ /**
+ * Maximum memory size per connection (followed by a
+ * size_t).
+ */
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT = 1,
+
+ /**
+ * Maximum number of concurrent connections to
+ * accept (followed by an unsigned int).
+ */
+ MHD_OPTION_CONNECTION_LIMIT = 2,
+
+ /**
+ * After how many seconds of inactivity should a
+ * connection automatically be timed out? (followed
+ * by an unsigned int; use zero for no timeout).
+ */
+ MHD_OPTION_CONNECTION_TIMEOUT = 3,
+
+ /**
+ * Register a function that should be called whenever a request has
+ * been completed (this can be used for application-specific clean
+ * up). Requests that have never been presented to the application
+ * (via MHD_AccessHandlerCallback) will not result in
+ * notifications.<p>
+ *
+ * This option should be followed by TWO pointers. First a pointer
+ * to a function of type "MHD_RequestCompletedCallback" and second a
+ * pointer to a closure to pass to the request completed callback.
+ * The second pointer maybe NULL.
+ */
+ MHD_OPTION_NOTIFY_COMPLETED = 4,
+
+ /**
+ * Limit on the number of (concurrent) connections made to the
+ * server from the same IP address. Can be used to prevent one
+ * IP from taking over all of the allowed connections. If the
+ * same IP tries to establish more than the specified number of
+ * connections, they will be immediately rejected. The option
+ * should be followed by an "unsigned int". The default is
+ * zero, which means no limit on the number of connections
+ * from the same IP address.
+ */
+ MHD_OPTION_PER_IP_CONNECTION_LIMIT = 5,
+
+ /**
+ * Bind daemon to the supplied sockaddr. this option should be followed by a
+ * 'struct sockaddr *'. If 'MHD_USE_IPv6' is specified, the 'struct sockaddr*'
+ * should point to a 'struct sockaddr_in6', otherwise to a 'struct sockaddr_in'.
+ */
+ MHD_OPTION_SOCK_ADDR = 6,
+
+ /**
+ * Specify a function that should be called before parsing the URI from
+ * the client. The specified callback function can be used for processing
+ * the URI (including the options) before it is parsed. The URI after
+ * parsing will no longer contain the options, which maybe inconvenient for
+ * logging. This option should be followed by two arguments, the first
+ * one must be of the form
+ * <pre>
+ * void * my_logger(void * cls, const char * uri)
+ * </pre>
+ * where the return value will be passed as
+ * (*con_cls) in calls to the MHD_AccessHandlerCallback
+ * when this request is processed later; returning a
+ * value of NULL has no special significance (however,
+ * note that if you return non-NULL, you can no longer
+ * rely on the first call to the access handler having
+ * NULL == *con_cls on entry;)
+ * "cls" will be set to the second argument following
+ * MHD_OPTION_URI_LOG_CALLBACK. Finally, uri will
+ * be the 0-terminated URI of the request.
+ */
+ MHD_OPTION_URI_LOG_CALLBACK = 7,
+
+ /**
+ * Memory pointer for the private key (key.pem) to be used by the
+ * HTTPS daemon. This option should be followed by an
+ * "const char*" argument.
+ * This should be used in conjunction with 'MHD_OPTION_HTTPS_MEM_CERT'.
+ */
+ MHD_OPTION_HTTPS_MEM_KEY = 8,
+
+ /**
+ * Memory pointer for the certificate (cert.pem) to be used by the
+ * HTTPS daemon. This option should be followed by an
+ * "const char*" argument.
+ * This should be used in conjunction with 'MHD_OPTION_HTTPS_MEM_KEY'.
+ */
+ MHD_OPTION_HTTPS_MEM_CERT = 9,
+
+ /**
+ * Daemon credentials type.
+ * This option should be followed by one of the values listed in
+ * "enum MHD_GNUTLS_CredentialsType".
+ */
+ MHD_OPTION_CRED_TYPE = 10,
+
+ /**
+ * SSL/TLS protocol version.
+ *
+ * Memory pointer to a zero (MHD_GNUTLS_PROTOCOL_END) terminated
+ * (const) array of 'enum MHD_GNUTLS_Protocol' values representing the
+ * protocol versions to this server should support. Unsupported
+ * requests will be droped by the server.
+ */
+ MHD_OPTION_PROTOCOL_VERSION = 11,
+
+ /**
+ * Memory pointer to a zero (MHD_GNUTLS_CIPHER_UNKNOWN)
+ * terminated (const) array of 'enum MHD_GNUTLS_CipherAlgorithm'
+ * representing the cipher priority order to which the HTTPS
+ * daemon should adhere.
+ */
+ MHD_OPTION_CIPHER_ALGORITHM = 12,
+
+ /**
+ * Use the given function for logging error messages.
+ * This option must be followed by two arguments; the
+ * first must be a pointer to a function
+ * of type "void fun(void * arg, const char * fmt, va_list ap)"
+ * and the second a pointer "void*" which will
+ * be passed as the "arg" argument to "fun".
+ * <p>
+ * Note that MHD will not generate any log messages
+ * if it was compiled without the "--enable-messages"
+ * flag being set.
+ */
+ MHD_OPTION_EXTERNAL_LOGGER = 13,
+
+ /**
+ * Number (unsigned int) of threads in thread pool. Enable
+ * thread pooling by setting this value to to something
+ * greater than 1. Currently, thread model must be
+ * MHD_USE_SELECT_INTERNALLY if thread pooling is enabled
+ * (MHD_start_daemon returns NULL for an unsupported thread
+ * model).
+ */
+ MHD_OPTION_THREAD_POOL_SIZE = 14,
+
+ /**
+ * Additional options given in an array of "struct MHD_OptionItem".
+ * The array must be terminated with an entry '{MHD_OPTION_END, 0, NULL}'.
+ * An example for code using MHD_OPTION_ARRAY is:
+ * <code>
+ * struct MHD_OptionItem ops[] = {
+ * { MHD_OPTION_CONNECTION_LIMIT, 100, NULL },
+ * { MHD_OPTION_CONNECTION_TIMEOUT, 10, NULL },
+ * { MHD_OPTION_END, 0, NULL }
+ * };
+ * d = MHD_start_daemon(0, 8080, NULL, NULL, dh, NULL,
+ * MHD_OPTION_ARRAY, ops,
+ * MHD_OPTION_END);
+ * </code>
+ * For options that expect a single pointer argument, the
+ * second member of the struct MHD_OptionItem is ignored.
+ * For options that expect two pointer arguments, the first
+ * argument must be cast to 'intptr_t'.
+ */
+ MHD_OPTION_ARRAY = 15
+};
+
+
+/**
+ * Entry in an MHD_OPTION_ARRAY.
+ */
+struct MHD_OptionItem
+{
+ /**
+ * Which option is being given. Use MHD_OPTION_END
+ * to terminate the array.
+ */
+ enum MHD_OPTION option;
+
+ /**
+ * Option value (for integer arguments, and for options requiring
+ * two pointer arguments); should be 0 for options that take no
+ * arguments or only a single pointer argument.
+ */
+ intptr_t value;
+
+ /**
+ * Pointer option value (use NULL for options taking no arguments
+ * or only an integer option).
+ */
+ void *ptr_value;
+
+};
+
+
+/**
+ * The MHD_ValueKind specifies the source of
+ * the key-value pairs in the HTTP protocol.
+ */
+enum MHD_ValueKind
+{
+
+ /**
+ * Response header
+ */
+ MHD_RESPONSE_HEADER_KIND = 0,
+
+ /**
+ * HTTP header.
+ */
+ MHD_HEADER_KIND = 1,
+
+ /**
+ * Cookies. Note that the original HTTP header containing
+ * the cookie(s) will still be available and intact.
+ */
+ MHD_COOKIE_KIND = 2,
+
+ /**
+ * POST data. This is available only if a content encoding
+ * supported by MHD is used (currently only URL encoding),
+ * and only if the posted content fits within the available
+ * memory pool. Note that in that case, the upload data
+ * given to the MHD_AccessHandlerCallback will be
+ * empty (since it has already been processed).
+ */
+ MHD_POSTDATA_KIND = 4,
+
+ /**
+ * GET (URI) arguments.
+ */
+ MHD_GET_ARGUMENT_KIND = 8,
+
+ /**
+ * HTTP footer (only for http 1.1 chunked encodings).
+ */
+ MHD_FOOTER_KIND = 16
+};
+
+/**
+ * The MHD_RequestTerminationCode specifies reasons
+ * why a request has been terminated (or completed).
+ */
+enum MHD_RequestTerminationCode
+{
+
+ /**
+ * We finished sending the response.
+ */
+ MHD_REQUEST_TERMINATED_COMPLETED_OK = 0,
+
+ /**
+ * Error handling the connection (resources
+ * exhausted, other side closed connection,
+ * application error accepting request, etc.)
+ */
+ MHD_REQUEST_TERMINATED_WITH_ERROR = 1,
+
+ /**
+ * No activity on the connection for the number
+ * of seconds specified using
+ * MHD_OPTION_CONNECTION_TIMEOUT.
+ */
+ MHD_REQUEST_TERMINATED_TIMEOUT_REACHED = 2,
+
+ /**
+ * We had to close the session since MHD was being
+ * shut down.
+ */
+ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN = 3
+
+};
+
+/**
+ * List of symmetric ciphers.
+ * Note that not all listed algorithms are necessarily
+ * supported by all builds of MHD.
+ */
+enum MHD_GNUTLS_CipherAlgorithm
+{
+ MHD_GNUTLS_CIPHER_UNKNOWN = 0,
+ MHD_GNUTLS_CIPHER_NULL = 1,
+ MHD_GNUTLS_CIPHER_ARCFOUR_128,
+ MHD_GNUTLS_CIPHER_3DES_CBC,
+ MHD_GNUTLS_CIPHER_AES_128_CBC,
+ MHD_GNUTLS_CIPHER_AES_256_CBC
+};
+
+/**
+ * SSL/TLS Protocol types.
+ * Note that not all listed algorithms are necessarily
+ * supported by all builds of MHD.
+ */
+enum MHD_GNUTLS_Protocol
+{
+ MHD_GNUTLS_PROTOCOL_END = 0,
+ MHD_GNUTLS_PROTOCOL_SSL3 = 1,
+ MHD_GNUTLS_PROTOCOL_TLS1_0,
+ MHD_GNUTLS_PROTOCOL_TLS1_1,
+ MHD_GNUTLS_PROTOCOL_TLS1_2,
+ MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN = 0xff
+};
+
+/**
+ * Values of this enum are used to specify what
+ * information about a connection is desired.
+ */
+enum MHD_ConnectionInfoType
+{
+ /**
+ * What cipher algorithm is being used.
+ * Takes no extra arguments.
+ */
+ MHD_CONNECTION_INFO_CIPHER_ALGO,
+
+ /**
+ *
+ * Takes no extra arguments.
+ */
+ MHD_CONNECTION_INFO_PROTOCOL,
+
+ /**
+ * Obtain IP address of the client.
+ * Takes no extra arguments.
+ */
+ MHD_CONNECTION_INFO_CLIENT_ADDRESS
+};
+
+/**
+ * Values of this enum are used to specify what
+ * information about a deamon is desired.
+ */
+enum MHD_DaemonInfoType
+{
+ /**
+ * Request information about the key size for
+ * a particular cipher algorithm. The cipher
+ * algorithm should be passed as an extra
+ * argument (of type 'enum MHD_GNUTLS_CipherAlgorithm').
+ */
+ MHD_DAEMON_INFO_KEY_SIZE,
+
+ /**
+ * Request information about the key size for
+ * a particular cipher algorithm. The cipher
+ * algorithm should be passed as an extra
+ * argument (of type 'enum MHD_GNUTLS_HashAlgorithm').
+ */
+ MHD_DAEMON_INFO_MAC_KEY_SIZE,
+
+ /**
+ * Request the file descriptor for the listening socket.
+ * No extra arguments should be passed.
+ */
+ MHD_DAEMON_INFO_LISTEN_FD
+};
+
+
+
+/**
+ * Handle for the daemon (listening on a socket for HTTP traffic).
+ */
+struct MHD_Daemon;
+
+/**
+ * Handle for a connection / HTTP request. With HTTP/1.1, multiple
+ * requests can be run over the same connection. However, MHD will
+ * only show one request per TCP connection to the client at any given
+ * time.
+ */
+struct MHD_Connection;
+
+/**
+ * Handle for a response.
+ */
+struct MHD_Response;
+
+/**
+ * Handle for POST processing.
+ */
+struct MHD_PostProcessor;
+
+/**
+ * Callback for serious error condition. The default action is to abort().
+ * @param cls user specified value
+ * @param file where the error occured
+ * @param line where the error occured
+ * @param reason error detail, may be NULL
+ */
+typedef void (*MHD_PanicCallback) (void *cls,
+ const char *file,
+ unsigned int line,
+ const char *reason);
+
+/**
+ * Allow or deny a client to connect.
+ *
+ * @param addr address information from the client
+ * @param addrlen length of the address information
+ * @return MHD_YES if connection is allowed, MHD_NO if not
+ */
+typedef int
+ (*MHD_AcceptPolicyCallback) (void *cls,
+ const struct sockaddr * addr,
+ socklen_t addrlen);
+
+/**
+ * A client has requested the given url using the given method ("GET",
+ * "PUT", "DELETE", "POST", etc). The callback must call MHS
+ * callbacks to provide content to give back to the client and return
+ * an HTTP status code (i.e. 200 for OK, 404, etc.).
+ *
+ * @param cls argument given together with the function
+ * pointer when the handler was registered with MHD
+ * @param url the requested url
+ * @param method the HTTP method used ("GET", "PUT", etc.)
+ * @param version the HTTP version string (i.e. "HTTP/1.1")
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ * for a POST that fits into memory and that is encoded
+ * with a supported encoding, the POST data will NOT be
+ * given in upload_data and is instead available as
+ * part of MHD_get_connection_values; very large POST
+ * data *will* be made available incrementally in
+ * upload_data)
+ * @param upload_data_size set initially to the size of the
+ * upload_data provided; the method must update this
+ * value to the number of bytes NOT processed;
+ * @param con_cls pointer that the callback can set to some
+ * address and that will be preserved by MHD for future
+ * calls for this request; since the access handler may
+ * be called many times (i.e., for a PUT/POST operation
+ * with plenty of upload data) this allows the application
+ * to easily associate some request-specific state.
+ * If necessary, this state can be cleaned up in the
+ * global "MHD_RequestCompleted" callback (which
+ * can be set with the MHD_OPTION_NOTIFY_COMPLETED).
+ * Initially, <tt>*con_cls</tt> will be NULL.
+ * @return MHS_YES if the connection was handled successfully,
+ * MHS_NO if the socket must be closed due to a serios
+ * error while handling the request
+ */
+typedef int
+ (*MHD_AccessHandlerCallback) (void *cls,
+ struct MHD_Connection * connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls);
+
+/**
+ * Signature of the callback used by MHD to notify the
+ * application about completed requests.
+ *
+ * @param cls client-defined closure
+ * @param connection connection handle
+ * @param con_cls value as set by the last call to
+ * the MHD_AccessHandlerCallback
+ * @param toe reason for request termination
+ * @see MHD_OPTION_NOTIFY_COMPLETED
+ */
+typedef void
+ (*MHD_RequestCompletedCallback) (void *cls,
+ struct MHD_Connection * connection,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe);
+
+/**
+ * Iterator over key-value pairs. This iterator
+ * can be used to iterate over all of the cookies,
+ * headers, or POST-data fields of a request, and
+ * also to iterate over the headers that have been
+ * added to a response.
+ *
+ * @return MHD_YES to continue iterating,
+ * MHD_NO to abort the iteration
+ */
+typedef int
+ (*MHD_KeyValueIterator) (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key, const char *value);
+
+/**
+ * Callback used by libmicrohttpd in order to obtain content. The
+ * callback is to copy at most "max" bytes of content into "buf". The
+ * total number of bytes that has been placed into "buf" should be
+ * returned.<p>
+ *
+ * Note that returning zero will cause libmicrohttpd to try again,
+ * either "immediately" if in multi-threaded mode (in which case the
+ * callback may want to do blocking operations) or in the next round
+ * if MHD_run is used. Returning 0 for a daemon that runs in internal
+ * select mode is an error (since it would result in busy waiting) and
+ * will cause the program to be aborted (abort()).
+ *
+ * @param cls extra argument to the callback
+ * @param pos position in the datastream to access;
+ * note that if an MHD_Response object is re-used,
+ * it is possible for the same content reader to
+ * be queried multiple times for the same data;
+ * however, if an MHD_Response is not re-used,
+ * libmicrohttpd guarantees that "pos" will be
+ * the sum of all non-negative return values
+ * obtained from the content reader so far.
+ * @return -1 for the end of transmission (or on error);
+ * if a content transfer size was pre-set and the callback
+ * has provided fewer than that amount of data,
+ * MHD will close the connection with the client;
+ * if no content size was specified and this is an
+ * http 1.1 connection using chunked encoding, MHD will
+ * interpret "-1" as the normal end of the transfer
+ * (possibly allowing the client to perform additional
+ * requests using the same TCP connection).
+ */
+typedef int
+ (*MHD_ContentReaderCallback) (void *cls,
+ uint64_t pos,
+ char *buf,
+ int max);
+
+/**
+ * This method is called by libmicrohttpd if we
+ * are done with a content reader. It should
+ * be used to free resources associated with the
+ * content reader.
+ */
+typedef void (*MHD_ContentReaderFreeCallback) (void *cls);
+
+/**
+ * Iterator over key-value pairs where the value
+ * maybe made available in increments and/or may
+ * not be zero-terminated. Used for processing
+ * POST data.
+ *
+ * @param cls user-specified closure
+ * @param kind type of the value
+ * @param key 0-terminated key for the value
+ * @param filename name of the uploaded file, NULL if not known
+ * @param content_type mime-type of the data, NULL if not known
+ * @param transfer_encoding encoding of the data, NULL if not known
+ * @param data pointer to size bytes of data at the
+ * specified offset
+ * @param off offset of data in the overall value
+ * @param size number of bytes in data available
+ * @return MHD_YES to continue iterating,
+ * MHD_NO to abort the iteration
+ */
+typedef int
+ (*MHD_PostDataIterator) (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *data, uint64_t off, size_t size);
+
+/* **************** Daemon handling functions ***************** */
+
+/**
+ * Start a webserver on the given port.
+ *
+ * @param flags combination of MHD_FLAG values
+ * @param port port to bind to
+ * @param apc callback to call to check which clients
+ * will be allowed to connect; you can pass NULL
+ * in which case connections from any IP will be
+ * accepted
+ * @param apc_cls extra argument to apc
+ * @param dh handler called for all requests (repeatedly)
+ * @param dh_cls extra argument to dh
+ * @param ... list of options (type-value pairs,
+ * terminated with MHD_OPTION_END).
+ * @return NULL on error, handle to daemon on success
+ */
+struct MHD_Daemon *MHD_start_daemon_va (unsigned int options,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls,
+ MHD_AccessHandlerCallback dh,
+ void *dh_cls, va_list ap);
+
+/**
+ * Start a webserver on the given port. Variadic version of
+ * MHD_start_daemon_va.
+ *
+ * @param flags combination of MHD_FLAG values
+ * @param port port to bind to
+ * @param apc callback to call to check which clients
+ * will be allowed to connect; you can pass NULL
+ * in which case connections from any IP will be
+ * accepted
+ * @param apc_cls extra argument to apc
+ * @param dh handler called for all requests (repeatedly)
+ * @param dh_cls extra argument to dh
+ * @return NULL on error, handle to daemon on success
+ */
+struct MHD_Daemon *MHD_start_daemon (unsigned int flags,
+ unsigned short port,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls,
+ MHD_AccessHandlerCallback dh,
+ void *dh_cls, ...);
+
+/**
+ * Shutdown an http daemon.
+ *
+ * @param daemon daemon to stop
+ */
+void MHD_stop_daemon (struct MHD_Daemon *daemon);
+
+
+/**
+ * Obtain the select sets for this daemon.
+ *
+ * @param daemon daemon to get sets from
+ * @param read_fd_set read set
+ * @param write_fd_set write set
+ * @param except_fd_set except set
+ * @param max_fd increased to largest FD added (if larger
+ * than existing value)
+ * @return MHD_YES on success, MHD_NO if this
+ * daemon was not started with the right
+ * options for this call.
+ */
+int
+MHD_get_fdset (struct MHD_Daemon *daemon,
+ fd_set * read_fd_set,
+ fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd);
+
+/**
+ * Obtain timeout value for select for this daemon
+ * (only needed if connection timeout is used). The
+ * returned value is how long select should at most
+ * block, not the timeout value set for connections.
+ *
+ * @param daemon daemon to query for timeout
+ * @param timeout set to the timeout (in milliseconds)
+ * @return MHD_YES on success, MHD_NO if timeouts are
+ * not used (or no connections exist that would
+ * necessiate the use of a timeout right now).
+ */
+int MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout);
+
+
+/**
+ * Run webserver operations (without blocking unless
+ * in client callbacks). This method should be called
+ * by clients in combination with MHD_get_fdset
+ * if the client-controlled select method is used.
+ *
+ * @param daemon daemon to run
+ * @return MHD_YES on success, MHD_NO if this
+ * daemon was not started with the right
+ * options for this call.
+ */
+int MHD_run (struct MHD_Daemon *daemon);
+
+
+/* **************** Connection handling functions ***************** */
+
+/**
+ * Get all of the headers from the request.
+ *
+ * @param connection connection to get values from
+ * @param kind types of values to iterate over
+ * @param iterator callback to call on each header;
+ * maybe NULL (then just count headers)
+ * @param iterator_cls extra argument to iterator
+ * @return number of entries iterated over
+ */
+int
+MHD_get_connection_values (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ MHD_KeyValueIterator iterator, void *iterator_cls);
+
+/**
+ * This function can be used to add an entry to
+ * the HTTP headers of a connection (so that the
+ * MHD_get_connection_values function will return
+ * them -- and the MHD PostProcessor will also
+ * see them). This maybe required in certain
+ * situations (see Mantis #1399) where (broken)
+ * HTTP implementations fail to supply values needed
+ * by the post processor (or other parts of the
+ * application).
+ * <p>
+ * This function MUST only be called from within
+ * the MHD_AccessHandlerCallback (otherwise, access
+ * maybe improperly synchronized). Furthermore,
+ * the client must guarantee that the key and
+ * value arguments are 0-terminated strings that
+ * are NOT freed until the connection is closed.
+ * (The easiest way to do this is by passing only
+ * arguments to permanently allocated strings.).
+ *
+ * @param connection the connection for which a
+ * value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself
+ * @return MHD_NO if the operation could not be
+ * performed due to insufficient memory;
+ * MHD_YES on success
+ */
+int
+MHD_set_connection_value (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ const char *key, const char *value);
+
+/**
+ * Sets the global error handler to a different implementation. "cb"
+ * will only be called in the case of typically fatal, serious
+ * internal consistency issues. These issues should only arise in the
+ * case of serious memory corruption or similar problems with the
+ * architecture. While "cb" is allowed to return and MHD will then
+ * try to continue, this is never safe.
+ *
+ * The default implementation that is used if no panic function is set
+ * simply calls "abort". Alternative implementations might call
+ * "exit" or other similar functions.
+ *
+ * @param cb new error handler
+ * @param cls passed to error handler
+ */
+void MHD_set_panic_func (MHD_PanicCallback cb, void *cls);
+
+/**
+ * Get a particular header value. If multiple
+ * values match the kind, return any one of them.
+ *
+ * @param connection connection to get values from
+ * @param kind what kind of value are we looking for
+ * @param key the header to look for
+ * @return NULL if no such item was found
+ */
+const char *MHD_lookup_connection_value (struct MHD_Connection *connection,
+ enum MHD_ValueKind kind,
+ const char *key);
+
+/**
+ * Queue a response to be transmitted to the client (as soon as
+ * possible but after MHD_AccessHandlerCallback returns).
+ *
+ * @param connection the connection identifying the client
+ * @param status_code HTTP status code (i.e. 200 for OK)
+ * @param response response to transmit
+ * @return MHD_NO on error (i.e. reply already sent),
+ * MHD_YES on success or if message has been queued
+ */
+int
+MHD_queue_response (struct MHD_Connection *connection,
+ unsigned int status_code, struct MHD_Response *response);
+
+
+/* **************** Response manipulation functions ***************** */
+
+/**
+ * Create a response object. The response object can be extended with
+ * header information and then be used any number of times.
+ *
+ * @param size size of the data portion of the response, MHD_SIZE_UNKNOW for unknown
+ * @param block_size preferred block size for querying crc (advisory only,
+ * MHD may still call crc using smaller chunks); this
+ * is essentially the buffer size used for IO, clients
+ * should pick a value that is appropriate for IO and
+ * memory performance requirements
+ * @param crc callback to use to obtain response data
+ * @param crc_cls extra argument to crc
+ * @param crfc callback to call to free crc_cls resources
+ * @return NULL on error (i.e. invalid arguments, out of memory)
+ */
+struct MHD_Response *MHD_create_response_from_callback (uint64_t size,
+ size_t block_size,
+ MHD_ContentReaderCallback
+ crc, void *crc_cls,
+ MHD_ContentReaderFreeCallback
+ crfc);
+
+/**
+ * Create a response object. The response object can be extended with
+ * header information and then be used any number of times.
+ *
+ * @param size size of the data portion of the response
+ * @param data the data itself
+ * @param must_free libmicrohttpd should free data when done
+ * @param must_copy libmicrohttpd must make a copy of data
+ * right away, the data maybe released anytime after
+ * this call returns
+ * @return NULL on error (i.e. invalid arguments, out of memory)
+ */
+struct MHD_Response *MHD_create_response_from_data (size_t size,
+ void *data,
+ int must_free,
+ int must_copy);
+
+/**
+ * Destroy a response object and associated resources. Note that
+ * libmicrohttpd may keep some of the resources around if the response
+ * is still in the queue for some clients, so the memory may not
+ * necessarily be freed immediatley.
+ *
+ * @param response response to destroy
+ */
+void MHD_destroy_response (struct MHD_Response *response);
+
+/**
+ * Add a header line to the response.
+ *
+ * @param response response to add a header to
+ * @param header the header to add
+ * @param content value to add
+ * @return MHD_NO on error (i.e. invalid header or content format),
+ * or out of memory
+ */
+int
+MHD_add_response_header (struct MHD_Response *response,
+ const char *header, const char *content);
+
+/**
+ * Delete a header line from the response.
+ *
+ * @param response response to remove a header from
+ * @param header the header to delete
+ * @param content value to delete
+ * @return MHD_NO on error (no such header known)
+ */
+int
+MHD_del_response_header (struct MHD_Response *response,
+ const char *header, const char *content);
+
+/**
+ * Get all of the headers added to a response.
+ *
+ * @param response response to query
+ * @param iterator callback to call on each header;
+ * maybe NULL (then just count headers)
+ * @param iterator_cls extra argument to iterator
+ * @return number of entries iterated over
+ */
+int
+MHD_get_response_headers (struct MHD_Response *response,
+ MHD_KeyValueIterator iterator, void *iterator_cls);
+
+
+/**
+ * Get a particular header from the response.
+ *
+ * @param response response to query
+ * @param key which header to get
+ * @return NULL if header does not exist
+ */
+const char *MHD_get_response_header (struct MHD_Response *response,
+ const char *key);
+
+
+/* ********************** PostProcessor functions ********************** */
+
+/**
+ * Create a PostProcessor.
+ *
+ * A PostProcessor can be used to (incrementally) parse the data
+ * portion of a POST request. Note that some buggy browsers fail to
+ * set the encoding type. If you want to support those, you may have
+ * to call 'MHD_set_connection_value' with the proper encoding type
+ * before creating a post processor (if no supported encoding type is
+ * set, this function will fail).
+ *
+ * @param connection the connection on which the POST is
+ * happening (used to determine the POST format)
+ * @param buffer_size maximum number of bytes to use for
+ * internal buffering (used only for the parsing,
+ * specifically the parsing of the keys). A
+ * tiny value (256-1024) should be sufficient.
+ * Do NOT use a value smaller than 256.
+ * @param iter iterator to be called with the parsed data,
+ * Must NOT be NULL.
+ * @param cls first argument to ikvi
+ * @return NULL on error (out of memory, unsupported encoding),
+ otherwise a PP handle
+ */
+struct MHD_PostProcessor *MHD_create_post_processor (struct MHD_Connection
+ *connection,
+ size_t buffer_size,
+ MHD_PostDataIterator
+ iter, void *cls);
+
+/**
+ * Parse and process POST data.
+ * Call this function when POST data is available
+ * (usually during an MHD_AccessHandlerCallback)
+ * with the upload_data and upload_data_size.
+ * Whenever possible, this will then cause calls
+ * to the MHD_IncrementalKeyValueIterator.
+ *
+ * @param pp the post processor
+ * @param post_data post_data_len bytes of POST data
+ * @param post_data_len length of post_data
+ * @return MHD_YES on success, MHD_NO on error
+ * (out-of-memory, iterator aborted, parse error)
+ */
+int
+MHD_post_process (struct MHD_PostProcessor *pp,
+ const char *post_data, size_t post_data_len);
+
+/**
+ * Release PostProcessor resources.
+ *
+ * @param pp the PostProcessor to destroy
+ * @return MHD_YES if processing completed nicely,
+ * MHD_NO if there were spurious characters / formatting
+ * problems; it is common to ignore the return
+ * value of this function
+ */
+int MHD_destroy_post_processor (struct MHD_PostProcessor *pp);
+
+
+
+/* ********************** generic query functions ********************** */
+
+
+/**
+ * Information about a connection.
+ */
+union MHD_ConnectionInfo
+{
+ enum MHD_GNUTLS_CipherAlgorithm cipher_algorithm;
+ enum MHD_GNUTLS_Protocol protocol;
+ /**
+ * Address information for the client.
+ */
+ struct sockaddr_in * client_addr;
+};
+
+/**
+ * Obtain information about the given connection.
+ *
+ * @param connection what connection to get information about
+ * @param infoType what information is desired?
+ * @param ... depends on infoType
+ * @return NULL if this information is not available
+ * (or if the infoType is unknown)
+ */
+const union MHD_ConnectionInfo *MHD_get_connection_info (struct MHD_Connection
+ *connection,
+ enum
+ MHD_ConnectionInfoType
+ infoType, ...);
+
+
+/**
+ * Information about an MHD daemon.
+ */
+union MHD_DaemonInfo
+{
+ /**
+ * Size of the key (unit??)
+ */
+ size_t key_size;
+
+ /**
+ * Size of the mac key (unit??)
+ */
+ size_t mac_key_size;
+
+ /**
+ * Listen socket file descriptor
+ */
+ int listen_fd;
+};
+
+/**
+ * Obtain information about the given daemon
+ * (not fully implemented!).
+ *
+ * @param daemon what daemon to get information about
+ * @param infoType what information is desired?
+ * @param ... depends on infoType
+ * @return NULL if this information is not available
+ * (or if the infoType is unknown)
+ */
+const union MHD_DaemonInfo *MHD_get_daemon_info (struct MHD_Daemon *daemon,
+ enum MHD_DaemonInfoType
+ infoType, ...);
+
+/**
+ * Obtain the version of this library
+ *
+ * @return static version string, e.g. "0.4.1"
+ */
+const char* MHD_get_version(void);
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libmicrohttpd/src/include/platform.h b/lib/libmicrohttpd/src/include/platform.h
new file mode 100644
index 0000000000..431ae48017
--- /dev/null
+++ b/lib/libmicrohttpd/src/include/platform.h
@@ -0,0 +1,115 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file platform.h
+ * @brief platform-specific includes for libmicrohttpd
+ * @author Christian Grothoff
+ *
+ * This file is included by the libmicrohttpd code
+ * before "microhttpd.h"; it provides the required
+ * standard headers (which are platform-specific).<p>
+ *
+ * Note that this file depends on our configure.ac
+ * build process and the generated config.h file.
+ * Hence you cannot include it directly in applications
+ * that use libmicrohttpd.
+ */
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+#include "MHD_config.h"
+
+#define _XOPEN_SOURCE_EXTENDED 1
+#if OS390
+#define _OPEN_THREADS
+#define _OPEN_SYS_SOCK_IPV6
+#define _OPEN_MSGQ_EXT
+#define _LP64
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#if !defined(MINGW) && !defined(__SYMBIAN32__)
+#include <search.h>
+#endif
+#include <stddef.h>
+#undef HAVE_CONFIG_H
+#include <pthread.h>
+#define HAVE_CONFIG_H 1
+
+/* different OSes have fd_set in
+ a broad range of header files;
+ we just include most of them (if they
+ are available) */
+
+
+#ifdef OS_VXWORKS
+#include <sockLib.h>
+#include <netinet/in.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#define RESTRICT __restrict__
+#endif
+
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_MSG_H
+#include <sys/msg.h>
+#endif
+#if HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_TIME_H
+#include <time.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "plibc.h"
+
+
+#endif
diff --git a/lib/libmicrohttpd/src/include/plibc.h b/lib/libmicrohttpd/src/include/plibc.h
new file mode 100644
index 0000000000..a1d3b13161
--- /dev/null
+++ b/lib/libmicrohttpd/src/include/plibc.h
@@ -0,0 +1,809 @@
+/*
+ This file is part of PlibC.
+ (C) 2005, 2006, 2007, 2008, 2009 Nils Durner (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/**
+ * @file include/plibc.h
+ * @brief PlibC header
+ * @attention This file is usually not installed under Unix,
+ * so ship it with your application
+ * @version $Revision: 39 $
+ */
+
+#ifndef _PLIBC_H_
+#define _PLIBC_H_
+
+#ifndef SIGALRM
+#define SIGALRM 14
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h>
+
+#ifdef Q_OS_WIN32
+#define WINDOWS 1
+#endif
+
+#define HAVE_PLIBC_FD 0
+
+#ifdef WINDOWS
+
+#if ENABLE_NLS
+#include "langinfo.h"
+#endif
+
+#include <windows.h>
+#include <Ws2tcpip.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+
+/* Conflicts with our definitions */
+#define __G_WIN32_H__
+
+/* Convert LARGE_INTEGER to double */
+#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + \
+ (double)((x).LowPart))
+
+#define socklen_t int
+#define ssize_t int
+#define off_t int
+#define int64_t long long
+#define int32_t long
+
+ struct stat64
+ {
+ _dev_t st_dev;
+ _ino_t st_ino;
+ _mode_t st_mode;
+ short st_nlink;
+ short st_uid;
+ short st_gid;
+ _dev_t st_rdev;
+ __int64 st_size;
+ __time64_t st_atime;
+ __time64_t st_mtime;
+ __time64_t st_ctime;
+ };
+
+#ifndef pid_t
+#define pid_t int
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
+#endif
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+
+/* Thanks to the Cygwin project */
+#define ENOCSI 43 /* No CSI structure available */
+#define EL2HLT 44 /* Level 2 halted */
+#ifndef EDEADLK
+#define EDEADLK 45 /* Deadlock condition */
+#endif
+#ifndef ENOLCK
+#define ENOLCK 46 /* No record locks available */
+#endif
+#define EBADE 50 /* Invalid exchange */
+#define EBADR 51 /* Invalid request descriptor */
+#define EXFULL 52 /* Exchange full */
+#define ENOANO 53 /* No anode */
+#define EBADRQC 54 /* Invalid request code */
+#define EBADSLT 55 /* Invalid slot */
+#ifndef EDEADLOCK
+#define EDEADLOCK EDEADLK /* File locking deadlock error */
+#endif
+#define EBFONT 57 /* Bad font file fmt */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data (for no delay io) */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* The object is remote */
+#define ENOLINK 67 /* The link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 74 /* Multihop attempted */
+#define ELBIN 75 /* Inode is remote (not really error) */
+#define EDOTDOT 76 /* Cross mount point (not really error) */
+#define EBADMSG 77 /* Trying to read unreadable message */
+#define ENOTUNIQ 80 /* Given log. name not unique */
+#define EBADFD 81 /* f.d. invalid for this operation */
+#define EREMCHG 82 /* Remote address changed */
+#define ELIBACC 83 /* Can't access a needed shared lib */
+#define ELIBBAD 84 /* Accessing a corrupted shared lib */
+#define ELIBSCN 85 /* .lib section in a.out corrupted */
+#define ELIBMAX 86 /* Attempting to link in too many libs */
+#define ELIBEXEC 87 /* Attempting to exec a shared library */
+#ifndef ENOSYS
+#define ENOSYS 88 /* Function not implemented */
+#endif
+#define ENMFILE 89 /* No more files */
+#ifndef ENOTEMPTY
+#define ENOTEMPTY 90 /* Directory not empty */
+#endif
+#ifndef ENAMETOOLONG
+#define ENAMETOOLONG 91 /* File or path name too long */
+#endif
+#define ELOOP 92 /* Too many symbolic links */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
+#define EPROTOTYPE 107 /* Protocol wrong type for socket */
+#define ENOTSOCK 108 /* Socket operation on non-socket */
+#define ENOPROTOOPT 109 /* Protocol not available */
+#define ESHUTDOWN 110 /* Can't send after socket shutdown */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EADDRINUSE 112 /* Address already in use */
+#define ECONNABORTED 113 /* Connection aborted */
+#define ENETUNREACH 114 /* Network is unreachable */
+#define ENETDOWN 115 /* Network interface is not configured */
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 116 /* Connection timed out */
+#endif
+#define EHOSTDOWN 117 /* Host is down */
+#define EHOSTUNREACH 118 /* Host is unreachable */
+#define EINPROGRESS 119 /* Connection already in progress */
+#define EALREADY 120 /* Socket already connected */
+#define EDESTADDRREQ 121 /* Destination address required */
+#define EMSGSIZE 122 /* Message too long */
+#define EPROTONOSUPPORT 123 /* Unknown protocol */
+#define ESOCKTNOSUPPORT 124 /* Socket type not supported */
+#define EADDRNOTAVAIL 125 /* Address not available */
+#define ENETRESET 126 /* Connection aborted by network */
+#define EISCONN 127 /* Socket is already connected */
+#define ENOTCONN 128 /* Socket is not connected */
+#define ETOOMANYREFS 129 /* Too many references: cannot splice */
+#define EPROCLIM 130 /* Too many processes */
+#define EUSERS 131 /* Too many users */
+#define EDQUOT 132 /* Disk quota exceeded */
+#define ESTALE 133 /* Unknown error */
+#ifndef ENOTSUP
+#define ENOTSUP 134 /* Not supported */
+#endif
+#define ENOMEDIUM 135 /* No medium (in tape drive) */
+#define ENOSHARE 136 /* No such host or network path */
+#define ECASECLASH 137 /* Filename exists with different case */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define EOVERFLOW 139 /* Value too large for defined data type */
+
+#undef HOST_NOT_FOUND
+#define HOST_NOT_FOUND 1
+#undef TRY_AGAIN
+#define TRY_AGAIN 2
+#undef NO_RECOVERY
+#define NO_RECOVERY 3
+#undef NO_ADDRESS
+#define NO_ADDRESS 4
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define MAP_SHARED 0x1
+#define MAP_PRIVATE 0x2 /* unsupported */
+#define MAP_FIXED 0x10
+#define MAP_FAILED ((void *)-1)
+
+ struct statfs
+ {
+ long f_type; /* type of filesystem (see below) */
+ long f_bsize; /* optimal transfer block size */
+ long f_blocks; /* total data blocks in file system */
+ long f_bfree; /* free blocks in fs */
+ long f_bavail; /* free blocks avail to non-superuser */
+ long f_files; /* total file nodes in file system */
+ long f_ffree; /* free file nodes in fs */
+ long f_fsid; /* file system id */
+ long f_namelen; /* maximum length of filenames */
+ long f_spare[6]; /* spare for later */
+ };
+
+ extern const struct in6_addr in6addr_any; /* :: */
+ extern const struct in6_addr in6addr_loopback; /* ::1 */
+
+/* Taken from the Wine project <http://www.winehq.org>
+ /wine/include/winternl.h */
+ enum SYSTEM_INFORMATION_CLASS
+ {
+ SystemBasicInformation = 0,
+ Unknown1,
+ SystemPerformanceInformation = 2,
+ SystemTimeOfDayInformation = 3, /* was SystemTimeInformation */
+ Unknown4,
+ SystemProcessInformation = 5,
+ Unknown6,
+ Unknown7,
+ SystemProcessorPerformanceInformation = 8,
+ Unknown9,
+ Unknown10,
+ SystemDriverInformation,
+ Unknown12,
+ Unknown13,
+ Unknown14,
+ Unknown15,
+ SystemHandleList,
+ Unknown17,
+ Unknown18,
+ Unknown19,
+ Unknown20,
+ SystemCacheInformation,
+ Unknown22,
+ SystemInterruptInformation = 23,
+ SystemExceptionInformation = 33,
+ SystemRegistryQuotaInformation = 37,
+ SystemLookasideInformation = 45
+ };
+
+ typedef struct
+ {
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER Reserved1[2];
+ ULONG Reserved2;
+ } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
+
+#define sleep(secs) (Sleep(secs * 1000))
+
+/*********************** statfs *****************************/
+/* fake block size */
+#define FAKED_BLOCK_SIZE 512
+
+/* linux-compatible values for fs type */
+#define MSDOS_SUPER_MAGIC 0x4d44
+#define NTFS_SUPER_MAGIC 0x5346544E
+
+/*********************** End of statfs ***********************/
+
+#define SHUT_RDWR SD_BOTH
+
+/* Operations for flock() */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+/* Not supported under MinGW */
+#define S_IRGRP 0
+#define S_IWGRP 0
+#define S_IROTH 0
+#define S_IXGRP 0
+#define S_IWOTH 0
+#define S_IXOTH 0
+#define S_ISUID 0
+#define S_ISGID 0
+#define S_ISVTX 0
+#define S_IRWXG 0
+#define S_IRWXO 0
+
+#define SHUT_WR SD_SEND
+#define SHUT_RD SD_RECEIVE
+#define SHUT_RDWR SD_BOTH
+
+#define SIGKILL 9
+#define SIGTERM 15
+
+#define SetErrnoFromWinError(e) _SetErrnoFromWinError(e, __FILE__, __LINE__)
+
+ BOOL _plibc_CreateShortcut (const char *pszSrc, const char *pszDest);
+ BOOL _plibc_DereferenceShortcut (char *pszShortcut);
+ char *plibc_ChooseDir (char *pszTitle, unsigned long ulFlags);
+ char *plibc_ChooseFile (char *pszTitle, unsigned long ulFlags);
+ long QueryRegistry (HKEY hMainKey, char *pszKey, char *pszSubKey,
+ char *pszBuffer, long *pdLength);
+
+ BOOL __win_IsHandleMarkedAsBlocking (SOCKET hHandle);
+ void __win_SetHandleBlockingMode (SOCKET s, BOOL bBlocking);
+ void __win_DiscardHandleBlockingMode (SOCKET s);
+ int _win_isSocketValid (int s);
+ int plibc_conv_to_win_path (const char *pszUnix, char *pszWindows);
+ unsigned plibc_get_handle_count ();
+
+ typedef void (*TPanicProc) (int, char *);
+ void plibc_set_panic_proc (TPanicProc proc);
+
+ int flock (int fd, int operation);
+ int fsync (int fildes);
+ int inet_pton (int af, const char *src, void *dst);
+ int inet_pton4 (const char *src, u_char * dst, int pton);
+#if USE_IPV6
+ int inet_pton6 (const char *src, u_char * dst);
+#endif
+ int truncate (const char *fname, int distance);
+ int statfs (const char *path, struct statfs *buf);
+ const char *hstrerror (int err);
+ int mkstemp (char *tmplate);
+ char *strptime (const char *buf, const char *format, struct tm *tm);
+ const char *inet_ntop (int af, const void *src, char *dst, size_t size);
+
+ int plibc_init (char *pszOrg, char *pszApp);
+ void plibc_shutdown ();
+ int plibc_initialized ();
+ int plibc_conv_to_win_path_ex (const char *pszUnix, char *pszWindows,
+ int derefLinks);
+ void _SetErrnoFromWinError (long lWinError, char *pszCaller, int iLine);
+ void SetErrnoFromWinsockError (long lWinError);
+ void SetHErrnoFromWinError (long lWinError);
+ void SetErrnoFromHRESULT (HRESULT hRes);
+ int GetErrnoFromWinsockError (long lWinError);
+ FILE *_win_fopen (const char *filename, const char *mode);
+ DIR *_win_opendir (const char *dirname);
+ int _win_open (const char *filename, int oflag, ...);
+#ifdef ENABLE_NLS
+ char *_win_bindtextdomain (const char *domainname, const char *dirname);
+#endif
+ int _win_chdir (const char *path);
+ int _win_close (int fd);
+ int _win_creat (const char *path, mode_t mode);
+ char *_win_ctime (const time_t * clock);
+ char *_win_ctime_r (const time_t * clock, char *buf);
+ int _win_fstat (int handle, struct stat *buffer);
+ int _win_ftruncate (int fildes, off_t length);
+ void _win_gettimeofday (struct timeval *tp, void *tzp);
+ int _win_kill (pid_t pid, int sig);
+ int _win_pipe (int *phandles);
+ int _win_rmdir (const char *path);
+ int _win_access (const char *path, int mode);
+ int _win_chmod (const char *filename, int pmode);
+ char *realpath (const char *file_name, char *resolved_name);
+ long _win_random (void);
+ int _win_remove (const char *path);
+ int _win_rename (const char *oldname, const char *newname);
+ int _win_stat (const char *path, struct stat *buffer);
+ int _win_stat64 (const char *path, struct stat64 *buffer);
+ int _win_unlink (const char *filename);
+ int _win_write (int fildes, const void *buf, size_t nbyte);
+ int _win_read (int fildes, void *buf, size_t nbyte);
+ size_t _win_fwrite (const void *buffer, size_t size, size_t count,
+ FILE * stream);
+ size_t _win_fread (void *buffer, size_t size, size_t count, FILE * stream);
+ int _win_symlink (const char *path1, const char *path2);
+ void *_win_mmap (void *start, size_t len, int access, int flags, int fd,
+ unsigned long long offset);
+ int _win_munmap (void *start, size_t length);
+ int _win_lstat (const char *path, struct stat *buf);
+ int _win_lstat64 (const char *path, struct stat64 *buf);
+ int _win_readlink (const char *path, char *buf, size_t bufsize);
+ int _win_accept (SOCKET s, struct sockaddr *addr, int *addrlen);
+ int _win_printf (const char *format, ...);
+ int _win_fprintf (FILE * f, const char *format, ...);
+ int _win_vprintf (const char *format, va_list ap);
+ int _win_vfprintf (FILE * stream, const char *format, va_list arg_ptr);
+ int _win_vsprintf (char *dest, const char *format, va_list arg_ptr);
+ int _win_vsnprintf (char *str, size_t size, const char *format,
+ va_list arg_ptr);
+ int _win_snprintf (char *str, size_t size, const char *format, ...);
+ int _win_sprintf (char *dest, const char *format, ...);
+ int _win_vsscanf (const char *str, const char *format, va_list arg_ptr);
+ int _win_sscanf (const char *str, const char *format, ...);
+ int _win_vfscanf (FILE * stream, const char *format, va_list arg_ptr);
+ int _win_vscanf (const char *format, va_list arg_ptr);
+ int _win_scanf (const char *format, ...);
+ int _win_fscanf (FILE * stream, const char *format, ...);
+ pid_t _win_waitpid (pid_t pid, int *stat_loc, int options);
+ int _win_bind (SOCKET s, const struct sockaddr *name, int namelen);
+ int _win_connect (SOCKET s, const struct sockaddr *name, int namelen);
+ int _win_getpeername (SOCKET s, struct sockaddr *name, int *namelen);
+ int _win_getsockname (SOCKET s, struct sockaddr *name, int *namelen);
+ int _win_getsockopt (SOCKET s, int level, int optname, char *optval,
+ int *optlen);
+ int _win_listen (SOCKET s, int backlog);
+ int _win_recv (SOCKET s, char *buf, int len, int flags);
+ int _win_recvfrom (SOCKET s, void *buf, int len, int flags,
+ struct sockaddr *from, int *fromlen);
+ int _win_select (int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds,
+ const struct timeval *tv);
+ int _win_send (SOCKET s, const char *buf, int len, int flags);
+ int _win_sendto (SOCKET s, const char *buf, int len, int flags,
+ const struct sockaddr *to, int tolen);
+ int _win_setsockopt (SOCKET s, int level, int optname, const void *optval,
+ int optlen);
+ int _win_shutdown (SOCKET s, int how);
+ SOCKET _win_socket (int af, int type, int protocol);
+ struct hostent *_win_gethostbyaddr (const char *addr, int len, int type);
+ struct hostent *_win_gethostbyname (const char *name);
+ struct hostent *gethostbyname2 (const char *name, int af);
+ char *_win_strerror (int errnum);
+ int IsWinNT ();
+ char *index (const char *s, int c);
+
+#if !HAVE_STRNDUP
+ char *strndup (const char *s, size_t n);
+#endif
+#if !HAVE_STRNLEN
+ size_t strnlen (const char *str, size_t maxlen);
+#endif
+
+#define strcasecmp(a, b) stricmp(a, b)
+#define strncasecmp(a, b, c) strnicmp(a, b, c)
+
+#endif /* WINDOWS */
+
+#ifndef WINDOWS
+#define DIR_SEPARATOR '/'
+#define DIR_SEPARATOR_STR "/"
+#define PATH_SEPARATOR ';'
+#define PATH_SEPARATOR_STR ";"
+#define NEWLINE "\n"
+
+#ifdef ENABLE_NLS
+#define BINDTEXTDOMAIN(d, n) bindtextdomain(d, n)
+#endif
+#define CREAT(p, m) creat(p, m)
+#define PLIBC_CTIME(c) ctime(c)
+#define CTIME_R(c, b) ctime_r(c, b)
+#undef FOPEN
+#define FOPEN(f, m) fopen(f, m)
+#define FTRUNCATE(f, l) ftruncate(f, l)
+#define OPENDIR(d) opendir(d)
+#define OPEN open
+#define CHDIR(d) chdir(d)
+#define CLOSE(f) close(f)
+#define LSEEK(f, o, w) lseek(f, o, w)
+#define RMDIR(f) rmdir(f)
+#define ACCESS(p, m) access(p, m)
+#define CHMOD(f, p) chmod(f, p)
+#define FSTAT(h, b) fstat(h, b)
+#define PLIBC_KILL(p, s) kill(p, s)
+#define PIPE(h) pipe(h)
+#define REMOVE(p) remove(p)
+#define RENAME(o, n) rename(o, n)
+#define STAT(p, b) stat(p, b)
+#define STAT64(p, b) stat64(p, b)
+#define UNLINK(f) unlink(f)
+#define WRITE(f, b, n) write(f, b, n)
+#define READ(f, b, n) read(f, b, n)
+#define GN_FREAD(b, s, c, f) fread(b, s, c, f)
+#define GN_FWRITE(b, s, c, f) fwrite(b, s, c, f)
+#define SYMLINK(a, b) symlink(a, b)
+#define MMAP(s, l, p, f, d, o) mmap(s, l, p, f, d, o)
+#define MUNMAP(s, l) munmap(s, l)
+#define STRERROR(i) strerror(i)
+#define RANDOM() random()
+#define READLINK(p, b, s) readlink(p, b, s)
+#define LSTAT(p, b) lstat(p, b)
+#define LSTAT64(p, b) lstat64(p, b)
+#define PRINTF printf
+#define FPRINTF fprintf
+#define VPRINTF(f, a) vprintf(f, a)
+#define VFPRINTF(s, f, a) vfprintf(s, f, a)
+#define VSPRINTF(d, f, a) vsprintf(d, f, a)
+#define VSNPRINTF(str, size, fmt, a) vsnprintf(str, size, fmt, a)
+#define _REAL_SNPRINTF snprintf
+#define SPRINTF sprintf
+#define VSSCANF(s, f, a) vsscanf(s, f, a)
+#define SSCANF sscanf
+#define VFSCANF(s, f, a) vfscanf(s, f, a)
+#define VSCANF(f, a) vscanf(f, a)
+#define SCANF scanf
+#define FSCANF fscanf
+#define WAITPID(p, s, o) waitpid(p, s, o)
+#define ACCEPT(s, a, l) accept(s, a, l)
+#define BIND(s, n, l) bind(s, n, l)
+#define CONNECT(s, n, l) connect(s, n, l)
+#define GETPEERNAME(s, n, l) getpeername(s, n, l)
+#define GETSOCKNAME(s, n, l) getsockname(s, n, l)
+#define GETSOCKOPT(s, l, o, v, p) getsockopt(s, l, o, v, p)
+#define LISTEN(s, b) listen(s, b)
+#define RECV(s, b, l, f) recv(s, b, l, f)
+#define RECVFROM(s, b, l, f, r, o) recvfrom(s, b, l, f, r, o)
+#define SELECT(n, r, w, e, t) select(n, r, w, e, t)
+#define SEND(s, b, l, f) send(s, b, l, f)
+#define SENDTO(s, b, l, f, o, n) sendto(s, b, l, f, o, n)
+#define SETSOCKOPT(s, l, o, v, n) setsockopt(s, l, o, v, n)
+#define SHUTDOWN(s, h) shutdown(s, h)
+#define SOCKET(a, t, p) socket(a, t, p)
+#define GETHOSTBYADDR(a, l, t) gethostbyname(a, l, t)
+#define GETHOSTBYNAME(n) gethostbyname(n)
+#define GETTIMEOFDAY(t, n) gettimeofday(t, n)
+#define INSQUE(e, p) insque(e, p)
+#define REMQUE(e) remque(e)
+
+#ifndef __SYMBIAN32__
+#define HSEARCH(i, a) hsearch(i, a)
+#define HCREATE(n) hcreate(n)
+#define HDESTROY() hdestroy()
+#define HSEARCH_R(i, a, r, h) hsearch_r(i, a, r, h)
+#define HCREATE_R(n, h) hcreate_r(n, h)
+#define HDESTROY_R(h) hdestroy_r(h)
+#define TSEARCH(k, r, c) tsearch(k, r, c)
+#define TFIND(k, r, c) tfind(k, r, c)
+#define TDELETE(k, r, c) tdelete(k, r, c)
+#define TWALK(r, a) twalk(r, a)
+#define TDESTROY(r, f) tdestroy(r, f)
+#define LFIND(k, b, n, s, c) lfind(k, b, n, s, c)
+#define LSEARCH(k, b, n, s, c) lsearch(k, b, n, s, c)
+#else // __SYMBIAN32__
+#define HSEARCH(i, a) _win_hsearch(i, a)
+#define HCREATE(n) _win_hcreate(n)
+#define HDESTROY() _win_hdestroy()
+#define HSEARCH_R(i, a, r, h) _win_hsearch_r(i, a, r, h)
+#define HCREATE_R(n, h) _win_hcreate_r(n, h)
+#define HDESTROY_R(h) _win_hdestroy_r(h)
+#define TSEARCH(k, r, c) _win_tsearch(k, r, c)
+#define TFIND(k, r, c) _win_tfind(k, r, c)
+#define TDELETE(k, r, c) _win_tdelete(k, r, c)
+#define TWALK(r, a) _win_twalk(r, a)
+#define TDESTROY(r, f) _win_tdestroy(r, f)
+#define LFIND(k, b, n, s, c) _win_lfind(k, b, n, s, c)
+#define LSEARCH(k, b, n, s, c) _win_lsearch(k, b, n, s, c)
+#endif // !__SYMBIAN32__
+
+#else
+#define DIR_SEPARATOR '\\'
+#define DIR_SEPARATOR_STR "\\"
+#define PATH_SEPARATOR ':'
+#define PATH_SEPARATOR_STR ":"
+#define NEWLINE "\r\n"
+
+#ifdef ENABLE_NLS
+#define BINDTEXTDOMAIN(d, n) _win_bindtextdomain(d, n)
+#endif
+#define CREAT(p, m) _win_creat(p, m)
+#define PLIBC_CTIME(c) _win_ctime(c)
+#define CTIME_R(c, b) _win_ctime_r(c, b)
+#define FOPEN(f, m) _win_fopen(f, m)
+#define FTRUNCATE(f, l) _win_ftruncate(f, l)
+#define OPENDIR(d) _win_opendir(d)
+#define OPEN _win_open
+#define CHDIR(d) _win_chdir(d)
+#define CLOSE(f) _win_close(f)
+#define PLIBC_KILL(p, s) _win_kill(p, s)
+#define LSEEK(f, o, w) _win_lseek(f, o, w)
+#define FSTAT(h, b) _win_fstat(h, b)
+#define RMDIR(f) _win_rmdir(f)
+#define ACCESS(p, m) _win_access(p, m)
+#define CHMOD(f, p) _win_chmod(f, p)
+#define PIPE(h) _win_pipe(h)
+#define RANDOM() _win_random()
+#define REMOVE(p) _win_remove(p)
+#define RENAME(o, n) _win_rename(o, n)
+#define STAT(p, b) _win_stat(p, b)
+#define STAT64(p, b) _win_stat64(p, b)
+#define UNLINK(f) _win_unlink(f)
+#define WRITE(f, b, n) _win_write(f, b, n)
+#define READ(f, b, n) _win_read(f, b, n)
+#define GN_FREAD(b, s, c, f) _win_fread(b, s, c, f)
+#define GN_FWRITE(b, s, c, f) _win_fwrite(b, s, c, f)
+#define SYMLINK(a, b) _win_symlink(a, b)
+#define MMAP(s, l, p, f, d, o) _win_mmap(s, l, p, f, d, o)
+#define MUNMAP(s, l) _win_munmap(s, l)
+#define STRERROR(i) _win_strerror(i)
+#define READLINK(p, b, s) _win_readlink(p, b, s)
+#define LSTAT(p, b) _win_lstat(p, b)
+#define LSTAT64(p, b) _win_lstat64(p, b)
+#define PRINTF(f, ...) _win_printf(f , __VA_ARGS__)
+#define FPRINTF(fil, fmt, ...) _win_fprintf(fil, fmt, __VA_ARGS__)
+#define VPRINTF(f, a) _win_vprintf(f, a)
+#define VFPRINTF(s, f, a) _win_vfprintf(s, f, a)
+#define VSPRINTF(d, f, a) _win_vsprintf(d, f, a)
+#define VSNPRINTF(str, size, fmt, a) _win_vsnprintf(str, size, fmt, a)
+#define _REAL_SNPRINTF(str, size, fmt, ...) _win_snprintf(str, size, fmt, __VA_ARGS__)
+#define SPRINTF(d, f, ...) _win_sprintf(d, f, __VA_ARGS__)
+#define VSSCANF(s, f, a) _win_vsscanf(s, f, a)
+#define SSCANF(s, f, ...) _win_sscanf(s, f, __VA_ARGS__)
+#define VFSCANF(s, f, a) _win_vfscanf(s, f, a)
+#define VSCANF(f, a) _win_vscanf(f, a)
+#define SCANF(f, ...) _win_scanf(f, __VA_ARGS__)
+#define FSCANF(s, f, ...) _win_fscanf(s, f, __VA_ARGS__)
+#define WAITPID(p, s, o) _win_waitpid(p, s, o)
+#define ACCEPT(s, a, l) _win_accept(s, a, l)
+#define BIND(s, n, l) _win_bind(s, n, l)
+#define CONNECT(s, n, l) _win_connect(s, n, l)
+#define GETPEERNAME(s, n, l) _win_getpeername(s, n, l)
+#define GETSOCKNAME(s, n, l) _win_getsockname(s, n, l)
+#define GETSOCKOPT(s, l, o, v, p) _win_getsockopt(s, l, o, v, p)
+#define LISTEN(s, b) _win_listen(s, b)
+#define RECV(s, b, l, f) _win_recv(s, b, l, f)
+#define RECVFROM(s, b, l, f, r, o) _win_recvfrom(s, b, l, f, r, o)
+#define SELECT(n, r, w, e, t) _win_select(n, r, w, e, t)
+#define SEND(s, b, l, f) _win_send(s, b, l, f)
+#define SENDTO(s, b, l, f, o, n) _win_sendto(s, b, l, f, o, n)
+#define SETSOCKOPT(s, l, o, v, n) _win_setsockopt(s, l, o, v, n)
+#define SHUTDOWN(s, h) _win_shutdown(s, h)
+#define SOCKET(a, t, p) _win_socket(a, t, p)
+#define GETHOSTBYADDR(a, l, t) _win_gethostbyname(a, l, t)
+#define GETHOSTBYNAME(n) _win_gethostbyname(n)
+#define GETTIMEOFDAY(t, n) _win_gettimeofday(t, n)
+#define INSQUE(e, p) _win_insque(e, p)
+#define REMQUE(e) _win_remque(e)
+#define HSEARCH(i, a) _win_hsearch(i, a)
+#define HCREATE(n) _win_hcreate(n)
+#define HDESTROY() _win_hdestroy()
+#define HSEARCH_R(i, a, r, h) _win_hsearch_r(i, a, r, h)
+#define HCREATE_R(n, h) _win_hcreate_r(n, h)
+#define HDESTROY_R(h) _win_hdestroy_r(h)
+#define TSEARCH(k, r, c) _win_tsearch(k, r, c)
+#define TFIND(k, r, c) _win_tfind(k, r, c)
+#define TDELETE(k, r, c) _win_tdelete(k, r, c)
+#define TWALK(r, a) _win_twalk(r, a)
+#define TDESTROY(r, f) _win_tdestroy(r, f)
+#define LFIND(k, b, n, s, c) _win_lfind(k, b, n, s, c)
+#define LSEARCH(k, b, n, s, c) _win_lsearch(k, b, n, s, c)
+#endif
+
+/* search.h */
+
+/* Prototype structure for a linked-list data structure.
+ This is the type used by the `insque' and `remque' functions. */
+
+ struct PLIBC_SEARCH_QELEM
+ {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char q_data[1];
+ };
+
+
+/* Insert ELEM into a doubly-linked list, after PREV. */
+ void _win_insque (void *__elem, void *__prev);
+
+/* Unlink ELEM from the doubly-linked list that it is in. */
+ void _win_remque (void *__elem);
+
+
+/* For use with hsearch(3). */
+ typedef int (*PLIBC_SEARCH__compar_fn_t) (__const void *, __const void *);
+
+ typedef PLIBC_SEARCH__compar_fn_t _win_comparison_fn_t;
+
+/* Action which shall be performed in the call the hsearch. */
+ typedef enum
+ {
+ PLIBC_SEARCH_FIND,
+ PLIBC_SEARCH_ENTER
+ }
+ PLIBC_SEARCH_ACTION;
+
+ typedef struct PLIBC_SEARCH_entry
+ {
+ char *key;
+ void *data;
+ }
+ PLIBC_SEARCH_ENTRY;
+
+/* The reentrant version has no static variables to maintain the state.
+ Instead the interface of all functions is extended to take an argument
+ which describes the current status. */
+ typedef struct _PLIBC_SEARCH_ENTRY
+ {
+ unsigned int used;
+ PLIBC_SEARCH_ENTRY entry;
+ }
+ _PLIBC_SEARCH_ENTRY;
+
+
+/* Family of hash table handling functions. The functions also
+ have reentrant counterparts ending with _r. The non-reentrant
+ functions all work on a signle internal hashing table. */
+
+/* Search for entry matching ITEM.key in internal hash table. If
+ ACTION is `FIND' return found entry or signal error by returning
+ NULL. If ACTION is `ENTER' replace existing data (if any) with
+ ITEM.data. */
+ PLIBC_SEARCH_ENTRY *_win_hsearch (PLIBC_SEARCH_ENTRY __item,
+ PLIBC_SEARCH_ACTION __action);
+
+/* Create a new hashing table which will at most contain NEL elements. */
+ int _win_hcreate (size_t __nel);
+
+/* Destroy current internal hashing table. */
+ void _win_hdestroy (void);
+
+/* Data type for reentrant functions. */
+ struct PLIBC_SEARCH_hsearch_data
+ {
+ struct _PLIBC_SEARCH_ENTRY *table;
+ unsigned int size;
+ unsigned int filled;
+ };
+
+/* Reentrant versions which can handle multiple hashing tables at the
+ same time. */
+ int _win_hsearch_r (PLIBC_SEARCH_ENTRY __item, PLIBC_SEARCH_ACTION __action,
+ PLIBC_SEARCH_ENTRY ** __retval,
+ struct PLIBC_SEARCH_hsearch_data *__htab);
+ int _win_hcreate_r (size_t __nel, struct PLIBC_SEARCH_hsearch_data *__htab);
+ void _win_hdestroy_r (struct PLIBC_SEARCH_hsearch_data *__htab);
+
+
+/* The tsearch routines are very interesting. They make many
+ assumptions about the compiler. It assumes that the first field
+ in node must be the "key" field, which points to the datum.
+ Everything depends on that. */
+/* For tsearch */
+ typedef enum
+ {
+ PLIBC_SEARCH_preorder,
+ PLIBC_SEARCH_postorder,
+ PLIBC_SEARCH_endorder,
+ PLIBC_SEARCH_leaf
+ }
+ PLIBC_SEARCH_VISIT;
+
+/* Search for an entry matching the given KEY in the tree pointed to
+ by *ROOTP and insert a new element if not found. */
+ void *_win_tsearch (__const void *__key, void **__rootp,
+ PLIBC_SEARCH__compar_fn_t __compar);
+
+/* Search for an entry matching the given KEY in the tree pointed to
+ by *ROOTP. If no matching entry is available return NULL. */
+ void *_win_tfind (__const void *__key, void *__const * __rootp,
+ PLIBC_SEARCH__compar_fn_t __compar);
+
+/* Remove the element matching KEY from the tree pointed to by *ROOTP. */
+ void *_win_tdelete (__const void *__restrict __key,
+ void **__restrict __rootp,
+ PLIBC_SEARCH__compar_fn_t __compar);
+
+ typedef void (*PLIBC_SEARCH__action_fn_t) (__const void *__nodep,
+ PLIBC_SEARCH_VISIT __value,
+ int __level);
+
+/* Walk through the whole tree and call the ACTION callback for every node
+ or leaf. */
+ void _win_twalk (__const void *__root, PLIBC_SEARCH__action_fn_t __action);
+
+/* Callback type for function to free a tree node. If the keys are atomic
+ data this function should do nothing. */
+ typedef void (*PLIBC_SEARCH__free_fn_t) (void *__nodep);
+
+/* Destroy the whole tree, call FREEFCT for each node or leaf. */
+ void _win_tdestroy (void *__root, PLIBC_SEARCH__free_fn_t __freefct);
+
+
+/* Perform linear search for KEY by comparing by COMPAR in an array
+ [BASE,BASE+NMEMB*SIZE). */
+ void *_win_lfind (__const void *__key, __const void *__base,
+ size_t * __nmemb, size_t __size,
+ PLIBC_SEARCH__compar_fn_t __compar);
+
+/* Perform linear search for KEY by comparing by COMPAR function in
+ array [BASE,BASE+NMEMB*SIZE) and insert entry if not found. */
+ void *_win_lsearch (__const void *__key, void *__base,
+ size_t * __nmemb, size_t __size,
+ PLIBC_SEARCH__compar_fn_t __compar);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //_PLIBC_H_
+
+/* end of plibc.h */
diff --git a/lib/libmicrohttpd/src/testcurl/Makefile.am b/lib/libmicrohttpd/src/testcurl/Makefile.am
new file mode 100644
index 0000000000..a4ed58fb1b
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/Makefile.am
@@ -0,0 +1,181 @@
+SUBDIRS = .
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+if ENABLE_HTTPS
+if MHD_DEBUG_TLS
+ SUBDIRS += https
+endif
+endif
+
+AM_CPPFLAGS = \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/daemon \
+-I$(top_srcdir)/src/include \
+$(LIBCURL_CPPFLAGS)
+
+check_PROGRAMS = \
+ daemontest_get \
+ daemontest_post \
+ daemontest_postform \
+ daemontest_post_loop \
+ daemontest_put \
+ daemontest_process_headers \
+ daemontest_process_arguments \
+ daemontest_parse_cookies \
+ daemontest_large_put \
+ daemontest_get11 \
+ daemontest_post11 \
+ daemontest_postform11 \
+ daemontest_post_loop11 \
+ daemontest_put11 \
+ daemontest_large_put11 \
+ daemontest_long_header \
+ daemontest_long_header11 \
+ daemontest_get_chunked \
+ daemontest_put_chunked \
+ daemontest_iplimit11 \
+ daemontest_termination
+noinst_PROGRAMS = \
+ daemon_options_test
+
+TESTS = $(check_PROGRAMS)
+
+noinst_LIBRARIES = libcurl_version_check.a
+
+libcurl_version_check_a_SOURCES = \
+ curl_version_check.c
+
+daemon_options_test_SOURCES = \
+ daemon_options_test.c
+daemon_options_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+daemontest_get_SOURCES = \
+ daemontest_get.c
+daemontest_get_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get_chunked_SOURCES = \
+ daemontest_get_chunked.c
+daemontest_get_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_SOURCES = \
+ daemontest_post.c
+daemontest_post_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_process_headers_SOURCES = \
+ daemontest_process_headers.c
+daemontest_process_headers_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_parse_cookies_SOURCES = \
+ daemontest_parse_cookies.c
+daemontest_parse_cookies_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_process_arguments_SOURCES = \
+ daemontest_process_arguments.c
+daemontest_process_arguments_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform_SOURCES = \
+ daemontest_postform.c
+daemontest_postform_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_loop_SOURCES = \
+ daemontest_post_loop.c
+daemontest_post_loop_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_SOURCES = \
+ daemontest_put.c
+daemontest_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_chunked_SOURCES = \
+ daemontest_put_chunked.c
+daemontest_put_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get11_SOURCES = \
+ daemontest_get.c
+daemontest_get11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post11_SOURCES = \
+ daemontest_post.c
+daemontest_post11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform11_SOURCES = \
+ daemontest_postform.c
+daemontest_postform11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_loop11_SOURCES = \
+ daemontest_post_loop.c
+daemontest_post_loop11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put11_SOURCES = \
+ daemontest_put.c
+daemontest_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put_SOURCES = \
+ daemontest_large_put.c
+daemontest_large_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put11_SOURCES = \
+ daemontest_large_put.c
+daemontest_large_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_long_header_SOURCES = \
+ daemontest_long_header.c
+daemontest_long_header_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_long_header11_SOURCES = \
+ daemontest_long_header.c
+daemontest_long_header11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_iplimit11_SOURCES = \
+ daemontest_iplimit.c
+daemontest_iplimit11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_termination_SOURCES = \
+ daemontest_termination.c
+daemontest_termination_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
diff --git a/lib/libmicrohttpd/src/testcurl/Makefile.in b/lib/libmicrohttpd/src/testcurl/Makefile.in
new file mode 100644
index 0000000000..7def1d4552
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/Makefile.in
@@ -0,0 +1,1147 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@ENABLE_HTTPS_TRUE@@MHD_DEBUG_TLS_TRUE@am__append_1 = https
+check_PROGRAMS = daemontest_get$(EXEEXT) daemontest_post$(EXEEXT) \
+ daemontest_postform$(EXEEXT) daemontest_post_loop$(EXEEXT) \
+ daemontest_put$(EXEEXT) daemontest_process_headers$(EXEEXT) \
+ daemontest_process_arguments$(EXEEXT) \
+ daemontest_parse_cookies$(EXEEXT) \
+ daemontest_large_put$(EXEEXT) daemontest_get11$(EXEEXT) \
+ daemontest_post11$(EXEEXT) daemontest_postform11$(EXEEXT) \
+ daemontest_post_loop11$(EXEEXT) daemontest_put11$(EXEEXT) \
+ daemontest_large_put11$(EXEEXT) \
+ daemontest_long_header$(EXEEXT) \
+ daemontest_long_header11$(EXEEXT) \
+ daemontest_get_chunked$(EXEEXT) \
+ daemontest_put_chunked$(EXEEXT) daemontest_iplimit11$(EXEEXT) \
+ daemontest_termination$(EXEEXT)
+noinst_PROGRAMS = daemon_options_test$(EXEEXT)
+subdir = src/testcurl
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libcurl_version_check_a_AR = $(AR) $(ARFLAGS)
+libcurl_version_check_a_LIBADD =
+am_libcurl_version_check_a_OBJECTS = curl_version_check.$(OBJEXT)
+libcurl_version_check_a_OBJECTS = \
+ $(am_libcurl_version_check_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_daemon_options_test_OBJECTS = daemon_options_test.$(OBJEXT)
+daemon_options_test_OBJECTS = $(am_daemon_options_test_OBJECTS)
+daemon_options_test_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_get_OBJECTS = daemontest_get.$(OBJEXT)
+daemontest_get_OBJECTS = $(am_daemontest_get_OBJECTS)
+daemontest_get_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_get11_OBJECTS = daemontest_get.$(OBJEXT)
+daemontest_get11_OBJECTS = $(am_daemontest_get11_OBJECTS)
+daemontest_get11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_get_chunked_OBJECTS = daemontest_get_chunked.$(OBJEXT)
+daemontest_get_chunked_OBJECTS = $(am_daemontest_get_chunked_OBJECTS)
+daemontest_get_chunked_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_iplimit11_OBJECTS = daemontest_iplimit.$(OBJEXT)
+daemontest_iplimit11_OBJECTS = $(am_daemontest_iplimit11_OBJECTS)
+daemontest_iplimit11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_large_put_OBJECTS = daemontest_large_put.$(OBJEXT)
+daemontest_large_put_OBJECTS = $(am_daemontest_large_put_OBJECTS)
+daemontest_large_put_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_large_put11_OBJECTS = daemontest_large_put.$(OBJEXT)
+daemontest_large_put11_OBJECTS = $(am_daemontest_large_put11_OBJECTS)
+daemontest_large_put11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_long_header_OBJECTS = daemontest_long_header.$(OBJEXT)
+daemontest_long_header_OBJECTS = $(am_daemontest_long_header_OBJECTS)
+daemontest_long_header_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_long_header11_OBJECTS = \
+ daemontest_long_header.$(OBJEXT)
+daemontest_long_header11_OBJECTS = \
+ $(am_daemontest_long_header11_OBJECTS)
+daemontest_long_header11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_parse_cookies_OBJECTS = \
+ daemontest_parse_cookies.$(OBJEXT)
+daemontest_parse_cookies_OBJECTS = \
+ $(am_daemontest_parse_cookies_OBJECTS)
+daemontest_parse_cookies_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_post_OBJECTS = daemontest_post.$(OBJEXT)
+daemontest_post_OBJECTS = $(am_daemontest_post_OBJECTS)
+daemontest_post_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_post11_OBJECTS = daemontest_post.$(OBJEXT)
+daemontest_post11_OBJECTS = $(am_daemontest_post11_OBJECTS)
+daemontest_post11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_post_loop_OBJECTS = daemontest_post_loop.$(OBJEXT)
+daemontest_post_loop_OBJECTS = $(am_daemontest_post_loop_OBJECTS)
+daemontest_post_loop_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_post_loop11_OBJECTS = daemontest_post_loop.$(OBJEXT)
+daemontest_post_loop11_OBJECTS = $(am_daemontest_post_loop11_OBJECTS)
+daemontest_post_loop11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_postform_OBJECTS = daemontest_postform.$(OBJEXT)
+daemontest_postform_OBJECTS = $(am_daemontest_postform_OBJECTS)
+daemontest_postform_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_postform11_OBJECTS = daemontest_postform.$(OBJEXT)
+daemontest_postform11_OBJECTS = $(am_daemontest_postform11_OBJECTS)
+daemontest_postform11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_process_arguments_OBJECTS = \
+ daemontest_process_arguments.$(OBJEXT)
+daemontest_process_arguments_OBJECTS = \
+ $(am_daemontest_process_arguments_OBJECTS)
+daemontest_process_arguments_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_process_headers_OBJECTS = \
+ daemontest_process_headers.$(OBJEXT)
+daemontest_process_headers_OBJECTS = \
+ $(am_daemontest_process_headers_OBJECTS)
+daemontest_process_headers_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_put_OBJECTS = daemontest_put.$(OBJEXT)
+daemontest_put_OBJECTS = $(am_daemontest_put_OBJECTS)
+daemontest_put_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_put11_OBJECTS = daemontest_put.$(OBJEXT)
+daemontest_put11_OBJECTS = $(am_daemontest_put11_OBJECTS)
+daemontest_put11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_put_chunked_OBJECTS = daemontest_put_chunked.$(OBJEXT)
+daemontest_put_chunked_OBJECTS = $(am_daemontest_put_chunked_OBJECTS)
+daemontest_put_chunked_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_termination_OBJECTS = daemontest_termination.$(OBJEXT)
+daemontest_termination_OBJECTS = $(am_daemontest_termination_OBJECTS)
+daemontest_termination_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libcurl_version_check_a_SOURCES) \
+ $(daemon_options_test_SOURCES) $(daemontest_get_SOURCES) \
+ $(daemontest_get11_SOURCES) $(daemontest_get_chunked_SOURCES) \
+ $(daemontest_iplimit11_SOURCES) \
+ $(daemontest_large_put_SOURCES) \
+ $(daemontest_large_put11_SOURCES) \
+ $(daemontest_long_header_SOURCES) \
+ $(daemontest_long_header11_SOURCES) \
+ $(daemontest_parse_cookies_SOURCES) $(daemontest_post_SOURCES) \
+ $(daemontest_post11_SOURCES) $(daemontest_post_loop_SOURCES) \
+ $(daemontest_post_loop11_SOURCES) \
+ $(daemontest_postform_SOURCES) \
+ $(daemontest_postform11_SOURCES) \
+ $(daemontest_process_arguments_SOURCES) \
+ $(daemontest_process_headers_SOURCES) \
+ $(daemontest_put_SOURCES) $(daemontest_put11_SOURCES) \
+ $(daemontest_put_chunked_SOURCES) \
+ $(daemontest_termination_SOURCES)
+DIST_SOURCES = $(libcurl_version_check_a_SOURCES) \
+ $(daemon_options_test_SOURCES) $(daemontest_get_SOURCES) \
+ $(daemontest_get11_SOURCES) $(daemontest_get_chunked_SOURCES) \
+ $(daemontest_iplimit11_SOURCES) \
+ $(daemontest_large_put_SOURCES) \
+ $(daemontest_large_put11_SOURCES) \
+ $(daemontest_long_header_SOURCES) \
+ $(daemontest_long_header11_SOURCES) \
+ $(daemontest_parse_cookies_SOURCES) $(daemontest_post_SOURCES) \
+ $(daemontest_post11_SOURCES) $(daemontest_post_loop_SOURCES) \
+ $(daemontest_post_loop11_SOURCES) \
+ $(daemontest_postform_SOURCES) \
+ $(daemontest_postform11_SOURCES) \
+ $(daemontest_process_arguments_SOURCES) \
+ $(daemontest_process_headers_SOURCES) \
+ $(daemontest_put_SOURCES) $(daemontest_put11_SOURCES) \
+ $(daemontest_put_chunked_SOURCES) \
+ $(daemontest_termination_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DIST_SUBDIRS = . https
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = . $(am__append_1)
+@USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage
+AM_CPPFLAGS = \
+-I$(top_srcdir) \
+-I$(top_srcdir)/src/daemon \
+-I$(top_srcdir)/src/include \
+$(LIBCURL_CPPFLAGS)
+
+TESTS = $(check_PROGRAMS)
+noinst_LIBRARIES = libcurl_version_check.a
+libcurl_version_check_a_SOURCES = \
+ curl_version_check.c
+
+daemon_options_test_SOURCES = \
+ daemon_options_test.c
+
+daemon_options_test_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+
+daemontest_get_SOURCES = \
+ daemontest_get.c
+
+daemontest_get_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get_chunked_SOURCES = \
+ daemontest_get_chunked.c
+
+daemontest_get_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_SOURCES = \
+ daemontest_post.c
+
+daemontest_post_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_process_headers_SOURCES = \
+ daemontest_process_headers.c
+
+daemontest_process_headers_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_parse_cookies_SOURCES = \
+ daemontest_parse_cookies.c
+
+daemontest_parse_cookies_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_process_arguments_SOURCES = \
+ daemontest_process_arguments.c
+
+daemontest_process_arguments_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform_SOURCES = \
+ daemontest_postform.c
+
+daemontest_postform_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_loop_SOURCES = \
+ daemontest_post_loop.c
+
+daemontest_post_loop_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_SOURCES = \
+ daemontest_put.c
+
+daemontest_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_chunked_SOURCES = \
+ daemontest_put_chunked.c
+
+daemontest_put_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get11_SOURCES = \
+ daemontest_get.c
+
+daemontest_get11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post11_SOURCES = \
+ daemontest_post.c
+
+daemontest_post11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform11_SOURCES = \
+ daemontest_postform.c
+
+daemontest_postform11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_loop11_SOURCES = \
+ daemontest_post_loop.c
+
+daemontest_post_loop11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put11_SOURCES = \
+ daemontest_put.c
+
+daemontest_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put_SOURCES = \
+ daemontest_large_put.c
+
+daemontest_large_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put11_SOURCES = \
+ daemontest_large_put.c
+
+daemontest_large_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_long_header_SOURCES = \
+ daemontest_long_header.c
+
+daemontest_long_header_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_long_header11_SOURCES = \
+ daemontest_long_header.c
+
+daemontest_long_header11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_iplimit11_SOURCES = \
+ daemontest_iplimit.c
+
+daemontest_iplimit11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_termination_SOURCES = \
+ daemontest_termination.c
+
+daemontest_termination_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/testcurl/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/testcurl/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libcurl_version_check.a: $(libcurl_version_check_a_OBJECTS) $(libcurl_version_check_a_DEPENDENCIES)
+ -rm -f libcurl_version_check.a
+ $(libcurl_version_check_a_AR) libcurl_version_check.a $(libcurl_version_check_a_OBJECTS) $(libcurl_version_check_a_LIBADD)
+ $(RANLIB) libcurl_version_check.a
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+daemon_options_test$(EXEEXT): $(daemon_options_test_OBJECTS) $(daemon_options_test_DEPENDENCIES)
+ @rm -f daemon_options_test$(EXEEXT)
+ $(LINK) $(daemon_options_test_OBJECTS) $(daemon_options_test_LDADD) $(LIBS)
+daemontest_get$(EXEEXT): $(daemontest_get_OBJECTS) $(daemontest_get_DEPENDENCIES)
+ @rm -f daemontest_get$(EXEEXT)
+ $(LINK) $(daemontest_get_OBJECTS) $(daemontest_get_LDADD) $(LIBS)
+daemontest_get11$(EXEEXT): $(daemontest_get11_OBJECTS) $(daemontest_get11_DEPENDENCIES)
+ @rm -f daemontest_get11$(EXEEXT)
+ $(LINK) $(daemontest_get11_OBJECTS) $(daemontest_get11_LDADD) $(LIBS)
+daemontest_get_chunked$(EXEEXT): $(daemontest_get_chunked_OBJECTS) $(daemontest_get_chunked_DEPENDENCIES)
+ @rm -f daemontest_get_chunked$(EXEEXT)
+ $(LINK) $(daemontest_get_chunked_OBJECTS) $(daemontest_get_chunked_LDADD) $(LIBS)
+daemontest_iplimit11$(EXEEXT): $(daemontest_iplimit11_OBJECTS) $(daemontest_iplimit11_DEPENDENCIES)
+ @rm -f daemontest_iplimit11$(EXEEXT)
+ $(LINK) $(daemontest_iplimit11_OBJECTS) $(daemontest_iplimit11_LDADD) $(LIBS)
+daemontest_large_put$(EXEEXT): $(daemontest_large_put_OBJECTS) $(daemontest_large_put_DEPENDENCIES)
+ @rm -f daemontest_large_put$(EXEEXT)
+ $(LINK) $(daemontest_large_put_OBJECTS) $(daemontest_large_put_LDADD) $(LIBS)
+daemontest_large_put11$(EXEEXT): $(daemontest_large_put11_OBJECTS) $(daemontest_large_put11_DEPENDENCIES)
+ @rm -f daemontest_large_put11$(EXEEXT)
+ $(LINK) $(daemontest_large_put11_OBJECTS) $(daemontest_large_put11_LDADD) $(LIBS)
+daemontest_long_header$(EXEEXT): $(daemontest_long_header_OBJECTS) $(daemontest_long_header_DEPENDENCIES)
+ @rm -f daemontest_long_header$(EXEEXT)
+ $(LINK) $(daemontest_long_header_OBJECTS) $(daemontest_long_header_LDADD) $(LIBS)
+daemontest_long_header11$(EXEEXT): $(daemontest_long_header11_OBJECTS) $(daemontest_long_header11_DEPENDENCIES)
+ @rm -f daemontest_long_header11$(EXEEXT)
+ $(LINK) $(daemontest_long_header11_OBJECTS) $(daemontest_long_header11_LDADD) $(LIBS)
+daemontest_parse_cookies$(EXEEXT): $(daemontest_parse_cookies_OBJECTS) $(daemontest_parse_cookies_DEPENDENCIES)
+ @rm -f daemontest_parse_cookies$(EXEEXT)
+ $(LINK) $(daemontest_parse_cookies_OBJECTS) $(daemontest_parse_cookies_LDADD) $(LIBS)
+daemontest_post$(EXEEXT): $(daemontest_post_OBJECTS) $(daemontest_post_DEPENDENCIES)
+ @rm -f daemontest_post$(EXEEXT)
+ $(LINK) $(daemontest_post_OBJECTS) $(daemontest_post_LDADD) $(LIBS)
+daemontest_post11$(EXEEXT): $(daemontest_post11_OBJECTS) $(daemontest_post11_DEPENDENCIES)
+ @rm -f daemontest_post11$(EXEEXT)
+ $(LINK) $(daemontest_post11_OBJECTS) $(daemontest_post11_LDADD) $(LIBS)
+daemontest_post_loop$(EXEEXT): $(daemontest_post_loop_OBJECTS) $(daemontest_post_loop_DEPENDENCIES)
+ @rm -f daemontest_post_loop$(EXEEXT)
+ $(LINK) $(daemontest_post_loop_OBJECTS) $(daemontest_post_loop_LDADD) $(LIBS)
+daemontest_post_loop11$(EXEEXT): $(daemontest_post_loop11_OBJECTS) $(daemontest_post_loop11_DEPENDENCIES)
+ @rm -f daemontest_post_loop11$(EXEEXT)
+ $(LINK) $(daemontest_post_loop11_OBJECTS) $(daemontest_post_loop11_LDADD) $(LIBS)
+daemontest_postform$(EXEEXT): $(daemontest_postform_OBJECTS) $(daemontest_postform_DEPENDENCIES)
+ @rm -f daemontest_postform$(EXEEXT)
+ $(LINK) $(daemontest_postform_OBJECTS) $(daemontest_postform_LDADD) $(LIBS)
+daemontest_postform11$(EXEEXT): $(daemontest_postform11_OBJECTS) $(daemontest_postform11_DEPENDENCIES)
+ @rm -f daemontest_postform11$(EXEEXT)
+ $(LINK) $(daemontest_postform11_OBJECTS) $(daemontest_postform11_LDADD) $(LIBS)
+daemontest_process_arguments$(EXEEXT): $(daemontest_process_arguments_OBJECTS) $(daemontest_process_arguments_DEPENDENCIES)
+ @rm -f daemontest_process_arguments$(EXEEXT)
+ $(LINK) $(daemontest_process_arguments_OBJECTS) $(daemontest_process_arguments_LDADD) $(LIBS)
+daemontest_process_headers$(EXEEXT): $(daemontest_process_headers_OBJECTS) $(daemontest_process_headers_DEPENDENCIES)
+ @rm -f daemontest_process_headers$(EXEEXT)
+ $(LINK) $(daemontest_process_headers_OBJECTS) $(daemontest_process_headers_LDADD) $(LIBS)
+daemontest_put$(EXEEXT): $(daemontest_put_OBJECTS) $(daemontest_put_DEPENDENCIES)
+ @rm -f daemontest_put$(EXEEXT)
+ $(LINK) $(daemontest_put_OBJECTS) $(daemontest_put_LDADD) $(LIBS)
+daemontest_put11$(EXEEXT): $(daemontest_put11_OBJECTS) $(daemontest_put11_DEPENDENCIES)
+ @rm -f daemontest_put11$(EXEEXT)
+ $(LINK) $(daemontest_put11_OBJECTS) $(daemontest_put11_LDADD) $(LIBS)
+daemontest_put_chunked$(EXEEXT): $(daemontest_put_chunked_OBJECTS) $(daemontest_put_chunked_DEPENDENCIES)
+ @rm -f daemontest_put_chunked$(EXEEXT)
+ $(LINK) $(daemontest_put_chunked_OBJECTS) $(daemontest_put_chunked_LDADD) $(LIBS)
+daemontest_termination$(EXEEXT): $(daemontest_termination_OBJECTS) $(daemontest_termination_DEPENDENCIES)
+ @rm -f daemontest_termination$(EXEEXT)
+ $(LINK) $(daemontest_termination_OBJECTS) $(daemontest_termination_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_version_check.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon_options_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_get.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_get_chunked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_iplimit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_large_put.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_long_header.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_parse_cookies.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_post.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_post_loop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_postform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_process_arguments.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_process_headers.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_put.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_put_chunked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_termination.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \
+ ctags-recursive install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/testcurl/curl_version_check.c b/lib/libmicrohttpd/src/testcurl/curl_version_check.c
new file mode 100644
index 0000000000..f794aa25eb
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/curl_version_check.c
@@ -0,0 +1,156 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file curl_version_check.c
+ * @brief verify required cURL version is available to run tests
+ * @author Sagie Amir
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int
+parse_version_number (const char **s)
+{
+ int i = 0;
+ char num[17];
+
+ while (i < 16 && ((**s >= '0') & (**s <= '9')))
+ {
+ num[i] = **s;
+ (*s)++;
+ i++;
+ }
+
+ num[i] = '\0';
+
+ return atoi (num);
+}
+
+const char *
+parse_version_string (const char *s, int *major, int *minor, int *micro)
+{
+ if (!s)
+ return NULL;
+ *major = parse_version_number (&s);
+ if (!s || *s != '.')
+ return NULL;
+ s++;
+ *minor = parse_version_number (&s);
+ if (*s != '.')
+ return NULL;
+ s++;
+ *micro = parse_version_number (&s);
+ return s;
+}
+
+
+/*
+ * check local libcurl version matches required version
+ */
+int
+curl_check_version (const char *req_version)
+{
+ const char *ver;
+ const char *curl_ver;
+#if HTTPS_SUPPORT
+ const char *ssl_ver;
+ const char *req_ssl_ver;
+#endif
+
+ int loc_major, loc_minor, loc_micro;
+ int rq_major, rq_minor, rq_micro;
+
+ ver = curl_version ();
+#if HAVE_MESSAGES
+ fprintf (stderr, "curl version: %s\n", ver);
+#endif
+ /*
+ * this call relies on the cURL string to be of the exact following format :
+ * 'libcurl/7.16.4 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/0.6.5' OR
+ * 'libcurl/7.18.2 GnuTLS/2.4.0 zlib/1.2.3.3 libidn/0.6.5'
+ */
+ curl_ver = strchr (ver, '/') + 1;
+
+ /* Parse version numbers */
+ parse_version_string (req_version, &rq_major, &rq_minor, &rq_micro);
+ parse_version_string (curl_ver, &loc_major, &loc_minor, &loc_micro);
+
+ /* Compare version numbers. */
+ if ((loc_major > rq_major
+ || (loc_major == rq_major && loc_minor > rq_minor)
+ || (loc_major == rq_major && loc_minor == rq_minor
+ && loc_micro > rq_micro) || (loc_major == rq_major
+ && loc_minor == rq_minor
+ && loc_micro == rq_micro)) == 0)
+ {
+ fprintf (stderr,
+ "Error: running curl test depends on local libcurl version > %s\n",
+ req_version);
+ return -1;
+ }
+
+ /*
+ * enforce required gnutls/openssl version.
+ * TODO use curl version string to assert use of gnutls
+ */
+#if HTTPS_SUPPORT
+ ssl_ver = strchr (curl_ver, ' ') + 1;
+
+ if (strncmp ("GnuTLS", ssl_ver, strlen ("GNUtls")) == 0)
+ {
+ ssl_ver = strchr (ssl_ver, '/') + 1;
+ req_ssl_ver = MHD_REQ_CURL_GNUTLS_VERSION;
+ }
+ else if (strncmp ("OpenSSL", ssl_ver, strlen ("OpenSSL")) == 0)
+ {
+ ssl_ver = strchr (ssl_ver, '/') + 1;
+ req_ssl_ver = MHD_REQ_CURL_OPENSSL_VERSION;
+ }
+ else
+ {
+ fprintf (stderr, "Error: unrecognized curl ssl library\n");
+ return -1;
+ }
+
+ parse_version_string (req_ssl_ver, &rq_major, &rq_minor, &rq_micro);
+ parse_version_string (ssl_ver, &loc_major, &loc_minor, &loc_micro);
+
+ if ((loc_major > rq_major
+ || (loc_major == rq_major && loc_minor > rq_minor)
+ || (loc_major == rq_major && loc_minor == rq_minor
+ && loc_micro > rq_micro) || (loc_major == rq_major
+ && loc_minor == rq_minor
+ && loc_micro == rq_micro)) == 0)
+ {
+ fprintf (stderr,
+ "Error: running curl test depends on local libcurl SSL version > %s\n",
+ req_ssl_ver);
+ return -1;
+ }
+#endif
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemon_options_test.c b/lib/libmicrohttpd/src/testcurl/daemon_options_test.c
new file mode 100644
index 0000000000..7a387d9446
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemon_options_test.c
@@ -0,0 +1,127 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_get_test.c
+ * @brief Testcase for libmicrohttpd HTTPS GET operations
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+
+#define MHD_E_MEM "Error: memory error\n"
+#define MHD_E_SERVER_INIT "Error: failed to start server\n"
+
+const int DEBUG_GNUTLS_LOG_LEVEL = 0;
+const char *test_file_name = "https_test_file";
+const char test_file_data[] = "Hello World\n";
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ return 0;
+}
+
+int
+test_wrap (char *test_name, int (*test) (void))
+{
+ int ret;
+
+ fprintf (stdout, "running test: %s ", test_name);
+ ret = test ();
+ if (ret == 0)
+ {
+ fprintf (stdout, "[pass]\n");
+ }
+ else
+ {
+ fprintf (stdout, "[fail]\n");
+ }
+ return ret;
+}
+
+
+/**
+ * Test daemon initialization with the MHD_OPTION_SOCK_ADDR option
+ */
+static int
+test_ip_addr_option ()
+{
+ struct MHD_Daemon *d;
+ struct sockaddr_in daemon_ip_addr;
+#if HAVE_INET6
+ struct sockaddr_in6 daemon_ip_addr6;
+#endif
+
+ memset (&daemon_ip_addr, 0, sizeof (struct sockaddr_in));
+ daemon_ip_addr.sin_family = AF_INET;
+ daemon_ip_addr.sin_port = htons (42433);
+
+#if HAVE_INET6
+ memset (&daemon_ip_addr6, 0, sizeof (struct sockaddr_in6));
+ daemon_ip_addr6.sin6_family = AF_INET6;
+ daemon_ip_addr6.sin6_port = htons (42433);
+#endif
+
+ inet_pton (AF_INET, "127.0.0.1", &daemon_ip_addr.sin_addr);
+#if HAVE_INET6
+ inet_pton (AF_INET6, "::ffff:127.0.0.1", &daemon_ip_addr6.sin6_addr);
+#endif
+
+ d = MHD_start_daemon (MHD_USE_DEBUG, 42433,
+ NULL, NULL, &ahc_echo, NULL, MHD_OPTION_SOCK_ADDR,
+ &daemon_ip_addr, MHD_OPTION_END);
+
+ if (d == 0)
+ return -1;
+
+ MHD_stop_daemon (d);
+
+#if HAVE_INET6
+ d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_IPv6, 42433,
+ NULL, NULL, &ahc_echo, NULL, MHD_OPTION_SOCK_ADDR,
+ &daemon_ip_addr6, MHD_OPTION_END);
+
+ if (d == 0)
+ return -1;
+
+ MHD_stop_daemon (d);
+#endif
+
+ return 0;
+}
+
+/* setup a temporary transfer test file */
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ errorCount += test_wrap ("ip addr option", &test_ip_addr_option);
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_get.c b/lib/libmicrohttpd/src/testcurl/daemontest_get.c
new file mode 100644
index 0000000000..43870177f8
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_get.c
@@ -0,0 +1,501 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get.c
+ * @brief Testcase for libmicrohttpd GET operations
+ * TODO: test parsing of query
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+
+static int
+testInternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system!*/
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testMultithreadedPoolGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system!*/
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+static int
+testUnknownPortGet ()
+{
+ struct MHD_Daemon *d;
+ const union MHD_DaemonInfo *di;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_SOCK_ADDR, &addr,
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 32768;
+
+ di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD);
+ if (di == NULL)
+ return 65536;
+
+ if (0 != getsockname(di->listen_fd, &addr, &addr_len))
+ return 131072;
+
+ if (addr.sin_family != AF_INET)
+ return 26214;
+
+ snprintf(buf, sizeof(buf), "http://localhost:%hu/hello_world",
+ ntohs(addr.sin_port));
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, buf);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 524288;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 1048576;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 2097152;
+ return 0;
+}
+
+
+static int
+testStopRace ()
+{
+ struct sockaddr_in sin;
+ int fd;
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ {
+ fprintf(stderr, "socket: %m\n");
+ return 256;
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(1081);
+ sin.sin_addr.s_addr = htonl(0x7f000001);
+
+ if (connect(fd, (struct sockaddr *)(&sin), sizeof(sin)) < 0)
+ {
+ fprintf(stderr, "connect: %m\n");
+ return 512;
+ }
+
+ /* printf("Waiting\n"); */
+ /* Let the thread get going. */
+ usleep(500000);
+
+ /* printf("Stopping daemon\n"); */
+ MHD_stop_daemon (d);
+
+ close(fd);
+
+ /* printf("good\n"); */
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalGet ();
+ errorCount += testMultithreadedGet ();
+ errorCount += testMultithreadedPoolGet ();
+ errorCount += testExternalGet ();
+ errorCount += testUnknownPortGet ();
+ errorCount += testStopRace ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_get_chunked.c b/lib/libmicrohttpd/src/testcurl/daemontest_get_chunked.c
new file mode 100644
index 0000000000..da11e90c92
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_get_chunked.c
@@ -0,0 +1,405 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get_chunked.c
+ * @brief Testcase for libmicrohttpd GET operations with chunked content encoding
+ * TODO:
+ * - how to test that chunking was actually used?
+ * - use CURLOPT_HEADERFUNCTION to validate
+ * footer was sent
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+/**
+ * MHD content reader callback that returns
+ * data in chunks.
+ */
+static int
+crc (void *cls, uint64_t pos, char *buf, int max)
+{
+ struct MHD_Response **responseptr = cls;
+
+ if (pos == 128 * 10)
+ {
+ MHD_add_response_header (*responseptr, "Footer", "working");
+ return -1; /* end of stream */
+ }
+ if (max < 128)
+ abort (); /* should not happen in this testcase... */
+ memset (buf, 'A' + (pos / 128), 128);
+ return 128;
+}
+
+/**
+ * Dummy function that does nothing.
+ */
+static void
+crcf (void *ptr)
+{
+ free (ptr);
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ struct MHD_Response **responseptr;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ responseptr = malloc (sizeof (struct MHD_Response *));
+ response = MHD_create_response_from_callback (-1,
+ 1024,
+ &crc, responseptr, &crcf);
+ *responseptr = response;
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+static int
+validate (struct CBC cbc, int ebase)
+{
+ int i;
+ char buf[128];
+
+ if (cbc.pos != 128 * 10)
+ return ebase;
+
+ for (i = 0; i < 10; i++)
+ {
+ memset (buf, 'A' + i, 128);
+ if (0 != memcmp (buf, &cbc.buf[i * 128], 128))
+ {
+ fprintf (stderr,
+ "Got `%.*s'\nWant `%.*s'\n",
+ 128, buf, 128, &cbc.buf[i * 128]);
+ return ebase * 2;
+ }
+ }
+ return 0;
+}
+
+static int
+testInternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return validate (cbc, 4);
+}
+
+static int
+testMultithreadedGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return validate (cbc, 64);
+}
+
+static int
+testMultithreadedPoolGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return validate (cbc, 64);
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ return validate (cbc, 8192);
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalGet ();
+ errorCount += testMultithreadedGet ();
+ errorCount += testMultithreadedPoolGet ();
+ errorCount += testExternalGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_iplimit.c b/lib/libmicrohttpd/src/testcurl/daemontest_iplimit.c
new file mode 100644
index 0000000000..93e6b06c78
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_iplimit.c
@@ -0,0 +1,301 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get.c
+ * @brief Testcase for libmicrohttpd GET operations
+ * TODO: test parsing of query
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+static int
+testMultithreadedGet ()
+{
+ struct MHD_Daemon *d;
+ char buf[2048];
+ int k;
+
+ /* Test only valid for HTTP/1.1 (uses persistent connections) */
+ if (!oneone)
+ return 0;
+
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+
+ for (k = 0; k < 3; ++k)
+ {
+ struct CBC cbc[3];
+ CURL *cenv[3];
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ CURL *c;
+ CURLcode errornum;
+
+ cenv[i] = c = curl_easy_init ();
+ cbc[i].buf = buf;
+ cbc[i].size = 2048;
+ cbc[i].pos = 0;
+
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+ errornum = curl_easy_perform (c);
+ if ( ( (CURLE_OK != errornum) && (i < 2) ) ||
+ ( (CURLE_OK == errornum) && (i == 2) ) )
+ {
+ int j;
+
+ /* First 2 should succeed */
+ if (i < 2)
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+
+ /* Last request should have failed */
+ else
+ fprintf (stderr,
+ "No error on IP address over limit\n");
+
+ for (j = 0; j < i; ++j)
+ curl_easy_cleanup (cenv[j]);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ }
+
+ /* Cleanup the environments */
+ for (i = 0; i < 3; ++i)
+ curl_easy_cleanup (cenv[i]);
+
+ sleep(2);
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (cbc[i].pos != strlen ("/hello_world"))
+ {
+ MHD_stop_daemon (d);
+ return 64;
+ }
+ if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world")))
+ {
+ MHD_stop_daemon (d);
+ return 128;
+ }
+ }
+
+
+ }
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedPoolGet ()
+{
+ struct MHD_Daemon *d;
+ char buf[2048];
+ int k;
+
+ /* Test only valid for HTTP/1.1 (uses persistent connections) */
+ if (!oneone)
+ return 0;
+
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
+ MHD_OPTION_THREAD_POOL_SIZE, 4,
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+
+ for (k = 0; k < 3; ++k)
+ {
+ struct CBC cbc[3];
+ CURL *cenv[3];
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ CURL *c;
+ CURLcode errornum;
+
+ cenv[i] = c = curl_easy_init ();
+ cbc[i].buf = buf;
+ cbc[i].size = 2048;
+ cbc[i].pos = 0;
+
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+ errornum = curl_easy_perform (c);
+ if ( ( (CURLE_OK != errornum) && (i < 2) ) ||
+ ( (CURLE_OK == errornum) && (i == 2) ) )
+ {
+ int j;
+
+ /* First 2 should succeed */
+ if (i < 2)
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+
+ /* Last request should have failed */
+ else
+ fprintf (stderr,
+ "No error on IP address over limit\n");
+
+ for (j = 0; j < i; ++j)
+ curl_easy_cleanup (cenv[j]);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ }
+
+ /* Cleanup the environments */
+ for (i = 0; i < 3; ++i)
+ curl_easy_cleanup (cenv[i]);
+
+ sleep(2);
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (cbc[i].pos != strlen ("/hello_world"))
+ {
+ MHD_stop_daemon (d);
+ return 64;
+ }
+ if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world")))
+ {
+ MHD_stop_daemon (d);
+ return 128;
+ }
+ }
+
+
+ }
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testMultithreadedGet ();
+ errorCount += testMultithreadedPoolGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_large_put.c b/lib/libmicrohttpd/src/testcurl/daemontest_large_put.c
new file mode 100644
index 0000000000..f046de9f47
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_large_put.c
@@ -0,0 +1,469 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_large_put.c
+ * @brief Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+/**
+ * Do not make this much larger since we will hit the
+ * MHD default buffer limit and the test code is not
+ * written for incremental upload processing...
+ * (larger values will likely cause MHD to generate
+ * an internal server error -- which would be avoided
+ * by writing the putBuffer method in a more general
+ * fashion).
+ */
+#define PUT_SIZE (256 * 1024)
+
+static char *put_buffer;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+ unsigned int *pos = ptr;
+ unsigned int wrt;
+
+ wrt = size * nmemb;
+ if (wrt > PUT_SIZE - (*pos))
+ wrt = PUT_SIZE - (*pos);
+ memcpy (stream, &put_buffer[*pos], wrt);
+ (*pos) += wrt;
+ return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ int *done = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp ("PUT", method))
+ return MHD_NO; /* unexpected method */
+ if ((*done) == 0)
+ {
+ if (*upload_data_size != PUT_SIZE)
+ {
+#if 0
+ fprintf (stderr,
+ "Waiting for more data (%u/%u)...\n",
+ *upload_data_size, PUT_SIZE);
+#endif
+ return MHD_YES; /* not yet ready */
+ }
+ if (0 == memcmp (upload_data, put_buffer, PUT_SIZE))
+ {
+ *upload_data_size = 0;
+ }
+ else
+ {
+ printf ("Invalid upload data!\n");
+ return MHD_NO;
+ }
+ *done = 1;
+ return MHD_YES;
+ }
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+ char buf[2048];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (1024*1024),
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+ char buf[2048];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (1024*1024),
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ {
+ fprintf (stderr, "Got invalid response `%.*s'\n", (int)cbc.pos, cbc.buf);
+ return 64;
+ }
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testMultithreadedPoolPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+ char buf[2048];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_THREAD_POOL_SIZE, 4,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (1024*1024),
+ MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ {
+ fprintf (stderr, "Got invalid response `%.*s'\n", (int)cbc.pos, cbc.buf);
+ return 64;
+ }
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testExternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ char buf[2048];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ multi = NULL;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (PUT_SIZE * 4), MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ {
+ fprintf (stderr, "Got invalid response `%.*s'\n", (int)cbc.pos, cbc.buf);
+ return 8192;
+ }
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ put_buffer = malloc (PUT_SIZE);
+ memset (put_buffer, 1, PUT_SIZE);
+ errorCount += testInternalPut ();
+ errorCount += testMultithreadedPut ();
+ errorCount += testMultithreadedPoolPut ();
+ errorCount += testExternalPut ();
+ free (put_buffer);
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_long_header.c b/lib/libmicrohttpd/src/testcurl/daemontest_long_header.c
new file mode 100644
index 0000000000..98dcc812ac
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_long_header.c
@@ -0,0 +1,241 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_long_header.c
+ * @brief Testcase for libmicrohttpd handling of very long headers
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+/**
+ * We will set the memory available per connection to
+ * half of this value, so the actual value does not have
+ * to be big at all...
+ */
+#define VERY_LONG (1024*10)
+
+static int oneone;
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return MHD_YES;
+}
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testLongUrlGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ char *url;
+ long code;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 1080,
+ &apc_all,
+ NULL,
+ &ahc_echo,
+ "GET",
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (VERY_LONG / 2), MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ url = malloc (VERY_LONG);
+ memset (url, 'a', VERY_LONG);
+ url[VERY_LONG - 1] = '\0';
+ memcpy (url, "http://localhost:1080/", strlen ("http://localhost:1080/"));
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK == curl_easy_perform (c))
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ free (url);
+ return 2;
+ }
+ if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ free (url);
+ return 4;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ free (url);
+ if (code != MHD_HTTP_REQUEST_URI_TOO_LONG)
+ return 8;
+ return 0;
+}
+
+
+static int
+testLongHeaderGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ char *url;
+ long code;
+ struct curl_slist *header = NULL;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 1080,
+ &apc_all,
+ NULL,
+ &ahc_echo,
+ "GET",
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (VERY_LONG / 2), MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ url = malloc (VERY_LONG);
+ memset (url, 'a', VERY_LONG);
+ url[VERY_LONG - 1] = '\0';
+ url[VERY_LONG / 2] = ':';
+ url[VERY_LONG / 2 + 1] = ' ';
+ header = curl_slist_append (header, url);
+
+ curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK == curl_easy_perform (c))
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ curl_slist_free_all (header);
+ free (url);
+ return 32;
+ }
+ if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+ {
+ curl_slist_free_all (header);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ free (url);
+ return 64;
+ }
+ curl_slist_free_all (header);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ free (url);
+ if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE)
+ return 128;
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testLongUrlGet ();
+ errorCount += testLongHeaderGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_parse_cookies.c b/lib/libmicrohttpd/src/testcurl/daemontest_parse_cookies.c
new file mode 100644
index 0000000000..bfa8f86097
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_parse_cookies.c
@@ -0,0 +1,249 @@
+
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_parse_cookies.c
+ * @brief Testcase for HTTP cookie parsing
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+ const char *hdr;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ ret = 0;
+
+ hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name1");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "var1")))
+ abort ();
+ hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name2");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "var2")))
+ abort ();
+ hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name3");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "")))
+ abort ();
+ hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name4");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "var4 with spaces")))
+ abort ();
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ /* note that the string below intentionally uses the
+ various ways cookies can be specified to exercise the
+ parser! Do not change! */
+ curl_easy_setopt (c, CURLOPT_COOKIE,
+ "name1=var1; name2=var2,name3 ;name4=\"var4 with spaces\";");
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testExternalGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_post.c b/lib/libmicrohttpd/src/testcurl/daemontest_post.c
new file mode 100644
index 0000000000..715047fe64
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_post.c
@@ -0,0 +1,430 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_post.c
+ * @brief Testcase for libmicrohttpd POST operations using URL-encoding
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#define POST_DATA "name=daniel&project=curl"
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+/**
+ * Note that this post_iterator is not perfect
+ * in that it fails to support incremental processing.
+ * (to be fixed in the future)
+ */
+static int
+post_iterator (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *value, uint64_t off, size_t size)
+{
+ int *eok = cls;
+
+ if ((0 == strcmp (key, "name")) &&
+ (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size)))
+ (*eok) |= 1;
+ if ((0 == strcmp (key, "project")) &&
+ (size == strlen ("curl")) && (0 == strncmp (value, "curl", size)))
+ (*eok) |= 2;
+ return MHD_YES;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int eok;
+ struct MHD_Response *response;
+ struct MHD_PostProcessor *pp;
+ int ret;
+
+ if (0 != strcmp ("POST", method))
+ {
+ printf ("METHOD: %s\n", method);
+ return MHD_NO; /* unexpected method */
+ }
+ pp = *unused;
+ if (pp == NULL)
+ {
+ eok = 0;
+ pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok);
+ *unused = pp;
+ }
+ MHD_post_process (pp, upload_data, *upload_data_size);
+ if ((eok == 3) && (0 == *upload_data_size))
+ {
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url,
+ MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ MHD_destroy_post_processor (pp);
+ *unused = NULL;
+ return ret;
+ }
+ *upload_data_size = 0;
+ return MHD_YES;
+}
+
+
+static int
+testInternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testMultithreadedPoolPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testExternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPost ();
+ errorCount += testMultithreadedPost ();
+ errorCount += testMultithreadedPoolPost ();
+ errorCount += testExternalPost ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_post_loop.c b/lib/libmicrohttpd/src/testcurl/daemontest_post_loop.c
new file mode 100644
index 0000000000..b1e1ab3f14
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_post_loop.c
@@ -0,0 +1,452 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_post_loop.c
+ * @brief Testcase for libmicrohttpd POST operations using URL-encoding
+ * @author Christian Grothoff (inspired by bug report #1296)
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#define POST_DATA "<?xml version='1.0' ?>\n<xml>\n<data-id>1</data-id>\n</xml>\n"
+
+#define LOOPCOUNT 10
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **mptr)
+{
+ static int marker;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp ("POST", method))
+ {
+ printf ("METHOD: %s\n", method);
+ return MHD_NO; /* unexpected method */
+ }
+ if ((*mptr != NULL) && (0 == *upload_data_size))
+ {
+ if (*mptr != &marker)
+ abort ();
+ response = MHD_create_response_from_data (2, "OK", MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ *mptr = NULL;
+ return ret;
+ }
+ if (strlen (POST_DATA) != *upload_data_size)
+ return MHD_YES;
+ *upload_data_size = 0;
+ *mptr = &marker;
+ return MHD_YES;
+}
+
+
+static int
+testInternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ int i;
+ char url[1024];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ for (i = 0; i < LOOPCOUNT; i++)
+ {
+ if (99 == i % 100)
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ cbc.pos = 0;
+ buf[0] = '\0';
+ sprintf (url, "http://localhost:1080/hw%d", i);
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ if ((buf[0] != 'O') || (buf[1] != 'K'))
+ {
+ MHD_stop_daemon (d);
+ return 4;
+ }
+ }
+ MHD_stop_daemon (d);
+ if (LOOPCOUNT >= 99)
+ fprintf (stderr, "\n");
+ return 0;
+}
+
+static int
+testMultithreadedPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ int i;
+ char url[1024];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ for (i = 0; i < LOOPCOUNT; i++)
+ {
+ if (99 == i % 100)
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ cbc.pos = 0;
+ buf[0] = '\0';
+ sprintf (url, "http://localhost:1081/hw%d", i);
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ if ((buf[0] != 'O') || (buf[1] != 'K'))
+ {
+ MHD_stop_daemon (d);
+ return 64;
+ }
+ }
+ MHD_stop_daemon (d);
+ if (LOOPCOUNT >= 99)
+ fprintf (stderr, "\n");
+ return 0;
+}
+
+static int
+testMultithreadedPoolPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ int i;
+ char url[1024];
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ for (i = 0; i < LOOPCOUNT; i++)
+ {
+ if (99 == i % 100)
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ cbc.pos = 0;
+ buf[0] = '\0';
+ sprintf (url, "http://localhost:1081/hw%d", i);
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ if ((buf[0] != 'O') || (buf[1] != 'K'))
+ {
+ MHD_stop_daemon (d);
+ return 64;
+ }
+ }
+ MHD_stop_daemon (d);
+ if (LOOPCOUNT >= 99)
+ fprintf (stderr, "\n");
+ return 0;
+}
+
+static int
+testExternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+ int i;
+ unsigned long long timeout;
+ long ctimeout;
+ char url[1024];
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ for (i = 0; i < LOOPCOUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ cbc.pos = 0;
+ buf[0] = '\0';
+ sprintf (url, "http://localhost:1082/hw%d", i);
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ while (CURLM_CALL_MULTI_PERFORM ==
+ curl_multi_perform (multi, &running));
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ if (MHD_NO == MHD_get_timeout (d, &timeout))
+ timeout = 100; /* 100ms == INFTY -- CURL bug... */
+ if ((CURLM_OK == curl_multi_timeout (multi, &ctimeout)) &&
+ (ctimeout < timeout) && (ctimeout >= 0))
+ timeout = ctimeout;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ while (CURLM_CALL_MULTI_PERFORM ==
+ curl_multi_perform (multi, &running));
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ if ((buf[0] != 'O') || (buf[1] != 'K'))
+ {
+ curl_multi_cleanup (multi);
+ MHD_stop_daemon (d);
+ return 8192;
+ }
+ }
+ curl_multi_cleanup (multi);
+ MHD_stop_daemon (d);
+ fprintf (stderr, "\n");
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPost ();
+ errorCount += testMultithreadedPost ();
+ errorCount += testMultithreadedPoolPost ();
+ errorCount += testExternalPost ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_postform.c b/lib/libmicrohttpd/src/testcurl/daemontest_postform.c
new file mode 100644
index 0000000000..a1e29f6953
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_postform.c
@@ -0,0 +1,457 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_post.c
+ * @brief Testcase for libmicrohttpd POST operations using multipart/postform data
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+/**
+ * Note that this post_iterator is not perfect
+ * in that it fails to support incremental processing.
+ * (to be fixed in the future)
+ */
+static int
+post_iterator (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *value, uint64_t off, size_t size)
+{
+ int *eok = cls;
+
+#if 0
+ fprintf (stderr, "PI sees %s-%.*s\n", key, size, value);
+#endif
+ if ((0 == strcmp (key, "name")) &&
+ (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size)))
+ (*eok) |= 1;
+ if ((0 == strcmp (key, "project")) &&
+ (size == strlen ("curl")) && (0 == strncmp (value, "curl", size)))
+ (*eok) |= 2;
+ return MHD_YES;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int eok;
+ struct MHD_Response *response;
+ struct MHD_PostProcessor *pp;
+ int ret;
+
+ if (0 != strcmp ("POST", method))
+ {
+ printf ("METHOD: %s\n", method);
+ return MHD_NO; /* unexpected method */
+ }
+ pp = *unused;
+ if (pp == NULL)
+ {
+ eok = 0;
+ pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok);
+ if (pp == NULL)
+ abort ();
+ *unused = pp;
+ }
+ MHD_post_process (pp, upload_data, *upload_data_size);
+ if ((eok == 3) && (0 == *upload_data_size))
+ {
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url,
+ MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ MHD_destroy_post_processor (pp);
+ *unused = NULL;
+ return ret;
+ }
+ *upload_data_size = 0;
+ return MHD_YES;
+}
+
+static struct curl_httppost *
+make_form ()
+{
+ struct curl_httppost *post = NULL;
+ struct curl_httppost *last = NULL;
+
+ curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
+ curl_formadd (&post, &last, CURLFORM_COPYNAME, "project",
+ CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
+ return post;
+}
+
+
+static int
+testInternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ struct curl_httppost *pd;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ struct curl_httppost *pd;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testMultithreadedPoolPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ struct curl_httppost *pd;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testExternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+ struct curl_httppost *pd;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_formfree (pd);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ curl_formfree (pd);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ curl_formfree (pd);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPost ();
+ errorCount += testMultithreadedPost ();
+ errorCount += testMultithreadedPoolPost ();
+ errorCount += testExternalPost ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_process_arguments.c b/lib/libmicrohttpd/src/testcurl/daemontest_process_arguments.c
new file mode 100644
index 0000000000..23fe78e356
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_process_arguments.c
@@ -0,0 +1,238 @@
+
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_process_arguments.c
+ * @brief Testcase for HTTP URI arguments
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+ const char *hdr;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ hdr = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "k");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "v x")))
+ abort ();
+ hdr = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND, "hash");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "#")))
+ abort ();
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL,
+ "http://localhost:21080/hello_world?k=v+x&hash=%23");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testExternalGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_process_headers.c b/lib/libmicrohttpd/src/testcurl/daemontest_process_headers.c
new file mode 100644
index 0000000000..cd4bd68c08
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_process_headers.c
@@ -0,0 +1,428 @@
+
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_process_headers.c
+ * @brief Testcase for HTTP header access
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+kv_cb (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
+{
+ if ((0 == strcmp (key, MHD_HTTP_HEADER_HOST)) &&
+ (0 == strcmp (value, "localhost:21080")) && (kind == MHD_HEADER_KIND))
+ {
+ *((int *) cls) = 1;
+ return MHD_NO;
+ }
+ return MHD_YES;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+ const char *hdr;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ ret = 0;
+ MHD_get_connection_values (connection, MHD_HEADER_KIND, &kv_cb, &ret);
+ if (ret != 1)
+ abort ();
+ hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "NotFound");
+ if (hdr != NULL)
+ abort ();
+ hdr = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT);
+ if ((hdr == NULL) || (0 != strcmp (hdr, "*/*")))
+ abort ();
+ hdr = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND, MHD_HTTP_HEADER_HOST);
+ if ((hdr == NULL) || (0 != strcmp (hdr, "localhost:21080")))
+ abort ();
+ MHD_set_connection_value (connection,
+ MHD_HEADER_KIND, "FakeHeader", "NowPresent");
+ hdr = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND, "FakeHeader");
+ if ((hdr == NULL) || (0 != strcmp (hdr, "NowPresent")))
+ abort ();
+
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ MHD_add_response_header (response, "MyHeader", "MyValue");
+ hdr = MHD_get_response_header (response, "MyHeader");
+ if (0 != strcmp ("MyValue", hdr))
+ abort ();
+ MHD_add_response_header (response, "MyHeader", "MyValueToo");
+ if (MHD_YES != MHD_del_response_header (response, "MyHeader", "MyValue"))
+ abort ();
+ hdr = MHD_get_response_header (response, "MyHeader");
+ if (0 != strcmp ("MyValueToo", hdr))
+ abort ();
+ if (1 != MHD_get_response_headers (response, NULL, NULL))
+ abort ();
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+
+static int
+testInternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testMultithreadedPoolGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 21080, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalGet ();
+ errorCount += testMultithreadedGet ();
+ errorCount += testMultithreadedPoolGet ();
+ errorCount += testExternalGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_put.c b/lib/libmicrohttpd/src/testcurl/daemontest_put.c
new file mode 100644
index 0000000000..76e9632075
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_put.c
@@ -0,0 +1,432 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put.c
+ * @brief Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+ unsigned int *pos = ptr;
+ unsigned int wrt;
+
+ wrt = size * nmemb;
+ if (wrt > 8 - (*pos))
+ wrt = 8 - (*pos);
+ memcpy (stream, &("Hello123"[*pos]), wrt);
+ (*pos) += wrt;
+ return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ int *done = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp ("PUT", method))
+ return MHD_NO; /* unexpected method */
+ if ((*done) == 0)
+ {
+ if (*upload_data_size != 8)
+ return MHD_YES; /* not yet ready */
+ if (0 == memcmp (upload_data, "Hello123", 8))
+ {
+ *upload_data_size = 0;
+ }
+ else
+ {
+ printf ("Invalid upload data `%8s'!\n", upload_data);
+ return MHD_NO;
+ }
+ *done = 1;
+ return MHD_YES;
+ }
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 1081,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+
+ return 0;
+}
+
+static int
+testMultithreadedPoolPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 1081,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+
+ return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+ unsigned int pos = 0;
+ int done_flag = 0;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPut ();
+ errorCount += testMultithreadedPut ();
+ errorCount += testMultithreadedPoolPut ();
+ errorCount += testExternalPut ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_put_chunked.c b/lib/libmicrohttpd/src/testcurl/daemontest_put_chunked.c
new file mode 100644
index 0000000000..3fa1f09250
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_put_chunked.c
@@ -0,0 +1,440 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put_chunked.c
+ * @brief Testcase for libmicrohttpd PUT operations with chunked encoding
+ * for the upload data
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+ unsigned int *pos = ptr;
+ unsigned int wrt;
+
+ wrt = size * nmemb;
+ if (wrt > 8 - (*pos))
+ wrt = 8 - (*pos);
+ if (wrt > 4)
+ wrt = 4; /* only send half at first => force multiple chunks! */
+ memcpy (stream, &("Hello123"[*pos]), wrt);
+ (*pos) += wrt;
+ return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ int *done = cls;
+ struct MHD_Response *response;
+ int ret;
+ int have;
+
+ if (0 != strcmp ("PUT", method))
+ return MHD_NO; /* unexpected method */
+ if ((*done) < 8)
+ {
+ have = *upload_data_size;
+ if (have + *done > 8)
+ {
+ printf ("Invalid upload data `%8s'!\n", upload_data);
+ return MHD_NO;
+ }
+ if (0 == memcmp (upload_data, &"Hello123"[*done], have))
+ {
+ *done += have;
+ *upload_data_size = 0;
+ }
+ else
+ {
+ printf ("Invalid upload data `%8s'!\n", upload_data);
+ return MHD_NO;
+ }
+#if 0
+ fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
+#endif
+ return MHD_YES;
+ }
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 11081,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+
+ return 0;
+}
+
+static int
+testMultithreadedPoolPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 11081,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+
+ return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+ unsigned int pos = 0;
+ int done_flag = 0;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 11082,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (multi != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ c = NULL;
+ multi = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (multi != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPut ();
+ errorCount += testMultithreadedPut ();
+ errorCount += testMultithreadedPoolPut ();
+ errorCount += testExternalPut ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testcurl/daemontest_termination.c b/lib/libmicrohttpd/src/testcurl/daemontest_termination.c
new file mode 100644
index 0000000000..23c5358625
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/daemontest_termination.c
@@ -0,0 +1,114 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2009 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_termination.c
+ * @brief Testcase for libmicrohttpd tolerating client not closing immediately
+ * @author hollosig
+ */
+#define PORT 12345
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <microhttpd.h>
+#include <unistd.h>
+#include <curl/curl.h>
+
+
+static int
+connection_handler (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t * upload_data_size,
+ void **ptr)
+{
+ static int i;
+
+ if (*ptr == NULL)
+ {
+ *ptr = &i;
+ return MHD_YES;
+ }
+
+ if (*upload_data_size != 0)
+ {
+ (*upload_data_size) = 0;
+ return MHD_YES;
+ }
+
+ struct MHD_Response *response =
+ MHD_create_response_from_data (strlen ("Response"), "Response", 0, 0);
+ int ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+
+ return ret;
+}
+
+static size_t
+write_data (void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ return size * nmemb;
+}
+
+int
+main ()
+{
+ struct MHD_Daemon *daemon;
+
+ daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ PORT,
+ NULL,
+ NULL, connection_handler, NULL, MHD_OPTION_END);
+
+ if (daemon == NULL)
+ {
+ fprintf (stderr, "Daemon cannot be started!");
+ exit (1);
+ }
+
+ CURL *curl = curl_easy_init ();
+ //curl_easy_setopt(curl, CURLOPT_POST, 1L);
+ char url[255];
+ sprintf (url, "http://localhost:%d", PORT);
+ curl_easy_setopt (curl, CURLOPT_URL, url);
+ curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);
+
+ CURLcode success = curl_easy_perform (curl);
+ if (success != 0)
+ {
+ fprintf (stderr, "CURL Error");
+ exit (1);
+ }
+ /* CPU used to go crazy here */
+ sleep (1);
+
+ curl_easy_cleanup (curl);
+ MHD_stop_daemon (daemon);
+
+ return 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/Makefile.am b/lib/libmicrohttpd/src/testcurl/https/Makefile.am
new file mode 100644
index 0000000000..d707bda06c
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/Makefile.am
@@ -0,0 +1,132 @@
+SUBDIRS = .
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage
+endif
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https \
+ -I$(top_srcdir)/src/daemon/https/tls \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/x509 \
+ -I$(top_srcdir)/src/daemon \
+ $(LIBCURL_CPPFLAGS)
+
+check_PROGRAMS = \
+ tls_daemon_options_test \
+ tls_authentication_test \
+ mhds_multi_daemon_test \
+ mhds_get_test \
+ mhds_session_info_test \
+ tls_thread_mode_test \
+ tls_multi_thread_mode_test \
+ tls_session_time_out_test \
+ tls_cipher_change_test \
+ tls_alert_test \
+ tls_extension_test
+
+EXTRA_DIST = cert.pem key.pem tls_test_keys.h tls_test_common.h
+
+# tls_authentication_test currently fails for unknown reasons
+TESTS = \
+ tls_daemon_options_test \
+ mhds_multi_daemon_test \
+ mhds_get_test \
+ mhds_session_info_test \
+ tls_thread_mode_test \
+ tls_multi_thread_mode_test \
+ tls_session_time_out_test \
+ tls_cipher_change_test \
+ tls_alert_test \
+ tls_extension_test \
+ tls_authentication_test
+
+# cURL dependent tests
+tls_extension_test_SOURCES = \
+ tls_extension_test.c \
+ tls_test_common.c
+tls_extension_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_session_time_out_test_SOURCES = \
+ tls_session_time_out_test.c \
+ tls_test_common.c
+tls_session_time_out_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_cipher_change_test_SOURCES = \
+ tls_cipher_change_test.c \
+ tls_test_common.c
+tls_cipher_change_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_alert_test_SOURCES = \
+ tls_alert_test.c \
+ tls_test_common.c
+tls_alert_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_daemon_options_test_SOURCES = \
+ tls_daemon_options_test.c \
+ tls_test_common.c
+tls_daemon_options_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_thread_mode_test_SOURCES = \
+ tls_thread_mode_test.c \
+ tls_test_common.c
+tls_thread_mode_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_multi_thread_mode_test_SOURCES = \
+ tls_multi_thread_mode_test.c \
+ tls_test_common.c
+tls_multi_thread_mode_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_authentication_test_SOURCES = \
+ tls_authentication_test.c \
+ tls_test_common.c
+tls_authentication_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+mhds_session_info_test_SOURCES = \
+ mhds_session_info_test.c \
+ tls_test_common.c
+mhds_session_info_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+mhds_multi_daemon_test_SOURCES = \
+ mhds_multi_daemon_test.c \
+ tls_test_common.c
+mhds_multi_daemon_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+mhds_get_test_SOURCES = \
+ mhds_get_test.c \
+ tls_test_common.c
+mhds_get_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
diff --git a/lib/libmicrohttpd/src/testcurl/https/Makefile.in b/lib/libmicrohttpd/src/testcurl/https/Makefile.in
new file mode 100644
index 0000000000..66e9a1cf17
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/Makefile.in
@@ -0,0 +1,986 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+check_PROGRAMS = tls_daemon_options_test$(EXEEXT) \
+ tls_authentication_test$(EXEEXT) \
+ mhds_multi_daemon_test$(EXEEXT) mhds_get_test$(EXEEXT) \
+ mhds_session_info_test$(EXEEXT) tls_thread_mode_test$(EXEEXT) \
+ tls_multi_thread_mode_test$(EXEEXT) \
+ tls_session_time_out_test$(EXEEXT) \
+ tls_cipher_change_test$(EXEEXT) tls_alert_test$(EXEEXT) \
+ tls_extension_test$(EXEEXT)
+TESTS = tls_daemon_options_test$(EXEEXT) \
+ mhds_multi_daemon_test$(EXEEXT) mhds_get_test$(EXEEXT) \
+ mhds_session_info_test$(EXEEXT) tls_thread_mode_test$(EXEEXT) \
+ tls_multi_thread_mode_test$(EXEEXT) \
+ tls_session_time_out_test$(EXEEXT) \
+ tls_cipher_change_test$(EXEEXT) tls_alert_test$(EXEEXT) \
+ tls_extension_test$(EXEEXT) tls_authentication_test$(EXEEXT)
+subdir = src/testcurl/https
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am_mhds_get_test_OBJECTS = mhds_get_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+mhds_get_test_OBJECTS = $(am_mhds_get_test_OBJECTS)
+mhds_get_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_mhds_multi_daemon_test_OBJECTS = mhds_multi_daemon_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+mhds_multi_daemon_test_OBJECTS = $(am_mhds_multi_daemon_test_OBJECTS)
+mhds_multi_daemon_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_mhds_session_info_test_OBJECTS = mhds_session_info_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+mhds_session_info_test_OBJECTS = $(am_mhds_session_info_test_OBJECTS)
+mhds_session_info_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_alert_test_OBJECTS = tls_alert_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+tls_alert_test_OBJECTS = $(am_tls_alert_test_OBJECTS)
+tls_alert_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_authentication_test_OBJECTS = \
+ tls_authentication_test.$(OBJEXT) tls_test_common.$(OBJEXT)
+tls_authentication_test_OBJECTS = \
+ $(am_tls_authentication_test_OBJECTS)
+tls_authentication_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_cipher_change_test_OBJECTS = tls_cipher_change_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+tls_cipher_change_test_OBJECTS = $(am_tls_cipher_change_test_OBJECTS)
+tls_cipher_change_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_daemon_options_test_OBJECTS = \
+ tls_daemon_options_test.$(OBJEXT) tls_test_common.$(OBJEXT)
+tls_daemon_options_test_OBJECTS = \
+ $(am_tls_daemon_options_test_OBJECTS)
+tls_daemon_options_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_extension_test_OBJECTS = tls_extension_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+tls_extension_test_OBJECTS = $(am_tls_extension_test_OBJECTS)
+tls_extension_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_multi_thread_mode_test_OBJECTS = \
+ tls_multi_thread_mode_test.$(OBJEXT) tls_test_common.$(OBJEXT)
+tls_multi_thread_mode_test_OBJECTS = \
+ $(am_tls_multi_thread_mode_test_OBJECTS)
+tls_multi_thread_mode_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_session_time_out_test_OBJECTS = \
+ tls_session_time_out_test.$(OBJEXT) tls_test_common.$(OBJEXT)
+tls_session_time_out_test_OBJECTS = \
+ $(am_tls_session_time_out_test_OBJECTS)
+tls_session_time_out_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_tls_thread_mode_test_OBJECTS = tls_thread_mode_test.$(OBJEXT) \
+ tls_test_common.$(OBJEXT)
+tls_thread_mode_test_OBJECTS = $(am_tls_thread_mode_test_OBJECTS)
+tls_thread_mode_test_DEPENDENCIES = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(mhds_get_test_SOURCES) $(mhds_multi_daemon_test_SOURCES) \
+ $(mhds_session_info_test_SOURCES) $(tls_alert_test_SOURCES) \
+ $(tls_authentication_test_SOURCES) \
+ $(tls_cipher_change_test_SOURCES) \
+ $(tls_daemon_options_test_SOURCES) \
+ $(tls_extension_test_SOURCES) \
+ $(tls_multi_thread_mode_test_SOURCES) \
+ $(tls_session_time_out_test_SOURCES) \
+ $(tls_thread_mode_test_SOURCES)
+DIST_SOURCES = $(mhds_get_test_SOURCES) \
+ $(mhds_multi_daemon_test_SOURCES) \
+ $(mhds_session_info_test_SOURCES) $(tls_alert_test_SOURCES) \
+ $(tls_authentication_test_SOURCES) \
+ $(tls_cipher_change_test_SOURCES) \
+ $(tls_daemon_options_test_SOURCES) \
+ $(tls_extension_test_SOURCES) \
+ $(tls_multi_thread_mode_test_SOURCES) \
+ $(tls_session_time_out_test_SOURCES) \
+ $(tls_thread_mode_test_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+@USE_COVERAGE_TRUE@AM_CFLAGS = --coverage
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/include \
+ -I$(top_srcdir)/src/daemon/https \
+ -I$(top_srcdir)/src/daemon/https/tls \
+ -I$(top_srcdir)/src/daemon/https/lgl \
+ -I$(top_srcdir)/src/daemon/https/x509 \
+ -I$(top_srcdir)/src/daemon \
+ $(LIBCURL_CPPFLAGS)
+
+EXTRA_DIST = cert.pem key.pem tls_test_keys.h tls_test_common.h
+
+# cURL dependent tests
+tls_extension_test_SOURCES = \
+ tls_extension_test.c \
+ tls_test_common.c
+
+tls_extension_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_session_time_out_test_SOURCES = \
+ tls_session_time_out_test.c \
+ tls_test_common.c
+
+tls_session_time_out_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_cipher_change_test_SOURCES = \
+ tls_cipher_change_test.c \
+ tls_test_common.c
+
+tls_cipher_change_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_alert_test_SOURCES = \
+ tls_alert_test.c \
+ tls_test_common.c
+
+tls_alert_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_daemon_options_test_SOURCES = \
+ tls_daemon_options_test.c \
+ tls_test_common.c
+
+tls_daemon_options_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_thread_mode_test_SOURCES = \
+ tls_thread_mode_test.c \
+ tls_test_common.c
+
+tls_thread_mode_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_multi_thread_mode_test_SOURCES = \
+ tls_multi_thread_mode_test.c \
+ tls_test_common.c
+
+tls_multi_thread_mode_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+tls_authentication_test_SOURCES = \
+ tls_authentication_test.c \
+ tls_test_common.c
+
+tls_authentication_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+mhds_session_info_test_SOURCES = \
+ mhds_session_info_test.c \
+ tls_test_common.c
+
+mhds_session_info_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+mhds_multi_daemon_test_SOURCES = \
+ mhds_multi_daemon_test.c \
+ tls_test_common.c
+
+mhds_multi_daemon_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+mhds_get_test_SOURCES = \
+ mhds_get_test.c \
+ tls_test_common.c
+
+mhds_get_test_LDADD = \
+ $(top_builddir)/src/testcurl/libcurl_version_check.a \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/testcurl/https/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/testcurl/https/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+mhds_get_test$(EXEEXT): $(mhds_get_test_OBJECTS) $(mhds_get_test_DEPENDENCIES)
+ @rm -f mhds_get_test$(EXEEXT)
+ $(LINK) $(mhds_get_test_OBJECTS) $(mhds_get_test_LDADD) $(LIBS)
+mhds_multi_daemon_test$(EXEEXT): $(mhds_multi_daemon_test_OBJECTS) $(mhds_multi_daemon_test_DEPENDENCIES)
+ @rm -f mhds_multi_daemon_test$(EXEEXT)
+ $(LINK) $(mhds_multi_daemon_test_OBJECTS) $(mhds_multi_daemon_test_LDADD) $(LIBS)
+mhds_session_info_test$(EXEEXT): $(mhds_session_info_test_OBJECTS) $(mhds_session_info_test_DEPENDENCIES)
+ @rm -f mhds_session_info_test$(EXEEXT)
+ $(LINK) $(mhds_session_info_test_OBJECTS) $(mhds_session_info_test_LDADD) $(LIBS)
+tls_alert_test$(EXEEXT): $(tls_alert_test_OBJECTS) $(tls_alert_test_DEPENDENCIES)
+ @rm -f tls_alert_test$(EXEEXT)
+ $(LINK) $(tls_alert_test_OBJECTS) $(tls_alert_test_LDADD) $(LIBS)
+tls_authentication_test$(EXEEXT): $(tls_authentication_test_OBJECTS) $(tls_authentication_test_DEPENDENCIES)
+ @rm -f tls_authentication_test$(EXEEXT)
+ $(LINK) $(tls_authentication_test_OBJECTS) $(tls_authentication_test_LDADD) $(LIBS)
+tls_cipher_change_test$(EXEEXT): $(tls_cipher_change_test_OBJECTS) $(tls_cipher_change_test_DEPENDENCIES)
+ @rm -f tls_cipher_change_test$(EXEEXT)
+ $(LINK) $(tls_cipher_change_test_OBJECTS) $(tls_cipher_change_test_LDADD) $(LIBS)
+tls_daemon_options_test$(EXEEXT): $(tls_daemon_options_test_OBJECTS) $(tls_daemon_options_test_DEPENDENCIES)
+ @rm -f tls_daemon_options_test$(EXEEXT)
+ $(LINK) $(tls_daemon_options_test_OBJECTS) $(tls_daemon_options_test_LDADD) $(LIBS)
+tls_extension_test$(EXEEXT): $(tls_extension_test_OBJECTS) $(tls_extension_test_DEPENDENCIES)
+ @rm -f tls_extension_test$(EXEEXT)
+ $(LINK) $(tls_extension_test_OBJECTS) $(tls_extension_test_LDADD) $(LIBS)
+tls_multi_thread_mode_test$(EXEEXT): $(tls_multi_thread_mode_test_OBJECTS) $(tls_multi_thread_mode_test_DEPENDENCIES)
+ @rm -f tls_multi_thread_mode_test$(EXEEXT)
+ $(LINK) $(tls_multi_thread_mode_test_OBJECTS) $(tls_multi_thread_mode_test_LDADD) $(LIBS)
+tls_session_time_out_test$(EXEEXT): $(tls_session_time_out_test_OBJECTS) $(tls_session_time_out_test_DEPENDENCIES)
+ @rm -f tls_session_time_out_test$(EXEEXT)
+ $(LINK) $(tls_session_time_out_test_OBJECTS) $(tls_session_time_out_test_LDADD) $(LIBS)
+tls_thread_mode_test$(EXEEXT): $(tls_thread_mode_test_OBJECTS) $(tls_thread_mode_test_DEPENDENCIES)
+ @rm -f tls_thread_mode_test$(EXEEXT)
+ $(LINK) $(tls_thread_mode_test_OBJECTS) $(tls_thread_mode_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mhds_get_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mhds_multi_daemon_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mhds_session_info_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_alert_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_authentication_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_cipher_change_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_daemon_options_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_extension_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_multi_thread_mode_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_session_time_out_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test_common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_thread_mode_test.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \
+ ctags-recursive install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/testcurl/https/cert.pem b/lib/libmicrohttpd/src/testcurl/https/cert.pem
new file mode 100644
index 0000000000..2c766dff08
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICpjCCAZCgAwIBAgIESEPtjjALBgkqhkiG9w0BAQUwADAeFw0wODA2MDIxMjU0
+MzhaFw0wOTA2MDIxMjU0NDZaMAAwggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKC
+AQC03TyUvK5HmUAirRp067taIEO4bibh5nqolUoUdo/LeblMQV+qnrv/RNAMTx5X
+fNLZ45/kbM9geF8qY0vsPyQvP4jumzK0LOJYuIwmHaUm9vbXnYieILiwCuTgjaud
+3VkZDoQ9fteIo+6we9UTpVqZpxpbLulBMh/VsvX0cPJ1VFC7rT59o9hAUlFf9jX/
+GmKdYI79MtgVx0OPBjmmSD6kicBBfmfgkO7bIGwlRtsIyMznxbHu6VuoX/eVxrTv
+rmCwgEXLWRZ6ru8MQl5YfqeGXXRVwMeXU961KefbuvmEPccgCxm8FZ1C1cnDHFXh
+siSgAzMBjC/b6KVhNQ4KnUdZAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0O
+BBYEFJcUvpjvE5fF/yzUshkWDpdYiQh/MAsGCSqGSIb3DQEBBQOCAQEARP7eKSB2
+RNd6XjEjK0SrxtoTnxS3nw9sfcS7/qD1+XHdObtDFqGNSjGYFB3Gpx8fpQhCXdoN
+8QUs3/5ZVa5yjZMQewWBgz8kNbnbH40F2y81MHITxxCe1Y+qqHWwVaYLsiOTqj2/
+0S3QjEJ9tvklmg7JX09HC4m5QRYfWBeQLD1u8ZjA1Sf1xJriomFVyRLI2VPO2bNe
+JDMXWuP+8kMC7gEvUnJ7A92Y2yrhu3QI3bjPk8uSpHea19Q77tul1UVBJ5g+zpH3
+OsF5p0MyaVf09GTzcLds5nE/osTdXGUyHJapWReVmPm3Zn6gqYlnzD99z+DPIgIV
+RhZvQx74NQnS6g==
+-----END CERTIFICATE-----
diff --git a/lib/libmicrohttpd/src/testcurl/https/key.pem b/lib/libmicrohttpd/src/testcurl/https/key.pem
new file mode 100644
index 0000000000..a5848eed9b
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAtN08lLyuR5lAIq0adOu7WiBDuG4m4eZ6qJVKFHaPy3m5TEFf
+qp67/0TQDE8eV3zS2eOf5GzPYHhfKmNL7D8kLz+I7psytCziWLiMJh2lJvb2152I
+niC4sArk4I2rnd1ZGQ6EPX7XiKPusHvVE6VamacaWy7pQTIf1bL19HDydVRQu60+
+faPYQFJRX/Y1/xpinWCO/TLYFcdDjwY5pkg+pInAQX5n4JDu2yBsJUbbCMjM58Wx
+7ulbqF/3lca0765gsIBFy1kWeq7vDEJeWH6nhl10VcDHl1PetSnn27r5hD3HIAsZ
+vBWdQtXJwxxV4bIkoAMzAYwv2+ilYTUOCp1HWQIDAQABAoIBAArOQv3R7gmqDspj
+lDaTFOz0C4e70QfjGMX0sWnakYnDGn6DU19iv3GnX1S072ejtgc9kcJ4e8VUO79R
+EmqpdRR7k8dJr3RTUCyjzf/C+qiCzcmhCFYGN3KRHA6MeEnkvRuBogX4i5EG1k5l
+/5t+YBTZBnqXKWlzQLKoUAiMLPg0eRWh+6q7H4N7kdWWBmTpako7TEqpIwuEnPGx
+u3EPuTR+LN6lF55WBePbCHccUHUQaXuav18NuDkcJmCiMArK9SKb+h0RqLD6oMI/
+dKD6n8cZXeMBkK+C8U/K0sN2hFHACsu30b9XfdnljgP9v+BP8GhnB0nCB6tNBCPo
+32srOwECgYEAxWh3iBT4lWqL6bZavVbnhmvtif4nHv2t2/hOs/CAq8iLAw0oWGZc
++JEZTUDMvFRlulr0kcaWra+4fN3OmJnjeuFXZq52lfMgXBIKBmoSaZpIh2aDY1Rd
+RbEse7nQl9hTEPmYspiXLGtnAXW7HuWqVfFFP3ya8rUS3t4d07Hig8ECgYEA6ou6
+OHiBRTbtDqLIv8NghARc/AqwNWgEc9PelCPe5bdCOLBEyFjqKiT2MttnSSUc2Zob
+XhYkHC6zN1Mlq30N0e3Q61YK9LxMdU1vsluXxNq2rfK1Scb1oOlOOtlbV3zA3VRF
+hV3t1nOA9tFmUrwZi0CUMWJE/zbPAyhwWotKyZkCgYEAh0kFicPdbABdrCglXVae
+SnfSjVwYkVuGd5Ze0WADvjYsVkYBHTvhgRNnRJMg+/vWz3Sf4Ps4rgUbqK8Vc20b
+AU5G6H6tlCvPRGm0ZxrwTWDHTcuKRVs+pJE8C/qWoklE/AAhjluWVoGwUMbPGuiH
+6Gf1bgHF6oj/Sq7rv/VLZ8ECgYBeq7ml05YyLuJutuwa4yzQ/MXfghzv4aVyb0F3
+QCdXR6o2IYgR6jnSewrZKlA9aPqFJrwHNR6sNXlnSmt5Fcf/RWO/qgJQGLUv3+rG
+7kuLTNDR05azSdiZc7J89ID3Bkb+z2YkV+6JUiPq/Ei1+nDBEXb/m+/HqALU/nyj
+P3gXeQKBgBusb8Rbd+KgxSA0hwY6aoRTPRt8LNvXdsB9vRcKKHUFQvxUWiUSS+L9
+/Qu1sJbrUquKOHqksV5wCnWnAKyJNJlhHuBToqQTgKXjuNmVdYSe631saiI7PHyC
+eRJ6DxULPxABytJrYCRrNqmXi5TCiqR2mtfalEMOPxz8rUU8dYyx
+-----END RSA PRIVATE KEY-----
diff --git a/lib/libmicrohttpd/src/testcurl/https/mhds_get_test.c b/lib/libmicrohttpd/src/testcurl/https/mhds_get_test.c
new file mode 100644
index 0000000000..ce0fcbda4e
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/mhds_get_test.c
@@ -0,0 +1,136 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_get_test.c
+ * @brief Testcase for libmicrohttpd HTTPS GET operations
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+
+#include <limits.h>
+#include <sys/stat.h>
+
+#include "gnutls.h"
+#include <curl/curl.h>
+
+#include "tls_test_common.h"
+
+int curl_check_version (const char *req_version, ...);
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+extern const char srv_signed_cert_pem[];
+extern const char srv_signed_key_pem[];
+
+static int
+test_cipher_option (FILE * test_fd, char *cipher_suite, int proto_version)
+{
+
+ int ret;
+ int ciper[] = { MHD_GNUTLS_CIPHER_3DES_CBC, 0 };
+ struct MHD_Daemon *d;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, 42433,
+ NULL, NULL, &http_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_CIPHER_ALGORITHM, ciper, MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ ret = test_https_transfer (test_fd, cipher_suite, proto_version);
+
+ MHD_stop_daemon (d);
+ return ret;
+}
+
+/* perform a HTTP GET request via SSL/TLS */
+int
+test_secure_get (FILE * test_fd, char *cipher_suite, int proto_version)
+{
+ int ret;
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, 42433,
+ NULL, NULL, &http_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ ret = test_https_transfer (test_fd, cipher_suite, proto_version);
+
+ MHD_stop_daemon (d);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ FILE *test_fd;
+ unsigned int errorCount = 0;
+
+ /* gnutls_global_set_log_level(11); */
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION, MHD_REQ_CURL_OPENSSL_VERSION))
+ {
+ return -1;
+ }
+
+ if ((test_fd = setup_test_file ()) == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error: %s\n", strerror (errno));
+ fclose (test_fd);
+ return -1;
+ }
+
+ errorCount +=
+ test_secure_get (test_fd, "AES256-SHA", CURL_SSLVERSION_TLSv1);
+ errorCount +=
+ test_secure_get (test_fd, "AES256-SHA", CURL_SSLVERSION_SSLv3);
+ errorCount +=
+ test_cipher_option (test_fd, "DES-CBC3-SHA", CURL_SSLVERSION_TLSv1);
+
+ print_test_result (errorCount, argv[0]);
+
+ curl_global_cleanup ();
+ fclose (test_fd);
+ remove (TEST_FILE_NAME);
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/mhds_multi_daemon_test.c b/lib/libmicrohttpd/src/testcurl/https/mhds_multi_daemon_test.c
new file mode 100644
index 0000000000..7b9d0fe696
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/mhds_multi_daemon_test.c
@@ -0,0 +1,226 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_multi_daemon_test.c
+ * @brief Testcase for libmicrohttpd multiple HTTPS daemon scenario
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include <curl/curl.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+#include "tls_test_common.h"
+
+extern int curl_check_version (const char *req_version, ...);
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+/* TODO mv to common */
+/**
+ * perform cURL request for file
+ * @param test_fd: file to attempt transferring
+ */
+static int
+test_daemon_get (FILE * test_fd, char *cipher_suite, int proto_version,
+ int port)
+{
+ CURL *c;
+ struct CBC cbc;
+ CURLcode errornum;
+ char url[255];
+ size_t len;
+ struct stat file_stat;
+
+ stat (TEST_FILE_NAME, &file_stat);
+ len = file_stat.st_size;
+
+ /* used to memcmp local copy & deamon supplied copy */
+ unsigned char *mem_test_file_local;
+
+ mem_test_file_local = malloc (len);
+ fseek (test_fd, 0, SEEK_SET);
+ if (fread (mem_test_file_local, sizeof (char), len, test_fd) != len)
+ {
+ fprintf (stderr, "Error: failed to read test file. %s\n",
+ strerror (errno));
+ free (mem_test_file_local);
+ return -1;
+ }
+
+ if (NULL == (cbc.buf = malloc (sizeof (char) * len)))
+ {
+ fprintf (stderr, "Error: failed to read test file. %s\n",
+ strerror (errno));
+ free (mem_test_file_local);
+ return -1;
+ }
+ cbc.size = len;
+ cbc.pos = 0;
+
+ if (gen_test_file_url (url, port))
+ {
+ free (mem_test_file_local);
+ free (cbc.buf);
+ return -1;
+ }
+
+ c = curl_easy_init ();
+#if DEBUG_HTTPS_TEST
+ curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
+#endif
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_FILE, &cbc);
+
+ /* TLS options */
+ curl_easy_setopt (c, CURLOPT_SSLVERSION, proto_version);
+ curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, cipher_suite);
+
+ /* currently skip any peer authentication */
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
+
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr, "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ free (mem_test_file_local);
+ free (cbc.buf);
+ return errornum;
+ }
+
+ curl_easy_cleanup (c);
+
+ /* compare received file and local reference */
+ if (memcmp (cbc.buf, mem_test_file_local, len) != 0)
+ {
+ fprintf (stderr, "Error: local file & received file differ.\n");
+ free (mem_test_file_local);
+ free (cbc.buf);
+ return -1;
+ }
+
+ free (mem_test_file_local);
+ free (cbc.buf);
+ return 0;
+}
+
+/*
+ * assert initiating two separate daemons and having one shut down
+ * doesn't affect the other
+ */
+int
+test_concurent_daemon_pair (FILE * test_fd, char *cipher_suite,
+ int proto_version)
+{
+
+ int ret;
+ struct MHD_Daemon *d1;
+ struct MHD_Daemon *d2;
+ d1 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &http_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d1 == NULL)
+ {
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ d2 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT + 1,
+ NULL, NULL, &http_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d2 == NULL)
+ {
+ MHD_stop_daemon (d1);
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ ret =
+ test_daemon_get (test_fd, cipher_suite, proto_version, DEAMON_TEST_PORT);
+ ret +=
+ test_daemon_get (test_fd, cipher_suite, proto_version,
+ DEAMON_TEST_PORT + 1);
+
+ MHD_stop_daemon (d2);
+ ret +=
+ test_daemon_get (test_fd, cipher_suite, proto_version, DEAMON_TEST_PORT);
+ MHD_stop_daemon (d1);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ FILE *test_fd;
+ unsigned int errorCount = 0;
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION))
+ {
+ return -1;
+ }
+
+ if ((test_fd = setup_test_file ()) == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error (code: %u). l:%d f:%s\n", errorCount, __LINE__,
+ __FUNCTION__);
+ fclose (test_fd);
+ return -1;
+ }
+
+ errorCount +=
+ test_concurent_daemon_pair (test_fd, "AES256-SHA", CURL_SSLVERSION_SSLv3);
+
+ print_test_result (errorCount, "concurent_daemon_pair");
+
+ curl_global_cleanup ();
+ fclose (test_fd);
+
+ remove (TEST_FILE_NAME);
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/mhds_session_info_test.c b/lib/libmicrohttpd/src/testcurl/https/mhds_session_info_test.c
new file mode 100644
index 0000000000..da0c2cdde1
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/mhds_session_info_test.c
@@ -0,0 +1,172 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_session_info_test.c
+ * @brief Testcase for libmicrohttpd HTTPS connection querying operations
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include <curl/curl.h>
+
+#include "tls_test_common.h"
+
+extern int curl_check_version (const char *req_version, ...);
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+struct MHD_Daemon *d;
+
+/*
+ * HTTP access handler call back
+ * used to query negotiated security parameters
+ */
+static int
+query_session_ahc (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method,
+ const char *upload_data, const char *version,
+ size_t *upload_data_size, void **ptr)
+{
+ struct MHD_Response *response;
+ int ret;
+
+ /* assert actual connection cipher is the one negotiated */
+ if (MHD_get_connection_info
+ (connection,
+ MHD_CONNECTION_INFO_CIPHER_ALGO)->cipher_algorithm !=
+ MHD_GNUTLS_CIPHER_AES_256_CBC)
+ {
+ fprintf (stderr, "Error: requested cipher mismatch. %s\n",
+ strerror (errno));
+ return -1;
+ }
+
+ if (MHD_get_connection_info
+ (connection,
+ MHD_CONNECTION_INFO_PROTOCOL)->protocol != MHD_GNUTLS_PROTOCOL_SSL3)
+ {
+ fprintf (stderr, "Error: requested compression mismatch. %s\n",
+ strerror (errno));
+ return -1;
+ }
+
+ response = MHD_create_response_from_data (strlen (EMPTY_PAGE),
+ (void *) EMPTY_PAGE,
+ MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+/*
+ * negotiate a secure connection with server & query negotiated security parameters
+ */
+static int
+test_query_session ()
+{
+ CURL *c;
+ struct CBC cbc;
+ CURLcode errornum;
+ char url[256];
+
+ if (NULL == (cbc.buf = malloc (sizeof (char) * 255)))
+ return 16;
+ cbc.size = 255;
+ cbc.pos = 0;
+
+ gen_test_file_url (url, DEAMON_TEST_PORT);
+
+ /* setup test */
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &query_session_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ return 2;
+
+ c = curl_easy_init ();
+#if DEBUG_HTTPS_TEST
+ curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
+#endif
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_FILE, &cbc);
+ /* TLS options */
+ curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
+ curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, "AES256-SHA");
+ /* currently skip any peer authentication */
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
+
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr, "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+
+ MHD_stop_daemon (d);
+ curl_easy_cleanup (c);
+ free (cbc.buf);
+ return -1;
+ }
+
+ MHD_stop_daemon (d);
+ curl_easy_cleanup (c);
+ free (cbc.buf);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION))
+ {
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ return -1;
+ }
+
+ errorCount += test_query_session ();
+
+ print_test_result (errorCount, argv[0]);
+
+ curl_global_cleanup ();
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_alert_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_alert_test.c
new file mode 100644
index 0000000000..b9d0810088
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_alert_test.c
@@ -0,0 +1,187 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_get_test.c
+ * @brief: daemon TLS alert response test-case
+ *
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include "gnutls_int.h"
+#include "gnutls_datum.h"
+#include "gnutls_record.h"
+
+#include "tls_test_common.h"
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+/*
+ * assert server closes connection upon receiving a
+ * close notify alert message.
+ *
+ * @param session: an initialized TLS session
+ */
+static int
+test_alert_close_notify (MHD_gtls_session_t session)
+{
+ int sd, ret;
+ struct sockaddr_in sa;
+
+ sd = socket (AF_INET, SOCK_STREAM, 0);
+ if (sd == -1)
+ {
+ fprintf (stderr, "Failed to create socket: %s\n", strerror (errno));
+ return -1;
+ }
+
+ memset (&sa, '\0', sizeof (struct sockaddr_in));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (DEAMON_TEST_PORT);
+ inet_pton (AF_INET, "127.0.0.1", &sa.sin_addr);
+
+ MHD__gnutls_transport_set_ptr (session, (MHD_gnutls_transport_ptr_t) (long) sd);
+
+ ret = connect (sd, &sa, sizeof (struct sockaddr_in));
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "%s\n", MHD_E_FAILED_TO_CONNECT);
+ return -1;
+ }
+
+ ret = MHD__gnutls_handshake (session);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ MHD__gnutls_alert_send (session, GNUTLS_AL_FATAL, GNUTLS_A_CLOSE_NOTIFY);
+
+ /* check server responds with a 'close-notify' */
+ MHD_gtls_recv_int (session, GNUTLS_ALERT, GNUTLS_HANDSHAKE_FINISHED, 0, 0);
+
+ close (sd);
+ /* CLOSE_NOTIFY */
+ if (session->internals.last_alert != GNUTLS_A_CLOSE_NOTIFY)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * assert server closes connection upon receiving a
+ * fatal unexpected_message alert.
+ *
+ * @param session: an initialized TLS session
+ */
+static int
+test_alert_unexpected_message (MHD_gtls_session_t session)
+{
+ int sd, ret;
+ struct sockaddr_in sa;
+
+ sd = socket (AF_INET, SOCK_STREAM, 0);
+ if (sd == -1)
+ {
+ fprintf (stderr, "Failed to create socket: %s\n", strerror (errno));
+ return -1;
+ }
+ memset (&sa, '\0', sizeof (struct sockaddr_in));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (DEAMON_TEST_PORT);
+ inet_pton (AF_INET, "127.0.0.1", &sa.sin_addr);
+
+ MHD__gnutls_transport_set_ptr (session,
+ (MHD_gnutls_transport_ptr_t) ((void *) (long) sd));
+
+ ret = connect (sd, &sa, sizeof (struct sockaddr_in));
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "%s\n", MHD_E_FAILED_TO_CONNECT);
+ return -1;
+ }
+
+ ret = MHD__gnutls_handshake (session);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ MHD__gnutls_alert_send (session, GNUTLS_AL_FATAL,
+ GNUTLS_A_UNEXPECTED_MESSAGE);
+ usleep (100);
+
+ /* TODO better RST trigger */
+ if (send (sd, "", 1, 0) == 0)
+ {
+ return -1;
+ }
+
+ close (sd);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ int errorCount = 0;;
+ struct MHD_Daemon *d;
+ MHD_gtls_session_t session;
+ MHD_gnutls_datum_t key;
+ MHD_gnutls_datum_t cert;
+ MHD_gtls_cert_credentials_t xcred;
+
+ MHD__gnutls_global_init ();
+ MHD_gtls_global_set_log_level (11);
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &http_dummy_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, "%s\n", MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_alert_close_notify (session);
+ teardown_session (session, &key, &cert, xcred);
+
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_alert_unexpected_message (session);
+ teardown_session (session, &key, &cert, xcred);
+
+ print_test_result (errorCount, argv[0]);
+
+ MHD_stop_daemon (d);
+ MHD__gnutls_global_deinit ();
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_authentication_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_authentication_test.c
new file mode 100644
index 0000000000..9fe7318d2f
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_authentication_test.c
@@ -0,0 +1,237 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file tls_authentication_test.c
+ * @brief Testcase for libmicrohttpd HTTPS GET operations
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include <curl/curl.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+#include "tls_test_common.h"
+
+extern int curl_check_version (const char *req_version, ...);
+extern const char test_file_data[];
+
+extern const char ca_key_pem[];
+extern const char ca_cert_pem[];
+extern const char srv_signed_cert_pem[];
+extern const char srv_signed_key_pem[];
+
+const char *ca_cert_file_name = "tmp_ca_cert.pem";
+
+/*
+ * test HTTPS transfer
+ * @param test_fd: file to attempt transfering
+ */
+static int
+test_daemon_get (FILE * test_fd, char *cipher_suite, int proto_version)
+{
+ CURL *c;
+ struct CBC cbc;
+ CURLcode errornum;
+ char url[255];
+ struct stat statb;
+
+ stat (TEST_FILE_NAME, &statb);
+
+ int len = statb.st_size;
+
+ /* used to memcmp local copy & deamon supplied copy */
+ unsigned char *mem_test_file_local;
+
+ if (NULL == (mem_test_file_local = malloc (len)))
+ {
+ fprintf (stderr, MHD_E_MEM);
+ return -1;
+ }
+
+ fseek (test_fd, 0, SEEK_SET);
+ if (fread (mem_test_file_local, sizeof (char), len, test_fd) != len)
+ {
+ fprintf (stderr, "Error: failed to read test file. %s\n",
+ strerror (errno));
+ free (mem_test_file_local);
+ return -1;
+ }
+
+ if (NULL == (cbc.buf = malloc (sizeof (char) * len)))
+ {
+ fprintf (stderr, MHD_E_MEM);
+ free (mem_test_file_local);
+ return -1;
+ }
+ cbc.size = len;
+ cbc.pos = 0;
+
+ /* construct url - this might use doc_path */
+ gen_test_file_url (url, DEAMON_TEST_PORT);
+
+ c = curl_easy_init ();
+#if DEBUG_HTTPS_TEST
+ curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
+#endif
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_FILE, &cbc);
+
+ /* TLS options */
+ curl_easy_setopt (c, CURLOPT_SSLVERSION, proto_version);
+ curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, cipher_suite);
+
+ /* perform peer authentication */
+ /* TODO merge into send_curl_req */
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 1);
+ curl_easy_setopt (c, CURLOPT_CAINFO, ca_cert_file_name);
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
+
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr, "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ free (mem_test_file_local);
+ free (cbc.buf);
+ return errornum;
+ }
+
+ curl_easy_cleanup (c);
+
+ if (memcmp (cbc.buf, mem_test_file_local, len) != 0)
+ {
+ fprintf (stderr, "Error: local file & received file differ.\n");
+ free (cbc.buf);
+ free (mem_test_file_local);
+ return -1;
+ }
+
+ free (mem_test_file_local);
+ free (cbc.buf);
+ return 0;
+}
+
+/* perform a HTTP GET request via SSL/TLS */
+static int
+test_secure_get (FILE * test_fd, char *cipher_suite, int proto_version)
+{
+ int ret;
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &http_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ ret = test_daemon_get (test_fd, cipher_suite, proto_version);
+
+ MHD_stop_daemon (d);
+ return ret;
+}
+
+static FILE *
+setup_ca_cert ()
+{
+ FILE *cert_fd;
+
+ if (NULL == (cert_fd = fopen (ca_cert_file_name, "wb+")))
+ {
+ fprintf (stderr, "Error: failed to open `%s': %s\n",
+ ca_cert_file_name, strerror (errno));
+ return NULL;
+ }
+ if (fwrite (ca_cert_pem, sizeof (char), strlen (ca_cert_pem), cert_fd)
+ != strlen (ca_cert_pem))
+ {
+ fprintf (stderr, "Error: failed to write `%s. %s'\n",
+ ca_cert_file_name, strerror (errno));
+ fclose (cert_fd);
+ return NULL;
+ }
+ if (fflush (cert_fd))
+ {
+ fprintf (stderr, "Error: failed to flush ca cert file stream. %s\n",
+ strerror (errno));
+ fclose (cert_fd);
+ return NULL;
+ }
+
+ return cert_fd;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ FILE *test_fd;
+ unsigned int errorCount = 0;
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION))
+ {
+ return -1;
+ }
+
+ if ((test_fd = setup_test_file ()) == NULL || setup_ca_cert () == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ fclose (test_fd);
+ return -1;
+ }
+
+ errorCount +=
+ test_secure_get (test_fd, "AES256-SHA", CURL_SSLVERSION_TLSv1);
+
+ print_test_result (errorCount, argv[0]);
+
+ curl_global_cleanup ();
+ fclose (test_fd);
+
+ remove (TEST_FILE_NAME);
+ remove (ca_cert_file_name);
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_cipher_change_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_cipher_change_test.c
new file mode 100644
index 0000000000..48ba50de91
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_cipher_change_test.c
@@ -0,0 +1,154 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_get_test.c
+ * @brief: daemon TLS cipher change message test-case
+ *
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include "internal.h"
+#include "gnutls_int.h"
+#include "gnutls_datum.h"
+#include "gnutls_record.h"
+
+#include "tls_test_common.h"
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+char *http_get_req = "GET / HTTP/1.1\r\n\r\n";
+
+/* HTTP access handler call back */
+static int
+rehandshake_ahc (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *upload_data,
+ const char *version, size_t *upload_data_size,
+ void **ptr)
+{
+ int ret;
+ /* server side re-handshake request */
+ ret = MHD__gnutls_rehandshake (connection->tls_session);
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "Error: %s. f: %s, l: %d\n",
+ "server failed to send Hello Request", __FUNCTION__, __LINE__);
+ }
+
+ return 0;
+}
+
+/*
+ * Cipher change message should only occur while negotiating
+ * the SSL/TLS handshake.
+ * Test server disconnects upon receiving an out of context
+ * message.
+ *
+ * @param session: initiallized TLS session
+ */
+static int
+test_out_of_context_cipher_change (MHD_gtls_session_t session)
+{
+ int sd, ret;
+ struct sockaddr_in sa;
+
+ sd = socket (AF_INET, SOCK_STREAM, 0);
+ if (sd == -1)
+ {
+ fprintf (stderr, "Failed to create socket: %s\n", strerror (errno));
+ return -1;
+ }
+
+ memset (&sa, '\0', sizeof (struct sockaddr_in));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (DEAMON_TEST_PORT);
+ inet_pton (AF_INET, "127.0.0.1", &sa.sin_addr);
+
+ MHD__gnutls_transport_set_ptr (session, (MHD_gnutls_transport_ptr_t) (long) sd);
+
+ ret = connect (sd, &sa, sizeof (struct sockaddr_in));
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "%s\n", MHD_E_FAILED_TO_CONNECT);
+ return -1;
+ }
+
+ ret = MHD__gnutls_handshake (session);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ /* send an out of context cipher change spec */
+ MHD_gtls_send_change_cipher_spec (session, 0);
+
+
+ /* assert server has closed connection */
+ /* TODO better RST trigger */
+ if (send (sd, "", 1, 0) == 0)
+ {
+ return -1;
+ }
+
+ close (sd);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ int errorCount = 0;;
+ struct MHD_Daemon *d;
+ MHD_gtls_session_t session;
+ MHD_gnutls_datum_t key;
+ MHD_gnutls_datum_t cert;
+ MHD_gtls_cert_credentials_t xcred;
+
+ MHD__gnutls_global_init ();
+ MHD_gtls_global_set_log_level (11);
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &rehandshake_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, "%s\n", MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_out_of_context_cipher_change (session);
+ teardown_session (session, &key, &cert, xcred);
+
+ print_test_result (errorCount, argv[0]);
+
+ MHD_stop_daemon (d);
+ MHD__gnutls_global_deinit ();
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_daemon_options_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_daemon_options_test.c
new file mode 100644
index 0000000000..d7b29b083f
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_daemon_options_test.c
@@ -0,0 +1,182 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file tls_daemon_options_test.c
+ * @brief Testcase for libmicrohttpd HTTPS GET operations
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include <sys/stat.h>
+#include <limits.h>
+#include "gnutls.h"
+
+#include "tls_test_common.h"
+
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+int curl_check_version (const char *req_version, ...);
+
+/**
+ * test server refuses to negotiate connections with unsupported protocol versions
+ *
+ */
+/* TODO rm test_fd */
+static int
+test_unmatching_ssl_version (FILE * test_fd, char *cipher_suite,
+ int curl_req_ssl_version)
+{
+ struct CBC cbc;
+ if (NULL == (cbc.buf = malloc (sizeof (char) * 256)))
+ {
+ fprintf (stderr, "Error: failed to allocate: %s\n",
+ strerror (errno));
+ return -1;
+ }
+ cbc.size = 256;
+ cbc.pos = 0;
+
+ char url[255];
+ if (gen_test_file_url (url, DEAMON_TEST_PORT))
+ {
+ free (cbc.buf);
+ return -1;
+ }
+
+ /* assert daemon *rejected* request */
+ if (CURLE_OK ==
+ send_curl_req (url, &cbc, cipher_suite, curl_req_ssl_version))
+ {
+ free (cbc.buf);
+ return -1;
+ }
+
+ free (cbc.buf);
+ return 0;
+}
+
+/* setup a temporary transfer test file */
+int
+main (int argc, char *const *argv)
+{
+ FILE *test_fd;
+ unsigned int errorCount = 0;
+ unsigned int cpos;
+ char test_name[64];
+
+ int daemon_flags =
+ MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL | MHD_USE_DEBUG;
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION))
+ {
+ return -1;
+ }
+
+ if ((test_fd = setup_test_file ()) == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fclose (test_fd);
+ remove (TEST_FILE_NAME);
+ fprintf (stderr, "Error: %s\n", strerror (errno));
+ return -1;
+ }
+
+ int p_ssl3[] = { MHD_GNUTLS_PROTOCOL_SSL3, 0 };
+ int p_tls[] = { MHD_GNUTLS_PROTOCOL_TLS1_2,
+ MHD_GNUTLS_PROTOCOL_TLS1_1,
+ MHD_GNUTLS_PROTOCOL_TLS1_0, 0
+ };
+
+ struct CipherDef ciphers[] = {
+ {{MHD_GNUTLS_CIPHER_AES_128_CBC, 0}, "AES128-SHA"},
+ {{MHD_GNUTLS_CIPHER_ARCFOUR_128, 0}, "RC4-SHA"},
+ {{MHD_GNUTLS_CIPHER_3DES_CBC, 0}, "3DES-SHA"},
+ {{MHD_GNUTLS_CIPHER_AES_256_CBC, 0}, "AES256-SHA"},
+ {{0, 0}, NULL}
+ };
+ fprintf (stderr, "SHA/TLS tests:\n");
+ cpos = 0;
+ while (ciphers[cpos].curlname != NULL)
+ {
+ sprintf (test_name, "%s-TLS", ciphers[cpos].curlname);
+ errorCount +=
+ test_wrap (test_name,
+ &test_https_transfer, test_fd, daemon_flags,
+ ciphers[cpos].curlname,
+ CURL_SSLVERSION_TLSv1,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_PROTOCOL_VERSION, p_tls,
+ MHD_OPTION_CIPHER_ALGORITHM, ciphers[cpos].options,
+ MHD_OPTION_END);
+ cpos++;
+ }
+ fprintf (stderr, "SHA/SSL3 tests:\n");
+ cpos = 0;
+ while (ciphers[cpos].curlname != NULL)
+ {
+ sprintf (test_name, "%s-SSL3", ciphers[cpos].curlname);
+ errorCount +=
+ test_wrap (test_name,
+ &test_https_transfer, test_fd, daemon_flags,
+ ciphers[cpos].curlname,
+ CURL_SSLVERSION_SSLv3,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_PROTOCOL_VERSION, p_ssl3,
+ MHD_OPTION_CIPHER_ALGORITHM, ciphers[cpos].options,
+ MHD_OPTION_END);
+ cpos++;
+ }
+#if 0
+ /* manual inspection of the handshake suggests that CURL will
+ request TLSv1, we send back "SSL3" and CURL takes it *despite*
+ being configured to speak SSL3-only. Notably, the other way
+ round (have curl request SSL3, respond with TLSv1 only)
+ is properly refused by CURL. Either way, this does NOT seem
+ to be a bug in MHD/gnuTLS but rather in CURL; hence this
+ test is commented out here... */
+ errorCount +=
+ test_wrap ("unmatching version: SSL3 vs. TLS", &test_unmatching_ssl_version,
+ test_fd, daemon_flags, "AES256-SHA", CURL_SSLVERSION_TLSv1,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_PROTOCOL_VERSION, p_ssl3, MHD_OPTION_END);
+#endif
+ errorCount +=
+ test_wrap ("unmatching version: TLS vs. SSL3", &test_unmatching_ssl_version,
+ test_fd, daemon_flags, "AES256-SHA", CURL_SSLVERSION_SSLv3,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_PROTOCOL_VERSION, p_tls, MHD_OPTION_END);
+ curl_global_cleanup ();
+ fclose (test_fd);
+ remove (TEST_FILE_NAME);
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_extension_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_extension_test.c
new file mode 100644
index 0000000000..84ed374f3a
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_extension_test.c
@@ -0,0 +1,276 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file tls_extension_test.c
+ * @brief: test daemon response to TLS client hello requests containing extensions
+ *
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include "gnutls_int.h"
+#include "gnutls_handshake.h" // MHD_gtls_send_handshake
+#include "gnutls_num.h" // MHD_gtls_write_x
+#include "common.h" // MHD_gtls_version_x
+
+
+#include "tls_test_common.h"
+#define MAX_EXT_DATA_LENGTH 256
+
+extern int
+MHD__gnutls_copy_ciphersuites (MHD_gtls_session_t session,
+ opaque * ret_data, size_t ret_data_size);
+
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+/**
+ * Test daemon response to TLS client hello requests containing extensions
+ *
+ * @param session
+ * @param exten_t - the type of extension being appended to client hello request
+ * @param ext_count - the number of consecutive extension replicas inserted into request
+ * @param ext_length - the length of each appended extension
+ * @return 0 on successful test completion, -1 otherwise
+ */
+static int
+test_hello_extension (MHD_gtls_session_t session, extensions_t exten_t,
+ int ext_count, int ext_length)
+{
+ int i, sd, ret = 0, pos = 0;
+ int exten_data_len, ciphersuite_len, datalen;
+ struct sockaddr_in sa;
+ char url[255];
+ opaque *data = NULL;
+ uint8_t session_id_len = 0;
+ opaque rnd[TLS_RANDOM_SIZE];
+ opaque extdata[MAX_EXT_DATA_LENGTH];
+
+ /* single, null compression */
+ unsigned char comp[] = { 0x01, 0x00 };
+ struct CBC cbc;
+
+ sd = -1;
+ memset (&cbc, 0, sizeof (struct CBC));
+ if (NULL == (cbc.buf = malloc (sizeof (char) * 256)))
+ {
+ fprintf (stderr, MHD_E_MEM);
+ ret = -1;
+ goto cleanup;
+ }
+ cbc.size = 256;
+
+ sd = socket (AF_INET, SOCK_STREAM, 0);
+ if (sd == -1)
+ {
+ fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
+ free (cbc.buf);
+ return -1;
+ }
+ memset (&sa, '\0', sizeof (struct sockaddr_in));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (DEAMON_TEST_PORT);
+ inet_pton (AF_INET, "127.0.0.1", &sa.sin_addr);
+
+ enum MHD_GNUTLS_Protocol hver;
+
+ /* init hash functions */
+ session->internals.handshake_mac_handle_md5 =
+ MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
+ session->internals.handshake_mac_handle_sha =
+ MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
+
+ /* version = 2 , random = [4 for unix time + 28 for random bytes] */
+ datalen = 2 /* version */ + TLS_RANDOM_SIZE + (session_id_len + 1);
+
+ data = MHD_gnutls_malloc (datalen);
+
+ hver = MHD_gtls_version_max (session);
+ data[pos++] = MHD_gtls_version_get_major (hver);
+ data[pos++] = MHD_gtls_version_get_minor (hver);
+
+ /* Set the version we advertise as maximum (RSA uses it). */
+ set_adv_version (session, MHD_gtls_version_get_major (hver),
+ MHD_gtls_version_get_minor (hver));
+
+ session->security_parameters.version = hver;
+ session->security_parameters.timestamp = time (NULL);
+
+ /* generate session client random */
+ memset (session->security_parameters.client_random, 0, TLS_RANDOM_SIZE);
+ MHD_gtls_write_uint32 (time (NULL), rnd);
+ if (GC_OK != MHD_gc_nonce ((char *) &rnd[4], TLS_RANDOM_SIZE - 4)) abort ();
+ memcpy (session->security_parameters.client_random, rnd, TLS_RANDOM_SIZE);
+ memcpy (&data[pos], rnd, TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+
+ /* Copy the Session ID */
+ data[pos++] = session_id_len;
+
+ /*
+ * len = ciphersuite data + 2 bytes ciphersuite length \
+ * 1 byte compression length + 1 byte compression data + \
+ * 2 bytes extension length, extensions data
+ */
+ ciphersuite_len = MHD__gnutls_copy_ciphersuites (session, extdata,
+ sizeof (extdata));
+ exten_data_len = ext_count * (2 + 2 + ext_length);
+ datalen += ciphersuite_len + 2 + 2 + exten_data_len;
+ data = MHD_gtls_realloc_fast (data, datalen);
+ memcpy (&data[pos], extdata, sizeof (ciphersuite_len));
+ pos += ciphersuite_len;
+
+ /* set compression */
+ memcpy (&data[pos], comp, sizeof (comp));
+ pos += 2;
+
+ /* set extensions length = 2 type bytes + 2 length bytes + extension length */
+ MHD_gtls_write_uint16 (exten_data_len, &data[pos]);
+ pos += 2;
+ for (i = 0; i < ext_count; ++i)
+ {
+ /* write extension type */
+ MHD_gtls_write_uint16 (exten_t, &data[pos]);
+ pos += 2;
+ MHD_gtls_write_uint16 (ext_length, &data[pos]);
+ pos += 2;
+ /* we might want to generate random data here */
+ memset (&data[pos], 0, ext_length);
+ pos += ext_length;
+ }
+
+ if (connect (sd, &sa, sizeof (struct sockaddr_in)) < 0)
+ {
+ fprintf (stderr, "%s\n", MHD_E_FAILED_TO_CONNECT);
+ ret = -1;
+ goto cleanup;
+ }
+
+ MHD__gnutls_transport_set_ptr (session, (MHD_gnutls_transport_ptr_t) (long) sd);
+
+ if (gen_test_file_url (url, DEAMON_TEST_PORT))
+ {
+ ret = -1;
+ goto cleanup;
+ }
+
+ /* this should crash the server */
+ ret = MHD_gtls_send_handshake (session, data, datalen,
+ GNUTLS_HANDSHAKE_CLIENT_HELLO);
+
+ /* advance to STATE2 */
+ session->internals.handshake_state = STATE2;
+ ret = MHD__gnutls_handshake (session);
+ ret = MHD__gnutls_bye (session, GNUTLS_SHUT_WR);
+
+ MHD_gnutls_free (data);
+
+ /* make sure daemon is still functioning */
+ if (CURLE_OK != send_curl_req (url, &cbc, "AES128-SHA",
+ MHD_GNUTLS_PROTOCOL_TLS1_2))
+ {
+ ret = -1;
+ goto cleanup;
+ }
+
+cleanup:
+ if (sd != -1)
+ close (sd);
+ MHD_gnutls_free (cbc.buf);
+ return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ int i, errorCount = 0;
+ FILE *test_fd;
+ struct MHD_Daemon *d;
+ MHD_gtls_session_t session;
+ MHD_gnutls_datum_t key;
+ MHD_gnutls_datum_t cert;
+ MHD_gtls_cert_credentials_t xcred;
+
+ int ext_arr[] = { GNUTLS_EXTENSION_SERVER_NAME,
+ -1
+ };
+
+ MHD_gtls_global_set_log_level (11);
+
+ if ((test_fd = setup_test_file ()) == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error: %s\n", strerror (errno));
+ return -1;
+ }
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &http_ahc, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, "%s\n", MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ i = 0;
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_hello_extension (session, ext_arr[i], 1, 16);
+ teardown_session (session, &key, &cert, xcred);
+#if 1
+ i = 0;
+ while (ext_arr[i] != -1)
+ {
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_hello_extension (session, ext_arr[i], 1, 16);
+ teardown_session (session, &key, &cert, xcred);
+
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_hello_extension (session, ext_arr[i], 3, 8);
+ teardown_session (session, &key, &cert, xcred);
+
+ /* this test specifically tests the issue raised in CVE-2008-1948 */
+ setup_session (&session, &key, &cert, &xcred);
+ errorCount += test_hello_extension (session, ext_arr[i], 6, 0);
+ teardown_session (session, &key, &cert, xcred);
+ i++;
+ }
+#endif
+
+ print_test_result (errorCount, argv[0]);
+
+ MHD_stop_daemon (d);
+
+ curl_global_cleanup ();
+ fclose (test_fd);
+
+ return errorCount;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_multi_thread_mode_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_multi_thread_mode_test.c
new file mode 100644
index 0000000000..602a7175aa
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_multi_thread_mode_test.c
@@ -0,0 +1,178 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file tls_thread_mode_test.c
+ * @brief Testcase for libmicrohttpd HTTPS GET operations
+ * @author Sagie Amir
+ * @author Christian Grothoff
+ *
+ * TODO: add test for external select!
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+
+#include <sys/stat.h>
+#include <limits.h>
+#include "gnutls.h"
+#include <curl/curl.h>
+
+#include "tls_test_common.h"
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+int curl_check_version (const char *req_version, ...);
+
+/**
+ * used when spawning multiple threads executing curl server requests
+ *
+ */
+static void *
+https_transfer_thread_adapter (void *args)
+{
+ static int nonnull;
+ struct https_test_data *cargs = args;
+ int ret;
+
+ /* time spread incomming requests */
+ usleep ((useconds_t) 10.0 * ((double) rand ()) / ((double) RAND_MAX));
+ ret = test_https_transfer (cargs->test_fd,
+ cargs->cipher_suite, cargs->proto_version);
+ if (ret == 0)
+ return NULL;
+ return &nonnull;
+}
+
+/**
+ * Test non-parallel requests.
+ *
+ * @return: 0 upon all client requests returning '0', -1 otherwise.
+ *
+ * TODO : make client_count a parameter - numver of curl client threads to spawn
+ */
+static int
+test_single_client (FILE * test_fd, char *cipher_suite,
+ int curl_proto_version)
+{
+ void *client_thread_ret;
+ struct https_test_data client_args =
+ { test_fd, cipher_suite, curl_proto_version };
+
+ client_thread_ret = https_transfer_thread_adapter (&client_args);
+ if (client_thread_ret != NULL)
+ return -1;
+ return 0;
+}
+
+
+/**
+ * Test parallel request handling.
+ *
+ * @return: 0 upon all client requests returning '0', -1 otherwise.
+ *
+ * TODO : make client_count a parameter - numver of curl client threads to spawn
+ */
+static int
+test_parallel_clients (FILE * test_fd, char *cipher_suite,
+ int curl_proto_version)
+{
+ int i;
+ int client_count = 3;
+ void *client_thread_ret;
+ pthread_t client_arr[client_count];
+ struct https_test_data client_args =
+ { test_fd, cipher_suite, curl_proto_version };
+
+ for (i = 0; i < client_count; ++i)
+ {
+ if (pthread_create (&client_arr[i], NULL,
+ &https_transfer_thread_adapter, &client_args) != 0)
+ {
+ fprintf (stderr, "Error: failed to spawn test client threads.\n");
+
+ return -1;
+ }
+ }
+
+ /* check all client requests fulfilled correctly */
+ for (i = 0; i < client_count; ++i)
+ {
+ if ((pthread_join (client_arr[i], &client_thread_ret) != 0) ||
+ (client_thread_ret != NULL))
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+ FILE *test_fd;
+ unsigned int errorCount = 0;
+
+ /* initialize random seed used by curl clients */
+ unsigned int iseed = (unsigned int) time (NULL);
+ srand (iseed);
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION))
+ return -1;
+
+ if ((test_fd = setup_test_file ()) == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error: %s\n", strerror (errno));
+ fclose (test_fd);
+ return -1;
+ }
+
+ errorCount +=
+ test_wrap ("multi threaded daemon, single client", &test_single_client,
+ test_fd,
+ MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
+ "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY,
+ srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
+ srv_self_signed_cert_pem, MHD_OPTION_END);
+
+ errorCount +=
+ test_wrap ("multi threaded daemon, parallel client",
+ &test_parallel_clients, test_fd,
+ MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
+ "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY,
+ srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
+ srv_self_signed_cert_pem, MHD_OPTION_END);
+
+ if (errorCount != 0)
+ fprintf (stderr, "Failed test: %s.\n", argv[0]);
+
+ curl_global_cleanup ();
+ fclose (test_fd);
+
+ remove (TEST_FILE_NAME);
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_session_time_out_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_session_time_out_test.c
new file mode 100644
index 0000000000..7609160d29
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_session_time_out_test.c
@@ -0,0 +1,171 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file mhds_get_test.c
+ * @brief: daemon TLS alert response test-case
+ *
+ * @author Sagie Amir
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+#include "internal.h"
+#include "gnutls_int.h"
+#include "gnutls_datum.h"
+#include "gnutls_record.h"
+
+#include "tls_test_common.h"
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+static const int TIME_OUT = 3;
+
+char *http_get_req = "GET / HTTP/1.1\r\n\r\n";
+
+static int
+setup_timeout_test (MHD_gtls_session_t * session,
+ MHD_gnutls_datum_t * key,
+ MHD_gnutls_datum_t * cert,
+ MHD_gtls_cert_credentials_t * xcred)
+{
+ int ret;
+
+ MHD__gnutls_certificate_allocate_credentials (xcred);
+
+ MHD_gtls_set_datum_m (key, srv_key_pem, strlen (srv_key_pem), &malloc);
+ MHD_gtls_set_datum_m (cert, srv_self_signed_cert_pem,
+ strlen (srv_self_signed_cert_pem), &malloc);
+
+ MHD__gnutls_certificate_set_x509_key_mem (*xcred, cert, key,
+ GNUTLS_X509_FMT_PEM);
+
+ MHD__gnutls_init (session, GNUTLS_CLIENT);
+ ret = MHD__gnutls_priority_set_direct (*session, "NORMAL", NULL);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ MHD__gnutls_credentials_set (*session, MHD_GNUTLS_CRD_CERTIFICATE, xcred);
+ return 0;
+}
+
+static int
+teardown_timeout_test (MHD_gtls_session_t session,
+ MHD_gnutls_datum_t * key,
+ MHD_gnutls_datum_t * cert,
+ MHD_gtls_cert_credentials_t xcred)
+{
+
+ MHD_gtls_free_datum_m (key, free);
+ MHD_gtls_free_datum_m (cert, free);
+
+ MHD__gnutls_deinit (session);
+
+ MHD__gnutls_certificate_free_credentials (xcred);
+ return 0;
+}
+
+static int
+test_tls_session_time_out (MHD_gtls_session_t session)
+{
+ int sd, ret;
+ struct sockaddr_in sa;
+
+ sd = socket (AF_INET, SOCK_STREAM, 0);
+ if (sd == -1)
+ {
+ fprintf (stderr, "Failed to create socket: %s\n", strerror (errno));
+ return -1;
+ }
+
+ memset (&sa, '\0', sizeof (struct sockaddr_in));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (DEAMON_TEST_PORT);
+ inet_pton (AF_INET, "127.0.0.1", &sa.sin_addr);
+
+ MHD__gnutls_transport_set_ptr (session, (MHD_gnutls_transport_ptr_t) (long) sd);
+
+ ret = connect (sd, &sa, sizeof (struct sockaddr_in));
+
+ if (ret < 0)
+ {
+ fprintf (stderr, "Error: %s\n", MHD_E_FAILED_TO_CONNECT);
+ return -1;
+ }
+
+ ret = MHD__gnutls_handshake (session);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ sleep (TIME_OUT + 1);
+
+ /* check that server has closed the connection */
+ /* TODO better RST trigger */
+ if (send (sd, "", 1, 0) == 0)
+ {
+ return -1;
+ }
+
+ close (sd);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ int errorCount = 0;;
+ struct MHD_Daemon *d;
+ MHD_gtls_session_t session;
+ MHD_gnutls_datum_t key;
+ MHD_gnutls_datum_t cert;
+ MHD_gtls_cert_credentials_t xcred;
+
+ MHD__gnutls_global_init ();
+ MHD_gtls_global_set_log_level (11);
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
+ MHD_USE_DEBUG, DEAMON_TEST_PORT,
+ NULL, NULL, &http_dummy_ahc, NULL,
+ MHD_OPTION_CONNECTION_TIMEOUT, TIME_OUT,
+ MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
+ MHD_OPTION_END);
+
+ if (d == NULL)
+ {
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ setup_timeout_test (&session, &key, &cert, &xcred);
+ errorCount += test_tls_session_time_out (session);
+ teardown_timeout_test (session, &key, &cert, xcred);
+
+ print_test_result (errorCount, argv[0]);
+
+ MHD_stop_daemon (d);
+ MHD__gnutls_global_deinit ();
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_test_common.c b/lib/libmicrohttpd/src/testcurl/https/tls_test_common.c
new file mode 100644
index 0000000000..ce79451157
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_test_common.c
@@ -0,0 +1,424 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file tls_daemon_options_test.c
+ * @brief Common tls test functions
+ * @author Sagie Amir
+ */
+#include "tls_test_common.h"
+#include "tls_test_keys.h"
+#include "gnutls.h"
+#include "gnutls_datum.h"
+
+const char test_file_data[] = "Hello World\n";
+
+int curl_check_version (const char *req_version, ...);
+
+void
+print_test_result (int test_outcome, char *test_name)
+{
+#if 0
+ if (test_outcome != 0)
+ fprintf (stderr, "running test: %s [fail]\n", test_name);
+ else
+ fprintf (stdout, "running test: %s [pass]\n", test_name);
+#endif
+}
+
+size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+file_reader (void *cls, uint64_t pos, char *buf, int max)
+{
+ FILE *file = cls;
+ fseek (file, pos, SEEK_SET);
+ return fread (buf, 1, max, file);
+}
+
+/**
+ * HTTP access handler call back
+ */
+int
+http_ahc (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *upload_data,
+ const char *version, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ struct MHD_Response *response;
+ int ret;
+ FILE *file;
+ struct stat buf;
+
+ if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ *ptr = NULL; /* reset when done */
+
+ file = fopen (url, "rb");
+ if (file == NULL)
+ {
+ response = MHD_create_response_from_data (strlen (PAGE_NOT_FOUND),
+ (void *) PAGE_NOT_FOUND,
+ MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
+ MHD_destroy_response (response);
+ }
+ else
+ {
+ stat (url, &buf);
+ response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
+ &file_reader, file,
+ (MHD_ContentReaderFreeCallback)
+ & fclose);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ }
+ return ret;
+}
+
+/* HTTP access handler call back */
+int
+http_dummy_ahc (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *upload_data,
+ const char *version, size_t *upload_data_size,
+ void **ptr)
+{
+ return 0;
+}
+
+/**
+ * send a test http request to the daemon
+ * @param url
+ * @param cbc - may be null
+ * @param cipher_suite
+ * @param proto_version
+ * @return
+ */
+/* TODO have test wrap consider a NULL cbc */
+int
+send_curl_req (char *url, struct CBC * cbc, char *cipher_suite,
+ int proto_version)
+{
+ CURL *c;
+ CURLcode errornum;
+ c = curl_easy_init ();
+#if DEBUG_HTTPS_TEST
+ curl_easy_setopt (c, CURLOPT_VERBOSE, CURL_VERBOS_LEVEL);
+#endif
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 60L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 60L);
+
+ if (cbc != NULL)
+ {
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_FILE, cbc);
+ }
+
+ /* TLS options */
+ curl_easy_setopt (c, CURLOPT_SSLVERSION, proto_version);
+ curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, cipher_suite);
+
+ /* currently skip any peer authentication */
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
+
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr, "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ return errornum;
+ }
+ curl_easy_cleanup (c);
+
+ return CURLE_OK;
+}
+
+/**
+ * compile test file url pointing to the current running directory path
+ * @param url - char buffer into which the url is compiled
+ * @return
+ */
+int
+gen_test_file_url (char *url, int port)
+{
+ int ret = 0;
+ char *doc_path;
+ size_t doc_path_len;
+ /* setup test file path, url */
+ doc_path_len = PATH_MAX > 4096 ? 4096 : PATH_MAX;
+ if (NULL == (doc_path = malloc (doc_path_len)))
+ {
+ fprintf (stderr, MHD_E_MEM);
+ return -1;
+ }
+ if (getcwd (doc_path, doc_path_len) == NULL)
+ {
+ fprintf (stderr, "Error: failed to get working directory. %s\n",
+ strerror (errno));
+ ret = -1;
+ }
+ /* construct url - this might use doc_path */
+ if (sprintf (url, "%s:%d%s/%s", "https://localhost", port,
+ doc_path, TEST_FILE_NAME) < 0)
+ ret = -1;
+
+ free (doc_path);
+ return ret;
+}
+
+/**
+ * test HTTPS file transfer
+ * @param test_fd: file to attempt transferring
+ */
+int
+test_https_transfer (FILE * test_fd, char *cipher_suite, int proto_version)
+{
+ int len, ret = 0;
+ struct CBC cbc;
+ char url[255];
+ struct stat statb;
+ /* used to memcmp local copy & deamon supplied copy */
+ unsigned char *mem_test_file_local;
+
+ if (0 != stat (TEST_FILE_NAME, &statb))
+ {
+ fprintf (stderr, "Failed to stat `%s': %s\n",
+ TEST_FILE_NAME, strerror(errno));
+ return -1;
+ }
+ len = statb.st_size;
+ cbc.buf = NULL;
+ if (NULL == (mem_test_file_local = malloc (len)))
+ {
+ fprintf (stderr, MHD_E_MEM);
+ ret = -1;
+ goto cleanup;
+ }
+
+ fseek (test_fd, 0, SEEK_SET);
+ if (fread (mem_test_file_local, sizeof (char), len, test_fd) != len)
+ {
+ fprintf (stderr, "Error: failed to read test file. %s\n",
+ strerror (errno));
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (NULL == (cbc.buf = malloc (sizeof (char) * len)))
+ {
+ fprintf (stderr, MHD_E_MEM);
+ ret = -1;
+ goto cleanup;
+ }
+ cbc.size = len;
+ cbc.pos = 0;
+
+ if (gen_test_file_url (url, DEAMON_TEST_PORT))
+ {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (CURLE_OK != send_curl_req (url, &cbc, cipher_suite, proto_version))
+ {
+ ret = -1;
+ goto cleanup;
+ }
+
+ /* compare test file & daemon responce */
+ if (memcmp (cbc.buf, mem_test_file_local, len) != 0)
+ {
+ fprintf (stderr, "Error: local file & received file differ.\n");
+ ret = -1;
+ }
+
+cleanup:
+ free (mem_test_file_local);
+ if (cbc.buf != NULL)
+ free (cbc.buf);
+ return ret;
+}
+
+/**
+ * setup a mock test file which is requested from the running daemon
+ * @return open file descriptor to the test file
+ */
+FILE *
+setup_test_file ()
+{
+ FILE *test_fd;
+
+ if (NULL == (test_fd = fopen (TEST_FILE_NAME, "wb+")))
+ {
+ fprintf (stderr, "Error: failed to open `%s': %s\n",
+ TEST_FILE_NAME, strerror (errno));
+ return NULL;
+ }
+ if (fwrite (test_file_data, sizeof (char), strlen (test_file_data), test_fd)
+ != strlen (test_file_data))
+ {
+ fprintf (stderr, "Error: failed to write `%s. %s'\n",
+ TEST_FILE_NAME, strerror (errno));
+ fclose (test_fd);
+ return NULL;
+ }
+ if (fflush (test_fd))
+ {
+ fprintf (stderr, "Error: failed to flush test file stream. %s\n",
+ strerror (errno));
+ fclose (test_fd);
+ return NULL;
+ }
+ return test_fd;
+}
+
+/**
+ * setup test case
+ *
+ * @param d
+ * @param daemon_flags
+ * @param arg_list
+ * @return
+ */
+int
+setup_testcase (struct MHD_Daemon **d, int daemon_flags, va_list arg_list)
+{
+ *d = MHD_start_daemon_va (daemon_flags, DEAMON_TEST_PORT,
+ NULL, NULL, &http_ahc, NULL, arg_list);
+
+ if (*d == NULL)
+ {
+ fprintf (stderr, MHD_E_SERVER_INIT);
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+teardown_testcase (struct MHD_Daemon *d)
+{
+ MHD_stop_daemon (d);
+}
+
+int
+setup_session (MHD_gtls_session_t * session,
+ MHD_gnutls_datum_t * key,
+ MHD_gnutls_datum_t * cert, MHD_gtls_cert_credentials_t * xcred)
+{
+ int ret;
+ const char *err_pos;
+
+ MHD__gnutls_certificate_allocate_credentials (xcred);
+
+ MHD_gtls_set_datum_m (key, srv_key_pem, strlen (srv_key_pem), &malloc);
+ MHD_gtls_set_datum_m (cert, srv_self_signed_cert_pem,
+ strlen (srv_self_signed_cert_pem), &malloc);
+
+ MHD__gnutls_certificate_set_x509_key_mem (*xcred, cert, key,
+ GNUTLS_X509_FMT_PEM);
+
+ MHD__gnutls_init (session, GNUTLS_CLIENT);
+ ret = MHD__gnutls_priority_set_direct (*session, "NORMAL", &err_pos);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ MHD__gnutls_credentials_set (*session, MHD_GNUTLS_CRD_CERTIFICATE, xcred);
+ return 0;
+}
+
+int
+teardown_session (MHD_gtls_session_t session,
+ MHD_gnutls_datum_t * key,
+ MHD_gnutls_datum_t * cert,
+ MHD_gtls_cert_credentials_t xcred)
+{
+
+ MHD_gtls_free_datum_m (key, free);
+ MHD_gtls_free_datum_m (cert, free);
+
+ MHD__gnutls_deinit (session);
+
+ MHD__gnutls_certificate_free_credentials (xcred);
+ return 0;
+}
+
+/* TODO test_wrap: change sig to (setup_func, test, va_list test_arg) */
+int
+test_wrap (char *test_name, int
+ (*test_function) (FILE * test_fd, char *cipher_suite,
+ int proto_version), FILE * test_fd,
+ int daemon_flags, char *cipher_suite, int proto_version, ...)
+{
+ int ret;
+ va_list arg_list;
+ struct MHD_Daemon *d;
+
+ va_start (arg_list, proto_version);
+ if (setup_testcase (&d, daemon_flags, arg_list) != 0)
+ {
+ va_end (arg_list);
+ return -1;
+ }
+#if 0
+ fprintf (stdout, "running test: %s ", test_name);
+#endif
+ ret = test_function (test_fd, cipher_suite, proto_version);
+#if 0
+ if (ret == 0)
+ {
+ fprintf (stdout, "[pass]\n");
+ }
+ else
+ {
+ fprintf (stdout, "[fail]\n");
+ }
+#endif
+ teardown_testcase (d);
+ va_end (arg_list);
+ return ret;
+}
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_test_common.h b/lib/libmicrohttpd/src/testcurl/https/tls_test_common.h
new file mode 100644
index 0000000000..965614d12e
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_test_common.h
@@ -0,0 +1,118 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+#ifndef TLS_TEST_COMMON_H_
+#define TLS_TEST_COMMON_H_
+
+#include "platform.h"
+#include "microhttpd.h"
+#include <curl/curl.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include "gnutls.h"
+
+/* this enables verbos CURL version checking */
+#define DEBUG_HTTPS_TEST 0
+#define CURL_VERBOS_LEVEL 0
+
+#define DEAMON_TEST_PORT 42433
+
+#define TEST_FILE_NAME "https_test_file"
+
+#define EMPTY_PAGE "<html><head><title>Empty page</title></head><body>Empty page</body></html>"
+#define PAGE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>"
+
+#define MHD_E_MEM "Error: memory error\n"
+#define MHD_E_SERVER_INIT "Error: failed to start server\n"
+#define MHD_E_TEST_FILE_CREAT "Error: failed to setup test file\n"
+#define MHD_E_CERT_FILE_CREAT "Error: failed to setup test certificate\n"
+#define MHD_E_KEY_FILE_CREAT "Error: failed to setup test certificate\n"
+#define MHD_E_FAILED_TO_CONNECT "Error: server connection could not be established\n"
+
+/* TODO rm if unused */
+struct https_test_data
+{
+ FILE *test_fd;
+ char *cipher_suite;
+ int proto_version;
+};
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+struct CipherDef
+{
+ int options[2];
+ char *curlname;
+};
+
+void print_test_result (int test_outcome, char *test_name);
+
+size_t copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx);
+
+int
+http_ahc (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *upload_data,
+ const char *version, size_t *upload_data_size, void **ptr);
+
+int
+http_dummy_ahc (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *upload_data,
+ const char *version, size_t *upload_data_size,
+ void **ptr);
+
+int gen_test_file_url (char *url, int port);
+
+int
+send_curl_req (char *url, struct CBC *cbc, char *cipher_suite,
+ int proto_version);
+
+int
+test_https_transfer (FILE * test_fd, char *cipher_suite, int proto_version);
+
+FILE *setup_test_file ();
+
+int
+setup_testcase (struct MHD_Daemon **d, int daemon_flags, va_list arg_list);
+
+void teardown_testcase (struct MHD_Daemon *d);
+
+int
+setup_session (MHD_gtls_session_t * session,
+ MHD_gnutls_datum_t * key,
+ MHD_gnutls_datum_t * cert,
+ MHD_gtls_cert_credentials_t * xcred);
+
+int
+teardown_session (MHD_gtls_session_t session,
+ MHD_gnutls_datum_t * key,
+ MHD_gnutls_datum_t * cert,
+ MHD_gtls_cert_credentials_t xcred);
+
+int
+test_wrap (char *test_name, int
+ (*test_function) (FILE * test_fd, char *cipher_suite,
+ int proto_version), FILE * test_fd,
+ int daemon_flags, char *cipher_suite, int proto_version, ...);
+#endif /* TLS_TEST_COMMON_H_ */
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_test_keys.h b/lib/libmicrohttpd/src/testcurl/https/tls_test_keys.h
new file mode 100644
index 0000000000..8ad8ca35a8
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_test_keys.h
@@ -0,0 +1,173 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2006, 2007, 2008 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef MHD_TLS_TEST_KEYS_H
+#define MHD_TLS_TEST_KEYS_H
+
+/* Test Certificates */
+
+/* Certificate Authority key */
+const char ca_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIIEowIBAAKCAQEA0EdlP613rjFvEj93tGo9fzBoKWU3CW+AbbfcJ397C89MyZ9J\n"
+ "rlxyLGfa6qVX7CFVNmzgWWfcl2tHlw/fZmWtf/SFgrlkldvuGyY8H3n2HuMsWz/E\n"
+ "h7n5VgwBX8NsP4eZNmikepxpr1mYx25K8FjnsKjAR9jGUSV8UfZ7VLIY0x/yqe+3\n"
+ "32oqc4D/wJbV1AwwvC5Xf9rvHJwcZg57eqbDCL/4GDDk7d9Gark4XK6ZG+FnnxQn\n"
+ "4a4jIdf4FoPp9s0EieHrHwYzs/uBqmfCSF4wXiaO8bmEwtbAsVbZH74Le7ggUbEe\n"
+ "o+jan9XK0dE88AIImGzgoBnlic/Rr7J8OWA+iwIDAQABAoIBAEICZqXkUdpsw2F6\n"
+ "qPMOergNPO3lrKg6ZO8hBs6j2fj3tcPuzljK5sqJDboxNejZ9Zo+rmnXf3Oj5fgL\n"
+ "6UcYMYEsm4W/QRA3uEJ1fzeQnT7Ty9KNprlHaSzquCLEGlIWJSo3xu0vFlWjJUcL\n"
+ "fwemfaOhD/OVUeEU6s5FOngwy6pZUsOajs3fNRtwBGuuXjniKZZlpSf2Wqu3xpHZ\n"
+ "31OF1V0ycUCGPPFtpmUCtnZhS9L8QBTkNtfTIdXv6SfoBRFm0oXb0uL5HGft6yc7\n"
+ "eYRXIscllQciqG3ymJ/y9o0E3A0YsBVauQyi7OEk+Kg8uoYOBkZCIY69hoN2Znlk\n"
+ "OY5S5Z0CgYEA3j8pRAJzvc827KcX4vJf05HYD4aCyaI80fNmx1DgXfglTSGLQ361\n"
+ "6i05YW8WtIvgkma3wF+jJOckBCW/7iq8wAX7Kz75WKGRyyTEb0wSfjx0G8grxX4d\n"
+ "7sTIAAOnQj5WT6E/bkqxQZAYnVtIPxKtSlwts0H/bjPVYwSFchHK7t8CgYEA7+ks\n"
+ "C0EMjF8CDeCfvbOUGiiqAvU3G20LEC3WlJM3AU+J9Jzp6AMkgaIA8J5oNdsbFBn4\n"
+ "N12JPOO+7WRUk6Av8bsh4faE36ThnHohgAL8guRU7jIXvsFyO5yiY7/o/0lES0/V\n"
+ "6xkh/Epj4MReuCGkiD9ifCVAo+dhHskeE9qbYdUCgYA4yBpa7eV0UUTPIcHQkew5\n"
+ "ucFh9hPkQDcZzP4tXlR0rbmaAz/5dp4zvmoyopdCeZpezS+VTtn3y7Y/+QUYbILc\n"
+ "7KpHWkeKhX0iUbp+VQlEh12C25mTU62CG3SdzFEnc5XJsoDqRNsUzSP80B2dP8BW\n"
+ "h0aFzg7csRGLwtP1WOZoMQKBgQCrgsKd+Q8Dexh421DXyX3jhZalLrEKxlXWZy60\n"
+ "YNo98aLqYRNHbpe2pR6O5nARsGYXZMlyq0flY9um0sc0Epyz79g1NoufZrxzpUw1\n"
+ "u+zRlnKxJtaa5KjJvRzKuvPTLYnJXXXM8Na/Cl+E3F3qvQJm9QlvPyKLCmsAGz+J\n"
+ "agsTUQKBgC0wqqJ6b1tbrAD8AVeeAn/IiP1rxYpc3x2s6ikFO2FMHXHC9wgrRPOc\n"
+ "mkokV+DrUOv3I/7jG8wQA/FmBUPy562a1bObIKzg6CPXzrN68AmNnOIVU+H8fdxI\n"
+ "iGyfT8WNpcRmtN11v34qXHwOWGQhpyyk2yNa8VIBSpkShq/EseZ1\n"
+ "-----END RSA PRIVATE KEY-----\n";
+
+/* Certificate Authority cert */
+const char ca_cert_pem[] = "-----BEGIN CERTIFICATE-----\n"
+ "MIIC6DCCAdKgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
+ "dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
+ "A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
+ "0EdlP613rjFvEj93tGo9fzBoKWU3CW+AbbfcJ397C89MyZ9JrlxyLGfa6qVX7CFV\n"
+ "NmzgWWfcl2tHlw/fZmWtf/SFgrlkldvuGyY8H3n2HuMsWz/Eh7n5VgwBX8NsP4eZ\n"
+ "Nmikepxpr1mYx25K8FjnsKjAR9jGUSV8UfZ7VLIY0x/yqe+332oqc4D/wJbV1Aww\n"
+ "vC5Xf9rvHJwcZg57eqbDCL/4GDDk7d9Gark4XK6ZG+FnnxQn4a4jIdf4FoPp9s0E\n"
+ "ieHrHwYzs/uBqmfCSF4wXiaO8bmEwtbAsVbZH74Le7ggUbEeo+jan9XK0dE88AII\n"
+ "mGzgoBnlic/Rr7J8OWA+iwIDAQABo0MwQTAPBgNVHRMBAf8EBTADAQH/MA8GA1Ud\n"
+ "DwEB/wQFAwMHBAAwHQYDVR0OBBYEFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsGCSqG\n"
+ "SIb3DQEBBQOCAQEAebD5m+vZkVXa8y+QZ5GtsiR9gpH+LKtdWBjk1kmfSgvQI/xA\n"
+ "aDCV/9BhdNGIBOTYGkln8urWd7g2Mj3TwKEAfNTUFpAsrBAlSSLTGYCSt72S2NsS\n"
+ "L/qUxmj1W6X95UHXCo49mSZx3LlaY3mz1L87gq/kK0XpzA3g2uF25jt84RvshsXy\n"
+ "clOc+eRrVETqFZqer96WB7kzFTv+qmROQKmW8X4a2A5r5Jl4vRwOz5/rEeB9Qs0K\n"
+ "rmK8+5HgvWd80WB8BtfFtZfoY/hHVM8nLD3ELVJrOKiTeIACunQFyT5lV0QkdmSA\n"
+ "CGInU7jzs8nu+s2avf6j+eVZUbVJ+dFMApTJgg==\n"
+ "-----END CERTIFICATE-----\n";
+
+/* test server CA signed certificates */
+const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n"
+ "MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
+ "dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
+ "A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
+ "vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n"
+ "dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n"
+ "F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n"
+ "IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n"
+ "II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n"
+ "RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n"
+ "MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n"
+ "XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n"
+ "CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n"
+ "GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n"
+ "A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n"
+ "YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n"
+ "Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n"
+ "4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n"
+ "-----END CERTIFICATE-----\n";
+
+/* test server key */
+const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n"
+ "+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n"
+ "q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n"
+ "20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n"
+ "QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n"
+ "yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n"
+ "+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n"
+ "lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n"
+ "DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n"
+ "bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n"
+ "sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n"
+ "Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n"
+ "d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n"
+ "pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n"
+ "b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n"
+ "cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n"
+ "LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n"
+ "2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n"
+ "SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n"
+ "Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n"
+ "4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n"
+ "IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n"
+ "C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n"
+ "GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n"
+ "tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n"
+ "-----END RSA PRIVATE KEY-----\n";
+
+/* test server self signed certificates */
+const char srv_self_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n"
+ "MIIC+jCCAeSgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n"
+ "dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n"
+ "A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n"
+ "tDEagv3p9OUhUL55jMucxjNK9N5cuozhcnrwDfBSU6oVrqm5kPqO1I7Cggzw68Y5\n"
+ "jhTcBi4FXmYOZppm1R3MhSJ5JSi/67Q7X4J5rnJLXYGN27qjMpnoGQ/2xmsNG/is\n"
+ "i+h/2vbtPU+WP9SEJnTfPLLpZ7KqCAk7FUUzKsuLx3/SOKtdkrWxPKwYTgnDEN6D\n"
+ "JL7tEzCnG5DFc4mQ7YW9PaRdC3rS1T8PvQ3jB2BUnohM0cFvKRuiU35tU7h7CPbL\n"
+ "4L66VglXoiwqmgcrwI2U968bD0+wRQ5c5bzNoshJOzN6CTMh1IhbklSh/Z6FA/e8\n"
+ "hj0yVo2tdllXuJGVs3PIEwIDAQABo1UwUzAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n"
+ "MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFDfU7pAv9LYn\n"
+ "n7jb4WHl4+Vgi2FnMAsGCSqGSIb3DQEBBQOCAQEAkaembPQMmv6OOjbIod8zTatr\n"
+ "x5Bwkwp3TOE1NRyy2OytzFIYRUkNrZYlcmrxcbNNycIK41CNVXbriFCF8gcmIq9y\n"
+ "vaKZn8Gcy+vGggv+1BP9IAPBGKRwSi0wmq9JoGE8hx+qqTpRSdfbM/cps/09hicO\n"
+ "0EIR7kWEbvnpMBcMKYOtYE9Gce7rdSMWVAsKc174xn8vW6TxCUvmWFv5DPg5HG1v\n"
+ "y1SUX73qafRo+W6FN4UC/DHfwRhF8RSKEnVbmgDVCs6GHdKBjU2qRgYyj6nWZqK1\n"
+ "XFUTWgia+Fl3D9vlsXaFcSZKA0Bq1eojl0B0AfeYAxTFwPWXscKvt/bXZfH8bg==\n"
+ "-----END CERTIFICATE-----\n";
+
+/* test server key */
+const char srv_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIIEpAIBAAKCAQEAtDEagv3p9OUhUL55jMucxjNK9N5cuozhcnrwDfBSU6oVrqm5\n"
+ "kPqO1I7Cggzw68Y5jhTcBi4FXmYOZppm1R3MhSJ5JSi/67Q7X4J5rnJLXYGN27qj\n"
+ "MpnoGQ/2xmsNG/isi+h/2vbtPU+WP9SEJnTfPLLpZ7KqCAk7FUUzKsuLx3/SOKtd\n"
+ "krWxPKwYTgnDEN6DJL7tEzCnG5DFc4mQ7YW9PaRdC3rS1T8PvQ3jB2BUnohM0cFv\n"
+ "KRuiU35tU7h7CPbL4L66VglXoiwqmgcrwI2U968bD0+wRQ5c5bzNoshJOzN6CTMh\n"
+ "1IhbklSh/Z6FA/e8hj0yVo2tdllXuJGVs3PIEwIDAQABAoIBAAEtcg+LFLGtoxjq\n"
+ "b+tFttBJfbRcfdG6ocYqBGmUXF+MgFs573DHX3sHNOQxlaNHtSgIclF1eYgNZFFt\n"
+ "VLIoBFTzfEQXoFosPUDoEuqVMeXLttmD7P2jwL780XJLZ4Xj6GY07npq1iGBcEZf\n"
+ "yCcdoyGkr9jgc5Auyis8DStGg/jfUBC4NBvF0GnuuNPAdYRPKUpKw9EatI+FdMjy\n"
+ "BuroD90fhdkK8EwMEVb9P17bdIc1MCIZFpUE9YHjVdK/oxCUhQ8KRfdbI4JU5Zh3\n"
+ "UtO6Jm2wFuP3VmeVpPvE/C2rxI70pyl6HMSiFGNc0rhJYCQ+yhohWj7nZ67H4vLx\n"
+ "plv5LxkCgYEAz7ewou8oFafDAMNoxaqKudvUg+lxXewdLDKaYBF5ACi9uAPCJ+v7\n"
+ "M5c/fvPFn/XHzo7xaXbtTAH3Z5xzBs+80OsvL+e1Ut4xR+ELRkybknh/s2wQeABk\n"
+ "Kb0vA59ukQGj12LV5phZMaVoXe6KJ7hZnN62d3K6m1wGE/k58i4pPLUCgYEA3hN8\n"
+ "G95zW7g0jVdSr+KUeVmephph9yh8Yb+3I3ojwOIv6d45TopGx8pFZlnBAMZf1ZQx\n"
+ "DIhzJNnaqZy/4w7RNaOGWnPA/5f+MIoHBiLGEEmfHC3lt087Yp9OuwDUHwpETYdV\n"
+ "o+KBCvVh60Et3bZUgF/1k/3YXxn8J5dsmJsjNqcCgYBLflyRa1BrRnTGMz9CEDCp\n"
+ "Si9b3h1Y4Hbd2GppHhCXMTd6yMrpDYhYANGQB3M9Juv+s88j4JhwNoq/uonH4Pqk\n"
+ "B8Y3qAQr4RuSH0WkwDUOsALhqBX4N1QwI1USAQEDbNAqeP5698X7GD3tXcQSmZrg\n"
+ "O8WfdjBCRNjkq4EW9xX/vQKBgQDONtmwJ0iHiu2BseyeVo/4fzfKlgUSNQ4K1rOA\n"
+ "xhIdMeu8Bxa/z7caHsGC4SVPSuYCtbE2Kh6BwapChcPJXCD45fgEViiJLuJiwEj1\n"
+ "caTpyvNsf1IoffJvCe9ZxtMyX549P8ZOgC3Dt0hN5CBrGLwu2Ox5l+YrqT10pi+5\n"
+ "JZX1UQKBgQCrcXrdkkDAc/a4+PxNRpJRLcU4fhv8/lr+UWItE8eUe7bd25bTQfQm\n"
+ "VpNKc/kAJ66PjIED6fy3ADhd2y4naT2a24uAgQ/M494J68qLnGh6K4JU/09uxR2v\n"
+ "1i2q/4FNLdFFk1XP4iNnTHRLZ+NYr2p5Y9RcvQfTjOauz8Ahav0lyg==\n"
+ "-----END RSA PRIVATE KEY-----\n";
+
+#endif
diff --git a/lib/libmicrohttpd/src/testcurl/https/tls_thread_mode_test.c b/lib/libmicrohttpd/src/testcurl/https/tls_thread_mode_test.c
new file mode 100644
index 0000000000..cf92a26db8
--- /dev/null
+++ b/lib/libmicrohttpd/src/testcurl/https/tls_thread_mode_test.c
@@ -0,0 +1,172 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file tls_thread_mode_test.c
+ * @brief Testcase for libmicrohttpd HTTPS GET operations
+ * @author Sagie Amir
+ * @author Christian Grothoff
+ *
+ * TODO: add test for external select!
+ */
+
+#include "platform.h"
+#include "microhttpd.h"
+
+#include <sys/stat.h>
+#include <limits.h>
+#include "gnutls.h"
+#include <curl/curl.h>
+
+#include "tls_test_common.h"
+extern const char srv_key_pem[];
+extern const char srv_self_signed_cert_pem[];
+
+int curl_check_version (const char *req_version, ...);
+
+/**
+ * used when spawning multiple threads executing curl server requests
+ *
+ */
+static void *
+https_transfer_thread_adapter (void *args)
+{
+ static int nonnull;
+ struct https_test_data *cargs = args;
+ int ret;
+
+ /* time spread incomming requests */
+ usleep ((useconds_t) 10.0 * ((double) rand ()) / ((double) RAND_MAX));
+ ret = test_https_transfer (cargs->test_fd,
+ cargs->cipher_suite, cargs->proto_version);
+ if (ret == 0)
+ return NULL;
+ return &nonnull;
+}
+
+/**
+ * Test non-parallel requests.
+ *
+ * @return: 0 upon all client requests returning '0', -1 otherwise.
+ *
+ * TODO : make client_count a parameter - numver of curl client threads to spawn
+ */
+static int
+test_single_client (FILE * test_fd, char *cipher_suite,
+ int curl_proto_version)
+{
+ void *client_thread_ret;
+ struct https_test_data client_args =
+ { test_fd, cipher_suite, curl_proto_version };
+
+ client_thread_ret = https_transfer_thread_adapter (&client_args);
+ if (client_thread_ret != NULL)
+ return -1;
+ return 0;
+}
+
+/**
+ * Test parallel request handling.
+ *
+ * @return: 0 upon all client requests returning '0', -1 otherwise.
+ *
+ * TODO : make client_count a parameter - numver of curl client threads to spawn
+ */
+static int
+test_parallel_clients (FILE * test_fd, char *cipher_suite,
+ int curl_proto_version)
+{
+ int i;
+ int client_count = 3;
+ void *client_thread_ret;
+ pthread_t client_arr[client_count];
+ struct https_test_data client_args =
+ { test_fd, cipher_suite, curl_proto_version };
+
+ for (i = 0; i < client_count; ++i)
+ {
+ if (pthread_create (&client_arr[i], NULL,
+ &https_transfer_thread_adapter, &client_args) != 0)
+ {
+ fprintf (stderr, "Error: failed to spawn test client threads.\n");
+ return -1;
+ }
+ }
+
+ /* check all client requests fulfilled correctly */
+ for (i = 0; i < client_count; ++i)
+ {
+ if ((pthread_join (client_arr[i], &client_thread_ret) != 0) ||
+ (client_thread_ret != NULL))
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ FILE *test_fd;
+ unsigned int errorCount = 0;
+
+ /* initialize random seed used by curl clients */
+ unsigned int iseed = (unsigned int) time (NULL);
+ srand (iseed);
+
+ if (curl_check_version (MHD_REQ_CURL_VERSION))
+ return -1;
+
+ if ((test_fd = setup_test_file ()) == NULL)
+ {
+ fprintf (stderr, MHD_E_TEST_FILE_CREAT);
+ return -1;
+ }
+
+ if (0 != curl_global_init (CURL_GLOBAL_ALL))
+ {
+ fprintf (stderr, "Error: %s\n", strerror (errno));
+ fclose (test_fd);
+ remove (TEST_FILE_NAME);
+ return -1;
+ }
+
+ errorCount +=
+ test_wrap ("single threaded daemon, single client", &test_single_client,
+ test_fd,
+ MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL | MHD_USE_DEBUG,
+ "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY,
+ srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
+ srv_self_signed_cert_pem, MHD_OPTION_END);
+
+ errorCount +=
+ test_wrap ("single threaded daemon, parallel clients",
+ &test_parallel_clients, test_fd,
+ MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL | MHD_USE_DEBUG,
+ "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY,
+ srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
+ srv_self_signed_cert_pem, MHD_OPTION_END);
+
+ curl_global_cleanup ();
+ fclose (test_fd);
+ remove (TEST_FILE_NAME);
+
+ return errorCount != 0;
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/Makefile.am b/lib/libmicrohttpd/src/testzzuf/Makefile.am
new file mode 100644
index 0000000000..42bc2fdc3d
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/Makefile.am
@@ -0,0 +1,105 @@
+SUBDIRS = .
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+INCLUDES = -I$(top_srcdir)/src/include
+
+EXTRA_DIST = README socat.c
+
+check_PROGRAMS = \
+ daemontest_get \
+ daemontest_post \
+ daemontest_postform \
+ daemontest_put \
+ daemontest_large_put \
+ daemontest_get11 \
+ daemontest_post11 \
+ daemontest_postform11 \
+ daemontest_put11 \
+ daemontest_large_put11 \
+ daemontest_long_header \
+ daemontest_get_chunked \
+ daemontest_put_chunked
+
+TESTS = $(check_PROGRAMS)
+
+daemontest_get_SOURCES = \
+ daemontest_get.c
+daemontest_get_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get_chunked_SOURCES = \
+ daemontest_get_chunked.c
+daemontest_get_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_SOURCES = \
+ daemontest_post.c
+daemontest_post_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform_SOURCES = \
+ daemontest_postform.c
+daemontest_postform_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_SOURCES = \
+ daemontest_put.c
+daemontest_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_chunked_SOURCES = \
+ daemontest_put_chunked.c
+daemontest_put_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get11_SOURCES = \
+ daemontest_get.c
+daemontest_get11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post11_SOURCES = \
+ daemontest_post.c
+daemontest_post11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform11_SOURCES = \
+ daemontest_postform.c
+daemontest_postform11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put11_SOURCES = \
+ daemontest_put.c
+daemontest_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+
+daemontest_large_put_SOURCES = \
+ daemontest_large_put.c
+daemontest_large_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put11_SOURCES = \
+ daemontest_large_put.c
+daemontest_large_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_long_header_SOURCES = \
+ daemontest_long_header.c
+daemontest_long_header_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
diff --git a/lib/libmicrohttpd/src/testzzuf/Makefile.in b/lib/libmicrohttpd/src/testzzuf/Makefile.in
new file mode 100644
index 0000000000..e0908968ab
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/Makefile.in
@@ -0,0 +1,943 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+check_PROGRAMS = daemontest_get$(EXEEXT) daemontest_post$(EXEEXT) \
+ daemontest_postform$(EXEEXT) daemontest_put$(EXEEXT) \
+ daemontest_large_put$(EXEEXT) daemontest_get11$(EXEEXT) \
+ daemontest_post11$(EXEEXT) daemontest_postform11$(EXEEXT) \
+ daemontest_put11$(EXEEXT) daemontest_large_put11$(EXEEXT) \
+ daemontest_long_header$(EXEEXT) \
+ daemontest_get_chunked$(EXEEXT) \
+ daemontest_put_chunked$(EXEEXT)
+subdir = src/testzzuf
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/MHD_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am_daemontest_get_OBJECTS = daemontest_get.$(OBJEXT)
+daemontest_get_OBJECTS = $(am_daemontest_get_OBJECTS)
+daemontest_get_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_get11_OBJECTS = daemontest_get.$(OBJEXT)
+daemontest_get11_OBJECTS = $(am_daemontest_get11_OBJECTS)
+daemontest_get11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_get_chunked_OBJECTS = daemontest_get_chunked.$(OBJEXT)
+daemontest_get_chunked_OBJECTS = $(am_daemontest_get_chunked_OBJECTS)
+daemontest_get_chunked_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_large_put_OBJECTS = daemontest_large_put.$(OBJEXT)
+daemontest_large_put_OBJECTS = $(am_daemontest_large_put_OBJECTS)
+daemontest_large_put_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_large_put11_OBJECTS = daemontest_large_put.$(OBJEXT)
+daemontest_large_put11_OBJECTS = $(am_daemontest_large_put11_OBJECTS)
+daemontest_large_put11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_long_header_OBJECTS = daemontest_long_header.$(OBJEXT)
+daemontest_long_header_OBJECTS = $(am_daemontest_long_header_OBJECTS)
+daemontest_long_header_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_post_OBJECTS = daemontest_post.$(OBJEXT)
+daemontest_post_OBJECTS = $(am_daemontest_post_OBJECTS)
+daemontest_post_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_post11_OBJECTS = daemontest_post.$(OBJEXT)
+daemontest_post11_OBJECTS = $(am_daemontest_post11_OBJECTS)
+daemontest_post11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_postform_OBJECTS = daemontest_postform.$(OBJEXT)
+daemontest_postform_OBJECTS = $(am_daemontest_postform_OBJECTS)
+daemontest_postform_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_postform11_OBJECTS = daemontest_postform.$(OBJEXT)
+daemontest_postform11_OBJECTS = $(am_daemontest_postform11_OBJECTS)
+daemontest_postform11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_put_OBJECTS = daemontest_put.$(OBJEXT)
+daemontest_put_OBJECTS = $(am_daemontest_put_OBJECTS)
+daemontest_put_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_put11_OBJECTS = daemontest_put.$(OBJEXT)
+daemontest_put11_OBJECTS = $(am_daemontest_put11_OBJECTS)
+daemontest_put11_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+am_daemontest_put_chunked_OBJECTS = daemontest_put_chunked.$(OBJEXT)
+daemontest_put_chunked_OBJECTS = $(am_daemontest_put_chunked_OBJECTS)
+daemontest_put_chunked_DEPENDENCIES = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(daemontest_get_SOURCES) $(daemontest_get11_SOURCES) \
+ $(daemontest_get_chunked_SOURCES) \
+ $(daemontest_large_put_SOURCES) \
+ $(daemontest_large_put11_SOURCES) \
+ $(daemontest_long_header_SOURCES) $(daemontest_post_SOURCES) \
+ $(daemontest_post11_SOURCES) $(daemontest_postform_SOURCES) \
+ $(daemontest_postform11_SOURCES) $(daemontest_put_SOURCES) \
+ $(daemontest_put11_SOURCES) $(daemontest_put_chunked_SOURCES)
+DIST_SOURCES = $(daemontest_get_SOURCES) $(daemontest_get11_SOURCES) \
+ $(daemontest_get_chunked_SOURCES) \
+ $(daemontest_large_put_SOURCES) \
+ $(daemontest_large_put11_SOURCES) \
+ $(daemontest_long_header_SOURCES) $(daemontest_post_SOURCES) \
+ $(daemontest_post11_SOURCES) $(daemontest_postform_SOURCES) \
+ $(daemontest_postform11_SOURCES) $(daemontest_put_SOURCES) \
+ $(daemontest_put11_SOURCES) $(daemontest_put_chunked_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SOCAT = @HAVE_SOCAT@
+HAVE_ZZUF = @HAVE_ZZUF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_VERSION_AGE = @LIB_VERSION_AGE@
+LIB_VERSION_CURRENT = @LIB_VERSION_CURRENT@
+LIB_VERSION_REVISION = @LIB_VERSION_REVISION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MHD_LIBDEPS = @MHD_LIBDEPS@
+MHD_LIB_LDFLAGS = @MHD_LIB_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@
+PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = .
+@USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage
+INCLUDES = -I$(top_srcdir)/src/include
+EXTRA_DIST = README socat.c
+TESTS = $(check_PROGRAMS)
+daemontest_get_SOURCES = \
+ daemontest_get.c
+
+daemontest_get_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get_chunked_SOURCES = \
+ daemontest_get_chunked.c
+
+daemontest_get_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post_SOURCES = \
+ daemontest_post.c
+
+daemontest_post_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform_SOURCES = \
+ daemontest_postform.c
+
+daemontest_postform_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_SOURCES = \
+ daemontest_put.c
+
+daemontest_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put_chunked_SOURCES = \
+ daemontest_put_chunked.c
+
+daemontest_put_chunked_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_get11_SOURCES = \
+ daemontest_get.c
+
+daemontest_get11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_post11_SOURCES = \
+ daemontest_post.c
+
+daemontest_post11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_postform11_SOURCES = \
+ daemontest_postform.c
+
+daemontest_postform11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_put11_SOURCES = \
+ daemontest_put.c
+
+daemontest_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put_SOURCES = \
+ daemontest_large_put.c
+
+daemontest_large_put_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_large_put11_SOURCES = \
+ daemontest_large_put.c
+
+daemontest_large_put11_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+daemontest_long_header_SOURCES = \
+ daemontest_long_header.c
+
+daemontest_long_header_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/testzzuf/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/testzzuf/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+daemontest_get$(EXEEXT): $(daemontest_get_OBJECTS) $(daemontest_get_DEPENDENCIES)
+ @rm -f daemontest_get$(EXEEXT)
+ $(LINK) $(daemontest_get_OBJECTS) $(daemontest_get_LDADD) $(LIBS)
+daemontest_get11$(EXEEXT): $(daemontest_get11_OBJECTS) $(daemontest_get11_DEPENDENCIES)
+ @rm -f daemontest_get11$(EXEEXT)
+ $(LINK) $(daemontest_get11_OBJECTS) $(daemontest_get11_LDADD) $(LIBS)
+daemontest_get_chunked$(EXEEXT): $(daemontest_get_chunked_OBJECTS) $(daemontest_get_chunked_DEPENDENCIES)
+ @rm -f daemontest_get_chunked$(EXEEXT)
+ $(LINK) $(daemontest_get_chunked_OBJECTS) $(daemontest_get_chunked_LDADD) $(LIBS)
+daemontest_large_put$(EXEEXT): $(daemontest_large_put_OBJECTS) $(daemontest_large_put_DEPENDENCIES)
+ @rm -f daemontest_large_put$(EXEEXT)
+ $(LINK) $(daemontest_large_put_OBJECTS) $(daemontest_large_put_LDADD) $(LIBS)
+daemontest_large_put11$(EXEEXT): $(daemontest_large_put11_OBJECTS) $(daemontest_large_put11_DEPENDENCIES)
+ @rm -f daemontest_large_put11$(EXEEXT)
+ $(LINK) $(daemontest_large_put11_OBJECTS) $(daemontest_large_put11_LDADD) $(LIBS)
+daemontest_long_header$(EXEEXT): $(daemontest_long_header_OBJECTS) $(daemontest_long_header_DEPENDENCIES)
+ @rm -f daemontest_long_header$(EXEEXT)
+ $(LINK) $(daemontest_long_header_OBJECTS) $(daemontest_long_header_LDADD) $(LIBS)
+daemontest_post$(EXEEXT): $(daemontest_post_OBJECTS) $(daemontest_post_DEPENDENCIES)
+ @rm -f daemontest_post$(EXEEXT)
+ $(LINK) $(daemontest_post_OBJECTS) $(daemontest_post_LDADD) $(LIBS)
+daemontest_post11$(EXEEXT): $(daemontest_post11_OBJECTS) $(daemontest_post11_DEPENDENCIES)
+ @rm -f daemontest_post11$(EXEEXT)
+ $(LINK) $(daemontest_post11_OBJECTS) $(daemontest_post11_LDADD) $(LIBS)
+daemontest_postform$(EXEEXT): $(daemontest_postform_OBJECTS) $(daemontest_postform_DEPENDENCIES)
+ @rm -f daemontest_postform$(EXEEXT)
+ $(LINK) $(daemontest_postform_OBJECTS) $(daemontest_postform_LDADD) $(LIBS)
+daemontest_postform11$(EXEEXT): $(daemontest_postform11_OBJECTS) $(daemontest_postform11_DEPENDENCIES)
+ @rm -f daemontest_postform11$(EXEEXT)
+ $(LINK) $(daemontest_postform11_OBJECTS) $(daemontest_postform11_LDADD) $(LIBS)
+daemontest_put$(EXEEXT): $(daemontest_put_OBJECTS) $(daemontest_put_DEPENDENCIES)
+ @rm -f daemontest_put$(EXEEXT)
+ $(LINK) $(daemontest_put_OBJECTS) $(daemontest_put_LDADD) $(LIBS)
+daemontest_put11$(EXEEXT): $(daemontest_put11_OBJECTS) $(daemontest_put11_DEPENDENCIES)
+ @rm -f daemontest_put11$(EXEEXT)
+ $(LINK) $(daemontest_put11_OBJECTS) $(daemontest_put11_LDADD) $(LIBS)
+daemontest_put_chunked$(EXEEXT): $(daemontest_put_chunked_OBJECTS) $(daemontest_put_chunked_DEPENDENCIES)
+ @rm -f daemontest_put_chunked$(EXEEXT)
+ $(LINK) $(daemontest_put_chunked_OBJECTS) $(daemontest_put_chunked_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_get.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_get_chunked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_large_put.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_long_header.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_post.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_postform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_put.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemontest_put_chunked.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \
+ ctags-recursive install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/libmicrohttpd/src/testzzuf/README b/lib/libmicrohttpd/src/testzzuf/README
new file mode 100644
index 0000000000..5ee1569838
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/README
@@ -0,0 +1,13 @@
+Testcases in this directory require zzuf and socat.
+
+zzuf is used to randomly mess with the TCP connection between the CURL
+clients and the MHD server. The goal is to expose problems in MHD's
+error handling (by introducing random syntax errors). socat is
+used to listen on port 11081 and forward the randomzied stream to
+port 11080 where MHD is waiting.
+
+As a result, the testcases in this directory do NOT check that
+whatever CURL returns is what was expected -- random modifications to
+the TCP stream can have random effects ;-). Testcases "fail" if the
+code crashes or hangs indefinitely.
+
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_get.c b/lib/libmicrohttpd/src/testzzuf/daemontest_get.c
new file mode 100644
index 0000000000..ed0e771926
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_get.c
@@ -0,0 +1,313 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get.c
+ * @brief Testcase for libmicrohttpd GET operations
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#include "socat.c"
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+
+static int
+testInternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ }
+ fprintf (stderr, "\n");
+ curl_multi_cleanup (multi);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalGet ();
+ errorCount += testMultithreadedGet ();
+ errorCount += testExternalGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_get_chunked.c b/lib/libmicrohttpd/src/testzzuf/daemontest_get_chunked.c
new file mode 100644
index 0000000000..29ee5028c5
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_get_chunked.c
@@ -0,0 +1,330 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get_chunked.c
+ * @brief Testcase for libmicrohttpd GET operations with chunked content encoding
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#include "socat.c"
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+/**
+ * MHD content reader callback that returns
+ * data in chunks.
+ */
+static int
+crc (void *cls, uint64_t pos, char *buf, int max)
+{
+ struct MHD_Response **responseptr = cls;
+
+ if (pos == 128 * 10)
+ {
+ MHD_add_response_header (*responseptr, "Footer", "working");
+ return -1; /* end of stream */
+ }
+ if (max < 128)
+ abort (); /* should not happen in this testcase... */
+ memset (buf, 'A' + (pos / 128), 128);
+ return 128;
+}
+
+/**
+ * Dummy function that does nothing.
+ */
+static void
+crcf (void *ptr)
+{
+ free (ptr);
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size, void **ptr)
+{
+ static int aptr;
+ const char *me = cls;
+ struct MHD_Response *response;
+ struct MHD_Response **responseptr;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&aptr != *ptr)
+ {
+ /* do never respond on first call */
+ *ptr = &aptr;
+ return MHD_YES;
+ }
+ responseptr = malloc (sizeof (struct MHD_Response *));
+ response = MHD_create_response_from_callback (-1,
+ 1024,
+ &crc, responseptr, &crcf);
+ *responseptr = response;
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+static int
+testInternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ }
+ fprintf (stderr, "\n");
+ curl_multi_cleanup (multi);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalGet ();
+ errorCount += testMultithreadedGet ();
+ errorCount += testExternalGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_large_put.c b/lib/libmicrohttpd/src/testzzuf/daemontest_large_put.c
new file mode 100644
index 0000000000..7bdfde8542
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_large_put.c
@@ -0,0 +1,381 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_large_put.c
+ * @brief Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#include "socat.c"
+
+static int oneone;
+
+/**
+ * Do not make this much larger since we will hit the
+ * MHD default buffer limit and the test code is not
+ * written for incremental upload processing...
+ */
+#define PUT_SIZE (256 * 1024)
+
+static char *put_buffer;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+ unsigned int *pos = ptr;
+ unsigned int wrt;
+
+ wrt = size * nmemb;
+ if (wrt > PUT_SIZE - (*pos))
+ wrt = PUT_SIZE - (*pos);
+ memcpy (stream, &put_buffer[*pos], wrt);
+ (*pos) += wrt;
+ return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ int *done = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp ("PUT", method))
+ return MHD_NO; /* unexpected method */
+ if ((*done) == 0)
+ {
+ if (*upload_data_size != PUT_SIZE)
+ {
+#if 0
+ fprintf (stderr,
+ "Waiting for more data (%u/%u)...\n",
+ *upload_data_size, PUT_SIZE);
+#endif
+ return MHD_YES; /* not yet ready */
+ }
+ if (0 == memcmp (upload_data, put_buffer, PUT_SIZE))
+ {
+ *upload_data_size = 0;
+ }
+ else
+ {
+ return MHD_NO;
+ }
+ *done = 1;
+ return MHD_YES;
+ }
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ char buf[2048];
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ char buf[2048];
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ char buf[2048];
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ multi = NULL;
+ d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ PUT_SIZE * 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ curl_multi_cleanup (multi);
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ put_buffer = malloc (PUT_SIZE);
+ memset (put_buffer, 1, PUT_SIZE);
+ errorCount += testInternalPut ();
+ errorCount += testMultithreadedPut ();
+ errorCount += testExternalPut ();
+ free (put_buffer);
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_long_header.c b/lib/libmicrohttpd/src/testzzuf/daemontest_long_header.c
new file mode 100644
index 0000000000..99b9e5e3c6
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_long_header.c
@@ -0,0 +1,231 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_long_header.c
+ * @brief Testcase for libmicrohttpd handling of very long headers
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#include "socat.c"
+
+/**
+ * We will set the memory available per connection to
+ * half of this value, so the actual value does not have
+ * to be big at all...
+ */
+#define VERY_LONG (1024*10)
+
+static int oneone;
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return MHD_YES;
+}
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ const char *me = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testLongUrlGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ char *url;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080,
+ &apc_all,
+ NULL,
+ &ahc_echo,
+ "GET",
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (VERY_LONG / 2), MHD_OPTION_END);
+
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ url = malloc (VERY_LONG);
+ memset (url, 'a', VERY_LONG);
+ url[VERY_LONG - 1] = '\0';
+ memcpy (url, "http://localhost:11081/",
+ strlen ("http://localhost:11081/"));
+ curl_easy_setopt (c, CURLOPT_URL, url);
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+
+ MHD_stop_daemon (d);
+ free (url);
+ return 0;
+}
+
+
+static int
+testLongHeaderGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ char *url;
+ struct curl_slist *header = NULL;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080,
+ &apc_all,
+ NULL,
+ &ahc_echo,
+ "GET",
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+ (size_t) (VERY_LONG / 2), MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ url = malloc (VERY_LONG);
+ memset (url, 'a', VERY_LONG);
+ url[VERY_LONG - 1] = '\0';
+ url[VERY_LONG / 2] = ':';
+ url[VERY_LONG / 2 + 1] = ' ';
+ header = curl_slist_append (header, url);
+
+ curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_slist_free_all (header);
+ header = NULL;
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+
+ MHD_stop_daemon (d);
+ free (url);
+ return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testLongUrlGet ();
+ errorCount += testLongHeaderGet ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_post.c b/lib/libmicrohttpd/src/testzzuf/daemontest_post.c
new file mode 100644
index 0000000000..6323a5eb82
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_post.c
@@ -0,0 +1,372 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_post.c
+ * @brief Testcase for libmicrohttpd POST operations using URL-encoding
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+
+#include "socat.c"
+
+#define POST_DATA "name=daniel&project=curl"
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+/**
+ * Note that this post_iterator is not perfect
+ * in that it fails to support incremental processing.
+ * (to be fixed in the future)
+ */
+static int
+post_iterator (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *value, uint64_t off, size_t size)
+{
+ int *eok = cls;
+
+ if ((0 == strcmp (key, "name")) &&
+ (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size)))
+ (*eok) |= 1;
+ if ((0 == strcmp (key, "project")) &&
+ (size == strlen ("curl")) && (0 == strncmp (value, "curl", size)))
+ (*eok) |= 2;
+ return MHD_YES;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int eok;
+ struct MHD_Response *response;
+ struct MHD_PostProcessor *pp;
+ int ret;
+
+ if (0 != strcmp ("POST", method))
+ {
+ return MHD_NO; /* unexpected method */
+ }
+ pp = *unused;
+ if (pp == NULL)
+ {
+ eok = 0;
+ pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok);
+ *unused = pp;
+ }
+ MHD_post_process (pp, upload_data, *upload_data_size);
+ if ((eok == 3) && (0 == *upload_data_size))
+ {
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url,
+ MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ MHD_destroy_post_processor (pp);
+ *unused = NULL;
+ return ret;
+ }
+ *upload_data_size = 0;
+ return MHD_YES;
+}
+
+
+static int
+testInternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+
+ return 0;
+}
+
+static int
+testMultithreadedPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testExternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
+ 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+ curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+ curl_easy_setopt (c, CURLOPT_POST, 1L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+
+ }
+ fprintf (stderr, "\n");
+ curl_multi_cleanup (multi);
+ zzuf_socat_stop ();
+
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPost ();
+ errorCount += testMultithreadedPost ();
+ errorCount += testExternalPost ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_postform.c b/lib/libmicrohttpd/src/testzzuf/daemontest_postform.c
new file mode 100644
index 0000000000..817b0bc726
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_postform.c
@@ -0,0 +1,387 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_post.c
+ * @brief Testcase for libmicrohttpd POST operations using multipart/postform data
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+
+#include "socat.c"
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+/**
+ * Note that this post_iterator is not perfect
+ * in that it fails to support incremental processing.
+ * (to be fixed in the future)
+ */
+static int
+post_iterator (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *value, uint64_t off, size_t size)
+{
+ int *eok = cls;
+
+ if (key == NULL)
+ return MHD_YES;
+#if 0
+ fprintf (stderr, "PI sees %s-%.*s\n", key, size, value);
+#endif
+ if ((0 == strcmp (key, "name")) &&
+ (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size)))
+ (*eok) |= 1;
+ if ((0 == strcmp (key, "project")) &&
+ (size == strlen ("curl")) && (0 == strncmp (value, "curl", size)))
+ (*eok) |= 2;
+ return MHD_YES;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int eok;
+ struct MHD_Response *response;
+ struct MHD_PostProcessor *pp;
+ int ret;
+
+ if (0 != strcmp ("POST", method))
+ {
+ return MHD_NO; /* unexpected method */
+ }
+ pp = *unused;
+ if (pp == NULL)
+ {
+ eok = 0;
+ pp = MHD_create_post_processor (connection, 1024, &post_iterator, &eok);
+ if (pp == NULL)
+ return MHD_NO;
+ *unused = pp;
+ }
+ MHD_post_process (pp, upload_data, *upload_data_size);
+ if ((eok == 3) && (0 == *upload_data_size))
+ {
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url,
+ MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ MHD_destroy_post_processor (pp);
+ *unused = NULL;
+ return ret;
+ }
+ *upload_data_size = 0;
+ return MHD_YES;
+}
+
+static struct curl_httppost *
+make_form ()
+{
+ struct curl_httppost *post = NULL;
+ struct curl_httppost *last = NULL;
+
+ curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
+ curl_formadd (&post, &last, CURLFORM_COPYNAME, "project",
+ CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
+ return post;
+}
+
+
+static int
+testInternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+ struct curl_httppost *pd;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ int i;
+ struct curl_httppost *pd;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
+ 11080, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testExternalPost ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ struct curl_httppost *pd;
+ int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
+ 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ pd = make_form ();
+ curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_formfree (pd);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ curl_formfree (pd);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ curl_formfree (pd);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ curl_formfree (pd);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPost ();
+ errorCount += testMultithreadedPost ();
+ errorCount += testExternalPost ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_put.c b/lib/libmicrohttpd/src/testzzuf/daemontest_put.c
new file mode 100644
index 0000000000..c759e05559
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_put.c
@@ -0,0 +1,360 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put.c
+ * @brief Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+
+#include "socat.c"
+
+static int oneone;
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+ unsigned int *pos = ptr;
+ unsigned int wrt;
+
+ wrt = size * nmemb;
+ if (wrt > 8 - (*pos))
+ wrt = 8 - (*pos);
+ memcpy (stream, &("Hello123"[*pos]), wrt);
+ (*pos) += wrt;
+ return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ int *done = cls;
+ struct MHD_Response *response;
+ int ret;
+
+ if (0 != strcmp ("PUT", method))
+ return MHD_NO; /* unexpected method */
+ if ((*done) == 0)
+ {
+ if (*upload_data_size != 8)
+ return MHD_YES; /* not yet ready */
+ if (0 == memcmp (upload_data, "Hello123", 8))
+ {
+ *upload_data_size = 0;
+ }
+ else
+ {
+ printf ("Invalid upload data `%8s'!\n", upload_data);
+ return MHD_NO;
+ }
+ *done = 1;
+ return MHD_YES;
+ }
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION /* | MHD_USE_DEBUG */ ,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ ,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ }
+ fprintf (stderr, "\n");
+ curl_multi_cleanup (multi);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPut ();
+ errorCount += testMultithreadedPut ();
+ errorCount += testExternalPut ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/daemontest_put_chunked.c b/lib/libmicrohttpd/src/testzzuf/daemontest_put_chunked.c
new file mode 100644
index 0000000000..d49478ee91
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/daemontest_put_chunked.c
@@ -0,0 +1,370 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put_chunked.c
+ * @brief Testcase for libmicrohttpd PUT operations with chunked encoding
+ * for the upload data
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+#include "socat.c"
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+ unsigned int *pos = ptr;
+ unsigned int wrt;
+
+ wrt = size * nmemb;
+ if (wrt > 8 - (*pos))
+ wrt = 8 - (*pos);
+ if (wrt > 4)
+ wrt = 4; /* only send half at first => force multiple chunks! */
+ memcpy (stream, &("Hello123"[*pos]), wrt);
+ (*pos) += wrt;
+ return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ int *done = cls;
+ struct MHD_Response *response;
+ int ret;
+ int have;
+
+ if (0 != strcmp ("PUT", method))
+ return MHD_NO; /* unexpected method */
+ if ((*done) < 8)
+ {
+ have = *upload_data_size;
+ if (have + *done > 8)
+ {
+ return MHD_NO;
+ }
+ if (0 == memcmp (upload_data, &"Hello123"[*done], have))
+ {
+ *done += have;
+ *upload_data_size = 0;
+ }
+ else
+ {
+ return MHD_NO;
+ }
+#if 0
+ fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
+#endif
+ return MHD_YES;
+ }
+ response = MHD_create_response_from_data (strlen (url),
+ (void *) url, MHD_NO, MHD_YES);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ 11080,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ curl_easy_perform (c);
+ curl_easy_cleanup (c);
+ }
+ fprintf (stderr, "\n");
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ CURLcode errornum;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ 11081,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+
+ return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ time_t start;
+ struct timeval tv;
+ unsigned int pos = 0;
+ int done_flag = 0;
+ int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ cbc.pos = 0;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 11082,
+ NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ zzuf_socat_start ();
+ for (i = 0; i < LOOP_COUNT; i++)
+ {
+ fprintf (stderr, ".");
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+ curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+ curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+ /*
+ // by not giving the file size, we force chunking!
+ curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+ */
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT);
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT);
+ // NOTE: use of CONNECTTIMEOUT without also
+ // setting NOSIGNAL results in really weird
+ // crashes on my system!
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ curl_multi_info_read (multi, &running);
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ MHD_run (d);
+ }
+ if (c != NULL)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ }
+ }
+ fprintf (stderr, "\n");
+ curl_multi_cleanup (multi);
+ zzuf_socat_stop ();
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ errorCount += testInternalPut ();
+ errorCount += testMultithreadedPut ();
+ errorCount += testExternalPut ();
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
diff --git a/lib/libmicrohttpd/src/testzzuf/socat.c b/lib/libmicrohttpd/src/testzzuf/socat.c
new file mode 100644
index 0000000000..e4559a02b4
--- /dev/null
+++ b/lib/libmicrohttpd/src/testzzuf/socat.c
@@ -0,0 +1,107 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2008 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file socat.c
+ * @brief Code to fork-exec zzuf and start the socat process
+ * @author Christian Grothoff
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+
+/**
+ * A larger loop count will run more random tests --
+ * which would be good, except that it may take too
+ * long for most user's patience. So this small
+ * value is the default.
+ */
+#define LOOP_COUNT 10
+
+#define CURL_TIMEOUT 50L
+
+static pid_t zzuf_pid;
+
+static void
+zzuf_socat_start ()
+{
+ int status;
+ char *const args[] = {
+ "zzuf",
+ "--ratio=0.0:0.75",
+ "-n",
+ "-A",
+ "--",
+ "socat",
+ "-lf",
+ "/dev/null",
+ "TCP4-LISTEN:11081,reuseaddr,fork",
+ "TCP4:127.0.0.1:11080",
+ NULL,
+ };
+ zzuf_pid = fork ();
+ if (zzuf_pid == -1)
+ {
+ fprintf (stderr, "fork failed: %s\n", strerror (errno));
+ exit (1);
+ }
+ if (zzuf_pid != 0)
+ {
+ sleep (1); /* allow zzuf and socat to start */
+ status = 0;
+ if (0 < waitpid (zzuf_pid, &status, WNOHANG))
+ {
+ if (WIFEXITED (status))
+ fprintf (stderr,
+ "zzuf died with status code %d!\n",
+ WEXITSTATUS (status));
+ if (WIFSIGNALED (status))
+ fprintf (stderr,
+ "zzuf died from signal %d!\n", WTERMSIG (status));
+ exit (1);
+ }
+ return;
+ }
+ setpgrp ();
+ execvp ("zzuf", args);
+ fprintf (stderr, "execution of `zzuf' failed: %s\n", strerror (errno));
+ zzuf_pid = 0; /* fork failed */
+ exit (1);
+}
+
+
+static void
+zzuf_socat_stop ()
+{
+ int status;
+ if (zzuf_pid != 0)
+ {
+ if (0 != killpg (zzuf_pid, SIGINT))
+ fprintf (stderr, "Failed to killpg: %s\n", strerror (errno));
+ kill (zzuf_pid, SIGINT);
+ waitpid (zzuf_pid, &status, 0);
+ sleep (1); /* allow socat to also die in peace */
+ }
+}
+
+/* end of socat.c */