1 2 /* 3 * Copyright (C) NGINX, Inc. 4 * Copyright (C) Igor Sysoev 5 */ 6 7 #include <nxt_main.h> 8 #include <cyassl/ssl.h> 9 #include <cyassl/error-ssl.h> 10 11 12 typedef struct { 13 CYASSL *session; 14 15 int ssl_error; 16 uint8_t times; /* 2 bits */ 17 18 nxt_buf_mem_t buffer; 19 } nxt_cyassl_conn_t; 20 21 22 static nxt_int_t nxt_cyassl_server_init(nxt_ssltls_conf_t *conf); 23 static void nxt_cyassl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, 24 nxt_event_conn_t *c); 25 static void nxt_cyassl_session_cleanup(void *data); 26 static int nxt_cyassl_io_recv(CYASSL *ssl, char *buf, int size, void *data); 27 static int nxt_cyassl_io_send(CYASSL *ssl, char *buf, int size, void *data); 28 static void nxt_cyassl_conn_handshake(nxt_thread_t *thr, void *obj, void *data); 29 static void nxt_cyassl_conn_io_read(nxt_thread_t *thr, void *obj, void *data); 30 static void nxt_cyassl_conn_io_shutdown(nxt_thread_t *thr, void *obj, 31 void *data); 32 static ssize_t nxt_cyassl_conn_io_write_chunk(nxt_thread_t *thr, 33 nxt_event_conn_t *c, nxt_buf_t *b, size_t limit); 34 static ssize_t nxt_cyassl_conn_io_send(nxt_event_conn_t *c, void *buf, 35 size_t size); 36 static nxt_int_t nxt_cyassl_conn_test_error(nxt_thread_t *thr, 37 nxt_event_conn_t *c, int err, nxt_work_handler_t handler); 38 static void nxt_cdecl nxt_cyassl_conn_error(nxt_event_conn_t *c, nxt_err_t err, 39 const char *fmt, ...); 40 static nxt_uint_t nxt_cyassl_log_error_level(nxt_event_conn_t *c, nxt_err_t err, 41 int ssl_error); 42 static void nxt_cdecl nxt_cyassl_log_error(nxt_uint_t level, nxt_log_t *log, 43 int ret, const char *fmt, ...); 44 static u_char *nxt_cyassl_copy_error(int err, u_char *p, u_char *end); 45 46 47 const nxt_ssltls_lib_t nxt_cyassl_lib = { 48 nxt_cyassl_server_init, 49 NULL, 50 }; 51 52 53 static nxt_event_conn_io_t nxt_cyassl_event_conn_io = { 54 NULL, 55 NULL, 56 57 nxt_cyassl_conn_io_read, 58 NULL, 59 NULL, 60 61 nxt_event_conn_io_write, 62 nxt_cyassl_conn_io_write_chunk, 63 NULL, 64 NULL, 65 nxt_cyassl_conn_io_send, 66 67 nxt_cyassl_conn_io_shutdown, 68 }; 69 70 71 static nxt_int_t 72 nxt_cyassl_start(void) 73 { 74 int err; 75 nxt_thread_t *thr; 76 static nxt_bool_t started; 77 78 if (nxt_fast_path(started)) { 79 return NXT_OK; 80 } 81 82 started = 1; 83 84 thr = nxt_thread(); 85 86 /* TODO: CyaSSL_Cleanup() */ 87 88 err = CyaSSL_Init(); 89 if (err != SSL_SUCCESS) { 90 nxt_cyassl_log_error(NXT_LOG_CRIT, thr->log, err, 91 "CyaSSL_Init() failed"); 92 return NXT_ERROR; 93 } 94 95 nxt_thread_log_error(NXT_LOG_INFO, "CyaSSL version: %s", 96 LIBCYASSL_VERSION_STRING); 97 98 /* CyaSSL_SetLoggingCb */ 99 /* CyaSSL_SetAllocators */ 100 101 return NXT_OK; 102 } 103 104 105 static nxt_int_t 106 nxt_cyassl_server_init(nxt_ssltls_conf_t *conf) 107 { 108 int err; 109 char *certificate, *key; 110 CYASSL_CTX *ctx; 111 nxt_thread_t *thr; 112 113 thr = nxt_thread(); 114 115 if (nxt_slow_path(nxt_cyassl_start() != NXT_OK)) { 116 return NXT_ERROR; 117 } 118 119 ctx = CyaSSL_CTX_new(CyaSSLv23_server_method()); 120 if (ctx == NULL) { 121 nxt_cyassl_log_error(NXT_LOG_CRIT, thr->log, 0, 122 "CyaSSL_CTX_new() failed"); 123 return NXT_ERROR; 124 } 125 126 conf->ctx = ctx; 127 conf->conn_init = nxt_cyassl_conn_init; 128 129 certificate = conf->certificate; 130 131 err = CyaSSL_CTX_use_certificate_file(ctx, certificate, SSL_FILETYPE_PEM); 132 if (err != SSL_SUCCESS) { 133 nxt_cyassl_log_error(NXT_LOG_CRIT, thr->log, err, 134 "CyaSSL_CTX_use_certificate_file(\"%s\") failed", 135 certificate); 136 goto fail; 137 } 138 139 key = conf->certificate_key; 140 141 err = CyaSSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM); 142 if (err != SSL_SUCCESS) { 143 nxt_cyassl_log_error(NXT_LOG_CRIT, thr->log, err, 144 "CyaSSL_CTX_use_PrivateKey_file(\"%s\") failed", 145 key); 146 goto fail; 147 } 148 149 if (conf->ciphers != NULL) { 150 err = CyaSSL_CTX_set_cipher_list(ctx, conf->ciphers); 151 if (err != SSL_SUCCESS) { 152 nxt_cyassl_log_error(NXT_LOG_CRIT, thr->log, err, 153 "CyaSSL_CTX_set_cipher_list(\"%s\") failed", 154 conf->ciphers); 155 goto fail; 156 } 157 } 158 159 /* TODO: ca_certificate */ 160 161 CyaSSL_SetIORecv(ctx, nxt_cyassl_io_recv); 162 CyaSSL_SetIOSend(ctx, nxt_cyassl_io_send); 163 164 return NXT_OK; 165 166 fail: 167 168 CyaSSL_CTX_free(ctx); 169 170 return NXT_ERROR; 171 } 172 173 174 static void 175 nxt_cyassl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, 176 nxt_event_conn_t *c) 177 { 178 CYASSL *s; 179 CYASSL_CTX *ctx; 180 nxt_cyassl_conn_t *ssltls; 181 nxt_mem_pool_cleanup_t *mpcl; 182 183 nxt_log_debug(c->socket.log, "cyassl conn init"); 184 185 ssltls = nxt_mem_zalloc(c->mem_pool, sizeof(nxt_cyassl_conn_t)); 186 if (ssltls == NULL) { 187 goto fail; 188 } 189 190 c->u.ssltls = ssltls; 191 nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size); 192 193 mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0); 194 if (mpcl == NULL) { 195 goto fail; 196 } 197 198 ctx = conf->ctx; 199 200 s = CyaSSL_new(ctx); 201 if (s == NULL) { 202 nxt_cyassl_log_error(NXT_LOG_CRIT, c->socket.log, 0, 203 "CyaSSL_new() failed"); 204 goto fail; 205 } 206 207 ssltls->session = s; 208 mpcl->handler = nxt_cyassl_session_cleanup; 209 mpcl->data = ssltls; 210 211 CyaSSL_SetIOReadCtx(s, c); 212 CyaSSL_SetIOWriteCtx(s, c); 213 214 c->io = &nxt_cyassl_event_conn_io; 215 c->sendfile = NXT_CONN_SENDFILE_OFF; 216 217 nxt_cyassl_conn_handshake(thr, c, c->socket.data); 218 return; 219 220 fail: 221 222 nxt_event_conn_io_handle(thr, c->read_work_queue, 223 c->read_state->error_handler, c, c->socket.data); 224 } 225 226 227 static void 228 nxt_cyassl_session_cleanup(void *data) 229 { 230 nxt_cyassl_conn_t *ssltls; 231 232 ssltls = data; 233 234 nxt_thread_log_debug("cyassl session cleanup"); 235 236 nxt_free(ssltls->buffer.start); 237 238 CyaSSL_free(ssltls->session); 239 } 240 241 242 static int 243 nxt_cyassl_io_recv(CYASSL *ssl, char *buf, int size, void *data) 244 { 245 ssize_t n; 246 nxt_thread_t *thr; 247 nxt_event_conn_t *c; 248 249 c = data; 250 thr = nxt_thread(); 251 252 n = thr->engine->event->io->recv(c, (u_char *) buf, size, 0); 253 254 if (n > 0) { 255 return n; 256 } 257 258 if (n == 0) { 259 return CYASSL_CBIO_ERR_CONN_CLOSE; 260 } 261 262 if (n == NXT_AGAIN) { 263 return CYASSL_CBIO_ERR_WANT_READ; 264 } 265 266 return CYASSL_CBIO_ERR_GENERAL; 267 } 268 269 270 static int 271 nxt_cyassl_io_send(CYASSL *ssl, char *buf, int size, void *data) 272 { 273 ssize_t n; 274 nxt_thread_t *thr; 275 nxt_event_conn_t *c; 276 277 c = data; 278 thr = nxt_thread(); 279 280 n = thr->engine->event->io->send(c, (u_char *) buf, size); 281 282 if (n > 0) { 283 return n; 284 } 285 286 if (n == NXT_AGAIN) { 287 return CYASSL_CBIO_ERR_WANT_WRITE; 288 } 289 290 return CYASSL_CBIO_ERR_GENERAL; 291 } 292 293 294 static void 295 nxt_cyassl_conn_handshake(nxt_thread_t *thr, void *obj, void *data) 296 { 297 int ret; 298 nxt_int_t n; 299 nxt_err_t err; 300 nxt_event_conn_t *c; 301 nxt_cyassl_conn_t *ssltls; 302 303 c = obj; 304 ssltls = c->u.ssltls; 305 306 nxt_log_debug(thr->log, "cyassl conn handshake: %d", ssltls->times); 307 308 /* "ssltls->times == 1" is suitable to run CyaSSL_negotiate() in job. */ 309 310 ret = CyaSSL_negotiate(ssltls->session); 311 312 err = (ret != 0) ? nxt_socket_errno : 0; 313 314 nxt_thread_time_debug_update(thr); 315 316 nxt_log_debug(thr->log, "CyaSSL_negotiate(%d): %d", c->socket.fd, ret); 317 318 if (ret == 0) { 319 nxt_cyassl_conn_io_read(thr, c, data); 320 return; 321 } 322 323 n = nxt_cyassl_conn_test_error(thr, c, ret, nxt_cyassl_conn_handshake); 324 325 if (n == NXT_ERROR) { 326 nxt_cyassl_conn_error(c, err, "CyaSSL_negotiate(%d) failed", 327 c->socket.fd); 328 329 nxt_event_conn_io_handle(thr, c->read_work_queue, 330 c->read_state->error_handler, c, data); 331 332 } else if (ssltls->ssl_error == SSL_ERROR_WANT_READ && ssltls->times < 2) { 333 ssltls->times++; 334 } 335 } 336 337 338 static void 339 nxt_cyassl_conn_io_read(nxt_thread_t *thr, void *obj, void *data) 340 { 341 int ret; 342 nxt_buf_t *b; 343 nxt_err_t err; 344 nxt_int_t n; 345 nxt_event_conn_t *c; 346 nxt_cyassl_conn_t *ssltls; 347 nxt_work_handler_t handler; 348 349 c = obj; 350 351 nxt_log_debug(thr->log, "cyassl conn read"); 352 353 handler = c->read_state->ready_handler; 354 b = c->read; 355 356 /* b == NULL is used to test descriptor readiness. */ 357 358 if (b != NULL) { 359 ssltls = c->u.ssltls; 360 361 ret = CyaSSL_read(ssltls->session, b->mem.free, 362 b->mem.end - b->mem.free); 363 364 err = (ret <= 0) ? nxt_socket_errno : 0; 365 366 nxt_log_debug(thr->log, "CyaSSL_read(%d, %p, %uz): %d", 367 c->socket.fd, b->mem.free, b->mem.end - b->mem.free, ret); 368 369 if (ret > 0) { 370 /* c->socket.read_ready is kept. */ 371 b->mem.free += ret; 372 handler = c->read_state->ready_handler; 373 374 } else { 375 n = nxt_cyassl_conn_test_error(thr, c, ret, 376 nxt_cyassl_conn_io_read); 377 378 if (nxt_fast_path(n != NXT_ERROR)) { 379 return; 380 } 381 382 nxt_cyassl_conn_error(c, err, "CyaSSL_read(%d, %p, %uz) failed", 383 c->socket.fd, b->mem.free, 384 b->mem.end - b->mem.free); 385 386 handler = c->read_state->error_handler; 387 } 388 } 389 390 nxt_event_conn_io_handle(thr, c->read_work_queue, handler, c, data); 391 } 392 393 394 static ssize_t 395 nxt_cyassl_conn_io_write_chunk(nxt_thread_t *thr, nxt_event_conn_t *c, 396 nxt_buf_t *b, size_t limit) 397 { 398 nxt_cyassl_conn_t *ssltls; 399 400 nxt_log_debug(thr->log, "cyassl conn write chunk"); 401 402 ssltls = c->u.ssltls; 403 404 return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit); 405 } 406 407 408 static ssize_t 409 nxt_cyassl_conn_io_send(nxt_event_conn_t *c, void *buf, size_t size) 410 { 411 int ret; 412 nxt_err_t err; 413 nxt_int_t n; 414 nxt_cyassl_conn_t *ssltls; 415 416 nxt_log_debug(c->socket.log, "cyassl send"); 417 418 ssltls = c->u.ssltls; 419 420 ret = CyaSSL_write(ssltls->session, buf, size); 421 422 if (ret <= 0) { 423 err = nxt_socket_errno; 424 c->socket.error = err; 425 426 } else { 427 err = 0; 428 } 429 430 nxt_log_debug(c->socket.log, "CyaSSL_write(%d, %p, %uz): %d", 431 c->socket.fd, buf, size, ret); 432 433 if (ret > 0) { 434 return ret; 435 } 436 437 n = nxt_cyassl_conn_test_error(nxt_thread(), c, ret, 438 nxt_event_conn_io_write); 439 440 if (nxt_slow_path(n == NXT_ERROR)) { 441 nxt_cyassl_conn_error(c, err, "CyaSSL_write(%d, %p, %uz) failed", 442 c->socket.fd, buf, size); 443 } 444 445 return n; 446 } 447 448 449 static void 450 nxt_cyassl_conn_io_shutdown(nxt_thread_t *thr, void *obj, void *data) 451 { 452 int ret; 453 nxt_event_conn_t *c; 454 nxt_cyassl_conn_t *ssltls; 455 456 c = obj; 457 458 nxt_log_debug(thr->log, "cyassl conn shutdown"); 459 460 ssltls = c->u.ssltls; 461 462 ret = CyaSSL_shutdown(ssltls->session); 463 464 nxt_log_debug(thr->log, "CyaSSL_shutdown(%d): %d", c->socket.fd, ret); 465 466 if (nxt_slow_path(ret != SSL_SUCCESS)) { 467 nxt_cyassl_conn_error(c, 0, "CyaSSL_shutdown(%d) failed", c->socket.fd); 468 } 469 470 nxt_event_conn_io_handle(thr, c->write_work_queue, 471 c->write_state->close_handler, c, data); 472 } 473 474 475 static nxt_int_t 476 nxt_cyassl_conn_test_error(nxt_thread_t *thr, nxt_event_conn_t *c, int ret, 477 nxt_work_handler_t handler) 478 { 479 nxt_work_queue_t *wq; 480 nxt_cyassl_conn_t *ssltls; 481 482 ssltls = c->u.ssltls; 483 ssltls->ssl_error = CyaSSL_get_error(ssltls->session, ret); 484 485 nxt_log_debug(thr->log, "CyaSSL_get_error(): %d", ssltls->ssl_error); 486 487 switch (ssltls->ssl_error) { 488 489 case SSL_ERROR_WANT_READ: 490 nxt_event_fd_block_write(thr->engine, &c->socket); 491 492 c->socket.read_ready = 0; 493 c->socket.read_handler = handler; 494 495 if (nxt_event_fd_is_disabled(c->socket.read)) { 496 nxt_event_fd_enable_read(thr->engine, &c->socket); 497 } 498 499 return NXT_AGAIN; 500 501 case SSL_ERROR_WANT_WRITE: 502 nxt_event_fd_block_read(thr->engine, &c->socket); 503 504 c->socket.write_ready = 0; 505 c->socket.write_handler = handler; 506 507 if (nxt_event_fd_is_disabled(c->socket.write)) { 508 nxt_event_fd_enable_write(thr->engine, &c->socket); 509 } 510 511 return NXT_AGAIN; 512 513 case SSL_ERROR_ZERO_RETURN: 514 /* A "close notify" alert */ 515 516 if (c->read_state != NULL) { 517 wq = c->read_work_queue; 518 handler = c->read_state->close_handler; 519 520 } else { 521 wq = c->write_work_queue; 522 handler = c->write_state->close_handler; 523 } 524 525 nxt_event_conn_io_handle(thr, wq, handler, c, c->socket.data); 526 527 return 0; 528 529 default: 530 return NXT_ERROR; 531 } 532 } 533 534 535 static void nxt_cdecl 536 nxt_cyassl_conn_error(nxt_event_conn_t *c, nxt_err_t err, const char *fmt, ...) 537 { 538 u_char *p, *end; 539 va_list args; 540 nxt_uint_t level; 541 nxt_cyassl_conn_t *ssltls; 542 u_char msg[NXT_MAX_ERROR_STR]; 543 544 ssltls = c->u.ssltls; 545 546 level = nxt_cyassl_log_error_level(c, err, ssltls->ssl_error); 547 548 if (nxt_log_level_enough(c->socket.log, level)) { 549 550 end = msg + sizeof(msg); 551 552 va_start(args, fmt); 553 p = nxt_vsprintf(msg, end, fmt, args); 554 va_end(args); 555 556 if (err != 0) { 557 p = nxt_sprintf(p, end, " %E", err); 558 } 559 560 p = nxt_cyassl_copy_error(ssltls->ssl_error, p, end); 561 562 nxt_log_error(level, c->socket.log, "%*s", p - msg, msg); 563 } 564 } 565 566 567 static nxt_uint_t 568 nxt_cyassl_log_error_level(nxt_event_conn_t *c, nxt_err_t err, int ssl_error) 569 { 570 switch (ssl_error) { 571 572 case SOCKET_ERROR_E: /* -208 */ 573 case MATCH_SUITE_ERROR: /* -261 */ 574 break; 575 576 default: 577 return NXT_LOG_CRIT; 578 } 579 580 return NXT_LOG_INFO; 581 } 582 583 584 static void nxt_cdecl 585 nxt_cyassl_log_error(nxt_uint_t level, nxt_log_t *log, int err, 586 const char *fmt, ...) 587 { 588 u_char *p, *end; 589 va_list args; 590 u_char msg[NXT_MAX_ERROR_STR]; 591 592 if (nxt_log_level_enough(log, level)) { 593 594 end = msg + sizeof(msg); 595 596 va_start(args, fmt); 597 p = nxt_vsprintf(msg, end, fmt, args); 598 va_end(args); 599 600 p = nxt_cyassl_copy_error(err, p, end); 601 602 nxt_log_error(level, log, "%*s", p - msg, msg); 603 } 604 } 605 606 607 static u_char * 608 nxt_cyassl_copy_error(int err, u_char *p, u_char *end) 609 { 610 p = nxt_sprintf(p, end, " (SSL:%d ", err); 611 612 CyaSSL_ERR_error_string_n(err, (char *) p, end - p); 613 614 p += nxt_strlen(p); 615 616 if (p < end) { 617 *p++ = ')'; 618 } 619 620 return p; 621 } 622