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 #include "P_SSLUtils.h"
00027
00028 #ifdef HAVE_OPENSSL_OCSP_STAPLING
00029
00030
00031
00032
00033 #define MAX_STAPLING_DER 10240
00034
00035
00036 struct certinfo
00037 {
00038 unsigned char idx[20];
00039 OCSP_CERTID *cid;
00040 char *uri;
00041 ink_mutex stapling_mutex;
00042 unsigned char resp_der[MAX_STAPLING_DER];
00043 unsigned int resp_derlen;
00044 bool is_expire;
00045 time_t expire_time;
00046 };
00047
00048 void certinfo_free(void * , void *ptr, CRYPTO_EX_DATA * ,
00049 int , long , void * )
00050 {
00051 certinfo *cinf = (certinfo *)ptr;
00052
00053 if (!cinf)
00054 return;
00055 if (cinf->uri)
00056 OPENSSL_free(cinf->uri);
00057 ink_mutex_destroy(&cinf->stapling_mutex);
00058 OPENSSL_free(cinf);
00059 }
00060
00061 static int ssl_stapling_index = -1;
00062
00063 void ssl_stapling_ex_init(void)
00064 {
00065 if (ssl_stapling_index != -1)
00066 return;
00067 ssl_stapling_index = SSL_CTX_get_ex_new_index(0, 0, 0, 0, certinfo_free);
00068 }
00069
00070 static X509 *
00071 stapling_get_issuer(SSL_CTX *ssl_ctx, X509 *x)
00072 {
00073 X509 *issuer = NULL;
00074 int i;
00075 X509_STORE *st = SSL_CTX_get_cert_store(ssl_ctx);
00076 X509_STORE_CTX inctx;
00077 STACK_OF(X509) *extra_certs = NULL;
00078
00079 #ifdef SSL_CTX_get_extra_chain_certs
00080 SSL_CTX_get_extra_chain_certs(ssl_ctx, &extra_certs);
00081 #else
00082 extra_certs = ssl_ctx->extra_certs;
00083 #endif
00084
00085 if (sk_X509_num(extra_certs) == 0)
00086 return NULL;
00087
00088 for (i = 0; i < sk_X509_num(extra_certs); i++) {
00089 issuer = sk_X509_value(extra_certs, i);
00090 if (X509_check_issued(issuer, x) == X509_V_OK) {
00091 CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
00092 return issuer;
00093 }
00094 }
00095
00096 if (!X509_STORE_CTX_init(&inctx, st, NULL, NULL))
00097 return NULL;
00098 if (X509_STORE_CTX_get1_issuer(&issuer, &inctx, x) <= 0)
00099 issuer = NULL;
00100 X509_STORE_CTX_cleanup(&inctx);
00101
00102 return issuer;
00103 }
00104
00105 bool
00106 ssl_stapling_init_cert(SSL_CTX *ctx, const char *certfile)
00107 {
00108 certinfo *cinf;
00109 scoped_X509 cert;
00110 scoped_X509 issuer;
00111 STACK_OF(OPENSSL_STRING) *aia = NULL;
00112 scoped_BIO bio(BIO_new_file(certfile, "r"));
00113
00114 cert = PEM_read_bio_X509_AUX(bio.get(), NULL, NULL, NULL);
00115 if (!cert) {
00116 Debug("ssl", "can not read cert from certfile %s!", certfile);
00117 return false;
00118 }
00119
00120 cinf = (certinfo *)SSL_CTX_get_ex_data(ctx, ssl_stapling_index);
00121 if (cinf) {
00122 Debug("ssl", "certificate already initialized!");
00123 return false;
00124 }
00125
00126 cinf = (certinfo *)OPENSSL_malloc(sizeof(certinfo));
00127 if (!cinf) {
00128 Debug("ssl", "error allocating memory!");
00129 return false;
00130 }
00131
00132
00133 cinf->cid = NULL;
00134 cinf->uri = NULL;
00135 cinf->resp_derlen = 0;
00136 ink_mutex_init(&cinf->stapling_mutex, "stapling_mutex");
00137 cinf->is_expire = true;
00138 cinf->expire_time = 0;
00139
00140 SSL_CTX_set_ex_data(ctx, ssl_stapling_index, cinf);
00141
00142 issuer = stapling_get_issuer(ctx, cert);
00143 if (issuer == NULL) {
00144 Debug("ssl", "can not get issuer certificate!");
00145 return false;
00146 }
00147
00148 cinf->cid = OCSP_cert_to_id(NULL, cert, 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