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