📄 ssl_engine_kernel.c
字号:
val = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_SERVER_CERT"); ap_table_set(e, "SSL_SERVER_CERT", val); val = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_CERT"); ap_table_set(e, "SSL_CLIENT_CERT", val); if ((sk = SSL_get_peer_cert_chain(ssl)) != NULL) { for (i = 0; i < sk_X509_num(sk); i++) { var = ap_psprintf(r->pool, "SSL_CLIENT_CERT_CHAIN_%d", i); val = ssl_var_lookup(r->pool, r->server, r->connection, r, var); if (val != NULL) ap_table_set(e, var, val); } } } /* * On-demand bloat up the SSI/CGI environment with compat variables */#ifdef SSL_COMPAT if (dc->nOptions & SSL_OPT_COMPATENVVARS) ssl_compat_variables(r);#endif return DECLINED;}/* _________________________________________________________________**** OpenSSL Callback Functions** _________________________________________________________________*//* * Handle out temporary RSA private keys on demand * * The background of this as the TLSv1 standard explains it: * * | D.1. Temporary RSA keys * | * | US Export restrictions limit RSA keys used for encryption to 512 * | bits, but do not place any limit on lengths of RSA keys used for * | signing operations. Certificates often need to be larger than 512 * | bits, since 512-bit RSA keys are not secure enough for high-value * | transactions or for applications requiring long-term security. Some * | certificates are also designated signing-only, in which case they * | cannot be used for key exchange. * | * | When the public key in the certificate cannot be used for encryption, * | the server signs a temporary RSA key, which is then exchanged. In * | exportable applications, the temporary RSA key should be the maximum * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are * | relatively insecure, they should be changed often. For typical * | electronic commerce applications, it is suggested that keys be * | changed daily or every 500 transactions, and more often if possible. * | Note that while it is acceptable to use the same temporary key for * | 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. * * So we generated 512 and 1024 bit temporary keys on startup * which we now just handle out on demand.... */RSA *ssl_callback_TmpRSA(SSL *pSSL, int nExport, int nKeyLen){ SSLModConfigRec *mc = myModConfig(); RSA *rsa; rsa = NULL; if (nExport) { /* It's because an export cipher is used */ if (nKeyLen == 512) rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA512]; else if (nKeyLen == 1024) rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024]; else /* it's too expensive to generate on-the-fly, so keep 1024bit */ rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024]; } else { /* It's because a sign-only certificate situation exists */ rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024]; } return rsa;}/* * Handle out the already generated DH parameters... */DH *ssl_callback_TmpDH(SSL *pSSL, int nExport, int nKeyLen){ SSLModConfigRec *mc = myModConfig(); DH *dh; dh = NULL; if (nExport) { /* It's because an export cipher is used */ if (nKeyLen == 512) dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH512]; else if (nKeyLen == 1024) dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024]; else /* it's too expensive to generate on-the-fly, so keep 1024bit */ dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024]; } else { /* It's because a sign-only certificate situation exists */ dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024]; } return dh;}/* * 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){ SSL *ssl; conn_rec *conn; server_rec *s; request_rec *r; SSLSrvConfigRec *sc; SSLDirConfigRec *dc; ap_ctx *actx; X509 *xs; int errnum; int errdepth; char *cp; char *cp2; int depth; int verify; /* * Get Apache context back through OpenSSL context */ ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx); conn = (conn_rec *)SSL_get_app_data(ssl); actx = (ap_ctx *)SSL_get_app_data2(ssl); r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec"); s = conn->server; sc = mySrvConfig(s); dc = (r != NULL ? myDirConfig(r) : NULL); /* * Get verify ingredients */ xs = X509_STORE_CTX_get_current_cert(ctx); errnum = X509_STORE_CTX_get_error(ctx); errdepth = X509_STORE_CTX_get_error_depth(ctx); /* * Log verification information */ cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0); cp2 = X509_NAME_oneline(X509_get_issuer_name(xs), NULL, 0); ssl_log(s, SSL_LOG_TRACE, "Certificate Verification: depth: %d, subject: %s, issuer: %s", errdepth, cp != NULL ? cp : "-unknown-", cp2 != NULL ? cp2 : "-unknown"); if (cp) OPENSSL_free(cp); if (cp2) OPENSSL_free(cp2); /* * Check for optionally acceptable non-verifiable issuer situation */ if (dc != NULL && dc->nVerifyClient != SSL_CVERIFY_UNSET) verify = dc->nVerifyClient; else verify = sc->nVerifyClient; if ( ( errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY#if SSL_LIBRARY_VERSION >= 0x00905000 || errnum == X509_V_ERR_CERT_UNTRUSTED#endif || errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE ) && verify == SSL_CVERIFY_OPTIONAL_NO_CA ) { ssl_log(s, SSL_LOG_TRACE, "Certificate Verification: Verifiable Issuer is configured as " "optional, therefore we're accepting the certificate"); ap_ctx_set(conn->client->ctx, "ssl::verify::info", "GENEROUS"); SSL_set_verify_result(ssl, X509_V_OK); ok = TRUE; } /* * Additionally perform CRL-based revocation checks */ if (ok) { ok = ssl_callback_SSLVerify_CRL(ok, ctx, s); if (!ok) errnum = X509_STORE_CTX_get_error(ctx); } /* * If we already know it's not ok, log the real reason */ if (!ok) { ssl_log(s, SSL_LOG_ERROR, "Certificate Verification: Error (%d): %s", errnum, X509_verify_cert_error_string(errnum)); ap_ctx_set(conn->client->ctx, "ssl::client::dn", NULL); ap_ctx_set(conn->client->ctx, "ssl::verify::error", (void *)X509_verify_cert_error_string(errnum)); } /* * Finally check the depth of the certificate verification */ if (dc != NULL && dc->nVerifyDepth != UNSET) depth = dc->nVerifyDepth; else depth = sc->nVerifyDepth; if (errdepth > depth) { ssl_log(s, SSL_LOG_ERROR, "Certificate Verification: Certificate Chain too long " "(chain has %d certificates, but maximum allowed are only %d)", errdepth, depth); ap_ctx_set(conn->client->ctx, "ssl::verify::error", (void *)X509_verify_cert_error_string(X509_V_ERR_CERT_CHAIN_TOO_LONG)); ok = FALSE; } /* * And finally signal OpenSSL the (perhaps changed) state */ return (ok);}int ssl_callback_SSLVerify_CRL( int ok, X509_STORE_CTX *ctx, server_rec *s){ SSLSrvConfigRec *sc; X509_OBJECT obj; X509_NAME *subject; X509_NAME *issuer; X509 *xs; X509_CRL *crl; X509_REVOKED *revoked; EVP_PKEY *pubkey; long serial; BIO *bio; int i, n, rc; char *cp; char *cp2; ASN1_TIME *t; /* * Unless a revocation store for CRLs was created we * cannot do any CRL-based verification, of course. */ sc = mySrvConfig(s); if (sc->pRevocationStore == NULL) return ok; /* * Determine certificate ingredients in advance */ xs = X509_STORE_CTX_get_current_cert(ctx); subject = X509_get_subject_name(xs); issuer = X509_get_issuer_name(xs); /* * 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(sc->pRevocationStore, X509_LU_CRL, subject, &obj); crl = obj.data.crl; if (rc > 0 && crl != NULL) { /* * Log information about CRL * (A little bit complicated because of ASN.1 and BIOs...) */ if (ssl_log_applies(s, SSL_LOG_TRACE)) { bio = BIO_new(BIO_s_mem()); 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_pending(bio); cp = malloc(n+1); n = BIO_read(bio, cp, n); cp[n] = NUL; BIO_free(bio); cp2 = X509_NAME_oneline(subject, NULL, 0); ssl_log(s, SSL_LOG_TRACE, "CA CRL: Issuer: %s, %s", cp2, cp); OPENSSL_free(cp2); free(cp); } /* * Verify the signature on this CRL */ pubkey = X509_get_pubkey(xs); if (X509_CRL_verify(crl, pubkey) <= 0) { ssl_log(s, SSL_LOG_WARN, "Invalid signature on CRL"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); X509_OBJECT_free_contents(&obj); if (pubkey != NULL) EVP_PKEY_free(pubkey); return FALSE; } if (pubkey != NULL) EVP_PKEY_f
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -