Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 5661:060c2e692b96
Upstream: proxy_ssl_verify and friends.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 18 Apr 2014 20:13:30 +0400 |
parents | 94ae92776441 |
children | a77c0839c993 |
comparison
equal
deleted
inserted
replaced
5660:7022564a9e0e | 5661:060c2e692b96 |
---|---|
40 | 40 |
41 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB | 41 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB |
42 static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, | 42 static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, |
43 unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, | 43 unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, |
44 HMAC_CTX *hctx, int enc); | 44 HMAC_CTX *hctx, int enc); |
45 #endif | |
46 | |
47 #if OPENSSL_VERSION_NUMBER < 0x10002001L | |
48 static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str); | |
45 #endif | 49 #endif |
46 | 50 |
47 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); | 51 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); |
48 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 52 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
49 static void ngx_openssl_exit(ngx_cycle_t *cycle); | 53 static void ngx_openssl_exit(ngx_cycle_t *cycle); |
2485 SSL_CTX_free(ssl->ctx); | 2489 SSL_CTX_free(ssl->ctx); |
2486 } | 2490 } |
2487 | 2491 |
2488 | 2492 |
2489 ngx_int_t | 2493 ngx_int_t |
2494 ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name) | |
2495 { | |
2496 X509 *cert; | |
2497 | |
2498 cert = SSL_get_peer_certificate(c->ssl->connection); | |
2499 if (cert == NULL) { | |
2500 return NGX_ERROR; | |
2501 } | |
2502 | |
2503 #if OPENSSL_VERSION_NUMBER >= 0x10002001L | |
2504 | |
2505 /* X509_check_host() is only available in OpenSSL 1.0.2+ */ | |
2506 | |
2507 if (X509_check_host(cert, name->data, name->len, 0) != 1) { | |
2508 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2509 "X509_check_host(): no match"); | |
2510 goto failed; | |
2511 } | |
2512 | |
2513 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2514 "X509_check_host(): match"); | |
2515 | |
2516 goto found; | |
2517 | |
2518 #else | |
2519 { | |
2520 int n, i; | |
2521 X509_NAME *sname; | |
2522 ASN1_STRING *str; | |
2523 X509_NAME_ENTRY *entry; | |
2524 GENERAL_NAME *altname; | |
2525 STACK_OF(GENERAL_NAME) *altnames; | |
2526 | |
2527 /* | |
2528 * As per RFC6125 and RFC2818, we check subjectAltName extension, | |
2529 * and if it's not present - commonName in Subject is checked. | |
2530 */ | |
2531 | |
2532 altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); | |
2533 | |
2534 if (altnames) { | |
2535 n = sk_GENERAL_NAME_num(altnames); | |
2536 | |
2537 for (i = 0; i < n; i++) { | |
2538 altname = sk_GENERAL_NAME_value(altnames, i); | |
2539 | |
2540 if (altname->type != GEN_DNS) { | |
2541 continue; | |
2542 } | |
2543 | |
2544 str = altname->d.dNSName; | |
2545 | |
2546 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2547 "SSL subjectAltName: \"%*s\"", | |
2548 ASN1_STRING_length(str), ASN1_STRING_data(str)); | |
2549 | |
2550 if (ngx_ssl_check_name(name, str) == NGX_OK) { | |
2551 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2552 "SSL subjectAltName: match"); | |
2553 GENERAL_NAMES_free(altnames); | |
2554 goto found; | |
2555 } | |
2556 } | |
2557 | |
2558 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2559 "SSL subjectAltName: no match"); | |
2560 | |
2561 GENERAL_NAMES_free(altnames); | |
2562 goto failed; | |
2563 } | |
2564 | |
2565 /* | |
2566 * If there is no subjectAltName extension, check commonName | |
2567 * in Subject. While RFC2818 requires to only check "most specific" | |
2568 * CN, both Apache and OpenSSL check all CNs, and so do we. | |
2569 */ | |
2570 | |
2571 sname = X509_get_subject_name(cert); | |
2572 | |
2573 if (sname == NULL) { | |
2574 goto failed; | |
2575 } | |
2576 | |
2577 i = -1; | |
2578 for ( ;; ) { | |
2579 i = X509_NAME_get_index_by_NID(sname, NID_commonName, i); | |
2580 | |
2581 if (i < 0) { | |
2582 break; | |
2583 } | |
2584 | |
2585 entry = X509_NAME_get_entry(sname, i); | |
2586 str = X509_NAME_ENTRY_get_data(entry); | |
2587 | |
2588 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2589 "SSL commonName: \"%*s\"", | |
2590 ASN1_STRING_length(str), ASN1_STRING_data(str)); | |
2591 | |
2592 if (ngx_ssl_check_name(name, str) == NGX_OK) { | |
2593 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2594 "SSL commonName: match"); | |
2595 goto found; | |
2596 } | |
2597 } | |
2598 | |
2599 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
2600 "SSL commonName: no match"); | |
2601 } | |
2602 #endif | |
2603 | |
2604 failed: | |
2605 | |
2606 X509_free(cert); | |
2607 return NGX_ERROR; | |
2608 | |
2609 found: | |
2610 | |
2611 X509_free(cert); | |
2612 return NGX_OK; | |
2613 } | |
2614 | |
2615 | |
2616 #if OPENSSL_VERSION_NUMBER < 0x10002001L | |
2617 | |
2618 static ngx_int_t | |
2619 ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *pattern) | |
2620 { | |
2621 u_char *s, *p, *end; | |
2622 size_t slen, plen; | |
2623 | |
2624 s = name->data; | |
2625 slen = name->len; | |
2626 | |
2627 p = ASN1_STRING_data(pattern); | |
2628 plen = ASN1_STRING_length(pattern); | |
2629 | |
2630 if (slen == plen && ngx_strncasecmp(s, p, plen) == 0) { | |
2631 return NGX_OK; | |
2632 } | |
2633 | |
2634 if (plen > 2 && p[0] == '*' && p[1] == '.') { | |
2635 plen -= 1; | |
2636 p += 1; | |
2637 | |
2638 end = s + slen; | |
2639 s = ngx_strlchr(s, end, '.'); | |
2640 slen = end - s; | |
2641 | |
2642 if (plen == slen && ngx_strncasecmp(s, p, plen) == 0) { | |
2643 return NGX_OK; | |
2644 } | |
2645 } | |
2646 | |
2647 return NGX_ERROR; | |
2648 } | |
2649 | |
2650 #endif | |
2651 | |
2652 | |
2653 ngx_int_t | |
2490 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) | 2654 ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) |
2491 { | 2655 { |
2492 s->data = (u_char *) SSL_get_version(c->ssl->connection); | 2656 s->data = (u_char *) SSL_get_version(c->ssl->connection); |
2493 return NGX_OK; | 2657 return NGX_OK; |
2494 } | 2658 } |