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