Home | History | Annotate | Line # | Download | only in ftp
ssl.c revision 1.15
      1 /*	$NetBSD: ssl.c,v 1.15 2023/05/05 15:46:06 lukem 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.15 2023/05/05 15:46:06 lukem 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 = delta.tv_sec * 1000 + delta.tv_usec/1000;
    117 				if (timeout_secs < 0)
    118 					timeout_secs = 0;
    119 				rv = ftp_poll(pfd, 1, timeout_secs);
    120 					/* loop until poll !EINTR && !EAGAIN */
    121 			} while (rv == -1 && (errno == EINTR || errno == EAGAIN));
    122 			if (rv == -1)
    123 				return -1;
    124 			if (rv == 0) {
    125 				errno = ETIMEDOUT;
    126 				return -1;
    127 			}
    128 		}
    129 		errno = 0;
    130 #ifdef WITH_SSL
    131 		if (conn->ssl != NULL)
    132 			len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len);
    133 		else
    134 #endif
    135 			len = writev(fd, iov, iovcnt);
    136 		if (len == 0) {
    137 			/* we consider a short write a failure */
    138 			/* XXX perhaps we shouldn't in the SSL case */
    139 			errno = EPIPE;
    140 			return -1;
    141 		}
    142 		if (len < 0) {
    143 			if (errno == EINTR || errno == EAGAIN)
    144 				continue;
    145 			return -1;
    146 		}
    147 		total += len;
    148 		while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) {
    149 			len -= iov->iov_len;
    150 			iov++;
    151 			iovcnt--;
    152 		}
    153 		if (iovcnt > 0) {
    154 			iov->iov_len -= len;
    155 			iov->iov_base = (char *)iov->iov_base + len;
    156 		}
    157 	}
    158 	return total;
    159 }
    160 
    161 static ssize_t
    162 fetch_write(const void *str, size_t len, struct fetch_connect *conn)
    163 {
    164 	struct iovec iov[1];
    165 
    166 	iov[0].iov_base = (char *)__UNCONST(str);
    167 	iov[0].iov_len = len;
    168 	return fetch_writev(conn, iov, 1);
    169 }
    170 
    171 /*
    172  * Send a formatted line; optionally echo to terminal
    173  */
    174 int
    175 fetch_printf(struct fetch_connect *conn, const char *fmt, ...)
    176 {
    177 	va_list ap;
    178 	size_t len;
    179 	char *msg;
    180 	int r;
    181 
    182 	va_start(ap, fmt);
    183 	len = vasprintf(&msg, fmt, ap);
    184 	va_end(ap);
    185 
    186 	if (msg == NULL) {
    187 		errno = ENOMEM;
    188 		return -1;
    189 	}
    190 
    191 	r = fetch_write(msg, len, conn);
    192 	free(msg);
    193 	return r;
    194 }
    195 
    196 int
    197 fetch_fileno(struct fetch_connect *conn)
    198 {
    199 
    200 	return conn->sd;
    201 }
    202 
    203 int
    204 fetch_error(struct fetch_connect *conn)
    205 {
    206 
    207 	return conn->iserr;
    208 }
    209 
    210 static void
    211 fetch_clearerr(struct fetch_connect *conn)
    212 {
    213 
    214 	conn->iserr = 0;
    215 }
    216 
    217 int
    218 fetch_flush(struct fetch_connect *conn)
    219 {
    220 
    221 	if (conn->issock) {
    222 		int fd = conn->sd;
    223 		int v;
    224 #ifdef TCP_NOPUSH
    225 		v = 0;
    226 		setsockopt(fd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
    227 #endif
    228 		v = 1;
    229 		setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
    230 	}
    231 	return 0;
    232 }
    233 
    234 /*ARGSUSED*/
    235 struct fetch_connect *
    236 fetch_open(const char *fname, const char *fmode)
    237 {
    238 	struct fetch_connect *conn;
    239 	int fd;
    240 
    241 	fd = open(fname, O_RDONLY); /* XXX: fmode */
    242 	if (fd < 0)
    243 		return NULL;
    244 
    245 	if ((conn = calloc(1, sizeof(*conn))) == NULL) {
    246 		close(fd);
    247 		return NULL;
    248 	}
    249 
    250 	conn->sd = fd;
    251 	conn->issock = 0;
    252 	return conn;
    253 }
    254 
    255 /*ARGSUSED*/
    256 struct fetch_connect *
    257 fetch_fdopen(int sd, const char *fmode)
    258 {
    259 	struct fetch_connect *conn;
    260 #if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH)
    261 	int opt = 1;
    262 #endif
    263 
    264 	if ((conn = calloc(1, sizeof(*conn))) == NULL)
    265 		return NULL;
    266 
    267 	conn->sd = sd;
    268 	conn->issock = 1;
    269 	fcntl(sd, F_SETFD, FD_CLOEXEC);
    270 #ifdef SO_NOSIGPIPE
    271 	setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
    272 #endif
    273 #ifdef TCP_NOPUSH
    274 	setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt));
    275 #endif
    276 	return conn;
    277 }
    278 
    279 int
    280 fetch_close(struct fetch_connect *conn)
    281 {
    282 	if (conn == NULL)
    283 		return 0;
    284 
    285 	fetch_flush(conn);
    286 #ifdef WITH_SSL
    287 	SSL_free(conn->ssl);
    288 #endif
    289 	close(conn->sd);
    290 	free(conn->cache.buf);
    291 	free(conn->buf);
    292 	free(conn);
    293 	return 0;
    294 }
    295 
    296 #define FETCH_WRITE_WAIT	-3
    297 #define FETCH_READ_WAIT		-2
    298 #define FETCH_READ_ERROR	-1
    299 
    300 #ifdef WITH_SSL
    301 static ssize_t
    302 fetch_ssl_read(SSL *ssl, void *buf, size_t len)
    303 {
    304 	ssize_t rlen;
    305 	rlen = SSL_read(ssl, buf, len);
    306 	if (rlen >= 0)
    307 		return rlen;
    308 
    309 	switch (SSL_get_error(ssl, rlen)) {
    310 	case SSL_ERROR_WANT_READ:
    311 		return FETCH_READ_WAIT;
    312 	case SSL_ERROR_WANT_WRITE:
    313 		return FETCH_WRITE_WAIT;
    314 	default:
    315 		ERR_print_errors_fp(ttyout);
    316 		return FETCH_READ_ERROR;
    317 	}
    318 }
    319 #endif /* WITH_SSL */
    320 
    321 static ssize_t
    322 fetch_nonssl_read(int sd, void *buf, size_t len)
    323 {
    324 	ssize_t rlen;
    325 
    326 	rlen = read(sd, buf, len);
    327 	if (rlen == -1) {
    328 		if (errno == EINTR || errno == EAGAIN)
    329 			return FETCH_READ_WAIT;
    330 		return FETCH_READ_ERROR;
    331 	}
    332 	return rlen;
    333 }
    334 
    335 /*
    336  * Cache some data that was read from a socket but cannot be immediately
    337  * returned because of an interrupted system call.
    338  */
    339 static int
    340 fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes)
    341 {
    342 
    343 	if (conn->cache.size < nbytes) {
    344 		char *tmp = realloc(conn->cache.buf, nbytes);
    345 		if (tmp == NULL)
    346 			return -1;
    347 
    348 		conn->cache.buf = tmp;
    349 		conn->cache.size = nbytes;
    350 	}
    351 
    352 	memcpy(conn->cache.buf, src, nbytes);
    353 	conn->cache.len = nbytes;
    354 	conn->cache.pos = 0;
    355 	return 0;
    356 }
    357 
    358 static int
    359 fetch_wait(struct fetch_connect *conn, ssize_t rlen, struct timeval *timeout)
    360 {
    361 	struct timeval now, delta;
    362 	int fd = conn->sd;
    363 	int rv, timeout_secs;
    364 	struct pollfd pfd[1];
    365 
    366 	pfd[0].fd = fd;
    367 	if (rlen == FETCH_READ_WAIT) {
    368 		pfd[0].events = POLLIN;
    369 	} else if (rlen == FETCH_WRITE_WAIT) {
    370 		pfd[0].events = POLLOUT;
    371 	} else {
    372 		pfd[0].events = 0;
    373 	}
    374 
    375 	do {
    376 		if (quit_time > 0) {
    377 			gettimeofday(&now, NULL);
    378 			timersub(timeout, &now, &delta);
    379 			timeout_secs = delta.tv_sec * 1000 + delta.tv_usec/1000;
    380 			if (timeout_secs < 0)
    381 				timeout_secs = 0;
    382 		} else {
    383 			timeout_secs = INFTIM;
    384 		}
    385 		errno = 0;
    386 		rv = ftp_poll(pfd, 1, timeout_secs);
    387 				/* loop until poll !EINTR && !EAGAIN */
    388 	} while (rv == -1 && (errno == EINTR || errno == EAGAIN));
    389 	if (rv == 0) {		/* poll timeout */
    390 		fprintf(ttyout, "\r\n%s: transfer aborted"
    391 		    " because stalled for %lu sec.\r\n",
    392 		    getprogname(), (unsigned long)quit_time);
    393 		errno = ETIMEDOUT;
    394 		conn->iserr = ETIMEDOUT;
    395 		return -1;
    396 	}
    397 	if (rv == -1) {		/* poll error */
    398 		conn->iserr = errno;
    399 		return -1;
    400 	}
    401 	return 0;
    402 }
    403 
    404 size_t
    405 fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
    406 {
    407 	ssize_t rlen, total;
    408 	size_t len;
    409 	char *start, *buf;
    410 	struct timeval timeout;
    411 
    412 	if (quit_time > 0) {
    413 		gettimeofday(&timeout, NULL);
    414 		timeout.tv_sec += quit_time;
    415 	}
    416 
    417 	total = 0;
    418 	start = buf = ptr;
    419 	len = size * nmemb;
    420 
    421 	if (conn->cache.len > 0) {
    422 		/*
    423 		 * The last invocation of fetch_read was interrupted by a
    424 		 * signal after some data had been read from the socket. Copy
    425 		 * the cached data into the supplied buffer before trying to
    426 		 * read from the socket again.
    427 		 */
    428 		total = (conn->cache.len < len) ? conn->cache.len : len;
    429 		memcpy(buf, conn->cache.buf, total);
    430 
    431 		conn->cache.len -= total;
    432 		conn->cache.pos += total;
    433 		len -= total;
    434 		buf += total;
    435 	}
    436 
    437 	while (len > 0) {
    438 		/*
    439 		 * The socket is non-blocking.  Instead of the canonical
    440 		 * poll() -> read(), we do the following:
    441 		 *
    442 		 * 1) call read() or SSL_read().
    443 		 * 2) if an error occurred, return -1.
    444 		 * 3) if we received data but we still expect more,
    445 		 *    update our counters and loop.
    446 		 * 4) if read() or SSL_read() signaled EOF, return.
    447 		 * 5) if we did not receive any data but we're not at EOF,
    448 		 *    call poll().
    449 		 *
    450 		 * In the SSL case, this is necessary because if we
    451 		 * receive a close notification, we have to call
    452 		 * SSL_read() one additional time after we've read
    453 		 * everything we received.
    454 		 *
    455 		 * In the non-SSL case, it may improve performance (very
    456 		 * slightly) when reading small amounts of data.
    457 		 */
    458 #ifdef WITH_SSL
    459 		if (conn->ssl != NULL)
    460 			rlen = fetch_ssl_read(conn->ssl, buf, len);
    461 		else
    462 #endif
    463 			rlen = fetch_nonssl_read(conn->sd, buf, len);
    464 		switch (rlen) {
    465 		case 0:
    466 			conn->iseof = 1;
    467 			return total;
    468 		case FETCH_READ_ERROR:
    469 			conn->iserr = errno;
    470 			if (errno == EINTR || errno == EAGAIN)
    471 				fetch_cache_data(conn, start, total);
    472 			return 0;
    473 		case FETCH_READ_WAIT:
    474 		case FETCH_WRITE_WAIT:
    475 			if (fetch_wait(conn, rlen, &timeout) == -1)
    476 				return 0;
    477 			break;
    478 		default:
    479 			len -= rlen;
    480 			buf += rlen;
    481 			total += rlen;
    482 			break;
    483 		}
    484 	}
    485 	return total;
    486 }
    487 
    488 #define MIN_BUF_SIZE 1024
    489 
    490 /*
    491  * Read a line of text from a connection w/ timeout
    492  */
    493 char *
    494 fetch_getln(char *str, int size, struct fetch_connect *conn)
    495 {
    496 	size_t tmpsize;
    497 	size_t len;
    498 	char c;
    499 
    500 	if (conn->buf == NULL) {
    501 		if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
    502 			errno = ENOMEM;
    503 			conn->iserr = 1;
    504 			return NULL;
    505 		}
    506 		conn->bufsize = MIN_BUF_SIZE;
    507 	}
    508 
    509 	if (conn->iserr || conn->iseof)
    510 		return NULL;
    511 
    512 	if (conn->buflen - conn->bufpos > 0)
    513 		goto done;
    514 
    515 	conn->buf[0] = '\0';
    516 	conn->bufpos = 0;
    517 	conn->buflen = 0;
    518 	do {
    519 		len = fetch_read(&c, sizeof(c), 1, conn);
    520 		if (len == 0) {
    521 			if (conn->iserr)
    522 				return NULL;
    523 			if (conn->iseof)
    524 				break;
    525 			abort();
    526 		}
    527 		conn->buf[conn->buflen++] = c;
    528 		if (conn->buflen == conn->bufsize) {
    529 			char *tmp = conn->buf;
    530 			tmpsize = conn->bufsize * 2 + 1;
    531 			if ((tmp = realloc(tmp, tmpsize)) == NULL) {
    532 				errno = ENOMEM;
    533 				conn->iserr = 1;
    534 				return NULL;
    535 			}
    536 			conn->buf = tmp;
    537 			conn->bufsize = tmpsize;
    538 		}
    539 	} while (c != '\n');
    540 
    541 	if (conn->buflen == 0)
    542 		return NULL;
    543  done:
    544 	tmpsize = MIN(size - 1, (int)(conn->buflen - conn->bufpos));
    545 	memcpy(str, conn->buf + conn->bufpos, tmpsize);
    546 	str[tmpsize] = '\0';
    547 	conn->bufpos += tmpsize;
    548 	return str;
    549 }
    550 
    551 int
    552 fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
    553     const char **errormsg)
    554 {
    555 	size_t len;
    556 	int rv;
    557 
    558 	if (fetch_getln(buf, buflen, conn) == NULL) {
    559 		if (conn->iseof) {	/* EOF */
    560 			rv = -2;
    561 			if (errormsg)
    562 				*errormsg = "\nEOF received";
    563 		} else {		/* error */
    564 			rv = -1;
    565 			if (errormsg)
    566 				*errormsg = "Error encountered";
    567 		}
    568 		fetch_clearerr(conn);
    569 		return rv;
    570 	}
    571 	len = strlen(buf);
    572 	if (buf[len - 1] == '\n') {	/* clear any trailing newline */
    573 		buf[--len] = '\0';
    574 	} else if (len == buflen - 1) {	/* line too long */
    575 		while (1) {
    576 			char c;
    577 			size_t rlen = fetch_read(&c, sizeof(c), 1, conn);
    578 			if (rlen == 0 || c == '\n')
    579 				break;
    580 		}
    581 		if (errormsg)
    582 			*errormsg = "Input line is too long";
    583 		fetch_clearerr(conn);
    584 		return -3;
    585 	}
    586 	if (errormsg)
    587 		*errormsg = NULL;
    588 	return len;
    589 }
    590 
    591 #ifdef WITH_SSL
    592 /*
    593  * Start the SSL/TLS negotiation.
    594  * Socket fcntl flags are temporarily updated to include O_NONBLOCK;
    595  * these will not be reverted on connection failure.
    596  * Returns pointer to allocated SSL structure on success,
    597  * or NULL upon failure.
    598  */
    599 void *
    600 fetch_start_ssl(int sock, const char *servername)
    601 {
    602 	SSL *ssl = NULL;
    603 	SSL_CTX *ctx = NULL;
    604 	X509_VERIFY_PARAM *param;
    605 	int ret, ssl_err, flags, rv, timeout_secs;
    606 	int verify = !ftp_truthy("sslnoverify", getoptionvalue("sslnoverify"), 0);
    607 	struct timeval timeout, now, delta;
    608 	struct pollfd pfd[1];
    609 
    610 	/* Init the SSL library and context */
    611 	if (!SSL_library_init()){
    612 		warnx("SSL library init failed");
    613 		goto cleanup_start_ssl;
    614 	}
    615 
    616 	SSL_load_error_strings();
    617 
    618 	ctx = SSL_CTX_new(SSLv23_client_method());
    619 	SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
    620 	if (verify) {
    621 		SSL_CTX_set_default_verify_paths(ctx);
    622 		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
    623 	}
    624 
    625 	ssl = SSL_new(ctx);
    626 	if (ssl == NULL){
    627 		warnx("SSL context creation failed");
    628 		goto cleanup_start_ssl;
    629 	}
    630 
    631 	if (verify) {
    632 		param = SSL_get0_param(ssl);
    633 		if (!X509_VERIFY_PARAM_set1_host(param, servername,
    634 		    strlen(servername))) {
    635 			warnx("SSL verification setup failed");
    636 			goto cleanup_start_ssl;
    637 		}
    638 
    639 		/* Enable peer verification, (using the default callback) */
    640 		SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
    641 	}
    642 
    643 						/* save current socket flags */
    644 	if ((flags = fcntl(sock, F_GETFL, 0)) == -1) {
    645 		warn("Can't %s socket flags for SSL connect to `%s'",
    646 		    "save", servername);
    647 		goto cleanup_start_ssl;
    648 	}
    649 						/* set non-blocking connect */
    650 	if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
    651 		warn("Can't set socket non-blocking for SSL connect to `%s'",
    652 		    servername);
    653 		goto cleanup_start_ssl;
    654 	}
    655 
    656 	/* NOTE: we now must restore socket flags on successful connection */
    657 
    658 	(void)gettimeofday(&timeout, NULL);	/* setup SSL_connect() timeout */
    659 	timeout.tv_sec += (quit_time > 0) ? quit_time: 60;
    660 						/* without -q, default to 60s */
    661 
    662 	SSL_set_fd(ssl, sock);
    663 	if (!SSL_set_tlsext_host_name(ssl, __UNCONST(servername))) {
    664 		warnx("SSL hostname setting failed");
    665 		goto cleanup_start_ssl;
    666 	}
    667 	pfd[0].fd = sock;
    668 	pfd[0].events = 0;
    669 	while ((ret = SSL_connect(ssl)) <= 0) {
    670 		ssl_err = SSL_get_error(ssl, ret);
    671 		DPRINTF("%s: SSL_connect() ret=%d ssl_err=%d\n",
    672 		    __func__, ret, ssl_err);
    673 		if (ret == 0) { /* unsuccessful handshake */
    674 			ERR_print_errors_fp(ttyout);
    675 			goto cleanup_start_ssl;
    676 		}
    677 		if (ssl_err == SSL_ERROR_WANT_READ) {
    678 			pfd[0].events = POLLIN;
    679 		} else if (ssl_err == SSL_ERROR_WANT_WRITE) {
    680 			pfd[0].events = POLLOUT;
    681 		} else {
    682 			ERR_print_errors_fp(ttyout);
    683 			goto cleanup_start_ssl;
    684 		}
    685 		(void)gettimeofday(&now, NULL);
    686 		timersub(&timeout, &now, &delta);
    687 		timeout_secs = delta.tv_sec * 1000 + delta.tv_usec/1000;
    688 		if (timeout_secs < 0)
    689 			timeout_secs = 0;
    690 		rv = ftp_poll(pfd, 1, timeout_secs);
    691 		if (rv == 0) {		/* poll for SSL_connect() timed out */
    692 			fprintf(ttyout, "Timeout establishing SSL connection to `%s'\n",
    693 			    servername);
    694 			goto cleanup_start_ssl;
    695 		} else if (rv == -1 && errno != EINTR && errno != EAGAIN) {
    696 			warn("Error polling for SSL connect to `%s'", servername);
    697 			goto cleanup_start_ssl;
    698 		}
    699 	}
    700 
    701 	if (fcntl(sock, F_SETFL, flags) == -1) {
    702 						/* restore socket flags */
    703 		warn("Can't %s socket flags for SSL connect to `%s'",
    704 		    "restore", servername);
    705 		goto cleanup_start_ssl;
    706 	}
    707 
    708 	if (ftp_debug && verbose) {
    709 		X509 *cert;
    710 		X509_NAME *name;
    711 		char *str;
    712 
    713 		fprintf(ttyout, "SSL connection established using %s\n",
    714 		    SSL_get_cipher(ssl));
    715 		cert = SSL_get_peer_certificate(ssl);
    716 		name = X509_get_subject_name(cert);
    717 		str = X509_NAME_oneline(name, 0, 0);
    718 		fprintf(ttyout, "Certificate subject: %s\n", str);
    719 		free(str);
    720 		name = X509_get_issuer_name(cert);
    721 		str = X509_NAME_oneline(name, 0, 0);
    722 		fprintf(ttyout, "Certificate issuer: %s\n", str);
    723 		free(str);
    724 	}
    725 
    726 	return ssl;
    727 
    728  cleanup_start_ssl:
    729 	if (ssl)
    730 		SSL_free(ssl);
    731 	if (ctx)
    732 		SSL_CTX_free(ctx);
    733 	return NULL;
    734 }
    735 #endif /* WITH_SSL */
    736 
    737 
    738 void
    739 fetch_set_ssl(struct fetch_connect *conn, void *ssl)
    740 {
    741 #ifdef WITH_SSL
    742 	conn->ssl = ssl;
    743 #endif
    744 }
    745