1 #include <sys/poll.h> 2 #include <openssl/ssl.h> 3 #include <uv.h> 4 #include <assert.h> 5 #ifdef USE_QUIC 6 # include <sys/time.h> 7 #endif 8 9 typedef struct app_conn_st APP_CONN; 10 typedef struct upper_write_op_st UPPER_WRITE_OP; 11 typedef struct lower_write_op_st LOWER_WRITE_OP; 12 13 typedef void (app_connect_cb)(APP_CONN *conn, int status, void *arg); 14 typedef void (app_write_cb)(APP_CONN *conn, int status, void *arg); 15 typedef void (app_read_cb)(APP_CONN *conn, void *buf, size_t buf_len, void *arg); 16 17 #ifdef USE_QUIC 18 static void set_timer(APP_CONN *conn); 19 #else 20 static void tcp_connect_done(uv_connect_t *tcp_connect, int status); 21 #endif 22 static void net_connect_fail_close_done(uv_handle_t *handle); 23 static int handshake_ssl(APP_CONN *conn); 24 static void flush_write_buf(APP_CONN *conn); 25 static void set_rx(APP_CONN *conn); 26 static int try_write(APP_CONN *conn, UPPER_WRITE_OP *op); 27 static void handle_pending_writes(APP_CONN *conn); 28 static int write_deferred(APP_CONN *conn, const void *buf, size_t buf_len, app_write_cb *cb, void *arg); 29 static void teardown_continued(uv_handle_t *handle); 30 static int setup_ssl(APP_CONN *conn, const char *hostname); 31 32 #ifdef USE_QUIC 33 static inline int timeval_to_ms(const struct timeval *t) 34 { 35 return t->tv_sec*1000 + t->tv_usec/1000; 36 } 37 #endif 38 39 /* 40 * Structure to track an application-level write request. Only created 41 * if SSL_write does not accept the data immediately, typically because 42 * it is in WANT_READ. 43 */ 44 struct upper_write_op_st { 45 struct upper_write_op_st *prev, *next; 46 const uint8_t *buf; 47 size_t buf_len, written; 48 APP_CONN *conn; 49 app_write_cb *cb; 50 void *cb_arg; 51 }; 52 53 /* 54 * Structure to track a network-level write request. 55 */ 56 struct lower_write_op_st { 57 #ifdef USE_QUIC 58 uv_udp_send_t w; 59 #else 60 uv_write_t w; 61 #endif 62 uv_buf_t b; 63 uint8_t *buf; 64 APP_CONN *conn; 65 }; 66 67 /* 68 * Application connection object. 69 */ 70 struct app_conn_st { 71 SSL_CTX *ctx; 72 SSL *ssl; 73 BIO *net_bio; 74 #ifdef USE_QUIC 75 uv_udp_t udp; 76 uv_timer_t timer; 77 #else 78 uv_stream_t *stream; 79 uv_tcp_t tcp; 80 uv_connect_t tcp_connect; 81 #endif 82 app_connect_cb *app_connect_cb; /* called once handshake is done */ 83 void *app_connect_arg; 84 app_read_cb *app_read_cb; /* application's on-RX callback */ 85 void *app_read_arg; 86 const char *hostname; 87 char init_handshake, done_handshake, closed; 88 char *teardown_done; 89 90 UPPER_WRITE_OP *pending_upper_write_head, *pending_upper_write_tail; 91 }; 92 93 /* 94 * The application is initializing and wants an SSL_CTX which it will use for 95 * some number of outgoing connections, which it creates in subsequent calls to 96 * new_conn. The application may also call this function multiple times to 97 * create multiple SSL_CTX. 98 */ 99 SSL_CTX *create_ssl_ctx(void) 100 { 101 SSL_CTX *ctx; 102 103 #ifdef USE_QUIC 104 ctx = SSL_CTX_new(OSSL_QUIC_client_method()); 105 #else 106 ctx = SSL_CTX_new(TLS_client_method()); 107 #endif 108 if (ctx == NULL) 109 return NULL; 110 111 /* Enable trust chain verification. */ 112 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 113 114 /* Load default root CA store. */ 115 if (SSL_CTX_set_default_verify_paths(ctx) == 0) { 116 SSL_CTX_free(ctx); 117 return NULL; 118 } 119 120 return ctx; 121 } 122 123 /* 124 * The application wants to create a new outgoing connection using a given 125 * SSL_CTX. An outgoing TCP connection is started and the callback is called 126 * asynchronously when the TLS handshake is complete. 127 * 128 * hostname is a string like "openssl.org" used for certificate validation. 129 */ 130 131 APP_CONN *new_conn(SSL_CTX *ctx, const char *hostname, 132 struct sockaddr *sa, socklen_t sa_len, 133 app_connect_cb *cb, void *arg) 134 { 135 int rc; 136 APP_CONN *conn = NULL; 137 138 conn = calloc(1, sizeof(APP_CONN)); 139 if (!conn) 140 return NULL; 141 142 #ifdef USE_QUIC 143 uv_udp_init(uv_default_loop(), &conn->udp); 144 conn->udp.data = conn; 145 146 uv_timer_init(uv_default_loop(), &conn->timer); 147 conn->timer.data = conn; 148 #else 149 uv_tcp_init(uv_default_loop(), &conn->tcp); 150 conn->tcp.data = conn; 151 152 conn->stream = (uv_stream_t *)&conn->tcp; 153 #endif 154 155 conn->app_connect_cb = cb; 156 conn->app_connect_arg = arg; 157 #ifdef USE_QUIC 158 rc = uv_udp_connect(&conn->udp, sa); 159 #else 160 conn->tcp_connect.data = conn; 161 rc = uv_tcp_connect(&conn->tcp_connect, &conn->tcp, sa, tcp_connect_done); 162 #endif 163 if (rc < 0) { 164 #ifdef USE_QUIC 165 uv_close((uv_handle_t *)&conn->udp, net_connect_fail_close_done); 166 #else 167 uv_close((uv_handle_t *)&conn->tcp, net_connect_fail_close_done); 168 #endif 169 return NULL; 170 } 171 172 conn->ctx = ctx; 173 conn->hostname = hostname; 174 175 #ifdef USE_QUIC 176 rc = setup_ssl(conn, hostname); 177 if (rc < 0) { 178 uv_close((uv_handle_t *)&conn->udp, net_connect_fail_close_done); 179 return NULL; 180 } 181 #endif 182 183 return conn; 184 } 185 186 /* 187 * The application wants to start reading from the SSL stream. 188 * The callback is called whenever data is available. 189 */ 190 int app_read_start(APP_CONN *conn, app_read_cb *cb, void *arg) 191 { 192 conn->app_read_cb = cb; 193 conn->app_read_arg = arg; 194 set_rx(conn); 195 return 0; 196 } 197 198 /* 199 * The application wants to write. The callback is called once the 200 * write is complete. The callback should free the buffer. 201 */ 202 int app_write(APP_CONN *conn, const void *buf, size_t buf_len, app_write_cb *cb, void *arg) 203 { 204 write_deferred(conn, buf, buf_len, cb, arg); 205 handle_pending_writes(conn); 206 return buf_len; 207 } 208 209 /* 210 * The application wants to close the connection and free bookkeeping 211 * structures. 212 */ 213 void teardown(APP_CONN *conn) 214 { 215 char teardown_done = 0; 216 217 if (conn == NULL) 218 return; 219 220 BIO_free_all(conn->net_bio); 221 SSL_free(conn->ssl); 222 223 #ifndef USE_QUIC 224 uv_cancel((uv_req_t *)&conn->tcp_connect); 225 #endif 226 227 conn->teardown_done = &teardown_done; 228 #ifdef USE_QUIC 229 uv_close((uv_handle_t *)&conn->udp, teardown_continued); 230 uv_close((uv_handle_t *)&conn->timer, teardown_continued); 231 #else 232 uv_close((uv_handle_t *)conn->stream, teardown_continued); 233 #endif 234 235 /* Just wait synchronously until teardown completes. */ 236 #ifdef USE_QUIC 237 while (teardown_done < 2) 238 #else 239 while (!teardown_done) 240 #endif 241 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 242 } 243 244 /* 245 * The application is shutting down and wants to free a previously 246 * created SSL_CTX. 247 */ 248 void teardown_ctx(SSL_CTX *ctx) 249 { 250 SSL_CTX_free(ctx); 251 } 252 253 /* 254 * ============================================================================ 255 * Internal implementation functions. 256 */ 257 static void enqueue_upper_write_op(APP_CONN *conn, UPPER_WRITE_OP *op) 258 { 259 op->prev = conn->pending_upper_write_tail; 260 if (op->prev) 261 op->prev->next = op; 262 263 conn->pending_upper_write_tail = op; 264 if (conn->pending_upper_write_head == NULL) 265 conn->pending_upper_write_head = op; 266 } 267 268 static void dequeue_upper_write_op(APP_CONN *conn) 269 { 270 if (conn->pending_upper_write_head == NULL) 271 return; 272 273 if (conn->pending_upper_write_head->next == NULL) { 274 conn->pending_upper_write_head = NULL; 275 conn->pending_upper_write_tail = NULL; 276 } else { 277 conn->pending_upper_write_head = conn->pending_upper_write_head->next; 278 conn->pending_upper_write_head->prev = NULL; 279 } 280 } 281 282 static void net_read_alloc(uv_handle_t *handle, 283 size_t suggested_size, uv_buf_t *buf) 284 { 285 #ifdef USE_QUIC 286 if (suggested_size < 1472) 287 suggested_size = 1472; 288 #endif 289 290 buf->base = malloc(suggested_size); 291 buf->len = suggested_size; 292 } 293 294 static void on_rx_push(APP_CONN *conn) 295 { 296 int srd, rc; 297 int buf_len = 4096; 298 299 do { 300 if (!conn->app_read_cb) 301 return; 302 303 void *buf = malloc(buf_len); 304 if (!buf) 305 return; 306 307 srd = SSL_read(conn->ssl, buf, buf_len); 308 flush_write_buf(conn); 309 if (srd <= 0) { 310 rc = SSL_get_error(conn->ssl, srd); 311 if (rc == SSL_ERROR_WANT_READ) { 312 free(buf); 313 return; 314 } 315 } 316 317 conn->app_read_cb(conn, buf, srd, conn->app_read_arg); 318 } while (srd == buf_len); 319 } 320 321 static void net_error(APP_CONN *conn) 322 { 323 conn->closed = 1; 324 set_rx(conn); 325 326 if (conn->app_read_cb) 327 conn->app_read_cb(conn, NULL, 0, conn->app_read_arg); 328 } 329 330 static void handle_pending_writes(APP_CONN *conn) 331 { 332 int rc; 333 334 if (conn->pending_upper_write_head == NULL) 335 return; 336 337 do { 338 UPPER_WRITE_OP *op = conn->pending_upper_write_head; 339 rc = try_write(conn, op); 340 if (rc <= 0) 341 break; 342 343 dequeue_upper_write_op(conn); 344 free(op); 345 } while (conn->pending_upper_write_head != NULL); 346 347 set_rx(conn); 348 } 349 350 #ifdef USE_QUIC 351 static void net_read_done(uv_udp_t *stream, ssize_t nr, const uv_buf_t *buf, 352 const struct sockaddr *addr, unsigned int flags) 353 #else 354 static void net_read_done(uv_stream_t *stream, ssize_t nr, const uv_buf_t *buf) 355 #endif 356 { 357 int rc; 358 APP_CONN *conn = (APP_CONN *)stream->data; 359 360 if (nr < 0) { 361 free(buf->base); 362 net_error(conn); 363 return; 364 } 365 366 if (nr > 0) { 367 int wr = BIO_write(conn->net_bio, buf->base, nr); 368 assert(wr == nr); 369 } 370 371 free(buf->base); 372 373 if (!conn->done_handshake) { 374 rc = handshake_ssl(conn); 375 if (rc < 0) { 376 fprintf(stderr, "handshake error: %d\n", rc); 377 return; 378 } 379 380 if (!conn->done_handshake) 381 return; 382 } 383 384 handle_pending_writes(conn); 385 on_rx_push(conn); 386 } 387 388 static void set_rx(APP_CONN *conn) 389 { 390 #ifdef USE_QUIC 391 if (!conn->closed) 392 uv_udp_recv_start(&conn->udp, net_read_alloc, net_read_done); 393 else 394 uv_udp_recv_stop(&conn->udp); 395 #else 396 if (!conn->closed && (conn->app_read_cb || (!conn->done_handshake && conn->init_handshake) || conn->pending_upper_write_head != NULL)) 397 uv_read_start(conn->stream, net_read_alloc, net_read_done); 398 else 399 uv_read_stop(conn->stream); 400 #endif 401 } 402 403 #ifdef USE_QUIC 404 static void net_write_done(uv_udp_send_t *req, int status) 405 #else 406 static void net_write_done(uv_write_t *req, int status) 407 #endif 408 { 409 LOWER_WRITE_OP *op = (LOWER_WRITE_OP *)req->data; 410 APP_CONN *conn = op->conn; 411 412 if (status < 0) { 413 fprintf(stderr, "UV write failed %d\n", status); 414 return; 415 } 416 417 free(op->buf); 418 free(op); 419 420 flush_write_buf(conn); 421 } 422 423 static void flush_write_buf(APP_CONN *conn) 424 { 425 int rc, rd; 426 LOWER_WRITE_OP *op; 427 uint8_t *buf; 428 429 buf = malloc(4096); 430 if (!buf) 431 return; 432 433 rd = BIO_read(conn->net_bio, buf, 4096); 434 if (rd <= 0) { 435 free(buf); 436 return; 437 } 438 439 op = calloc(1, sizeof(LOWER_WRITE_OP)); 440 if (!op) 441 return; 442 443 op->buf = buf; 444 op->conn = conn; 445 op->w.data = op; 446 op->b.base = (char *)buf; 447 op->b.len = rd; 448 449 #ifdef USE_QUIC 450 rc = uv_udp_send(&op->w, &conn->udp, &op->b, 1, NULL, net_write_done); 451 #else 452 rc = uv_write(&op->w, conn->stream, &op->b, 1, net_write_done); 453 #endif 454 if (rc < 0) { 455 free(buf); 456 free(op); 457 fprintf(stderr, "UV write failed\n"); 458 return; 459 } 460 } 461 462 static void handshake_done_ssl(APP_CONN *conn) 463 { 464 #ifdef USE_QUIC 465 set_timer(conn); 466 #endif 467 conn->app_connect_cb(conn, 0, conn->app_connect_arg); 468 } 469 470 static int handshake_ssl(APP_CONN *conn) 471 { 472 int rc, rcx; 473 474 conn->init_handshake = 1; 475 476 rc = SSL_do_handshake(conn->ssl); 477 if (rc > 0) { 478 conn->done_handshake = 1; 479 handshake_done_ssl(conn); 480 set_rx(conn); 481 return 0; 482 } 483 484 flush_write_buf(conn); 485 rcx = SSL_get_error(conn->ssl, rc); 486 if (rcx == SSL_ERROR_WANT_READ) { 487 set_rx(conn); 488 return 0; 489 } 490 491 fprintf(stderr, "Handshake error: %d\n", rcx); 492 return -rcx; 493 } 494 495 static int setup_ssl(APP_CONN *conn, const char *hostname) 496 { 497 BIO *internal_bio = NULL, *net_bio = NULL; 498 SSL *ssl = NULL; 499 #ifdef USE_QUIC 500 static const unsigned char alpn[] = {5, 'd', 'u', 'm', 'm', 'y'}; 501 #endif 502 503 ssl = SSL_new(conn->ctx); 504 if (!ssl) 505 return -1; 506 507 SSL_set_connect_state(ssl); 508 509 #ifdef USE_QUIC 510 if (BIO_new_bio_dgram_pair(&internal_bio, 0, &net_bio, 0) <= 0) { 511 SSL_free(ssl); 512 return -1; 513 } 514 #else 515 if (BIO_new_bio_pair(&internal_bio, 0, &net_bio, 0) <= 0) { 516 SSL_free(ssl); 517 return -1; 518 } 519 #endif 520 521 SSL_set_bio(ssl, internal_bio, internal_bio); 522 523 if (SSL_set1_host(ssl, hostname) <= 0) { 524 SSL_free(ssl); 525 return -1; 526 } 527 528 if (SSL_set_tlsext_host_name(ssl, hostname) <= 0) { 529 SSL_free(ssl); 530 return -1; 531 } 532 533 #ifdef USE_QUIC 534 /* Configure ALPN, which is required for QUIC. */ 535 if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) { 536 /* Note: SSL_set_alpn_protos returns 1 for failure. */ 537 SSL_free(ssl); 538 return -1; 539 } 540 #endif 541 542 conn->net_bio = net_bio; 543 conn->ssl = ssl; 544 return handshake_ssl(conn); 545 } 546 547 #ifndef USE_QUIC 548 static void tcp_connect_done(uv_connect_t *tcp_connect, int status) 549 { 550 int rc; 551 APP_CONN *conn = (APP_CONN *)tcp_connect->data; 552 553 if (status < 0) { 554 uv_stop(uv_default_loop()); 555 return; 556 } 557 558 rc = setup_ssl(conn, conn->hostname); 559 if (rc < 0) { 560 fprintf(stderr, "cannot init SSL\n"); 561 uv_stop(uv_default_loop()); 562 return; 563 } 564 } 565 #endif 566 567 static void net_connect_fail_close_done(uv_handle_t *handle) 568 { 569 APP_CONN *conn = (APP_CONN *)handle->data; 570 571 free(conn); 572 } 573 574 #ifdef USE_QUIC 575 576 static void timer_done(uv_timer_t *timer) 577 { 578 APP_CONN *conn = (APP_CONN *)timer->data; 579 580 SSL_handle_events(conn->ssl); 581 handle_pending_writes(conn); 582 flush_write_buf(conn); 583 set_rx(conn); 584 set_timer(conn); /* repeat timer */ 585 } 586 587 static void set_timer(APP_CONN *conn) 588 { 589 struct timeval tv; 590 int ms, is_infinite; 591 592 if (!SSL_get_event_timeout(conn->ssl, &tv, &is_infinite)) 593 return; 594 595 ms = is_infinite ? -1 : timeval_to_ms(&tv); 596 if (ms > 0) 597 uv_timer_start(&conn->timer, timer_done, ms, 0); 598 } 599 600 #endif 601 602 static int try_write(APP_CONN *conn, UPPER_WRITE_OP *op) 603 { 604 int rc, rcx; 605 size_t written = op->written; 606 607 while (written < op->buf_len) { 608 rc = SSL_write(conn->ssl, op->buf + written, op->buf_len - written); 609 if (rc <= 0) { 610 rcx = SSL_get_error(conn->ssl, rc); 611 if (rcx == SSL_ERROR_WANT_READ) { 612 op->written = written; 613 return 0; 614 } else { 615 if (op->cb != NULL) 616 op->cb(conn, -rcx, op->cb_arg); 617 return 1; /* op should be freed */ 618 } 619 } 620 621 written += rc; 622 } 623 624 if (op->cb != NULL) 625 op->cb(conn, 0, op->cb_arg); 626 627 flush_write_buf(conn); 628 return 1; /* op should be freed */ 629 } 630 631 static int write_deferred(APP_CONN *conn, const void *buf, size_t buf_len, app_write_cb *cb, void *arg) 632 { 633 UPPER_WRITE_OP *op = calloc(1, sizeof(UPPER_WRITE_OP)); 634 if (!op) 635 return -1; 636 637 op->buf = buf; 638 op->buf_len = buf_len; 639 op->conn = conn; 640 op->cb = cb; 641 op->cb_arg = arg; 642 643 enqueue_upper_write_op(conn, op); 644 set_rx(conn); 645 flush_write_buf(conn); 646 return buf_len; 647 } 648 649 static void teardown_continued(uv_handle_t *handle) 650 { 651 APP_CONN *conn = (APP_CONN *)handle->data; 652 UPPER_WRITE_OP *op, *next_op; 653 char *teardown_done = conn->teardown_done; 654 655 #ifdef USE_QUIC 656 if (++*teardown_done < 2) 657 return; 658 #endif 659 660 for (op=conn->pending_upper_write_head; op; op=next_op) { 661 next_op = op->next; 662 free(op); 663 } 664 665 free(conn); 666 #ifndef USE_QUIC 667 *teardown_done = 1; 668 #endif 669 } 670 671 /* 672 * ============================================================================ 673 * Example driver for the above code. This is just to demonstrate that the code 674 * works and is not intended to be representative of a real application. 675 */ 676 static void post_read(APP_CONN *conn, void *buf, size_t buf_len, void *arg) 677 { 678 if (!buf_len) { 679 free(buf); 680 uv_stop(uv_default_loop()); 681 return; 682 } 683 684 fwrite(buf, 1, buf_len, stdout); 685 free(buf); 686 } 687 688 static void post_write_get(APP_CONN *conn, int status, void *arg) 689 { 690 if (status < 0) { 691 fprintf(stderr, "write failed: %d\n", status); 692 return; 693 } 694 695 app_read_start(conn, post_read, NULL); 696 } 697 698 char tx_msg[300]; 699 int mlen; 700 701 static void post_connect(APP_CONN *conn, int status, void *arg) 702 { 703 int wr; 704 705 if (status < 0) { 706 fprintf(stderr, "failed to connect: %d\n", status); 707 uv_stop(uv_default_loop()); 708 return; 709 } 710 711 wr = app_write(conn, tx_msg, mlen, post_write_get, NULL); 712 if (wr < mlen) { 713 fprintf(stderr, "error writing request"); 714 return; 715 } 716 } 717 718 int main(int argc, char **argv) 719 { 720 int rc = 1; 721 SSL_CTX *ctx = NULL; 722 APP_CONN *conn = NULL; 723 struct addrinfo hints = {0}, *result = NULL; 724 725 if (argc < 3) { 726 fprintf(stderr, "usage: %s host port\n", argv[0]); 727 goto fail; 728 } 729 730 mlen = snprintf(tx_msg, sizeof(tx_msg), 731 "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", argv[1]); 732 733 ctx = create_ssl_ctx(); 734 if (!ctx) 735 goto fail; 736 737 hints.ai_family = AF_INET; 738 hints.ai_socktype = SOCK_STREAM; 739 hints.ai_flags = AI_PASSIVE; 740 rc = getaddrinfo(argv[1], argv[2], &hints, &result); 741 if (rc < 0) { 742 fprintf(stderr, "cannot resolve\n"); 743 goto fail; 744 } 745 746 conn = new_conn(ctx, argv[1], result->ai_addr, result->ai_addrlen, post_connect, NULL); 747 if (!conn) 748 goto fail; 749 750 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 751 752 rc = 0; 753 fail: 754 teardown(conn); 755 freeaddrinfo(result); 756 uv_loop_close(uv_default_loop()); 757 teardown_ctx(ctx); 758 } 759