xref: /dragonfly/lib/libfetch/common.c (revision 926ea7d70a29c7feb20ceda5c70ca1ab4a173250)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1998-2016 Dag-Erling Smørgrav
5  * Copyright (c) 2013 Michael Gmelin <freebsd@grem.de>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer
13  *    in this position and unchanged.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD: head/lib/libfetch/common.c 358227 2020-02-21 18:21:57Z kevans
32  */
33 
34 #include <sys/cdefs.h>
35 
36 #include <sys/param.h>
37 #include <sys/socket.h>
38 #include <sys/time.h>
39 #include <sys/uio.h>
40 
41 #include <netinet/in.h>
42 
43 #include <ctype.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <inttypes.h>
47 #include <netdb.h>
48 #include <poll.h>
49 #include <pwd.h>
50 #include <stdarg.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <unistd.h>
55 
56 #ifdef WITH_SSL
57 #include <openssl/x509v3.h>
58 #endif
59 
60 #include "fetch.h"
61 #include "common.h"
62 
63 
64 /*** Local data **************************************************************/
65 
66 /*
67  * Error messages for resolver errors
68  */
69 static struct fetcherr netdb_errlist[] = {
70 #ifdef EAI_NODATA
71           { EAI_NODATA,       FETCH_RESOLV,       "Host not found" },
72 #endif
73           { EAI_AGAIN,        FETCH_TEMP,         "Transient resolver failure" },
74           { EAI_FAIL,         FETCH_RESOLV,       "Non-recoverable resolver failure" },
75           { EAI_NONAME,       FETCH_RESOLV,       "No address record" },
76           { -1,               FETCH_UNKNOWN,      "Unknown resolver error" }
77 };
78 
79 /*
80  * SOCKS5 error enumerations
81  */
82 enum SOCKS5_ERR {
83 /* Protocol errors */
84           SOCKS5_ERR_SELECTION,
85           SOCKS5_ERR_READ_METHOD,
86           SOCKS5_ERR_VER5_ONLY,
87           SOCKS5_ERR_NOMETHODS,
88           SOCKS5_ERR_NOTIMPLEMENTED,
89           SOCKS5_ERR_HOSTNAME_SIZE,
90           SOCKS5_ERR_REQUEST,
91           SOCKS5_ERR_REPLY,
92           SOCKS5_ERR_NON_VER5_RESP,
93           SOCKS5_ERR_GENERAL,
94           SOCKS5_ERR_NOT_ALLOWED,
95           SOCKS5_ERR_NET_UNREACHABLE,
96           SOCKS5_ERR_HOST_UNREACHABLE,
97           SOCKS5_ERR_CONN_REFUSED,
98           SOCKS5_ERR_TTL_EXPIRED,
99           SOCKS5_ERR_COM_UNSUPPORTED,
100           SOCKS5_ERR_ADDR_UNSUPPORTED,
101           SOCKS5_ERR_UNSPECIFIED,
102 /* Configuration errors */
103           SOCKS5_ERR_BAD_HOST,
104           SOCKS5_ERR_BAD_PROXY_FORMAT,
105           SOCKS5_ERR_BAD_PORT
106 };
107 
108 /*
109  * Error messages for SOCKS5 errors
110  */
111 static struct fetcherr socks5_errlist[] = {
112 /* SOCKS5 protocol errors */
113           { SOCKS5_ERR_SELECTION,                 FETCH_ABORT,        "SOCKS5: Failed to send selection method" },
114           { SOCKS5_ERR_READ_METHOD,     FETCH_ABORT,        "SOCKS5: Failed to read method" },
115           { SOCKS5_ERR_VER5_ONLY,                 FETCH_PROTO,        "SOCKS5: Only version 5 is implemented" },
116           { SOCKS5_ERR_NOMETHODS,                 FETCH_PROTO,        "SOCKS5: No acceptable methods" },
117           { SOCKS5_ERR_NOTIMPLEMENTED,  FETCH_PROTO,        "SOCKS5: Method currently not implemented" },
118           { SOCKS5_ERR_HOSTNAME_SIZE,   FETCH_PROTO,        "SOCKS5: Hostname size is above 256 bytes" },
119           { SOCKS5_ERR_REQUEST,                   FETCH_PROTO,        "SOCKS5: Failed to request" },
120           { SOCKS5_ERR_REPLY,           FETCH_PROTO,        "SOCKS5: Failed to receive reply" },
121           { SOCKS5_ERR_NON_VER5_RESP,   FETCH_PROTO,        "SOCKS5: Server responded with a non-version 5 response" },
122           { SOCKS5_ERR_GENERAL,                   FETCH_ABORT,        "SOCKS5: General server failure" },
123           { SOCKS5_ERR_NOT_ALLOWED,     FETCH_AUTH,         "SOCKS5: Connection not allowed by ruleset" },
124           { SOCKS5_ERR_NET_UNREACHABLE, FETCH_NETWORK,      "SOCKS5: Network unreachable" },
125           { SOCKS5_ERR_HOST_UNREACHABLE,          FETCH_ABORT,        "SOCKS5: Host unreachable" },
126           { SOCKS5_ERR_CONN_REFUSED,    FETCH_ABORT,        "SOCKS5: Connection refused" },
127           { SOCKS5_ERR_TTL_EXPIRED,     FETCH_TIMEOUT,      "SOCKS5: TTL expired" },
128           { SOCKS5_ERR_COM_UNSUPPORTED, FETCH_PROTO,        "SOCKS5: Command not supported" },
129           { SOCKS5_ERR_ADDR_UNSUPPORTED,          FETCH_ABORT,        "SOCKS5: Address type not supported" },
130           { SOCKS5_ERR_UNSPECIFIED,     FETCH_UNKNOWN,      "SOCKS5: Unspecified error" },
131 /* Configuration error */
132           { SOCKS5_ERR_BAD_HOST,                  FETCH_ABORT,        "SOCKS5: Bad proxy host" },
133           { SOCKS5_ERR_BAD_PROXY_FORMAT,          FETCH_ABORT,        "SOCKS5: Bad proxy format" },
134           { SOCKS5_ERR_BAD_PORT,                  FETCH_ABORT,        "SOCKS5: Bad port" }
135 };
136 
137 /* End-of-Line */
138 static const char ENDL[2] = "\r\n";
139 
140 
141 /*** Error-reporting functions ***********************************************/
142 
143 /*
144  * Map error code to string
145  */
146 static struct fetcherr *
fetch_finderr(struct fetcherr * p,int e)147 fetch_finderr(struct fetcherr *p, int e)
148 {
149           while (p->num != -1 && p->num != e)
150                     p++;
151           return (p);
152 }
153 
154 /*
155  * Set error code
156  */
157 void
fetch_seterr(struct fetcherr * p,int e)158 fetch_seterr(struct fetcherr *p, int e)
159 {
160           p = fetch_finderr(p, e);
161           fetchLastErrCode = p->cat;
162           snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string);
163 }
164 
165 /*
166  * Set error code according to errno
167  */
168 void
fetch_syserr(void)169 fetch_syserr(void)
170 {
171           switch (errno) {
172           case 0:
173                     fetchLastErrCode = FETCH_OK;
174                     break;
175           case EPERM:
176           case EACCES:
177           case EROFS:
178           case EAUTH:
179           case ENEEDAUTH:
180                     fetchLastErrCode = FETCH_AUTH;
181                     break;
182           case ENOENT:
183           case EISDIR: /* XXX */
184                     fetchLastErrCode = FETCH_UNAVAIL;
185                     break;
186           case ENOMEM:
187                     fetchLastErrCode = FETCH_MEMORY;
188                     break;
189           case EBUSY:
190           case EAGAIN:
191                     fetchLastErrCode = FETCH_TEMP;
192                     break;
193           case EEXIST:
194                     fetchLastErrCode = FETCH_EXISTS;
195                     break;
196           case ENOSPC:
197                     fetchLastErrCode = FETCH_FULL;
198                     break;
199           case EADDRINUSE:
200           case EADDRNOTAVAIL:
201           case ENETDOWN:
202           case ENETUNREACH:
203           case ENETRESET:
204           case EHOSTUNREACH:
205                     fetchLastErrCode = FETCH_NETWORK;
206                     break;
207           case ECONNABORTED:
208           case ECONNRESET:
209                     fetchLastErrCode = FETCH_ABORT;
210                     break;
211           case ETIMEDOUT:
212                     fetchLastErrCode = FETCH_TIMEOUT;
213                     break;
214           case ECONNREFUSED:
215           case EHOSTDOWN:
216                     fetchLastErrCode = FETCH_DOWN;
217                     break;
218           default:
219                     fetchLastErrCode = FETCH_UNKNOWN;
220           }
221           snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
222 }
223 
224 
225 /*
226  * Emit status message
227  */
228 void
fetch_info(const char * fmt,...)229 fetch_info(const char *fmt, ...)
230 {
231           va_list ap;
232 
233           va_start(ap, fmt);
234           vfprintf(stderr, fmt, ap);
235           va_end(ap);
236           fputc('\n', stderr);
237 }
238 
239 
240 /*** Network-related utility functions ***************************************/
241 
242 /*
243  * Return the default port for a scheme
244  */
245 int
fetch_default_port(const char * scheme)246 fetch_default_port(const char *scheme)
247 {
248           struct servent *se;
249 
250           if ((se = getservbyname(scheme, "tcp")) != NULL)
251                     return (ntohs(se->s_port));
252           if (strcmp(scheme, SCHEME_FTP) == 0)
253                     return (FTP_DEFAULT_PORT);
254           if (strcmp(scheme, SCHEME_HTTP) == 0)
255                     return (HTTP_DEFAULT_PORT);
256           return (0);
257 }
258 
259 /*
260  * Return the default proxy port for a scheme
261  */
262 int
fetch_default_proxy_port(const char * scheme)263 fetch_default_proxy_port(const char *scheme)
264 {
265           if (strcmp(scheme, SCHEME_FTP) == 0)
266                     return (FTP_DEFAULT_PROXY_PORT);
267           if (strcmp(scheme, SCHEME_HTTP) == 0)
268                     return (HTTP_DEFAULT_PROXY_PORT);
269           return (0);
270 }
271 
272 
273 /*
274  * Create a connection for an existing descriptor.
275  */
276 conn_t *
fetch_reopen(int sd)277 fetch_reopen(int sd)
278 {
279           conn_t *conn;
280           int opt = 1;
281 
282           /* allocate and fill connection structure */
283           if ((conn = calloc(1, sizeof(*conn))) == NULL)
284                     return (NULL);
285           fcntl(sd, F_SETFD, FD_CLOEXEC);
286           setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof opt);
287           conn->sd = sd;
288           ++conn->ref;
289           return (conn);
290 }
291 
292 
293 /*
294  * Bump a connection's reference count.
295  */
296 conn_t *
fetch_ref(conn_t * conn)297 fetch_ref(conn_t *conn)
298 {
299 
300           ++conn->ref;
301           return (conn);
302 }
303 
304 
305 /*
306  * Resolve an address
307  */
308 struct addrinfo *
fetch_resolve(const char * addr,int port,int af)309 fetch_resolve(const char *addr, int port, int af)
310 {
311           char hbuf[256], sbuf[8];
312           struct addrinfo hints, *res;
313           const char *hb, *he, *sep;
314           const char *host, *service;
315           int err, len;
316 
317           /* first, check for a bracketed IPv6 address */
318           if (*addr == '[') {
319                     hb = addr + 1;
320                     if ((sep = strchr(hb, ']')) == NULL) {
321                               errno = EINVAL;
322                               goto syserr;
323                     }
324                     he = sep++;
325           } else {
326                     hb = addr;
327                     sep = strchrnul(hb, ':');
328                     he = sep;
329           }
330 
331           /* see if we need to copy the host name */
332           if (*he != '\0') {
333                     len = snprintf(hbuf, sizeof(hbuf),
334                         "%.*s", (int)(he - hb), hb);
335                     if (len < 0)
336                               goto syserr;
337                     if (len >= (int)sizeof(hbuf)) {
338                               errno = ENAMETOOLONG;
339                               goto syserr;
340                     }
341                     host = hbuf;
342           } else {
343                     host = hb;
344           }
345 
346           /* was it followed by a service name? */
347           if (*sep == '\0' && port != 0) {
348                     if (port < 1 || port > 65535) {
349                               errno = EINVAL;
350                               goto syserr;
351                     }
352                     if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0)
353                               goto syserr;
354                     service = sbuf;
355           } else if (*sep != '\0') {
356                     service = sep + 1;
357           } else {
358                     service = NULL;
359           }
360 
361           /* resolve */
362           memset(&hints, 0, sizeof(hints));
363           hints.ai_family = af;
364           hints.ai_socktype = SOCK_STREAM;
365           hints.ai_flags = AI_ADDRCONFIG;
366           if ((err = getaddrinfo(host, service, &hints, &res)) != 0) {
367                     netdb_seterr(err);
368                     return (NULL);
369           }
370           return (res);
371 syserr:
372           fetch_syserr();
373           return (NULL);
374 }
375 
376 
377 /*
378  * Bind a socket to a specific local address
379  */
380 int
fetch_bind(int sd,int af,const char * addr)381 fetch_bind(int sd, int af, const char *addr)
382 {
383           struct addrinfo *cliai, *ai;
384           int err;
385 
386           if ((cliai = fetch_resolve(addr, 0, af)) == NULL)
387                     return (-1);
388           for (ai = cliai; ai != NULL; ai = ai->ai_next)
389                     if ((err = bind(sd, ai->ai_addr, ai->ai_addrlen)) == 0)
390                               break;
391           if (err != 0)
392                     fetch_syserr();
393           freeaddrinfo(cliai);
394           return (err == 0 ? 0 : -1);
395 }
396 
397 
398 /*
399  * SOCKS5 connection initiation, based on RFC 1928
400  * Default DNS resolution over SOCKS5
401  */
402 int
fetch_socks5_init(conn_t * conn,const char * host,int port,int verbose)403 fetch_socks5_init(conn_t *conn, const char *host, int port, int verbose)
404 {
405           /*
406            * Size is based on largest packet prefix (4 bytes) +
407            * Largest FQDN (256) + one byte size (1) +
408            * Port (2)
409            */
410           unsigned char buf[BUFF_SIZE];
411           unsigned char *ptr;
412           int ret = 1;
413 
414           if (verbose)
415                     fetch_info("Initializing SOCKS5 connection: %s:%d", host, port);
416 
417           /* Connection initialization */
418           ptr = buf;
419           *ptr++ = SOCKS_VERSION_5;
420           *ptr++ = SOCKS_CONNECTION;
421           *ptr++ = SOCKS_RSV;
422 
423           if (fetch_write(conn, buf, 3) != 3) {
424                     ret = SOCKS5_ERR_SELECTION;
425                     goto fail;
426           }
427 
428           /* Verify response from SOCKS5 server */
429           if (fetch_read(conn, buf, 2) != 2) {
430                     ret = SOCKS5_ERR_READ_METHOD;
431                     goto fail;
432           }
433 
434           ptr = buf;
435           if (ptr[0] != SOCKS_VERSION_5) {
436                     ret = SOCKS5_ERR_VER5_ONLY;
437                     goto fail;
438           }
439           if (ptr[1] == SOCKS_NOMETHODS) {
440                     ret = SOCKS5_ERR_NOMETHODS;
441                     goto fail;
442           }
443           else if (ptr[1] != SOCKS5_NOTIMPLEMENTED) {
444                     ret = SOCKS5_ERR_NOTIMPLEMENTED;
445                     goto fail;
446           }
447 
448           /* Send Request */
449           *ptr++ = SOCKS_VERSION_5;
450           *ptr++ = SOCKS_CONNECTION;
451           *ptr++ = SOCKS_RSV;
452           /* Encode all targets as a hostname to avoid DNS leaks */
453           *ptr++ = SOCKS_ATYP_DOMAINNAME;
454           if (strlen(host) > FQDN_SIZE) {
455                     ret = SOCKS5_ERR_HOSTNAME_SIZE;
456                     goto fail;
457           }
458           *ptr++ = strlen(host);
459           strncpy(ptr, host, strlen(host));
460           ptr = ptr + strlen(host);
461 
462           port = htons(port);
463           *ptr++ = port & 0x00ff;
464           *ptr++ = (port & 0xff00) >> 8;
465 
466           if (fetch_write(conn, buf, ptr - buf) != ptr - buf) {
467                     ret = SOCKS5_ERR_REQUEST;
468                     goto fail;
469           }
470 
471           /* BND.ADDR is variable length, read the largest on non-blocking socket */
472           if (!fetch_read(conn, buf, BUFF_SIZE)) {
473                     ret = SOCKS5_ERR_REPLY;
474                     goto fail;
475           }
476 
477           ptr = buf;
478           if (*ptr++ != SOCKS_VERSION_5) {
479                     ret = SOCKS5_ERR_NON_VER5_RESP;
480                     goto fail;
481           }
482 
483           switch(*ptr++) {
484           case SOCKS_SUCCESS:
485                     break;
486           case SOCKS_GENERAL_FAILURE:
487                     ret = SOCKS5_ERR_GENERAL;
488                     goto fail;
489           case SOCKS_CONNECTION_NOT_ALLOWED:
490                     ret = SOCKS5_ERR_NOT_ALLOWED;
491                     goto fail;
492           case SOCKS_NETWORK_UNREACHABLE:
493                     ret = SOCKS5_ERR_NET_UNREACHABLE;
494                     goto fail;
495           case SOCKS_HOST_UNREACHABLE:
496                     ret = SOCKS5_ERR_HOST_UNREACHABLE;
497                     goto fail;
498           case SOCKS_CONNECTION_REFUSED:
499                     ret = SOCKS5_ERR_CONN_REFUSED;
500                     goto fail;
501           case SOCKS_TTL_EXPIRED:
502                     ret = SOCKS5_ERR_TTL_EXPIRED;
503                     goto fail;
504           case SOCKS_COMMAND_NOT_SUPPORTED:
505                     ret = SOCKS5_ERR_COM_UNSUPPORTED;
506                     goto fail;
507           case SOCKS_ADDRESS_NOT_SUPPORTED:
508                     ret = SOCKS5_ERR_ADDR_UNSUPPORTED;
509                     goto fail;
510           default:
511                     ret = SOCKS5_ERR_UNSPECIFIED;
512                     goto fail;
513           }
514 
515           return (ret);
516 
517 fail:
518           socks5_seterr(ret);
519           return (0);
520 }
521 
522 /*
523  * Perform SOCKS5 initialization
524  */
525 int
fetch_socks5_getenv(char ** host,int * port)526 fetch_socks5_getenv(char **host, int *port)
527 {
528           char *socks5env, *endptr, *ext;
529           const char *portDelim;
530           size_t slen;
531 
532           portDelim = ":";
533           if ((socks5env = getenv("SOCKS5_PROXY")) == NULL || *socks5env == '\0') {
534                     *host = NULL;
535                     *port = -1;
536                     return (-1);
537           }
538 
539           /*
540            * IPv6 addresses begin and end in brackets.  Set the port delimiter
541            * accordingly and search for it so we can do appropriate validation.
542            */
543           if (socks5env[0] == '[')
544                     portDelim = "]:";
545 
546           slen = strlen(socks5env);
547           ext = strstr(socks5env, portDelim);
548           if (socks5env[0] == '[') {
549                     if (socks5env[slen - 1] == ']') {
550                               *host = strndup(socks5env, slen);
551                     } else if (ext != NULL) {
552                               *host = strndup(socks5env, ext - socks5env + 1);
553                     } else {
554                               socks5_seterr(SOCKS5_ERR_BAD_PROXY_FORMAT);
555                               return (0);
556                     }
557           } else {
558                     *host = strndup(socks5env, ext - socks5env);
559           }
560 
561           if (*host == NULL) {
562                     fprintf(stderr, "Failure to allocate memory, exiting.\n");
563                     return (-1);
564           }
565           if (ext == NULL) {
566                     *port = 1080; /* Default port as defined in RFC1928 */
567           } else {
568                     ext += strlen(portDelim);
569                     errno = 0;
570                     *port = strtoimax(ext, (char **)&endptr, 10);
571                     if (*endptr != '\0' || errno != 0 || *port < 0 ||
572                         *port > 65535) {
573                               free(*host);
574                               *host = NULL;
575                               socks5_seterr(SOCKS5_ERR_BAD_PORT);
576                               return (0);
577                     }
578           }
579 
580           return (2);
581 }
582 
583 
584 /*
585  * Establish a TCP connection to the specified port on the specified host.
586  */
587 conn_t *
fetch_connect(const char * host,int port,int af,int verbose)588 fetch_connect(const char *host, int port, int af, int verbose)
589 {
590           struct addrinfo *cais = NULL, *sais = NULL, *cai, *sai;
591           const char *bindaddr = NULL;
592           conn_t *conn = NULL;
593           int err = 0, sd = -1;
594           char *sockshost;
595           int socksport;
596 
597           DEBUGF("---> %s:%d\n", host, port);
598 
599           /*
600            * Check if SOCKS5_PROXY env variable is set.  fetch_socks5_getenv
601            * will either set sockshost = NULL or allocate memory in all cases.
602            */
603           sockshost = NULL;
604           if (!fetch_socks5_getenv(&sockshost, &socksport))
605                     goto fail;
606 
607           /* Not using SOCKS5 proxy */
608           if (sockshost == NULL) {
609                     /* resolve server address */
610                     if (verbose)
611                               fetch_info("resolving server address: %s:%d", host,
612                                   port);
613                     if ((sais = fetch_resolve(host, port, af)) == NULL)
614                               goto fail;
615 
616                     /* resolve client address */
617                     bindaddr = getenv("FETCH_BIND_ADDRESS");
618                     if (bindaddr != NULL && *bindaddr != '\0') {
619                               if (verbose)
620                                         fetch_info("resolving client address: %s",
621                                             bindaddr);
622                               if ((cais = fetch_resolve(bindaddr, 0, af)) == NULL)
623                                         goto fail;
624                     }
625           } else {
626                     /* resolve socks5 proxy address */
627                     if (verbose)
628                               fetch_info("resolving SOCKS5 server address: %s:%d",
629                                   sockshost, socksport);
630                     if ((sais = fetch_resolve(sockshost, socksport, af)) == NULL) {
631                               socks5_seterr(SOCKS5_ERR_BAD_HOST);
632                               goto fail;
633                     }
634           }
635 
636           /* try each server address in turn */
637           for (err = 0, sai = sais; sai != NULL; sai = sai->ai_next) {
638                     /* open socket */
639                     if ((sd = socket(sai->ai_family, SOCK_STREAM, 0)) < 0)
640                               goto syserr;
641                     /* attempt to bind to client address */
642                     for (err = 0, cai = cais; cai != NULL; cai = cai->ai_next) {
643                               if (cai->ai_family != sai->ai_family)
644                                         continue;
645                               if ((err = bind(sd, cai->ai_addr, cai->ai_addrlen)) == 0)
646                                         break;
647                     }
648                     if (err != 0) {
649                               if (verbose)
650                                         fetch_info("failed to bind to %s", bindaddr);
651                               goto syserr;
652                     }
653                     /* attempt to connect to server address */
654                     if ((err = connect(sd, sai->ai_addr, sai->ai_addrlen)) == 0)
655                               break;
656                     /* clean up before next attempt */
657                     close(sd);
658                     sd = -1;
659           }
660           if (err != 0) {
661                     if (verbose && sockshost == NULL) {
662                               fetch_info("failed to connect to %s:%d", host, port);
663                               goto syserr;
664                     } else if (sockshost != NULL) {
665                               if (verbose)
666                                         fetch_info(
667                                             "failed to connect to SOCKS5 server %s:%d",
668                                             sockshost, socksport);
669                               socks5_seterr(SOCKS5_ERR_CONN_REFUSED);
670                               goto fail;
671                     }
672                     goto syserr;
673           }
674 
675           if ((conn = fetch_reopen(sd)) == NULL)
676                     goto syserr;
677 
678           if (sockshost)
679                     if (!fetch_socks5_init(conn, host, port, verbose))
680                               goto fail;
681           free(sockshost);
682           if (cais != NULL)
683                     freeaddrinfo(cais);
684           if (sais != NULL)
685                     freeaddrinfo(sais);
686           return (conn);
687 syserr:
688           fetch_syserr();
689 fail:
690           free(sockshost);
691           /* Fully close if it was opened; otherwise just don't leak the fd. */
692           if (conn != NULL)
693                     fetch_close(conn);
694           else if (sd >= 0)
695                     close(sd);
696           if (cais != NULL)
697                     freeaddrinfo(cais);
698           if (sais != NULL)
699                     freeaddrinfo(sais);
700           return (NULL);
701 }
702 
703 #ifdef WITH_SSL
704 /*
705  * Convert characters A-Z to lowercase (intentionally avoid any locale
706  * specific conversions).
707  */
708 static char
fetch_ssl_tolower(char in)709 fetch_ssl_tolower(char in)
710 {
711           if (in >= 'A' && in <= 'Z')
712                     return (in + 32);
713           else
714                     return (in);
715 }
716 
717 /*
718  * isalpha implementation that intentionally avoids any locale specific
719  * conversions.
720  */
721 static int
fetch_ssl_isalpha(char in)722 fetch_ssl_isalpha(char in)
723 {
724           return ((in >= 'A' && in <= 'Z') || (in >= 'a' && in <= 'z'));
725 }
726 
727 /*
728  * Check if passed hostnames a and b are equal.
729  */
730 static int
fetch_ssl_hname_equal(const char * a,size_t alen,const char * b,size_t blen)731 fetch_ssl_hname_equal(const char *a, size_t alen, const char *b,
732     size_t blen)
733 {
734           size_t i;
735 
736           if (alen != blen)
737                     return (0);
738           for (i = 0; i < alen; ++i) {
739                     if (fetch_ssl_tolower(a[i]) != fetch_ssl_tolower(b[i]))
740                               return (0);
741           }
742           return (1);
743 }
744 
745 /*
746  * Check if domain label is traditional, meaning that only A-Z, a-z, 0-9
747  * and '-' (hyphen) are allowed. Hyphens have to be surrounded by alpha-
748  * numeric characters. Double hyphens (like they're found in IDN a-labels
749  * 'xn--') are not allowed. Empty labels are invalid.
750  */
751 static int
fetch_ssl_is_trad_domain_label(const char * l,size_t len,int wcok)752 fetch_ssl_is_trad_domain_label(const char *l, size_t len, int wcok)
753 {
754           size_t i;
755 
756           if (!len || l[0] == '-' || l[len-1] == '-')
757                     return (0);
758           for (i = 0; i < len; ++i) {
759                     if (!isdigit(l[i]) &&
760                         !fetch_ssl_isalpha(l[i]) &&
761                         !(l[i] == '*' && wcok) &&
762                         !(l[i] == '-' && l[i - 1] != '-'))
763                               return (0);
764           }
765           return (1);
766 }
767 
768 /*
769  * Check if host name consists only of numbers. This might indicate an IP
770  * address, which is not a good idea for CN wildcard comparison.
771  */
772 static int
fetch_ssl_hname_is_only_numbers(const char * hostname,size_t len)773 fetch_ssl_hname_is_only_numbers(const char *hostname, size_t len)
774 {
775           size_t i;
776 
777           for (i = 0; i < len; ++i) {
778                     if (!((hostname[i] >= '0' && hostname[i] <= '9') ||
779                         hostname[i] == '.'))
780                               return (0);
781           }
782           return (1);
783 }
784 
785 /*
786  * Check if the host name h passed matches the pattern passed in m which
787  * is usually part of subjectAltName or CN of a certificate presented to
788  * the client. This includes wildcard matching. The algorithm is based on
789  * RFC6125, sections 6.4.3 and 7.2, which clarifies RFC2818 and RFC3280.
790  */
791 static int
fetch_ssl_hname_match(const char * h,size_t hlen,const char * m,size_t mlen)792 fetch_ssl_hname_match(const char *h, size_t hlen, const char *m,
793     size_t mlen)
794 {
795           int delta, hdotidx, mdot1idx, wcidx;
796           const char *hdot, *mdot1, *mdot2;
797           const char *wc; /* wildcard */
798 
799           if (!(h && *h && m && *m))
800                     return (0);
801           if ((wc = strnstr(m, "*", mlen)) == NULL)
802                     return (fetch_ssl_hname_equal(h, hlen, m, mlen));
803           wcidx = wc - m;
804           /* hostname should not be just dots and numbers */
805           if (fetch_ssl_hname_is_only_numbers(h, hlen))
806                     return (0);
807           /* only one wildcard allowed in pattern */
808           if (strnstr(wc + 1, "*", mlen - wcidx - 1) != NULL)
809                     return (0);
810           /*
811            * there must be at least two more domain labels and
812            * wildcard has to be in the leftmost label (RFC6125)
813            */
814           mdot1 = strnstr(m, ".", mlen);
815           if (mdot1 == NULL || mdot1 < wc || (mlen - (mdot1 - m)) < 4)
816                     return (0);
817           mdot1idx = mdot1 - m;
818           mdot2 = strnstr(mdot1 + 1, ".", mlen - mdot1idx - 1);
819           if (mdot2 == NULL || (mlen - (mdot2 - m)) < 2)
820                     return (0);
821           /* hostname must contain a dot and not be the 1st char */
822           hdot = strnstr(h, ".", hlen);
823           if (hdot == NULL || hdot == h)
824                     return (0);
825           hdotidx = hdot - h;
826           /*
827            * host part of hostname must be at least as long as
828            * pattern it's supposed to match
829            */
830           if (hdotidx < mdot1idx)
831                     return (0);
832           /*
833            * don't allow wildcards in non-traditional domain names
834            * (IDN, A-label, U-label...)
835            */
836           if (!fetch_ssl_is_trad_domain_label(h, hdotidx, 0) ||
837               !fetch_ssl_is_trad_domain_label(m, mdot1idx, 1))
838                     return (0);
839           /* match domain part (part after first dot) */
840           if (!fetch_ssl_hname_equal(hdot, hlen - hdotidx, mdot1,
841               mlen - mdot1idx))
842                     return (0);
843           /* match part left of wildcard */
844           if (!fetch_ssl_hname_equal(h, wcidx, m, wcidx))
845                     return (0);
846           /* match part right of wildcard */
847           delta = mdot1idx - wcidx - 1;
848           if (!fetch_ssl_hname_equal(hdot - delta, delta,
849               mdot1 - delta, delta))
850                     return (0);
851           /* all tests succeeded, it's a match */
852           return (1);
853 }
854 
855 /*
856  * Get numeric host address info - returns NULL if host was not an IP
857  * address. The caller is responsible for deallocation using
858  * freeaddrinfo(3).
859  */
860 static struct addrinfo *
fetch_ssl_get_numeric_addrinfo(const char * hostname,size_t len)861 fetch_ssl_get_numeric_addrinfo(const char *hostname, size_t len)
862 {
863           struct addrinfo hints, *res;
864           char *host;
865 
866           host = (char *)malloc(len + 1);
867           memcpy(host, hostname, len);
868           host[len] = '\0';
869           memset(&hints, 0, sizeof(hints));
870           hints.ai_family = PF_UNSPEC;
871           hints.ai_socktype = SOCK_STREAM;
872           hints.ai_protocol = 0;
873           hints.ai_flags = AI_NUMERICHOST;
874           /* port is not relevant for this purpose */
875           if (getaddrinfo(host, "443", &hints, &res) != 0)
876                     res = NULL;
877           free(host);
878           return res;
879 }
880 
881 /*
882  * Compare ip address in addrinfo with address passes.
883  */
884 static int
fetch_ssl_ipaddr_match_bin(const struct addrinfo * lhost,const char * rhost,size_t rhostlen)885 fetch_ssl_ipaddr_match_bin(const struct addrinfo *lhost, const char *rhost,
886     size_t rhostlen)
887 {
888           const void *left;
889 
890           if (lhost->ai_family == AF_INET && rhostlen == 4) {
891                     left = (void *)&((struct sockaddr_in*)(void *)
892                         lhost->ai_addr)->sin_addr.s_addr;
893 #ifdef INET6
894           } else if (lhost->ai_family == AF_INET6 && rhostlen == 16) {
895                     left = (void *)&((struct sockaddr_in6 *)(void *)
896                         lhost->ai_addr)->sin6_addr;
897 #endif
898           } else
899                     return (0);
900           return (!memcmp(left, (const void *)rhost, rhostlen) ? 1 : 0);
901 }
902 
903 /*
904  * Compare ip address in addrinfo with host passed. If host is not an IP
905  * address, comparison will fail.
906  */
907 static int
fetch_ssl_ipaddr_match(const struct addrinfo * laddr,const char * r,size_t rlen)908 fetch_ssl_ipaddr_match(const struct addrinfo *laddr, const char *r,
909     size_t rlen)
910 {
911           struct addrinfo *raddr;
912           int ret;
913           char *rip;
914 
915           ret = 0;
916           if ((raddr = fetch_ssl_get_numeric_addrinfo(r, rlen)) == NULL)
917                     return 0; /* not a numeric host */
918 
919           if (laddr->ai_family == raddr->ai_family) {
920                     if (laddr->ai_family == AF_INET) {
921                               rip = (char *)&((struct sockaddr_in *)(void *)
922                                   raddr->ai_addr)->sin_addr.s_addr;
923                               ret = fetch_ssl_ipaddr_match_bin(laddr, rip, 4);
924 #ifdef INET6
925                     } else if (laddr->ai_family == AF_INET6) {
926                               rip = (char *)&((struct sockaddr_in6 *)(void *)
927                                   raddr->ai_addr)->sin6_addr;
928                               ret = fetch_ssl_ipaddr_match_bin(laddr, rip, 16);
929 #endif
930                     }
931 
932           }
933           freeaddrinfo(raddr);
934           return (ret);
935 }
936 
937 /*
938  * Verify server certificate by subjectAltName.
939  */
940 static int
fetch_ssl_verify_altname(STACK_OF (GENERAL_NAME)* altnames,const char * host,struct addrinfo * ip)941 fetch_ssl_verify_altname(STACK_OF(GENERAL_NAME) *altnames,
942     const char *host, struct addrinfo *ip)
943 {
944           const GENERAL_NAME *name;
945           size_t nslen;
946           int i;
947           const char *ns;
948 
949           for (i = 0; i < sk_GENERAL_NAME_num(altnames); ++i) {
950 #if OPENSSL_VERSION_NUMBER < 0x10000000L
951                     /*
952                      * This is a workaround, since the following line causes
953                      * alignment issues in clang:
954                      * name = sk_GENERAL_NAME_value(altnames, i);
955                      * OpenSSL explicitly warns not to use those macros
956                      * directly, but there isn't much choice (and there
957                      * shouldn't be any ill side effects)
958                      */
959                     name = (GENERAL_NAME *)SKM_sk_value(void, altnames, i);
960 #else
961                     name = sk_GENERAL_NAME_value(altnames, i);
962 #endif
963 #if OPENSSL_VERSION_NUMBER < 0x10100000L
964                     ns = (const char *)ASN1_STRING_data(name->d.ia5);
965 #else
966                     ns = (const char *)ASN1_STRING_get0_data(name->d.ia5);
967 #endif
968                     nslen = (size_t)ASN1_STRING_length(name->d.ia5);
969 
970                     if (name->type == GEN_DNS && ip == NULL &&
971                         fetch_ssl_hname_match(host, strlen(host), ns, nslen))
972                               return (1);
973                     else if (name->type == GEN_IPADD && ip != NULL &&
974                         fetch_ssl_ipaddr_match_bin(ip, ns, nslen))
975                               return (1);
976           }
977           return (0);
978 }
979 
980 /*
981  * Verify server certificate by CN.
982  */
983 static int
fetch_ssl_verify_cn(X509_NAME * subject,const char * host,struct addrinfo * ip)984 fetch_ssl_verify_cn(X509_NAME *subject, const char *host,
985     struct addrinfo *ip)
986 {
987           ASN1_STRING *namedata;
988           X509_NAME_ENTRY *nameentry;
989           int cnlen, lastpos, loc, ret;
990           unsigned char *cn;
991 
992           ret = 0;
993           lastpos = -1;
994           loc = -1;
995           cn = NULL;
996           /* get most specific CN (last entry in list) and compare */
997           while ((lastpos = X509_NAME_get_index_by_NID(subject,
998               NID_commonName, lastpos)) != -1)
999                     loc = lastpos;
1000 
1001           if (loc > -1) {
1002                     nameentry = X509_NAME_get_entry(subject, loc);
1003                     namedata = X509_NAME_ENTRY_get_data(nameentry);
1004                     cnlen = ASN1_STRING_to_UTF8(&cn, namedata);
1005                     if (ip == NULL &&
1006                         fetch_ssl_hname_match(host, strlen(host), cn, cnlen))
1007                               ret = 1;
1008                     else if (ip != NULL && fetch_ssl_ipaddr_match(ip, cn, cnlen))
1009                               ret = 1;
1010                     OPENSSL_free(cn);
1011           }
1012           return (ret);
1013 }
1014 
1015 /*
1016  * Verify that server certificate subjectAltName/CN matches
1017  * hostname. First check, if there are alternative subject names. If yes,
1018  * those have to match. Only if those don't exist it falls back to
1019  * checking the subject's CN.
1020  */
1021 static int
fetch_ssl_verify_hname(X509 * cert,const char * host)1022 fetch_ssl_verify_hname(X509 *cert, const char *host)
1023 {
1024           struct addrinfo *ip;
1025           STACK_OF(GENERAL_NAME) *altnames;
1026           X509_NAME *subject;
1027           int ret;
1028 
1029           ret = 0;
1030           ip = fetch_ssl_get_numeric_addrinfo(host, strlen(host));
1031           altnames = X509_get_ext_d2i(cert, NID_subject_alt_name,
1032               NULL, NULL);
1033 
1034           if (altnames != NULL) {
1035                     ret = fetch_ssl_verify_altname(altnames, host, ip);
1036           } else {
1037                     subject = X509_get_subject_name(cert);
1038                     if (subject != NULL)
1039                               ret = fetch_ssl_verify_cn(subject, host, ip);
1040           }
1041 
1042           if (ip != NULL)
1043                     freeaddrinfo(ip);
1044           if (altnames != NULL)
1045                     GENERAL_NAMES_free(altnames);
1046           return (ret);
1047 }
1048 
1049 /*
1050  * Configure transport security layer based on environment.
1051  */
1052 static void
fetch_ssl_setup_transport_layer(SSL_CTX * ctx,int verbose)1053 fetch_ssl_setup_transport_layer(SSL_CTX *ctx, int verbose)
1054 {
1055           long ssl_ctx_options;
1056 
1057           ssl_ctx_options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_TICKET;
1058           if (getenv("SSL_ALLOW_SSL3") == NULL)
1059                     ssl_ctx_options |= SSL_OP_NO_SSLv3;
1060           if (getenv("SSL_NO_TLS1") != NULL)
1061                     ssl_ctx_options |= SSL_OP_NO_TLSv1;
1062           if (getenv("SSL_NO_TLS1_1") != NULL)
1063                     ssl_ctx_options |= SSL_OP_NO_TLSv1_1;
1064           if (getenv("SSL_NO_TLS1_2") != NULL)
1065                     ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
1066           if (verbose)
1067                     fetch_info("SSL options: %lx", ssl_ctx_options);
1068           SSL_CTX_set_options(ctx, ssl_ctx_options);
1069 }
1070 
1071 
1072 /*
1073  * Configure peer verification based on environment.
1074  */
1075 #define LOCAL_CERT_FILE       "/usr/local/etc/ssl/cert.pem"
1076 #define BASE_CERT_FILE        "/etc/ssl/cert.pem"
1077 static int
fetch_ssl_setup_peer_verification(SSL_CTX * ctx,int verbose)1078 fetch_ssl_setup_peer_verification(SSL_CTX *ctx, int verbose)
1079 {
1080           X509_LOOKUP *crl_lookup;
1081           X509_STORE *crl_store;
1082           const char *ca_cert_file, *ca_cert_path, *crl_file;
1083 
1084           if (getenv("SSL_NO_VERIFY_PEER") == NULL) {
1085                     ca_cert_file = getenv("SSL_CA_CERT_FILE");
1086                     if (ca_cert_file == NULL &&
1087                         access(LOCAL_CERT_FILE, R_OK) == 0)
1088                               ca_cert_file = LOCAL_CERT_FILE;
1089                     if (ca_cert_file == NULL &&
1090                         access(BASE_CERT_FILE, R_OK) == 0)
1091                               ca_cert_file = BASE_CERT_FILE;
1092                     ca_cert_path = getenv("SSL_CA_CERT_PATH");
1093                     if (verbose) {
1094                               fetch_info("Peer verification enabled");
1095                               if (ca_cert_file != NULL)
1096                                         fetch_info("Using CA cert file: %s",
1097                                             ca_cert_file);
1098                               if (ca_cert_path != NULL)
1099                                         fetch_info("Using CA cert path: %s",
1100                                             ca_cert_path);
1101                               if (ca_cert_file == NULL && ca_cert_path == NULL)
1102                                         fetch_info("Using OpenSSL default "
1103                                             "CA cert file and path");
1104                     }
1105                     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER,
1106                         fetch_ssl_cb_verify_crt);
1107                     if (ca_cert_file != NULL || ca_cert_path != NULL)
1108                               SSL_CTX_load_verify_locations(ctx, ca_cert_file,
1109                                   ca_cert_path);
1110                     else
1111                               SSL_CTX_set_default_verify_paths(ctx);
1112                     if ((crl_file = getenv("SSL_CRL_FILE")) != NULL) {
1113                               if (verbose)
1114                                         fetch_info("Using CRL file: %s", crl_file);
1115                               crl_store = SSL_CTX_get_cert_store(ctx);
1116                               crl_lookup = X509_STORE_add_lookup(crl_store,
1117                                   X509_LOOKUP_file());
1118                               if (crl_lookup == NULL ||
1119                                   !X509_load_crl_file(crl_lookup, crl_file,
1120                                         X509_FILETYPE_PEM)) {
1121                                         fprintf(stderr,
1122                                             "Could not load CRL file %s\n",
1123                                             crl_file);
1124                                         return (0);
1125                               }
1126                               X509_STORE_set_flags(crl_store,
1127                                   X509_V_FLAG_CRL_CHECK |
1128                                   X509_V_FLAG_CRL_CHECK_ALL);
1129                     }
1130           }
1131           return (1);
1132 }
1133 
1134 /*
1135  * Configure client certificate based on environment.
1136  */
1137 static int
fetch_ssl_setup_client_certificate(SSL_CTX * ctx,int verbose)1138 fetch_ssl_setup_client_certificate(SSL_CTX *ctx, int verbose)
1139 {
1140           const char *client_cert_file, *client_key_file;
1141 
1142           if ((client_cert_file = getenv("SSL_CLIENT_CERT_FILE")) != NULL) {
1143                     client_key_file = getenv("SSL_CLIENT_KEY_FILE") != NULL ?
1144                         getenv("SSL_CLIENT_KEY_FILE") : client_cert_file;
1145                     if (verbose) {
1146                               fetch_info("Using client cert file: %s",
1147                                   client_cert_file);
1148                               fetch_info("Using client key file: %s",
1149                                   client_key_file);
1150                     }
1151                     if (SSL_CTX_use_certificate_chain_file(ctx,
1152                               client_cert_file) != 1) {
1153                               fprintf(stderr,
1154                                   "Could not load client certificate %s\n",
1155                                   client_cert_file);
1156                               return (0);
1157                     }
1158                     if (SSL_CTX_use_PrivateKey_file(ctx, client_key_file,
1159                               SSL_FILETYPE_PEM) != 1) {
1160                               fprintf(stderr,
1161                                   "Could not load client key %s\n",
1162                                   client_key_file);
1163                               return (0);
1164                     }
1165           }
1166           return (1);
1167 }
1168 
1169 /*
1170  * Callback for SSL certificate verification, this is called on server
1171  * cert verification. It takes no decision, but informs the user in case
1172  * verification failed.
1173  */
1174 int
fetch_ssl_cb_verify_crt(int verified,X509_STORE_CTX * ctx)1175 fetch_ssl_cb_verify_crt(int verified, X509_STORE_CTX *ctx)
1176 {
1177           X509 *crt;
1178           X509_NAME *name;
1179           char *str;
1180 
1181           str = NULL;
1182           if (!verified) {
1183                     if ((crt = X509_STORE_CTX_get_current_cert(ctx)) != NULL &&
1184                         (name = X509_get_subject_name(crt)) != NULL)
1185                               str = X509_NAME_oneline(name, 0, 0);
1186                     fprintf(stderr, "Certificate verification failed for %s\n",
1187                         str != NULL ? str : "no relevant certificate");
1188                     OPENSSL_free(str);
1189           }
1190           return (verified);
1191 }
1192 
1193 #endif
1194 
1195 /*
1196  * Enable SSL on a connection.
1197  */
1198 int
fetch_ssl(conn_t * conn,const struct url * URL,int verbose)1199 fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
1200 {
1201 #ifdef WITH_SSL
1202           int ret, ssl_err;
1203           X509_NAME *name;
1204           char *str;
1205 
1206           /* Init the SSL library and context */
1207           if (!SSL_library_init()){
1208                     fprintf(stderr, "SSL library init failed\n");
1209                     return (-1);
1210           }
1211 
1212           SSL_load_error_strings();
1213 
1214           conn->ssl_meth = SSLv23_client_method();
1215           conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth);
1216           SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY);
1217 
1218           fetch_ssl_setup_transport_layer(conn->ssl_ctx, verbose);
1219           if (!fetch_ssl_setup_peer_verification(conn->ssl_ctx, verbose))
1220                     return (-1);
1221           if (!fetch_ssl_setup_client_certificate(conn->ssl_ctx, verbose))
1222                     return (-1);
1223 
1224           conn->ssl = SSL_new(conn->ssl_ctx);
1225           if (conn->ssl == NULL) {
1226                     fprintf(stderr, "SSL context creation failed\n");
1227                     return (-1);
1228           }
1229           SSL_set_fd(conn->ssl, conn->sd);
1230 
1231 #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
1232           if (!SSL_set_tlsext_host_name(conn->ssl,
1233               __DECONST(struct url *, URL)->host)) {
1234                     fprintf(stderr,
1235                         "TLS server name indication extension failed for host %s\n",
1236                         URL->host);
1237                     return (-1);
1238           }
1239 #endif
1240           while ((ret = SSL_connect(conn->ssl)) == -1) {
1241                     ssl_err = SSL_get_error(conn->ssl, ret);
1242                     if (ssl_err != SSL_ERROR_WANT_READ &&
1243                         ssl_err != SSL_ERROR_WANT_WRITE) {
1244                               ERR_print_errors_fp(stderr);
1245                               return (-1);
1246                     }
1247           }
1248           conn->ssl_cert = SSL_get_peer_certificate(conn->ssl);
1249 
1250           if (conn->ssl_cert == NULL) {
1251                     fprintf(stderr, "No server SSL certificate\n");
1252                     return (-1);
1253           }
1254 
1255           if (getenv("SSL_NO_VERIFY_HOSTNAME") == NULL) {
1256                     if (verbose)
1257                               fetch_info("Verify hostname");
1258                     if (!fetch_ssl_verify_hname(conn->ssl_cert, URL->host)) {
1259                               fprintf(stderr,
1260                                   "SSL certificate subject doesn't match host %s\n",
1261                                   URL->host);
1262                               return (-1);
1263                     }
1264           }
1265 
1266           if (verbose) {
1267                     fetch_info("%s connection established using %s",
1268                         SSL_get_version(conn->ssl), SSL_get_cipher(conn->ssl));
1269                     name = X509_get_subject_name(conn->ssl_cert);
1270                     str = X509_NAME_oneline(name, 0, 0);
1271                     fetch_info("Certificate subject: %s", str);
1272                     OPENSSL_free(str);
1273                     name = X509_get_issuer_name(conn->ssl_cert);
1274                     str = X509_NAME_oneline(name, 0, 0);
1275                     fetch_info("Certificate issuer: %s", str);
1276                     OPENSSL_free(str);
1277           }
1278 
1279           return (0);
1280 #else
1281           (void)conn;
1282           (void)verbose;
1283           (void)URL;
1284           fprintf(stderr, "SSL support disabled\n");
1285           return (-1);
1286 #endif
1287 }
1288 
1289 #define FETCH_READ_WAIT                 -2
1290 #define FETCH_READ_ERROR      -1
1291 #define FETCH_READ_DONE                  0
1292 
1293 #ifdef WITH_SSL
1294 static ssize_t
fetch_ssl_read(SSL * ssl,char * buf,size_t len)1295 fetch_ssl_read(SSL *ssl, char *buf, size_t len)
1296 {
1297           ssize_t rlen;
1298           int ssl_err;
1299 
1300           rlen = SSL_read(ssl, buf, len);
1301           if (rlen < 0) {
1302                     ssl_err = SSL_get_error(ssl, rlen);
1303                     if (ssl_err == SSL_ERROR_WANT_READ ||
1304                         ssl_err == SSL_ERROR_WANT_WRITE) {
1305                               return (FETCH_READ_WAIT);
1306                     } else {
1307                               ERR_print_errors_fp(stderr);
1308                               return (FETCH_READ_ERROR);
1309                     }
1310           }
1311           return (rlen);
1312 }
1313 #endif
1314 
1315 static ssize_t
fetch_socket_read(int sd,char * buf,size_t len)1316 fetch_socket_read(int sd, char *buf, size_t len)
1317 {
1318           ssize_t rlen;
1319 
1320           rlen = read(sd, buf, len);
1321           if (rlen < 0) {
1322                     if (errno == EAGAIN || (errno == EINTR && fetchRestartCalls))
1323                               return (FETCH_READ_WAIT);
1324                     else
1325                               return (FETCH_READ_ERROR);
1326           }
1327           return (rlen);
1328 }
1329 
1330 /*
1331  * Read a character from a connection w/ timeout
1332  */
1333 ssize_t
fetch_read(conn_t * conn,char * buf,size_t len)1334 fetch_read(conn_t *conn, char *buf, size_t len)
1335 {
1336           struct timeval now, timeout, delta;
1337           struct pollfd pfd;
1338           ssize_t rlen;
1339           int deltams;
1340 
1341           if (fetchTimeout > 0) {
1342                     gettimeofday(&timeout, NULL);
1343                     timeout.tv_sec += fetchTimeout;
1344           }
1345 
1346           deltams = INFTIM;
1347           memset(&pfd, 0, sizeof pfd);
1348           pfd.fd = conn->sd;
1349           pfd.events = POLLIN | POLLERR;
1350 
1351           for (;;) {
1352                     /*
1353                      * The socket is non-blocking.  Instead of the canonical
1354                      * poll() -> read(), we do the following:
1355                      *
1356                      * 1) call read() or SSL_read().
1357                      * 2) if we received some data, return it.
1358                      * 3) if an error occurred, return -1.
1359                      * 4) if read() or SSL_read() signaled EOF, return.
1360                      * 5) if we did not receive any data but we're not at EOF,
1361                      *    call poll().
1362                      *
1363                      * In the SSL case, this is necessary because if we
1364                      * receive a close notification, we have to call
1365                      * SSL_read() one additional time after we've read
1366                      * everything we received.
1367                      *
1368                      * In the non-SSL case, it may improve performance (very
1369                      * slightly) when reading small amounts of data.
1370                      */
1371 #ifdef WITH_SSL
1372                     if (conn->ssl != NULL)
1373                               rlen = fetch_ssl_read(conn->ssl, buf, len);
1374                     else
1375 #endif
1376                               rlen = fetch_socket_read(conn->sd, buf, len);
1377                     if (rlen >= 0) {
1378                               break;
1379                     } else if (rlen == FETCH_READ_ERROR) {
1380                               fetch_syserr();
1381                               return (-1);
1382                     }
1383                     // assert(rlen == FETCH_READ_WAIT);
1384                     if (fetchTimeout > 0) {
1385                               gettimeofday(&now, NULL);
1386                               if (!timercmp(&timeout, &now, >)) {
1387                                         errno = ETIMEDOUT;
1388                                         fetch_syserr();
1389                                         return (-1);
1390                               }
1391                               timersub(&timeout, &now, &delta);
1392                               deltams = delta.tv_sec * 1000 +
1393                                   delta.tv_usec / 1000;;
1394                     }
1395                     errno = 0;
1396                     pfd.revents = 0;
1397                     if (poll(&pfd, 1, deltams) < 0) {
1398                               if (errno == EINTR && fetchRestartCalls)
1399                                         continue;
1400                               fetch_syserr();
1401                               return (-1);
1402                     }
1403           }
1404           return (rlen);
1405 }
1406 
1407 
1408 /*
1409  * Read a line of text from a connection w/ timeout
1410  */
1411 #define MIN_BUF_SIZE 1024
1412 
1413 int
fetch_getln(conn_t * conn)1414 fetch_getln(conn_t *conn)
1415 {
1416           char *tmp;
1417           size_t tmpsize;
1418           ssize_t len;
1419           char c;
1420 
1421           if (conn->buf == NULL) {
1422                     if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
1423                               errno = ENOMEM;
1424                               return (-1);
1425                     }
1426                     conn->bufsize = MIN_BUF_SIZE;
1427           }
1428 
1429           conn->buf[0] = '\0';
1430           conn->buflen = 0;
1431 
1432           do {
1433                     len = fetch_read(conn, &c, 1);
1434                     if (len == -1)
1435                               return (-1);
1436                     if (len == 0)
1437                               break;
1438                     conn->buf[conn->buflen++] = c;
1439                     if (conn->buflen == conn->bufsize) {
1440                               tmp = conn->buf;
1441                               tmpsize = conn->bufsize * 2 + 1;
1442                               if ((tmp = realloc(tmp, tmpsize)) == NULL) {
1443                                         errno = ENOMEM;
1444                                         return (-1);
1445                               }
1446                               conn->buf = tmp;
1447                               conn->bufsize = tmpsize;
1448                     }
1449           } while (c != '\n');
1450 
1451           conn->buf[conn->buflen] = '\0';
1452           DEBUGF("<<< %s", conn->buf);
1453           return (0);
1454 }
1455 
1456 
1457 /*
1458  * Write to a connection w/ timeout
1459  */
1460 ssize_t
fetch_write(conn_t * conn,const char * buf,size_t len)1461 fetch_write(conn_t *conn, const char *buf, size_t len)
1462 {
1463           struct iovec iov;
1464 
1465           iov.iov_base = __DECONST(char *, buf);
1466           iov.iov_len = len;
1467           return fetch_writev(conn, &iov, 1);
1468 }
1469 
1470 /*
1471  * Write a vector to a connection w/ timeout
1472  * Note: can modify the iovec.
1473  */
1474 ssize_t
fetch_writev(conn_t * conn,struct iovec * iov,int iovcnt)1475 fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt)
1476 {
1477           struct timeval now, timeout, delta;
1478           struct pollfd pfd;
1479           ssize_t wlen, total;
1480           int deltams;
1481 
1482           memset(&pfd, 0, sizeof pfd);
1483           if (fetchTimeout) {
1484                     pfd.fd = conn->sd;
1485                     pfd.events = POLLOUT | POLLERR;
1486                     gettimeofday(&timeout, NULL);
1487                     timeout.tv_sec += fetchTimeout;
1488           }
1489 
1490           total = 0;
1491           while (iovcnt > 0) {
1492                     while (fetchTimeout && pfd.revents == 0) {
1493                               gettimeofday(&now, NULL);
1494                               if (!timercmp(&timeout, &now, >)) {
1495                                         errno = ETIMEDOUT;
1496                                         fetch_syserr();
1497                                         return (-1);
1498                               }
1499                               timersub(&timeout, &now, &delta);
1500                               deltams = delta.tv_sec * 1000 +
1501                                   delta.tv_usec / 1000;
1502                               errno = 0;
1503                               pfd.revents = 0;
1504                               if (poll(&pfd, 1, deltams) < 0) {
1505                                         /* POSIX compliance */
1506                                         if (errno == EAGAIN)
1507                                                   continue;
1508                                         if (errno == EINTR && fetchRestartCalls)
1509                                                   continue;
1510                                         return (-1);
1511                               }
1512                     }
1513                     errno = 0;
1514 #ifdef WITH_SSL
1515                     if (conn->ssl != NULL)
1516                               wlen = SSL_write(conn->ssl,
1517                                   iov->iov_base, iov->iov_len);
1518                     else
1519 #endif
1520                               wlen = writev(conn->sd, iov, iovcnt);
1521                     if (wlen == 0) {
1522                               /* we consider a short write a failure */
1523                               /* XXX perhaps we shouldn't in the SSL case */
1524                               errno = EPIPE;
1525                               fetch_syserr();
1526                               return (-1);
1527                     }
1528                     if (wlen < 0) {
1529                               if (errno == EINTR && fetchRestartCalls)
1530                                         continue;
1531                               return (-1);
1532                     }
1533                     total += wlen;
1534                     while (iovcnt > 0 && wlen >= (ssize_t)iov->iov_len) {
1535                               wlen -= iov->iov_len;
1536                               iov++;
1537                               iovcnt--;
1538                     }
1539                     if (iovcnt > 0) {
1540                               iov->iov_len -= wlen;
1541                               iov->iov_base = __DECONST(char *, iov->iov_base) + wlen;
1542                     }
1543           }
1544           return (total);
1545 }
1546 
1547 
1548 /*
1549  * Write a line of text to a connection w/ timeout
1550  */
1551 int
fetch_putln(conn_t * conn,const char * str,size_t len)1552 fetch_putln(conn_t *conn, const char *str, size_t len)
1553 {
1554           struct iovec iov[2];
1555           int ret;
1556 
1557           DEBUGF(">>> %s\n", str);
1558           iov[0].iov_base = __DECONST(char *, str);
1559           iov[0].iov_len = len;
1560           iov[1].iov_base = __DECONST(char *, ENDL);
1561           iov[1].iov_len = sizeof(ENDL);
1562           if (len == 0)
1563                     ret = fetch_writev(conn, &iov[1], 1);
1564           else
1565                     ret = fetch_writev(conn, iov, 2);
1566           if (ret == -1)
1567                     return (-1);
1568           return (0);
1569 }
1570 
1571 
1572 /*
1573  * Close connection
1574  */
1575 int
fetch_close(conn_t * conn)1576 fetch_close(conn_t *conn)
1577 {
1578           int ret;
1579 
1580           if (--conn->ref > 0)
1581                     return (0);
1582 #ifdef WITH_SSL
1583           if (conn->ssl) {
1584                     SSL_shutdown(conn->ssl);
1585                     SSL_set_connect_state(conn->ssl);
1586                     SSL_free(conn->ssl);
1587                     conn->ssl = NULL;
1588           }
1589           if (conn->ssl_ctx) {
1590                     SSL_CTX_free(conn->ssl_ctx);
1591                     conn->ssl_ctx = NULL;
1592           }
1593           if (conn->ssl_cert) {
1594                     X509_free(conn->ssl_cert);
1595                     conn->ssl_cert = NULL;
1596           }
1597 #endif
1598           ret = close(conn->sd);
1599           free(conn->buf);
1600           free(conn);
1601           return (ret);
1602 }
1603 
1604 
1605 /*** Directory-related utility functions *************************************/
1606 
1607 int
fetch_add_entry(struct url_ent ** p,int * size,int * len,const char * name,struct url_stat * us)1608 fetch_add_entry(struct url_ent **p, int *size, int *len,
1609     const char *name, struct url_stat *us)
1610 {
1611           struct url_ent *tmp;
1612 
1613           if (*p == NULL) {
1614                     *size = 0;
1615                     *len = 0;
1616           }
1617 
1618           if (*len >= *size - 1) {
1619                     tmp = reallocarray(*p, *size * 2 + 1, sizeof(**p));
1620                     if (tmp == NULL) {
1621                               errno = ENOMEM;
1622                               fetch_syserr();
1623                               return (-1);
1624                     }
1625                     *size = (*size * 2 + 1);
1626                     *p = tmp;
1627           }
1628 
1629           tmp = *p + *len;
1630           snprintf(tmp->name, PATH_MAX, "%s", name);
1631           memcpy(&tmp->stat, us, sizeof(*us));
1632 
1633           (*len)++;
1634           (++tmp)->name[0] = 0;
1635 
1636           return (0);
1637 }
1638 
1639 
1640 /*** Authentication-related utility functions ********************************/
1641 
1642 static const char *
fetch_read_word(FILE * f)1643 fetch_read_word(FILE *f)
1644 {
1645           static char word[1024];
1646 
1647           if (fscanf(f, " %1023s ", word) != 1)
1648                     return (NULL);
1649           return (word);
1650 }
1651 
1652 static int
fetch_netrc_open(void)1653 fetch_netrc_open(void)
1654 {
1655           struct passwd *pwd;
1656           char fn[PATH_MAX];
1657           const char *p;
1658           int fd, serrno;
1659 
1660           if ((p = getenv("NETRC")) != NULL) {
1661                     DEBUGF("NETRC=%s\n", p);
1662                     if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
1663                               fetch_info("$NETRC specifies a file name "
1664                                   "longer than PATH_MAX");
1665                               return (-1);
1666                     }
1667           } else {
1668                     if ((p = getenv("HOME")) == NULL) {
1669                               if ((pwd = getpwuid(getuid())) == NULL ||
1670                                   (p = pwd->pw_dir) == NULL)
1671                                         return (-1);
1672                     }
1673                     if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn))
1674                               return (-1);
1675           }
1676 
1677           if ((fd = open(fn, O_RDONLY)) < 0) {
1678                     serrno = errno;
1679                     DEBUGF("%s: %s\n", fn, strerror(serrno));
1680                     errno = serrno;
1681           }
1682           return (fd);
1683 }
1684 
1685 /*
1686  * Get authentication data for a URL from .netrc
1687  */
1688 int
fetch_netrc_auth(struct url * url)1689 fetch_netrc_auth(struct url *url)
1690 {
1691           const char *word;
1692           int serrno;
1693           FILE *f;
1694 
1695           if (url->netrcfd < 0)
1696                     url->netrcfd = fetch_netrc_open();
1697           if (url->netrcfd < 0)
1698                     return (-1);
1699           if ((f = fdopen(url->netrcfd, "r")) == NULL) {
1700                     serrno = errno;
1701                     DEBUGF("fdopen(netrcfd): %s", strerror(errno));
1702                     close(url->netrcfd);
1703                     url->netrcfd = -1;
1704                     errno = serrno;
1705                     return (-1);
1706           }
1707           rewind(f);
1708           DEBUGF("searching netrc for %s\n", url->host);
1709           while ((word = fetch_read_word(f)) != NULL) {
1710                     if (strcmp(word, "default") == 0) {
1711                               DEBUGF("using default netrc settings\n");
1712                               break;
1713                     }
1714                     if (strcmp(word, "machine") == 0 &&
1715                         (word = fetch_read_word(f)) != NULL &&
1716                         strcasecmp(word, url->host) == 0) {
1717                               DEBUGF("using netrc settings for %s\n", word);
1718                               break;
1719                     }
1720           }
1721           if (word == NULL)
1722                     goto ferr;
1723           while ((word = fetch_read_word(f)) != NULL) {
1724                     if (strcmp(word, "login") == 0) {
1725                               if ((word = fetch_read_word(f)) == NULL)
1726                                         goto ferr;
1727                               if (snprintf(url->user, sizeof(url->user),
1728                                         "%s", word) > (int)sizeof(url->user)) {
1729                                         fetch_info("login name in .netrc is too long");
1730                                         url->user[0] = '\0';
1731                               }
1732                     } else if (strcmp(word, "password") == 0) {
1733                               if ((word = fetch_read_word(f)) == NULL)
1734                                         goto ferr;
1735                               if (snprintf(url->pwd, sizeof(url->pwd),
1736                                         "%s", word) > (int)sizeof(url->pwd)) {
1737                                         fetch_info("password in .netrc is too long");
1738                                         url->pwd[0] = '\0';
1739                               }
1740                     } else if (strcmp(word, "account") == 0) {
1741                               if ((word = fetch_read_word(f)) == NULL)
1742                                         goto ferr;
1743                               /* XXX not supported! */
1744                     } else {
1745                               break;
1746                     }
1747           }
1748           fclose(f);
1749           url->netrcfd = -1;
1750           return (0);
1751 ferr:
1752           serrno = errno;
1753           fclose(f);
1754           url->netrcfd = -1;
1755           errno = serrno;
1756           return (-1);
1757 }
1758 
1759 /*
1760  * The no_proxy environment variable specifies a set of domains for
1761  * which the proxy should not be consulted; the contents is a comma-,
1762  * or space-separated list of domain names.  A single asterisk will
1763  * override all proxy variables and no transactions will be proxied
1764  * (for compatibility with lynx and curl, see the discussion at
1765  * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>).
1766  */
1767 int
fetch_no_proxy_match(const char * host)1768 fetch_no_proxy_match(const char *host)
1769 {
1770           const char *no_proxy, *p, *q;
1771           size_t h_len, d_len;
1772 
1773           if ((no_proxy = getenv("NO_PROXY")) == NULL &&
1774               (no_proxy = getenv("no_proxy")) == NULL)
1775                     return (0);
1776 
1777           /* asterisk matches any hostname */
1778           if (strcmp(no_proxy, "*") == 0)
1779                     return (1);
1780 
1781           h_len = strlen(host);
1782           p = no_proxy;
1783           do {
1784                     /* position p at the beginning of a domain suffix */
1785                     while (*p == ',' || isspace((unsigned char)*p))
1786                               p++;
1787 
1788                     /* position q at the first separator character */
1789                     for (q = p; *q; ++q)
1790                               if (*q == ',' || isspace((unsigned char)*q))
1791                                         break;
1792 
1793                     d_len = q - p;
1794                     if (d_len > 0 && h_len >= d_len &&
1795                         strncasecmp(host + h_len - d_len,
1796                               p, d_len) == 0) {
1797                               /* domain name matches */
1798                               return (1);
1799                     }
1800 
1801                     p = q + 1;
1802           } while (*q);
1803 
1804           return (0);
1805 }
1806