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