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