Annotation of embedaddon/nginx/src/event/ngx_event_openssl.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_event.h>
                     11: 
                     12: 
                     13: typedef struct {
                     14:     ngx_uint_t  engine;   /* unsigned  engine:1; */
                     15: } ngx_openssl_conf_t;
                     16: 
                     17: 
                     18: static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
                     19: static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
                     20:     int ret);
                     21: static void ngx_ssl_handshake_handler(ngx_event_t *ev);
                     22: static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
                     23: static void ngx_ssl_write_handler(ngx_event_t *wev);
                     24: static void ngx_ssl_read_handler(ngx_event_t *rev);
                     25: static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
                     26: static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
                     27:     ngx_err_t err, char *text);
                     28: static void ngx_ssl_clear_error(ngx_log_t *log);
                     29: 
                     30: ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
                     31: static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
                     32:     ngx_ssl_session_t *sess);
                     33: static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
                     34:     u_char *id, int len, int *copy);
                     35: static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess);
                     36: static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
                     37:     ngx_slab_pool_t *shpool, ngx_uint_t n);
                     38: static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
                     39:     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
                     40: 
                     41: static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
                     42: static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
                     43: static void ngx_openssl_exit(ngx_cycle_t *cycle);
                     44: 
                     45: 
                     46: static ngx_command_t  ngx_openssl_commands[] = {
                     47: 
                     48:     { ngx_string("ssl_engine"),
                     49:       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
                     50:       ngx_openssl_engine,
                     51:       0,
                     52:       0,
                     53:       NULL },
                     54: 
                     55:       ngx_null_command
                     56: };
                     57: 
                     58: 
                     59: static ngx_core_module_t  ngx_openssl_module_ctx = {
                     60:     ngx_string("openssl"),
                     61:     ngx_openssl_create_conf,
                     62:     NULL
                     63: };
                     64: 
                     65: 
                     66: ngx_module_t  ngx_openssl_module = {
                     67:     NGX_MODULE_V1,
                     68:     &ngx_openssl_module_ctx,               /* module context */
                     69:     ngx_openssl_commands,                  /* module directives */
                     70:     NGX_CORE_MODULE,                       /* module type */
                     71:     NULL,                                  /* init master */
                     72:     NULL,                                  /* init module */
                     73:     NULL,                                  /* init process */
                     74:     NULL,                                  /* init thread */
                     75:     NULL,                                  /* exit thread */
                     76:     NULL,                                  /* exit process */
                     77:     ngx_openssl_exit,                      /* exit master */
                     78:     NGX_MODULE_V1_PADDING
                     79: };
                     80: 
                     81: 
                     82: int  ngx_ssl_connection_index;
                     83: int  ngx_ssl_server_conf_index;
                     84: int  ngx_ssl_session_cache_index;
                     85: int  ngx_ssl_certificate_index;
                     86: int  ngx_ssl_stapling_index;
                     87: 
                     88: 
                     89: ngx_int_t
                     90: ngx_ssl_init(ngx_log_t *log)
                     91: {
                     92:     OPENSSL_config(NULL);
                     93: 
                     94:     SSL_library_init();
                     95:     SSL_load_error_strings();
                     96: 
                     97:     OpenSSL_add_all_algorithms();
                     98: 
                     99: #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
                    100: #ifndef SSL_OP_NO_COMPRESSION
                    101:     {
                    102:     /*
                    103:      * Disable gzip compression in OpenSSL prior to 1.0.0 version,
                    104:      * this saves about 522K per connection.
                    105:      */
                    106:     int                  n;
                    107:     STACK_OF(SSL_COMP)  *ssl_comp_methods;
                    108: 
                    109:     ssl_comp_methods = SSL_COMP_get_compression_methods();
                    110:     n = sk_SSL_COMP_num(ssl_comp_methods);
                    111: 
                    112:     while (n--) {
                    113:         (void) sk_SSL_COMP_pop(ssl_comp_methods);
                    114:     }
                    115:     }
                    116: #endif
                    117: #endif
                    118: 
                    119:     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
                    120: 
                    121:     if (ngx_ssl_connection_index == -1) {
                    122:         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");
                    123:         return NGX_ERROR;
                    124:     }
                    125: 
                    126:     ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
                    127:                                                          NULL);
                    128:     if (ngx_ssl_server_conf_index == -1) {
                    129:         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
                    130:                       "SSL_CTX_get_ex_new_index() failed");
                    131:         return NGX_ERROR;
                    132:     }
                    133: 
                    134:     ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
                    135:                                                            NULL);
                    136:     if (ngx_ssl_session_cache_index == -1) {
                    137:         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
                    138:                       "SSL_CTX_get_ex_new_index() failed");
                    139:         return NGX_ERROR;
                    140:     }
                    141: 
                    142:     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
                    143:                                                          NULL);
                    144:     if (ngx_ssl_certificate_index == -1) {
                    145:         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
                    146:                       "SSL_CTX_get_ex_new_index() failed");
                    147:         return NGX_ERROR;
                    148:     }
                    149: 
                    150:     ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
                    151:                                                       NULL);
                    152:     if (ngx_ssl_stapling_index == -1) {
                    153:         ngx_ssl_error(NGX_LOG_ALERT, log, 0,
                    154:                       "SSL_CTX_get_ex_new_index() failed");
                    155:         return NGX_ERROR;
                    156:     }
                    157: 
                    158:     return NGX_OK;
                    159: }
                    160: 
                    161: 
                    162: ngx_int_t
                    163: ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
                    164: {
                    165:     ssl->ctx = SSL_CTX_new(SSLv23_method());
                    166: 
                    167:     if (ssl->ctx == NULL) {
                    168:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_new() failed");
                    169:         return NGX_ERROR;
                    170:     }
                    171: 
                    172:     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
                    173:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    174:                       "SSL_CTX_set_ex_data() failed");
                    175:         return NGX_ERROR;
                    176:     }
                    177: 
                    178:     /* client side options */
                    179: 
                    180:     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
                    181:     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
                    182: 
                    183:     /* server side options */
                    184: 
                    185:     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
                    186:     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
                    187: 
                    188:     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
                    189:     SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
                    190: 
                    191:     SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
                    192:     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
                    193:     SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
                    194: 
                    195:     SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
                    196: 
                    197:     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
                    198: 
                    199:     if (!(protocols & NGX_SSL_SSLv2)) {
                    200:         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
                    201:     }
                    202:     if (!(protocols & NGX_SSL_SSLv3)) {
                    203:         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
                    204:     }
                    205:     if (!(protocols & NGX_SSL_TLSv1)) {
                    206:         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
                    207:     }
                    208: #ifdef SSL_OP_NO_TLSv1_1
                    209:     if (!(protocols & NGX_SSL_TLSv1_1)) {
                    210:         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_1);
                    211:     }
                    212: #endif
                    213: #ifdef SSL_OP_NO_TLSv1_2
                    214:     if (!(protocols & NGX_SSL_TLSv1_2)) {
                    215:         SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2);
                    216:     }
                    217: #endif
                    218: 
                    219: #ifdef SSL_OP_NO_COMPRESSION
                    220:     SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
                    221: #endif
                    222: 
                    223: #ifdef SSL_MODE_RELEASE_BUFFERS
                    224:     SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
                    225: #endif
                    226: 
                    227:     SSL_CTX_set_read_ahead(ssl->ctx, 1);
                    228: 
                    229:     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
                    230: 
                    231:     return NGX_OK;
                    232: }
                    233: 
                    234: 
                    235: ngx_int_t
                    236: ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
                    237:     ngx_str_t *key)
                    238: {
                    239:     BIO     *bio;
                    240:     X509    *x509;
                    241:     u_long   n;
                    242: 
                    243:     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
                    244:         return NGX_ERROR;
                    245:     }
                    246: 
                    247:     /*
                    248:      * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
                    249:      * allow to access certificate later from SSL_CTX, so we reimplement
                    250:      * it here
                    251:      */
                    252: 
                    253:     bio = BIO_new_file((char *) cert->data, "r");
                    254:     if (bio == NULL) {
                    255:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    256:                       "BIO_new_file(\"%s\") failed", cert->data);
                    257:         return NGX_ERROR;
                    258:     }
                    259: 
                    260:     x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
                    261:     if (x509 == NULL) {
                    262:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    263:                       "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
                    264:         BIO_free(bio);
                    265:         return NGX_ERROR;
                    266:     }
                    267: 
                    268:     if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
                    269:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    270:                       "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
                    271:         X509_free(x509);
                    272:         BIO_free(bio);
                    273:         return NGX_ERROR;
                    274:     }
                    275: 
                    276:     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
                    277:         == 0)
                    278:     {
                    279:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    280:                       "SSL_CTX_set_ex_data() failed");
                    281:         return NGX_ERROR;
                    282:     }
                    283: 
                    284:     X509_free(x509);
                    285: 
                    286:     /* read rest of the chain */
                    287: 
                    288:     for ( ;; ) {
                    289: 
                    290:         x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
                    291:         if (x509 == NULL) {
                    292:             n = ERR_peek_last_error();
                    293: 
                    294:             if (ERR_GET_LIB(n) == ERR_LIB_PEM
                    295:                 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
                    296:             {
                    297:                 /* end of file */
                    298:                 ERR_clear_error();
                    299:                 break;
                    300:             }
                    301: 
                    302:             /* some real error */
                    303: 
                    304:             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    305:                           "PEM_read_bio_X509(\"%s\") failed", cert->data);
                    306:             BIO_free(bio);
                    307:             return NGX_ERROR;
                    308:         }
                    309: 
                    310:         if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
                    311:             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    312:                           "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
                    313:                           cert->data);
                    314:             X509_free(x509);
                    315:             BIO_free(bio);
                    316:             return NGX_ERROR;
                    317:         }
                    318:     }
                    319: 
                    320:     BIO_free(bio);
                    321: 
                    322:     if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
                    323:         return NGX_ERROR;
                    324:     }
                    325: 
                    326:     if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
                    327:                                     SSL_FILETYPE_PEM)
                    328:         == 0)
                    329:     {
                    330:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    331:                       "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
                    332:         return NGX_ERROR;
                    333:     }
                    334: 
                    335:     return NGX_OK;
                    336: }
                    337: 
                    338: 
                    339: ngx_int_t
                    340: ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
                    341:     ngx_int_t depth)
                    342: {
                    343:     STACK_OF(X509_NAME)  *list;
                    344: 
                    345:     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
                    346: 
                    347:     SSL_CTX_set_verify_depth(ssl->ctx, depth);
                    348: 
                    349:     if (cert->len == 0) {
                    350:         return NGX_OK;
                    351:     }
                    352: 
                    353:     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
                    354:         return NGX_ERROR;
                    355:     }
                    356: 
                    357:     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
                    358:         == 0)
                    359:     {
                    360:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    361:                       "SSL_CTX_load_verify_locations(\"%s\") failed",
                    362:                       cert->data);
                    363:         return NGX_ERROR;
                    364:     }
                    365: 
                    366:     list = SSL_load_client_CA_file((char *) cert->data);
                    367: 
                    368:     if (list == NULL) {
                    369:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    370:                       "SSL_load_client_CA_file(\"%s\") failed", cert->data);
                    371:         return NGX_ERROR;
                    372:     }
                    373: 
                    374:     /*
                    375:      * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
                    376:      * always leaved an error in the error queue
                    377:      */
                    378: 
                    379:     ERR_clear_error();
                    380: 
                    381:     SSL_CTX_set_client_CA_list(ssl->ctx, list);
                    382: 
                    383:     return NGX_OK;
                    384: }
                    385: 
                    386: 
                    387: ngx_int_t
                    388: ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
                    389:     ngx_int_t depth)
                    390: {
                    391:     SSL_CTX_set_verify_depth(ssl->ctx, depth);
                    392: 
                    393:     if (cert->len == 0) {
                    394:         return NGX_OK;
                    395:     }
                    396: 
                    397:     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
                    398:         return NGX_ERROR;
                    399:     }
                    400: 
                    401:     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
                    402:         == 0)
                    403:     {
                    404:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    405:                       "SSL_CTX_load_verify_locations(\"%s\") failed",
                    406:                       cert->data);
                    407:         return NGX_ERROR;
                    408:     }
                    409: 
                    410:     return NGX_OK;
                    411: }
                    412: 
                    413: 
                    414: ngx_int_t
                    415: ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl)
                    416: {
                    417:     X509_STORE   *store;
                    418:     X509_LOOKUP  *lookup;
                    419: 
                    420:     if (crl->len == 0) {
                    421:         return NGX_OK;
                    422:     }
                    423: 
                    424:     if (ngx_conf_full_name(cf->cycle, crl, 1) != NGX_OK) {
                    425:         return NGX_ERROR;
                    426:     }
                    427: 
                    428:     store = SSL_CTX_get_cert_store(ssl->ctx);
                    429: 
                    430:     if (store == NULL) {
                    431:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    432:                       "SSL_CTX_get_cert_store() failed");
                    433:         return NGX_ERROR;
                    434:     }
                    435: 
                    436:     lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
                    437: 
                    438:     if (lookup == NULL) {
                    439:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    440:                       "X509_STORE_add_lookup() failed");
                    441:         return NGX_ERROR;
                    442:     }
                    443: 
                    444:     if (X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM)
                    445:         == 0)
                    446:     {
                    447:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    448:                       "X509_LOOKUP_load_file(\"%s\") failed", crl->data);
                    449:         return NGX_ERROR;
                    450:     }
                    451: 
                    452:     X509_STORE_set_flags(store,
                    453:                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
                    454: 
                    455:     return NGX_OK;
                    456: }
                    457: 
                    458: 
                    459: static int
                    460: ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
                    461: {
                    462: #if (NGX_DEBUG)
                    463:     char              *subject, *issuer;
                    464:     int                err, depth;
                    465:     X509              *cert;
                    466:     X509_NAME         *sname, *iname;
                    467:     ngx_connection_t  *c;
                    468:     ngx_ssl_conn_t    *ssl_conn;
                    469: 
                    470:     ssl_conn = X509_STORE_CTX_get_ex_data(x509_store,
                    471:                                           SSL_get_ex_data_X509_STORE_CTX_idx());
                    472: 
                    473:     c = ngx_ssl_get_connection(ssl_conn);
                    474: 
                    475:     cert = X509_STORE_CTX_get_current_cert(x509_store);
                    476:     err = X509_STORE_CTX_get_error(x509_store);
                    477:     depth = X509_STORE_CTX_get_error_depth(x509_store);
                    478: 
                    479:     sname = X509_get_subject_name(cert);
                    480:     subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)";
                    481: 
                    482:     iname = X509_get_issuer_name(cert);
                    483:     issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)";
                    484: 
                    485:     ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    486:                    "verify:%d, error:%d, depth:%d, "
                    487:                    "subject:\"%s\",issuer: \"%s\"",
                    488:                    ok, err, depth, subject, issuer);
                    489: 
                    490:     if (sname) {
                    491:         OPENSSL_free(subject);
                    492:     }
                    493: 
                    494:     if (iname) {
                    495:         OPENSSL_free(issuer);
                    496:     }
                    497: #endif
                    498: 
                    499:     return 1;
                    500: }
                    501: 
                    502: 
                    503: static void
                    504: ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
                    505: {
                    506:     ngx_connection_t  *c;
                    507: 
                    508:     if (where & SSL_CB_HANDSHAKE_START) {
                    509:         c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
                    510: 
                    511:         if (c->ssl->handshaked) {
                    512:             c->ssl->renegotiation = 1;
                    513:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
                    514:         }
                    515:     }
                    516: }
                    517: 
                    518: 
                    519: RSA *
                    520: ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length)
                    521: {
                    522:     static RSA  *key;
                    523: 
                    524:     if (key_length == 512) {
                    525:         if (key == NULL) {
                    526:             key = RSA_generate_key(512, RSA_F4, NULL, NULL);
                    527:         }
                    528:     }
                    529: 
                    530:     return key;
                    531: }
                    532: 
                    533: 
                    534: ngx_int_t
                    535: ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
                    536: {
                    537:     DH   *dh;
                    538:     BIO  *bio;
                    539: 
                    540:     /*
                    541:      * -----BEGIN DH PARAMETERS-----
                    542:      * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
                    543:      * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
                    544:      * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
                    545:      * -----END DH PARAMETERS-----
                    546:      */
                    547: 
                    548:     static unsigned char dh1024_p[] = {
                    549:         0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5,
                    550:         0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B,
                    551:         0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76,
                    552:         0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5,
                    553:         0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04,
                    554:         0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
                    555:         0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF,
                    556:         0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50,
                    557:         0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E,
                    558:         0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA,
                    559:         0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B
                    560:     };
                    561: 
                    562:     static unsigned char dh1024_g[] = { 0x02 };
                    563: 
                    564: 
                    565:     if (file->len == 0) {
                    566: 
                    567:         dh = DH_new();
                    568:         if (dh == NULL) {
                    569:             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed");
                    570:             return NGX_ERROR;
                    571:         }
                    572: 
                    573:         dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
                    574:         dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
                    575: 
                    576:         if (dh->p == NULL || dh->g == NULL) {
                    577:             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed");
                    578:             DH_free(dh);
                    579:             return NGX_ERROR;
                    580:         }
                    581: 
                    582:         SSL_CTX_set_tmp_dh(ssl->ctx, dh);
                    583: 
                    584:         DH_free(dh);
                    585: 
                    586:         return NGX_OK;
                    587:     }
                    588: 
                    589:     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
                    590:         return NGX_ERROR;
                    591:     }
                    592: 
                    593:     bio = BIO_new_file((char *) file->data, "r");
                    594:     if (bio == NULL) {
                    595:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    596:                       "BIO_new_file(\"%s\") failed", file->data);
                    597:         return NGX_ERROR;
                    598:     }
                    599: 
                    600:     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
                    601:     if (dh == NULL) {
                    602:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    603:                       "PEM_read_bio_DHparams(\"%s\") failed", file->data);
                    604:         BIO_free(bio);
                    605:         return NGX_ERROR;
                    606:     }
                    607: 
                    608:     SSL_CTX_set_tmp_dh(ssl->ctx, dh);
                    609: 
                    610:     DH_free(dh);
                    611:     BIO_free(bio);
                    612: 
                    613:     return NGX_OK;
                    614: }
                    615: 
                    616: 
                    617: ngx_int_t
                    618: ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
                    619: {
                    620: #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
                    621: #ifndef OPENSSL_NO_ECDH
                    622:     int      nid;
                    623:     EC_KEY  *ecdh;
                    624: 
                    625:     /*
                    626:      * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
                    627:      * from RFC 4492 section 5.1.1, or explicitly described curves over
                    628:      * binary fields. OpenSSL only supports the "named curves", which provide
                    629:      * maximum interoperability.
                    630:      */
                    631: 
                    632:     nid = OBJ_sn2nid((const char *) name->data);
                    633:     if (nid == 0) {
                    634:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    635:                       "Unknown curve name \"%s\"", name->data);
                    636:         return NGX_ERROR;
                    637:     }
                    638: 
                    639:     ecdh = EC_KEY_new_by_curve_name(nid);
                    640:     if (ecdh == NULL) {
                    641:         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                    642:                       "Unable to create curve \"%s\"", name->data);
                    643:         return NGX_ERROR;
                    644:     }
                    645: 
                    646:     SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
                    647: 
                    648:     SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
                    649: 
                    650:     EC_KEY_free(ecdh);
                    651: #endif
                    652: #endif
                    653: 
                    654:     return NGX_OK;
                    655: }
                    656: 
                    657: 
                    658: ngx_int_t
                    659: ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
                    660: {
                    661:     ngx_ssl_connection_t  *sc;
                    662: 
                    663:     sc = ngx_pcalloc(c->pool, sizeof(ngx_ssl_connection_t));
                    664:     if (sc == NULL) {
                    665:         return NGX_ERROR;
                    666:     }
                    667: 
                    668:     sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
                    669: 
                    670:     sc->connection = SSL_new(ssl->ctx);
                    671: 
                    672:     if (sc->connection == NULL) {
                    673:         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
                    674:         return NGX_ERROR;
                    675:     }
                    676: 
                    677:     if (SSL_set_fd(sc->connection, c->fd) == 0) {
                    678:         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
                    679:         return NGX_ERROR;
                    680:     }
                    681: 
                    682:     if (flags & NGX_SSL_CLIENT) {
                    683:         SSL_set_connect_state(sc->connection);
                    684: 
                    685:     } else {
                    686:         SSL_set_accept_state(sc->connection);
                    687:     }
                    688: 
                    689:     if (SSL_set_ex_data(sc->connection, ngx_ssl_connection_index, c) == 0) {
                    690:         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
                    691:         return NGX_ERROR;
                    692:     }
                    693: 
                    694:     c->ssl = sc;
                    695: 
                    696:     return NGX_OK;
                    697: }
                    698: 
                    699: 
                    700: ngx_int_t
                    701: ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session)
                    702: {
                    703:     if (session) {
                    704:         if (SSL_set_session(c->ssl->connection, session) == 0) {
                    705:             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_session() failed");
                    706:             return NGX_ERROR;
                    707:         }
                    708:     }
                    709: 
                    710:     return NGX_OK;
                    711: }
                    712: 
                    713: 
                    714: ngx_int_t
                    715: ngx_ssl_handshake(ngx_connection_t *c)
                    716: {
                    717:     int        n, sslerr;
                    718:     ngx_err_t  err;
                    719: 
                    720:     ngx_ssl_clear_error(c->log);
                    721: 
                    722:     n = SSL_do_handshake(c->ssl->connection);
                    723: 
                    724:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
                    725: 
                    726:     if (n == 1) {
                    727: 
                    728:         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
                    729:             return NGX_ERROR;
                    730:         }
                    731: 
                    732:         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                    733:             return NGX_ERROR;
                    734:         }
                    735: 
                    736: #if (NGX_DEBUG)
                    737:         {
                    738:         char         buf[129], *s, *d;
                    739: #if OPENSSL_VERSION_NUMBER >= 0x10000000L
                    740:         const
                    741: #endif
                    742:         SSL_CIPHER  *cipher;
                    743: 
                    744:         cipher = SSL_get_current_cipher(c->ssl->connection);
                    745: 
                    746:         if (cipher) {
                    747:             SSL_CIPHER_description(cipher, &buf[1], 128);
                    748: 
                    749:             for (s = &buf[1], d = buf; *s; s++) {
                    750:                 if (*s == ' ' && *d == ' ') {
                    751:                     continue;
                    752:                 }
                    753: 
                    754:                 if (*s == LF || *s == CR) {
                    755:                     continue;
                    756:                 }
                    757: 
                    758:                 *++d = *s;
                    759:             }
                    760: 
                    761:             if (*d != ' ') {
                    762:                 d++;
                    763:             }
                    764: 
                    765:             *d = '\0';
                    766: 
                    767:             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    768:                            "SSL: %s, cipher: \"%s\"",
                    769:                            SSL_get_version(c->ssl->connection), &buf[1]);
                    770: 
                    771:             if (SSL_session_reused(c->ssl->connection)) {
                    772:                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    773:                                "SSL reused session");
                    774:             }
                    775: 
                    776:         } else {
                    777:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    778:                            "SSL no shared ciphers");
                    779:         }
                    780:         }
                    781: #endif
                    782: 
                    783:         c->ssl->handshaked = 1;
                    784: 
                    785:         c->recv = ngx_ssl_recv;
                    786:         c->send = ngx_ssl_write;
                    787:         c->recv_chain = ngx_ssl_recv_chain;
                    788:         c->send_chain = ngx_ssl_send_chain;
                    789: 
                    790:         /* initial handshake done, disable renegotiation (CVE-2009-3555) */
                    791:         if (c->ssl->connection->s3) {
                    792:             c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
                    793:         }
                    794: 
                    795:         return NGX_OK;
                    796:     }
                    797: 
                    798:     sslerr = SSL_get_error(c->ssl->connection, n);
                    799: 
                    800:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
                    801: 
                    802:     if (sslerr == SSL_ERROR_WANT_READ) {
                    803:         c->read->ready = 0;
                    804:         c->read->handler = ngx_ssl_handshake_handler;
                    805:         c->write->handler = ngx_ssl_handshake_handler;
                    806: 
                    807:         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
                    808:             return NGX_ERROR;
                    809:         }
                    810: 
                    811:         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                    812:             return NGX_ERROR;
                    813:         }
                    814: 
                    815:         return NGX_AGAIN;
                    816:     }
                    817: 
                    818:     if (sslerr == SSL_ERROR_WANT_WRITE) {
                    819:         c->write->ready = 0;
                    820:         c->read->handler = ngx_ssl_handshake_handler;
                    821:         c->write->handler = ngx_ssl_handshake_handler;
                    822: 
                    823:         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
                    824:             return NGX_ERROR;
                    825:         }
                    826: 
                    827:         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                    828:             return NGX_ERROR;
                    829:         }
                    830: 
                    831:         return NGX_AGAIN;
                    832:     }
                    833: 
                    834:     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
                    835: 
                    836:     c->ssl->no_wait_shutdown = 1;
                    837:     c->ssl->no_send_shutdown = 1;
                    838:     c->read->eof = 1;
                    839: 
                    840:     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
                    841:         ngx_log_error(NGX_LOG_INFO, c->log, err,
                    842:                       "peer closed connection in SSL handshake");
                    843: 
                    844:         return NGX_ERROR;
                    845:     }
                    846: 
                    847:     c->read->error = 1;
                    848: 
                    849:     ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
                    850: 
                    851:     return NGX_ERROR;
                    852: }
                    853: 
                    854: 
                    855: static void
                    856: ngx_ssl_handshake_handler(ngx_event_t *ev)
                    857: {
                    858:     ngx_connection_t  *c;
                    859: 
                    860:     c = ev->data;
                    861: 
                    862:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    863:                    "SSL handshake handler: %d", ev->write);
                    864: 
                    865:     if (ev->timedout) {
                    866:         c->ssl->handler(c);
                    867:         return;
                    868:     }
                    869: 
                    870:     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
                    871:         return;
                    872:     }
                    873: 
                    874:     c->ssl->handler(c);
                    875: }
                    876: 
                    877: 
                    878: ssize_t
                    879: ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl)
                    880: {
                    881:     u_char     *last;
                    882:     ssize_t     n, bytes;
                    883:     ngx_buf_t  *b;
                    884: 
                    885:     bytes = 0;
                    886: 
                    887:     b = cl->buf;
                    888:     last = b->last;
                    889: 
                    890:     for ( ;; ) {
                    891: 
                    892:         n = ngx_ssl_recv(c, last, b->end - last);
                    893: 
                    894:         if (n > 0) {
                    895:             last += n;
                    896:             bytes += n;
                    897: 
                    898:             if (last == b->end) {
                    899:                 cl = cl->next;
                    900: 
                    901:                 if (cl == NULL) {
                    902:                     return bytes;
                    903:                 }
                    904: 
                    905:                 b = cl->buf;
                    906:                 last = b->last;
                    907:             }
                    908: 
                    909:             continue;
                    910:         }
                    911: 
                    912:         if (bytes) {
                    913: 
                    914:             if (n == 0 || n == NGX_ERROR) {
                    915:                 c->read->ready = 1;
                    916:             }
                    917: 
                    918:             return bytes;
                    919:         }
                    920: 
                    921:         return n;
                    922:     }
                    923: }
                    924: 
                    925: 
                    926: ssize_t
                    927: ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
                    928: {
                    929:     int  n, bytes;
                    930: 
                    931:     if (c->ssl->last == NGX_ERROR) {
                    932:         c->read->error = 1;
                    933:         return NGX_ERROR;
                    934:     }
                    935: 
                    936:     if (c->ssl->last == NGX_DONE) {
                    937:         c->read->ready = 0;
                    938:         c->read->eof = 1;
                    939:         return 0;
                    940:     }
                    941: 
                    942:     bytes = 0;
                    943: 
                    944:     ngx_ssl_clear_error(c->log);
                    945: 
                    946:     /*
                    947:      * SSL_read() may return data in parts, so try to read
                    948:      * until SSL_read() would return no data
                    949:      */
                    950: 
                    951:     for ( ;; ) {
                    952: 
                    953:         n = SSL_read(c->ssl->connection, buf, size);
                    954: 
                    955:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n);
                    956: 
                    957:         if (n > 0) {
                    958:             bytes += n;
                    959:         }
                    960: 
                    961:         c->ssl->last = ngx_ssl_handle_recv(c, n);
                    962: 
                    963:         if (c->ssl->last == NGX_OK) {
                    964: 
                    965:             size -= n;
                    966: 
                    967:             if (size == 0) {
                    968:                 return bytes;
                    969:             }
                    970: 
                    971:             buf += n;
                    972: 
                    973:             continue;
                    974:         }
                    975: 
                    976:         if (bytes) {
                    977:             return bytes;
                    978:         }
                    979: 
                    980:         switch (c->ssl->last) {
                    981: 
                    982:         case NGX_DONE:
                    983:             c->read->ready = 0;
                    984:             c->read->eof = 1;
                    985:             return 0;
                    986: 
                    987:         case NGX_ERROR:
                    988:             c->read->error = 1;
                    989: 
                    990:             /* fall through */
                    991: 
                    992:         case NGX_AGAIN:
                    993:             return c->ssl->last;
                    994:         }
                    995:     }
                    996: }
                    997: 
                    998: 
                    999: static ngx_int_t
                   1000: ngx_ssl_handle_recv(ngx_connection_t *c, int n)
                   1001: {
                   1002:     int        sslerr;
                   1003:     ngx_err_t  err;
                   1004: 
                   1005:     if (c->ssl->renegotiation) {
                   1006:         /*
                   1007:          * disable renegotiation (CVE-2009-3555):
                   1008:          * OpenSSL (at least up to 0.9.8l) does not handle disabled
                   1009:          * renegotiation gracefully, so drop connection here
                   1010:          */
                   1011: 
                   1012:         ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
                   1013: 
                   1014:         while (ERR_peek_error()) {
                   1015:             ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
                   1016:                           "ignoring stale global SSL error");
                   1017:         }
                   1018: 
                   1019:         ERR_clear_error();
                   1020: 
                   1021:         c->ssl->no_wait_shutdown = 1;
                   1022:         c->ssl->no_send_shutdown = 1;
                   1023: 
                   1024:         return NGX_ERROR;
                   1025:     }
                   1026: 
                   1027:     if (n > 0) {
                   1028: 
                   1029:         if (c->ssl->saved_write_handler) {
                   1030: 
                   1031:             c->write->handler = c->ssl->saved_write_handler;
                   1032:             c->ssl->saved_write_handler = NULL;
                   1033:             c->write->ready = 1;
                   1034: 
                   1035:             if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                   1036:                 return NGX_ERROR;
                   1037:             }
                   1038: 
                   1039:             ngx_post_event(c->write, &ngx_posted_events);
                   1040:         }
                   1041: 
                   1042:         return NGX_OK;
                   1043:     }
                   1044: 
                   1045:     sslerr = SSL_get_error(c->ssl->connection, n);
                   1046: 
                   1047:     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
                   1048: 
                   1049:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
                   1050: 
                   1051:     if (sslerr == SSL_ERROR_WANT_READ) {
                   1052:         c->read->ready = 0;
                   1053:         return NGX_AGAIN;
                   1054:     }
                   1055: 
                   1056:     if (sslerr == SSL_ERROR_WANT_WRITE) {
                   1057: 
                   1058:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1059:                       "peer started SSL renegotiation");
                   1060: 
                   1061:         c->write->ready = 0;
                   1062: 
                   1063:         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                   1064:             return NGX_ERROR;
                   1065:         }
                   1066: 
                   1067:         /*
                   1068:          * we do not set the timer because there is already the read event timer
                   1069:          */
                   1070: 
                   1071:         if (c->ssl->saved_write_handler == NULL) {
                   1072:             c->ssl->saved_write_handler = c->write->handler;
                   1073:             c->write->handler = ngx_ssl_write_handler;
                   1074:         }
                   1075: 
                   1076:         return NGX_AGAIN;
                   1077:     }
                   1078: 
                   1079:     c->ssl->no_wait_shutdown = 1;
                   1080:     c->ssl->no_send_shutdown = 1;
                   1081: 
                   1082:     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
                   1083:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   1084:                        "peer shutdown SSL cleanly");
                   1085:         return NGX_DONE;
                   1086:     }
                   1087: 
                   1088:     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
                   1089: 
                   1090:     return NGX_ERROR;
                   1091: }
                   1092: 
                   1093: 
                   1094: static void
                   1095: ngx_ssl_write_handler(ngx_event_t *wev)
                   1096: {
                   1097:     ngx_connection_t  *c;
                   1098: 
                   1099:     c = wev->data;
                   1100: 
                   1101:     c->read->handler(c->read);
                   1102: }
                   1103: 
                   1104: 
                   1105: /*
                   1106:  * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer
                   1107:  * before the SSL_write() call to decrease a SSL overhead.
                   1108:  *
                   1109:  * Besides for protocols such as HTTP it is possible to always buffer
                   1110:  * the output to decrease a SSL overhead some more.
                   1111:  */
                   1112: 
                   1113: ngx_chain_t *
                   1114: ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
                   1115: {
                   1116:     int          n;
                   1117:     ngx_uint_t   flush;
                   1118:     ssize_t      send, size;
                   1119:     ngx_buf_t   *buf;
                   1120: 
                   1121:     if (!c->ssl->buffer) {
                   1122: 
                   1123:         while (in) {
                   1124:             if (ngx_buf_special(in->buf)) {
                   1125:                 in = in->next;
                   1126:                 continue;
                   1127:             }
                   1128: 
                   1129:             n = ngx_ssl_write(c, in->buf->pos, in->buf->last - in->buf->pos);
                   1130: 
                   1131:             if (n == NGX_ERROR) {
                   1132:                 return NGX_CHAIN_ERROR;
                   1133:             }
                   1134: 
                   1135:             if (n == NGX_AGAIN) {
                   1136:                 return in;
                   1137:             }
                   1138: 
                   1139:             in->buf->pos += n;
                   1140:             c->sent += n;
                   1141: 
                   1142:             if (in->buf->pos == in->buf->last) {
                   1143:                 in = in->next;
                   1144:             }
                   1145:         }
                   1146: 
                   1147:         return in;
                   1148:     }
                   1149: 
                   1150: 
                   1151:     /* the maximum limit size is the maximum int32_t value - the page size */
                   1152: 
                   1153:     if (limit == 0 || limit > (off_t) (NGX_MAX_INT32_VALUE - ngx_pagesize)) {
                   1154:         limit = NGX_MAX_INT32_VALUE - ngx_pagesize;
                   1155:     }
                   1156: 
                   1157:     buf = c->ssl->buf;
                   1158: 
                   1159:     if (buf == NULL) {
                   1160:         buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
                   1161:         if (buf == NULL) {
                   1162:             return NGX_CHAIN_ERROR;
                   1163:         }
                   1164: 
                   1165:         c->ssl->buf = buf;
                   1166:     }
                   1167: 
                   1168:     if (buf->start == NULL) {
                   1169:         buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
                   1170:         if (buf->start == NULL) {
                   1171:             return NGX_CHAIN_ERROR;
                   1172:         }
                   1173: 
                   1174:         buf->pos = buf->start;
                   1175:         buf->last = buf->start;
                   1176:         buf->end = buf->start + NGX_SSL_BUFSIZE;
                   1177:     }
                   1178: 
                   1179:     send = buf->last - buf->pos;
                   1180:     flush = (in == NULL) ? 1 : buf->flush;
                   1181: 
                   1182:     for ( ;; ) {
                   1183: 
                   1184:         while (in && buf->last < buf->end && send < limit) {
                   1185:             if (in->buf->last_buf || in->buf->flush) {
                   1186:                 flush = 1;
                   1187:             }
                   1188: 
                   1189:             if (ngx_buf_special(in->buf)) {
                   1190:                 in = in->next;
                   1191:                 continue;
                   1192:             }
                   1193: 
                   1194:             size = in->buf->last - in->buf->pos;
                   1195: 
                   1196:             if (size > buf->end - buf->last) {
                   1197:                 size = buf->end - buf->last;
                   1198:             }
                   1199: 
                   1200:             if (send + size > limit) {
                   1201:                 size = (ssize_t) (limit - send);
                   1202:             }
                   1203: 
                   1204:             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   1205:                            "SSL buf copy: %d", size);
                   1206: 
                   1207:             ngx_memcpy(buf->last, in->buf->pos, size);
                   1208: 
                   1209:             buf->last += size;
                   1210:             in->buf->pos += size;
                   1211:             send += size;
                   1212: 
                   1213:             if (in->buf->pos == in->buf->last) {
                   1214:                 in = in->next;
                   1215:             }
                   1216:         }
                   1217: 
                   1218:         if (!flush && send < limit && buf->last < buf->end) {
                   1219:             break;
                   1220:         }
                   1221: 
                   1222:         size = buf->last - buf->pos;
                   1223: 
                   1224:         if (size == 0) {
                   1225:             buf->flush = 0;
                   1226:             c->buffered &= ~NGX_SSL_BUFFERED;
                   1227:             return in;
                   1228:         }
                   1229: 
                   1230:         n = ngx_ssl_write(c, buf->pos, size);
                   1231: 
                   1232:         if (n == NGX_ERROR) {
                   1233:             return NGX_CHAIN_ERROR;
                   1234:         }
                   1235: 
                   1236:         if (n == NGX_AGAIN) {
                   1237:             break;
                   1238:         }
                   1239: 
                   1240:         buf->pos += n;
                   1241:         c->sent += n;
                   1242: 
                   1243:         if (n < size) {
                   1244:             break;
                   1245:         }
                   1246: 
                   1247:         flush = 0;
                   1248: 
                   1249:         buf->pos = buf->start;
                   1250:         buf->last = buf->start;
                   1251: 
                   1252:         if (in == NULL || send == limit) {
                   1253:             break;
                   1254:         }
                   1255:     }
                   1256: 
                   1257:     buf->flush = flush;
                   1258: 
                   1259:     if (buf->pos < buf->last) {
                   1260:         c->buffered |= NGX_SSL_BUFFERED;
                   1261: 
                   1262:     } else {
                   1263:         c->buffered &= ~NGX_SSL_BUFFERED;
                   1264:     }
                   1265: 
                   1266:     return in;
                   1267: }
                   1268: 
                   1269: 
                   1270: ssize_t
                   1271: ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
                   1272: {
                   1273:     int        n, sslerr;
                   1274:     ngx_err_t  err;
                   1275: 
                   1276:     ngx_ssl_clear_error(c->log);
                   1277: 
                   1278:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size);
                   1279: 
                   1280:     n = SSL_write(c->ssl->connection, data, size);
                   1281: 
                   1282:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n);
                   1283: 
                   1284:     if (n > 0) {
                   1285: 
                   1286:         if (c->ssl->saved_read_handler) {
                   1287: 
                   1288:             c->read->handler = c->ssl->saved_read_handler;
                   1289:             c->ssl->saved_read_handler = NULL;
                   1290:             c->read->ready = 1;
                   1291: 
                   1292:             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
                   1293:                 return NGX_ERROR;
                   1294:             }
                   1295: 
                   1296:             ngx_post_event(c->read, &ngx_posted_events);
                   1297:         }
                   1298: 
                   1299:         return n;
                   1300:     }
                   1301: 
                   1302:     sslerr = SSL_get_error(c->ssl->connection, n);
                   1303: 
                   1304:     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
                   1305: 
                   1306:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
                   1307: 
                   1308:     if (sslerr == SSL_ERROR_WANT_WRITE) {
                   1309:         c->write->ready = 0;
                   1310:         return NGX_AGAIN;
                   1311:     }
                   1312: 
                   1313:     if (sslerr == SSL_ERROR_WANT_READ) {
                   1314: 
                   1315:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                   1316:                       "peer started SSL renegotiation");
                   1317: 
                   1318:         c->read->ready = 0;
                   1319: 
                   1320:         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
                   1321:             return NGX_ERROR;
                   1322:         }
                   1323: 
                   1324:         /*
                   1325:          * we do not set the timer because there is already
                   1326:          * the write event timer
                   1327:          */
                   1328: 
                   1329:         if (c->ssl->saved_read_handler == NULL) {
                   1330:             c->ssl->saved_read_handler = c->read->handler;
                   1331:             c->read->handler = ngx_ssl_read_handler;
                   1332:         }
                   1333: 
                   1334:         return NGX_AGAIN;
                   1335:     }
                   1336: 
                   1337:     c->ssl->no_wait_shutdown = 1;
                   1338:     c->ssl->no_send_shutdown = 1;
                   1339:     c->write->error = 1;
                   1340: 
                   1341:     ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
                   1342: 
                   1343:     return NGX_ERROR;
                   1344: }
                   1345: 
                   1346: 
                   1347: static void
                   1348: ngx_ssl_read_handler(ngx_event_t *rev)
                   1349: {
                   1350:     ngx_connection_t  *c;
                   1351: 
                   1352:     c = rev->data;
                   1353: 
                   1354:     c->write->handler(c->write);
                   1355: }
                   1356: 
                   1357: 
                   1358: void
                   1359: ngx_ssl_free_buffer(ngx_connection_t *c)
                   1360: {
                   1361:     if (c->ssl->buf && c->ssl->buf->start) {
                   1362:         if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
                   1363:             c->ssl->buf->start = NULL;
                   1364:         }
                   1365:     }
                   1366: }
                   1367: 
                   1368: 
                   1369: ngx_int_t
                   1370: ngx_ssl_shutdown(ngx_connection_t *c)
                   1371: {
                   1372:     int        n, sslerr, mode;
                   1373:     ngx_err_t  err;
                   1374: 
                   1375:     if (c->timedout) {
                   1376:         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
                   1377:         SSL_set_quiet_shutdown(c->ssl->connection, 1);
                   1378: 
                   1379:     } else {
                   1380:         mode = SSL_get_shutdown(c->ssl->connection);
                   1381: 
                   1382:         if (c->ssl->no_wait_shutdown) {
                   1383:             mode |= SSL_RECEIVED_SHUTDOWN;
                   1384:         }
                   1385: 
                   1386:         if (c->ssl->no_send_shutdown) {
                   1387:             mode |= SSL_SENT_SHUTDOWN;
                   1388:         }
                   1389: 
                   1390:         if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
                   1391:             SSL_set_quiet_shutdown(c->ssl->connection, 1);
                   1392:         }
                   1393:     }
                   1394: 
                   1395:     SSL_set_shutdown(c->ssl->connection, mode);
                   1396: 
                   1397:     ngx_ssl_clear_error(c->log);
                   1398: 
                   1399:     n = SSL_shutdown(c->ssl->connection);
                   1400: 
                   1401:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
                   1402: 
                   1403:     sslerr = 0;
                   1404: 
                   1405:     /* SSL_shutdown() never returns -1, on error it returns 0 */
                   1406: 
                   1407:     if (n != 1 && ERR_peek_error()) {
                   1408:         sslerr = SSL_get_error(c->ssl->connection, n);
                   1409: 
                   1410:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   1411:                        "SSL_get_error: %d", sslerr);
                   1412:     }
                   1413: 
                   1414:     if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
                   1415:         SSL_free(c->ssl->connection);
                   1416:         c->ssl = NULL;
                   1417: 
                   1418:         return NGX_OK;
                   1419:     }
                   1420: 
                   1421:     if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
                   1422:         c->read->handler = ngx_ssl_shutdown_handler;
                   1423:         c->write->handler = ngx_ssl_shutdown_handler;
                   1424: 
                   1425:         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
                   1426:             return NGX_ERROR;
                   1427:         }
                   1428: 
                   1429:         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
                   1430:             return NGX_ERROR;
                   1431:         }
                   1432: 
                   1433:         if (sslerr == SSL_ERROR_WANT_READ) {
                   1434:             ngx_add_timer(c->read, 30000);
                   1435:         }
                   1436: 
                   1437:         return NGX_AGAIN;
                   1438:     }
                   1439: 
                   1440:     err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
                   1441: 
                   1442:     ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
                   1443: 
                   1444:     SSL_free(c->ssl->connection);
                   1445:     c->ssl = NULL;
                   1446: 
                   1447:     return NGX_ERROR;
                   1448: }
                   1449: 
                   1450: 
                   1451: static void
                   1452: ngx_ssl_shutdown_handler(ngx_event_t *ev)
                   1453: {
                   1454:     ngx_connection_t           *c;
                   1455:     ngx_connection_handler_pt   handler;
                   1456: 
                   1457:     c = ev->data;
                   1458:     handler = c->ssl->handler;
                   1459: 
                   1460:     if (ev->timedout) {
                   1461:         c->timedout = 1;
                   1462:     }
                   1463: 
                   1464:     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "SSL shutdown handler");
                   1465: 
                   1466:     if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
                   1467:         return;
                   1468:     }
                   1469: 
                   1470:     handler(c);
                   1471: }
                   1472: 
                   1473: 
                   1474: static void
                   1475: ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
                   1476:     char *text)
                   1477: {
                   1478:     int         n;
                   1479:     ngx_uint_t  level;
                   1480: 
                   1481:     level = NGX_LOG_CRIT;
                   1482: 
                   1483:     if (sslerr == SSL_ERROR_SYSCALL) {
                   1484: 
                   1485:         if (err == NGX_ECONNRESET
                   1486:             || err == NGX_EPIPE
                   1487:             || err == NGX_ENOTCONN
                   1488:             || err == NGX_ETIMEDOUT
                   1489:             || err == NGX_ECONNREFUSED
                   1490:             || err == NGX_ENETDOWN
                   1491:             || err == NGX_ENETUNREACH
                   1492:             || err == NGX_EHOSTDOWN
                   1493:             || err == NGX_EHOSTUNREACH)
                   1494:         {
                   1495:             switch (c->log_error) {
                   1496: 
                   1497:             case NGX_ERROR_IGNORE_ECONNRESET:
                   1498:             case NGX_ERROR_INFO:
                   1499:                 level = NGX_LOG_INFO;
                   1500:                 break;
                   1501: 
                   1502:             case NGX_ERROR_ERR:
                   1503:                 level = NGX_LOG_ERR;
                   1504:                 break;
                   1505: 
                   1506:             default:
                   1507:                 break;
                   1508:             }
                   1509:         }
                   1510: 
                   1511:     } else if (sslerr == SSL_ERROR_SSL) {
                   1512: 
                   1513:         n = ERR_GET_REASON(ERR_peek_error());
                   1514: 
                   1515:             /* handshake failures */
                   1516:         if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC                        /*  103 */
                   1517:             || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  /*  129 */
                   1518:             || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
                   1519:             || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              /*  151 */
                   1520:             || n == SSL_R_EXCESSIVE_MESSAGE_SIZE                     /*  152 */
                   1521:             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
                   1522:             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
                   1523:             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
                   1524:             || n == SSL_R_NO_COMPRESSION_SPECIFIED                   /*  187 */
                   1525:             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
                   1526:             || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
                   1527: #ifdef SSL_R_PARSE_TLSEXT
                   1528:             || n == SSL_R_PARSE_TLSEXT                               /*  227 */
                   1529: #endif
                   1530:             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
                   1531:             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
                   1532:             || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
                   1533:             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
                   1534:             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
                   1535:             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
                   1536: #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
                   1537:             || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG                   /*  335 */
                   1538:             || n == SSL_R_RENEGOTIATION_ENCODING_ERR                 /*  336 */
                   1539:             || n == SSL_R_RENEGOTIATION_MISMATCH                     /*  337 */
                   1540: #endif
                   1541: #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
                   1542:             || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED       /*  338 */
                   1543: #endif
                   1544: #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
                   1545:             || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING           /*  345 */
                   1546: #endif
                   1547:             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
                   1548:             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
                   1549:             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
                   1550:             || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED              /* 1021 */
                   1551:             || n == SSL_R_TLSV1_ALERT_RECORD_OVERFLOW                /* 1022 */
                   1552:             || n == SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE          /* 1030 */
                   1553:             || n == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE              /* 1040 */
                   1554:             || n == SSL_R_SSLV3_ALERT_NO_CERTIFICATE                 /* 1041 */
                   1555:             || n == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE                /* 1042 */
                   1556:             || n == SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE        /* 1043 */
                   1557:             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED            /* 1044 */
                   1558:             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED            /* 1045 */
                   1559:             || n == SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN            /* 1046 */
                   1560:             || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER              /* 1047 */
                   1561:             || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA                     /* 1048 */
                   1562:             || n == SSL_R_TLSV1_ALERT_ACCESS_DENIED                  /* 1049 */
                   1563:             || n == SSL_R_TLSV1_ALERT_DECODE_ERROR                   /* 1050 */
                   1564:             || n == SSL_R_TLSV1_ALERT_DECRYPT_ERROR                  /* 1051 */
                   1565:             || n == SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION             /* 1060 */
                   1566:             || n == SSL_R_TLSV1_ALERT_PROTOCOL_VERSION               /* 1070 */
                   1567:             || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY          /* 1071 */
                   1568:             || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR                 /* 1080 */
                   1569:             || n == SSL_R_TLSV1_ALERT_USER_CANCELLED                 /* 1090 */
                   1570:             || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION)              /* 1100 */
                   1571:         {
                   1572:             switch (c->log_error) {
                   1573: 
                   1574:             case NGX_ERROR_IGNORE_ECONNRESET:
                   1575:             case NGX_ERROR_INFO:
                   1576:                 level = NGX_LOG_INFO;
                   1577:                 break;
                   1578: 
                   1579:             case NGX_ERROR_ERR:
                   1580:                 level = NGX_LOG_ERR;
                   1581:                 break;
                   1582: 
                   1583:             default:
                   1584:                 break;
                   1585:             }
                   1586:         }
                   1587:     }
                   1588: 
                   1589:     ngx_ssl_error(level, c->log, err, text);
                   1590: }
                   1591: 
                   1592: 
                   1593: static void
                   1594: ngx_ssl_clear_error(ngx_log_t *log)
                   1595: {
                   1596:     while (ERR_peek_error()) {
                   1597:         ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error");
                   1598:     }
                   1599: 
                   1600:     ERR_clear_error();
                   1601: }
                   1602: 
                   1603: 
                   1604: void ngx_cdecl
                   1605: ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
                   1606: {
                   1607:     int          flags;
                   1608:     u_long       n;
                   1609:     va_list      args;
                   1610:     u_char      *p, *last;
                   1611:     u_char       errstr[NGX_MAX_CONF_ERRSTR];
                   1612:     const char  *data;
                   1613: 
                   1614:     last = errstr + NGX_MAX_CONF_ERRSTR;
                   1615: 
                   1616:     va_start(args, fmt);
                   1617:     p = ngx_vslprintf(errstr, last - 1, fmt, args);
                   1618:     va_end(args);
                   1619: 
                   1620:     p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
                   1621: 
                   1622:     for ( ;; ) {
                   1623: 
                   1624:         n = ERR_peek_error_line_data(NULL, NULL, &data, &flags);
                   1625: 
                   1626:         if (n == 0) {
                   1627:             break;
                   1628:         }
                   1629: 
                   1630:         if (p >= last) {
                   1631:             goto next;
                   1632:         }
                   1633: 
                   1634:         *p++ = ' ';
                   1635: 
                   1636:         ERR_error_string_n(n, (char *) p, last - p);
                   1637: 
                   1638:         while (p < last && *p) {
                   1639:             p++;
                   1640:         }
                   1641: 
                   1642:         if (p < last && *data && (flags & ERR_TXT_STRING)) {
                   1643:             *p++ = ':';
                   1644:             p = ngx_cpystrn(p, (u_char *) data, last - p);
                   1645:         }
                   1646: 
                   1647:     next:
                   1648: 
                   1649:         (void) ERR_get_error();
                   1650:     }
                   1651: 
                   1652:     ngx_log_error(level, log, err, "%s)", errstr);
                   1653: }
                   1654: 
                   1655: 
                   1656: ngx_int_t
                   1657: ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
                   1658:     ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout)
                   1659: {
                   1660:     long  cache_mode;
                   1661: 
                   1662:     if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
                   1663:         SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
                   1664:         return NGX_OK;
                   1665:     }
                   1666: 
                   1667:     SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
                   1668: 
                   1669:     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
                   1670: 
                   1671:         /*
                   1672:          * If the server explicitly says that it does not support
                   1673:          * session reuse (see SSL_SESS_CACHE_OFF above), then
                   1674:          * Outlook Express fails to upload a sent email to
                   1675:          * the Sent Items folder on the IMAP server via a separate IMAP
                   1676:          * connection in the background. Therefore we have a special
                   1677:          * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE)
                   1678:          * where the server pretends that it supports session reuse,
                   1679:          * but it does not actually store any session.
                   1680:          */
                   1681: 
                   1682:         SSL_CTX_set_session_cache_mode(ssl->ctx,
                   1683:                                        SSL_SESS_CACHE_SERVER
                   1684:                                        |SSL_SESS_CACHE_NO_AUTO_CLEAR
                   1685:                                        |SSL_SESS_CACHE_NO_INTERNAL_STORE);
                   1686: 
                   1687:         SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
                   1688: 
                   1689:         return NGX_OK;
                   1690:     }
                   1691: 
                   1692:     cache_mode = SSL_SESS_CACHE_SERVER;
                   1693: 
                   1694:     if (shm_zone && builtin_session_cache == NGX_SSL_NO_BUILTIN_SCACHE) {
                   1695:         cache_mode |= SSL_SESS_CACHE_NO_INTERNAL;
                   1696:     }
                   1697: 
                   1698:     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
                   1699: 
                   1700:     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
                   1701: 
                   1702:         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
                   1703:             SSL_CTX_sess_set_cache_size(ssl->ctx, builtin_session_cache);
                   1704:         }
                   1705:     }
                   1706: 
                   1707:     SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
                   1708: 
                   1709:     if (shm_zone) {
                   1710:         SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
                   1711:         SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
                   1712:         SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session);
                   1713: 
                   1714:         if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone)
                   1715:             == 0)
                   1716:         {
                   1717:             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                   1718:                           "SSL_CTX_set_ex_data() failed");
                   1719:             return NGX_ERROR;
                   1720:         }
                   1721:     }
                   1722: 
                   1723:     return NGX_OK;
                   1724: }
                   1725: 
                   1726: 
                   1727: ngx_int_t
                   1728: ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
                   1729: {
                   1730:     size_t                    len;
                   1731:     ngx_slab_pool_t          *shpool;
                   1732:     ngx_ssl_session_cache_t  *cache;
                   1733: 
                   1734:     if (data) {
                   1735:         shm_zone->data = data;
                   1736:         return NGX_OK;
                   1737:     }
                   1738: 
                   1739:     if (shm_zone->shm.exists) {
                   1740:         shm_zone->data = data;
                   1741:         return NGX_OK;
                   1742:     }
                   1743: 
                   1744:     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
                   1745: 
                   1746:     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
                   1747:     if (cache == NULL) {
                   1748:         return NGX_ERROR;
                   1749:     }
                   1750: 
                   1751:     shpool->data = cache;
                   1752:     shm_zone->data = cache;
                   1753: 
                   1754:     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
                   1755:                     ngx_ssl_session_rbtree_insert_value);
                   1756: 
                   1757:     ngx_queue_init(&cache->expire_queue);
                   1758: 
                   1759:     len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
                   1760: 
                   1761:     shpool->log_ctx = ngx_slab_alloc(shpool, len);
                   1762:     if (shpool->log_ctx == NULL) {
                   1763:         return NGX_ERROR;
                   1764:     }
                   1765: 
                   1766:     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
                   1767:                 &shm_zone->shm.name);
                   1768: 
                   1769:     return NGX_OK;
                   1770: }
                   1771: 
                   1772: 
                   1773: /*
                   1774:  * The length of the session id is 16 bytes for SSLv2 sessions and
                   1775:  * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
                   1776:  * It seems that the typical length of the external ASN1 representation
                   1777:  * of a session is 118 or 119 bytes for SSLv3/TSLv1.
                   1778:  *
                   1779:  * Thus on 32-bit platforms we allocate separately an rbtree node,
                   1780:  * a session id, and an ASN1 representation, they take accordingly
                   1781:  * 64, 32, and 128 bytes.
                   1782:  *
                   1783:  * On 64-bit platforms we allocate separately an rbtree node + session_id,
                   1784:  * and an ASN1 representation, they take accordingly 128 and 128 bytes.
                   1785:  *
                   1786:  * OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
                   1787:  * so they are outside the code locked by shared pool mutex
                   1788:  */
                   1789: 
                   1790: static int
                   1791: ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
                   1792: {
                   1793:     int                       len;
                   1794:     u_char                   *p, *id, *cached_sess;
                   1795:     uint32_t                  hash;
                   1796:     SSL_CTX                  *ssl_ctx;
                   1797:     ngx_shm_zone_t           *shm_zone;
                   1798:     ngx_connection_t         *c;
                   1799:     ngx_slab_pool_t          *shpool;
                   1800:     ngx_ssl_sess_id_t        *sess_id;
                   1801:     ngx_ssl_session_cache_t  *cache;
                   1802:     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
                   1803: 
                   1804:     len = i2d_SSL_SESSION(sess, NULL);
                   1805: 
                   1806:     /* do not cache too big session */
                   1807: 
                   1808:     if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
                   1809:         return 0;
                   1810:     }
                   1811: 
                   1812:     p = buf;
                   1813:     i2d_SSL_SESSION(sess, &p);
                   1814: 
                   1815:     c = ngx_ssl_get_connection(ssl_conn);
                   1816: 
                   1817:     ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
                   1818:     shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
                   1819: 
                   1820:     cache = shm_zone->data;
                   1821:     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
                   1822: 
                   1823:     ngx_shmtx_lock(&shpool->mutex);
                   1824: 
                   1825:     /* drop one or two expired sessions */
                   1826:     ngx_ssl_expire_sessions(cache, shpool, 1);
                   1827: 
                   1828:     cached_sess = ngx_slab_alloc_locked(shpool, len);
                   1829: 
                   1830:     if (cached_sess == NULL) {
                   1831: 
                   1832:         /* drop the oldest non-expired session and try once more */
                   1833: 
                   1834:         ngx_ssl_expire_sessions(cache, shpool, 0);
                   1835: 
                   1836:         cached_sess = ngx_slab_alloc_locked(shpool, len);
                   1837: 
                   1838:         if (cached_sess == NULL) {
                   1839:             sess_id = NULL;
                   1840:             goto failed;
                   1841:         }
                   1842:     }
                   1843: 
                   1844:     sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
                   1845: 
                   1846:     if (sess_id == NULL) {
                   1847: 
                   1848:         /* drop the oldest non-expired session and try once more */
                   1849: 
                   1850:         ngx_ssl_expire_sessions(cache, shpool, 0);
                   1851: 
                   1852:         sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
                   1853: 
                   1854:         if (sess_id == NULL) {
                   1855:             goto failed;
                   1856:         }
                   1857:     }
                   1858: 
                   1859: #if (NGX_PTR_SIZE == 8)
                   1860: 
                   1861:     id = sess_id->sess_id;
                   1862: 
                   1863: #else
                   1864: 
                   1865:     id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
                   1866: 
                   1867:     if (id == NULL) {
                   1868: 
                   1869:         /* drop the oldest non-expired session and try once more */
                   1870: 
                   1871:         ngx_ssl_expire_sessions(cache, shpool, 0);
                   1872: 
                   1873:         id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
                   1874: 
                   1875:         if (id == NULL) {
                   1876:             goto failed;
                   1877:         }
                   1878:     }
                   1879: 
                   1880: #endif
                   1881: 
                   1882:     ngx_memcpy(cached_sess, buf, len);
                   1883: 
                   1884:     ngx_memcpy(id, sess->session_id, sess->session_id_length);
                   1885: 
                   1886:     hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
                   1887: 
                   1888:     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   1889:                    "ssl new session: %08XD:%d:%d",
                   1890:                    hash, sess->session_id_length, len);
                   1891: 
                   1892:     sess_id->node.key = hash;
                   1893:     sess_id->node.data = (u_char) sess->session_id_length;
                   1894:     sess_id->id = id;
                   1895:     sess_id->len = len;
                   1896:     sess_id->session = cached_sess;
                   1897: 
                   1898:     sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
                   1899: 
                   1900:     ngx_queue_insert_head(&cache->expire_queue, &sess_id->queue);
                   1901: 
                   1902:     ngx_rbtree_insert(&cache->session_rbtree, &sess_id->node);
                   1903: 
                   1904:     ngx_shmtx_unlock(&shpool->mutex);
                   1905: 
                   1906:     return 0;
                   1907: 
                   1908: failed:
                   1909: 
                   1910:     if (cached_sess) {
                   1911:         ngx_slab_free_locked(shpool, cached_sess);
                   1912:     }
                   1913: 
                   1914:     if (sess_id) {
                   1915:         ngx_slab_free_locked(shpool, sess_id);
                   1916:     }
                   1917: 
                   1918:     ngx_shmtx_unlock(&shpool->mutex);
                   1919: 
                   1920:     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                   1921:                   "could not add new SSL session to the session cache");
                   1922: 
                   1923:     return 0;
                   1924: }
                   1925: 
                   1926: 
                   1927: static ngx_ssl_session_t *
                   1928: ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
                   1929:     int *copy)
                   1930: {
                   1931: #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
                   1932:     const
                   1933: #endif
                   1934:     u_char                   *p;
                   1935:     uint32_t                  hash;
                   1936:     ngx_int_t                 rc;
                   1937:     ngx_shm_zone_t           *shm_zone;
                   1938:     ngx_slab_pool_t          *shpool;
                   1939:     ngx_rbtree_node_t        *node, *sentinel;
                   1940:     ngx_ssl_session_t        *sess;
                   1941:     ngx_ssl_sess_id_t        *sess_id;
                   1942:     ngx_ssl_session_cache_t  *cache;
                   1943:     u_char                    buf[NGX_SSL_MAX_SESSION_SIZE];
                   1944: #if (NGX_DEBUG)
                   1945:     ngx_connection_t         *c;
                   1946: #endif
                   1947: 
                   1948:     hash = ngx_crc32_short(id, (size_t) len);
                   1949:     *copy = 0;
                   1950: 
                   1951: #if (NGX_DEBUG)
                   1952:     c = ngx_ssl_get_connection(ssl_conn);
                   1953: 
                   1954:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   1955:                    "ssl get session: %08XD:%d", hash, len);
                   1956: #endif
                   1957: 
                   1958:     shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
                   1959:                                    ngx_ssl_session_cache_index);
                   1960: 
                   1961:     cache = shm_zone->data;
                   1962: 
                   1963:     sess = NULL;
                   1964: 
                   1965:     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
                   1966: 
                   1967:     ngx_shmtx_lock(&shpool->mutex);
                   1968: 
                   1969:     node = cache->session_rbtree.root;
                   1970:     sentinel = cache->session_rbtree.sentinel;
                   1971: 
                   1972:     while (node != sentinel) {
                   1973: 
                   1974:         if (hash < node->key) {
                   1975:             node = node->left;
                   1976:             continue;
                   1977:         }
                   1978: 
                   1979:         if (hash > node->key) {
                   1980:             node = node->right;
                   1981:             continue;
                   1982:         }
                   1983: 
                   1984:         /* hash == node->key */
                   1985: 
                   1986:         sess_id = (ngx_ssl_sess_id_t *) node;
                   1987: 
                   1988:         rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data);
                   1989: 
                   1990:         if (rc == 0) {
                   1991: 
                   1992:             if (sess_id->expire > ngx_time()) {
                   1993:                 ngx_memcpy(buf, sess_id->session, sess_id->len);
                   1994: 
                   1995:                 ngx_shmtx_unlock(&shpool->mutex);
                   1996: 
                   1997:                 p = buf;
                   1998:                 sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
                   1999: 
                   2000:                 return sess;
                   2001:             }
                   2002: 
                   2003:             ngx_queue_remove(&sess_id->queue);
                   2004: 
                   2005:             ngx_rbtree_delete(&cache->session_rbtree, node);
                   2006: 
                   2007:             ngx_slab_free_locked(shpool, sess_id->session);
                   2008: #if (NGX_PTR_SIZE == 4)
                   2009:             ngx_slab_free_locked(shpool, sess_id->id);
                   2010: #endif
                   2011:             ngx_slab_free_locked(shpool, sess_id);
                   2012: 
                   2013:             sess = NULL;
                   2014: 
                   2015:             goto done;
                   2016:         }
                   2017: 
                   2018:         node = (rc < 0) ? node->left : node->right;
                   2019:     }
                   2020: 
                   2021: done:
                   2022: 
                   2023:     ngx_shmtx_unlock(&shpool->mutex);
                   2024: 
                   2025:     return sess;
                   2026: }
                   2027: 
                   2028: 
                   2029: void
                   2030: ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
                   2031: {
                   2032:      SSL_CTX_remove_session(ssl, sess);
                   2033: 
                   2034:      ngx_ssl_remove_session(ssl, sess);
                   2035: }
                   2036: 
                   2037: 
                   2038: static void
                   2039: ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
                   2040: {
                   2041:     size_t                    len;
                   2042:     u_char                   *id;
                   2043:     uint32_t                  hash;
                   2044:     ngx_int_t                 rc;
                   2045:     ngx_shm_zone_t           *shm_zone;
                   2046:     ngx_slab_pool_t          *shpool;
                   2047:     ngx_rbtree_node_t        *node, *sentinel;
                   2048:     ngx_ssl_sess_id_t        *sess_id;
                   2049:     ngx_ssl_session_cache_t  *cache;
                   2050: 
                   2051:     shm_zone = SSL_CTX_get_ex_data(ssl, ngx_ssl_session_cache_index);
                   2052: 
                   2053:     if (shm_zone == NULL) {
                   2054:         return;
                   2055:     }
                   2056: 
                   2057:     cache = shm_zone->data;
                   2058: 
                   2059:     id = sess->session_id;
                   2060:     len = (size_t) sess->session_id_length;
                   2061: 
                   2062:     hash = ngx_crc32_short(id, len);
                   2063: 
                   2064:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
                   2065:                    "ssl remove session: %08XD:%uz", hash, len);
                   2066: 
                   2067:     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
                   2068: 
                   2069:     ngx_shmtx_lock(&shpool->mutex);
                   2070: 
                   2071:     node = cache->session_rbtree.root;
                   2072:     sentinel = cache->session_rbtree.sentinel;
                   2073: 
                   2074:     while (node != sentinel) {
                   2075: 
                   2076:         if (hash < node->key) {
                   2077:             node = node->left;
                   2078:             continue;
                   2079:         }
                   2080: 
                   2081:         if (hash > node->key) {
                   2082:             node = node->right;
                   2083:             continue;
                   2084:         }
                   2085: 
                   2086:         /* hash == node->key */
                   2087: 
                   2088:         sess_id = (ngx_ssl_sess_id_t *) node;
                   2089: 
                   2090:         rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
                   2091: 
                   2092:         if (rc == 0) {
                   2093: 
                   2094:             ngx_queue_remove(&sess_id->queue);
                   2095: 
                   2096:             ngx_rbtree_delete(&cache->session_rbtree, node);
                   2097: 
                   2098:             ngx_slab_free_locked(shpool, sess_id->session);
                   2099: #if (NGX_PTR_SIZE == 4)
                   2100:             ngx_slab_free_locked(shpool, sess_id->id);
                   2101: #endif
                   2102:             ngx_slab_free_locked(shpool, sess_id);
                   2103: 
                   2104:             goto done;
                   2105:         }
                   2106: 
                   2107:         node = (rc < 0) ? node->left : node->right;
                   2108:     }
                   2109: 
                   2110: done:
                   2111: 
                   2112:     ngx_shmtx_unlock(&shpool->mutex);
                   2113: }
                   2114: 
                   2115: 
                   2116: static void
                   2117: ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
                   2118:     ngx_slab_pool_t *shpool, ngx_uint_t n)
                   2119: {
                   2120:     time_t              now;
                   2121:     ngx_queue_t        *q;
                   2122:     ngx_ssl_sess_id_t  *sess_id;
                   2123: 
                   2124:     now = ngx_time();
                   2125: 
                   2126:     while (n < 3) {
                   2127: 
                   2128:         if (ngx_queue_empty(&cache->expire_queue)) {
                   2129:             return;
                   2130:         }
                   2131: 
                   2132:         q = ngx_queue_last(&cache->expire_queue);
                   2133: 
                   2134:         sess_id = ngx_queue_data(q, ngx_ssl_sess_id_t, queue);
                   2135: 
                   2136:         if (n++ != 0 && sess_id->expire > now) {
                   2137:             return;
                   2138:         }
                   2139: 
                   2140:         ngx_queue_remove(q);
                   2141: 
                   2142:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
                   2143:                        "expire session: %08Xi", sess_id->node.key);
                   2144: 
                   2145:         ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
                   2146: 
                   2147:         ngx_slab_free_locked(shpool, sess_id->session);
                   2148: #if (NGX_PTR_SIZE == 4)
                   2149:         ngx_slab_free_locked(shpool, sess_id->id);
                   2150: #endif
                   2151:         ngx_slab_free_locked(shpool, sess_id);
                   2152:     }
                   2153: }
                   2154: 
                   2155: 
                   2156: static void
                   2157: ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
                   2158:     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
                   2159: {
                   2160:     ngx_rbtree_node_t  **p;
                   2161:     ngx_ssl_sess_id_t   *sess_id, *sess_id_temp;
                   2162: 
                   2163:     for ( ;; ) {
                   2164: 
                   2165:         if (node->key < temp->key) {
                   2166: 
                   2167:             p = &temp->left;
                   2168: 
                   2169:         } else if (node->key > temp->key) {
                   2170: 
                   2171:             p = &temp->right;
                   2172: 
                   2173:         } else { /* node->key == temp->key */
                   2174: 
                   2175:             sess_id = (ngx_ssl_sess_id_t *) node;
                   2176:             sess_id_temp = (ngx_ssl_sess_id_t *) temp;
                   2177: 
                   2178:             p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
                   2179:                               (size_t) node->data, (size_t) temp->data)
                   2180:                  < 0) ? &temp->left : &temp->right;
                   2181:         }
                   2182: 
                   2183:         if (*p == sentinel) {
                   2184:             break;
                   2185:         }
                   2186: 
                   2187:         temp = *p;
                   2188:     }
                   2189: 
                   2190:     *p = node;
                   2191:     node->parent = temp;
                   2192:     node->left = sentinel;
                   2193:     node->right = sentinel;
                   2194:     ngx_rbt_red(node);
                   2195: }
                   2196: 
                   2197: 
                   2198: void
                   2199: ngx_ssl_cleanup_ctx(void *data)
                   2200: {
                   2201:     ngx_ssl_t  *ssl = data;
                   2202: 
                   2203:     SSL_CTX_free(ssl->ctx);
                   2204: }
                   2205: 
                   2206: 
                   2207: ngx_int_t
                   2208: ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2209: {
                   2210:     s->data = (u_char *) SSL_get_version(c->ssl->connection);
                   2211:     return NGX_OK;
                   2212: }
                   2213: 
                   2214: 
                   2215: ngx_int_t
                   2216: ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2217: {
                   2218:     s->data = (u_char *) SSL_get_cipher_name(c->ssl->connection);
                   2219:     return NGX_OK;
                   2220: }
                   2221: 
                   2222: 
                   2223: ngx_int_t
                   2224: ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2225: {
                   2226:     int           len;
                   2227:     u_char       *p, *buf;
                   2228:     SSL_SESSION  *sess;
                   2229: 
                   2230:     sess = SSL_get0_session(c->ssl->connection);
                   2231: 
                   2232:     len = i2d_SSL_SESSION(sess, NULL);
                   2233: 
                   2234:     buf = ngx_alloc(len, c->log);
                   2235:     if (buf == NULL) {
                   2236:         return NGX_ERROR;
                   2237:     }
                   2238: 
                   2239:     s->len = 2 * len;
                   2240:     s->data = ngx_pnalloc(pool, 2 * len);
                   2241:     if (s->data == NULL) {
                   2242:         ngx_free(buf);
                   2243:         return NGX_ERROR;
                   2244:     }
                   2245: 
                   2246:     p = buf;
                   2247:     i2d_SSL_SESSION(sess, &p);
                   2248: 
                   2249:     ngx_hex_dump(s->data, buf, len);
                   2250: 
                   2251:     ngx_free(buf);
                   2252: 
                   2253:     return NGX_OK;
                   2254: }
                   2255: 
                   2256: 
                   2257: ngx_int_t
                   2258: ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2259: {
                   2260:     size_t   len;
                   2261:     BIO     *bio;
                   2262:     X509    *cert;
                   2263: 
                   2264:     s->len = 0;
                   2265: 
                   2266:     cert = SSL_get_peer_certificate(c->ssl->connection);
                   2267:     if (cert == NULL) {
                   2268:         return NGX_OK;
                   2269:     }
                   2270: 
                   2271:     bio = BIO_new(BIO_s_mem());
                   2272:     if (bio == NULL) {
                   2273:         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
                   2274:         X509_free(cert);
                   2275:         return NGX_ERROR;
                   2276:     }
                   2277: 
                   2278:     if (PEM_write_bio_X509(bio, cert) == 0) {
                   2279:         ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
                   2280:         goto failed;
                   2281:     }
                   2282: 
                   2283:     len = BIO_pending(bio);
                   2284:     s->len = len;
                   2285: 
                   2286:     s->data = ngx_pnalloc(pool, len);
                   2287:     if (s->data == NULL) {
                   2288:         goto failed;
                   2289:     }
                   2290: 
                   2291:     BIO_read(bio, s->data, len);
                   2292: 
                   2293:     BIO_free(bio);
                   2294:     X509_free(cert);
                   2295: 
                   2296:     return NGX_OK;
                   2297: 
                   2298: failed:
                   2299: 
                   2300:     BIO_free(bio);
                   2301:     X509_free(cert);
                   2302: 
                   2303:     return NGX_ERROR;
                   2304: }
                   2305: 
                   2306: 
                   2307: ngx_int_t
                   2308: ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2309: {
                   2310:     u_char      *p;
                   2311:     size_t       len;
                   2312:     ngx_uint_t   i;
                   2313:     ngx_str_t    cert;
                   2314: 
                   2315:     if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
                   2316:         return NGX_ERROR;
                   2317:     }
                   2318: 
                   2319:     if (cert.len == 0) {
                   2320:         s->len = 0;
                   2321:         return NGX_OK;
                   2322:     }
                   2323: 
                   2324:     len = cert.len - 1;
                   2325: 
                   2326:     for (i = 0; i < cert.len - 1; i++) {
                   2327:         if (cert.data[i] == LF) {
                   2328:             len++;
                   2329:         }
                   2330:     }
                   2331: 
                   2332:     s->len = len;
                   2333:     s->data = ngx_pnalloc(pool, len);
                   2334:     if (s->data == NULL) {
                   2335:         return NGX_ERROR;
                   2336:     }
                   2337: 
                   2338:     p = s->data;
                   2339: 
                   2340:     for (i = 0; i < cert.len - 1; i++) {
                   2341:         *p++ = cert.data[i];
                   2342:         if (cert.data[i] == LF) {
                   2343:             *p++ = '\t';
                   2344:         }
                   2345:     }
                   2346: 
                   2347:     return NGX_OK;
                   2348: }
                   2349: 
                   2350: 
                   2351: ngx_int_t
                   2352: ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2353: {
                   2354:     char       *p;
                   2355:     size_t      len;
                   2356:     X509       *cert;
                   2357:     X509_NAME  *name;
                   2358: 
                   2359:     s->len = 0;
                   2360: 
                   2361:     cert = SSL_get_peer_certificate(c->ssl->connection);
                   2362:     if (cert == NULL) {
                   2363:         return NGX_OK;
                   2364:     }
                   2365: 
                   2366:     name = X509_get_subject_name(cert);
                   2367:     if (name == NULL) {
                   2368:         X509_free(cert);
                   2369:         return NGX_ERROR;
                   2370:     }
                   2371: 
                   2372:     p = X509_NAME_oneline(name, NULL, 0);
                   2373: 
                   2374:     for (len = 0; p[len]; len++) { /* void */ }
                   2375: 
                   2376:     s->len = len;
                   2377:     s->data = ngx_pnalloc(pool, len);
                   2378:     if (s->data == NULL) {
                   2379:         OPENSSL_free(p);
                   2380:         X509_free(cert);
                   2381:         return NGX_ERROR;
                   2382:     }
                   2383: 
                   2384:     ngx_memcpy(s->data, p, len);
                   2385: 
                   2386:     OPENSSL_free(p);
                   2387:     X509_free(cert);
                   2388: 
                   2389:     return NGX_OK;
                   2390: }
                   2391: 
                   2392: 
                   2393: ngx_int_t
                   2394: ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2395: {
                   2396:     char       *p;
                   2397:     size_t      len;
                   2398:     X509       *cert;
                   2399:     X509_NAME  *name;
                   2400: 
                   2401:     s->len = 0;
                   2402: 
                   2403:     cert = SSL_get_peer_certificate(c->ssl->connection);
                   2404:     if (cert == NULL) {
                   2405:         return NGX_OK;
                   2406:     }
                   2407: 
                   2408:     name = X509_get_issuer_name(cert);
                   2409:     if (name == NULL) {
                   2410:         X509_free(cert);
                   2411:         return NGX_ERROR;
                   2412:     }
                   2413: 
                   2414:     p = X509_NAME_oneline(name, NULL, 0);
                   2415: 
                   2416:     for (len = 0; p[len]; len++) { /* void */ }
                   2417: 
                   2418:     s->len = len;
                   2419:     s->data = ngx_pnalloc(pool, len);
                   2420:     if (s->data == NULL) {
                   2421:         OPENSSL_free(p);
                   2422:         X509_free(cert);
                   2423:         return NGX_ERROR;
                   2424:     }
                   2425: 
                   2426:     ngx_memcpy(s->data, p, len);
                   2427: 
                   2428:     OPENSSL_free(p);
                   2429:     X509_free(cert);
                   2430: 
                   2431:     return NGX_OK;
                   2432: }
                   2433: 
                   2434: 
                   2435: ngx_int_t
                   2436: ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2437: {
                   2438:     size_t   len;
                   2439:     X509    *cert;
                   2440:     BIO     *bio;
                   2441: 
                   2442:     s->len = 0;
                   2443: 
                   2444:     cert = SSL_get_peer_certificate(c->ssl->connection);
                   2445:     if (cert == NULL) {
                   2446:         return NGX_OK;
                   2447:     }
                   2448: 
                   2449:     bio = BIO_new(BIO_s_mem());
                   2450:     if (bio == NULL) {
                   2451:         X509_free(cert);
                   2452:         return NGX_ERROR;
                   2453:     }
                   2454: 
                   2455:     i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert));
                   2456:     len = BIO_pending(bio);
                   2457: 
                   2458:     s->len = len;
                   2459:     s->data = ngx_pnalloc(pool, len);
                   2460:     if (s->data == NULL) {
                   2461:         BIO_free(bio);
                   2462:         X509_free(cert);
                   2463:         return NGX_ERROR;
                   2464:     }
                   2465: 
                   2466:     BIO_read(bio, s->data, len);
                   2467:     BIO_free(bio);
                   2468:     X509_free(cert);
                   2469: 
                   2470:     return NGX_OK;
                   2471: }
                   2472: 
                   2473: 
                   2474: ngx_int_t
                   2475: ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
                   2476: {
                   2477:     X509  *cert;
                   2478: 
                   2479:     if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
                   2480:         ngx_str_set(s, "FAILED");
                   2481:         return NGX_OK;
                   2482:     }
                   2483: 
                   2484:     cert = SSL_get_peer_certificate(c->ssl->connection);
                   2485: 
                   2486:     if (cert) {
                   2487:         ngx_str_set(s, "SUCCESS");
                   2488: 
                   2489:     } else {
                   2490:         ngx_str_set(s, "NONE");
                   2491:     }
                   2492: 
                   2493:     X509_free(cert);
                   2494: 
                   2495:     return NGX_OK;
                   2496: }
                   2497: 
                   2498: 
                   2499: static void *
                   2500: ngx_openssl_create_conf(ngx_cycle_t *cycle)
                   2501: {
                   2502:     ngx_openssl_conf_t  *oscf;
                   2503: 
                   2504:     oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
                   2505:     if (oscf == NULL) {
                   2506:         return NULL;
                   2507:     }
                   2508: 
                   2509:     /*
                   2510:      * set by ngx_pcalloc():
                   2511:      *
                   2512:      *     oscf->engine = 0;
                   2513:      */
                   2514: 
                   2515:     return oscf;
                   2516: }
                   2517: 
                   2518: 
                   2519: static char *
                   2520: ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                   2521: {
                   2522:     ngx_openssl_conf_t *oscf = conf;
                   2523: 
                   2524:     ENGINE     *engine;
                   2525:     ngx_str_t  *value;
                   2526: 
                   2527:     if (oscf->engine) {
                   2528:         return "is duplicate";
                   2529:     }
                   2530: 
                   2531:     oscf->engine = 1;
                   2532: 
                   2533:     value = cf->args->elts;
                   2534: 
                   2535:     engine = ENGINE_by_id((const char *) value[1].data);
                   2536: 
                   2537:     if (engine == NULL) {
                   2538:         ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
                   2539:                       "ENGINE_by_id(\"%V\") failed", &value[1]);
                   2540:         return NGX_CONF_ERROR;
                   2541:     }
                   2542: 
                   2543:     if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) {
                   2544:         ngx_ssl_error(NGX_LOG_WARN, cf->log, 0,
                   2545:                       "ENGINE_set_default(\"%V\", ENGINE_METHOD_ALL) failed",
                   2546:                       &value[1]);
                   2547: 
                   2548:         ENGINE_free(engine);
                   2549: 
                   2550:         return NGX_CONF_ERROR;
                   2551:     }
                   2552: 
                   2553:     ENGINE_free(engine);
                   2554: 
                   2555:     return NGX_CONF_OK;
                   2556: }
                   2557: 
                   2558: 
                   2559: static void
                   2560: ngx_openssl_exit(ngx_cycle_t *cycle)
                   2561: {
                   2562:     EVP_cleanup();
                   2563:     ENGINE_cleanup();
                   2564: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>