00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include <openssl/ocsp.h>
00023 #include "P_OCSPStapling.h"
00024 #include "P_Net.h"
00025 #include "P_SSLConfig.h"
00026 
00027 #ifdef HAVE_OPENSSL_OCSP_STAPLING
00028 
00029 
00030 
00031 
00032 #define MAX_STAPLING_DER 10240
00033 
00034 
00035 struct certinfo
00036 {
00037   unsigned char idx[20];  
00038   OCSP_CERTID *cid; 
00039   char *uri;  
00040   ink_mutex stapling_mutex;
00041   unsigned char resp_der[MAX_STAPLING_DER];
00042   unsigned int resp_derlen;
00043   bool is_expire;
00044   time_t expire_time;
00045 };
00046 
00047 void certinfo_free(void * , void *ptr, CRYPTO_EX_DATA * ,
00048     int , long , void * )
00049 {
00050   certinfo *cinf = (certinfo *)ptr;
00051 
00052   if (!cinf)
00053     return;
00054   if (cinf->uri)
00055     OPENSSL_free(cinf->uri);
00056   ink_mutex_destroy(&cinf->stapling_mutex);
00057   OPENSSL_free(cinf);
00058 }
00059 
00060 static int ssl_stapling_index = -1;
00061 
00062 void ssl_stapling_ex_init(void)
00063 {
00064   if (ssl_stapling_index != -1)
00065     return;
00066   ssl_stapling_index = SSL_CTX_get_ex_new_index(0, 0, 0, 0, certinfo_free);
00067 }
00068 
00069 static X509 *
00070 stapling_get_issuer(SSL_CTX *ssl_ctx, X509 *x)
00071 {
00072   X509 *issuer = NULL;
00073   int i;
00074   X509_STORE *st = SSL_CTX_get_cert_store(ssl_ctx);
00075   X509_STORE_CTX inctx;
00076   STACK_OF(X509) *extra_certs = NULL;
00077 
00078 #ifdef SSL_CTX_get_extra_chain_certs
00079   SSL_CTX_get_extra_chain_certs(ssl_ctx, &extra_certs);
00080 #else
00081   extra_certs = ssl_ctx->extra_certs;
00082 #endif
00083 
00084   if (sk_X509_num(extra_certs) == 0)
00085     return NULL;
00086 
00087   for (i = 0; i < sk_X509_num(extra_certs); i++) {
00088     issuer = sk_X509_value(extra_certs, i);
00089     if (X509_check_issued(issuer, x) == X509_V_OK) {
00090       CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
00091       return issuer;
00092     }
00093   }
00094 
00095   if (!X509_STORE_CTX_init(&inctx, st, NULL, NULL))
00096     return NULL;
00097   if (X509_STORE_CTX_get1_issuer(&issuer, &inctx, x) <= 0)
00098     issuer = NULL;
00099   X509_STORE_CTX_cleanup(&inctx);
00100 
00101   return issuer;
00102 }
00103 
00104 bool
00105 ssl_stapling_init_cert(SSL_CTX *ctx, const char *certfile)
00106 {
00107   certinfo *cinf;
00108   X509 *cert = NULL;
00109   X509 *issuer = NULL;
00110   STACK_OF(OPENSSL_STRING) *aia = NULL;
00111   BIO *bio = BIO_new_file(certfile, "r");
00112 
00113   cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
00114   if (!cert) {
00115     Debug("ssl", "can not read cert from certfile %s!", certfile);
00116     return false;
00117   }
00118 
00119   cinf  = (certinfo *)SSL_CTX_get_ex_data(ctx, ssl_stapling_index);
00120   if (cinf) {
00121     Debug("ssl", "certificate already initialized!");
00122     return false;
00123   }
00124 
00125   cinf = (certinfo *)OPENSSL_malloc(sizeof(certinfo));
00126   if (!cinf) {
00127     Debug("ssl", "error allocating memory!");
00128     return false;
00129   }
00130 
00131   
00132   cinf->cid = NULL;
00133   cinf->uri = NULL;
00134   cinf->resp_derlen = 0;
00135   ink_mutex_init(&cinf->stapling_mutex, "stapling_mutex");
00136   cinf->is_expire = true;
00137   cinf->expire_time = 0;
00138 
00139   SSL_CTX_set_ex_data(ctx, ssl_stapling_index, cinf);
00140 
00141   issuer = stapling_get_issuer(ctx, cert);
00142   if (issuer == NULL) {
00143         Debug("ssl", "can not get issuer certificate!");
00144     return false;
00145   }
00146 
00147   cinf->cid = OCSP_cert_to_id(NULL, cert, issuer);
00148   X509_free(issuer);
00149   if (!cinf->cid)
00150     return false;
00151   X509_digest(cert, EVP_sha1(), cinf->idx, NULL);
00152 
00153   aia = X509_get1_ocsp(cert);
00154   if (aia)
00155     cinf->uri = sk_OPENSSL_STRING_pop(aia);
00156   if (!cinf->uri) {
00157         Debug("ssl", "no responder URI");
00158   }
00159   if (aia)
00160     X509_email_free(aia);
00161 
00162   Debug("ssl", "success to init certinfo into SSL_CTX: %p", ctx);
00163   return true;
00164 }
00165 
00166 static certinfo *
00167 stapling_get_cert_info(SSL_CTX *ctx)
00168 {
00169   certinfo *cinf;
00170 
00171   cinf = (certinfo *)SSL_CTX_get_ex_data(ctx, ssl_stapling_index);
00172   if (cinf && cinf->cid)
00173     return cinf;
00174 
00175   return NULL;
00176 }
00177 
00178 static bool
00179 stapling_cache_response(OCSP_RESPONSE *rsp, certinfo *cinf)
00180 {
00181   unsigned char resp_der[MAX_STAPLING_DER];
00182   unsigned char *p;
00183   unsigned int resp_derlen;
00184 
00185   p = resp_der;
00186   resp_derlen = i2d_OCSP_RESPONSE(rsp, &p);
00187 
00188   if (resp_derlen == 0) {
00189     Error("stapling_cache_response: can not encode OCSP stapling response");
00190     return false;
00191   }
00192 
00193   if (resp_derlen > MAX_STAPLING_DER) {
00194     Error("stapling_cache_response: OCSP stapling response too big (%u bytes)", resp_derlen);
00195     return false;
00196   }
00197 
00198   ink_mutex_acquire(&cinf->stapling_mutex);
00199   memcpy(cinf->resp_der, resp_der, resp_derlen);
00200   cinf->resp_derlen = resp_derlen;
00201   cinf->is_expire = false;
00202   cinf->expire_time = time(NULL) + SSLConfigParams::ssl_ocsp_cache_timeout;
00203   ink_mutex_release(&cinf->stapling_mutex);
00204 
00205   Debug("ssl", "stapling_cache_response: success to cache response");
00206   return true;
00207 }
00208 
00209 static int
00210 stapling_check_response(certinfo *cinf, OCSP_RESPONSE *rsp)
00211 {
00212   int status, reason;
00213   OCSP_BASICRESP *bs = NULL;
00214   ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
00215   int response_status = OCSP_response_status(rsp);
00216 
00217   
00218   
00219   if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
00220     return SSL_TLSEXT_ERR_NOACK;
00221   }
00222 
00223   bs = OCSP_response_get1_basic(rsp);
00224   if (bs == NULL) {
00225     
00226     Error("stapling_check_response: can not parsing response");
00227     return SSL_TLSEXT_ERR_OK;
00228   }
00229   if (!OCSP_resp_find_status(bs, cinf->cid, &status, &reason, &rev,
00230         &thisupd, &nextupd)) {
00231     
00232     Error("stapling_check_response: certificate ID not present in response");
00233   } else {
00234     OCSP_check_validity(thisupd, nextupd, 300, -1);
00235   }
00236   OCSP_BASICRESP_free(bs);
00237 
00238   return SSL_TLSEXT_ERR_OK;
00239 }
00240 
00241 static OCSP_RESPONSE *
00242 query_responder(BIO *b, char *host, char *path, OCSP_REQUEST *req, int req_timeout)
00243 {
00244   ink_hrtime start, end;
00245   OCSP_RESPONSE *resp = NULL;
00246   OCSP_REQ_CTX *ctx;
00247   int rv;
00248 
00249   start = ink_get_hrtime();
00250   end = ink_hrtime_add(start, ink_hrtime_from_sec(req_timeout));
00251 
00252   ctx = OCSP_sendreq_new(b, path, NULL, -1);
00253   OCSP_REQ_CTX_add1_header(ctx, "Host", host);
00254   OCSP_REQ_CTX_set1_req(ctx, req);
00255 
00256   do {
00257     rv = OCSP_sendreq_nbio(&resp, ctx);
00258     ink_hrtime_sleep(HRTIME_MSECONDS(1));
00259   } while ((rv == -1) && BIO_should_retry(b) && (ink_get_hrtime() < end));
00260 
00261   OCSP_REQ_CTX_free(ctx);
00262 
00263   if (rv)
00264     return resp;
00265 
00266   return NULL;
00267 }
00268 
00269 static OCSP_RESPONSE *
00270 process_responder(OCSP_REQUEST *req,
00271     char *host, char *path, char *port,
00272     int req_timeout)
00273 {
00274   BIO *cbio = NULL;
00275   OCSP_RESPONSE *resp = NULL;
00276   cbio = BIO_new_connect(host);
00277   if (!cbio) {
00278     goto end;
00279   }
00280   if (port) BIO_set_conn_port(cbio, port);
00281 
00282   BIO_set_nbio(cbio, 1);
00283   if (BIO_do_connect(cbio) <= 0 && !BIO_should_retry(cbio)) {
00284     Debug("ssl", "process_responder: fail to connect to OCSP respond server");
00285     goto end;
00286   }
00287   resp = query_responder(cbio, host, path, req, req_timeout);
00288 
00289 end:
00290   if (cbio)
00291     BIO_free_all(cbio);
00292   return resp;
00293 }
00294 
00295 static bool
00296 stapling_refresh_response(certinfo *cinf, OCSP_RESPONSE **prsp)
00297 {
00298   bool rv = true;
00299   OCSP_REQUEST *req = NULL;
00300   OCSP_CERTID *id = NULL;
00301   char *host, *path, *port;
00302   int ssl_flag = 0;
00303   int req_timeout = -1;
00304 
00305   Debug("ssl", "stapling_refresh_response: querying responder");
00306   *prsp = NULL;
00307 
00308   if (!OCSP_parse_url(cinf->uri, &host, &port, &path, &ssl_flag)) {
00309     goto err;
00310   }
00311 
00312   req = OCSP_REQUEST_new();
00313   if (!req)
00314     goto err;
00315   id = OCSP_CERTID_dup(cinf->cid);
00316   if (!id)
00317     goto err;
00318   if (!OCSP_request_add0_id(req, id))
00319     goto err;
00320 
00321   req_timeout = SSLConfigParams::ssl_ocsp_request_timeout;
00322   *prsp = process_responder(req, host, path, port, req_timeout);
00323 
00324   if (*prsp == NULL) {
00325     goto done;
00326   }
00327 
00328   if (OCSP_response_status(*prsp) == OCSP_RESPONSE_STATUS_SUCCESSFUL) {
00329     Debug("ssl", "stapling_refresh_response: query response received");
00330     stapling_check_response(cinf, *prsp);
00331   } else {
00332     Error("stapling_refresh_response: responder error");
00333   }
00334 
00335   if (!stapling_cache_response(*prsp, cinf)) {
00336     Error("stapling_refresh_response: can not cache response");
00337   } else {
00338     Debug("ssl", "stapling_refresh_response: success to refresh response");
00339   }
00340 
00341 done:
00342   if (req)
00343     OCSP_REQUEST_free(req);
00344   if (*prsp)
00345     OCSP_RESPONSE_free(*prsp);
00346   return rv;
00347 
00348 err:
00349   rv = false;
00350   Debug("ssl", "stapling_refresh_response: fail to refresh response");
00351   goto done;
00352 }
00353 
00354 void
00355 ocsp_update()
00356 {
00357   SSL_CTX *ctx;
00358   certinfo *cinf = NULL;
00359   OCSP_RESPONSE *resp = NULL;
00360   time_t current_time;
00361 
00362   SSLCertificateConfig::scoped_config certLookup;
00363   const unsigned ctxCount = certLookup->count();
00364 
00365   for (unsigned i = 0; i < ctxCount; i++) {
00366     ctx = certLookup->get(i);
00367     cinf = stapling_get_cert_info(ctx);
00368     if (cinf) {
00369       ink_mutex_acquire(&cinf->stapling_mutex);
00370       current_time = time(NULL);
00371       if (cinf->resp_derlen == 0 || cinf->is_expire || cinf->expire_time < current_time) {
00372         ink_mutex_release(&cinf->stapling_mutex);
00373         if (stapling_refresh_response(cinf, &resp)) {
00374           Note("Success to refresh OCSP response for 1 certificate.");
00375         } else {
00376           Note("Fail to refresh OCSP response for 1 certificate.");
00377         }
00378       } else {
00379         ink_mutex_release(&cinf->stapling_mutex);
00380       }
00381     }
00382   }
00383 }
00384 
00385 
00386 int
00387 ssl_callback_ocsp_stapling(SSL *ssl)
00388 {
00389   certinfo *cinf = NULL;
00390   time_t current_time;
00391 
00392   cinf = stapling_get_cert_info(ssl->ctx);
00393   if (cinf == NULL) {
00394     Debug("ssl", "ssl_callback_ocsp_stapling: fail to get certificate information");
00395     return SSL_TLSEXT_ERR_NOACK;
00396   }
00397 
00398   ink_mutex_acquire(&cinf->stapling_mutex);
00399   current_time = time(NULL);
00400   if (cinf->resp_derlen == 0 || cinf->is_expire || cinf->expire_time < current_time) {
00401     ink_mutex_release(&cinf->stapling_mutex);
00402     Debug("ssl", "ssl_callback_ocsp_stapling: fail to get certificate status");
00403     return SSL_TLSEXT_ERR_NOACK;
00404   } else {
00405     unsigned char *p = (unsigned char *)OPENSSL_malloc(cinf->resp_derlen);
00406     unsigned int len = cinf->resp_derlen;
00407     memcpy(p, cinf->resp_der, cinf->resp_derlen);
00408     ink_mutex_release(&cinf->stapling_mutex);
00409     SSL_set_tlsext_status_ocsp_resp(ssl, p, len);
00410     Debug("ssl", "ssl_callback_ocsp_stapling: success to get certificate status");
00411     return SSL_TLSEXT_ERR_OK;
00412   }
00413 }
00414 
00415 #endif