From: Stefan Fritsch Date: Wed, 29 Sep 2010 20:32:23 +0000 (+0000) Subject: Add authz providers for use with mod_authz_core and its RequireAny/RequireAll X-Git-Tag: 2.3.9~391 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8afd97db5f7c89f804058a7081cb3f913d6ec15e;p=apache Add authz providers for use with mod_authz_core and its RequireAny/RequireAll containers: 'ssl' (equivalent to SSLRequireSSL) 'ssl-verify-client' (for use with 'SSLVerifyClient optional') 'ssl-require' (expressions with same syntax as SSLRequire) We may decide to axe 'ssl-require' again in favor of the generic 'expr' provider, depending on the development of the ap_expr parser. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1002837 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 350573e44c..3fc6f0a19b 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,12 @@ Changes with Apache 2.3.9 + *) mod_ssl: Add authz providers for use with mod_authz_core and its + RequireAny/RequireAll containers: 'ssl' (equivalent to SSLRequireSSL), + 'ssl-verify-client' (for use with 'SSLVerifyClient optional'), and + 'ssl-require' (expressions with same syntax as SSLRequire). + [Stefan Fritsch] + *) mod_ssl: Make the ssl expression parser thread-safe. It now requires bison instead of yacc. [Stefan Fritsch] diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 603a00e7c7..aa2dec8401 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -554,6 +554,22 @@ static void ssl_register_hooks(apr_pool_t *p) APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable); APR_REGISTER_OPTIONAL_FN(ssl_engine_disable); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl", + AUTHZ_PROVIDER_VERSION, + &ssl_authz_provider_require_ssl, + AP_AUTH_INTERNAL_PER_CONF); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl-verify-client", + AUTHZ_PROVIDER_VERSION, + &ssl_authz_provider_verify_client, + AP_AUTH_INTERNAL_PER_CONF); + + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl-require", + AUTHZ_PROVIDER_VERSION, + &ssl_authz_provider_sslrequire, + AP_AUTH_INTERNAL_PER_CONF); + } module AP_MODULE_DECLARE_DATA ssl_module = { diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index b9534e56b5..b3dbfef63e 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -1151,7 +1151,7 @@ const char *ssl_cmd_SSLRequire(cmd_parms *cmd, ssl_require_t *require; const char *errstring; - if (!(expr = ssl_expr_comp(cmd->pool, (char *)arg, &errstring))) { + if (!(expr = ssl_expr_comp(cmd->pool, arg, &errstring))) { return apr_pstrcat(cmd->pool, "SSLRequire: ", errstring, NULL); } diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index bc5e64aa09..82fee24dae 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -1202,6 +1202,135 @@ int ssl_hook_Fixup(request_rec *r) return DECLINED; } +/* _________________________________________________________________ +** +** Authz providers for use with mod_authz_core +** _________________________________________________________________ +*/ + +static authz_status ssl_authz_require_ssl_check(request_rec *r, + const char *require_line, + const void *parsed) +{ + SSLConnRec *sslconn = myConnConfig(r->connection); + SSL *ssl = sslconn ? sslconn->ssl : NULL; + + if (ssl) + return AUTHZ_GRANTED; + else + return AUTHZ_DENIED; +} + +static const char *ssl_authz_require_ssl_parse(cmd_parms *cmd, + const char *require_line, + const void **parsed) +{ + if (require_line && require_line[0]) + return "'Require ssl' does not take arguments"; + + return NULL; +} + +const authz_provider ssl_authz_provider_require_ssl = +{ + &ssl_authz_require_ssl_check, + &ssl_authz_require_ssl_parse, +}; + +static authz_status ssl_authz_verify_client_check(request_rec *r, + const char *require_line, + const void *parsed) +{ + SSLConnRec *sslconn = myConnConfig(r->connection); + SSL *ssl = sslconn ? sslconn->ssl : NULL; + + if (!ssl) + return AUTHZ_DENIED; + + if (sslconn->verify_error == NULL && + sslconn->verify_info == NULL && + SSL_get_verify_result(ssl) == X509_V_OK) + { + X509 *xs = SSL_get_peer_certificate(ssl); + + if (xs) { + X509_free(xs); + return AUTHZ_GRANTED; + } + else { + X509_free(xs); + } + } + + return AUTHZ_DENIED; +} + +static const char *ssl_authz_verify_client_parse(cmd_parms *cmd, + const char *require_line, + const void **parsed) +{ + if (require_line && require_line[0]) + return "'Require ssl-verify-client' does not take arguments"; + + return NULL; +} + +const authz_provider ssl_authz_provider_verify_client = +{ + &ssl_authz_verify_client_check, + &ssl_authz_verify_client_parse, +}; + + +static authz_status ssl_authz_sslrequire_check(request_rec *r, + const char *require_line, + const void *parsed) +{ + const ssl_expr *expr = parsed; + const char *errstring; + int ok = ssl_expr_exec(r, expr, &errstring); + + if (ok < 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to execute SSL requirement expression in " + "'Require ssl-require': %s", + errstring); + return AUTHZ_DENIED; + } + + if (ok != 1) { + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "SSL requirement expression in 'Require ssl-require' " + "not fulfilled"); + return AUTHZ_DENIED; + } + + return AUTHZ_GRANTED; +} + +static const char *ssl_authz_sslrequire_parse(cmd_parms *cmd, + const char *require_line, + const void **parsed) +{ + const char *errstring; + ssl_expr *expr = ssl_expr_comp(cmd->pool, require_line, &errstring); + + if (!expr) + return apr_psprintf(cmd->pool, "Error in 'Require require-ssl': %s", + errstring); + + *parsed = expr; + + return NULL; +} + +const authz_provider ssl_authz_provider_sslrequire = +{ + &ssl_authz_sslrequire_check, + &ssl_authz_sslrequire_parse, +}; + + /* _________________________________________________________________ ** ** OpenSSL Callback Functions diff --git a/modules/ssl/ssl_expr.c b/modules/ssl/ssl_expr.c index 32e3feedfb..04262af1ab 100644 --- a/modules/ssl/ssl_expr.c +++ b/modules/ssl/ssl_expr.c @@ -36,7 +36,7 @@ */ -ssl_expr *ssl_expr_comp(apr_pool_t *p, char *expr, const char **err) +ssl_expr *ssl_expr_comp(apr_pool_t *p, const char *expr, const char **err) { ssl_expr_info_type context; int rc; @@ -72,7 +72,7 @@ ssl_expr *ssl_expr_make(ssl_expr_node_op op, void *a1, void *a2, return node; } -int ssl_expr_exec(request_rec *r, ssl_expr *expr, const char **err) +int ssl_expr_exec(request_rec *r, const ssl_expr *expr, const char **err) { BOOL rc; diff --git a/modules/ssl/ssl_expr.h b/modules/ssl/ssl_expr.h index d1391c84e0..049efefd02 100644 --- a/modules/ssl/ssl_expr.h +++ b/modules/ssl/ssl_expr.h @@ -85,9 +85,9 @@ typedef ssl_expr_node ssl_expr; typedef struct { apr_pool_t *pool; - char *inputbuf; + const char *inputbuf; int inputlen; - char *inputptr; + const char *inputptr; ssl_expr *expr; void *scanner; char *error; @@ -99,11 +99,11 @@ int ssl_expr_yylex_init(void **scanner); int ssl_expr_yylex_destroy(void *scanner); void ssl_expr_yyset_extra(ssl_expr_info_type *context, void *scanner); -ssl_expr *ssl_expr_comp(apr_pool_t *p, char *exprstr, const char **err); -int ssl_expr_exec(request_rec *r, ssl_expr *expr, const char **err); +ssl_expr *ssl_expr_comp(apr_pool_t *p, const char *exprstr, const char **err); +int ssl_expr_exec(request_rec *r, const ssl_expr *expr, const char **err); ssl_expr *ssl_expr_make(ssl_expr_node_op op, void *arg1, void *arg2, ssl_expr_info_type *context); -BOOL ssl_expr_eval(request_rec *r, ssl_expr *expr, const char **err); +BOOL ssl_expr_eval(request_rec *r, const ssl_expr *expr, const char **err); #endif /* __SSL_EXPR_H__ */ /** @} */ diff --git a/modules/ssl/ssl_expr_eval.c b/modules/ssl/ssl_expr_eval.c index ccc86e28cd..9480048d89 100644 --- a/modules/ssl/ssl_expr_eval.c +++ b/modules/ssl/ssl_expr_eval.c @@ -41,7 +41,7 @@ static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, static char *ssl_expr_eval_func_file(request_rec *, char *, const char **err); static int ssl_expr_eval_strcmplex(char *, char *, const char **err); -BOOL ssl_expr_eval(request_rec *r, ssl_expr *node, const char **err) +BOOL ssl_expr_eval(request_rec *r, const ssl_expr *node, const char **err) { switch (node->node_op) { case op_True: { diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 5ead74678e..abf34a223b 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -51,6 +51,7 @@ #include "apr_global_mutex.h" #include "apr_optional.h" #include "ap_socache.h" +#include "mod_auth.h" #define MOD_SSL_VERSION AP_SERVER_BASEREVISION @@ -613,6 +614,11 @@ int ssl_hook_ReadReq(request_rec *); int ssl_hook_Upgrade(request_rec *); void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s); +/** Apache authz provisders */ +extern const authz_provider ssl_authz_provider_require_ssl; +extern const authz_provider ssl_authz_provider_verify_client; +extern const authz_provider ssl_authz_provider_sslrequire; + /** OpenSSL callbacks */ RSA *ssl_callback_TmpRSA(SSL *, int, int); DH *ssl_callback_TmpDH(SSL *, int, int);