2 * Copyright (c) 1998-2014 Dag-Erling Smørgrav
3 * Copyright (c) 2013 Michael Gmelin <freebsd@grem.de>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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 * $FreeBSD: head/lib/libfetch/common.c 266291 2014-05-17 03:39:56Z des $
31 #include <sys/cdefs.h>
32 #include <sys/param.h>
33 #include <sys/socket.h>
37 #include <netinet/in.h>
52 #include <openssl/x509v3.h>
59 /*** Local data **************************************************************/
62 * Error messages for resolver errors
64 static struct fetcherr netdb_errlist
[] = {
66 { EAI_NODATA
, FETCH_RESOLV
, "Host not found" },
68 { EAI_AGAIN
, FETCH_TEMP
, "Transient resolver failure" },
69 { EAI_FAIL
, FETCH_RESOLV
, "Non-recoverable resolver failure" },
70 { EAI_NONAME
, FETCH_RESOLV
, "No address record" },
71 { -1, FETCH_UNKNOWN
, "Unknown resolver error" }
75 static const char ENDL
[2] = "\r\n";
78 /*** Error-reporting functions ***********************************************/
81 * Map error code to string
83 static struct fetcherr
*
84 fetch_finderr(struct fetcherr
*p
, int e
)
86 while (p
->num
!= -1 && p
->num
!= e
)
95 fetch_seterr(struct fetcherr
*p
, int e
)
97 p
= fetch_finderr(p
, e
);
98 fetchLastErrCode
= p
->cat
;
99 snprintf(fetchLastErrString
, MAXERRSTRING
, "%s", p
->string
);
103 * Set error code according to errno
110 fetchLastErrCode
= FETCH_OK
;
117 fetchLastErrCode
= FETCH_AUTH
;
120 case EISDIR
: /* XXX */
121 fetchLastErrCode
= FETCH_UNAVAIL
;
124 fetchLastErrCode
= FETCH_MEMORY
;
128 fetchLastErrCode
= FETCH_TEMP
;
131 fetchLastErrCode
= FETCH_EXISTS
;
134 fetchLastErrCode
= FETCH_FULL
;
142 fetchLastErrCode
= FETCH_NETWORK
;
146 fetchLastErrCode
= FETCH_ABORT
;
149 fetchLastErrCode
= FETCH_TIMEOUT
;
153 fetchLastErrCode
= FETCH_DOWN
;
156 fetchLastErrCode
= FETCH_UNKNOWN
;
158 snprintf(fetchLastErrString
, MAXERRSTRING
, "%s", strerror(errno
));
163 * Emit status message
166 fetch_info(const char *fmt
, ...)
171 vfprintf(stderr
, fmt
, ap
);
177 /*** Network-related utility functions ***************************************/
180 * Return the default port for a scheme
183 fetch_default_port(const char *scheme
)
187 if ((se
= getservbyname(scheme
, "tcp")) != NULL
)
188 return (ntohs(se
->s_port
));
189 if (strcasecmp(scheme
, SCHEME_FTP
) == 0)
190 return (FTP_DEFAULT_PORT
);
191 if (strcasecmp(scheme
, SCHEME_HTTP
) == 0)
192 return (HTTP_DEFAULT_PORT
);
197 * Return the default proxy port for a scheme
200 fetch_default_proxy_port(const char *scheme
)
202 if (strcasecmp(scheme
, SCHEME_FTP
) == 0)
203 return (FTP_DEFAULT_PROXY_PORT
);
204 if (strcasecmp(scheme
, SCHEME_HTTP
) == 0)
205 return (HTTP_DEFAULT_PROXY_PORT
);
211 * Create a connection for an existing descriptor.
219 /* allocate and fill connection structure */
220 if ((conn
= calloc(1, sizeof(*conn
))) == NULL
)
222 fcntl(sd
, F_SETFD
, FD_CLOEXEC
);
223 setsockopt(sd
, SOL_SOCKET
, SO_NOSIGPIPE
, &opt
, sizeof opt
);
231 * Bump a connection's reference count.
234 fetch_ref(conn_t
*conn
)
243 * Bind a socket to a specific local address
246 fetch_bind(int sd
, int af
, const char *addr
)
248 struct addrinfo hints
, *res
, *res0
;
251 memset(&hints
, 0, sizeof(hints
));
252 hints
.ai_family
= af
;
253 hints
.ai_socktype
= SOCK_STREAM
;
254 hints
.ai_protocol
= 0;
255 if ((err
= getaddrinfo(addr
, NULL
, &hints
, &res0
)) != 0)
257 for (res
= res0
; res
; res
= res
->ai_next
)
258 if (bind(sd
, res
->ai_addr
, res
->ai_addrlen
) == 0)
265 * Establish a TCP connection to the specified port on the specified host.
268 fetch_connect(const char *host
, int port
, int af
, int verbose
)
272 const char *bindaddr
;
273 struct addrinfo hints
, *res
, *res0
;
276 DEBUG(fprintf(stderr
, "---> %s:%d\n", host
, port
));
279 fetch_info("looking up %s", host
);
281 /* look up host name and set up socket address structure */
282 snprintf(pbuf
, sizeof(pbuf
), "%d", port
);
283 memset(&hints
, 0, sizeof(hints
));
284 hints
.ai_family
= af
;
285 hints
.ai_socktype
= SOCK_STREAM
;
286 hints
.ai_protocol
= 0;
287 if ((err
= getaddrinfo(host
, pbuf
, &hints
, &res0
)) != 0) {
291 bindaddr
= getenv("FETCH_BIND_ADDRESS");
294 fetch_info("connecting to %s:%d", host
, port
);
297 for (sd
= -1, res
= res0
; res
; sd
= -1, res
= res
->ai_next
) {
298 if ((sd
= socket(res
->ai_family
, res
->ai_socktype
,
299 res
->ai_protocol
)) == -1)
301 if (bindaddr
!= NULL
&& *bindaddr
!= '\0' &&
302 fetch_bind(sd
, res
->ai_family
, bindaddr
) != 0) {
303 fetch_info("failed to bind to '%s'", bindaddr
);
307 if (connect(sd
, res
->ai_addr
, res
->ai_addrlen
) == 0 &&
308 fcntl(sd
, F_SETFL
, O_NONBLOCK
) == 0)
318 if ((conn
= fetch_reopen(sd
)) == NULL
) {
327 * Convert characters A-Z to lowercase (intentionally avoid any locale
328 * specific conversions).
331 fetch_ssl_tolower(char in
)
333 if (in
>= 'A' && in
<= 'Z')
340 * isalpha implementation that intentionally avoids any locale specific
344 fetch_ssl_isalpha(char in
)
346 return ((in
>= 'A' && in
<= 'Z') || (in
>= 'a' && in
<= 'z'));
350 * Check if passed hostnames a and b are equal.
353 fetch_ssl_hname_equal(const char *a
, size_t alen
, const char *b
,
360 for (i
= 0; i
< alen
; ++i
) {
361 if (fetch_ssl_tolower(a
[i
]) != fetch_ssl_tolower(b
[i
]))
368 * Check if domain label is traditional, meaning that only A-Z, a-z, 0-9
369 * and '-' (hyphen) are allowed. Hyphens have to be surrounded by alpha-
370 * numeric characters. Double hyphens (like they're found in IDN a-labels
371 * 'xn--') are not allowed. Empty labels are invalid.
374 fetch_ssl_is_trad_domain_label(const char *l
, size_t len
, int wcok
)
378 if (!len
|| l
[0] == '-' || l
[len
-1] == '-')
380 for (i
= 0; i
< len
; ++i
) {
381 if (!isdigit(l
[i
]) &&
382 !fetch_ssl_isalpha(l
[i
]) &&
383 !(l
[i
] == '*' && wcok
) &&
384 !(l
[i
] == '-' && l
[i
- 1] != '-'))
391 * Check if host name consists only of numbers. This might indicate an IP
392 * address, which is not a good idea for CN wildcard comparison.
395 fetch_ssl_hname_is_only_numbers(const char *hostname
, size_t len
)
399 for (i
= 0; i
< len
; ++i
) {
400 if (!((hostname
[i
] >= '0' && hostname
[i
] <= '9') ||
408 * Check if the host name h passed matches the pattern passed in m which
409 * is usually part of subjectAltName or CN of a certificate presented to
410 * the client. This includes wildcard matching. The algorithm is based on
411 * RFC6125, sections 6.4.3 and 7.2, which clarifies RFC2818 and RFC3280.
414 fetch_ssl_hname_match(const char *h
, size_t hlen
, const char *m
,
417 int delta
, hdotidx
, mdot1idx
, wcidx
;
418 const char *hdot
, *mdot1
, *mdot2
;
419 const char *wc
; /* wildcard */
421 if (!(h
&& *h
&& m
&& *m
))
423 if ((wc
= strnstr(m
, "*", mlen
)) == NULL
)
424 return (fetch_ssl_hname_equal(h
, hlen
, m
, mlen
));
426 /* hostname should not be just dots and numbers */
427 if (fetch_ssl_hname_is_only_numbers(h
, hlen
))
429 /* only one wildcard allowed in pattern */
430 if (strnstr(wc
+ 1, "*", mlen
- wcidx
- 1) != NULL
)
433 * there must be at least two more domain labels and
434 * wildcard has to be in the leftmost label (RFC6125)
436 mdot1
= strnstr(m
, ".", mlen
);
437 if (mdot1
== NULL
|| mdot1
< wc
|| (mlen
- (mdot1
- m
)) < 4)
439 mdot1idx
= mdot1
- m
;
440 mdot2
= strnstr(mdot1
+ 1, ".", mlen
- mdot1idx
- 1);
441 if (mdot2
== NULL
|| (mlen
- (mdot2
- m
)) < 2)
443 /* hostname must contain a dot and not be the 1st char */
444 hdot
= strnstr(h
, ".", hlen
);
445 if (hdot
== NULL
|| hdot
== h
)
449 * host part of hostname must be at least as long as
450 * pattern it's supposed to match
452 if (hdotidx
< mdot1idx
)
455 * don't allow wildcards in non-traditional domain names
456 * (IDN, A-label, U-label...)
458 if (!fetch_ssl_is_trad_domain_label(h
, hdotidx
, 0) ||
459 !fetch_ssl_is_trad_domain_label(m
, mdot1idx
, 1))
461 /* match domain part (part after first dot) */
462 if (!fetch_ssl_hname_equal(hdot
, hlen
- hdotidx
, mdot1
,
465 /* match part left of wildcard */
466 if (!fetch_ssl_hname_equal(h
, wcidx
, m
, wcidx
))
468 /* match part right of wildcard */
469 delta
= mdot1idx
- wcidx
- 1;
470 if (!fetch_ssl_hname_equal(hdot
- delta
, delta
,
471 mdot1
- delta
, delta
))
473 /* all tests succeded, it's a match */
478 * Get numeric host address info - returns NULL if host was not an IP
479 * address. The caller is responsible for deallocation using
482 static struct addrinfo
*
483 fetch_ssl_get_numeric_addrinfo(const char *hostname
, size_t len
)
485 struct addrinfo hints
, *res
;
488 host
= (char *)malloc(len
+ 1);
489 memcpy(host
, hostname
, len
);
491 memset(&hints
, 0, sizeof(hints
));
492 hints
.ai_family
= PF_UNSPEC
;
493 hints
.ai_socktype
= SOCK_STREAM
;
494 hints
.ai_protocol
= 0;
495 hints
.ai_flags
= AI_NUMERICHOST
;
496 /* port is not relevant for this purpose */
497 getaddrinfo(host
, "443", &hints
, &res
);
503 * Compare ip address in addrinfo with address passes.
506 fetch_ssl_ipaddr_match_bin(const struct addrinfo
*lhost
, const char *rhost
,
511 if (lhost
->ai_family
== AF_INET
&& rhostlen
== 4) {
512 left
= (void *)&((struct sockaddr_in
*)(void *)
513 lhost
->ai_addr
)->sin_addr
.s_addr
;
515 } else if (lhost
->ai_family
== AF_INET6
&& rhostlen
== 16) {
516 left
= (void *)&((struct sockaddr_in6
*)(void *)
517 lhost
->ai_addr
)->sin6_addr
;
521 return (!memcmp(left
, (const void *)rhost
, rhostlen
) ? 1 : 0);
525 * Compare ip address in addrinfo with host passed. If host is not an IP
526 * address, comparison will fail.
529 fetch_ssl_ipaddr_match(const struct addrinfo
*laddr
, const char *r
,
532 struct addrinfo
*raddr
;
537 if ((raddr
= fetch_ssl_get_numeric_addrinfo(r
, rlen
)) == NULL
)
538 return 0; /* not a numeric host */
540 if (laddr
->ai_family
== raddr
->ai_family
) {
541 if (laddr
->ai_family
== AF_INET
) {
542 rip
= (char *)&((struct sockaddr_in
*)(void *)
543 raddr
->ai_addr
)->sin_addr
.s_addr
;
544 ret
= fetch_ssl_ipaddr_match_bin(laddr
, rip
, 4);
546 } else if (laddr
->ai_family
== AF_INET6
) {
547 rip
= (char *)&((struct sockaddr_in6
*)(void *)
548 raddr
->ai_addr
)->sin6_addr
;
549 ret
= fetch_ssl_ipaddr_match_bin(laddr
, rip
, 16);
559 * Verify server certificate by subjectAltName.
562 fetch_ssl_verify_altname(STACK_OF(GENERAL_NAME
) *altnames
,
563 const char *host
, struct addrinfo
*ip
)
565 const GENERAL_NAME
*name
;
570 for (i
= 0; i
< sk_GENERAL_NAME_num(altnames
); ++i
) {
571 #if OPENSSL_VERSION_NUMBER < 0x10000000L
573 * This is a workaround, since the following line causes
574 * alignment issues in clang:
575 * name = sk_GENERAL_NAME_value(altnames, i);
576 * OpenSSL explicitly warns not to use those macros
577 * directly, but there isn't much choice (and there
578 * shouldn't be any ill side effects)
580 name
= (GENERAL_NAME
*)SKM_sk_value(void, altnames
, i
);
582 name
= sk_GENERAL_NAME_value(altnames
, i
);
584 ns
= (const char *)ASN1_STRING_data(name
->d
.ia5
);
585 nslen
= (size_t)ASN1_STRING_length(name
->d
.ia5
);
587 if (name
->type
== GEN_DNS
&& ip
== NULL
&&
588 fetch_ssl_hname_match(host
, strlen(host
), ns
, nslen
))
590 else if (name
->type
== GEN_IPADD
&& ip
!= NULL
&&
591 fetch_ssl_ipaddr_match_bin(ip
, ns
, nslen
))
598 * Verify server certificate by CN.
601 fetch_ssl_verify_cn(X509_NAME
*subject
, const char *host
,
604 ASN1_STRING
*namedata
;
605 X509_NAME_ENTRY
*nameentry
;
606 int cnlen
, lastpos
, loc
, ret
;
613 /* get most specific CN (last entry in list) and compare */
614 while ((lastpos
= X509_NAME_get_index_by_NID(subject
,
615 NID_commonName
, lastpos
)) != -1)
619 nameentry
= X509_NAME_get_entry(subject
, loc
);
620 namedata
= X509_NAME_ENTRY_get_data(nameentry
);
621 cnlen
= ASN1_STRING_to_UTF8(&cn
, namedata
);
623 fetch_ssl_hname_match(host
, strlen(host
), cn
, cnlen
))
625 else if (ip
!= NULL
&& fetch_ssl_ipaddr_match(ip
, cn
, cnlen
))
633 * Verify that server certificate subjectAltName/CN matches
634 * hostname. First check, if there are alternative subject names. If yes,
635 * those have to match. Only if those don't exist it falls back to
636 * checking the subject's CN.
639 fetch_ssl_verify_hname(X509
*cert
, const char *host
)
642 STACK_OF(GENERAL_NAME
) *altnames
;
647 ip
= fetch_ssl_get_numeric_addrinfo(host
, strlen(host
));
648 altnames
= X509_get_ext_d2i(cert
, NID_subject_alt_name
,
651 if (altnames
!= NULL
) {
652 ret
= fetch_ssl_verify_altname(altnames
, host
, ip
);
654 subject
= X509_get_subject_name(cert
);
656 ret
= fetch_ssl_verify_cn(subject
, host
, ip
);
661 if (altnames
!= NULL
)
662 GENERAL_NAMES_free(altnames
);
667 * Configure transport security layer based on environment.
670 fetch_ssl_setup_transport_layer(SSL_CTX
*ctx
, int verbose
)
672 long ssl_ctx_options
;
674 ssl_ctx_options
= SSL_OP_ALL
| SSL_OP_NO_TICKET
;
675 if (getenv("SSL_ALLOW_SSL2") == NULL
)
676 ssl_ctx_options
|= SSL_OP_NO_SSLv2
;
677 if (getenv("SSL_NO_SSL3") != NULL
)
678 ssl_ctx_options
|= SSL_OP_NO_SSLv3
;
679 if (getenv("SSL_NO_TLS1") != NULL
)
680 ssl_ctx_options
|= SSL_OP_NO_TLSv1
;
682 fetch_info("SSL options: %lx", ssl_ctx_options
);
683 SSL_CTX_set_options(ctx
, ssl_ctx_options
);
688 * Configure peer verification based on environment.
690 #define LOCAL_CERT_FILE "/usr/local/etc/ssl/cert.pem"
691 #define BASE_CERT_FILE "/etc/ssl/cert.pem"
693 fetch_ssl_setup_peer_verification(SSL_CTX
*ctx
, int verbose
)
695 X509_LOOKUP
*crl_lookup
;
696 X509_STORE
*crl_store
;
697 const char *ca_cert_file
, *ca_cert_path
, *crl_file
;
699 if (getenv("SSL_NO_VERIFY_PEER") == NULL
) {
700 ca_cert_file
= getenv("SSL_CA_CERT_FILE");
701 if (ca_cert_file
== NULL
&&
702 access(LOCAL_CERT_FILE
, R_OK
) == 0)
703 ca_cert_file
= LOCAL_CERT_FILE
;
704 if (ca_cert_file
== NULL
)
705 ca_cert_file
= BASE_CERT_FILE
;
706 ca_cert_path
= getenv("SSL_CA_CERT_PATH");
708 fetch_info("Peer verification enabled");
709 if (ca_cert_file
!= NULL
)
710 fetch_info("Using CA cert file: %s",
712 if (ca_cert_path
!= NULL
)
713 fetch_info("Using CA cert path: %s",
716 SSL_CTX_set_verify(ctx
, SSL_VERIFY_PEER
,
717 fetch_ssl_cb_verify_crt
);
718 SSL_CTX_load_verify_locations(ctx
, ca_cert_file
,
720 if ((crl_file
= getenv("SSL_CRL_FILE")) != NULL
) {
722 fetch_info("Using CRL file: %s", crl_file
);
723 crl_store
= SSL_CTX_get_cert_store(ctx
);
724 crl_lookup
= X509_STORE_add_lookup(crl_store
,
726 if (crl_lookup
== NULL
||
727 !X509_load_crl_file(crl_lookup
, crl_file
,
728 X509_FILETYPE_PEM
)) {
730 "Could not load CRL file %s\n",
734 X509_STORE_set_flags(crl_store
,
735 X509_V_FLAG_CRL_CHECK
|
736 X509_V_FLAG_CRL_CHECK_ALL
);
743 * Configure client certificate based on environment.
746 fetch_ssl_setup_client_certificate(SSL_CTX
*ctx
, int verbose
)
748 const char *client_cert_file
, *client_key_file
;
750 if ((client_cert_file
= getenv("SSL_CLIENT_CERT_FILE")) != NULL
) {
751 client_key_file
= getenv("SSL_CLIENT_KEY_FILE") != NULL
?
752 getenv("SSL_CLIENT_KEY_FILE") : client_cert_file
;
754 fetch_info("Using client cert file: %s",
756 fetch_info("Using client key file: %s",
759 if (SSL_CTX_use_certificate_chain_file(ctx
,
760 client_cert_file
) != 1) {
762 "Could not load client certificate %s\n",
766 if (SSL_CTX_use_PrivateKey_file(ctx
, client_key_file
,
767 SSL_FILETYPE_PEM
) != 1) {
769 "Could not load client key %s\n",
778 * Callback for SSL certificate verification, this is called on server
779 * cert verification. It takes no decision, but informs the user in case
780 * verification failed.
783 fetch_ssl_cb_verify_crt(int verified
, X509_STORE_CTX
*ctx
)
791 if ((crt
= X509_STORE_CTX_get_current_cert(ctx
)) != NULL
&&
792 (name
= X509_get_subject_name(crt
)) != NULL
)
793 str
= X509_NAME_oneline(name
, 0, 0);
794 fprintf(stderr
, "Certificate verification failed for %s\n",
795 str
!= NULL
? str
: "no relevant certificate");
804 * Enable SSL on a connection.
807 fetch_ssl(conn_t
*conn
, const struct url
*URL
, int verbose
)
814 /* Init the SSL library and context */
815 if (!SSL_library_init()){
816 fprintf(stderr
, "SSL library init failed\n");
820 SSL_load_error_strings();
822 conn
->ssl_meth
= SSLv23_client_method();
823 conn
->ssl_ctx
= SSL_CTX_new(conn
->ssl_meth
);
824 SSL_CTX_set_mode(conn
->ssl_ctx
, SSL_MODE_AUTO_RETRY
);
826 fetch_ssl_setup_transport_layer(conn
->ssl_ctx
, verbose
);
827 if (!fetch_ssl_setup_peer_verification(conn
->ssl_ctx
, verbose
))
829 if (!fetch_ssl_setup_client_certificate(conn
->ssl_ctx
, verbose
))
832 conn
->ssl
= SSL_new(conn
->ssl_ctx
);
833 if (conn
->ssl
== NULL
) {
834 fprintf(stderr
, "SSL context creation failed\n");
837 SSL_set_fd(conn
->ssl
, conn
->sd
);
839 #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
840 if (!SSL_set_tlsext_host_name(conn
->ssl
,
841 __DECONST(struct url
*, URL
)->host
)) {
843 "TLS server name indication extension failed for host %s\n",
848 while ((ret
= SSL_connect(conn
->ssl
)) == -1) {
849 ssl_err
= SSL_get_error(conn
->ssl
, ret
);
850 if (ssl_err
!= SSL_ERROR_WANT_READ
&&
851 ssl_err
!= SSL_ERROR_WANT_WRITE
) {
852 ERR_print_errors_fp(stderr
);
856 conn
->ssl_cert
= SSL_get_peer_certificate(conn
->ssl
);
858 if (conn
->ssl_cert
== NULL
) {
859 fprintf(stderr
, "No server SSL certificate\n");
863 if (getenv("SSL_NO_VERIFY_HOSTNAME") == NULL
) {
865 fetch_info("Verify hostname");
866 if (!fetch_ssl_verify_hname(conn
->ssl_cert
, URL
->host
)) {
868 "SSL certificate subject doesn't match host %s\n",
875 fetch_info("SSL connection established using %s",
876 SSL_get_cipher(conn
->ssl
));
877 name
= X509_get_subject_name(conn
->ssl_cert
);
878 str
= X509_NAME_oneline(name
, 0, 0);
879 fetch_info("Certificate subject: %s", str
);
881 name
= X509_get_issuer_name(conn
->ssl_cert
);
882 str
= X509_NAME_oneline(name
, 0, 0);
883 fetch_info("Certificate issuer: %s", str
);
891 fprintf(stderr
, "SSL support disabled\n");
896 #define FETCH_READ_WAIT -2
897 #define FETCH_READ_ERROR -1
898 #define FETCH_READ_DONE 0
902 fetch_ssl_read(SSL
*ssl
, char *buf
, size_t len
)
907 rlen
= SSL_read(ssl
, buf
, len
);
909 ssl_err
= SSL_get_error(ssl
, rlen
);
910 if (ssl_err
== SSL_ERROR_WANT_READ
||
911 ssl_err
== SSL_ERROR_WANT_WRITE
) {
912 return (FETCH_READ_WAIT
);
914 ERR_print_errors_fp(stderr
);
915 return (FETCH_READ_ERROR
);
923 fetch_socket_read(int sd
, char *buf
, size_t len
)
927 rlen
= read(sd
, buf
, len
);
929 if (errno
== EAGAIN
|| (errno
== EINTR
&& fetchRestartCalls
))
930 return (FETCH_READ_WAIT
);
932 return (FETCH_READ_ERROR
);
938 * Read a character from a connection w/ timeout
941 fetch_read(conn_t
*conn
, char *buf
, size_t len
)
943 struct timeval now
, timeout
, delta
;
948 if (fetchTimeout
> 0) {
949 gettimeofday(&timeout
, NULL
);
950 timeout
.tv_sec
+= fetchTimeout
;
954 memset(&pfd
, 0, sizeof pfd
);
956 pfd
.events
= POLLIN
| POLLERR
;
960 * The socket is non-blocking. Instead of the canonical
961 * poll() -> read(), we do the following:
963 * 1) call read() or SSL_read().
964 * 2) if we received some data, return it.
965 * 3) if an error occurred, return -1.
966 * 4) if read() or SSL_read() signaled EOF, return.
967 * 5) if we did not receive any data but we're not at EOF,
970 * In the SSL case, this is necessary because if we
971 * receive a close notification, we have to call
972 * SSL_read() one additional time after we've read
973 * everything we received.
975 * In the non-SSL case, it may improve performance (very
976 * slightly) when reading small amounts of data.
979 if (conn
->ssl
!= NULL
)
980 rlen
= fetch_ssl_read(conn
->ssl
, buf
, len
);
983 rlen
= fetch_socket_read(conn
->sd
, buf
, len
);
986 } else if (rlen
== FETCH_READ_ERROR
) {
990 // assert(rlen == FETCH_READ_WAIT);
991 if (fetchTimeout
> 0) {
992 gettimeofday(&now
, NULL
);
993 if (!timercmp(&timeout
, &now
, >)) {
998 timersub(&timeout
, &now
, &delta
);
999 deltams
= delta
.tv_sec
* 1000 +
1000 delta
.tv_usec
/ 1000;;
1004 if (poll(&pfd
, 1, deltams
) < 0) {
1005 if (errno
== EINTR
&& fetchRestartCalls
)
1016 * Read a line of text from a connection w/ timeout
1018 #define MIN_BUF_SIZE 1024
1021 fetch_getln(conn_t
*conn
)
1028 if (conn
->buf
== NULL
) {
1029 if ((conn
->buf
= malloc(MIN_BUF_SIZE
)) == NULL
) {
1033 conn
->bufsize
= MIN_BUF_SIZE
;
1036 conn
->buf
[0] = '\0';
1040 len
= fetch_read(conn
, &c
, 1);
1045 conn
->buf
[conn
->buflen
++] = c
;
1046 if (conn
->buflen
== conn
->bufsize
) {
1048 tmpsize
= conn
->bufsize
* 2 + 1;
1049 if ((tmp
= realloc(tmp
, tmpsize
)) == NULL
) {
1054 conn
->bufsize
= tmpsize
;
1056 } while (c
!= '\n');
1058 conn
->buf
[conn
->buflen
] = '\0';
1059 DEBUG(fprintf(stderr
, "<<< %s", conn
->buf
));
1065 * Write to a connection w/ timeout
1068 fetch_write(conn_t
*conn
, const char *buf
, size_t len
)
1072 iov
.iov_base
= __DECONST(char *, buf
);
1074 return fetch_writev(conn
, &iov
, 1);
1078 * Write a vector to a connection w/ timeout
1079 * Note: can modify the iovec.
1082 fetch_writev(conn_t
*conn
, struct iovec
*iov
, int iovcnt
)
1084 struct timeval now
, timeout
, delta
;
1086 ssize_t wlen
, total
;
1089 memset(&pfd
, 0, sizeof pfd
);
1092 pfd
.events
= POLLOUT
| POLLERR
;
1093 gettimeofday(&timeout
, NULL
);
1094 timeout
.tv_sec
+= fetchTimeout
;
1098 while (iovcnt
> 0) {
1099 while (fetchTimeout
&& pfd
.revents
== 0) {
1100 gettimeofday(&now
, NULL
);
1101 if (!timercmp(&timeout
, &now
, >)) {
1106 timersub(&timeout
, &now
, &delta
);
1107 deltams
= delta
.tv_sec
* 1000 +
1108 delta
.tv_usec
/ 1000;
1111 if (poll(&pfd
, 1, deltams
) < 0) {
1112 if (errno
== EINTR
&& fetchRestartCalls
)
1119 if (conn
->ssl
!= NULL
)
1120 wlen
= SSL_write(conn
->ssl
,
1121 iov
->iov_base
, iov
->iov_len
);
1124 wlen
= writev(conn
->sd
, iov
, iovcnt
);
1126 /* we consider a short write a failure */
1127 /* XXX perhaps we shouldn't in the SSL case */
1133 if (errno
== EINTR
&& fetchRestartCalls
)
1138 while (iovcnt
> 0 && wlen
>= (ssize_t
)iov
->iov_len
) {
1139 wlen
-= iov
->iov_len
;
1144 iov
->iov_len
-= wlen
;
1145 iov
->iov_base
= __DECONST(char *, iov
->iov_base
) + wlen
;
1153 * Write a line of text to a connection w/ timeout
1156 fetch_putln(conn_t
*conn
, const char *str
, size_t len
)
1158 struct iovec iov
[2];
1161 DEBUG(fprintf(stderr
, ">>> %s\n", str
));
1162 iov
[0].iov_base
= __DECONST(char *, str
);
1163 iov
[0].iov_len
= len
;
1164 iov
[1].iov_base
= __DECONST(char *, ENDL
);
1165 iov
[1].iov_len
= sizeof(ENDL
);
1167 ret
= fetch_writev(conn
, &iov
[1], 1);
1169 ret
= fetch_writev(conn
, iov
, 2);
1180 fetch_close(conn_t
*conn
)
1184 if (--conn
->ref
> 0)
1188 SSL_shutdown(conn
->ssl
);
1189 SSL_set_connect_state(conn
->ssl
);
1190 SSL_free(conn
->ssl
);
1193 if (conn
->ssl_ctx
) {
1194 SSL_CTX_free(conn
->ssl_ctx
);
1195 conn
->ssl_ctx
= NULL
;
1197 if (conn
->ssl_cert
) {
1198 X509_free(conn
->ssl_cert
);
1199 conn
->ssl_cert
= NULL
;
1202 ret
= close(conn
->sd
);
1209 /*** Directory-related utility functions *************************************/
1212 fetch_add_entry(struct url_ent
**p
, int *size
, int *len
,
1213 const char *name
, struct url_stat
*us
)
1215 struct url_ent
*tmp
;
1222 if (*len
>= *size
- 1) {
1223 tmp
= realloc(*p
, (*size
* 2 + 1) * sizeof(**p
));
1229 *size
= (*size
* 2 + 1);
1234 snprintf(tmp
->name
, PATH_MAX
, "%s", name
);
1235 memcpy(&tmp
->stat
, us
, sizeof(*us
));
1238 (++tmp
)->name
[0] = 0;
1244 /*** Authentication-related utility functions ********************************/
1247 fetch_read_word(FILE *f
)
1249 static char word
[1024];
1251 if (fscanf(f
, " %1023s ", word
) != 1)
1257 * Get authentication data for a URL from .netrc
1260 fetch_netrc_auth(struct url
*url
)
1267 if ((p
= getenv("NETRC")) != NULL
) {
1268 if (snprintf(fn
, sizeof(fn
), "%s", p
) >= (int)sizeof(fn
)) {
1269 fetch_info("$NETRC specifies a file name "
1270 "longer than PATH_MAX");
1274 if ((p
= getenv("HOME")) != NULL
) {
1277 if ((pwd
= getpwuid(getuid())) == NULL
||
1278 (p
= pwd
->pw_dir
) == NULL
)
1281 if (snprintf(fn
, sizeof(fn
), "%s/.netrc", p
) >= (int)sizeof(fn
))
1285 if ((f
= fopen(fn
, "r")) == NULL
)
1287 while ((word
= fetch_read_word(f
)) != NULL
) {
1288 if (strcmp(word
, "default") == 0) {
1289 DEBUG(fetch_info("Using default .netrc settings"));
1292 if (strcmp(word
, "machine") == 0 &&
1293 (word
= fetch_read_word(f
)) != NULL
&&
1294 strcasecmp(word
, url
->host
) == 0) {
1295 DEBUG(fetch_info("Using .netrc settings for %s", word
));
1301 while ((word
= fetch_read_word(f
)) != NULL
) {
1302 if (strcmp(word
, "login") == 0) {
1303 if ((word
= fetch_read_word(f
)) == NULL
)
1305 if (snprintf(url
->user
, sizeof(url
->user
),
1306 "%s", word
) > (int)sizeof(url
->user
)) {
1307 fetch_info("login name in .netrc is too long");
1308 url
->user
[0] = '\0';
1310 } else if (strcmp(word
, "password") == 0) {
1311 if ((word
= fetch_read_word(f
)) == NULL
)
1313 if (snprintf(url
->pwd
, sizeof(url
->pwd
),
1314 "%s", word
) > (int)sizeof(url
->pwd
)) {
1315 fetch_info("password in .netrc is too long");
1318 } else if (strcmp(word
, "account") == 0) {
1319 if ((word
= fetch_read_word(f
)) == NULL
)
1321 /* XXX not supported! */
1334 * The no_proxy environment variable specifies a set of domains for
1335 * which the proxy should not be consulted; the contents is a comma-,
1336 * or space-separated list of domain names. A single asterisk will
1337 * override all proxy variables and no transactions will be proxied
1338 * (for compatability with lynx and curl, see the discussion at
1339 * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>).
1342 fetch_no_proxy_match(const char *host
)
1344 const char *no_proxy
, *p
, *q
;
1345 size_t h_len
, d_len
;
1347 if ((no_proxy
= getenv("NO_PROXY")) == NULL
&&
1348 (no_proxy
= getenv("no_proxy")) == NULL
)
1351 /* asterisk matches any hostname */
1352 if (strcmp(no_proxy
, "*") == 0)
1355 h_len
= strlen(host
);
1358 /* position p at the beginning of a domain suffix */
1359 while (*p
== ',' || isspace((unsigned char)*p
))
1362 /* position q at the first separator character */
1363 for (q
= p
; *q
; ++q
)
1364 if (*q
== ',' || isspace((unsigned char)*q
))
1368 if (d_len
> 0 && h_len
>= d_len
&&
1369 strncasecmp(host
+ h_len
- d_len
,
1371 /* domain name matches */