LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_ssl_ocsp.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 0 236 0.0 %
Date: 2020-03-03 04:25:50 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /*
       3             :  * Copyright (C) Yichun Zhang (agentzh)
       4             :  */
       5             : 
       6             : 
       7             : #ifndef DDEBUG
       8             : #define DDEBUG 0
       9             : #endif
      10             : #include "ddebug.h"
      11             : 
      12             : 
      13             : #if (NGX_HTTP_SSL)
      14             : 
      15             : 
      16             : #include "ngx_http_lua_common.h"
      17             : 
      18             : 
      19             : #ifndef NGX_LUA_NO_FFI_API
      20             : 
      21             : #ifdef NGX_HTTP_LUA_USE_OCSP
      22             : static int ngx_http_lua_ssl_empty_status_callback(ngx_ssl_conn_t *ssl_conn,
      23             :     void *data);
      24             : #endif
      25             : 
      26             : 
      27             : int
      28           0 : ngx_http_lua_ffi_ssl_get_ocsp_responder_from_der_chain(
      29             :     const char *chain_data, size_t chain_len, unsigned char *out,
      30             :     size_t *out_size, char **err)
      31             : {
      32             : #ifndef NGX_HTTP_LUA_USE_OCSP
      33             : 
      34             :     *err = "no OCSP support";
      35             :     return NGX_ERROR;
      36             : 
      37             : #else
      38             : 
      39           0 :     int                        rc = NGX_OK;
      40           0 :     BIO                       *bio = NULL;
      41             :     char                      *s;
      42           0 :     X509                      *cert = NULL, *issuer = NULL;
      43             :     size_t                     len;
      44           0 :     STACK_OF(OPENSSL_STRING)  *aia = NULL;
      45             : 
      46             :     /* certificate */
      47             : 
      48           0 :     bio = BIO_new_mem_buf((char *) chain_data, chain_len);
      49           0 :     if (bio == NULL) {
      50           0 :         *err = "BIO_new_mem_buf() failed";
      51           0 :         rc = NGX_ERROR;
      52           0 :         goto done;
      53             :     }
      54             : 
      55           0 :     cert = d2i_X509_bio(bio, NULL);
      56           0 :     if (cert == NULL) {
      57           0 :         *err = "d2i_X509_bio() failed";
      58           0 :         rc = NGX_ERROR;
      59           0 :         goto done;
      60             :     }
      61             : 
      62             :     /* responder */
      63             : 
      64           0 :     aia = X509_get1_ocsp(cert);
      65           0 :     if (aia == NULL) {
      66           0 :         rc = NGX_DECLINED;
      67           0 :         goto done;
      68             :     }
      69             : 
      70             : #if OPENSSL_VERSION_NUMBER >= 0x10000000L
      71           0 :     s = sk_OPENSSL_STRING_value(aia, 0);
      72             : #else
      73             :     s = sk_value(aia, 0);
      74             : #endif
      75           0 :     if (s == NULL) {
      76           0 :         rc = NGX_DECLINED;
      77           0 :         goto done;
      78             :     }
      79             : 
      80           0 :     len = ngx_strlen(s);
      81           0 :     if (len > *out_size) {
      82           0 :         len = *out_size;
      83           0 :         rc = NGX_BUSY;
      84             : 
      85             :     } else {
      86           0 :         rc = NGX_OK;
      87           0 :         *out_size = len;
      88             :     }
      89             : 
      90           0 :     ngx_memcpy(out, s, len);
      91             : 
      92           0 :     X509_email_free(aia);
      93           0 :     aia = NULL;
      94             : 
      95             :     /* issuer */
      96             : 
      97           0 :     if (BIO_eof(bio)) {
      98           0 :         *err = "no issuer certificate in chain";
      99           0 :         rc = NGX_ERROR;
     100           0 :         goto done;
     101             :     }
     102             : 
     103           0 :     issuer = d2i_X509_bio(bio, NULL);
     104           0 :     if (issuer == NULL) {
     105           0 :         *err = "d2i_X509_bio() failed";
     106           0 :         rc = NGX_ERROR;
     107           0 :         goto done;
     108             :     }
     109             : 
     110           0 :     if (X509_check_issued(issuer, cert) != X509_V_OK) {
     111           0 :         *err = "issuer certificate not next to leaf";
     112           0 :         rc = NGX_ERROR;
     113           0 :         goto done;
     114             :     }
     115             : 
     116           0 :     X509_free(issuer);
     117           0 :     X509_free(cert);
     118           0 :     BIO_free(bio);
     119             : 
     120           0 :     return rc;
     121             : 
     122           0 : done:
     123             : 
     124           0 :     if (aia) {
     125           0 :         X509_email_free(aia);
     126             :     }
     127             : 
     128           0 :     if (issuer) {
     129           0 :         X509_free(issuer);
     130             :     }
     131             : 
     132           0 :     if (cert) {
     133           0 :         X509_free(cert);
     134             :     }
     135             : 
     136           0 :     if (bio) {
     137           0 :         BIO_free(bio);
     138             :     }
     139             : 
     140           0 :     if (rc == NGX_ERROR) {
     141           0 :         ERR_clear_error();
     142             :     }
     143             : 
     144           0 :     return rc;
     145             : 
     146             : #endif  /* NGX_HTTP_LUA_USE_OCSP */
     147             : }
     148             : 
     149             : 
     150             : int
     151           0 : ngx_http_lua_ffi_ssl_create_ocsp_request(const char *chain_data,
     152             :     size_t chain_len, unsigned char *out, size_t *out_size, char **err)
     153             : {
     154             : #ifndef NGX_HTTP_LUA_USE_OCSP
     155             : 
     156             :     *err = "no OCSP support";
     157             :     return NGX_ERROR;
     158             : 
     159             : #else
     160             : 
     161           0 :     int                        rc = NGX_ERROR;
     162           0 :     BIO                       *bio = NULL;
     163           0 :     X509                      *cert = NULL, *issuer = NULL;
     164             :     size_t                     len;
     165             :     OCSP_CERTID               *id;
     166           0 :     OCSP_REQUEST              *ocsp = NULL;
     167             : 
     168             :     /* certificate */
     169             : 
     170           0 :     bio = BIO_new_mem_buf((char *) chain_data, chain_len);
     171           0 :     if (bio == NULL) {
     172           0 :         *err = "BIO_new_mem_buf() failed";
     173           0 :         goto failed;
     174             :     }
     175             : 
     176           0 :     cert = d2i_X509_bio(bio, NULL);
     177           0 :     if (cert == NULL) {
     178           0 :         *err = "d2i_X509_bio() failed";
     179           0 :         goto failed;
     180             :     }
     181             : 
     182           0 :     if (BIO_eof(bio)) {
     183           0 :         *err = "no issuer certificate in chain";
     184           0 :         goto failed;
     185             :     }
     186             : 
     187           0 :     issuer = d2i_X509_bio(bio, NULL);
     188           0 :     if (issuer == NULL) {
     189           0 :         *err = "d2i_X509_bio() failed";
     190           0 :         goto failed;
     191             :     }
     192             : 
     193           0 :     ocsp = OCSP_REQUEST_new();
     194           0 :     if (ocsp == NULL) {
     195           0 :         *err = "OCSP_REQUEST_new() failed";
     196           0 :         goto failed;
     197             :     }
     198             : 
     199           0 :     id = OCSP_cert_to_id(NULL, cert, issuer);
     200           0 :     if (id == NULL) {
     201           0 :         *err = "OCSP_cert_to_id() failed";
     202           0 :         goto failed;
     203             :     }
     204             : 
     205           0 :     if (OCSP_request_add0_id(ocsp, id) == NULL) {
     206           0 :         *err = "OCSP_request_add0_id() failed";
     207           0 :         goto failed;
     208             :     }
     209             : 
     210           0 :     len = i2d_OCSP_REQUEST(ocsp, NULL);
     211           0 :     if (len <= 0) {
     212           0 :         *err = "i2d_OCSP_REQUEST() failed";
     213           0 :         goto failed;
     214             :     }
     215             : 
     216           0 :     if (len > *out_size) {
     217           0 :         *err = "output buffer too small";
     218           0 :         *out_size = len;
     219           0 :         rc = NGX_BUSY;
     220           0 :         goto failed;
     221             :     }
     222             : 
     223           0 :     len = i2d_OCSP_REQUEST(ocsp, &out);
     224           0 :     if (len <=  0) {
     225           0 :         *err = "i2d_OCSP_REQUEST() failed";
     226           0 :         goto failed;
     227             :     }
     228             : 
     229           0 :     *out_size = len;
     230             : 
     231           0 :     OCSP_REQUEST_free(ocsp);
     232           0 :     X509_free(issuer);
     233           0 :     X509_free(cert);
     234           0 :     BIO_free(bio);
     235             : 
     236           0 :     return NGX_OK;
     237             : 
     238           0 : failed:
     239             : 
     240           0 :     if (ocsp) {
     241           0 :         OCSP_REQUEST_free(ocsp);
     242             :     }
     243             : 
     244           0 :     if (issuer) {
     245           0 :         X509_free(issuer);
     246             :     }
     247             : 
     248           0 :     if (cert) {
     249           0 :         X509_free(cert);
     250             :     }
     251             : 
     252           0 :     if (bio) {
     253           0 :         BIO_free(bio);
     254             :     }
     255             : 
     256           0 :     ERR_clear_error();
     257             : 
     258           0 :     return rc;
     259             : 
     260             : #endif  /* NGX_HTTP_LUA_USE_OCSP */
     261             : }
     262             : 
     263             : 
     264             : int
     265           0 : ngx_http_lua_ffi_ssl_validate_ocsp_response(const u_char *resp,
     266             :     size_t resp_len, const char *chain_data, size_t chain_len,
     267             :     u_char *errbuf, size_t *errbuf_size)
     268             : {
     269             : #ifndef NGX_HTTP_LUA_USE_OCSP
     270             : 
     271             :     *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     272             :                                 "no OCSP support") - errbuf;
     273             :     return NGX_ERROR;
     274             : 
     275             : #else
     276             : 
     277             :     int                    n;
     278           0 :     BIO                   *bio = NULL;
     279           0 :     X509                  *cert = NULL, *issuer = NULL;
     280           0 :     OCSP_CERTID           *id = NULL;
     281           0 :     OCSP_RESPONSE         *ocsp = NULL;
     282           0 :     OCSP_BASICRESP        *basic = NULL;
     283           0 :     STACK_OF(X509)        *chain = NULL;
     284             :     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
     285             : 
     286           0 :     ocsp = d2i_OCSP_RESPONSE(NULL, &resp, resp_len);
     287           0 :     if (ocsp == NULL) {
     288           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     289           0 :                                     "d2i_OCSP_RESPONSE() failed") - errbuf;
     290           0 :         goto error;
     291             :     }
     292             : 
     293           0 :     n = OCSP_response_status(ocsp);
     294             : 
     295           0 :     if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
     296           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     297             :                                     "OCSP response not successful (%d: %s)",
     298           0 :                                     n, OCSP_response_status_str(n)) - errbuf;
     299           0 :         goto error;
     300             :     }
     301             : 
     302           0 :     basic = OCSP_response_get1_basic(ocsp);
     303           0 :     if (basic == NULL) {
     304           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     305             :                                     "OCSP_response_get1_basic() failed")
     306           0 :                        - errbuf;
     307           0 :         goto error;
     308             :     }
     309             : 
     310             :     /* get issuer certificate from chain */
     311             : 
     312           0 :     bio = BIO_new_mem_buf((char *) chain_data, chain_len);
     313           0 :     if (bio == NULL) {
     314           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     315             :                                     "BIO_new_mem_buf() failed")
     316           0 :                        - errbuf;
     317           0 :         goto error;
     318             :     }
     319             : 
     320           0 :     cert = d2i_X509_bio(bio, NULL);
     321           0 :     if (cert == NULL) {
     322           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     323             :                                     "d2i_X509_bio() failed")
     324           0 :                        - errbuf;
     325           0 :         goto error;
     326             :     }
     327             : 
     328           0 :     if (BIO_eof(bio)) {
     329           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     330             :                                     "no issuer certificate in chain")
     331           0 :                        - errbuf;
     332           0 :         goto error;
     333             :     }
     334             : 
     335           0 :     issuer = d2i_X509_bio(bio, NULL);
     336           0 :     if (issuer == NULL) {
     337           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     338           0 :                                     "d2i_X509_bio() failed") - errbuf;
     339           0 :         goto error;
     340             :     }
     341             : 
     342           0 :     chain = sk_X509_new_null();
     343           0 :     if (chain == NULL) {
     344           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     345           0 :                                     "sk_X509_new_null() failed") - errbuf;
     346           0 :         goto error;
     347             :     }
     348             : 
     349           0 :     (void) sk_X509_push(chain, issuer);
     350             : 
     351           0 :     if (OCSP_basic_verify(basic, chain, NULL, OCSP_NOVERIFY) != 1) {
     352           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     353           0 :                                     "OCSP_basic_verify() failed") - errbuf;
     354           0 :         goto error;
     355             :     }
     356             : 
     357           0 :     id = OCSP_cert_to_id(NULL, cert, issuer);
     358           0 :     if (id == NULL) {
     359           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     360           0 :                                     "OCSP_cert_to_id() failed") - errbuf;
     361           0 :         goto error;
     362             :     }
     363             : 
     364           0 :     if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
     365             :                               &thisupdate, &nextupdate)
     366             :         != 1)
     367             :     {
     368           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     369             :                                     "certificate status not found in the "
     370           0 :                                     "OCSP response") - errbuf;
     371           0 :         goto error;
     372             :     }
     373             : 
     374           0 :     if (n != V_OCSP_CERTSTATUS_GOOD) {
     375           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     376             :                                     "certificate status \"%s\" in the OCSP "
     377             :                                     "response", OCSP_cert_status_str(n))
     378           0 :                        - errbuf;
     379           0 :         goto error;
     380             :     }
     381             : 
     382           0 :     if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
     383           0 :         *errbuf_size = ngx_snprintf(errbuf, *errbuf_size,
     384           0 :                                     "OCSP_check_validity() failed") - errbuf;
     385           0 :         goto error;
     386             :     }
     387             : 
     388           0 :     sk_X509_free(chain);
     389           0 :     X509_free(cert);
     390           0 :     X509_free(issuer);
     391           0 :     BIO_free(bio);
     392           0 :     OCSP_CERTID_free(id);
     393           0 :     OCSP_BASICRESP_free(basic);
     394           0 :     OCSP_RESPONSE_free(ocsp);
     395             : 
     396           0 :     return NGX_OK;
     397             : 
     398           0 : error:
     399             : 
     400           0 :     if (chain) {
     401           0 :         sk_X509_free(chain);
     402             :     }
     403             : 
     404           0 :     if (id) {
     405           0 :         OCSP_CERTID_free(id);
     406             :     }
     407             : 
     408           0 :     if (basic) {
     409           0 :         OCSP_BASICRESP_free(basic);
     410             :     }
     411             : 
     412           0 :     if (ocsp) {
     413           0 :         OCSP_RESPONSE_free(ocsp);
     414             :     }
     415             : 
     416           0 :     if (cert) {
     417           0 :         X509_free(cert);
     418             :     }
     419             : 
     420           0 :     if (issuer) {
     421           0 :         X509_free(issuer);
     422             :     }
     423             : 
     424           0 :     if (bio) {
     425           0 :         BIO_free(bio);
     426             :     }
     427             : 
     428           0 :     ERR_clear_error();
     429             : 
     430           0 :     return NGX_ERROR;
     431             : 
     432             : #endif  /* NGX_HTTP_LUA_USE_OCSP */
     433             : }
     434             : 
     435             : 
     436             : #ifdef NGX_HTTP_LUA_USE_OCSP
     437             : static int
     438           0 : ngx_http_lua_ssl_empty_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
     439             : {
     440           0 :     return SSL_TLSEXT_ERR_OK;
     441             : }
     442             : #endif
     443             : 
     444             : 
     445             : int
     446           0 : ngx_http_lua_ffi_ssl_set_ocsp_status_resp(ngx_http_request_t *r,
     447             :     const u_char *resp, size_t resp_len, char **err)
     448             : {
     449             : #ifndef NGX_HTTP_LUA_USE_OCSP
     450             : 
     451             :     *err = "no OCSP support";
     452             :     return NGX_ERROR;
     453             : 
     454             : #else
     455             : 
     456             :     u_char                  *p;
     457             :     SSL_CTX                 *ctx;
     458             :     ngx_ssl_conn_t          *ssl_conn;
     459             : 
     460           0 :     if (r->connection == NULL || r->connection->ssl == NULL) {
     461           0 :         *err = "bad request";
     462           0 :         return NGX_ERROR;
     463             :     }
     464             : 
     465           0 :     ssl_conn = r->connection->ssl->connection;
     466           0 :     if (ssl_conn == NULL) {
     467           0 :         *err = "bad ssl conn";
     468           0 :         return NGX_ERROR;
     469             :     }
     470             : 
     471           0 :     if (ssl_conn->tlsext_status_type == -1) {
     472             :         dd("no ocsp status req from client");
     473           0 :         return NGX_DECLINED;
     474             :     }
     475             : 
     476             :     /* we have to register an empty status callback here otherwise
     477             :      * OpenSSL won't send the response staple. */
     478             : 
     479           0 :     ctx = SSL_get_SSL_CTX(ssl_conn);
     480           0 :     SSL_CTX_set_tlsext_status_cb(ctx,
     481             :                                  ngx_http_lua_ssl_empty_status_callback);
     482             : 
     483           0 :     p = OPENSSL_malloc(resp_len);
     484           0 :     if (p == NULL) {
     485           0 :         *err = "OPENSSL_malloc() failed";
     486           0 :         return NGX_ERROR;
     487             :     }
     488             : 
     489           0 :     ngx_memcpy(p, resp, resp_len);
     490             : 
     491             :     dd("set ocsp resp: resp_len=%d", (int) resp_len);
     492           0 :     (void) SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, resp_len);
     493             : 
     494           0 :     return NGX_OK;
     495             : 
     496             : #endif  /* NGX_HTTP_LUA_USE_OCSP */
     497             : }
     498             : 
     499             : #endif  /* NGX_LUA_NO_FFI_API */
     500             : 
     501             : 
     502             : #endif  /* NGX_HTTP_SSL */

Generated by: LCOV version 1.13