Home | History | Annotate | Line # | Download | only in ftp
      1 /*	$NetBSD: ssl.c,v 1.20 2024/09/25 16:53:58 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998-2004 Dag-Erling Codan Smrgrav
      5  * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg (at) NetBSD.org>
      6  * Copyright (c) 2015 Thomas Klausner <wiz (at) NetBSD.org>
      7  * Copyright (c) 2023 Michael van Elst <mlelstv (at) NetBSD.org>
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer
     15  *    in this position and unchanged.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  *
     33  * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 __RCSID("$NetBSD: ssl.c,v 1.20 2024/09/25 16:53:58 christos Exp $");
     39 #endif
     40 
     41 #include <err.h>
     42 #include <errno.h>
     43 #include <fcntl.h>
     44 #include <stdarg.h>
     45 #include <stdio.h>
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <time.h>
     49 #include <unistd.h>
     50 
     51 #include <sys/param.h>
     52 #include <sys/uio.h>
     53 
     54 #include <netinet/tcp.h>
     55 #include <netinet/in.h>
     56 
     57 #ifdef WITH_SSL
     58 #include <openssl/crypto.h>
     59 #include <openssl/x509.h>
     60 #include <openssl/pem.h>
     61 #include <openssl/ssl.h>
     62 #include <openssl/err.h>
     63 #endif
     64 
     65 #include "ssl.h"
     66 #include "ftp_var.h"
     67 
     68 extern int quit_time, verbose, ftp_debug;
     69 extern FILE *ttyout;
     70 
     71 struct fetch_connect {
     72 	int			 sd;		/* file/socket descriptor */
     73 	char			*buf;		/* buffer */
     74 	size_t			 bufsize;	/* buffer size */
     75 	size_t			 bufpos;	/* position of buffer */
     76 	size_t			 buflen;	/* length of buffer contents */
     77 	struct {				/* data cached after an
     78 						   interrupted read */
     79 		char	*buf;
     80 		size_t	 size;
     81 		size_t	 pos;
     82 		size_t	 len;
     83 	} cache;
     84 	int 			 issock;
     85 	int			 iserr;
     86 	int			 iseof;
     87 #ifdef WITH_SSL
     88 	SSL			*ssl;		/* SSL handle */
     89 #endif
     90 };
     91 
     92 /*
     93  * Write a vector to a connection w/ timeout
     94  * Note: can modify the iovec.
     95  */
     96 static ssize_t
     97 fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
     98 {
     99 	struct timeval timeout, now, delta;
    100 	ssize_t len, total;
    101 	int fd = conn->sd;
    102 	int rv, timeout_secs;
    103 	struct pollfd pfd[1];
    104 
    105 	pfd[0].fd = fd;
    106 	pfd[0].events = POLLOUT;
    107 	gettimeofday(&timeout, NULL);
    108 	timeout.tv_sec += quit_time;
    109 
    110 	total = 0;
    111 	while (iovcnt > 0) {
    112 		if (quit_time > 0) {	/* enforce timeout */
    113 			do {
    114 				(void)gettimeofday(&now, NULL);
    115 				timersub(&timeout, &now, &delta);
    116 				timeout_secs = (int)(delta.tv_sec * 1000
    117 				    + delta.tv_usec / 1000);
    118 				if (timeout_secs < 0)
    119 					timeout_secs = 0;
    120 				rv = ftp_poll(pfd, 1, timeout_secs);
    121 					/* loop until poll !EINTR && !EAGAIN */
    122 			} while (rv == -1 && (errno == EINTR || errno == EAGAIN));
    123 			if (rv == -1)
    124 				return -1;
    125 			if (rv == 0) {
    126 				errno = ETIMEDOUT;
    127 				return -1;
    128 			}
    129 		}
    130 		errno = 0;
    131 #ifdef WITH_SSL
    132 		if (conn->ssl != NULL)
    133 			len = SSL_write(conn->ssl, iov->iov_base, (int)iov->iov_len);
    134 		else
    135 #endif
    136 			len = writev(fd, iov, iovcnt);
    137 		if (len == 0) {
    138 			/* we consider a short write a failure */
    139 			/* XXX perhaps we shouldn't in the SSL case */
    140 			errno = EPIPE;
    141 			return -1;
    142 		}
    143 		if (len < 0) {
    144 			if (errno == EINTR || errno == EAGAIN)
    145 				continue;
    146 			return -1;
    147 		}
    148 		total += len;
    149 		while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) {
    150 			len -= iov->iov_len;
    151 			iov++;
    152 			iovcnt--;
    153 		}
    154 		if (iovcnt > 0) {
    155 			iov->iov_len -= len;
    156 			iov->iov_base = (char *)iov->iov_base + len;
    157 		}
    158 	}
    159 	return total;
    160 }
    161 
    162 static ssize_t
    163 fetch_write(const void *str, size_t len, struct fetch_connect *conn)
    164 {
    165 	struct iovec iov[1];
    166 
    167 	iov[0].iov_base = (char *)__UNCONST(str);
    168 	iov[0].iov_len = len;
    169 	return fetch_writev(conn, iov, 1);
    170 }
    171 
    172 /*
    173  * Send a formatted line; optionally echo to terminal
    174  */
    175 int
    176 fetch_printf(struct fetch_connect *conn, const char *fmt, ...)
    177 {
    178 	va_list ap;
    179 	size_t len;
    180 	char *msg;
    181 	ssize_t r;
    182 
    183 	va_start(ap, fmt);
    184 	len = vasprintf(&msg, fmt, ap);
    185 	va_end(ap);
    186 
    187 	if (msg == NULL) {
    188 		errno = ENOMEM;
    189 		return -1;
    190 	}
    191 
    192 	r = fetch_write(msg, len, conn);
    193 	free(msg);
    194 	return (int)r;
    195 }
    196 
    197 int
    198 fetch_fileno(struct fetch_connect *conn)
    199 {
    200 
    201 	return conn->sd;
    202 }
    203 
    204 int
    205 fetch_error(struct fetch_connect *conn)
    206 {
    207 
    208 	return conn->iserr;
    209 }
    210 
    211 static void
    212 fetch_clearerr(struct fetch_connect *conn)
    213 {
    214 
    215 	conn->iserr = 0;
    216 }
    217 
    218 int
    219 fetch_flush(struct fetch_connect *conn)
    220 {
    221 
    222 	if (conn->issock) {
    223 		int fd = conn->sd;
    224 		int v;
    225 #ifdef TCP_NOPUSH
    226 		v = 0;
    227 		setsockopt(fd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
    228 #endif
    229 		v = 1;
    230 		setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
    231 	}
    232 	return 0;
    233 }
    234 
    235 /*ARGSUSED*/
    236 struct fetch_connect *
    237 fetch_open(const char *fname, const char *fmode)
    238 {
    239 	struct fetch_connect *conn;
    240 	int fd;
    241 
    242 	fd = open(fname, O_RDONLY); /* XXX: fmode */
    243 	if (fd < 0)
    244 		return NULL;
    245 
    246 	if ((conn = calloc(1, sizeof(*conn))) == NULL) {
    247 		close(fd);
    248 		return NULL;
    249 	}
    250 
    251 	conn->sd = fd;
    252 	conn->issock = 0;
    253 	return conn;
    254 }
    255 
    256 /*ARGSUSED*/
    257 struct fetch_connect *
    258 fetch_fdopen(int sd, const char *fmode)
    259 {
    260 	struct fetch_connect *conn;
    261 #if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH)
    262 	int opt = 1;
    263 #endif
    264 
    265 	if ((conn = calloc(1, sizeof(*conn))) == NULL)
    266 		return NULL;
    267 
    268 	conn->sd = sd;
    269 	conn->issock = 1;
    270 	fcntl(sd, F_SETFD, FD_CLOEXEC);
    271 #ifdef SO_NOSIGPIPE
    272 	setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
    273 #endif
    274 #ifdef TCP_NOPUSH
    275 	setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt));
    276 #endif
    277 	return conn;
    278 }
    279 
    280 int
    281 fetch_close(struct fetch_connect *conn)
    282 {
    283 	if (conn == NULL)
    284 		return 0;
    285 
    286 	fetch_flush(conn);
    287 #ifdef WITH_SSL
    288 	SSL_free(conn->ssl);
    289 #endif
    290 	close(conn->sd);
    291 	free(conn->cache.buf);
    292 	free(conn->buf);
    293 	free(conn);
    294 	return 0;
    295 }
    296 
    297 #define FETCH_WRITE_WAIT	-3
    298 #define FETCH_READ_WAIT		-2
    299 #define FETCH_READ_ERROR	-1
    300 
    301 #ifdef WITH_SSL
    302 static ssize_t
    303 fetch_ssl_read(SSL *ssl, void *buf, size_t len)
    304 {
    305 	int rlen;
    306 	rlen = SSL_read(ssl, buf, (int)len);
    307 	if (rlen >= 0)
    308 		return rlen;
    309 
    310 	switch (SSL_get_error(ssl, rlen)) {
    311 	case SSL_ERROR_WANT_READ:
    312 		return FETCH_READ_WAIT;
    313 	case SSL_ERROR_WANT_WRITE:
    314 		return FETCH_WRITE_WAIT;
    315 	default:
    316 		ERR_print_errors_fp(ttyout);
    317 		return FETCH_READ_ERROR;
    318 	}
    319 }
    320 #endif /* WITH_SSL */
    321 
    322 static ssize_t
    323 fetch_nonssl_read(int sd, void *buf, size_t len)
    324 {
    325 	ssize_t rlen;
    326 
    327 	rlen = read(sd, buf, len);
    328 	if (rlen == -1) {
    329 		if (errno == EINTR || errno == EAGAIN)
    330 			return FETCH_READ_WAIT;
    331 		return FETCH_READ_ERROR;
    332 	}
    333 	return rlen;
    334 }
    335 
    336 /*
    337  * Cache some data that was read from a socket but cannot be immediately
    338  * returned because of an interrupted system call.
    339  */
    340 static int
    341 fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes)
    342 {
    343 
    344 	if (conn->cache.size < nbytes) {
    345 		char *tmp = realloc(conn->cache.buf, nbytes);
    346 		if (tmp == NULL)
    347 			return -1;
    348 
    349 		conn->cache.buf = tmp;
    350 		conn->cache.size = nbytes;
    351 	}
    352 
    353 	memcpy(conn->cache.buf, src, nbytes);
    354 	conn->cache.len = nbytes;
    355 	conn->cache.pos = 0;
    356 	return 0;
    357 }
    358 
    359 static int
    360 fetch_wait(struct fetch_connect *conn, ssize_t rlen, struct timeval *timeout)
    361 {
    362 	struct timeval now, delta;
    363 	int fd = conn->sd;
    364 	int rv, timeout_secs;
    365 	struct pollfd pfd[1];
    366 
    367 	pfd[0].fd = fd;
    368 	if (rlen == FETCH_READ_WAIT) {
    369 		pfd[0].events = POLLIN;
    370 	} else if (rlen == FETCH_WRITE_WAIT) {
    371 		pfd[0].events = POLLOUT;
    372 	} else {
    373 		pfd[0].events = 0;
    374 	}
    375 
    376 	do {
    377 		if (quit_time > 0) {
    378 			gettimeofday(&now, NULL);
    379 			timersub(timeout, &now, &delta);
    380 			timeout_secs = (int)(delta.tv_sec * 1000
    381 			    + delta.tv_usec / 1000);
    382 			if (timeout_secs < 0)
    383 				timeout_secs = 0;
    384 		} else {
    385 			timeout_secs = INFTIM;
    386 		}
    387 		errno = 0;
    388 		rv = ftp_poll(pfd, 1, timeout_secs);
    389 				/* loop until poll !EINTR && !EAGAIN */
    390 	} while (rv == -1 && (errno == EINTR || errno == EAGAIN));
    391 	if (rv == 0) {		/* poll timeout */
    392 		fprintf(ttyout, "\r\n%s: transfer aborted"
    393 		    " because stalled for %lu sec.\r\n",
    394 		    getprogname(), (unsigned long)quit_time);
    395 		errno = ETIMEDOUT;
    396 		conn->iserr = ETIMEDOUT;
    397 		return -1;
    398 	}
    399 	if (rv == -1) {		/* poll error */
    400 		conn->iserr = errno;
    401 		return -1;
    402 	}
    403 	return 0;
    404 }
    405 
    406 size_t
    407 fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
    408 {
    409 	ssize_t rlen, total;
    410 	size_t len;
    411 	char *start, *buf;
    412 	struct timeval timeout;
    413 
    414 	if (quit_time > 0) {
    415 		gettimeofday(&timeout, NULL);
    416 		timeout.tv_sec += quit_time;
    417 	}
    418 
    419 	total = 0;
    420 	start = buf = ptr;
    421 	len = size * nmemb;
    422 
    423 	if (conn->cache.len > 0) {
    424 		/*
    425 		 * The last invocation of fetch_read was interrupted by a
    426 		 * signal after some data had been read from the socket. Copy
    427 		 * the cached data into the supplied buffer before trying to
    428 		 * read from the socket again.
    429 		 */
    430 		total = (conn->cache.len < len) ? conn->cache.len : len;
    431 		memcpy(buf, conn->cache.buf, total);
    432 
    433 		conn->cache.len -= total;
    434 		conn->cache.pos += total;
    435 		len -= total;
    436 		buf += total;
    437 	}
    438 
    439 	while (len > 0) {
    440 		/*
    441 		 * The socket is non-blocking.  Instead of the canonical
    442 		 * poll() -> read(), we do the following:
    443 		 *
    444 		 * 1) call read() or SSL_read().
    445 		 * 2) if an error occurred, return -1.
    446 		 * 3) if we received data but we still expect more,
    447 		 *    update our counters and loop.
    448 		 * 4) if read() or SSL_read() signaled EOF, return.
    449 		 * 5) if we did not receive any data but we're not at EOF,
    450 		 *    call poll().
    451 		 *
    452 		 * In the SSL case, this is necessary because if we
    453 		 * receive a close notification, we have to call
    454 		 * SSL_read() one additional time after we've read
    455 		 * everything we received.
    456 		 *
    457 		 * In the non-SSL case, it may improve performance (very
    458 		 * slightly) when reading small amounts of data.
    459 		 */
    460 #ifdef WITH_SSL
    461 		if (conn->ssl != NULL)
    462 			rlen = fetch_ssl_read(conn->ssl, buf, len);
    463 		else
    464 #endif
    465 			rlen = fetch_nonssl_read(conn->sd, buf, len);
    466 		switch (rlen) {
    467 		case 0:
    468 			conn->iseof = 1;
    469 			return total;
    470 		case FETCH_READ_ERROR:
    471 			conn->iserr = errno;
    472 			if (errno == EINTR || errno == EAGAIN)
    473 				fetch_cache_data(conn, start, total);
    474 			return 0;
    475 		case FETCH_READ_WAIT:
    476 		case FETCH_WRITE_WAIT:
    477 			if (fetch_wait(conn, rlen, &timeout) == -1)
    478 				return 0;
    479 			break;
    480 		default:
    481 			len -= rlen;
    482 			buf += rlen;
    483 			total += rlen;
    484 			break;
    485 		}
    486 	}
    487 	return total;
    488 }
    489 
    490 #define MIN_BUF_SIZE 1024
    491 
    492 /*
    493  * Read a line of text from a connection w/ timeout
    494  */
    495 char *
    496 fetch_getln(char *str, int size, struct fetch_connect *conn)
    497 {
    498 	size_t tmpsize;
    499 	size_t len;
    500 	char c;
    501 
    502 	if (conn->buf == NULL) {
    503 		if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
    504 			errno = ENOMEM;
    505 			conn->iserr = 1;
    506 			return NULL;
    507 		}
    508 		conn->bufsize = MIN_BUF_SIZE;
    509 	}
    510 
    511 	if (conn->iserr || conn->iseof)
    512 		return NULL;
    513 
    514 	if (conn->buflen - conn->bufpos > 0)
    515 		goto done;
    516 
    517 	conn->buf[0] = '\0';
    518 	conn->bufpos = 0;
    519 	conn->buflen = 0;
    520 	do {
    521 		len = fetch_read(&c, sizeof(c), 1, conn);
    522 		if (len == 0) {
    523 			if (conn->iserr)
    524 				return NULL;
    525 			if (conn->iseof)
    526 				break;
    527 			abort();
    528 		}
    529 		conn->buf[conn->buflen++] = c;
    530 		if (conn->buflen == conn->bufsize) {
    531 			char *tmp = conn->buf;
    532 			tmpsize = conn->bufsize * 2 + 1;
    533 			if ((tmp = realloc(tmp, tmpsize)) == NULL) {
    534 				errno = ENOMEM;
    535 				conn->iserr = 1;
    536 				return NULL;
    537 			}
    538 			conn->buf = tmp;
    539 			conn->bufsize = tmpsize;
    540 		}
    541 	} while (c != '\n');
    542 
    543 	if (conn->buflen == 0)
    544 		return NULL;
    545  done:
    546 	tmpsize = MIN(size - 1, (int)(conn->buflen - conn->bufpos));
    547 	memcpy(str, conn->buf + conn->bufpos, tmpsize);
    548 	str[tmpsize] = '\0';
    549 	conn->bufpos += tmpsize;
    550 	return str;
    551 }
    552 
    553 int
    554 fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
    555     const char **errormsg)
    556 {
    557 	size_t len;
    558 	int rv;
    559 
    560 	if (fetch_getln(buf, (int)buflen, conn) == NULL) {
    561 		if (conn->iseof) {	/* EOF */
    562 			rv = -2;
    563 			if (errormsg)
    564 				*errormsg = "\nEOF received";
    565 		} else {		/* error */
    566 			rv = -1;
    567 			if (errormsg)
    568 				*errormsg = "Error encountered";
    569 		}
    570 		fetch_clearerr(conn);
    571 		return rv;
    572 	}
    573 	len = strlen(buf);
    574 	if (buf[len - 1] == '\n') {	/* clear any trailing newline */
    575 		buf[--len] = '\0';
    576 	} else if (len == buflen - 1) {	/* line too long */
    577 		for (;;) {
    578 			char c;
    579 			size_t rlen = fetch_read(&c, sizeof(c), 1, conn);
    580 			if (rlen == 0 || c == '\n')
    581 				break;
    582 		}
    583 		if (errormsg)
    584 			*errormsg = "Input line is too long (specify -b > 16384)";
    585 		fetch_clearerr(conn);
    586 		return -3;
    587 	}
    588 	if (errormsg)
    589 		*errormsg = NULL;
    590 	return (int)len;
    591 }
    592 
    593 #ifdef WITH_SSL
    594 /*
    595  * Start the SSL/TLS negotiation.
    596  * Socket fcntl flags are temporarily updated to include O_NONBLOCK;
    597  * these will not be reverted on connection failure.
    598  * Returns pointer to allocated SSL structure on success,
    599  * or NULL upon failure.
    600  */
    601 void *
    602 fetch_start_ssl(int sock, const char *servername)
    603 {
    604 	SSL *ssl = NULL;
    605 	SSL_CTX *ctx = NULL;
    606 	X509_VERIFY_PARAM *param;
    607 	int ret, ssl_err, flags, rv, timeout_secs;
    608 	int verify = !ftp_truthy("sslnoverify", getoptionvalue("sslnoverify"), 0);
    609 	struct timeval timeout, now, delta;
    610 	struct pollfd pfd[1];
    611 
    612 	/* Init the SSL library and context */
    613 	if (!SSL_library_init()){
    614 		warnx("SSL library init failed");
    615 		goto cleanup_start_ssl;
    616 	}
    617 
    618 	SSL_load_error_strings();
    619 
    620 	ctx = SSL_CTX_new(SSLv23_client_method());
    621 	SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
    622 	if (verify) {
    623 		SSL_CTX_set_default_verify_paths(ctx);
    624 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
    625 	}
    626 
    627 	ssl = SSL_new(ctx);
    628 	if (ssl == NULL){
    629 		warnx("SSL context creation failed");
    630 		goto cleanup_start_ssl;
    631 	}
    632 
    633 	if (verify) {
    634 		param = SSL_get0_param(ssl);
    635 		if (!X509_VERIFY_PARAM_set1_host(param, servername,
    636 		    strlen(servername))) {
    637 			warnx("SSL verification setup failed");
    638 			goto cleanup_start_ssl;
    639 		}
    640 
    641 		/* Enable peer verification, (using the default callback) */
    642 		SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
    643 	}
    644 #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
    645 	SSL_set_options(ssl, SSL_OP_IGNORE_UNEXPECTED_EOF);
    646 #endif
    647 
    648 						/* save current socket flags */
    649 	if ((flags = fcntl(sock, F_GETFL, 0)) == -1) {
    650 		warn("Can't %s socket flags for SSL connect to `%s'",
    651 		    "save", servername);
    652 		goto cleanup_start_ssl;
    653 	}
    654 						/* set non-blocking connect */
    655 	if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
    656 		warn("Can't set socket non-blocking for SSL connect to `%s'",
    657 		    servername);
    658 		goto cleanup_start_ssl;
    659 	}
    660 
    661 	/* NOTE: we now must restore socket flags on successful connection */
    662 
    663 	(void)gettimeofday(&timeout, NULL);	/* setup SSL_connect() timeout */
    664 	timeout.tv_sec += (quit_time > 0) ? quit_time: 60;
    665 						/* without -q, default to 60s */
    666 
    667 	SSL_set_fd(ssl, sock);
    668 	if (!SSL_set_tlsext_host_name(ssl, __UNCONST(servername))) {
    669 		warnx("SSL hostname setting failed");
    670 		goto cleanup_start_ssl;
    671 	}
    672 	pfd[0].fd = sock;
    673 	pfd[0].events = 0;
    674 	while ((ret = SSL_connect(ssl)) <= 0) {
    675 		ssl_err = SSL_get_error(ssl, ret);
    676 		DPRINTF("%s: SSL_connect() ret=%d ssl_err=%d\n",
    677 		    __func__, ret, ssl_err);
    678 		if (ret == 0) { /* unsuccessful handshake */
    679 			ERR_print_errors_fp(ttyout);
    680 			goto cleanup_start_ssl;
    681 		}
    682 		if (ssl_err == SSL_ERROR_WANT_READ) {
    683 			pfd[0].events = POLLIN;
    684 		} else if (ssl_err == SSL_ERROR_WANT_WRITE) {
    685 			pfd[0].events = POLLOUT;
    686 		} else {
    687 			ERR_print_errors_fp(ttyout);
    688 			goto cleanup_start_ssl;
    689 		}
    690 		(void)gettimeofday(&now, NULL);
    691 		timersub(&timeout, &now, &delta);
    692 		timeout_secs = (int)(delta.tv_sec * 1000
    693 		    + delta.tv_usec / 1000);
    694 		if (timeout_secs < 0)
    695 			timeout_secs = 0;
    696 		rv = ftp_poll(pfd, 1, timeout_secs);
    697 		if (rv == 0) {		/* poll for SSL_connect() timed out */
    698 			fprintf(ttyout, "Timeout establishing SSL connection to `%s'\n",
    699 			    servername);
    700 			goto cleanup_start_ssl;
    701 		} else if (rv == -1 && errno != EINTR && errno != EAGAIN) {
    702 			warn("Error polling for SSL connect to `%s'", servername);
    703 			goto cleanup_start_ssl;
    704 		}
    705 	}
    706 
    707 	if (fcntl(sock, F_SETFL, flags) == -1) {
    708 						/* restore socket flags */
    709 		warn("Can't %s socket flags for SSL connect to `%s'",
    710 		    "restore", servername);
    711 		goto cleanup_start_ssl;
    712 	}
    713 
    714 	if (ftp_debug && verbose) {
    715 		X509 *cert;
    716 		X509_NAME *name;
    717 		char *str;
    718 
    719 		fprintf(ttyout, "SSL connection established using %s\n",
    720 		    SSL_get_cipher(ssl));
    721 		cert = SSL_get_peer_certificate(ssl);
    722 		name = X509_get_subject_name(cert);
    723 		str = X509_NAME_oneline(name, 0, 0);
    724 		fprintf(ttyout, "Certificate subject: %s\n", str);
    725 		free(str);
    726 		name = X509_get_issuer_name(cert);
    727 		str = X509_NAME_oneline(name, 0, 0);
    728 		fprintf(ttyout, "Certificate issuer: %s\n", str);
    729 		free(str);
    730 	}
    731 
    732 	return ssl;
    733 
    734  cleanup_start_ssl:
    735 	if (ssl)
    736 		SSL_free(ssl);
    737 	if (ctx)
    738 		SSL_CTX_free(ctx);
    739 	return NULL;
    740 }
    741 #endif /* WITH_SSL */
    742 
    743 
    744 void
    745 fetch_set_ssl(struct fetch_connect *conn, void *ssl)
    746 {
    747 #ifdef WITH_SSL
    748 	conn->ssl = ssl;
    749 #endif
    750 }
    751