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