📄 ssl_engine_kernel.c
字号:
* | multiple transactions, it must be signed each time it is used. * | * | RSA key generation is a time-consuming process. In many cases, a * | low-priority process can be assigned the task of key generation. * | Whenever a new key is completed, the existing temporary key can be * | replaced with the new one. * * XXX: base on comment above, if thread support is enabled, * we should spawn a low-priority thread to generate new keys * on the fly. * * So we generated 512 and 1024 bit temporary keys on startup * which we now just hand out on demand.... */RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen){ conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); SSLModConfigRec *mc = myModConfig(c->base_server); int idx; ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "handing out temporary %d bit RSA key", keylen); /* doesn't matter if export flag is on, * we won't be asked for keylen > 512 in that case. * if we are asked for a keylen > 1024, it is too expensive * to generate on the fly. * XXX: any reason not to generate 2048 bit keys at startup? */ switch (keylen) { case 512: idx = SSL_TMP_KEY_RSA_512; break; case 1024: default: idx = SSL_TMP_KEY_RSA_1024; } return (RSA *)mc->pTmpKeys[idx];}/* * Hand out the already generated DH parameters... */DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen){ conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); SSLModConfigRec *mc = myModConfig(c->base_server); int idx; ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "handing out temporary %d bit DH key", keylen); switch (keylen) { case 512: idx = SSL_TMP_KEY_DH_512; break; case 1024: default: idx = SSL_TMP_KEY_DH_1024; } return (DH *)mc->pTmpKeys[idx];}/* * This OpenSSL callback function is called when OpenSSL * does client authentication and verifies the certificate chain. */int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx){ /* Get Apache context back through OpenSSL context */ SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); conn_rec *conn = (conn_rec *)SSL_get_app_data(ssl); server_rec *s = conn->base_server; request_rec *r = (request_rec *)SSL_get_app_data2(ssl); SSLSrvConfigRec *sc = mySrvConfig(s); SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL; SSLConnRec *sslconn = myConnConfig(conn); modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); /* Get verify ingredients */ int errnum = X509_STORE_CTX_get_error(ctx); int errdepth = X509_STORE_CTX_get_error_depth(ctx); int depth, verify; /* * Log verification information */ if (s->loglevel >= APLOG_DEBUG) { X509 *cert = X509_STORE_CTX_get_current_cert(ctx); char *sname = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); char *iname = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Certificate Verification: " "depth: %d, subject: %s, issuer: %s", errdepth, sname ? sname : "-unknown-", iname ? iname : "-unknown-"); if (sname) { modssl_free(sname); } if (iname) { modssl_free(iname); } } /* * Check for optionally acceptable non-verifiable issuer situation */ if (dc && (dc->nVerifyClient != SSL_CVERIFY_UNSET)) { verify = dc->nVerifyClient; } else { verify = mctx->auth.verify_mode; } if (verify == SSL_CVERIFY_NONE) { /* * SSLProxyVerify is either not configured or set to "none". * (this callback doesn't happen in the server context if SSLVerify * is not configured or set to "none") */ return TRUE; } if (ssl_verify_error_is_optional(errnum) && (verify == SSL_CVERIFY_OPTIONAL_NO_CA)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Certificate Verification: Verifiable Issuer is " "configured as optional, therefore we're accepting " "the certificate"); sslconn->verify_info = "GENEROUS"; ok = TRUE; } /* * Additionally perform CRL-based revocation checks */ if (ok) { if (!(ok = ssl_callback_SSLVerify_CRL(ok, ctx, conn))) { errnum = X509_STORE_CTX_get_error(ctx); } } /* * If we already know it's not ok, log the real reason */ if (!ok) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Certificate Verification: Error (%d): %s", errnum, X509_verify_cert_error_string(errnum)); if (sslconn->client_cert) { X509_free(sslconn->client_cert); sslconn->client_cert = NULL; } sslconn->client_dn = NULL; sslconn->verify_error = X509_verify_cert_error_string(errnum); } /* * Finally check the depth of the certificate verification */ if (dc && (dc->nVerifyDepth != UNSET)) { depth = dc->nVerifyDepth; } else { depth = mctx->auth.verify_depth; } if (errdepth > depth) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Certificate Verification: Certificate Chain too long " "(chain has %d certificates, but maximum allowed are " "only %d)", errdepth, depth); errnum = X509_V_ERR_CERT_CHAIN_TOO_LONG; sslconn->verify_error = X509_verify_cert_error_string(errnum); ok = FALSE; } /* * And finally signal OpenSSL the (perhaps changed) state */ return ok;}int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c){ server_rec *s = c->base_server; SSLSrvConfigRec *sc = mySrvConfig(s); SSLConnRec *sslconn = myConnConfig(c); modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); X509_OBJECT obj; X509_NAME *subject, *issuer; X509 *cert; X509_CRL *crl; EVP_PKEY *pubkey; int i, n, rc; /* * Unless a revocation store for CRLs was created we * cannot do any CRL-based verification, of course. */ if (!mctx->crl) { return ok; } /* * Determine certificate ingredients in advance */ cert = X509_STORE_CTX_get_current_cert(ctx); subject = X509_get_subject_name(cert); issuer = X509_get_issuer_name(cert); /* * OpenSSL provides the general mechanism to deal with CRLs but does not * use them automatically when verifying certificates, so we do it * explicitly here. We will check the CRL for the currently checked * certificate, if there is such a CRL in the store. * * We come through this procedure for each certificate in the certificate * chain, starting with the root-CA's certificate. At each step we've to * both verify the signature on the CRL (to make sure it's a valid CRL) * and it's revocation list (to make sure the current certificate isn't * revoked). But because to check the signature on the CRL we need the * public key of the issuing CA certificate (which was already processed * one round before), we've a little problem. But we can both solve it and * at the same time optimize the processing by using the following * verification scheme (idea and code snippets borrowed from the GLOBUS * project): * * 1. We'll check the signature of a CRL in each step when we find a CRL * through the _subject_ name of the current certificate. This CRL * itself will be needed the first time in the next round, of course. * But we do the signature processing one round before this where the * public key of the CA is available. * * 2. We'll check the revocation list of a CRL in each step when * we find a CRL through the _issuer_ name of the current certificate. * This CRLs signature was then already verified one round before. * * This verification scheme allows a CA to revoke its own certificate as * well, of course. */ /* * Try to retrieve a CRL corresponding to the _subject_ of * the current certificate in order to verify it's integrity. */ memset((char *)&obj, 0, sizeof(obj)); rc = SSL_X509_STORE_lookup(mctx->crl, X509_LU_CRL, subject, &obj); crl = obj.data.crl; if ((rc > 0) && crl) { /* * Log information about CRL * (A little bit complicated because of ASN.1 and BIOs...) */ if (s->loglevel >= APLOG_DEBUG) { char buff[512]; /* should be plenty */ BIO *bio = BIO_new(BIO_s_mem()); BIO_printf(bio, "CA CRL: Issuer: "); X509_NAME_print(bio, issuer, 0); BIO_printf(bio, ", lastUpdate: "); ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl)); BIO_printf(bio, ", nextUpdate: "); ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl)); n = BIO_read(bio, buff, sizeof(buff) - 1); buff[n] = '\0'; BIO_free(bio); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "%s", buff); } /* * Verify the signature on this CRL */ pubkey = X509_get_pubkey(cert); rc = X509_CRL_verify(crl, pubkey);#ifdef OPENSSL_VERSION_NUMBER /* Only refcounted in OpenSSL */ if (pubkey) EVP_PKEY_free(pubkey);#endif if (rc <= 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "Invalid signature on CRL"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); X509_OBJECT_free_contents(&obj); return FALSE; } /* * Check date of CRL to make sure it's not expired */ i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl)); if (i == 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "Found CRL has invalid nextUpdate field"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); X509_OBJECT_free_contents(&obj); return FALSE; } if (i < 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "Found CRL is expired - " "revoking all certificates until you get updated CRL"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED); X509_OBJECT_free_contents(&obj); return FALSE; } X509_OBJECT_free_contents(&obj); } /* * Try to retrieve a CRL corresponding to the _issuer_ of * the current certificate in order to check for revocation. */ memset((char *)&obj, 0, sizeof(obj)); rc = SSL_X509_STORE_lookup(mctx->crl, X509_LU_CRL, issuer, &obj); crl = obj.data.crl; if ((rc > 0) && crl) { /* * Check if the current certificate is revoked by this CRL */ n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); for (i = 0; i < n; i++) { X509_REVOKED *revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -