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