From a42bf00b4edce789999aa3bdfce235cf726463ae Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 23 Feb 2017 10:30:58 +0100 Subject: [PATCH] dirmngr,w32: Make https with ntbtls work. * dirmngr/http.c (simple_cookie_functions): New. (send_request) [HTTP_USE_NTBTLS, W32]: Use es_fopencookie. (cookie_read): Factor some code out to ... (read_server): new. (simple_cookie_read, simple_cookie_write) [W32]: New. Signed-off-by: Werner Koch --- dirmngr/http.c | 127 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 27 deletions(-) diff --git a/dirmngr/http.c b/dirmngr/http.c index f4b40a8bc..e5e36b23f 100644 --- a/dirmngr/http.c +++ b/dirmngr/http.c @@ -158,13 +158,19 @@ static gpg_error_t parse_response (http_t hd); static gpg_error_t connect_server (const char *server, unsigned short port, unsigned int flags, const char *srvtag, assuan_fd_t *r_sock); +static gpgrt_ssize_t read_server (int sock, void *buffer, size_t size); static gpg_error_t write_server (int sock, const char *data, size_t length); static gpgrt_ssize_t cookie_read (void *cookie, void *buffer, size_t size); static gpgrt_ssize_t cookie_write (void *cookie, const void *buffer, size_t size); static int cookie_close (void *cookie); - +#ifdef HAVE_W32_SYSTEM +static gpgrt_ssize_t simple_cookie_read (void *cookie, + void *buffer, size_t size); +static gpgrt_ssize_t simple_cookie_write (void *cookie, + const void *buffer, size_t size); +#endif /* A socket object used to a allow ref counting of sockets. */ struct my_socket_s @@ -184,6 +190,7 @@ static es_cookie_io_functions_t cookie_functions = cookie_close }; + struct cookie_s { /* Socket object or NULL if already closed. */ @@ -203,6 +210,19 @@ struct cookie_s typedef struct cookie_s *cookie_t; +/* Simple cookie functions. Here the cookie is an int with the + * socket. */ +#ifdef HAVE_W32_SYSTEM +static es_cookie_io_functions_t simple_cookie_functions = + { + simple_cookie_read, + simple_cookie_write, + NULL, + NULL + }; +#endif + + #if SIZEOF_UNSIGNED_LONG == 8 # define HTTP_SESSION_MAGIC 0x0068545470534553 /* "hTTpSES" */ #else @@ -362,7 +382,7 @@ _my_socket_new (int lnr, assuan_fd_t fd) so->refcount = 1; if (opt_debug) log_debug ("http.c:%d:socket_new: object %p for fd %d created\n", - lnr, so, so->fd); + lnr, (int)so, so->fd); return so; } #define my_socket_new(a) _my_socket_new (__LINE__, (a)) @@ -374,7 +394,7 @@ _my_socket_ref (int lnr, my_socket_t so) so->refcount++; if (opt_debug > 1) log_debug ("http.c:%d:socket_ref: object %p for fd %d refcount now %d\n", - lnr, so, so->fd, so->refcount); + lnr, (int)so, so->fd, so->refcount); return so; } #define my_socket_ref(a) _my_socket_ref (__LINE__,(a)) @@ -392,7 +412,7 @@ _my_socket_unref (int lnr, my_socket_t so, so->refcount--; if (opt_debug > 1) log_debug ("http.c:%d:socket_unref: object %p for fd %d ref now %d\n", - lnr, so, so->fd, so->refcount); + lnr, (int)so, so->fd, so->refcount); if (!so->refcount) { @@ -1768,7 +1788,14 @@ send_request (http_t hd, const char *httphost, const char *auth, my_socket_ref (hd->sock); + /* Until we support send/recv in estream under Windows we need + * to use es_fopencookie. */ +#ifdef HAVE_W32_SYSTEM + in = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "rb", + simple_cookie_functions); +#else in = es_fdopen_nc (hd->sock->fd, "rb"); +#endif if (!in) { err = gpg_error_from_syserror (); @@ -1776,7 +1803,12 @@ send_request (http_t hd, const char *httphost, const char *auth, return err; } +#ifdef HAVE_W32_SYSTEM + out = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "wb", + simple_cookie_functions); +#else out = es_fdopen_nc (hd->sock->fd, "wb"); +#endif if (!out) { err = gpg_error_from_syserror (); @@ -2651,6 +2683,41 @@ connect_server (const char *server, unsigned short port, } +/* Helper to read from a socket. This handles npth things and + * EINTR. */ +static gpgrt_ssize_t +read_server (int sock, void *buffer, size_t size) +{ + int nread; + + do + { +#ifdef HAVE_W32_SYSTEM + /* Under Windows we need to use recv for a socket. */ +# if defined(USE_NPTH) + npth_unprotect (); +# endif + nread = recv (sock, buffer, size, 0); +# if defined(USE_NPTH) + npth_protect (); +# endif + +#else /*!HAVE_W32_SYSTEM*/ + +# ifdef USE_NPTH + nread = npth_read (sock, buffer, size); +# else + nread = read (sock, buffer, size); +# endif + +#endif /*!HAVE_W32_SYSTEM*/ + } + while (nread == -1 && errno == EINTR); + + return nread; +} + + static gpg_error_t write_server (int sock, const char *data, size_t length) { @@ -2766,29 +2833,7 @@ cookie_read (void *cookie, void *buffer, size_t size) else #endif /*HTTP_USE_GNUTLS*/ { - do - { -#ifdef HAVE_W32_SYSTEM - /* Under Windows we need to use recv for a socket. */ -# if defined(USE_NPTH) - npth_unprotect (); -# endif - nread = recv (c->sock->fd, buffer, size, 0); -# if defined(USE_NPTH) - npth_protect (); -# endif - -#else /*!HAVE_W32_SYSTEM*/ - -# ifdef USE_NPTH - nread = npth_read (c->sock->fd, buffer, size); -# else - nread = read (c->sock->fd, buffer, size); -# endif - -#endif /*!HAVE_W32_SYSTEM*/ - } - while (nread == -1 && errno == EINTR); + nread = read_server (c->sock->fd, buffer, size); } if (c->content_length_valid && nread > 0) @@ -2870,6 +2915,34 @@ cookie_write (void *cookie, const void *buffer_arg, size_t size) } +#ifdef HAVE_W32_SYSTEM +static gpgrt_ssize_t +simple_cookie_read (void *cookie, void *buffer, size_t size) +{ + int sock = (int)(uintptr_t)cookie; + return read_server (sock, buffer, size); +} + +static gpgrt_ssize_t +simple_cookie_write (void *cookie, const void *buffer_arg, size_t size) +{ + int sock = (int)(uintptr_t)cookie; + const char *buffer = buffer_arg; + int nwritten; + + if (write_server (sock, buffer, size)) + { + gpg_err_set_errno (EIO); + nwritten = -1; + } + else + nwritten = size; + + return (gpgrt_ssize_t)nwritten; +} +#endif /*HAVE_W32_SYSTEM*/ + + #ifdef HTTP_USE_GNUTLS /* Wrapper for gnutls_bye used by my_socket_unref. */ static void