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