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 }