http: Revamp TLS API.

* configure.ac (NEED_GNUTLS_VERSION): New.
(HTTP_USE_GNUTLS, LIBGNUTLS_CFLAGS, LIBGNUTLS_LIBS): New ac_subst.

* common/http.h (http_session_t): New.
* common/http.c: Remove compatibility for gnutls < 3.0.
(http_session_s): New.
(cookie_s): Replace gnutls_session_t by http_session_t.
(tls_callback, tls_ca_certlist): New variables.
(my_socket_unref): Add preclose args.
(my_npth_read, my_npth_write): New.
(make_header_line): Fix bug using int* instead of char*.
(http_register_tls_callback): New.
(http_register_tls_ca): New.
(http_session_new): New.
(http_session_release): New.
(http_get_header_names): New.
(escape_data): Add hack to escape in forms mode.
(send_request) [HTTP_USE_GNUTLS]: Support SNI.
(send_request) [HTTP_USE_GNUTLS]: Fix use of make_header_line.
(send_gnutls_bye): New.
(cookie_close): Make use of preclose feature.
(http_verify_server_credentials): New.
(main) [TEST]: Remove test code.
* common/t-http.c: New.
* common/tls-ca.pem: New.
* common/Makefile.am (tls_sources): New. Move http code to here.
(libcommontls_a_SOURCES): New.
(libcommontlsnpth_a_SOURCES): New.
(EXTRA_DIST): Add tls-ca.pem
(module_maint_tests): Add t-http.
(t_http_SOURCES, t_http_CFLAGS, t_http_LDADD): New.

* dirmngr/Makefile.am (dirmngr_LDADD): Add libcommontlsnpth.
--

This new TLS API for http.c is much more flexible than the crude old
hack.
This commit is contained in:
Werner Koch 2014-05-02 10:33:19 +02:00
parent 84289e85c7
commit 8412a5825c
8 changed files with 775 additions and 226 deletions

View File

@ -75,3 +75,5 @@ resource_objs =
# Convenience macros
libcommon = ../common/libcommon.a
libcommonpth = ../common/libcommonpth.a
libcommontls = ../common/libcommontls.a
libcommontlsnpth = ../common/libcommontlsnpth.a

View File

@ -20,9 +20,10 @@
EXTRA_DIST = mkstrtable.awk exaudit.awk exstatus.awk ChangeLog-2011 \
audit-events.h status-codes.h README.jnlib ChangeLog.jnlib \
ChangeLog-2011.include w32info-rc.h.in gnupg.ico
ChangeLog-2011.include w32info-rc.h.in gnupg.ico tls-ca.pem
noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a
noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a \
libcommontls.a libcommontlsnpth.a
if !HAVE_W32CE_SYSTEM
noinst_LIBRARIES += libsimple-pwquery.a
endif
@ -88,7 +89,6 @@ common_sources = \
srv.h \
dns-cert.c dns-cert.h \
pka.c pka.h \
http.c http.h \
localename.c \
session-env.c session-env.h \
userids.c userids.h \
@ -97,6 +97,12 @@ common_sources = \
agent-opt.c \
helpfile.c
# Sources possible requiring a TLS library are put into a separate
# conveince library.
tls_sources = \
http.c http.h
# To make the code easier to read we have split home some code into
# separate source files.
if HAVE_W32_SYSTEM
@ -126,6 +132,12 @@ libcommonpth_a_SOURCES += srv.c
endif
libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
libcommontls_a_SOURCES = $(tls_sources)
libcommontls_a_CFLAGS = $(AM_CFLAGS) $(LIBGNUTLS_CFLAGS) -DWITHOUT_NPTH=1
libcommontlsnpth_a_SOURCES = $(tls_sources)
libcommontlsnpth_a_CFLAGS = $(AM_CFLAGS) $(LIBGNUTLS_CFLAGS) $(NPTH_CFLAGS)
if !HAVE_W32CE_SYSTEM
libsimple_pwquery_a_SOURCES = \
simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h
@ -170,11 +182,12 @@ module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil \
if !HAVE_W32CE_SYSTEM
module_tests += t-exechelp
endif
module_maint_tests = t-helpfile t-b64
module_maint_tests = t-helpfile t-b64 t-http
t_common_ldadd = libcommon.a ../gl/libgnu.a \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBINTL) $(LIBICONV)
# jnlib tests
t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src)
@ -203,3 +216,8 @@ t_ssh_utils_LDADD = $(t_common_ldadd)
t_dns_cert_LDADD = $(t_common_ldadd) $(DNSLIBS)
t_mapstrings_LDADD = $(t_common_ldadd)
t_zb32_LDADD = $(t_common_ldadd)
# http tests
t_http_SOURCES = t-http.c
t_http_CFLAGS = $(t_common_cflags) $(LIBGNUTLS_CFLAGS)
t_http_LDADD = $(libcommontls) $(t_common_ldadd) $(LIBGNUTLS_LIBS) $(DNSLIBS)

View File

@ -39,8 +39,9 @@
- fixme: list other requirements.
- With HTTP_USE_GNUTLS support for https is provided (this also
requires estream).
- With HTTP_USE_GNUTLS or HTTP_USE_POLARSSL support for https is
provided (this also requires estream).
- With HTTP_NO_WSASTARTUP the socket initialization is not done
under Windows. This is useful if the socket layer has already
been initialized elsewhere. This also avoids the installation of
@ -81,20 +82,19 @@
# include <npth.h>
#endif
#if defined (HTTP_USE_GNUTLS) && defined (HTTP_USE_POLARSSL)
# error Both, HTTP_USE_GNUTLS and HTTP_USE_POLARSSL, are defined.
#endif
#ifdef HTTP_USE_GNUTLS
# include <gnutls/gnutls.h>
/* For non-understandable reasons GNUTLS dropped the _t suffix from
all types. yes, ISO-C might be read as this but there are still
other name space conflicts and using _t is actually a Good
Thing. */
typedef gnutls_session gnutls_session_t;
typedef gnutls_transport_ptr gnutls_transport_ptr_t;
# include <gnutls/x509.h>
#endif /*HTTP_USE_GNUTLS*/
#ifdef TEST
# undef USE_DNS_SRV
#ifdef HTTP_USE_POLARSSL
# error Support for PolarSSL has not yet been added
#endif
#include "util.h"
#include "i18n.h"
#include "http.h"
@ -204,22 +204,36 @@ struct cookie_s
/* Socket object or NULL if already closed. */
my_socket_t sock;
/* TLS session context or NULL if not used. */
gnutls_session_t tls_session;
/* The session object or NULL if not used. */
http_session_t session;
/* True if TLS is to be used. */
int use_tls;
/* The remaining content length and a flag telling whether to use
the content length. */
longcounter_t content_length;
unsigned int content_length_valid:1;
/* Flag to communicate with the close handler. */
unsigned int keep_socket:1;
};
typedef struct cookie_s *cookie_t;
/* The session object. */
struct http_session_s
{
#ifdef HTTP_USE_GNUTLS
static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int);
#endif /*HTTP_USE_GNUTLS*/
gnutls_certificate_credentials_t certcred;
gnutls_session_t tls_session;
struct {
int done; /* Verifciation has been done. */
int rc; /* GnuTLS verification return code. */
unsigned int status; /* Verification status. */
} verify;
char *servername; /* Malloced server name. */
#else
int dummy;
#endif
};
/* An object to save header lines. */
@ -243,7 +257,7 @@ struct http_context_s
estream_t fp_write;
void *write_cookie;
void *read_cookie;
void *tls_context;
http_session_t session;
parsed_uri_t uri;
http_req_t req_type;
char *buffer; /* Line buffer. */
@ -253,6 +267,12 @@ struct http_context_s
};
/* The global callback for the verification fucntion. */
static gpg_error_t (*tls_callback) (http_t, http_session_t, int);
/* The list of files with trusted CA certificates. */
static strlist_t tls_ca_certlist;
#if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
@ -340,7 +360,7 @@ my_socket_ref (my_socket_t so)
has no more references, close the socket and release the
object. */
static void
my_socket_unref (my_socket_t so)
my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg)
{
if (so)
{
@ -349,6 +369,8 @@ my_socket_unref (my_socket_t so)
/* lnr, so, so->fd, so->refcount); */
if (!so->refcount)
{
if (preclose)
preclose (preclosearg);
sock_close (so->fd);
xfree (so);
}
@ -357,6 +379,21 @@ my_socket_unref (my_socket_t so)
/* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */
#if defined (USE_NPTH) && defined(HTTP_USE_GNUTLS)
static ssize_t
my_npth_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size)
{
return npth_read ((int)(unsigned long)ptr, buffer, size);
}
static ssize_t
my_npth_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
{
return npth_write ((int)(unsigned long)ptr, buffer, size);
}
#endif /*USE_NPTH && HTTP_USE_GNUTLS*/
/* This notification function is called by estream whenever stream is
closed. Its purpose is to mark the closing in the handle so
@ -383,13 +420,13 @@ fp_onclose_notification (estream_t stream, void *opaque)
*/
static char *
make_header_line (const char *prefix, const char *suffix,
const void *data, size_t len )
const void *data, size_t len )
{
static unsigned char bintoasc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
const unsigned int *s = data;
const unsigned char *s = data;
char *buffer, *p;
buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
@ -402,6 +439,7 @@ make_header_line (const char *prefix, const char *suffix,
*p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
*p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077];
*p++ = bintoasc[s[2]&077];
*p = 0;
}
if ( len == 2 )
{
@ -417,6 +455,7 @@ make_header_line (const char *prefix, const char *suffix,
*p++ = '=';
*p++ = '=';
}
*p = 0;
strcpy (p, suffix);
return buffer;
}
@ -424,17 +463,132 @@ make_header_line (const char *prefix, const char *suffix,
/* Register the global TLS callback fucntion. */
void
http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int))
{
#ifdef HTTP_USE_GNUTLS
tls_callback = (gpg_error_t (*) (http_t, gnutls_session_t, int))cb;
#else
(void)cb;
#endif
tls_callback = cb;
}
/* Register a CA certificate for future use. The certificate is
expected to be in FNAME. PEM format is assume if FNAME has a
suffix of ".pem" */
void
http_register_tls_ca (const char *fname)
{
strlist_t sl;
sl = add_to_strlist (&tls_ca_certlist, fname);
if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
sl->flags = 1;
}
/* Create a new session object which is currently used to enable TLS
support. It may eventually allow reusing existing connections. */
gpg_error_t
http_session_new (http_session_t *r_session, const char *tls_priority)
{
gpg_error_t err;
http_session_t sess;
*r_session = NULL;
sess = xtrycalloc (1, sizeof *sess);
if (!sess)
return gpg_error_from_syserror ();
#ifdef HTTP_USE_GNUTLS
{
const char *errpos;
int rc;
strlist_t sl;
rc = gnutls_certificate_allocate_credentials (&sess->certcred);
if (rc < 0)
{
log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
gnutls_strerror (rc));
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
for (sl = tls_ca_certlist; sl; sl = sl->next)
{
rc = gnutls_certificate_set_x509_trust_file
(sess->certcred, sl->d,
(sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
if (rc < 0)
log_info ("setting CA from file '%s' failed: %s\n",
sl->d, gnutls_strerror (rc));
}
rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
if (rc < 0)
{
log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
rc = gnutls_priority_set_direct (sess->tls_session,
tls_priority? tls_priority : "NORMAL",
&errpos);
if (rc < 0)
{
log_error ("gnutls_priority_set_direct failed at '%s': %s\n",
errpos, gnutls_strerror (rc));
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
rc = gnutls_credentials_set (sess->tls_session,
GNUTLS_CRD_CERTIFICATE, sess->certcred);
if (rc < 0)
{
log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
}
#else /*!HTTP_USE_GNUTLS*/
(void)tls_priority;
#endif /*!HTTP_USE_GNUTLS*/
err = 0;
#ifdef HTTP_USE_GNUTLS
leave:
#endif /*HTTP_USE_GNUTLS*/
if (err)
http_session_release (sess);
else
*r_session = sess;
return err;
}
/* Release a session. Take care not to release it while it is beeing
used by a http contect object. */
void
http_session_release (http_session_t sess)
{
if (!sess)
return;
#ifdef HTTP_USE_GNUTLS
if (sess->tls_session)
gnutls_deinit (sess->tls_session);
if (sess->certcred)
gnutls_certificate_free_credentials (sess->certcred);
xfree (sess->servername);
#endif /*HTTP_USE_GNUTLS*/
xfree (sess);
}
/* Start a HTTP retrieval and return on success in R_HD a context
pointer for completing the the request and to wait for the
@ -442,7 +596,7 @@ http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
gpg_error_t
http_open (http_t *r_hd, http_req_t reqtype, const char *url,
const char *auth, unsigned int flags, const char *proxy,
void *tls_context, const char *srvtag, strlist_t headers)
http_session_t session, const char *srvtag, strlist_t headers)
{
gpg_error_t err;
http_t hd;
@ -458,7 +612,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
return gpg_error_from_syserror ();
hd->req_type = reqtype;
hd->flags = flags;
hd->tls_context = tls_context;
hd->session = session;
err = http_parse_uri (&hd->uri, url, 0);
if (!err)
@ -466,7 +620,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
if (err)
{
my_socket_unref (hd->sock);
my_socket_unref (hd->sock, NULL, NULL);
if (hd->fp_read)
es_fclose (hd->fp_read);
if (hd->fp_write)
@ -531,7 +685,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
if (!hd->fp_write)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
my_socket_unref (cookie->sock);
my_socket_unref (cookie->sock, NULL, NULL);
xfree (cookie);
goto leave;
}
@ -548,7 +702,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
if (!hd->fp_read)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
my_socket_unref (cookie->sock);
my_socket_unref (cookie->sock, NULL, NULL);
xfree (cookie);
goto leave;
}
@ -567,7 +721,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
es_fclose (hd->fp_read);
if (hd->fp_write)
es_fclose (hd->fp_write);
my_socket_unref (hd->sock);
my_socket_unref (hd->sock, NULL, NULL);
xfree (hd);
}
else
@ -624,15 +778,15 @@ http_wait_response (http_t hd)
if (!cookie)
return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
cookie->sock = my_socket_ref (hd->sock);
if (hd->uri->use_tls)
cookie->tls_session = hd->tls_context;
cookie->session = hd->session;
cookie->use_tls = hd->uri->use_tls;
hd->read_cookie = cookie;
hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
if (!hd->fp_read)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
my_socket_unref (cookie->sock);
my_socket_unref (cookie->sock, NULL, NULL);
xfree (cookie);
hd->read_cookie = NULL;
return err;
@ -654,12 +808,13 @@ http_wait_response (http_t hd)
gpg_error_t
http_open_document (http_t *r_hd, const char *document,
const char *auth, unsigned int flags, const char *proxy,
void *tls_context, const char *srvtag, strlist_t headers)
http_session_t session,
const char *srvtag, strlist_t headers)
{
gpg_error_t err;
err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
proxy, tls_context, srvtag, headers);
proxy, session, srvtag, headers);
if (err)
return err;
@ -684,7 +839,7 @@ http_close (http_t hd, int keep_read_stream)
es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
/* Now we can close the streams. */
my_socket_unref (hd->sock);
my_socket_unref (hd->sock, NULL, NULL);
if (hd->fp_read && !keep_read_stream)
es_fclose (hd->fp_read);
if (hd->fp_write)
@ -962,16 +1117,41 @@ remove_escapes (char *string)
}
/* If SPECIAL is NULL this function escapes in forms mode. */
static size_t
escape_data (char *buffer, const void *data, size_t datalen,
const char *special)
{
int forms = !special;
const unsigned char *s;
size_t n = 0;
if (forms)
special = "%;?&=";
for (s = data; datalen; s++, datalen--)
{
if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
if (forms && *s == ' ')
{
if (buffer)
*buffer++ = '+';
n++;
}
else if (forms && *s == '\n')
{
if (buffer)
memcpy (buffer, "%0D%0A", 6);
n += 6;
}
else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
{
if (buffer)
memcpy (buffer, "%0D%0A", 6);
n += 6;
s++;
datalen--;
}
else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
{
if (buffer)
*(unsigned char*)buffer++ = *s;
@ -1003,7 +1183,8 @@ insert_escapes (char *buffer, const char *string,
well as escaping of characters given in SPECIALS. A common pattern
for SPECIALS is "%;?&=". However it depends on the needs, for
example "+" and "/: often needs to be escaped too. Returns NULL on
failure and sets ERRNO. */
failure and sets ERRNO. If SPECIAL is NULL a dedicated forms
encoding mode is used. */
char *
http_escape_string (const char *string, const char *specials)
{
@ -1024,7 +1205,8 @@ http_escape_string (const char *string, const char *specials)
escaping as well as escaping of characters given in SPECIALS. A
common pattern for SPECIALS is "%;?&=". However it depends on the
needs, for example "+" and "/: often needs to be escaped too.
Returns NULL on failure and sets ERRNO. */
Returns NULL on failure and sets ERRNO. If SPECIAL is NULL a
dedicated forms encoding mode is used. */
char *
http_escape_data (const void *data, size_t datalen, const char *specials)
{
@ -1042,7 +1224,6 @@ http_escape_data (const void *data, size_t datalen, const char *specials)
}
static uri_tuple_t
parse_tuple (char *string)
{
@ -1089,7 +1270,6 @@ static gpg_error_t
send_request (http_t hd, const char *auth,
const char *proxy, const char *srvtag, strlist_t headers)
{
gnutls_session_t tls_session;
gpg_error_t err;
const char *server;
char *request, *p;
@ -1100,16 +1280,44 @@ send_request (http_t hd, const char *auth,
int sock;
int hnf;
tls_session = hd->tls_context;
if (hd->uri->use_tls && !tls_session)
if (hd->uri->use_tls && !hd->session)
{
log_error ("TLS requested but no GNUTLS context provided\n");
log_error ("TLS requested but no session object provided\n");
return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
}
#ifdef HTTP_USE_GNUTLS
if (hd->uri->use_tls && !hd->session->tls_session)
{
log_error ("TLS requested but no GNUTLS context available\n");
return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
}
#endif /*HTTP_USE_GNUTLS*/
server = *hd->uri->host ? hd->uri->host : "localhost";
port = hd->uri->port ? hd->uri->port : 80;
/* Try to use SNI. */
#ifdef HTTP_USE_GNUTLS
if (hd->uri->use_tls)
{
int rc;
xfree (hd->session->servername);
hd->session->servername = xtrystrdup (server);
if (!hd->session->servername)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
return err;
}
rc = gnutls_server_name_set (hd->session->tls_session,
GNUTLS_NAME_DNS,
server, strlen (server));
if (rc < 0)
log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
}
#endif /*HTTP_USE_GNUTLS*/
if ( (proxy && *proxy)
|| ( (hd->flags & HTTP_FLAG_TRY_PROXY)
&& (http_proxy = getenv (HTTP_PROXY_ENV))
@ -1179,11 +1387,22 @@ send_request (http_t hd, const char *auth,
int rc;
my_socket_ref (hd->sock);
gnutls_transport_set_ptr (tls_session,
#if GNUTLS_VERSION_NUMBER >= 0x030109
gnutls_transport_set_int (hd->session->tls_session, hd->sock->fd);
#else
gnutls_transport_set_ptr (hd->session->tls_session,
(gnutls_transport_ptr_t)(hd->sock->fd));
#endif
#ifdef USE_NPTH
gnutls_transport_set_pull_function (hd->session->tls_session,
my_npth_read);
gnutls_transport_set_push_function (hd->session->tls_session,
my_npth_write);
#endif
do
{
rc = gnutls_handshake (tls_session);
rc = gnutls_handshake (hd->session->tls_session);
}
while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
if (rc < 0)
@ -1195,7 +1414,8 @@ send_request (http_t hd, const char *auth,
if (tls_callback)
{
err = tls_callback (hd, tls_session, 0);
hd->session->verify.done = 0;
err = tls_callback (hd, hd->session, 0);
if (err)
{
log_info ("TLS connection authentication failed: %s\n",
@ -1227,7 +1447,7 @@ send_request (http_t hd, const char *auth,
myauth = hd->uri->auth;
}
authstr = make_header_line ("Authorization: Basic %s", "\r\n",
authstr = make_header_line ("Authorization: Basic ", "\r\n",
myauth, strlen (myauth));
if (auth)
xfree (myauth);
@ -1281,6 +1501,7 @@ send_request (http_t hd, const char *auth,
return err;
}
/* log_debug ("request:\n%s\nEND request\n", request); */
/* First setup estream so that we can write even the first line
using estream. This is also required for the sake of gnutls. */
@ -1295,14 +1516,14 @@ send_request (http_t hd, const char *auth,
}
cookie->sock = my_socket_ref (hd->sock);
hd->write_cookie = cookie;
if (hd->uri->use_tls)
cookie->tls_session = tls_session;
cookie->use_tls = hd->uri->use_tls;
cookie->session = hd->session;
hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
if (!hd->fp_write)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
my_socket_unref (cookie->sock);
my_socket_unref (cookie->sock, NULL, NULL);
xfree (cookie);
hd->write_cookie = NULL;
}
@ -1491,8 +1712,8 @@ store_header (http_t hd, char *line)
/* Return the header NAME from the last response. The returned value
is valid as along as HD has not been closed and no othe request has
been send. If the header was not found, NULL is returned. Name
is valid as along as HD has not been closed and no other request
has been send. If the header was not found, NULL is returned. NAME
must be canonicalized, that is the first letter of each dash
delimited part must be uppercase and all other letters lowercase. */
const char *
@ -1507,6 +1728,29 @@ http_get_header (http_t hd, const char *name)
}
/* Return a newly allocated and NULL terminated array with pointers to
header names. The array must be released with xfree() and its
content is only values as long as no other request has been
send. */
const char **
http_get_header_names (http_t hd)
{
const char **array;
size_t n;
header_t h;
for (n=0, h = hd->headers; h; h = h->next)
n++;
array = xtrycalloc (n+1, sizeof *array);
if (array)
{
for (n=0, h = hd->headers; h; h = h->next)
array[n++] = h->name;
}
return array;
}
/*
* Parse the response from a server.
@ -1960,10 +2204,10 @@ cookie_read (void *cookie, void *buffer, size_t size)
}
#ifdef HTTP_USE_GNUTLS
if (c->tls_session)
if (c->use_tls && c->session && c->session->tls_session)
{
again:
nread = gnutls_record_recv (c->tls_session, buffer, size);
nread = gnutls_record_recv (c->session->tls_session, buffer, size);
if (nread < 0)
{
if (nread == GNUTLS_E_INTERRUPTED)
@ -2014,18 +2258,20 @@ cookie_read (void *cookie, void *buffer, size_t size)
/* Write handler for estream. */
static ssize_t
cookie_write (void *cookie, const void *buffer, size_t size)
cookie_write (void *cookie, const void *buffer_arg, size_t size)
{
const char *buffer = buffer_arg;
cookie_t c = cookie;
int nwritten = 0;
#ifdef HTTP_USE_GNUTLS
if (c->tls_session)
if (c->use_tls && c->session && c->session->tls_session)
{
int nleft = size;
while (nleft > 0)
{
nwritten = gnutls_record_send (c->tls_session, buffer, nleft);
nwritten = gnutls_record_send (c->session->tls_session,
buffer, nleft);
if (nwritten <= 0)
{
if (nwritten == GNUTLS_E_INTERRUPTED)
@ -2063,6 +2309,18 @@ cookie_write (void *cookie, const void *buffer, size_t size)
return nwritten;
}
#ifdef HTTP_USE_GNUTLS
/* Wrapper for gnutls_bye used by my_socket_unref. */
static void
send_gnutls_bye (void *opaque)
{
gnutls_session_t tls_session = opaque;
gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
}
#endif /*HTTP_USE_GNUTLS*/
/* Close handler for estream. */
static int
cookie_close (void *cookie)
@ -2073,182 +2331,117 @@ cookie_close (void *cookie)
return 0;
#ifdef HTTP_USE_GNUTLS
if (c->tls_session && !c->keep_socket)
{
gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR);
my_socket_unref (c->sock);
}
if (c->use_tls && c->session && c->session->tls_session)
my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
else
#endif /*HTTP_USE_GNUTLS*/
if (c->sock && !c->keep_socket)
my_socket_unref (c->sock);
if (c->sock)
my_socket_unref (c->sock, NULL, NULL);
xfree (c);
return 0;
}
/**** Test code ****/
#ifdef TEST
/* Verify the credentials of the server. Returns 0 on success and
store the result in the session object. */
gpg_error_t
http_verify_server_credentials (http_session_t sess)
{
#ifdef HTTP_USE_GNUTLS
static gpg_error_t
verify_callback (http_t hd, void *tls_context, int reserved)
{
log_info ("verification of certificates skipped\n");
return 0;
}
#endif /*HTTP_USE_GNUTLS*/
/* static void */
/* my_gnutls_log (int level, const char *text) */
/* { */
/* fprintf (stderr, "gnutls:L%d: %s", level, text); */
/* } */
int
main (int argc, char **argv)
{
static const char const errprefix[] = "TLS verification of peer failed";
int rc;
parsed_uri_t uri;
uri_tuple_t r;
http_t hd;
int c;
gnutls_session_t tls_session = NULL;
#ifdef HTTP_USE_GNUTLS
gnutls_certificate_credentials certcred;
const int certprio[] = { GNUTLS_CRT_X509, 0 };
#endif /*HTTP_USE_GNUTLS*/
header_t hdr;
unsigned int status;
const char *hostname;
const gnutls_datum_t *certlist;
unsigned int certlistlen;
gnutls_x509_crt_t cert;
es_init ();
log_set_prefix ("http-test", 1 | 4);
if (argc == 1)
sess->verify.done = 1;
sess->verify.status = 0;
sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
{
/*start_server (); */
return 0;
log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
return gpg_error (GPG_ERR_GENERAL);
}
if (argc != 2)
{
fprintf (stderr, "usage: http-test uri\n");
return 1;
}
argc--;
argv++;
#ifdef HTTP_USE_GNUTLS
rc = gnutls_global_init ();
if (rc)
log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
rc = gnutls_certificate_allocate_credentials (&certcred);
if (rc)
log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
gnutls_strerror (rc));
/* rc = gnutls_certificate_set_x509_trust_file */
/* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
/* if (rc) */
/* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
/* gnutls_strerror (rc)); */
rc = gnutls_init (&tls_session, GNUTLS_CLIENT);
if (rc)
log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
rc = gnutls_set_default_priority (tls_session);
if (rc)
log_error ("gnutls_set_default_priority failed: %s\n",
gnutls_strerror (rc));
rc = gnutls_certificate_type_set_priority (tls_session, certprio);
if (rc)
log_error ("gnutls_certificate_type_set_priority failed: %s\n",
gnutls_strerror (rc));
rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred);
if (rc)
log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
/* gnutls_global_set_log_function (my_gnutls_log); */
/* gnutls_global_set_log_level (4); */
http_register_tls_callback (verify_callback);
#endif /*HTTP_USE_GNUTLS*/
rc = http_parse_uri (&uri, *argv, 1);
rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
if (rc)
{
log_error ("'%s': %s\n", *argv, gpg_strerror (rc));
return 1;
log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
return gpg_error (GPG_ERR_GENERAL);
}
printf ("Scheme: %s\n", uri->scheme);
if (uri->opaque)
printf ("Value : %s\n", uri->path);
else
if (status)
{
printf ("Auth : %s\n", uri->auth? uri->auth:"[none]");
printf ("Host : %s\n", uri->host);
printf ("Port : %u\n", uri->port);
printf ("Path : %s\n", uri->path);
for (r = uri->params; r; r = r->next)
{
printf ("Params: %s", r->name);
if (!r->no_value)
{
printf ("=%s", r->value);
if (strlen (r->value) != r->valuelen)
printf (" [real length=%d]", (int) r->valuelen);
}
putchar ('\n');
}
for (r = uri->query; r; r = r->next)
{
printf ("Query : %s", r->name);
if (!r->no_value)
{
printf ("=%s", r->value);
if (strlen (r->value) != r->valuelen)
printf (" [real length=%d]", (int) r->valuelen);
}
putchar ('\n');
}
log_error ("%s: status=0x%04x\n", errprefix, status);
sess->verify.status = status;
return gpg_error (GPG_ERR_GENERAL);
}
http_release_parsed_uri (uri);
uri = NULL;
rc = http_open_document (&hd, *argv, NULL, 0, NULL, tls_session, NULL, NULL);
if (rc)
hostname = sess->servername;
if (!hostname || !strchr (hostname, '.'))
{
log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc));
return 1;
log_error ("%s: %s\n", errprefix, "hostname missing");
return gpg_error (GPG_ERR_GENERAL);
}
log_info ("open_http_document succeeded; status=%u\n",
http_get_status_code (hd));
for (hdr = hd->headers; hdr; hdr = hdr->next)
printf ("HDR: %s: %s\n", hdr->name, hdr->value);
switch (http_get_status_code (hd))
certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
if (!certlistlen)
{
case 200:
while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
putchar (c);
break;
case 301:
case 302:
printf ("Redirected to '%s'\n", http_get_header (hd, "Location"));
break;
log_error ("%s: %s\n", errprefix, "server did not send a certificate");
return gpg_error (GPG_ERR_GENERAL);
}
http_close (hd, 0);
#ifdef HTTP_USE_GNUTLS
gnutls_deinit (tls_session);
gnutls_certificate_free_credentials (certcred);
gnutls_global_deinit ();
#endif /*HTTP_USE_GNUTLS*/
/* log_debug ("Server sent %u certs\n", certlistlen); */
/* { */
/* int i; */
/* char fname[50]; */
/* FILE *fp; */
return 0;
/* for (i=0; i < certlistlen; i++) */
/* { */
/* snprintf (fname, sizeof fname, "xc_%d.der", i); */
/* fp = fopen (fname, "wb"); */
/* if (!fp) */
/* log_fatal ("Failed to create '%s'\n", fname); */
/* if (fwrite (certlist[i].data, certlist[i].size, 1, fp) != 1) */
/* log_fatal ("Error writing to '%s'\n", fname); */
/* fclose (fp); */
/* } */
/* } */
rc = gnutls_x509_crt_init (&cert);
if (rc < 0)
{
return gpg_error (GPG_ERR_GENERAL);
}
rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
if (rc < 0)
{
log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
gnutls_strerror (rc));
gnutls_x509_crt_deinit (cert);
return gpg_error (GPG_ERR_GENERAL);
}
if (!gnutls_x509_crt_check_hostname (cert, hostname))
{
log_error ("%s: %s\n", errprefix, "hostname does not match");
gnutls_x509_crt_deinit (cert);
return gpg_error (GPG_ERR_GENERAL);
}
gnutls_x509_crt_deinit (cert);
sess->verify.rc = 0;
return 0; /* Verification succeeded. */
#else /*!HTTP_USE_GNUTLS*/
(void)sess;
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
#endif
}
#endif /*TEST*/
/*
Local Variables:
compile-command: "gcc -I.. -I../gl -DTEST -DHAVE_CONFIG_H -Wall -O2 -g -o http-test http.c -L. -lcommon -lgcrypt -lpth -lgnutls"
End:
*/

View File

@ -82,10 +82,20 @@ enum
HTTP_FLAG_IGNORE_IPv6 = 128 /* Do not use IPv6. */
};
struct http_session_s;
typedef struct http_session_s *http_session_t;
struct http_context_s;
typedef struct http_context_s *http_t;
void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int));
void http_register_tls_callback (gpg_error_t (*cb)(http_t,http_session_t,int));
void http_register_tls_ca (const char *fname);
gpg_error_t http_session_new (http_session_t *r_session,
const char *tls_priority);
void http_session_release (http_session_t sess);
gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
int no_scheme_check);
@ -101,7 +111,7 @@ gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
const char *auth,
unsigned int flags,
const char *proxy,
void *tls_context,
http_session_t session,
const char *srvtag,
strlist_t headers);
@ -116,7 +126,7 @@ gpg_error_t http_open_document (http_t *r_hd,
const char *auth,
unsigned int flags,
const char *proxy,
void *tls_context,
http_session_t session,
const char *srvtag,
strlist_t headers);
@ -124,6 +134,8 @@ estream_t http_get_read_ptr (http_t hd);
estream_t http_get_write_ptr (http_t hd);
unsigned int http_get_status_code (http_t hd);
const char *http_get_header (http_t hd, const char *name);
const char **http_get_header_names (http_t hd);
gpg_error_t http_verify_server_credentials (http_session_t sess);
char *http_escape_string (const char *string, const char *specials);
char *http_escape_data (const void *data, size_t datalen, const char *specials);

269
common/t-http.c Normal file
View File

@ -0,0 +1,269 @@
/* t-http.c
* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
* 2011 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* 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 General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "util.h"
#include "logging.h"
#include "http.h"
#ifdef HTTP_USE_GNUTLS
# include <gnutls/gnutls.h> /* For init, logging, and deinit. */
#endif /*HTTP_USE_GNUTLS*/
/* static void */
/* read_dh_params (const char *fname) */
/* { */
/* gpg_error_t err; */
/* int rc; */
/* FILE *fp; */
/* struct stat st; */
/* char *buf; */
/* size_t buflen; */
/* gnutls_datum_t datum; */
/* fp = fopen (fname, "rb"); */
/* if (!fp) */
/* { */
/* err = gpg_error_from_syserror (); */
/* log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err)); */
/* } */
/* if (fstat (fileno(fp), &st)) */
/* { */
/* err = gpg_error_from_syserror (); */
/* log_fatal ("can't stat '%s': %s\n", fname, gpg_strerror (err)); */
/* } */
/* buflen = st.st_size; */
/* buf = xmalloc (buflen+1); */
/* if (fread (buf, buflen, 1, fp) != 1) */
/* { */
/* err = gpg_error_from_syserror (); */
/* log_fatal ("error reading '%s': %s\n", fname, gpg_strerror (err)); */
/* } */
/* fclose (fp); */
/* datum.size = buflen; */
/* datum.data = buf; */
/* rc = gnutls_dh_params_import_pkcs3 (dh_params, &datum, GNUTLS_X509_FMT_PEM); */
/* if (rc < 0) */
/* log_fatal ("gnutls_dh_param_import failed: %s\n", gnutls_strerror (rc)); */
/* xfree (buf); */
/* } */
static gpg_error_t
verify_callback (http_t hd, http_session_t session, int reserved)
{
(void)hd;
(void)reserved;
return http_verify_server_credentials (session);
}
static void
my_gnutls_log (int level, const char *text)
{
fprintf (stderr, "gnutls:L%d: %s", level, text);
}
/* Prepend FNAME with the srcdir environment variable's value and
return an allocated filename. */
static char *
prepend_srcdir (const char *fname)
{
static const char *srcdir;
char *result;
if (!srcdir && !(srcdir = getenv ("srcdir")))
srcdir = ".";
result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
strcpy (result, srcdir);
strcat (result, "/");
strcat (result, fname);
return result;
}
int
main (int argc, char **argv)
{
gpg_error_t err;
int rc;
parsed_uri_t uri;
uri_tuple_t r;
http_t hd;
int c;
http_session_t session = NULL;
es_init ();
log_set_prefix ("t-http", 1 | 4);
if (argc != 2)
{
fprintf (stderr, "usage: t-http uri\n");
return 1;
}
argc--;
argv++;
#ifdef HTTP_USE_GNUTLS
rc = gnutls_global_init ();
if (rc)
log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
http_register_tls_callback (verify_callback);
http_register_tls_ca (prepend_srcdir ("tls-ca.pem"));
err = http_session_new (&session, NULL);
if (err)
log_error ("http_session_new failed: %s\n", gpg_strerror (err));
/* rc = gnutls_dh_params_init(&dh_params); */
/* if (rc) */
/* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */
/* read_dh_params ("dh_param.pem"); */
/* rc = gnutls_certificate_set_x509_trust_file */
/* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
/* if (rc) */
/* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
/* gnutls_strerror (rc)); */
/* gnutls_certificate_set_dh_params (certcred, dh_params); */
gnutls_global_set_log_function (my_gnutls_log);
/* gnutls_global_set_log_level (2); */
#endif /*HTTP_USE_GNUTLS*/
rc = http_parse_uri (&uri, *argv, 1);
if (rc)
{
log_error ("'%s': %s\n", *argv, gpg_strerror (rc));
return 1;
}
printf ("Scheme: %s\n", uri->scheme);
if (uri->opaque)
printf ("Value : %s\n", uri->path);
else
{
printf ("Auth : %s\n", uri->auth? uri->auth:"[none]");
printf ("Host : %s\n", uri->host);
printf ("Port : %u\n", uri->port);
printf ("Path : %s\n", uri->path);
for (r = uri->params; r; r = r->next)
{
printf ("Params: %s", r->name);
if (!r->no_value)
{
printf ("=%s", r->value);
if (strlen (r->value) != r->valuelen)
printf (" [real length=%d]", (int) r->valuelen);
}
putchar ('\n');
}
for (r = uri->query; r; r = r->next)
{
printf ("Query : %s", r->name);
if (!r->no_value)
{
printf ("=%s", r->value);
if (strlen (r->value) != r->valuelen)
printf (" [real length=%d]", (int) r->valuelen);
}
putchar ('\n');
}
}
http_release_parsed_uri (uri);
uri = NULL;
rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL);
if (rc)
{
log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc));
return 1;
}
log_info ("open_http_document succeeded; status=%u\n",
http_get_status_code (hd));
{
const char **names;
int i;
names = http_get_header_names (hd);
if (!names)
log_fatal ("http_get_header_names failed: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
for (i = 0; names[i]; i++)
printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i]));
xfree (names);
}
switch (http_get_status_code (hd))
{
case 200:
case 400:
case 401:
case 403:
case 404:
while ((c = es_getc (http_get_read_ptr (hd))) != EOF)
putchar (c);
break;
case 301:
case 302:
printf ("Redirected to '%s'\n", http_get_header (hd, "Location"));
break;
}
http_close (hd, 0);
http_session_release (session);
#ifdef HTTP_USE_GNUTLS
gnutls_global_deinit ();
#endif /*HTTP_USE_GNUTLS*/
return 0;
}

30
common/tls-ca.pem Normal file
View File

@ -0,0 +1,30 @@
Issuer ...: /CN=UTN-USERFirst-Hardware/OU=http:\x2f\x2fwww.usertrust.com/O=The USERTRUST Network/L=Salt Lake City/ST=UT/C=US
Serial ...: 44BE0C8B500024B411D3362AFE650AFD
Subject ..: /CN=UTN-USERFirst-Hardware/OU=http:\x2f\x2fwww.usertrust.com/O=The USERTRUST Network/L=Salt Lake City/ST=UT/C=US
-----BEGIN CERTIFICATE-----
MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
-----END CERTIFICATE-----

View File

@ -58,6 +58,8 @@ NEED_KSBA_VERSION=1.2.0
NEED_NPTH_API=1
NEED_NPTH_VERSION=0.91
NEED_GNUTLS_VERSION=3.0
development_version=mym4_isgit
PACKAGE=$PACKAGE_NAME
@ -912,6 +914,26 @@ else
***]])
fi
#
# Check whether GNUTLS is available
#
PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= $NEED_GNUTLS_VERSION],
[have_gnutls=yes],
[have_gnutls=no])
if test "$have_gnutls" = "yes"; then
AC_SUBST([LIBGNUTLS_CFLAGS])
AC_SUBST([LIBGNUTLS_LIBS])
AC_DEFINE(HTTP_USE_GNUTLS, 1, [Enable GNUTLS support in http.c])
else
tmp=$(echo "$LIBGNUTLS_PKG_ERRORS" | tr '\n' '\v' | sed 's/\v/\n*** /g')
AC_MSG_WARN([[
***
*** Building without GNUTLS - no TLS access to keyservers.
***
*** $tmp]])
fi
AC_MSG_NOTICE([checking for networking options])
@ -1867,6 +1889,8 @@ echo "
Use standard socket: $use_standard_socket
Dirmngr auto start: $dirmngr_auto_start
Readline support: $gnupg_cv_have_readline
DNS SRV support: $use_dns_srv
TLS support: $have_gnutls
"
if test x"$use_regex" != xyes ; then
echo "

View File

@ -60,8 +60,10 @@ dirmngr_SOURCES += ldap-wrapper-ce.c dirmngr_ldap.c
endif
dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) $(LIBINTL) $(LIBICONV)
dirmngr_LDADD = $(libcommontlsnpth) $(libcommonpth) \
../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) \
$(LIBGNUTLS_LIBS) $(LIBINTL) $(LIBICONV)
if !USE_LDAPWRAPPER
dirmngr_LDADD += $(LDAPLIBS)
endif
@ -79,8 +81,7 @@ endif
dirmngr_client_SOURCES = dirmngr-client.c
dirmngr_client_LDADD = $(libcommon) no-libgcrypt.o \
../gl/libgnu.a $(LIBASSUAN_LIBS) \
$(GPG_ERROR_LIBS) $(LIBINTL) \
$(LIBICONV)
$(GPG_ERROR_LIBS) $(NETLIBS) $(LIBINTL) $(LIBICONV)
dirmngr_client_LDFLAGS = $(extra_bin_ldflags)