📄 ssl_engine_kernel.c
字号:
pRequirement = &pRequirements[i]; ok = ssl_expr_exec(r, pRequirement->mpExpr); if (ok < 0) { cp = ap_psprintf(r->pool, "Failed to execute SSL requirement expression: %s", ssl_expr_get_error()); ap_log_reason(cp, r->filename, r); /* remember forbidden access for strict require option */ ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1); return FORBIDDEN; } if (ok != 1) { ssl_log(r->server, SSL_LOG_INFO, "Access to %s denied for %s (requirement expression not fulfilled)", r->filename, r->connection->remote_ip); ssl_log(r->server, SSL_LOG_INFO, "Failed expression: %s", pRequirement->cpExpr); ap_log_reason("SSL requirement expression not fulfilled " "(see SSL logfile for more details)", r->filename, r); /* remember forbidden access for strict require option */ ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1); return FORBIDDEN; } } /* * Else access is granted... * (except vendor handlers override) */ rc = OK;#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::access_handler", AP_HOOK_SIG2(int,ptr), AP_HOOK_DECLINE(DECLINED), &rc, r);#endif return rc;}/* * Auth Handler: * Fake a Basic authentication from the X509 client certificate. * * This must be run fairly early on to prevent a real authentication from * occuring, in particular it must be run before anything else that * authenticates a user. This means that the Module statement for this * module should be LAST in the Configuration file. */int ssl_hook_Auth(request_rec *r){ SSLSrvConfigRec *sc = mySrvConfig(r->server); SSLDirConfigRec *dc = myDirConfig(r); char b1[MAX_STRING_LEN], b2[MAX_STRING_LEN]; char *clientdn; /* * Additionally forbid access (again) * when strict require option is used. */ if ( (dc->nOptions & SSL_OPT_STRICTREQUIRE) && (ap_table_get(r->notes, "ssl-access-forbidden") != NULL)) return FORBIDDEN; /* * We decline operation in various situations... */ if (!sc->bEnabled) return DECLINED; if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL) return DECLINED; if (!(dc->nOptions & SSL_OPT_FAKEBASICAUTH)) return DECLINED; if (r->connection->user) return DECLINED; if ((clientdn = (char *)ap_ctx_get(r->connection->client->ctx, "ssl::client::dn")) == NULL) return DECLINED; /* * Fake a password - which one would be immaterial, as, it seems, an empty * password in the users file would match ALL incoming passwords, if only * we were using the standard crypt library routine. Unfortunately, OpenSSL * "fixes" a "bug" in crypt and thus prevents blank passwords from * working. (IMHO what they really fix is a bug in the users of the code * - failing to program correctly for shadow passwords). We need, * therefore, to provide a password. This password can be matched by * adding the string "xxj31ZMTZzkVA" as the password in the user file. * This is just the crypted variant of the word "password" ;-) */ ap_snprintf(b1, sizeof(b1), "%s:password", clientdn); ssl_util_uuencode(b2, b1, FALSE); ap_snprintf(b1, sizeof(b1), "Basic %s", b2); ap_table_set(r->headers_in, "Authorization", b1); ssl_log(r->server, SSL_LOG_INFO, "Faking HTTP Basic Auth header: \"Authorization: %s\"", b1); return DECLINED;}int ssl_hook_UserCheck(request_rec *r){ SSLDirConfigRec *dc = myDirConfig(r); /* * Additionally forbid access (again) * when strict require option is used. */ if ( (dc->nOptions & SSL_OPT_STRICTREQUIRE) && (ap_table_get(r->notes, "ssl-access-forbidden") != NULL)) return FORBIDDEN; return DECLINED;}/* * Fixup Handler */static const char *ssl_hook_Fixup_vars[] = { "SSL_VERSION_INTERFACE", "SSL_VERSION_LIBRARY", "SSL_PROTOCOL", "SSL_CIPHER", "SSL_CIPHER_EXPORT", "SSL_CIPHER_USEKEYSIZE", "SSL_CIPHER_ALGKEYSIZE", "SSL_CLIENT_VERIFY", "SSL_CLIENT_M_VERSION", "SSL_CLIENT_M_SERIAL", "SSL_CLIENT_V_START", "SSL_CLIENT_V_END", "SSL_CLIENT_S_DN", "SSL_CLIENT_S_DN_C", "SSL_CLIENT_S_DN_ST", "SSL_CLIENT_S_DN_L", "SSL_CLIENT_S_DN_O", "SSL_CLIENT_S_DN_OU", "SSL_CLIENT_S_DN_CN", "SSL_CLIENT_S_DN_T", "SSL_CLIENT_S_DN_I", "SSL_CLIENT_S_DN_G", "SSL_CLIENT_S_DN_S", "SSL_CLIENT_S_DN_D", "SSL_CLIENT_S_DN_UID", "SSL_CLIENT_S_DN_Email", "SSL_CLIENT_I_DN", "SSL_CLIENT_I_DN_C", "SSL_CLIENT_I_DN_ST", "SSL_CLIENT_I_DN_L", "SSL_CLIENT_I_DN_O", "SSL_CLIENT_I_DN_OU", "SSL_CLIENT_I_DN_CN", "SSL_CLIENT_I_DN_T", "SSL_CLIENT_I_DN_I", "SSL_CLIENT_I_DN_G", "SSL_CLIENT_I_DN_S", "SSL_CLIENT_I_DN_D", "SSL_CLIENT_I_DN_UID", "SSL_CLIENT_I_DN_Email", "SSL_CLIENT_A_KEY", "SSL_CLIENT_A_SIG", "SSL_SERVER_M_VERSION", "SSL_SERVER_M_SERIAL", "SSL_SERVER_V_START", "SSL_SERVER_V_END", "SSL_SERVER_S_DN", "SSL_SERVER_S_DN_C", "SSL_SERVER_S_DN_ST", "SSL_SERVER_S_DN_L", "SSL_SERVER_S_DN_O", "SSL_SERVER_S_DN_OU", "SSL_SERVER_S_DN_CN", "SSL_SERVER_S_DN_T", "SSL_SERVER_S_DN_I", "SSL_SERVER_S_DN_G", "SSL_SERVER_S_DN_S", "SSL_SERVER_S_DN_D", "SSL_SERVER_S_DN_UID", "SSL_SERVER_S_DN_Email", "SSL_SERVER_I_DN", "SSL_SERVER_I_DN_C", "SSL_SERVER_I_DN_ST", "SSL_SERVER_I_DN_L", "SSL_SERVER_I_DN_O", "SSL_SERVER_I_DN_OU", "SSL_SERVER_I_DN_CN", "SSL_SERVER_I_DN_T", "SSL_SERVER_I_DN_I", "SSL_SERVER_I_DN_G", "SSL_SERVER_I_DN_S", "SSL_SERVER_I_DN_D", "SSL_SERVER_I_DN_UID", "SSL_SERVER_I_DN_Email", "SSL_SERVER_A_KEY", "SSL_SERVER_A_SIG", "SSL_SESSION_ID", NULL};int ssl_hook_Fixup(request_rec *r){ SSLSrvConfigRec *sc = mySrvConfig(r->server); SSLDirConfigRec *dc = myDirConfig(r); table *e = r->subprocess_env; char *var; char *val; STACK_OF(X509) *sk; SSL *ssl; int i; /* * Check to see if SSL is on */ if (!sc->bEnabled) return DECLINED; if ((ssl = ap_ctx_get(r->connection->client->ctx, "ssl")) == NULL) return DECLINED; /* * Annotate the SSI/CGI environment with standard SSL information */ /* the always present HTTPS (=HTTP over SSL) flag! */ ap_table_set(e, "HTTPS", "on"); /* standard SSL environment variables */ if (dc->nOptions & SSL_OPT_STDENVVARS) { for (i = 0; ssl_hook_Fixup_vars[i] != NULL; i++) { var = (char *)ssl_hook_Fixup_vars[i]; val = ssl_var_lookup(r->pool, r->server, r->connection, r, var); if (!strIsEmpty(val)) ap_table_set(e, var, val); } } /* * On-demand bloat up the SSI/CGI environment with certificate data */ if (dc->nOptions & SSL_OPT_EXPORTCERTDATA) { 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -