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