1 /* $NetBSD: ssl.c,v 1.7 2021/08/27 01:48:01 lukem Exp $ */ 2 /* from NetBSD: ssl.c,v 1.10 2021/06/03 10:23:33 lukem Exp */ 3 4 /*- 5 * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav 6 * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org> 7 * Copyright (c) 2015 Thomas Klausner <wiz@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 "tnftp.h" 37 38 #if 0 /* tnftp */ 39 40 #include <sys/cdefs.h> 41 #ifndef lint 42 __RCSID(" NetBSD: ssl.c,v 1.10 2021/06/03 10:23:33 lukem Exp "); 43 #endif 44 45 #include <errno.h> 46 #include <fcntl.h> 47 #include <stdarg.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <time.h> 52 #include <unistd.h> 53 54 #include <sys/param.h> 55 #include <sys/select.h> 56 #include <sys/uio.h> 57 58 #include <netinet/tcp.h> 59 #include <netinet/in.h> 60 61 #endif /* tnftp */ 62 63 #ifdef WITH_SSL 64 #include <openssl/crypto.h> 65 #include <openssl/x509.h> 66 #include <openssl/pem.h> 67 #include <openssl/ssl.h> 68 #include <openssl/err.h> 69 #endif 70 71 #include "ssl.h" 72 73 extern int quit_time, verbose, ftp_debug; 74 extern FILE *ttyout; 75 76 struct fetch_connect { 77 int sd; /* file/socket descriptor */ 78 char *buf; /* buffer */ 79 size_t bufsize; /* buffer size */ 80 size_t bufpos; /* position of buffer */ 81 size_t buflen; /* length of buffer contents */ 82 struct { /* data cached after an 83 interrupted read */ 84 char *buf; 85 size_t size; 86 size_t pos; 87 size_t len; 88 } cache; 89 int issock; 90 int iserr; 91 int iseof; 92 #ifdef WITH_SSL 93 SSL *ssl; /* SSL handle */ 94 #endif 95 }; 96 97 /* 98 * Write a vector to a connection w/ timeout 99 * Note: can modify the iovec. 100 */ 101 static ssize_t 102 fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt) 103 { 104 struct timeval now, timeout, delta; 105 fd_set writefds; 106 ssize_t len, total; 107 int fd = conn->sd; 108 int r; 109 110 if (quit_time > 0) { 111 FD_ZERO(&writefds); 112 gettimeofday(&timeout, NULL); 113 timeout.tv_sec += quit_time; 114 } 115 116 total = 0; 117 while (iovcnt > 0) { 118 while (quit_time > 0 && !FD_ISSET(fd, &writefds)) { 119 FD_SET(fd, &writefds); 120 gettimeofday(&now, NULL); 121 delta.tv_sec = timeout.tv_sec - now.tv_sec; 122 delta.tv_usec = timeout.tv_usec - now.tv_usec; 123 if (delta.tv_usec < 0) { 124 delta.tv_usec += 1000000; 125 delta.tv_sec--; 126 } 127 if (delta.tv_sec < 0) { 128 errno = ETIMEDOUT; 129 return -1; 130 } 131 errno = 0; 132 r = select(fd + 1, NULL, &writefds, NULL, &delta); 133 if (r == -1) { 134 if (errno == EINTR) 135 continue; 136 return -1; 137 } 138 } 139 errno = 0; 140 #ifdef WITH_SSL 141 if (conn->ssl != NULL) 142 len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len); 143 else 144 #endif 145 len = writev(fd, iov, iovcnt); 146 if (len == 0) { 147 /* we consider a short write a failure */ 148 /* XXX perhaps we shouldn't in the SSL case */ 149 errno = EPIPE; 150 return -1; 151 } 152 if (len < 0) { 153 if (errno == EINTR || errno == EAGAIN) 154 continue; 155 return -1; 156 } 157 total += len; 158 while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) { 159 len -= iov->iov_len; 160 iov++; 161 iovcnt--; 162 } 163 if (iovcnt > 0) { 164 iov->iov_len -= len; 165 iov->iov_base = (char *)iov->iov_base + len; 166 } 167 } 168 return total; 169 } 170 171 static ssize_t 172 fetch_write(const void *str, size_t len, struct fetch_connect *conn) 173 { 174 struct iovec iov[1]; 175 176 iov[0].iov_base = __DECONST(char *, str); 177 iov[0].iov_len = len; 178 return fetch_writev(conn, iov, 1); 179 } 180 181 /* 182 * Send a formatted line; optionally echo to terminal 183 */ 184 int 185 fetch_printf(struct fetch_connect *conn, const char *fmt, ...) 186 { 187 va_list ap; 188 size_t len; 189 char *msg; 190 int r; 191 192 va_start(ap, fmt); 193 len = vasprintf(&msg, fmt, ap); 194 va_end(ap); 195 196 if (msg == NULL) { 197 errno = ENOMEM; 198 return -1; 199 } 200 201 r = fetch_write(msg, len, conn); 202 free(msg); 203 return r; 204 } 205 206 int 207 fetch_fileno(struct fetch_connect *conn) 208 { 209 210 return conn->sd; 211 } 212 213 int 214 fetch_error(struct fetch_connect *conn) 215 { 216 217 return conn->iserr; 218 } 219 220 static void 221 fetch_clearerr(struct fetch_connect *conn) 222 { 223 224 conn->iserr = 0; 225 } 226 227 int 228 fetch_flush(struct fetch_connect *conn) 229 { 230 231 if (conn->issock) { 232 int fd = conn->sd; 233 int v; 234 #ifdef TCP_NOPUSH 235 v = 0; 236 setsockopt(fd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v)); 237 #endif 238 v = 1; 239 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); 240 } 241 return 0; 242 } 243 244 /*ARGSUSED*/ 245 struct fetch_connect * 246 fetch_open(const char *fname, const char *fmode) 247 { 248 struct fetch_connect *conn; 249 int fd; 250 251 fd = open(fname, O_RDONLY); /* XXX: fmode */ 252 if (fd < 0) 253 return NULL; 254 255 if ((conn = calloc(1, sizeof(*conn))) == NULL) { 256 close(fd); 257 return NULL; 258 } 259 260 conn->sd = fd; 261 conn->issock = 0; 262 return conn; 263 } 264 265 /*ARGSUSED*/ 266 struct fetch_connect * 267 fetch_fdopen(int sd, const char *fmode) 268 { 269 struct fetch_connect *conn; 270 #if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH) 271 int opt = 1; 272 #endif 273 274 if ((conn = calloc(1, sizeof(*conn))) == NULL) 275 return NULL; 276 277 conn->sd = sd; 278 conn->issock = 1; 279 fcntl(sd, F_SETFD, FD_CLOEXEC); 280 #ifdef SO_NOSIGPIPE 281 setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); 282 #endif 283 #ifdef TCP_NOPUSH 284 setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt)); 285 #endif 286 return conn; 287 } 288 289 int 290 fetch_close(struct fetch_connect *conn) 291 { 292 if (conn == NULL) 293 return 0; 294 295 fetch_flush(conn); 296 #ifdef WITH_SSL 297 SSL_free(conn->ssl); 298 #endif 299 close(conn->sd); 300 free(conn->cache.buf); 301 free(conn->buf); 302 free(conn); 303 return 0; 304 } 305 306 #define FETCH_WRITE_WAIT -3 307 #define FETCH_READ_WAIT -2 308 #define FETCH_READ_ERROR -1 309 310 #ifdef WITH_SSL 311 static ssize_t 312 fetch_ssl_read(SSL *ssl, void *buf, size_t len) 313 { 314 ssize_t rlen; 315 rlen = SSL_read(ssl, buf, len); 316 if (rlen >= 0) 317 return rlen; 318 319 switch (SSL_get_error(ssl, rlen)) { 320 case SSL_ERROR_WANT_READ: 321 return FETCH_READ_WAIT; 322 case SSL_ERROR_WANT_WRITE: 323 return FETCH_WRITE_WAIT; 324 default: 325 ERR_print_errors_fp(ttyout); 326 return FETCH_READ_ERROR; 327 } 328 } 329 #endif /* WITH_SSL */ 330 331 static ssize_t 332 fetch_nonssl_read(int sd, void *buf, size_t len) 333 { 334 ssize_t rlen; 335 336 rlen = read(sd, buf, len); 337 if (rlen == -1) { 338 if (errno == EAGAIN || errno == EINTR) 339 return FETCH_READ_WAIT; 340 return FETCH_READ_ERROR; 341 } 342 return rlen; 343 } 344 345 /* 346 * Cache some data that was read from a socket but cannot be immediately 347 * returned because of an interrupted system call. 348 */ 349 static int 350 fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes) 351 { 352 353 if (conn->cache.size < nbytes) { 354 char *tmp = realloc(conn->cache.buf, nbytes); 355 if (tmp == NULL) 356 return -1; 357 358 conn->cache.buf = tmp; 359 conn->cache.size = nbytes; 360 } 361 362 memcpy(conn->cache.buf, src, nbytes); 363 conn->cache.len = nbytes; 364 conn->cache.pos = 0; 365 return 0; 366 } 367 368 static int 369 fetch_wait(struct fetch_connect *conn, ssize_t rlen, struct timeval *timeout) 370 { 371 struct timeval now, delta; 372 int fd = conn->sd; 373 fd_set fds; 374 375 FD_ZERO(&fds); 376 while (!FD_ISSET(fd, &fds)) { 377 FD_SET(fd, &fds); 378 if (quit_time > 0) { 379 gettimeofday(&now, NULL); 380 if (!timercmp(timeout, &now, >)) { 381 fprintf(ttyout, "\r\n%s: transfer aborted" 382 " because stalled for %lu sec.\r\n", 383 getprogname(), (unsigned long)quit_time); 384 errno = ETIMEDOUT; 385 conn->iserr = ETIMEDOUT; 386 return -1; 387 } 388 timersub(timeout, &now, &delta); 389 } 390 errno = 0; 391 if (select(fd + 1, 392 rlen == FETCH_READ_WAIT ? &fds : NULL, 393 rlen == FETCH_WRITE_WAIT ? &fds : NULL, 394 NULL, quit_time > 0 ? &delta : NULL) < 0) { 395 if (errno == EINTR) 396 continue; 397 conn->iserr = errno; 398 return -1; 399 } 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 * select() -> 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 select(). 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) 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 void * 593 fetch_start_ssl(int sock, const char *servername) 594 { 595 SSL *ssl; 596 SSL_CTX *ctx; 597 int ret, ssl_err; 598 599 /* Init the SSL library and context */ 600 if (!SSL_library_init()){ 601 fprintf(ttyout, "SSL library init failed\n"); 602 return NULL; 603 } 604 605 SSL_load_error_strings(); 606 607 ctx = SSL_CTX_new(SSLv23_client_method()); 608 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 609 610 ssl = SSL_new(ctx); 611 if (ssl == NULL){ 612 fprintf(ttyout, "SSL context creation failed\n"); 613 SSL_CTX_free(ctx); 614 return NULL; 615 } 616 SSL_set_fd(ssl, sock); 617 if (!SSL_set_tlsext_host_name(ssl, __UNCONST(servername))) { 618 fprintf(ttyout, "SSL hostname setting failed\n"); 619 SSL_CTX_free(ctx); 620 return NULL; 621 } 622 while ((ret = SSL_connect(ssl)) == -1) { 623 ssl_err = SSL_get_error(ssl, ret); 624 if (ssl_err != SSL_ERROR_WANT_READ && 625 ssl_err != SSL_ERROR_WANT_WRITE) { 626 ERR_print_errors_fp(ttyout); 627 SSL_free(ssl); 628 return NULL; 629 } 630 } 631 632 if (ftp_debug && verbose) { 633 X509 *cert; 634 X509_NAME *name; 635 char *str; 636 637 fprintf(ttyout, "SSL connection established using %s\n", 638 SSL_get_cipher(ssl)); 639 cert = SSL_get_peer_certificate(ssl); 640 name = X509_get_subject_name(cert); 641 str = X509_NAME_oneline(name, 0, 0); 642 fprintf(ttyout, "Certificate subject: %s\n", str); 643 free(str); 644 name = X509_get_issuer_name(cert); 645 str = X509_NAME_oneline(name, 0, 0); 646 fprintf(ttyout, "Certificate issuer: %s\n", str); 647 free(str); 648 } 649 650 return ssl; 651 } 652 #endif /* WITH_SSL */ 653 654 655 void 656 fetch_set_ssl(struct fetch_connect *conn, void *ssl) 657 { 658 #ifdef WITH_SSL 659 conn->ssl = ssl; 660 #endif 661 } 662