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