1 /* http.c  -  HTTP protocol handler
2  * Copyright (C) 1999, 2001-2004, 2006, 2009, 2010,
3  *               2011 Free Software Foundation, Inc.
4  * Copyright (C) 1999, 2001-2004, 2006, 2009, 2010, 2011, 2014 Werner Koch
5  * Copyright (C) 2015-2017, 2021 g10 Code GmbH
6  *
7  * This file is part of GnuPG.
8  *
9  * This file is free software; you can redistribute it and/or modify
10  * it under the terms of either
11  *
12  *   - the GNU Lesser General Public License as published by the Free
13  *     Software Foundation; either version 3 of the License, or (at
14  *     your option) any later version.
15  *
16  * or
17  *
18  *   - the GNU General Public License as published by the Free
19  *     Software Foundation; either version 2 of the License, or (at
20  *     your option) any later version.
21  *
22  * or both in parallel, as here.
23  *
24  * This file is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, see <https://www.gnu.org/licenses/>.
31  */
32 
33 /* Simple HTTP client implementation.  We try to keep the code as
34    self-contained as possible.  There are some constraints however:
35 
36   - estream is required.  We now require estream because it provides a
37     very useful and portable asprintf implementation and the fopencookie
38     function.
39   - stpcpy is required
40   - fixme: list other requirements.
41 
42   - Either HTTP_USE_NTBTLS or HTTP_USE_GNUTLS must be defined to select
43     which TLS library to use.
44 
45   - With HTTP_NO_WSASTARTUP the socket initialization is not done
46     under Windows.  This is useful if the socket layer has already
47     been initialized elsewhere.  This also avoids the installation of
48     an exit handler to cleanup the socket layer.
49 */
50 
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <stdarg.h>
57 #include <string.h>
58 #include <ctype.h>
59 #include <errno.h>
60 #include <unistd.h>
61 
62 #ifdef HAVE_W32_SYSTEM
63 # ifdef HAVE_WINSOCK2_H
64 #  include <winsock2.h>
65 # endif
66 # include <windows.h>
67 #else /*!HAVE_W32_SYSTEM*/
68 # include <sys/types.h>
69 # include <sys/socket.h>
70 # include <sys/time.h>
71 # include <time.h>
72 # include <fcntl.h>
73 # include <netinet/in.h>
74 # include <arpa/inet.h>
75 # include <netdb.h>
76 #endif /*!HAVE_W32_SYSTEM*/
77 
78 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
79 # undef USE_NPTH
80 #endif
81 
82 #ifdef USE_NPTH
83 # include <npth.h>
84 #endif
85 
86 #if defined (HTTP_USE_GNUTLS) && defined (HTTP_USE_NTBTLS)
87 # error Both, HTTP_USE_GNUTLS and HTTP_USE_NTBTLS, are defined.
88 #endif
89 
90 #ifdef HTTP_USE_NTBTLS
91 # include <ntbtls.h>
92 #elif HTTP_USE_GNUTLS
93 # include <gnutls/gnutls.h>
94 # include <gnutls/x509.h>
95 #endif /*HTTP_USE_GNUTLS*/
96 
97 #include <assuan.h>  /* We need the socket wrapper.  */
98 
99 #include "../common/util.h"
100 #include "../common/i18n.h"
101 #include "../common/sysutils.h" /* (gnupg_fd_t) */
102 #include "dns-stuff.h"
103 #include "dirmngr-status.h"    /* (dirmngr_status_printf)  */
104 #include "http.h"
105 #include "http-common.h"
106 
107 
108 #ifdef USE_NPTH
109 # define my_select(a,b,c,d,e)  npth_select ((a), (b), (c), (d), (e))
110 # define my_accept(a,b,c)      npth_accept ((a), (b), (c))
111 #else
112 # define my_select(a,b,c,d,e)  select ((a), (b), (c), (d), (e))
113 # define my_accept(a,b,c)      accept ((a), (b), (c))
114 #endif
115 
116 #ifdef HAVE_W32_SYSTEM
117 #define sock_close(a)  closesocket(a)
118 #else
119 #define sock_close(a)  close(a)
120 #endif
121 
122 #ifndef EAGAIN
123 #define EAGAIN  EWOULDBLOCK
124 #endif
125 #ifndef INADDR_NONE  /* Slowaris is missing that.  */
126 #define INADDR_NONE  ((unsigned long)(-1))
127 #endif /*INADDR_NONE*/
128 
129 #define HTTP_PROXY_ENV           "http_proxy"
130 #define MAX_LINELEN 20000  /* Max. length of a HTTP header line. */
131 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz"   \
132                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"   \
133                         "01234567890@"                 \
134                         "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
135 
136 #if HTTP_USE_NTBTLS
137 typedef ntbtls_t         tls_session_t;
138 #elif HTTP_USE_GNUTLS
139 typedef gnutls_session_t tls_session_t;
140 #else
141 # error building without TLS is not supported
142 #endif
143 
144 static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part,
145                                     int no_scheme_check, int force_tls);
146 static gpg_error_t parse_uri (parsed_uri_t *ret_uri, const char *uri,
147                               int no_scheme_check, int force_tls);
148 static int remove_escapes (char *string);
149 static int insert_escapes (char *buffer, const char *string,
150                            const char *special);
151 static uri_tuple_t parse_tuple (char *string);
152 static gpg_error_t send_request (ctrl_t ctrl, http_t hd, const char *httphost,
153                                  const char *auth,const char *proxy,
154 				 const char *srvtag, unsigned int timeout,
155                                  strlist_t headers);
156 static char *build_rel_path (parsed_uri_t uri);
157 static gpg_error_t parse_response (http_t hd);
158 
159 static gpg_error_t connect_server (ctrl_t ctrl,
160                                    const char *server, unsigned short port,
161                                    unsigned int flags, const char *srvtag,
162                                    unsigned int timeout, assuan_fd_t *r_sock);
163 static gpgrt_ssize_t read_server (assuan_fd_t sock, void *buffer, size_t size);
164 static gpg_error_t write_server (assuan_fd_t sock, const char *data, size_t length);
165 
166 static gpgrt_ssize_t cookie_read (void *cookie, void *buffer, size_t size);
167 static gpgrt_ssize_t cookie_write (void *cookie,
168                                    const void *buffer, size_t size);
169 static int cookie_close (void *cookie);
170 #if defined(HAVE_W32_SYSTEM) && defined(HTTP_USE_NTBTLS)
171 static gpgrt_ssize_t simple_cookie_read (void *cookie,
172                                          void *buffer, size_t size);
173 static gpgrt_ssize_t simple_cookie_write (void *cookie,
174                                           const void *buffer, size_t size);
175 #endif
176 
177 /* A socket object used to a allow ref counting of sockets.  */
178 struct my_socket_s
179 {
180   assuan_fd_t fd; /* The actual socket - shall never be ASSUAN_INVALID_FD.  */
181   int refcount;   /* Number of references to this socket.  */
182 };
183 typedef struct my_socket_s *my_socket_t;
184 
185 
186 /* Cookie function structure and cookie object.  */
187 static es_cookie_io_functions_t cookie_functions =
188   {
189     cookie_read,
190     cookie_write,
191     NULL,
192     cookie_close
193   };
194 
195 
196 struct cookie_s
197 {
198   /* Socket object or NULL if already closed. */
199   my_socket_t sock;
200 
201   /* The session object or NULL if not used. */
202   http_session_t session;
203 
204   /* True if TLS is to be used.  */
205   int use_tls;
206 
207   /* The remaining content length and a flag telling whether to use
208      the content length.  */
209   uint64_t content_length;
210   unsigned int content_length_valid:1;
211 };
212 typedef struct cookie_s *cookie_t;
213 
214 
215 /* Simple cookie functions.  Here the cookie is an int with the
216  * socket. */
217 #if defined(HAVE_W32_SYSTEM) && defined(HTTP_USE_NTBTLS)
218 static es_cookie_io_functions_t simple_cookie_functions =
219   {
220     simple_cookie_read,
221     simple_cookie_write,
222     NULL,
223     NULL
224   };
225 #endif
226 
227 
228 #if SIZEOF_UNSIGNED_LONG == 8
229 # define HTTP_SESSION_MAGIC 0x0068545470534553 /* "hTTpSES" */
230 #else
231 # define HTTP_SESSION_MAGIC 0x68547365         /* "hTse"    */
232 #endif
233 
234 /* The session object. */
235 struct http_session_s
236 {
237   unsigned long magic;
238 
239   int refcount;    /* Number of references to this object.  */
240 
241   tls_session_t tls_session;
242   struct {
243     int done;      /* Verifciation has been done.  */
244     int rc;        /* TLS verification return code.  */
245     unsigned int status; /* Verification status.  */
246   } verify;
247   char *servername; /* Malloced server name.  */
248 
249   /* A callback function to log details of TLS certifciates.  */
250   void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
251                        const void **, size_t *);
252 
253   /* The flags passed to the session object.  */
254   unsigned int flags;
255 
256   /* A per-session TLS verification callback.  */
257   http_verify_cb_t verify_cb;
258   void *verify_cb_value;
259 
260   /* The connect timeout */
261   unsigned int connect_timeout;
262 
263 #ifdef HTTP_USE_GNUTLS
264   gnutls_certificate_credentials_t certcred;
265 #endif /*HTTP_USE_GNUTLS*/
266 };
267 
268 
269 /* An object to save header lines. */
270 struct header_s
271 {
272   struct header_s *next;
273   char *value;    /* The value of the header (malloced).  */
274   char name[1];   /* The name of the header (canonicalized). */
275 };
276 typedef struct header_s *header_t;
277 
278 
279 #if SIZEOF_UNSIGNED_LONG == 8
280 # define HTTP_CONTEXT_MAGIC 0x0068545470435458 /* "hTTpCTX" */
281 #else
282 # define HTTP_CONTEXT_MAGIC 0x68546378         /* "hTcx"    */
283 #endif
284 
285 
286 /* Our handle context. */
287 struct http_context_s
288 {
289   unsigned long magic;
290   unsigned int status_code;
291   my_socket_t sock;
292   unsigned int in_data:1;
293   unsigned int is_http_0_9:1;
294   estream_t fp_read;
295   estream_t fp_write;
296   void *write_cookie;
297   void *read_cookie;
298   http_session_t session;
299   parsed_uri_t uri;
300   http_req_t req_type;
301   char *buffer;          /* Line buffer. */
302   size_t buffer_size;
303   unsigned int flags;
304   header_t headers;      /* Received headers. */
305 };
306 
307 
308 /* Two flags to enable verbose and debug mode.  Although currently not
309  * set-able a value > 1 for OPT_DEBUG enables debugging of the session
310  * reference counting.  */
311 static int opt_verbose;
312 static int opt_debug;
313 
314 /* The global callback for the verification function.  */
315 static gpg_error_t (*tls_callback) (http_t, http_session_t, int);
316 
317 /* The list of files with trusted CA certificates.  */
318 static strlist_t tls_ca_certlist;
319 
320 /* The list of files with extra trusted CA certificates.  */
321 static strlist_t cfg_ca_certlist;
322 
323 /* The global callback for net activity.  */
324 static void (*netactivity_cb)(void);
325 
326 
327 
328 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
329 
330 #if GNUPG_MAJOR_VERSION == 1
331 #define REQ_WINSOCK_MAJOR  1
332 #define REQ_WINSOCK_MINOR  1
333 #else
334 #define REQ_WINSOCK_MAJOR  2
335 #define REQ_WINSOCK_MINOR  2
336 #endif
337 
338 
339 static void
deinit_sockets(void)340 deinit_sockets (void)
341 {
342   WSACleanup();
343 }
344 
345 static void
init_sockets(void)346 init_sockets (void)
347 {
348   static int initialized;
349   static WSADATA wsdata;
350 
351   if (initialized)
352     return;
353 
354   if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) )
355     {
356       log_error ("error initializing socket library: ec=%d\n",
357                  (int)WSAGetLastError () );
358       return;
359     }
360   if ( LOBYTE(wsdata.wVersion) != REQ_WINSOCK_MAJOR
361        || HIBYTE(wsdata.wVersion) != REQ_WINSOCK_MINOR )
362     {
363       log_error ("socket library version is %x.%x - but %d.%d needed\n",
364                  LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion),
365                  REQ_WINSOCK_MAJOR, REQ_WINSOCK_MINOR);
366       WSACleanup();
367       return;
368     }
369   atexit ( deinit_sockets );
370   initialized = 1;
371 }
372 #endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/
373 
374 
375 /* Create a new socket object.  Returns NULL and closes FD if not
376    enough memory is available.  */
377 static my_socket_t
_my_socket_new(int lnr,assuan_fd_t fd)378 _my_socket_new (int lnr, assuan_fd_t fd)
379 {
380   my_socket_t so;
381 
382   so = xtrymalloc (sizeof *so);
383   if (!so)
384     {
385       int save_errno = errno;
386       assuan_sock_close (fd);
387       gpg_err_set_errno (save_errno);
388       return NULL;
389     }
390   so->fd = fd;
391   so->refcount = 1;
392   if (opt_debug)
393     log_debug ("http.c:%d:socket_new: object %p for fd %d created\n",
394                lnr, so, (int)so->fd);
395   return so;
396 }
397 #define my_socket_new(a) _my_socket_new (__LINE__, (a))
398 
399 /* Bump up the reference counter for the socket object SO.  */
400 static my_socket_t
_my_socket_ref(int lnr,my_socket_t so)401 _my_socket_ref (int lnr, my_socket_t so)
402 {
403   so->refcount++;
404   if (opt_debug > 1)
405     log_debug ("http.c:%d:socket_ref: object %p for fd %d refcount now %d\n",
406                lnr, so, (int)so->fd, so->refcount);
407   return so;
408 }
409 #define my_socket_ref(a) _my_socket_ref (__LINE__,(a))
410 
411 
412 /* Bump down the reference counter for the socket object SO.  If SO
413    has no more references, close the socket and release the
414    object.  */
415 static void
_my_socket_unref(int lnr,my_socket_t so,void (* preclose)(void *),void * preclosearg)416 _my_socket_unref (int lnr, my_socket_t so,
417                   void (*preclose)(void*), void *preclosearg)
418 {
419   if (so)
420     {
421       so->refcount--;
422       if (opt_debug > 1)
423         log_debug ("http.c:%d:socket_unref: object %p for fd %d ref now %d\n",
424                    lnr, so, (int)so->fd, so->refcount);
425 
426       if (!so->refcount)
427         {
428           if (preclose)
429             preclose (preclosearg);
430           assuan_sock_close (so->fd);
431           xfree (so);
432         }
433     }
434 }
435 #define my_socket_unref(a,b,c) _my_socket_unref (__LINE__,(a),(b),(c))
436 
437 
438 #ifdef HTTP_USE_GNUTLS
439 static ssize_t
my_gnutls_read(gnutls_transport_ptr_t ptr,void * buffer,size_t size)440 my_gnutls_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size)
441 {
442   my_socket_t sock = ptr;
443 #if USE_NPTH
444   return npth_read (sock->fd, buffer, size);
445 #else
446   return read (sock->fd, buffer, size);
447 #endif
448 }
449 static ssize_t
my_gnutls_write(gnutls_transport_ptr_t ptr,const void * buffer,size_t size)450 my_gnutls_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size)
451 {
452   my_socket_t sock = ptr;
453 #if USE_NPTH
454   return npth_write (sock->fd, buffer, size);
455 #else
456   return write (sock->fd, buffer, size);
457 #endif
458 }
459 #endif /*HTTP_USE_GNUTLS*/
460 
461 
462 #ifdef HTTP_USE_NTBTLS
463 /* Connect the ntbls callback to our generic callback.  */
464 static gpg_error_t
my_ntbtls_verify_cb(void * opaque,ntbtls_t tls,unsigned int verify_flags)465 my_ntbtls_verify_cb (void *opaque, ntbtls_t tls, unsigned int verify_flags)
466 {
467   http_t hd = opaque;
468 
469   (void)verify_flags;
470 
471   log_assert (hd && hd->session && hd->session->verify_cb);
472   log_assert (hd->magic == HTTP_CONTEXT_MAGIC);
473   log_assert (hd->session->magic == HTTP_SESSION_MAGIC);
474 
475   return hd->session->verify_cb (hd->session->verify_cb_value,
476                                  hd, hd->session,
477                                  (hd->flags | hd->session->flags),
478                                  tls);
479 }
480 #endif /*HTTP_USE_NTBTLS*/
481 
482 
483 
484 
485 /* This notification function is called by estream whenever stream is
486    closed.  Its purpose is to mark the closing in the handle so
487    that a http_close won't accidentally close the estream.  The function
488    http_close removes this notification so that it won't be called if
489    http_close was used before an es_fclose.  */
490 static void
fp_onclose_notification(estream_t stream,void * opaque)491 fp_onclose_notification (estream_t stream, void *opaque)
492 {
493   http_t hd = opaque;
494 
495   log_assert (hd->magic == HTTP_CONTEXT_MAGIC);
496   if (hd->fp_read && hd->fp_read == stream)
497     hd->fp_read = NULL;
498   else if (hd->fp_write && hd->fp_write == stream)
499     hd->fp_write = NULL;
500 }
501 
502 
503 /*
504  * Helper function to create an HTTP header with hex encoded data.  A
505  * new buffer is returned.  This buffer is the concatenation of the
506  * string PREFIX, the hex-encoded DATA of length LEN and the string
507  * SUFFIX.  On error NULL is returned and ERRNO set.
508  */
509 static char *
make_header_line(const char * prefix,const char * suffix,const void * data,size_t len)510 make_header_line (const char *prefix, const char *suffix,
511                   const void *data, size_t len )
512 {
513   static unsigned char bintoasc[] =
514     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
515     "abcdefghijklmnopqrstuvwxyz"
516     "0123456789+/";
517   const unsigned char *s = data;
518   char *buffer, *p;
519 
520   buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1);
521   if (!buffer)
522     return NULL;
523   p = stpcpy (buffer, prefix);
524   for ( ; len >= 3 ; len -= 3, s += 3 )
525     {
526       *p++ = bintoasc[(s[0] >> 2) & 077];
527       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
528       *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077];
529       *p++ = bintoasc[s[2]&077];
530       *p = 0;
531     }
532   if ( len == 2 )
533     {
534       *p++ = bintoasc[(s[0] >> 2) & 077];
535       *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077];
536       *p++ = bintoasc[((s[1]<<2)&074)];
537       *p++ = '=';
538     }
539   else if ( len == 1 )
540     {
541       *p++ = bintoasc[(s[0] >> 2) & 077];
542       *p++ = bintoasc[(s[0] <<4)&060];
543       *p++ = '=';
544       *p++ = '=';
545     }
546   *p = 0;
547   strcpy (p, suffix);
548   return buffer;
549 }
550 
551 
552 
553 
554 /* Set verbosity and debug mode for this module. */
555 void
http_set_verbose(int verbose,int debug)556 http_set_verbose (int verbose, int debug)
557 {
558   opt_verbose = verbose;
559   opt_debug = debug;
560 }
561 
562 
563 /* Register a non-standard global TLS callback function.  If no
564    verification is desired a callback needs to be registered which
565    always returns NULL.  */
566 void
http_register_tls_callback(gpg_error_t (* cb)(http_t,http_session_t,int))567 http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int))
568 {
569   tls_callback = cb;
570 }
571 
572 
573 /* Register a CA certificate for future use.  The certificate is
574    expected to be in FNAME.  PEM format is assume if FNAME has a
575    suffix of ".pem".  If FNAME is NULL the list of CA files is
576    removed.  */
577 void
http_register_tls_ca(const char * fname)578 http_register_tls_ca (const char *fname)
579 {
580   gpg_err_code_t ec;
581   strlist_t sl;
582 
583   if (!fname)
584     {
585       free_strlist (tls_ca_certlist);
586       tls_ca_certlist = NULL;
587     }
588   else
589     {
590       /* Warn if we can't access right now, but register it anyway in
591          case it becomes accessible later */
592       if ((ec = gnupg_access (fname, F_OK)))
593         log_info (_("can't access '%s': %s\n"), fname, gpg_strerror (ec));
594       sl = add_to_strlist (&tls_ca_certlist, fname);
595       if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
596         sl->flags = 1;
597     }
598 }
599 
600 
601 /* Register a CA certificate for future use.  The certificate is
602  * expected to be in FNAME.  PEM format is assume if FNAME has a
603  * suffix of ".pem".  If FNAME is NULL the list of CA files is
604  * removed.  This is a variant of http_register_tls_ca which puts the
605  * certificate into a separate list enabled using HTTP_FLAG_TRUST_CFG.  */
606 void
http_register_cfg_ca(const char * fname)607 http_register_cfg_ca (const char *fname)
608 {
609   gpg_err_code_t ec;
610   strlist_t sl;
611 
612   if (!fname)
613     {
614       free_strlist (cfg_ca_certlist);
615       cfg_ca_certlist = NULL;
616     }
617   else
618     {
619       /* Warn if we can't access right now, but register it anyway in
620          case it becomes accessible later */
621       if ((ec = gnupg_access (fname, F_OK)))
622         log_info (_("can't access '%s': %s\n"), fname, gpg_strerror (ec));
623       sl = add_to_strlist (&cfg_ca_certlist, fname);
624       if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem"))
625         sl->flags = 1;
626     }
627 }
628 
629 
630 /* Register a callback which is called every time the HTTP mode has
631  * made a successful connection to some server.  */
632 void
http_register_netactivity_cb(void (* cb)(void))633 http_register_netactivity_cb (void (*cb)(void))
634 {
635   netactivity_cb = cb;
636 }
637 
638 
639 /* Call the netactivity callback if any.  */
640 static void
notify_netactivity(void)641 notify_netactivity (void)
642 {
643   if (netactivity_cb)
644     netactivity_cb ();
645 }
646 
647 
648 
649 /* Free the TLS session associated with SESS, if any.  */
650 static void
close_tls_session(http_session_t sess)651 close_tls_session (http_session_t sess)
652 {
653   if (sess->tls_session)
654     {
655 #if HTTP_USE_NTBTLS
656       /* FIXME!!
657          Possibly, ntbtls_get_transport and close those streams.
658          Somehow get SOCK to call my_socket_unref.
659       */
660       ntbtls_release (sess->tls_session);
661 #elif HTTP_USE_GNUTLS
662       my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session);
663       my_socket_unref (sock, NULL, NULL);
664       gnutls_deinit (sess->tls_session);
665       if (sess->certcred)
666         gnutls_certificate_free_credentials (sess->certcred);
667 #endif /*HTTP_USE_GNUTLS*/
668       xfree (sess->servername);
669       sess->tls_session = NULL;
670     }
671 }
672 
673 
674 /* Release a session.  Take care not to release it while it is being
675    used by a http context object.  */
676 static void
session_unref(int lnr,http_session_t sess)677 session_unref (int lnr, http_session_t sess)
678 {
679   if (!sess)
680     return;
681 
682   log_assert (sess->magic == HTTP_SESSION_MAGIC);
683 
684   sess->refcount--;
685   if (opt_debug > 1)
686     log_debug ("http.c:%d:session_unref: sess %p ref now %d\n",
687                lnr, sess, sess->refcount);
688   if (sess->refcount)
689     return;
690 
691   close_tls_session (sess);
692 
693   sess->magic = 0xdeadbeef;
694   xfree (sess);
695 }
696 #define http_session_unref(a) session_unref (__LINE__, (a))
697 
698 
699 void
http_session_release(http_session_t sess)700 http_session_release (http_session_t sess)
701 {
702   http_session_unref (sess);
703 }
704 
705 
706 /* Create a new session object which is currently used to enable TLS
707  * support.  It may eventually allow reusing existing connections.
708  * Valid values for FLAGS are:
709  *   HTTP_FLAG_TRUST_DEF - Use the CAs set with http_register_tls_ca
710  *   HTTP_FLAG_TRUST_SYS - Also use the CAs defined by the system
711  *   HTTP_FLAG_TRUST_CFG - Also use CAs set with http_register_cfg_ca
712  *   HTTP_FLAG_NO_CRL    - Do not consult CRLs for https.
713  */
714 gpg_error_t
http_session_new(http_session_t * r_session,const char * intended_hostname,unsigned int flags,http_verify_cb_t verify_cb,void * verify_cb_value)715 http_session_new (http_session_t *r_session,
716                   const char *intended_hostname, unsigned int flags,
717                   http_verify_cb_t verify_cb, void *verify_cb_value)
718 {
719   gpg_error_t err;
720   http_session_t sess;
721 
722   *r_session = NULL;
723 
724   sess = xtrycalloc (1, sizeof *sess);
725   if (!sess)
726     return gpg_error_from_syserror ();
727   sess->magic = HTTP_SESSION_MAGIC;
728   sess->refcount = 1;
729   sess->flags = flags;
730   sess->verify_cb = verify_cb;
731   sess->verify_cb_value = verify_cb_value;
732   sess->connect_timeout = 0;
733 
734 #if HTTP_USE_NTBTLS
735   {
736     (void)intended_hostname; /* Not needed because we do not preload
737                               * certificates.  */
738 
739     err = ntbtls_new (&sess->tls_session, NTBTLS_CLIENT);
740     if (err)
741       {
742         log_error ("ntbtls_new failed: %s\n", gpg_strerror (err));
743         goto leave;
744       }
745 
746   }
747 #elif HTTP_USE_GNUTLS
748   {
749     const char *errpos;
750     int rc;
751     strlist_t sl;
752     int add_system_cas = !!(flags & HTTP_FLAG_TRUST_SYS);
753     int is_hkps_pool;
754 
755     rc = gnutls_certificate_allocate_credentials (&sess->certcred);
756     if (rc < 0)
757       {
758         log_error ("gnutls_certificate_allocate_credentials failed: %s\n",
759                    gnutls_strerror (rc));
760         err = gpg_error (GPG_ERR_GENERAL);
761         goto leave;
762       }
763 
764     /* Disabled for 2.3.2 to due problems with the standard hkps pool.  */
765     /* is_hkps_pool = (intended_hostname */
766     /*                 && !ascii_strcasecmp (intended_hostname, */
767     /*                                       get_default_keyserver (1))); */
768     is_hkps_pool = 0;
769 
770     /* If we are looking for the hkps pool from sks-keyservers.net,
771      * then forcefully use its dedicated certificate authority.  */
772     /* Disabled for 2.3.2 because the service had to be shutdown.  */
773     /* if (is_hkps_pool) */
774     /*   { */
775     /*     char *pemname = make_filename_try (gnupg_datadir (), */
776     /*                                        "sks-keyservers.netCA.pem", NULL); */
777     /*     if (!pemname) */
778     /*       { */
779     /*         err = gpg_error_from_syserror (); */
780     /*         log_error ("setting CA from file '%s' failed: %s\n", */
781     /*                    pemname, gpg_strerror (err)); */
782     /*       } */
783     /*     else */
784     /*       { */
785     /*         rc = gnutls_certificate_set_x509_trust_file */
786     /*           (sess->certcred, pemname, GNUTLS_X509_FMT_PEM); */
787     /*         if (rc < 0) */
788     /*           log_info ("setting CA from file '%s' failed: %s\n", */
789     /*                     pemname, gnutls_strerror (rc)); */
790     /*         xfree (pemname); */
791     /*       } */
792     /*         */
793     /*     if (is_hkps_pool) */
794     /*       add_system_cas = 0; */
795     /*   } */
796 
797     /* Add configured certificates to the session.  */
798     if ((flags & HTTP_FLAG_TRUST_DEF) && !is_hkps_pool)
799       {
800         for (sl = tls_ca_certlist; sl; sl = sl->next)
801           {
802             rc = gnutls_certificate_set_x509_trust_file
803               (sess->certcred, sl->d,
804                (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
805             if (rc < 0)
806               log_info ("setting CA from file '%s' failed: %s\n",
807                         sl->d, gnutls_strerror (rc));
808           }
809 
810         /* If HKP trust is requested and there are no HKP certificates
811          * configured, also try the standard system certificates.  */
812         if (!tls_ca_certlist)
813           add_system_cas = 1;
814       }
815 
816     /* Add system certificates to the session.  */
817     if (add_system_cas)
818       {
819 #if GNUTLS_VERSION_NUMBER >= 0x030014
820         static int shown;
821 
822         rc = gnutls_certificate_set_x509_system_trust (sess->certcred);
823         if (rc < 0)
824           log_info ("setting system CAs failed: %s\n", gnutls_strerror (rc));
825         else if (!shown)
826           {
827             shown = 1;
828             log_info ("number of system provided CAs: %d\n", rc);
829           }
830 #endif /* gnutls >= 3.0.20 */
831       }
832 
833     /* Add other configured certificates to the session.  */
834     if ((flags & HTTP_FLAG_TRUST_CFG) && !is_hkps_pool)
835       {
836         for (sl = cfg_ca_certlist; sl; sl = sl->next)
837           {
838             rc = gnutls_certificate_set_x509_trust_file
839               (sess->certcred, sl->d,
840                (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER);
841             if (rc < 0)
842               log_info ("setting extra CA from file '%s' failed: %s\n",
843                         sl->d, gnutls_strerror (rc));
844           }
845       }
846 
847 
848     rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT);
849     if (rc < 0)
850       {
851         log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc));
852         err = gpg_error (GPG_ERR_GENERAL);
853         goto leave;
854       }
855     /* A new session has the transport ptr set to (void*(-1), we need
856        it to be NULL.  */
857     gnutls_transport_set_ptr (sess->tls_session, NULL);
858 
859     rc = gnutls_priority_set_direct (sess->tls_session,
860                                      "NORMAL",
861                                      &errpos);
862     if (rc < 0)
863       {
864         log_error ("gnutls_priority_set_direct failed at '%s': %s\n",
865                    errpos, gnutls_strerror (rc));
866         err = gpg_error (GPG_ERR_GENERAL);
867         goto leave;
868       }
869 
870     rc = gnutls_credentials_set (sess->tls_session,
871                                  GNUTLS_CRD_CERTIFICATE, sess->certcred);
872     if (rc < 0)
873       {
874         log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc));
875         err = gpg_error (GPG_ERR_GENERAL);
876         goto leave;
877       }
878   }
879 #else /*!HTTP_USE_GNUTLS && !HTTP_USE_NTBTLS*/
880   {
881     (void)intended_hostname;
882     (void)flags;
883   }
884 #endif /*!HTTP_USE_GNUTLS && !HTTP_USE_NTBTLS*/
885 
886   if (opt_debug > 1)
887     log_debug ("http.c:session_new: sess %p created\n", sess);
888   err = 0;
889 
890  leave:
891   if (err)
892     http_session_unref (sess);
893   else
894     *r_session = sess;
895 
896   return err;
897 }
898 
899 
900 /* Increment the reference count for session SESS.  Passing NULL for
901    SESS is allowed. */
902 http_session_t
http_session_ref(http_session_t sess)903 http_session_ref (http_session_t sess)
904 {
905   if (sess)
906     {
907       sess->refcount++;
908       if (opt_debug > 1)
909         log_debug ("http.c:session_ref: sess %p ref now %d\n",
910                    sess, sess->refcount);
911     }
912   return sess;
913 }
914 
915 
916 void
http_session_set_log_cb(http_session_t sess,void (* cb)(http_session_t,gpg_error_t,const char * hostname,const void ** certs,size_t * certlens))917 http_session_set_log_cb (http_session_t sess,
918                          void (*cb)(http_session_t, gpg_error_t,
919                                     const char *hostname,
920                                     const void **certs, size_t *certlens))
921 {
922   sess->cert_log_cb = cb;
923 }
924 
925 
926 /* Set the TIMEOUT in milliseconds for the connection's connect
927  * calls.  Using 0 disables the timeout.  */
928 void
http_session_set_timeout(http_session_t sess,unsigned int timeout)929 http_session_set_timeout (http_session_t sess, unsigned int timeout)
930 {
931   sess->connect_timeout = timeout;
932 }
933 
934 
935 
936 
937 /* Start a HTTP retrieval and on success store at R_HD a context
938    pointer for completing the request and to wait for the response.
939    If HTTPHOST is not NULL it is used for the Host header instead of a
940    Host header derived from the URL. */
941 gpg_error_t
http_open(ctrl_t ctrl,http_t * r_hd,http_req_t reqtype,const char * url,const char * httphost,const char * auth,unsigned int flags,const char * proxy,http_session_t session,const char * srvtag,strlist_t headers)942 http_open (ctrl_t ctrl, http_t *r_hd, http_req_t reqtype, const char *url,
943            const char *httphost,
944            const char *auth, unsigned int flags, const char *proxy,
945            http_session_t session, const char *srvtag, strlist_t headers)
946 {
947   gpg_error_t err;
948   http_t hd;
949 
950   *r_hd = NULL;
951 
952   if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
953     return gpg_err_make (default_errsource, GPG_ERR_INV_ARG);
954 
955   /* Create the handle. */
956   hd = xtrycalloc (1, sizeof *hd);
957   if (!hd)
958     return gpg_error_from_syserror ();
959   hd->magic = HTTP_CONTEXT_MAGIC;
960   hd->req_type = reqtype;
961   hd->flags = flags;
962   hd->session = http_session_ref (session);
963 
964   err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
965   if (!err)
966     err = send_request (ctrl, hd, httphost, auth, proxy, srvtag,
967                         hd->session? hd->session->connect_timeout : 0,
968                         headers);
969 
970   if (err)
971     {
972       my_socket_unref (hd->sock, NULL, NULL);
973       if (hd->fp_read)
974         es_fclose (hd->fp_read);
975       if (hd->fp_write)
976         es_fclose (hd->fp_write);
977       http_session_unref (hd->session);
978       xfree (hd);
979     }
980   else
981     *r_hd = hd;
982   return err;
983 }
984 
985 
986 /* This function is useful to connect to a generic TCP service using
987    this http abstraction layer.  This has the advantage of providing
988    service tags and an estream interface.  TIMEOUT is in milliseconds. */
989 gpg_error_t
http_raw_connect(ctrl_t ctrl,http_t * r_hd,const char * server,unsigned short port,unsigned int flags,const char * srvtag,unsigned int timeout)990 http_raw_connect (ctrl_t ctrl, http_t *r_hd,
991                   const char *server, unsigned short port,
992                   unsigned int flags, const char *srvtag, unsigned int timeout)
993 {
994   gpg_error_t err = 0;
995   http_t hd;
996   cookie_t cookie;
997 
998   *r_hd = NULL;
999 
1000   if ((flags & HTTP_FLAG_FORCE_TOR))
1001     {
1002       int mode;
1003 
1004       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1005         {
1006           log_error ("Tor support is not available\n");
1007           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1008         }
1009       /* Non-blocking connects do not work with our Tor proxy because
1010        * we can't continue the Socks protocol after the EINPROGRESS.
1011        * Disable the timeout to use a blocking connect.  */
1012       timeout = 0;
1013     }
1014 
1015   /* Create the handle. */
1016   hd = xtrycalloc (1, sizeof *hd);
1017   if (!hd)
1018     return gpg_error_from_syserror ();
1019   hd->magic = HTTP_CONTEXT_MAGIC;
1020   hd->req_type = HTTP_REQ_OPAQUE;
1021   hd->flags = flags;
1022 
1023   /* Connect.  */
1024   {
1025     assuan_fd_t sock;
1026 
1027     err = connect_server (ctrl, server, port,
1028                           hd->flags, srvtag, timeout, &sock);
1029     if (err)
1030       {
1031         xfree (hd);
1032         return err;
1033       }
1034     hd->sock = my_socket_new (sock);
1035     if (!hd->sock)
1036       {
1037         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1038         xfree (hd);
1039         return err;
1040       }
1041   }
1042 
1043   /* Setup estreams for reading and writing.  */
1044   cookie = xtrycalloc (1, sizeof *cookie);
1045   if (!cookie)
1046     {
1047       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1048       goto leave;
1049     }
1050   cookie->sock = my_socket_ref (hd->sock);
1051   hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1052   if (!hd->fp_write)
1053     {
1054       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1055       my_socket_unref (cookie->sock, NULL, NULL);
1056       xfree (cookie);
1057       goto leave;
1058     }
1059   hd->write_cookie = cookie; /* Cookie now owned by FP_WRITE.  */
1060 
1061   cookie = xtrycalloc (1, sizeof *cookie);
1062   if (!cookie)
1063     {
1064       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1065       goto leave;
1066     }
1067   cookie->sock = my_socket_ref (hd->sock);
1068   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
1069   if (!hd->fp_read)
1070     {
1071       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1072       my_socket_unref (cookie->sock, NULL, NULL);
1073       xfree (cookie);
1074       goto leave;
1075     }
1076   hd->read_cookie = cookie; /* Cookie now owned by FP_READ.  */
1077 
1078   /* Register close notification to interlock the use of es_fclose in
1079      http_close and in user code.  */
1080   err = es_onclose (hd->fp_write, 1, fp_onclose_notification, hd);
1081   if (!err)
1082     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1083 
1084  leave:
1085   if (err)
1086     {
1087       if (hd->fp_read)
1088         es_fclose (hd->fp_read);
1089       if (hd->fp_write)
1090         es_fclose (hd->fp_write);
1091       my_socket_unref (hd->sock, NULL, NULL);
1092       xfree (hd);
1093     }
1094   else
1095     *r_hd = hd;
1096   return err;
1097 }
1098 
1099 
1100 
1101 
1102 void
http_start_data(http_t hd)1103 http_start_data (http_t hd)
1104 {
1105   if (!hd->in_data)
1106     {
1107       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1108         log_debug_string ("\r\n", "http.c:request-header:");
1109       es_fputs ("\r\n", hd->fp_write);
1110       es_fflush (hd->fp_write);
1111       hd->in_data = 1;
1112     }
1113   else
1114     es_fflush (hd->fp_write);
1115 }
1116 
1117 
1118 gpg_error_t
http_wait_response(http_t hd)1119 http_wait_response (http_t hd)
1120 {
1121   gpg_error_t err;
1122   cookie_t cookie;
1123   int use_tls;
1124 
1125   /* Make sure that we are in the data. */
1126   http_start_data (hd);
1127 
1128   /* Close the write stream.  Note that the reference counted socket
1129      object keeps the actual system socket open.  */
1130   cookie = hd->write_cookie;
1131   if (!cookie)
1132     return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1133 
1134   use_tls = cookie->use_tls;
1135   es_fclose (hd->fp_write);
1136   hd->fp_write = NULL;
1137   /* The close has released the cookie and thus we better set it to NULL.  */
1138   hd->write_cookie = NULL;
1139 
1140   /* Shutdown one end of the socket is desired.  As per HTTP/1.0 this
1141      is not required but some very old servers (e.g. the original pksd
1142      keyserver didn't worked without it.  */
1143   if ((hd->flags & HTTP_FLAG_SHUTDOWN))
1144     shutdown (FD2INT (hd->sock->fd), 1);
1145   hd->in_data = 0;
1146 
1147   /* Create a new cookie and a stream for reading.  */
1148   cookie = xtrycalloc (1, sizeof *cookie);
1149   if (!cookie)
1150     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1151   cookie->sock = my_socket_ref (hd->sock);
1152   cookie->session = http_session_ref (hd->session);
1153   cookie->use_tls = use_tls;
1154 
1155   hd->read_cookie = cookie;
1156   hd->fp_read = es_fopencookie (cookie, "r", cookie_functions);
1157   if (!hd->fp_read)
1158     {
1159       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1160       my_socket_unref (cookie->sock, NULL, NULL);
1161       http_session_unref (cookie->session);
1162       xfree (cookie);
1163       hd->read_cookie = NULL;
1164       return err;
1165     }
1166 
1167   err = parse_response (hd);
1168 
1169   if (!err)
1170     err = es_onclose (hd->fp_read, 1, fp_onclose_notification, hd);
1171 
1172   return err;
1173 }
1174 
1175 
1176 /* Convenience function to send a request and wait for the response.
1177    Closes the handle on error.  If PROXY is not NULL, this value will
1178    be used as an HTTP proxy and any enabled $http_proxy gets
1179    ignored. */
1180 gpg_error_t
http_open_document(ctrl_t ctrl,http_t * r_hd,const char * document,const char * auth,unsigned int flags,const char * proxy,http_session_t session,const char * srvtag,strlist_t headers)1181 http_open_document (ctrl_t ctrl, http_t *r_hd, const char *document,
1182                     const char *auth, unsigned int flags, const char *proxy,
1183                     http_session_t session,
1184                     const char *srvtag, strlist_t headers)
1185 {
1186   gpg_error_t err;
1187 
1188   err = http_open (ctrl, r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
1189                    proxy, session, srvtag, headers);
1190   if (err)
1191     return err;
1192 
1193   err = http_wait_response (*r_hd);
1194   if (err)
1195     http_close (*r_hd, 0);
1196 
1197   return err;
1198 }
1199 
1200 
1201 void
http_close(http_t hd,int keep_read_stream)1202 http_close (http_t hd, int keep_read_stream)
1203 {
1204   if (!hd)
1205     return;
1206 
1207   log_assert (hd->magic == HTTP_CONTEXT_MAGIC);
1208 
1209   /* First remove the close notifications for the streams.  */
1210   if (hd->fp_read)
1211     es_onclose (hd->fp_read, 0, fp_onclose_notification, hd);
1212   if (hd->fp_write)
1213     es_onclose (hd->fp_write, 0, fp_onclose_notification, hd);
1214 
1215   /* Now we can close the streams.  */
1216   my_socket_unref (hd->sock, NULL, NULL);
1217   if (hd->fp_read && !keep_read_stream)
1218     es_fclose (hd->fp_read);
1219   if (hd->fp_write)
1220     es_fclose (hd->fp_write);
1221   http_session_unref (hd->session);
1222   hd->magic = 0xdeadbeef;
1223   http_release_parsed_uri (hd->uri);
1224   while (hd->headers)
1225     {
1226       header_t tmp = hd->headers->next;
1227       xfree (hd->headers->value);
1228       xfree (hd->headers);
1229       hd->headers = tmp;
1230     }
1231   xfree (hd->buffer);
1232   xfree (hd);
1233 }
1234 
1235 
1236 estream_t
http_get_read_ptr(http_t hd)1237 http_get_read_ptr (http_t hd)
1238 {
1239   return hd?hd->fp_read:NULL;
1240 }
1241 
1242 estream_t
http_get_write_ptr(http_t hd)1243 http_get_write_ptr (http_t hd)
1244 {
1245   return hd?hd->fp_write:NULL;
1246 }
1247 
1248 unsigned int
http_get_status_code(http_t hd)1249 http_get_status_code (http_t hd)
1250 {
1251   return hd?hd->status_code:0;
1252 }
1253 
1254 /* Return information pertaining to TLS.  If TLS is not in use for HD,
1255    NULL is returned.  WHAT is used ask for specific information:
1256 
1257      (NULL) := Only check whether TLS is in use.  Returns an
1258                unspecified string if TLS is in use.  That string may
1259                even be the empty string.
1260  */
1261 const char *
http_get_tls_info(http_t hd,const char * what)1262 http_get_tls_info (http_t hd, const char *what)
1263 {
1264   (void)what;
1265 
1266   if (!hd)
1267     return NULL;
1268 
1269   return hd->uri->use_tls? "":NULL;
1270 }
1271 
1272 
1273 
1274 static gpg_error_t
parse_uri(parsed_uri_t * ret_uri,const char * uri,int no_scheme_check,int force_tls)1275 parse_uri (parsed_uri_t *ret_uri, const char *uri,
1276            int no_scheme_check, int force_tls)
1277 {
1278   gpg_err_code_t ec;
1279 
1280   *ret_uri = xtrycalloc (1, sizeof **ret_uri + 2 * strlen (uri) + 1);
1281   if (!*ret_uri)
1282     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1283   strcpy ((*ret_uri)->buffer, uri);
1284   strcpy ((*ret_uri)->buffer + strlen (uri) + 1, uri);
1285   (*ret_uri)->original = (*ret_uri)->buffer + strlen (uri) + 1;
1286   ec = do_parse_uri (*ret_uri, 0, no_scheme_check, force_tls);
1287   if (ec)
1288     {
1289       http_release_parsed_uri (*ret_uri);
1290       *ret_uri = NULL;
1291     }
1292   return gpg_err_make (default_errsource, ec);
1293 }
1294 
1295 
1296 /*
1297  * Parse an URI and put the result into the newly allocated RET_URI.
1298  * On success the caller must use http_release_parsed_uri() to
1299  * releases the resources.  If the HTTP_PARSE_NO_SCHEME_CHECK flag is
1300  * set, the function tries to parse the URL in the same way it would
1301  * do for an HTTP style URI.   */
1302 gpg_error_t
http_parse_uri(parsed_uri_t * ret_uri,const char * uri,unsigned int flags)1303 http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
1304                 unsigned int flags)
1305 {
1306   return parse_uri (ret_uri, uri, !!(flags & HTTP_PARSE_NO_SCHEME_CHECK), 0);
1307 }
1308 
1309 
1310 void
http_release_parsed_uri(parsed_uri_t uri)1311 http_release_parsed_uri (parsed_uri_t uri)
1312 {
1313   if (uri)
1314     {
1315       uri_tuple_t r, r2;
1316 
1317       for (r = uri->params; r; r = r2)
1318 	{
1319 	  r2 = r->next;
1320 	  xfree (r);
1321 	}
1322       for (r = uri->query; r; r = r2)
1323 	{
1324 	  r2 = r->next;
1325 	  xfree (r);
1326 	}
1327       xfree (uri);
1328     }
1329 }
1330 
1331 
1332 static gpg_err_code_t
do_parse_uri(parsed_uri_t uri,int only_local_part,int no_scheme_check,int force_tls)1333 do_parse_uri (parsed_uri_t uri, int only_local_part,
1334               int no_scheme_check, int force_tls)
1335 {
1336   uri_tuple_t *tail;
1337   char *p, *p2, *p3, *pp;
1338   int n;
1339 
1340   p = uri->buffer;
1341   n = strlen (uri->buffer);
1342 
1343   /* Initialize all fields to an empty string or an empty list. */
1344   uri->scheme = uri->host = uri->path = p + n;
1345   uri->port = 0;
1346   uri->params = uri->query = NULL;
1347   uri->use_tls = 0;
1348   uri->is_http = 0;
1349   uri->is_ldap = 0;
1350   uri->opaque = 0;
1351   uri->v6lit = 0;
1352   uri->onion = 0;
1353   uri->explicit_port = 0;
1354   uri->off_host = 0;
1355   uri->off_path = 0;
1356 
1357   /* A quick validity check unless we have the opaque scheme. */
1358   if (strspn (p, VALID_URI_CHARS) != n
1359       && strncmp (p, "opaque:", 7))
1360     return GPG_ERR_BAD_URI;	/* Invalid characters found. */
1361 
1362   if (!only_local_part)
1363     {
1364       /* Find the scheme. */
1365       if (!(p2 = strchr (p, ':')) || p2 == p)
1366 	return GPG_ERR_BAD_URI; /* No scheme. */
1367       *p2++ = 0;
1368       for (pp=p; *pp; pp++)
1369        *pp = tolower (*(unsigned char*)pp);
1370       uri->scheme = p;
1371       if (!strcmp (uri->scheme, "http") && !force_tls)
1372         {
1373           uri->port = 80;
1374           uri->is_http = 1;
1375         }
1376       else if (!strcmp (uri->scheme, "hkp") && !force_tls)
1377         {
1378           uri->port = 11371;
1379           uri->is_http = 1;
1380         }
1381       else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")
1382                || (force_tls && (!strcmp (uri->scheme, "http")
1383                                  || !strcmp (uri->scheme,"hkp"))))
1384         {
1385           uri->port = 443;
1386           uri->is_http = 1;
1387           uri->use_tls = 1;
1388         }
1389       else if (!strcmp (uri->scheme, "opaque"))
1390         {
1391           uri->opaque = 1;
1392           uri->path = p2;
1393           return 0;
1394         }
1395       else if (!no_scheme_check)
1396 	return GPG_ERR_INV_URI; /* Not an http style scheme.  */
1397       else if (!strcmp (uri->scheme, "ldap") && !force_tls)
1398         {
1399           uri->port = 389;
1400           uri->is_ldap = 1;
1401         }
1402       else if (!strcmp (uri->scheme, "ldaps")
1403                || (force_tls && (!strcmp (uri->scheme, "ldap"))))
1404         {
1405           uri->port = 636;
1406           uri->is_ldap = 1;
1407           uri->use_tls = 1;
1408         }
1409       else if (!strcmp (uri->scheme, "ldapi"))  /* LDAP via IPC.  */
1410         {
1411           uri->port = 0;
1412           uri->is_ldap = 1;
1413         }
1414 
1415       p = p2;
1416 
1417       if (*p == '/' && p[1] == '/' ) /* There seems to be a hostname. */
1418 	{
1419           p += 2;
1420 	  if ((p2 = strchr (p, '/')))
1421             {
1422               if (p2 - uri->buffer > 10000)
1423                 return GPG_ERR_BAD_URI;
1424               uri->off_path = p2 - uri->buffer;
1425               *p2++ = 0;
1426             }
1427           else
1428             {
1429               n = (p - uri->buffer) + strlen (p);
1430               if (n > 10000)
1431                 return GPG_ERR_BAD_URI;
1432               uri->off_path = n;
1433             }
1434 
1435           /* Check for username/password encoding */
1436           if ((p3 = strchr (p, '@')))
1437             {
1438               uri->auth = p;
1439               *p3++ = '\0';
1440               p = p3;
1441             }
1442 
1443           for (pp=p; *pp; pp++)
1444             *pp = tolower (*(unsigned char*)pp);
1445 
1446 	  /* Handle an IPv6 literal */
1447 	  if( *p == '[' && (p3=strchr( p, ']' )) )
1448 	    {
1449 	      *p3++ = '\0';
1450 	      /* worst case, uri->host should have length 0, points to \0 */
1451 	      uri->host = p + 1;
1452               if (p - uri->buffer > 10000)
1453                 return GPG_ERR_BAD_URI;
1454               uri->off_host = (p + 1) - uri->buffer;
1455               uri->v6lit = 1;
1456 	      p = p3;
1457 	    }
1458 	  else
1459             {
1460               uri->host = p;
1461               if (p - uri->buffer > 10000)
1462                 return GPG_ERR_BAD_URI;
1463               uri->off_host = p - uri->buffer;
1464             }
1465 
1466 	  if ((p3 = strchr (p, ':')))
1467 	    {
1468 	      *p3++ = '\0';
1469 	      uri->port = atoi (p3);
1470               uri->explicit_port = 1;
1471 	    }
1472 
1473 	  if ((n = remove_escapes (uri->host)) < 0)
1474 	    return GPG_ERR_BAD_URI;
1475 	  if (n != strlen (uri->host))
1476 	    return GPG_ERR_BAD_URI;	/* Hostname includes a Nul. */
1477 	  p = p2 ? p2 : NULL;
1478 	}
1479       else if (!no_scheme_check && (uri->is_http || uri->is_ldap))
1480 	return GPG_ERR_INV_URI; /* HTTP or LDAP w/o leading double slash. */
1481       else
1482         {
1483           uri->opaque = 1;
1484           uri->path = p;
1485           if (is_onion_address (uri->path))
1486             uri->onion = 1;
1487           return 0;
1488         }
1489 
1490     } /* End global URI part. */
1491 
1492   /* Parse the pathname part if any.  */
1493   if (p && *p)
1494     {
1495       /* TODO: Here we have to check params. */
1496 
1497       /* Do we have a query part? */
1498       if ((p2 = strchr (p, '?')))
1499         *p2++ = 0;
1500 
1501       uri->path = p;
1502       if ((n = remove_escapes (p)) < 0)
1503         return GPG_ERR_BAD_URI;
1504       if (n != strlen (p))
1505         return GPG_ERR_BAD_URI;	/* Path includes a Nul. */
1506       p = p2 ? p2 : NULL;
1507 
1508       /* Parse a query string if any.  */
1509       if (p && *p)
1510         {
1511           tail = &uri->query;
1512           for (;;)
1513             {
1514               uri_tuple_t elem;
1515 
1516               if ((p2 = strchr (p, '&')))
1517                 *p2++ = 0;
1518               if (!(elem = parse_tuple (p)))
1519                 return GPG_ERR_BAD_URI;
1520               *tail = elem;
1521               tail = &elem->next;
1522 
1523               if (!p2)
1524                 break; /* Ready. */
1525               p = p2;
1526             }
1527         }
1528     }
1529 
1530   if (is_onion_address (uri->host))
1531     uri->onion = 1;
1532 
1533   return 0;
1534 }
1535 
1536 
1537 /*
1538  * Remove all %xx escapes; this is done in-place.  Returns: New length
1539  * of the string.
1540  */
1541 static int
remove_escapes(char * string)1542 remove_escapes (char *string)
1543 {
1544   int n = 0;
1545   unsigned char *p, *s;
1546 
1547   for (p = s = (unsigned char*)string; *s; s++)
1548     {
1549       if (*s == '%')
1550 	{
1551 	  if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2]))
1552 	    {
1553 	      s++;
1554 	      *p = *s >= '0' && *s <= '9' ? *s - '0' :
1555 		*s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1556 	      *p <<= 4;
1557 	      s++;
1558 	      *p |= *s >= '0' && *s <= '9' ? *s - '0' :
1559 		*s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10;
1560 	      p++;
1561 	      n++;
1562 	    }
1563 	  else
1564 	    {
1565 	      *p++ = *s++;
1566 	      if (*s)
1567 		*p++ = *s++;
1568 	      if (*s)
1569 		*p++ = *s++;
1570 	      if (*s)
1571 		*p = 0;
1572 	      return -1; /* Bad URI. */
1573 	    }
1574 	}
1575       else
1576 	{
1577 	  *p++ = *s;
1578 	  n++;
1579 	}
1580     }
1581   *p = 0; /* Make sure to keep a string terminator. */
1582   return n;
1583 }
1584 
1585 
1586 /* If SPECIAL is NULL this function escapes in forms mode.  */
1587 static size_t
escape_data(char * buffer,const void * data,size_t datalen,const char * special)1588 escape_data (char *buffer, const void *data, size_t datalen,
1589              const char *special)
1590 {
1591   int forms = !special;
1592   const unsigned char *s;
1593   size_t n = 0;
1594 
1595   if (forms)
1596     special = "%;?&=";
1597 
1598   for (s = data; datalen; s++, datalen--)
1599     {
1600       if (forms && *s == ' ')
1601         {
1602 	  if (buffer)
1603 	    *buffer++ = '+';
1604 	  n++;
1605         }
1606       else if (forms && *s == '\n')
1607         {
1608 	  if (buffer)
1609 	    memcpy (buffer, "%0D%0A", 6);
1610 	  n += 6;
1611         }
1612       else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n')
1613         {
1614 	  if (buffer)
1615 	    memcpy (buffer, "%0D%0A", 6);
1616 	  n += 6;
1617           s++;
1618           datalen--;
1619         }
1620       else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s))
1621 	{
1622 	  if (buffer)
1623 	    *(unsigned char*)buffer++ = *s;
1624 	  n++;
1625 	}
1626       else
1627 	{
1628 	  if (buffer)
1629 	    {
1630 	      snprintf (buffer, 4, "%%%02X", *s);
1631 	      buffer += 3;
1632 	    }
1633 	  n += 3;
1634 	}
1635     }
1636   return n;
1637 }
1638 
1639 
1640 static int
insert_escapes(char * buffer,const char * string,const char * special)1641 insert_escapes (char *buffer, const char *string,
1642 		const char *special)
1643 {
1644   return escape_data (buffer, string, strlen (string), special);
1645 }
1646 
1647 
1648 /* Allocate a new string from STRING using standard HTTP escaping as
1649    well as escaping of characters given in SPECIALS.  A common pattern
1650    for SPECIALS is "%;?&=". However it depends on the needs, for
1651    example "+" and "/: often needs to be escaped too.  Returns NULL on
1652    failure and sets ERRNO.  If SPECIAL is NULL a dedicated forms
1653    encoding mode is used. */
1654 char *
http_escape_string(const char * string,const char * specials)1655 http_escape_string (const char *string, const char *specials)
1656 {
1657   int n;
1658   char *buf;
1659 
1660   n = insert_escapes (NULL, string, specials);
1661   buf = xtrymalloc (n+1);
1662   if (buf)
1663     {
1664       insert_escapes (buf, string, specials);
1665       buf[n] = 0;
1666     }
1667   return buf;
1668 }
1669 
1670 /* Allocate a new string from {DATA,DATALEN} using standard HTTP
1671    escaping as well as escaping of characters given in SPECIALS.  A
1672    common pattern for SPECIALS is "%;?&=".  However it depends on the
1673    needs, for example "+" and "/: often needs to be escaped too.
1674    Returns NULL on failure and sets ERRNO.  If SPECIAL is NULL a
1675    dedicated forms encoding mode is used. */
1676 char *
http_escape_data(const void * data,size_t datalen,const char * specials)1677 http_escape_data (const void *data, size_t datalen, const char *specials)
1678 {
1679   int n;
1680   char *buf;
1681 
1682   n = escape_data (NULL, data, datalen, specials);
1683   buf = xtrymalloc (n+1);
1684   if (buf)
1685     {
1686       escape_data (buf, data, datalen, specials);
1687       buf[n] = 0;
1688     }
1689   return buf;
1690 }
1691 
1692 
1693 static uri_tuple_t
parse_tuple(char * string)1694 parse_tuple (char *string)
1695 {
1696   char *p = string;
1697   char *p2;
1698   int n;
1699   uri_tuple_t tuple;
1700 
1701   if ((p2 = strchr (p, '=')))
1702     *p2++ = 0;
1703   if ((n = remove_escapes (p)) < 0)
1704     return NULL; /* Bad URI. */
1705   if (n != strlen (p))
1706     return NULL; /* Name with a Nul in it. */
1707   tuple = xtrycalloc (1, sizeof *tuple);
1708   if (!tuple)
1709     return NULL; /* Out of core. */
1710   tuple->name = p;
1711   if (!p2) /* We have only the name, so we assume an empty value string. */
1712     {
1713       tuple->value = p + strlen (p);
1714       tuple->valuelen = 0;
1715       tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */
1716     }
1717   else /* Name and value. */
1718     {
1719       if ((n = remove_escapes (p2)) < 0)
1720 	{
1721 	  xfree (tuple);
1722 	  return NULL; /* Bad URI. */
1723 	}
1724       tuple->value = p2;
1725       tuple->valuelen = n;
1726     }
1727   return tuple;
1728 }
1729 
1730 
1731 /* Return true if STRING is likely "hostname:port" or only "hostname".  */
1732 static int
is_hostname_port(const char * string)1733 is_hostname_port (const char *string)
1734 {
1735   int colons = 0;
1736 
1737   if (!string || !*string)
1738     return 0;
1739   for (; *string; string++)
1740     {
1741       if (*string == ':')
1742         {
1743           if (colons)
1744             return 0;
1745           if (!string[1])
1746             return 0;
1747           colons++;
1748         }
1749       else if (!colons && strchr (" \t\f\n\v_@[]/", *string))
1750         return 0; /* Invalid characters in hostname. */
1751       else if (colons && !digitp (string))
1752         return 0; /* Not a digit in the port.  */
1753     }
1754   return 1;
1755 }
1756 
1757 
1758 /*
1759  * Send a HTTP request to the server
1760  * Returns 0 if the request was successful
1761  */
1762 static gpg_error_t
send_request(ctrl_t ctrl,http_t hd,const char * httphost,const char * auth,const char * proxy,const char * srvtag,unsigned int timeout,strlist_t headers)1763 send_request (ctrl_t ctrl, http_t hd, const char *httphost, const char *auth,
1764 	      const char *proxy, const char *srvtag, unsigned int timeout,
1765               strlist_t headers)
1766 {
1767   gpg_error_t err;
1768   const char *server;
1769   char *request, *p;
1770   unsigned short port;
1771   const char *http_proxy = NULL;
1772   char *proxy_authstr = NULL;
1773   char *authstr = NULL;
1774   assuan_fd_t sock;
1775   int have_http_proxy = 0;
1776 
1777   if (hd->uri->use_tls && !hd->session)
1778     {
1779       log_error ("TLS requested but no session object provided\n");
1780       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1781     }
1782   if (hd->uri->use_tls && !hd->session->tls_session)
1783     {
1784       log_error ("TLS requested but no TLS context available\n");
1785       return gpg_err_make (default_errsource, GPG_ERR_INTERNAL);
1786     }
1787   if (opt_debug)
1788     log_debug ("Using TLS library: %s %s\n",
1789 #if HTTP_USE_NTBTLS
1790                "NTBTLS", ntbtls_check_version (NULL)
1791 #elif HTTP_USE_GNUTLS
1792                "GNUTLS", gnutls_check_version (NULL)
1793 #endif /*HTTP_USE_GNUTLS*/
1794                );
1795 
1796   if ((hd->flags & HTTP_FLAG_FORCE_TOR))
1797     {
1798       int mode;
1799 
1800       if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
1801         {
1802           log_error ("Tor support is not available\n");
1803           return gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1804         }
1805       /* Non-blocking connects do not work with our Tor proxy because
1806        * we can't continue the Socks protocol after the EINPROGRESS.
1807        * Disable the timeout to use a blocking connect.  */
1808       timeout = 0;
1809     }
1810 
1811   server = *hd->uri->host ? hd->uri->host : "localhost";
1812   port = hd->uri->port ? hd->uri->port : 80;
1813 
1814   /* Try to use SNI.  */
1815   if (hd->uri->use_tls)
1816     {
1817 #if HTTP_USE_GNUTLS
1818       int rc;
1819 #endif
1820 
1821       xfree (hd->session->servername);
1822       hd->session->servername = xtrystrdup (httphost? httphost : server);
1823       if (!hd->session->servername)
1824         {
1825           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1826           return err;
1827         }
1828 
1829 #if HTTP_USE_NTBTLS
1830       err = ntbtls_set_hostname (hd->session->tls_session,
1831                                  hd->session->servername);
1832       if (err)
1833         {
1834           log_info ("ntbtls_set_hostname failed: %s\n", gpg_strerror (err));
1835           return err;
1836         }
1837 #elif HTTP_USE_GNUTLS
1838       rc = gnutls_server_name_set (hd->session->tls_session,
1839                                    GNUTLS_NAME_DNS,
1840                                    hd->session->servername,
1841                                    strlen (hd->session->servername));
1842       if (rc < 0)
1843         log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc));
1844 #endif /*HTTP_USE_GNUTLS*/
1845     }
1846 
1847   if ( (proxy && *proxy)
1848        || ( (hd->flags & HTTP_FLAG_TRY_PROXY)
1849             && (http_proxy = getenv (HTTP_PROXY_ENV))
1850             && *http_proxy ))
1851     {
1852       parsed_uri_t uri;
1853 
1854       if (proxy)
1855 	http_proxy = proxy;
1856 
1857       err = parse_uri (&uri, http_proxy, 0, 0);
1858       if (gpg_err_code (err) == GPG_ERR_INV_URI
1859           && is_hostname_port (http_proxy))
1860         {
1861           /* Retry assuming a "hostname:port" string.  */
1862           char *tmpname = strconcat ("http://", http_proxy, NULL);
1863           if (tmpname && !parse_uri (&uri, tmpname, 0, 0))
1864             err = 0;
1865           xfree (tmpname);
1866         }
1867 
1868       if (err)
1869         ;
1870       else if (!strcmp (uri->scheme, "http"))
1871         have_http_proxy = 1;
1872       else if (!strcmp (uri->scheme, "socks4")
1873                || !strcmp (uri->scheme, "socks5h"))
1874         err = gpg_err_make (default_errsource, GPG_ERR_NOT_IMPLEMENTED);
1875       else
1876         err = gpg_err_make (default_errsource, GPG_ERR_INV_URI);
1877 
1878       if (err)
1879 	{
1880 	  log_error ("invalid HTTP proxy (%s): %s\n",
1881 		     http_proxy, gpg_strerror (err));
1882 	  return gpg_err_make (default_errsource, GPG_ERR_CONFIGURATION);
1883 	}
1884 
1885       if (uri->auth)
1886         {
1887           remove_escapes (uri->auth);
1888           proxy_authstr = make_header_line ("Proxy-Authorization: Basic ",
1889                                             "\r\n",
1890                                             uri->auth, strlen(uri->auth));
1891           if (!proxy_authstr)
1892             {
1893               err = gpg_err_make (default_errsource,
1894                                   gpg_err_code_from_syserror ());
1895               http_release_parsed_uri (uri);
1896               return err;
1897             }
1898         }
1899 
1900       err = connect_server (ctrl,
1901                             *uri->host ? uri->host : "localhost",
1902                             uri->port ? uri->port : 80,
1903                             hd->flags, NULL, timeout, &sock);
1904       http_release_parsed_uri (uri);
1905     }
1906   else
1907     {
1908       err = connect_server (ctrl,
1909                             server, port, hd->flags, srvtag, timeout, &sock);
1910     }
1911 
1912   if (err)
1913     {
1914       xfree (proxy_authstr);
1915       return err;
1916     }
1917   hd->sock = my_socket_new (sock);
1918   if (!hd->sock)
1919     {
1920       xfree (proxy_authstr);
1921       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1922     }
1923 
1924   if (have_http_proxy && hd->uri->use_tls)
1925     {
1926       int saved_flags;
1927       cookie_t cookie;
1928 
1929       /* Try to use the CONNECT method to proxy our TLS stream.  */
1930       request = es_bsprintf
1931         ("CONNECT %s:%hu HTTP/1.0\r\nHost: %s:%hu\r\n%s",
1932          httphost ? httphost : server,
1933          port,
1934          httphost ? httphost : server,
1935          port,
1936          proxy_authstr ? proxy_authstr : "");
1937       xfree (proxy_authstr);
1938       proxy_authstr = NULL;
1939 
1940       if (! request)
1941         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1942 
1943       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
1944         log_debug_string (request, "http.c:request:");
1945 
1946       cookie = xtrycalloc (1, sizeof *cookie);
1947       if (! cookie)
1948         {
1949           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1950           xfree (request);
1951           return err;
1952         }
1953       cookie->sock = my_socket_ref (hd->sock);
1954       hd->write_cookie = cookie;
1955 
1956       hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
1957       if (! hd->fp_write)
1958         {
1959           err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1960           my_socket_unref (cookie->sock, NULL, NULL);
1961           xfree (cookie);
1962           xfree (request);
1963           hd->write_cookie = NULL;
1964           return err;
1965         }
1966       else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
1967         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
1968 
1969       xfree (request);
1970       request = NULL;
1971 
1972       /* Make sure http_wait_response doesn't close the stream.  */
1973       saved_flags = hd->flags;
1974       hd->flags &= ~HTTP_FLAG_SHUTDOWN;
1975 
1976       /* Get the response.  */
1977       err = http_wait_response (hd);
1978 
1979       /* Restore flags, destroy stream.  */
1980       hd->flags = saved_flags;
1981       es_fclose (hd->fp_read);
1982       hd->fp_read = NULL;
1983       hd->read_cookie = NULL;
1984 
1985       /* Reset state.  */
1986       hd->in_data = 0;
1987 
1988       if (err)
1989         return err;
1990 
1991       if (hd->status_code != 200)
1992         {
1993           request = es_bsprintf
1994             ("CONNECT %s:%hu",
1995              httphost ? httphost : server,
1996              port);
1997 
1998           log_error (_("error accessing '%s': http status %u\n"),
1999                      request ? request : "out of core",
2000                      http_get_status_code (hd));
2001 
2002           xfree (request);
2003           return gpg_error (GPG_ERR_NO_DATA);
2004         }
2005 
2006       /* We are done with the proxy, the code below will establish a
2007        * TLS session and talk directly to the target server.  */
2008       http_proxy = NULL;
2009     }
2010 
2011 #if HTTP_USE_NTBTLS
2012   if (hd->uri->use_tls)
2013     {
2014       estream_t in, out;
2015 
2016       my_socket_ref (hd->sock);
2017 
2018       /* Until we support send/recv in estream under Windows we need
2019        * to use es_fopencookie.  */
2020 # ifdef HAVE_W32_SYSTEM
2021       in = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "rb",
2022                            simple_cookie_functions);
2023 # else
2024       in = es_fdopen_nc (hd->sock->fd, "rb");
2025 # endif
2026       if (!in)
2027         {
2028           err = gpg_error_from_syserror ();
2029           xfree (proxy_authstr);
2030           return err;
2031         }
2032 
2033 # ifdef HAVE_W32_SYSTEM
2034       out = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "wb",
2035                             simple_cookie_functions);
2036 # else
2037       out = es_fdopen_nc (hd->sock->fd, "wb");
2038 # endif
2039       if (!out)
2040         {
2041           err = gpg_error_from_syserror ();
2042           es_fclose (in);
2043           xfree (proxy_authstr);
2044           return err;
2045         }
2046 
2047       err = ntbtls_set_transport (hd->session->tls_session, in, out);
2048       if (err)
2049         {
2050           log_info ("TLS set_transport failed: %s <%s>\n",
2051                     gpg_strerror (err), gpg_strsource (err));
2052           xfree (proxy_authstr);
2053           return err;
2054         }
2055 
2056       if (hd->session->verify_cb)
2057         {
2058           err = ntbtls_set_verify_cb (hd->session->tls_session,
2059                                       my_ntbtls_verify_cb, hd);
2060           if (err)
2061             {
2062               log_error ("ntbtls_set_verify_cb failed: %s\n",
2063                          gpg_strerror (err));
2064               xfree (proxy_authstr);
2065               return err;
2066             }
2067         }
2068 
2069       while ((err = ntbtls_handshake (hd->session->tls_session)))
2070         {
2071 #if NTBTLS_VERSION_NUMBER >= 0x000200
2072           unsigned int tlevel, ttype;
2073           const char *s = ntbtls_get_last_alert (hd->session->tls_session,
2074                                                  &tlevel, &ttype);
2075           if (s)
2076             log_info ("TLS alert: %s (%u.%u)\n", s, tlevel, ttype);
2077 #endif
2078 
2079           switch (err)
2080             {
2081             default:
2082               log_info ("TLS handshake failed: %s <%s>\n",
2083                         gpg_strerror (err), gpg_strsource (err));
2084               xfree (proxy_authstr);
2085               return err;
2086             }
2087         }
2088 
2089       hd->session->verify.done = 0;
2090 
2091       /* Try the available verify callbacks until one returns success
2092        * or a real error.  Note that NTBTLS does the verification
2093        * during the handshake via   */
2094       err = 0; /* Fixme check that the CB has been called.  */
2095 
2096       if (hd->session->verify_cb
2097           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
2098           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
2099         err = hd->session->verify_cb (hd->session->verify_cb_value,
2100                                       hd, hd->session,
2101                                       (hd->flags | hd->session->flags),
2102                                       hd->session->tls_session);
2103 
2104       if (tls_callback
2105           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
2106           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
2107         err = tls_callback (hd, hd->session, 0);
2108 
2109       if (gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR
2110           && gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
2111         err = http_verify_server_credentials (hd->session);
2112 
2113       if (err)
2114         {
2115           log_info ("TLS connection authentication failed: %s <%s>\n",
2116                     gpg_strerror (err), gpg_strsource (err));
2117           xfree (proxy_authstr);
2118           return err;
2119         }
2120 
2121     }
2122 
2123 #elif HTTP_USE_GNUTLS
2124 
2125   if (hd->uri->use_tls)
2126     {
2127       int rc;
2128 
2129       my_socket_ref (hd->sock);
2130       gnutls_transport_set_ptr (hd->session->tls_session, hd->sock);
2131       gnutls_transport_set_pull_function (hd->session->tls_session,
2132                                           my_gnutls_read);
2133       gnutls_transport_set_push_function (hd->session->tls_session,
2134                                           my_gnutls_write);
2135 
2136     handshake_again:
2137       do
2138         {
2139           rc = gnutls_handshake (hd->session->tls_session);
2140         }
2141       while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
2142       if (rc < 0)
2143         {
2144           if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED
2145               || rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
2146             {
2147               gnutls_alert_description_t alertno;
2148               const char *alertstr;
2149 
2150               alertno = gnutls_alert_get (hd->session->tls_session);
2151               alertstr = gnutls_alert_get_name (alertno);
2152               log_info ("TLS handshake %s: %s (alert %d)\n",
2153                         rc == GNUTLS_E_WARNING_ALERT_RECEIVED
2154                         ? "warning" : "failed",
2155                         alertstr, (int)alertno);
2156               if (alertno == GNUTLS_A_UNRECOGNIZED_NAME && server)
2157                 log_info ("  (sent server name '%s')\n", server);
2158 
2159               if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED)
2160                 goto handshake_again;
2161             }
2162           else
2163             log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
2164           xfree (proxy_authstr);
2165           return gpg_err_make (default_errsource, GPG_ERR_NETWORK);
2166         }
2167 
2168       hd->session->verify.done = 0;
2169       if (tls_callback)
2170         err = tls_callback (hd, hd->session, 0);
2171       else
2172         err = http_verify_server_credentials (hd->session);
2173       if (err)
2174         {
2175           log_info ("TLS connection authentication failed: %s\n",
2176                     gpg_strerror (err));
2177           xfree (proxy_authstr);
2178           return err;
2179         }
2180     }
2181 
2182 #endif /*HTTP_USE_GNUTLS*/
2183 
2184   if (auth || hd->uri->auth)
2185     {
2186       char *myauth;
2187 
2188       if (auth)
2189         {
2190           myauth = xtrystrdup (auth);
2191           if (!myauth)
2192             {
2193               xfree (proxy_authstr);
2194               return gpg_err_make (default_errsource,
2195                                    gpg_err_code_from_syserror ());
2196             }
2197           remove_escapes (myauth);
2198         }
2199       else
2200         {
2201           remove_escapes (hd->uri->auth);
2202           myauth = hd->uri->auth;
2203         }
2204 
2205       authstr = make_header_line ("Authorization: Basic ", "\r\n",
2206                                   myauth, strlen (myauth));
2207       if (auth)
2208         xfree (myauth);
2209 
2210       if (!authstr)
2211         {
2212           xfree (proxy_authstr);
2213           return gpg_err_make (default_errsource,
2214                                gpg_err_code_from_syserror ());
2215         }
2216     }
2217 
2218   p = build_rel_path (hd->uri);
2219   if (!p)
2220     {
2221       xfree (authstr);
2222       xfree (proxy_authstr);
2223       return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2224     }
2225 
2226   if (http_proxy && *http_proxy)
2227     {
2228       request = es_bsprintf
2229         ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s",
2230          hd->req_type == HTTP_REQ_GET ? "GET" :
2231          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
2232          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
2233          hd->uri->use_tls? "https" : "http",
2234          httphost? httphost : server,
2235          port, *p == '/' ? "" : "/", p,
2236          authstr ? authstr : "",
2237          proxy_authstr ? proxy_authstr : "");
2238     }
2239   else
2240     {
2241       char portstr[35];
2242 
2243       if (port == (hd->uri->use_tls? 443 : 80))
2244         *portstr = 0;
2245       else
2246         snprintf (portstr, sizeof portstr, ":%u", port);
2247 
2248       request = es_bsprintf
2249         ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
2250          hd->req_type == HTTP_REQ_GET ? "GET" :
2251          hd->req_type == HTTP_REQ_HEAD ? "HEAD" :
2252          hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS",
2253          *p == '/' ? "" : "/", p,
2254          httphost? httphost : server,
2255          portstr,
2256          authstr? authstr:"");
2257     }
2258   xfree (p);
2259   if (!request)
2260     {
2261       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2262       xfree (authstr);
2263       xfree (proxy_authstr);
2264       return err;
2265     }
2266 
2267   if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2268     log_debug_string (request, "http.c:request:");
2269 
2270   /* First setup estream so that we can write even the first line
2271      using estream.  This is also required for the sake of gnutls. */
2272   {
2273     cookie_t cookie;
2274 
2275     cookie = xtrycalloc (1, sizeof *cookie);
2276     if (!cookie)
2277       {
2278         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2279         goto leave;
2280       }
2281     cookie->sock = my_socket_ref (hd->sock);
2282     hd->write_cookie = cookie;
2283     cookie->use_tls = hd->uri->use_tls;
2284     cookie->session = http_session_ref (hd->session);
2285 
2286     hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
2287     if (!hd->fp_write)
2288       {
2289         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2290         my_socket_unref (cookie->sock, NULL, NULL);
2291         xfree (cookie);
2292         hd->write_cookie = NULL;
2293       }
2294     else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
2295       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2296     else
2297       err = 0;
2298 
2299   if (!err)
2300     {
2301       for (;headers; headers=headers->next)
2302         {
2303           if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2304             log_debug_string (headers->d, "http.c:request-header:");
2305           if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
2306               || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
2307             {
2308               err = gpg_err_make (default_errsource,
2309                                   gpg_err_code_from_syserror ());
2310               break;
2311             }
2312         }
2313     }
2314   }
2315 
2316  leave:
2317   es_free (request);
2318   xfree (authstr);
2319   xfree (proxy_authstr);
2320 
2321   return err;
2322 }
2323 
2324 
2325 /*
2326  * Build the relative path from the parsed URI.  Minimal
2327  * implementation.  May return NULL in case of memory failure; errno
2328  * is then set accordingly.
2329  */
2330 static char *
build_rel_path(parsed_uri_t uri)2331 build_rel_path (parsed_uri_t uri)
2332 {
2333   uri_tuple_t r;
2334   char *rel_path, *p;
2335   int n;
2336 
2337   /* Count the needed space. */
2338   n = insert_escapes (NULL, uri->path, "%;?&");
2339   /* TODO: build params. */
2340   for (r = uri->query; r; r = r->next)
2341     {
2342       n++; /* '?'/'&' */
2343       n += insert_escapes (NULL, r->name, "%;?&=");
2344       if (!r->no_value)
2345 	{
2346 	  n++; /* '=' */
2347 	  n += insert_escapes (NULL, r->value, "%;?&=");
2348 	}
2349     }
2350   n++;
2351 
2352   /* Now allocate and copy. */
2353   p = rel_path = xtrymalloc (n);
2354   if (!p)
2355     return NULL;
2356   n = insert_escapes (p, uri->path, "%;?&");
2357   p += n;
2358   /* TODO: add params. */
2359   for (r = uri->query; r; r = r->next)
2360     {
2361       *p++ = r == uri->query ? '?' : '&';
2362       n = insert_escapes (p, r->name, "%;?&=");
2363       p += n;
2364       if (!r->no_value)
2365 	{
2366 	  *p++ = '=';
2367 	  /* TODO: Use valuelen. */
2368 	  n = insert_escapes (p, r->value, "%;?&=");
2369 	  p += n;
2370 	}
2371     }
2372   *p = 0;
2373   return rel_path;
2374 }
2375 
2376 
2377 /* Transform a header name into a standard capitalized format; e.g.
2378    "Content-Type".  Conversion stops at the colon.  As usual we don't
2379    use the localized versions of ctype.h. */
2380 static void
capitalize_header_name(char * name)2381 capitalize_header_name (char *name)
2382 {
2383   int first = 1;
2384 
2385   for (; *name && *name != ':'; name++)
2386     {
2387       if (*name == '-')
2388         first = 1;
2389       else if (first)
2390         {
2391           if (*name >= 'a' && *name <= 'z')
2392             *name = *name - 'a' + 'A';
2393           first = 0;
2394         }
2395       else if (*name >= 'A' && *name <= 'Z')
2396         *name = *name - 'A' + 'a';
2397     }
2398 }
2399 
2400 
2401 /* Store an HTTP header line in LINE away.  Line continuation is
2402    supported as well as merging of headers with the same name. This
2403    function may modify LINE. */
2404 static gpg_err_code_t
store_header(http_t hd,char * line)2405 store_header (http_t hd, char *line)
2406 {
2407   size_t n;
2408   char *p, *value;
2409   header_t h;
2410 
2411   n = strlen (line);
2412   if (n && line[n-1] == '\n')
2413     {
2414       line[--n] = 0;
2415       if (n && line[n-1] == '\r')
2416         line[--n] = 0;
2417     }
2418   if (!n)  /* we are never called to hit this. */
2419     return GPG_ERR_BUG;
2420   if (*line == ' ' || *line == '\t')
2421     {
2422       /* Continuation. This won't happen too often as it is not
2423          recommended.  We use a straightforward implementation. */
2424       if (!hd->headers)
2425         return GPG_ERR_PROTOCOL_VIOLATION;
2426       n += strlen (hd->headers->value);
2427       p = xtrymalloc (n+1);
2428       if (!p)
2429         return gpg_err_code_from_syserror ();
2430       strcpy (stpcpy (p, hd->headers->value), line);
2431       xfree (hd->headers->value);
2432       hd->headers->value = p;
2433       return 0;
2434     }
2435 
2436   capitalize_header_name (line);
2437   p = strchr (line, ':');
2438   if (!p)
2439     return GPG_ERR_PROTOCOL_VIOLATION;
2440   *p++ = 0;
2441   while (*p == ' ' || *p == '\t')
2442     p++;
2443   value = p;
2444 
2445   for (h=hd->headers; h; h = h->next)
2446     if ( !strcmp (h->name, line) )
2447       break;
2448   if (h)
2449     {
2450       /* We have already seen a line with that name.  Thus we assume
2451        * it is a comma separated list and merge them.  */
2452       p = strconcat (h->value, ",", value, NULL);
2453       if (!p)
2454         return gpg_err_code_from_syserror ();
2455       xfree (h->value);
2456       h->value = p;
2457       return 0;
2458     }
2459 
2460   /* Append a new header. */
2461   h = xtrymalloc (sizeof *h + strlen (line));
2462   if (!h)
2463     return gpg_err_code_from_syserror ();
2464   strcpy (h->name, line);
2465   h->value = xtrymalloc (strlen (value)+1);
2466   if (!h->value)
2467     {
2468       xfree (h);
2469       return gpg_err_code_from_syserror ();
2470     }
2471   strcpy (h->value, value);
2472   h->next = hd->headers;
2473   hd->headers = h;
2474 
2475   return 0;
2476 }
2477 
2478 
2479 /* Return the header NAME from the last response.  The returned value
2480    is valid as along as HD has not been closed and no other request
2481    has been send. If the header was not found, NULL is returned.  NAME
2482    must be canonicalized, that is the first letter of each dash
2483    delimited part must be uppercase and all other letters lowercase.  */
2484 const char *
http_get_header(http_t hd,const char * name)2485 http_get_header (http_t hd, const char *name)
2486 {
2487   header_t h;
2488 
2489   for (h=hd->headers; h; h = h->next)
2490     if ( !strcmp (h->name, name) )
2491       return h->value;
2492   return NULL;
2493 }
2494 
2495 
2496 /* Return a newly allocated and NULL terminated array with pointers to
2497    header names.  The array must be released with xfree() and its
2498    content is only values as long as no other request has been
2499    send.  */
2500 const char **
http_get_header_names(http_t hd)2501 http_get_header_names (http_t hd)
2502 {
2503   const char **array;
2504   size_t n;
2505   header_t h;
2506 
2507   for (n=0, h = hd->headers; h; h = h->next)
2508     n++;
2509   array = xtrycalloc (n+1, sizeof *array);
2510   if (array)
2511     {
2512       for (n=0, h = hd->headers; h; h = h->next)
2513         array[n++] = h->name;
2514     }
2515 
2516   return array;
2517 }
2518 
2519 
2520 /*
2521  * Parse the response from a server.
2522  * Returns: Errorcode and sets some files in the handle
2523  */
2524 static gpg_err_code_t
parse_response(http_t hd)2525 parse_response (http_t hd)
2526 {
2527   char *line, *p, *p2;
2528   size_t maxlen, len;
2529   cookie_t cookie = hd->read_cookie;
2530   const char *s;
2531 
2532   /* Delete old header lines.  */
2533   while (hd->headers)
2534     {
2535       header_t tmp = hd->headers->next;
2536       xfree (hd->headers->value);
2537       xfree (hd->headers);
2538       hd->headers = tmp;
2539     }
2540 
2541   /* Wait for the status line. */
2542   do
2543     {
2544       maxlen = MAX_LINELEN;
2545       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2546       line = hd->buffer;
2547       if (!line)
2548 	return gpg_err_code_from_syserror (); /* Out of core. */
2549       if (!maxlen)
2550 	return GPG_ERR_TRUNCATED; /* Line has been truncated. */
2551       if (!len)
2552 	return GPG_ERR_EOF;
2553 
2554       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2555         log_debug_string (line, "http.c:response:\n");
2556     }
2557   while (!*line);
2558 
2559   if ((p = strchr (line, '/')))
2560     *p++ = 0;
2561   if (!p || strcmp (line, "HTTP"))
2562     return 0; /* Assume http 0.9. */
2563 
2564   if ((p2 = strpbrk (p, " \t")))
2565     {
2566       *p2++ = 0;
2567       p2 += strspn (p2, " \t");
2568     }
2569   if (!p2)
2570     return 0; /* Also assume http 0.9. */
2571   p = p2;
2572   /* TODO: Add HTTP version number check. */
2573   if ((p2 = strpbrk (p, " \t")))
2574     *p2++ = 0;
2575   if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1])
2576       || !isdigit ((unsigned int)p[2]) || p[3])
2577     {
2578       /* Malformed HTTP status code - assume http 0.9. */
2579       hd->is_http_0_9 = 1;
2580       hd->status_code = 200;
2581       return 0;
2582     }
2583   hd->status_code = atoi (p);
2584 
2585   /* Skip all the header lines and wait for the empty line. */
2586   do
2587     {
2588       maxlen = MAX_LINELEN;
2589       len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
2590       line = hd->buffer;
2591       if (!line)
2592 	return gpg_err_code_from_syserror (); /* Out of core. */
2593       /* Note, that we can silently ignore truncated lines. */
2594       if (!len)
2595 	return GPG_ERR_EOF;
2596       /* Trim line endings of empty lines. */
2597       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
2598 	*line = 0;
2599       if (opt_debug || (hd->flags & HTTP_FLAG_LOG_RESP))
2600         log_info ("http.c:RESP: '%.*s'\n",
2601                   (int)strlen(line)-(*line&&line[1]?2:0),line);
2602       if (*line)
2603         {
2604           gpg_err_code_t ec = store_header (hd, line);
2605           if (ec)
2606             return ec;
2607         }
2608     }
2609   while (len && *line);
2610 
2611   cookie->content_length_valid = 0;
2612   if (!(hd->flags & HTTP_FLAG_IGNORE_CL))
2613     {
2614       s = http_get_header (hd, "Content-Length");
2615       if (s)
2616         {
2617           cookie->content_length_valid = 1;
2618           cookie->content_length = string_to_u64 (s);
2619         }
2620     }
2621 
2622   return 0;
2623 }
2624 
2625 #if 0
2626 static int
2627 start_server ()
2628 {
2629   struct sockaddr_in mya;
2630   struct sockaddr_in peer;
2631   int fd, client;
2632   fd_set rfds;
2633   int addrlen;
2634   int i;
2635 
2636   if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
2637     {
2638       log_error ("socket() failed: %s\n", strerror (errno));
2639       return -1;
2640     }
2641   i = 1;
2642   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i)))
2643     log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno));
2644 
2645   mya.sin_family = AF_INET;
2646   memset (&mya.sin_addr, 0, sizeof (mya.sin_addr));
2647   mya.sin_port = htons (11371);
2648 
2649   if (bind (fd, (struct sockaddr *) &mya, sizeof (mya)))
2650     {
2651       log_error ("bind to port 11371 failed: %s\n", strerror (errno));
2652       sock_close (fd);
2653       return -1;
2654     }
2655 
2656   if (listen (fd, 5))
2657     {
2658       log_error ("listen failed: %s\n", strerror (errno));
2659       sock_close (fd);
2660       return -1;
2661     }
2662 
2663   for (;;)
2664     {
2665       FD_ZERO (&rfds);
2666       FD_SET (fd, &rfds);
2667 
2668       if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0)
2669 	continue;		/* ignore any errors */
2670 
2671       if (!FD_ISSET (fd, &rfds))
2672 	continue;
2673 
2674       addrlen = sizeof peer;
2675       client = my_accept (fd, (struct sockaddr *) &peer, &addrlen);
2676       if (client == -1)
2677 	continue;		/* oops */
2678 
2679       log_info ("connect from %s\n", inet_ntoa (peer.sin_addr));
2680 
2681       fflush (stdout);
2682       fflush (stderr);
2683       if (!fork ())
2684 	{
2685 	  int c;
2686 	  FILE *fp;
2687 
2688 	  fp = fdopen (client, "r");
2689 	  while ((c = getc (fp)) != EOF)
2690 	    putchar (c);
2691 	  fclose (fp);
2692 	  exit (0);
2693 	}
2694       sock_close (client);
2695     }
2696 
2697 
2698   return 0;
2699 }
2700 #endif
2701 
2702 
2703 
2704 /* Return true if SOCKS shall be used.  This is the case if tor_mode
2705  * is enabled and the desired address is not the loopback address.
2706  * This function is basically a copy of the same internal function in
2707  * Libassuan.  */
2708 static int
use_socks(struct sockaddr_storage * addr)2709 use_socks (struct sockaddr_storage *addr)
2710 {
2711   int mode;
2712 
2713   if (assuan_sock_get_flag (ASSUAN_INVALID_FD, "tor-mode", &mode) || !mode)
2714     return 0;  /* Not in Tor mode.  */
2715   else if (addr->ss_family == AF_INET6)
2716     {
2717       struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
2718       const unsigned char *s;
2719       int i;
2720 
2721       s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
2722       if (s[15] != 1)
2723         return 1;   /* Last octet is not 1 - not the loopback address.  */
2724       for (i=0; i < 15; i++, s++)
2725         if (*s)
2726           return 1; /* Non-zero octet found - not the loopback address.  */
2727 
2728       return 0; /* This is the loopback address.  */
2729     }
2730   else if (addr->ss_family == AF_INET)
2731     {
2732       struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
2733 
2734       if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
2735         return 0; /* Loopback (127.0.0.0/8) */
2736 
2737       return 1;
2738     }
2739   else
2740     return 0;
2741 }
2742 
2743 
2744 /* Wrapper around assuan_sock_new which takes the domain from an
2745  * address parameter.  */
2746 static assuan_fd_t
my_sock_new_for_addr(struct sockaddr_storage * addr,int type,int proto)2747 my_sock_new_for_addr (struct sockaddr_storage *addr, int type, int proto)
2748 {
2749   int domain;
2750 
2751   if (use_socks (addr))
2752     {
2753       /* Libassaun always uses 127.0.0.1 to connect to the socks
2754        * server (i.e. the Tor daemon).  */
2755       domain = AF_INET;
2756     }
2757   else
2758     domain = addr->ss_family;
2759 
2760   return assuan_sock_new (domain, type, proto);
2761 }
2762 
2763 
2764 /* Call WSAGetLastError and map it to a libgpg-error.  */
2765 #ifdef HAVE_W32_SYSTEM
2766 static gpg_error_t
my_wsagetlasterror(void)2767 my_wsagetlasterror (void)
2768 {
2769   int wsaerr;
2770   gpg_err_code_t ec;
2771 
2772   wsaerr = WSAGetLastError ();
2773   switch (wsaerr)
2774     {
2775     case WSAENOTSOCK:        ec = GPG_ERR_EINVAL;       break;
2776     case WSAEWOULDBLOCK:     ec = GPG_ERR_EAGAIN;       break;
2777     case ERROR_BROKEN_PIPE:  ec = GPG_ERR_EPIPE;        break;
2778     case WSANOTINITIALISED:  ec = GPG_ERR_ENOSYS;       break;
2779     case WSAENOBUFS:         ec = GPG_ERR_ENOBUFS;      break;
2780     case WSAEMSGSIZE:        ec = GPG_ERR_EMSGSIZE;     break;
2781     case WSAECONNREFUSED:    ec = GPG_ERR_ECONNREFUSED; break;
2782     case WSAEISCONN:         ec = GPG_ERR_EISCONN;      break;
2783     case WSAEALREADY:        ec = GPG_ERR_EALREADY;     break;
2784     case WSAETIMEDOUT:       ec = GPG_ERR_ETIMEDOUT;    break;
2785     default:                 ec = GPG_ERR_EIO;          break;
2786     }
2787 
2788   return gpg_err_make (default_errsource, ec);
2789 }
2790 #endif /*HAVE_W32_SYSTEM*/
2791 
2792 
2793 /* Connect SOCK and return GPG_ERR_ETIMEOUT if a connection could not
2794  * be established within TIMEOUT milliseconds.  0 indicates the
2795  * system's default timeout.  The other args are the usual connect
2796  * args.  On success 0 is returned, on timeout GPG_ERR_ETIMEDOUT, and
2797  * another error code for other errors.  On timeout the caller needs
2798  * to close the socket as soon as possible to stop an ongoing
2799  * handshake.
2800  *
2801  * This implementation is for well-behaving systems; see Stevens,
2802  * Network Programming, 2nd edition, Vol 1, 15.4.  */
2803 static gpg_error_t
connect_with_timeout(assuan_fd_t sock,struct sockaddr * addr,int addrlen,unsigned int timeout)2804 connect_with_timeout (assuan_fd_t sock,
2805                       struct sockaddr *addr, int addrlen,
2806                       unsigned int timeout)
2807 {
2808   gpg_error_t err;
2809   int syserr;
2810   socklen_t slen;
2811   fd_set rset, wset;
2812   struct timeval tval;
2813   int n;
2814 
2815 #ifndef HAVE_W32_SYSTEM
2816   int oflags;
2817 # define RESTORE_BLOCKING()  do {  \
2818     fcntl (sock, F_SETFL, oflags); \
2819   } while (0)
2820 #else /*HAVE_W32_SYSTEM*/
2821 # define RESTORE_BLOCKING()  do {                       \
2822     unsigned long along = 0;                            \
2823     ioctlsocket (FD2INT (sock), FIONBIO, &along);       \
2824   } while (0)
2825 #endif /*HAVE_W32_SYSTEM*/
2826 
2827 
2828   if (!timeout)
2829     {
2830       /* Shortcut.  */
2831       if (assuan_sock_connect (sock, addr, addrlen))
2832         err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2833       else
2834         err = 0;
2835       return err;
2836     }
2837 
2838   /* Switch the socket into non-blocking mode.  */
2839 #ifdef HAVE_W32_SYSTEM
2840   {
2841     unsigned long along = 1;
2842     if (ioctlsocket (FD2INT (sock), FIONBIO, &along))
2843       return my_wsagetlasterror ();
2844   }
2845 #else
2846   oflags = fcntl (sock, F_GETFL, 0);
2847   if (fcntl (sock, F_SETFL, oflags | O_NONBLOCK))
2848     return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2849 #endif
2850 
2851   /* Do the connect.  */
2852   if (!assuan_sock_connect (sock, addr, addrlen))
2853     {
2854       /* Immediate connect.  Restore flags. */
2855       RESTORE_BLOCKING ();
2856       return 0; /* Success.  */
2857     }
2858   err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2859   if (gpg_err_code (err) != GPG_ERR_EINPROGRESS
2860 #ifdef HAVE_W32_SYSTEM
2861       && gpg_err_code (err) != GPG_ERR_EAGAIN
2862 #endif
2863       )
2864     {
2865       RESTORE_BLOCKING ();
2866       return err;
2867     }
2868 
2869   FD_ZERO (&rset);
2870   FD_SET (FD2INT (sock), &rset);
2871   wset = rset;
2872   tval.tv_sec = timeout / 1000;
2873   tval.tv_usec = (timeout % 1000) * 1000;
2874 
2875   n = my_select (FD2INT(sock)+1, &rset, &wset, NULL, &tval);
2876   if (n < 0)
2877     {
2878       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2879       RESTORE_BLOCKING ();
2880       return err;
2881     }
2882   if (!n)
2883     {
2884       /* Timeout: We do not restore the socket flags on timeout
2885        * because the caller is expected to close the socket.  */
2886       return gpg_err_make (default_errsource, GPG_ERR_ETIMEDOUT);
2887     }
2888   if (!FD_ISSET (sock, &rset) && !FD_ISSET (sock, &wset))
2889     {
2890       /* select misbehaved.  */
2891       return gpg_err_make (default_errsource, GPG_ERR_SYSTEM_BUG);
2892     }
2893 
2894   slen = sizeof (syserr);
2895   if (getsockopt (FD2INT(sock), SOL_SOCKET, SO_ERROR,
2896                   (void*)&syserr, &slen) < 0)
2897     {
2898       /* Assume that this is Solaris which returns the error in ERRNO.  */
2899       err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2900     }
2901   else if (syserr)
2902     err = gpg_err_make (default_errsource, gpg_err_code_from_errno (syserr));
2903   else
2904     err = 0; /* Connected.  */
2905 
2906   RESTORE_BLOCKING ();
2907 
2908   return err;
2909 
2910 #undef RESTORE_BLOCKING
2911 }
2912 
2913 
2914 /* Actually connect to a server.  On success 0 is returned and the
2915  * file descriptor for the socket is stored at R_SOCK; on error an
2916  * error code is returned and ASSUAN_INVALID_FD is stored at R_SOCK.
2917  * TIMEOUT is the connect timeout in milliseconds.  Note that the
2918  * function tries to connect to all known addresses and the timeout is
2919  * for each one. */
2920 static gpg_error_t
connect_server(ctrl_t ctrl,const char * server,unsigned short port,unsigned int flags,const char * srvtag,unsigned int timeout,assuan_fd_t * r_sock)2921 connect_server (ctrl_t ctrl, const char *server, unsigned short port,
2922                 unsigned int flags, const char *srvtag, unsigned int timeout,
2923                 assuan_fd_t *r_sock)
2924 {
2925   gpg_error_t err;
2926   assuan_fd_t sock = ASSUAN_INVALID_FD;
2927   unsigned int srvcount = 0;
2928   int hostfound = 0;
2929   int anyhostaddr = 0;
2930   int srv, connected, v4_valid, v6_valid;
2931   gpg_error_t last_err = 0;
2932   struct srventry *serverlist = NULL;
2933 
2934   *r_sock = ASSUAN_INVALID_FD;
2935 
2936 #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP)
2937   init_sockets ();
2938 #endif /*Windows*/
2939 
2940   check_inet_support (&v4_valid, &v6_valid);
2941 
2942   /* Onion addresses require special treatment.  */
2943   if (is_onion_address (server))
2944     {
2945 #ifdef ASSUAN_SOCK_TOR
2946 
2947       if (opt_debug)
2948         log_debug ("http.c:connect_server:onion: name='%s' port=%hu\n",
2949                    server, port);
2950       sock = assuan_sock_connect_byname (server, port, 0, NULL,
2951                                          ASSUAN_SOCK_TOR);
2952       if (sock == ASSUAN_INVALID_FD)
2953         {
2954           err = gpg_err_make (default_errsource,
2955                               (errno == EHOSTUNREACH)? GPG_ERR_UNKNOWN_HOST
2956                               : gpg_err_code_from_syserror ());
2957           log_error ("can't connect to '%s': %s\n", server, gpg_strerror (err));
2958           return err;
2959         }
2960 
2961       notify_netactivity ();
2962       *r_sock = sock;
2963       return 0;
2964 
2965 #else /*!ASSUAN_SOCK_TOR*/
2966 
2967       err = gpg_err_make (default_errsource, GPG_ERR_ENETUNREACH);
2968       return ASSUAN_INVALID_FD;
2969 
2970 #endif /*!HASSUAN_SOCK_TOR*/
2971     }
2972 
2973   /* Do the SRV thing */
2974   if (srvtag)
2975     {
2976       err = get_dns_srv (ctrl, server, srvtag, NULL, &serverlist, &srvcount);
2977       if (err)
2978         log_info ("getting '%s' SRV for '%s' failed: %s\n",
2979                   srvtag, server, gpg_strerror (err));
2980       /* Note that on error SRVCOUNT is zero.  */
2981       err = 0;
2982     }
2983 
2984   if (!serverlist)
2985     {
2986       /* Either we're not using SRV, or the SRV lookup failed.  Make
2987 	 up a fake SRV record. */
2988       serverlist = xtrycalloc (1, sizeof *serverlist);
2989       if (!serverlist)
2990         return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
2991 
2992       serverlist->port = port;
2993       strncpy (serverlist->target, server, DIMof (struct srventry, target));
2994       serverlist->target[DIMof (struct srventry, target)-1] = '\0';
2995       srvcount = 1;
2996     }
2997 
2998   connected = 0;
2999   for (srv=0; srv < srvcount && !connected; srv++)
3000     {
3001       dns_addrinfo_t aibuf, ai;
3002 
3003       if (opt_debug)
3004         log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
3005                    serverlist[srv].target, port);
3006       err = resolve_dns_name (ctrl,
3007                               serverlist[srv].target, port, 0, SOCK_STREAM,
3008                               &aibuf, NULL);
3009       if (err)
3010         {
3011           log_info ("resolving '%s' failed: %s\n",
3012                     serverlist[srv].target, gpg_strerror (err));
3013           last_err = err;
3014           continue; /* Not found - try next one. */
3015         }
3016       hostfound = 1;
3017 
3018       for (ai = aibuf; ai && !connected; ai = ai->next)
3019         {
3020           if (ai->family == AF_INET
3021               && ((flags & HTTP_FLAG_IGNORE_IPv4) || !v4_valid))
3022             continue;
3023           if (ai->family == AF_INET6
3024               && ((flags & HTTP_FLAG_IGNORE_IPv6) || !v6_valid))
3025             continue;
3026 
3027           if (sock != ASSUAN_INVALID_FD)
3028             assuan_sock_close (sock);
3029           sock = my_sock_new_for_addr (ai->addr, ai->socktype, ai->protocol);
3030           if (sock == ASSUAN_INVALID_FD)
3031             {
3032               if (errno == EAFNOSUPPORT)
3033                 {
3034                   if (ai->family == AF_INET)
3035                     v4_valid = 0;
3036                   if (ai->family == AF_INET6)
3037                     v6_valid = 0;
3038                   continue;
3039                 }
3040 
3041               err = gpg_err_make (default_errsource,
3042                                   gpg_err_code_from_syserror ());
3043               log_error ("error creating socket: %s\n", gpg_strerror (err));
3044               free_dns_addrinfo (aibuf);
3045               xfree (serverlist);
3046               return err;
3047             }
3048 
3049           anyhostaddr = 1;
3050           err = connect_with_timeout (sock, (struct sockaddr *)ai->addr,
3051                                       ai->addrlen, timeout);
3052           if (err)
3053             {
3054               last_err = err;
3055             }
3056           else
3057             {
3058               connected = 1;
3059               notify_netactivity ();
3060             }
3061         }
3062       free_dns_addrinfo (aibuf);
3063     }
3064 
3065   xfree (serverlist);
3066 
3067   if (!connected)
3068     {
3069       if (!hostfound)
3070         log_error ("can't connect to '%s': %s\n",
3071                    server, "host not found");
3072       else if (!anyhostaddr)
3073         log_error ("can't connect to '%s': %s\n",
3074                    server, "no IP address for host");
3075       else
3076         {
3077 #ifdef HAVE_W32_SYSTEM
3078         log_error ("can't connect to '%s': ec=%d\n",
3079                    server, (int)WSAGetLastError());
3080 #else
3081         log_error ("can't connect to '%s': %s\n",
3082                    server, gpg_strerror (last_err));
3083 #endif
3084         }
3085       err = last_err? last_err : gpg_err_make (default_errsource,
3086                                                GPG_ERR_UNKNOWN_HOST);
3087       if (sock != ASSUAN_INVALID_FD)
3088 	assuan_sock_close (sock);
3089       return err;
3090     }
3091 
3092   *r_sock = sock;
3093   return 0;
3094 }
3095 
3096 
3097 /* Helper to read from a socket.  This handles npth things and
3098  * EINTR.  */
3099 static gpgrt_ssize_t
read_server(assuan_fd_t sock,void * buffer,size_t size)3100 read_server (assuan_fd_t sock, void *buffer, size_t size)
3101 {
3102   int nread;
3103 
3104   do
3105     {
3106 #ifdef HAVE_W32_SYSTEM
3107       /* Under Windows we need to use recv for a socket.  */
3108 # if defined(USE_NPTH)
3109       npth_unprotect ();
3110 # endif
3111       nread = recv (FD2INT (sock), buffer, size, 0);
3112 # if defined(USE_NPTH)
3113       npth_protect ();
3114 # endif
3115 
3116 #else /*!HAVE_W32_SYSTEM*/
3117 
3118 # ifdef USE_NPTH
3119       nread = npth_read (sock, buffer, size);
3120 # else
3121       nread = read (sock, buffer, size);
3122 # endif
3123 
3124 #endif /*!HAVE_W32_SYSTEM*/
3125     }
3126   while (nread == -1 && errno == EINTR);
3127 
3128   return nread;
3129 }
3130 
3131 
3132 static gpg_error_t
write_server(assuan_fd_t sock,const char * data,size_t length)3133 write_server (assuan_fd_t sock, const char *data, size_t length)
3134 {
3135   int nleft;
3136   int nwritten;
3137 
3138   nleft = length;
3139   while (nleft > 0)
3140     {
3141 #if defined(HAVE_W32_SYSTEM)
3142 # if defined(USE_NPTH)
3143       npth_unprotect ();
3144 # endif
3145       nwritten = send (FD2INT (sock), data, nleft, 0);
3146 # if defined(USE_NPTH)
3147       npth_protect ();
3148 # endif
3149       if ( nwritten == SOCKET_ERROR )
3150         {
3151           log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
3152           return gpg_error (GPG_ERR_NETWORK);
3153         }
3154 #else /*!HAVE_W32_SYSTEM*/
3155 # ifdef USE_NPTH
3156       nwritten = npth_write (sock, data, nleft);
3157 # else
3158       nwritten = write (sock, data, nleft);
3159 # endif
3160       if (nwritten == -1)
3161 	{
3162 	  if (errno == EINTR)
3163 	    continue;
3164 	  if (errno == EAGAIN)
3165 	    {
3166 	      struct timeval tv;
3167 
3168 	      tv.tv_sec = 0;
3169 	      tv.tv_usec = 50000;
3170 	      my_select (0, NULL, NULL, NULL, &tv);
3171 	      continue;
3172 	    }
3173 	  log_info ("network write failed: %s\n", strerror (errno));
3174 	  return gpg_error_from_syserror ();
3175 	}
3176 #endif /*!HAVE_W32_SYSTEM*/
3177       nleft -= nwritten;
3178       data += nwritten;
3179     }
3180 
3181   return 0;
3182 }
3183 
3184 
3185 
3186 /* Read handler for estream.  */
3187 static gpgrt_ssize_t
cookie_read(void * cookie,void * buffer,size_t size)3188 cookie_read (void *cookie, void *buffer, size_t size)
3189 {
3190   cookie_t c = cookie;
3191   int nread;
3192 
3193   if (c->content_length_valid)
3194     {
3195       if (!c->content_length)
3196         return 0; /* EOF */
3197       if (c->content_length < size)
3198         size = c->content_length;
3199     }
3200 
3201 #if HTTP_USE_NTBTLS
3202   if (c->use_tls && c->session && c->session->tls_session)
3203     {
3204       estream_t in, out;
3205 
3206       ntbtls_get_stream (c->session->tls_session, &in, &out);
3207       nread = es_fread (buffer, 1, size, in);
3208       if (opt_debug)
3209         log_debug ("TLS network read: %d/%zu\n", nread, size);
3210     }
3211   else
3212 #elif HTTP_USE_GNUTLS
3213   if (c->use_tls && c->session && c->session->tls_session)
3214     {
3215     again:
3216       nread = gnutls_record_recv (c->session->tls_session, buffer, size);
3217       if (nread < 0)
3218         {
3219           if (nread == GNUTLS_E_INTERRUPTED)
3220             goto again;
3221           if (nread == GNUTLS_E_AGAIN)
3222             {
3223               struct timeval tv;
3224 
3225               tv.tv_sec = 0;
3226               tv.tv_usec = 50000;
3227               my_select (0, NULL, NULL, NULL, &tv);
3228               goto again;
3229             }
3230           if (nread == GNUTLS_E_REHANDSHAKE)
3231             goto again; /* A client is allowed to just ignore this request. */
3232           if (nread == GNUTLS_E_PREMATURE_TERMINATION)
3233             {
3234               /* The server terminated the connection.  Close the TLS
3235                  session, and indicate EOF using a short read.  */
3236               close_tls_session (c->session);
3237               return 0;
3238             }
3239           log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
3240           gpg_err_set_errno (EIO);
3241           return -1;
3242         }
3243     }
3244   else
3245 #endif /*HTTP_USE_GNUTLS*/
3246     {
3247       nread = read_server (c->sock->fd, buffer, size);
3248     }
3249 
3250   if (c->content_length_valid && nread > 0)
3251     {
3252       if (nread < c->content_length)
3253         c->content_length -= nread;
3254       else
3255         c->content_length = 0;
3256     }
3257 
3258   return (gpgrt_ssize_t)nread;
3259 }
3260 
3261 /* Write handler for estream.  */
3262 static gpgrt_ssize_t
cookie_write(void * cookie,const void * buffer_arg,size_t size)3263 cookie_write (void *cookie, const void *buffer_arg, size_t size)
3264 {
3265   const char *buffer = buffer_arg;
3266   cookie_t c = cookie;
3267   int nwritten = 0;
3268 
3269 #if HTTP_USE_NTBTLS
3270   if (c->use_tls && c->session && c->session->tls_session)
3271     {
3272       estream_t in, out;
3273 
3274       ntbtls_get_stream (c->session->tls_session, &in, &out);
3275       if (size == 0)
3276         es_fflush (out);
3277       else
3278         nwritten = es_fwrite (buffer, 1, size, out);
3279       if (opt_debug)
3280         log_debug ("TLS network write: %d/%zu\n", nwritten, size);
3281     }
3282   else
3283 #elif HTTP_USE_GNUTLS
3284   if (c->use_tls && c->session && c->session->tls_session)
3285     {
3286       int nleft = size;
3287       while (nleft > 0)
3288         {
3289           nwritten = gnutls_record_send (c->session->tls_session,
3290                                          buffer, nleft);
3291           if (nwritten <= 0)
3292             {
3293               if (nwritten == GNUTLS_E_INTERRUPTED)
3294                 continue;
3295               if (nwritten == GNUTLS_E_AGAIN)
3296                 {
3297                   struct timeval tv;
3298 
3299                   tv.tv_sec = 0;
3300                   tv.tv_usec = 50000;
3301                   my_select (0, NULL, NULL, NULL, &tv);
3302                   continue;
3303                 }
3304               log_info ("TLS network write failed: %s\n",
3305                         gnutls_strerror (nwritten));
3306               gpg_err_set_errno (EIO);
3307               return -1;
3308             }
3309           nleft -= nwritten;
3310           buffer += nwritten;
3311         }
3312     }
3313   else
3314 #endif /*HTTP_USE_GNUTLS*/
3315     {
3316       if ( write_server (c->sock->fd, buffer, size) )
3317         {
3318           gpg_err_set_errno (EIO);
3319           nwritten = -1;
3320         }
3321       else
3322         nwritten = size;
3323     }
3324 
3325   return (gpgrt_ssize_t)nwritten;
3326 }
3327 
3328 
3329 #if defined(HAVE_W32_SYSTEM) && defined(HTTP_USE_NTBTLS)
3330 static gpgrt_ssize_t
simple_cookie_read(void * cookie,void * buffer,size_t size)3331 simple_cookie_read (void *cookie, void *buffer, size_t size)
3332 {
3333   assuan_fd_t sock = (assuan_fd_t)cookie;
3334   return read_server (sock, buffer, size);
3335 }
3336 
3337 static gpgrt_ssize_t
simple_cookie_write(void * cookie,const void * buffer_arg,size_t size)3338 simple_cookie_write (void *cookie, const void *buffer_arg, size_t size)
3339 {
3340   assuan_fd_t sock = (assuan_fd_t)cookie;
3341   const char *buffer = buffer_arg;
3342   int nwritten;
3343 
3344   if (write_server (sock, buffer, size))
3345     {
3346       gpg_err_set_errno (EIO);
3347       nwritten = -1;
3348     }
3349   else
3350     nwritten = size;
3351 
3352   return (gpgrt_ssize_t)nwritten;
3353 }
3354 #endif /*HAVE_W32_SYSTEM*/
3355 
3356 
3357 #ifdef HTTP_USE_GNUTLS
3358 /* Wrapper for gnutls_bye used by my_socket_unref.  */
3359 static void
send_gnutls_bye(void * opaque)3360 send_gnutls_bye (void *opaque)
3361 {
3362   tls_session_t tls_session = opaque;
3363   int ret;
3364 
3365  again:
3366   do
3367     ret = gnutls_bye (tls_session, GNUTLS_SHUT_RDWR);
3368   while (ret == GNUTLS_E_INTERRUPTED);
3369   if (ret == GNUTLS_E_AGAIN)
3370     {
3371       struct timeval tv;
3372 
3373       tv.tv_sec = 0;
3374       tv.tv_usec = 50000;
3375       my_select (0, NULL, NULL, NULL, &tv);
3376       goto again;
3377     }
3378 }
3379 #endif /*HTTP_USE_GNUTLS*/
3380 
3381 /* Close handler for estream.  */
3382 static int
cookie_close(void * cookie)3383 cookie_close (void *cookie)
3384 {
3385   cookie_t c = cookie;
3386 
3387   if (!c)
3388     return 0;
3389 
3390 #if HTTP_USE_NTBTLS
3391   if (c->use_tls && c->session && c->session->tls_session)
3392     {
3393       /* FIXME!! Possibly call ntbtls_close_notify for close
3394          of write stream.  */
3395       my_socket_unref (c->sock, NULL, NULL);
3396     }
3397   else
3398 #elif HTTP_USE_GNUTLS
3399   if (c->use_tls && c->session && c->session->tls_session)
3400     my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session);
3401   else
3402 #endif /*HTTP_USE_GNUTLS*/
3403     if (c->sock)
3404       my_socket_unref (c->sock, NULL, NULL);
3405 
3406   if (c->session)
3407     http_session_unref (c->session);
3408   xfree (c);
3409   return 0;
3410 }
3411 
3412 
3413 
3414 
3415 /* Verify the credentials of the server.  Returns 0 on success and
3416    store the result in the session object.  */
3417 gpg_error_t
http_verify_server_credentials(http_session_t sess)3418 http_verify_server_credentials (http_session_t sess)
3419 {
3420 #if HTTP_USE_GNUTLS
3421   static const char errprefix[] = "TLS verification of peer failed";
3422   int rc;
3423   unsigned int status;
3424   const char *hostname;
3425   const gnutls_datum_t *certlist;
3426   unsigned int certlistlen;
3427   gnutls_x509_crt_t cert;
3428   gpg_error_t err = 0;
3429 
3430   sess->verify.done = 1;
3431   sess->verify.status = 0;
3432   sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR;
3433 
3434   if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509)
3435     {
3436       log_error ("%s: %s\n", errprefix, "not an X.509 certificate");
3437       sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
3438       return gpg_error (GPG_ERR_GENERAL);
3439     }
3440 
3441   rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status);
3442   if (rc)
3443     {
3444       log_error ("%s: %s\n", errprefix, gnutls_strerror (rc));
3445       if (!err)
3446         err = gpg_error (GPG_ERR_GENERAL);
3447     }
3448   else if (status)
3449     {
3450       log_error ("%s: status=0x%04x\n", errprefix, status);
3451 #if GNUTLS_VERSION_NUMBER >= 0x030104
3452       {
3453         gnutls_datum_t statusdat;
3454 
3455         if (!gnutls_certificate_verification_status_print
3456             (status, GNUTLS_CRT_X509, &statusdat, 0))
3457           {
3458             log_info ("%s: %s\n", errprefix, statusdat.data);
3459             gnutls_free (statusdat.data);
3460           }
3461       }
3462 #endif /*gnutls >= 3.1.4*/
3463 
3464       sess->verify.status = status;
3465       if (!err)
3466         err = gpg_error (GPG_ERR_GENERAL);
3467     }
3468 
3469   hostname = sess->servername;
3470   if (!hostname || !strchr (hostname, '.'))
3471     {
3472       log_error ("%s: %s\n", errprefix, "hostname missing");
3473       if (!err)
3474         err = gpg_error (GPG_ERR_GENERAL);
3475     }
3476 
3477   certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen);
3478   if (!certlistlen)
3479     {
3480       log_error ("%s: %s\n", errprefix, "server did not send a certificate");
3481       if (!err)
3482         err = gpg_error (GPG_ERR_GENERAL);
3483 
3484       /* Need to stop here.  */
3485       if (err)
3486         return err;
3487     }
3488 
3489   rc = gnutls_x509_crt_init (&cert);
3490   if (rc < 0)
3491     {
3492       if (!err)
3493         err = gpg_error (GPG_ERR_GENERAL);
3494       if (err)
3495         return err;
3496     }
3497 
3498   rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER);
3499   if (rc < 0)
3500     {
3501       log_error ("%s: %s: %s\n", errprefix, "error importing certificate",
3502                  gnutls_strerror (rc));
3503       if (!err)
3504         err = gpg_error (GPG_ERR_GENERAL);
3505     }
3506 
3507   if (!gnutls_x509_crt_check_hostname (cert, hostname))
3508     {
3509       log_error ("%s: %s\n", errprefix, "hostname does not match");
3510       if (!err)
3511         err = gpg_error (GPG_ERR_GENERAL);
3512     }
3513 
3514   gnutls_x509_crt_deinit (cert);
3515 
3516   if (!err)
3517     sess->verify.rc = 0;
3518 
3519   if (sess->cert_log_cb)
3520     {
3521       const void *bufarr[10];
3522       size_t buflenarr[10];
3523       size_t n;
3524 
3525       for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++)
3526         {
3527           bufarr[n] = certlist[n].data;
3528           buflenarr[n] = certlist[n].size;
3529         }
3530       bufarr[n] = NULL;
3531       buflenarr[n] = 0;
3532       sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr);
3533     }
3534 
3535   return err;
3536 #else /*!HTTP_USE_GNUTLS*/
3537   (void)sess;
3538   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
3539 #endif
3540 }
3541 
3542 
3543 /* Return the first query variable with the specified key.  If there
3544    is no such variable, return NULL.  */
3545 struct uri_tuple_s *
uri_query_lookup(parsed_uri_t uri,const char * key)3546 uri_query_lookup (parsed_uri_t uri, const char *key)
3547 {
3548   struct uri_tuple_s *t;
3549 
3550   for (t = uri->query; t; t = t->next)
3551     if (strcmp (t->name, key) == 0)
3552       return t;
3553 
3554   return NULL;
3555 }
3556 
3557 const char *
uri_query_value(parsed_uri_t url,const char * key)3558 uri_query_value (parsed_uri_t url, const char *key)
3559 {
3560   struct uri_tuple_s *t;
3561   t = uri_query_lookup (url, key);
3562   return t? t->value : NULL;
3563 }
3564 
3565 
3566 
3567 /* Return true if both URI point to the same host for the purpose of
3568  * redirection check.  A is the original host and B the host given in
3569  * the Location header.  As a temporary workaround a fixed list of
3570  * exceptions is also consulted.  */
3571 static int
same_host_p(parsed_uri_t a,parsed_uri_t b)3572 same_host_p (parsed_uri_t a, parsed_uri_t b)
3573 {
3574   static struct
3575   {
3576     const char *from;  /* NULL uses the last entry from the table.  */
3577     const char *to;
3578   } allow[] =
3579   {
3580     { "protonmail.com", "api.protonmail.com" },
3581     { NULL,             "api.protonmail.ch"  },
3582     { "protonmail.ch",  "api.protonmail.com" },
3583     { NULL,             "api.protonmail.ch"  },
3584     { "pm.me",          "api.protonmail.ch"  }
3585   };
3586   static const char *subdomains[] =
3587     {
3588       "openpgpkey."
3589     };
3590   int i;
3591   const char *from;
3592 
3593   if (!a->host || !b->host)
3594     return 0;
3595 
3596   if (!ascii_strcasecmp (a->host, b->host))
3597     return 1;
3598 
3599   from = NULL;
3600   for (i=0; i < DIM (allow); i++)
3601     {
3602       if (allow[i].from)
3603         from = allow[i].from;
3604       if (!from)
3605         continue;
3606       if (!ascii_strcasecmp (from, a->host)
3607           && !ascii_strcasecmp (allow[i].to, b->host))
3608         return 1;
3609     }
3610 
3611   /* Also consider hosts the same if they differ only in a subdomain;
3612    * in both direction.  This allows to have redirection between the
3613    * WKD advanced and direct lookup methods. */
3614   for (i=0; i < DIM (subdomains); i++)
3615     {
3616       const char *subdom = subdomains[i];
3617       size_t subdomlen = strlen (subdom);
3618 
3619       if (!ascii_strncasecmp (a->host, subdom, subdomlen)
3620           && !ascii_strcasecmp (a->host + subdomlen, b->host))
3621         return 1;
3622       if (!ascii_strncasecmp (b->host, subdom, subdomlen)
3623           && !ascii_strcasecmp (b->host + subdomlen, a->host))
3624         return 1;
3625     }
3626 
3627   return 0;
3628 }
3629 
3630 
3631 /* Prepare a new URL for a HTTP redirect.  INFO has flags controlling
3632  * the operation, STATUS_CODE is used for diagnostics, LOCATION is the
3633  * value of the "Location" header, and R_URL reveives the new URL on
3634  * success or NULL or error.  Note that INFO->ORIG_URL is
3635  * required.  */
3636 gpg_error_t
http_prepare_redirect(http_redir_info_t * info,unsigned int status_code,const char * location,char ** r_url)3637 http_prepare_redirect (http_redir_info_t *info, unsigned int status_code,
3638                        const char *location, char **r_url)
3639 {
3640   gpg_error_t err;
3641   parsed_uri_t locuri;
3642   parsed_uri_t origuri;
3643   char *newurl;
3644   char *p;
3645 
3646   *r_url = NULL;
3647 
3648   if (!info || !info->orig_url)
3649     return gpg_error (GPG_ERR_INV_ARG);
3650 
3651   if (!info->silent)
3652     log_info (_("URL '%s' redirected to '%s' (%u)\n"),
3653               info->orig_url, location? location:"[none]", status_code);
3654 
3655   if (!info->redirects_left)
3656     {
3657       if (!info->silent)
3658         log_error (_("too many redirections\n"));
3659       return gpg_error (GPG_ERR_NO_DATA);
3660     }
3661   info->redirects_left--;
3662 
3663   if (!location || !*location)
3664     return gpg_error (GPG_ERR_NO_DATA);
3665 
3666   err = http_parse_uri (&locuri, location, 0);
3667   if (err)
3668     return err;
3669 
3670   /* Make sure that an onion address only redirects to another
3671    * onion address, or that a https address only redirects to a
3672    * https address. */
3673   if (info->orig_onion && !locuri->onion)
3674     {
3675       dirmngr_status_printf (info->ctrl, "WARNING",
3676                              "http_redirect %u"
3677                              " redirect from onion to non-onion address"
3678                              " rejected",
3679                              err);
3680       http_release_parsed_uri (locuri);
3681       return gpg_error (GPG_ERR_FORBIDDEN);
3682     }
3683   if (!info->allow_downgrade && info->orig_https && !locuri->use_tls)
3684     {
3685       err = gpg_error (GPG_ERR_FORBIDDEN);
3686       dirmngr_status_printf (info->ctrl, "WARNING",
3687                              "http_redirect %u"
3688                              " redirect '%s' to '%s' rejected",
3689                              err, info->orig_url, location);
3690       http_release_parsed_uri (locuri);
3691       return err;
3692     }
3693 
3694   if (info->trust_location)
3695     {
3696       /* We trust the Location - return it verbatim.  */
3697       http_release_parsed_uri (locuri);
3698       newurl = xtrystrdup (location);
3699       if (!newurl)
3700         {
3701           err = gpg_error_from_syserror ();
3702           return err;
3703         }
3704     }
3705   else if ((err = http_parse_uri (&origuri, info->orig_url, 0)))
3706     {
3707       http_release_parsed_uri (locuri);
3708       return err;
3709     }
3710   else if (same_host_p (origuri, locuri))
3711     {
3712       /* The host is the same or on an exception list and thus we can
3713        * take the location verbatim.  */
3714       http_release_parsed_uri (origuri);
3715       http_release_parsed_uri (locuri);
3716       newurl = xtrystrdup (location);
3717       if (!newurl)
3718         {
3719           err = gpg_error_from_syserror ();
3720           return err;
3721         }
3722     }
3723   else
3724     {
3725       /* We take only the host and port from the URL given in the
3726        * Location.  This limits the effects of redirection attacks by
3727        * rogue hosts returning an URL to servers in the client's own
3728        * network.  We don't even include the userinfo because they
3729        * should be considered similar to the path and query parts.
3730        */
3731       if (!(locuri->off_path - locuri->off_host))
3732         {
3733           http_release_parsed_uri (origuri);
3734           http_release_parsed_uri (locuri);
3735           return gpg_error (GPG_ERR_BAD_URI);
3736         }
3737       if (!(origuri->off_path - origuri->off_host))
3738         {
3739           http_release_parsed_uri (origuri);
3740           http_release_parsed_uri (locuri);
3741           return gpg_error (GPG_ERR_BAD_URI);
3742         }
3743 
3744       newurl = xtrymalloc (strlen (origuri->original)
3745                            + (locuri->off_path - locuri->off_host) + 1);
3746       if (!newurl)
3747         {
3748           err = gpg_error_from_syserror ();
3749           http_release_parsed_uri (origuri);
3750           http_release_parsed_uri (locuri);
3751           return err;
3752         }
3753       /* Build new URL from
3754        *   uriguri:  scheme userinfo ---- ---- path rest
3755        *   locuri:   ------ -------- host port ---- ----
3756        */
3757       p = newurl;
3758       memcpy (p, origuri->original, origuri->off_host);
3759       p += origuri->off_host;
3760       memcpy (p, locuri->original + locuri->off_host,
3761               (locuri->off_path - locuri->off_host));
3762       p += locuri->off_path - locuri->off_host;
3763       strcpy (p, origuri->original + origuri->off_path);
3764 
3765       http_release_parsed_uri (origuri);
3766       http_release_parsed_uri (locuri);
3767       if (!info->silent)
3768         log_info (_("redirection changed to '%s'\n"), newurl);
3769       dirmngr_status_printf (info->ctrl, "WARNING",
3770                              "http_redirect_cleanup %u"
3771                              " changed from '%s' to '%s'",
3772                              0, info->orig_url, newurl);
3773     }
3774 
3775   *r_url = newurl;
3776   return 0;
3777 }
3778 
3779 
3780 /* Return string describing the http STATUS.  Returns an empty string
3781  * for an unknown status.  */
3782 const char *
http_status2string(unsigned int status)3783 http_status2string (unsigned int status)
3784 {
3785   switch (status)
3786     {
3787     case 500: return "Internal Server Error";
3788     case 501: return "Not Implemented";
3789     case 502: return "Bad Gateway";
3790     case 503: return "Service Unavailable";
3791     case 504: return "Gateway Timeout";
3792     case 505: return "HTTP version Not Supported";
3793     case 506: return "Variant Also Negation";
3794     case 507: return "Insufficient Storage";
3795     case 508: return "Loop Detected";
3796     case 510: return "Not Extended";
3797     case 511: return "Network Authentication Required";
3798     }
3799 
3800   return "";
3801 }
3802