Author: jkaluza Date: Wed Feb 20 11:40:50 2013 New Revision: 1448098 URL: http://svn.apache.org/r1448098 Log: Add new authz/authn API defined in httpd-2.4. It adds new directives PerlAddAuthzProvider/PerlAddAuthnProvider to register providers and RequestUtil::register_auth_provider method.
This commit is initial try to port this new API to mod_perl and it definitely needs a review. Modified: perl/modperl/branches/httpd24/lib/Apache2/ParseSource.pm perl/modperl/branches/httpd24/lib/ModPerl/Code.pm perl/modperl/branches/httpd24/src/modules/perl/mod_perl.c perl/modperl/branches/httpd24/src/modules/perl/modperl_apache_includes.h perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.c perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.h perl/modperl/branches/httpd24/src/modules/perl/modperl_util.c perl/modperl/branches/httpd24/src/modules/perl/modperl_util.h perl/modperl/branches/httpd24/xs/Apache2/RequestUtil/Apache2__RequestUtil.h perl/modperl/branches/httpd24/xs/maps/apache2_functions.map Modified: perl/modperl/branches/httpd24/lib/Apache2/ParseSource.pm URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/lib/Apache2/ParseSource.pm?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/lib/Apache2/ParseSource.pm (original) +++ perl/modperl/branches/httpd24/lib/Apache2/ParseSource.pm Wed Feb 20 11:40:50 2013 @@ -255,6 +255,7 @@ my %defines_wanted = ( remotehost => [qw{REMOTE_}], satisfy => [qw{SATISFY_}], types => [qw{DIR_MAGIC_TYPE}], + auth => [qw{AUTHN_ AUTHZ AP_AUTH_ AUTH_ AUTHZ_}], }, 'APR::Const' => { common => [qw{APR_SUCCESS}], @@ -287,7 +288,7 @@ while (my ($class, $groups) = each %defi } my %enums_wanted = ( - 'Apache2::Const' => { map { $_, 1 } qw(cmd_how input_mode filter_type conn_keepalive) }, + 'Apache2::Const' => { map { $_, 1 } qw(cmd_how input_mode filter_type conn_keepalive authn_status authz_status) }, 'APR::Const' => { map { $_, 1 } qw(apr_shutdown_how apr_read_type apr_lockmech) }, ); Modified: perl/modperl/branches/httpd24/lib/ModPerl/Code.pm URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/lib/ModPerl/Code.pm?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/lib/ModPerl/Code.pm (original) +++ perl/modperl/branches/httpd24/lib/ModPerl/Code.pm Wed Feb 20 11:40:50 2013 @@ -891,6 +891,15 @@ EOF if ($name eq 'DECLINE_CMD' || $name eq 'DIR_MAGIC_TYPE' || $name eq 'CRLF' || + $name eq 'AUTHN_PROVIDER_GROUP' || + $name eq 'AUTHZ_PROVIDER_GROUP' || + $name eq 'AUTHN_PROVIDER_VERSION' || + $name eq 'AUTHZ_PROVIDER_VERSION' || + $name eq 'AUTHN_DEFAULT_PROVIDER' || + $name eq 'AUTHN_PROVIDER_NAME_NOTE' || + $name eq 'AUTHZ_PROVIDER_NAME_NOTE' || + $name eq 'AUTHN_PREFIX' || + $name eq 'AUTHZ_PREFIX' || $name eq 'CRLF_ASCII') { print $c_fh <<EOF; return newSVpv($alias{$name}, 0); Modified: perl/modperl/branches/httpd24/src/modules/perl/mod_perl.c URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/src/modules/perl/mod_perl.c?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/src/modules/perl/mod_perl.c (original) +++ perl/modperl/branches/httpd24/src/modules/perl/mod_perl.c Wed Feb 20 11:40:50 2013 @@ -911,6 +911,8 @@ static const command_rec modperl_cmds[] MP_CMD_DIR_ITERATE("PerlRequire", requires, "PerlRequire"), MP_CMD_SRV_ITERATE("PerlConfigRequire", config_requires, "PerlConfigRequire"), MP_CMD_SRV_ITERATE("PerlPostConfigRequire", post_config_requires, "PerlPostConfigRequire"), + MP_CMD_SRV_TAKE2("PerlAddAuthzProvider", authz_provider, "PerlAddAuthzProvider"), + MP_CMD_SRV_TAKE2("PerlAddAuthnProvider", authn_provider, "PerlAddAuthnProvider"), MP_CMD_DIR_ITERATE("PerlOptions", options, "Perl Options"), MP_CMD_DIR_ITERATE("PerlInitHandler", init_handlers, "Subroutine name"), MP_CMD_DIR_TAKE2("PerlSetVar", set_var, "PerlSetVar"), Modified: perl/modperl/branches/httpd24/src/modules/perl/modperl_apache_includes.h URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/src/modules/perl/modperl_apache_includes.h?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/src/modules/perl/modperl_apache_includes.h (original) +++ perl/modperl/branches/httpd24/src/modules/perl/modperl_apache_includes.h Wed Feb 20 11:40:50 2013 @@ -43,4 +43,9 @@ APLOG_USE_MODULE(perl); #endif +#if AP_SERVER_MAJORVERSION_NUMBER>2 || \ + (AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER>=3) +#include "mod_auth.h" +#endif + #endif /* MODPERL_APACHE_INCLUDES_H */ Modified: perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.c URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.c?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.c (original) +++ perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.c Wed Feb 20 11:40:50 2013 @@ -417,6 +417,30 @@ MP_CMD_SRV_DECLARE(init_handlers) return modperl_cmd_post_read_request_handlers(parms, mconfig, arg); } +MP_CMD_SRV_DECLARE2(authz_provider) +{ + apr_pool_t *p = parms->server->process->pool; + char *name = apr_pstrdup(p, arg1); + char *cb = apr_pstrdup(p, arg2); + + modperl_register_auth_provider_name(p, AUTHZ_PROVIDER_GROUP, name, + AUTHZ_PROVIDER_VERSION, cb, NULL, + AP_AUTH_INTERNAL_PER_CONF); + return NULL; +} + +MP_CMD_SRV_DECLARE2(authn_provider) +{ + apr_pool_t *p = parms->server->process->pool; + char *name = apr_pstrdup(p, arg1); + char *cb = apr_pstrdup(p, arg2); + + modperl_register_auth_provider_name(p, AUTHN_PROVIDER_GROUP, name, + AUTHN_PROVIDER_VERSION, cb, NULL, + AP_AUTH_INTERNAL_PER_CONF); + return NULL; +} + static const char *modperl_cmd_parse_args(apr_pool_t *p, const char *args, apr_table_t **t) Modified: perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.h URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.h?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.h (original) +++ perl/modperl/branches/httpd24/src/modules/perl/modperl_cmd.h Wed Feb 20 11:40:50 2013 @@ -42,6 +42,8 @@ MP_CMD_SRV_DECLARE(modules); MP_CMD_SRV_DECLARE(requires); MP_CMD_SRV_DECLARE(config_requires); MP_CMD_SRV_DECLARE(post_config_requires); +MP_CMD_SRV_DECLARE2(authz_provider); +MP_CMD_SRV_DECLARE2(authn_provider); MP_CMD_SRV_DECLARE2(set_var); MP_CMD_SRV_DECLARE2(add_var); MP_CMD_SRV_DECLARE2(set_env); Modified: perl/modperl/branches/httpd24/src/modules/perl/modperl_util.c URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/src/modules/perl/modperl_util.c?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/src/modules/perl/modperl_util.c (original) +++ perl/modperl/branches/httpd24/src/modules/perl/modperl_util.c Wed Feb 20 11:40:50 2013 @@ -910,3 +910,306 @@ U16 *modperl_code_attrs(pTHX_ CV *cv) { mg = mg_find((SV*)cv, PERL_MAGIC_ext); return &(mg->mg_private); } + +static apr_hash_t *global_authz_providers = NULL; +static apr_hash_t *global_authn_providers = NULL; + +typedef struct { + SV *cb1; + SV *cb2; + modperl_handler_t *cb1_handler; + modperl_handler_t *cb2_handler; +} auth_callback; + +static apr_status_t cleanup_perl_global_providers(void *ctx) +{ + global_authz_providers = NULL; + global_authn_providers = NULL; + return APR_SUCCESS; +} + +static authz_status perl_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + authz_status ret = AUTHZ_DENIED; + int count; + AV *args = Nullav; + + if (global_authz_providers == NULL) { + return ret; + } + + const char *key = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE); + auth_callback *ab = apr_hash_get(global_authz_providers, key, + APR_HASH_KEY_STRING); + if (ab == NULL) { + return ret; + } + + MP_dTHX; + + if (ab->cb1 == NULL) { + if (ab->cb1_handler == NULL) { + return ret; + } + + modperl_handler_make_args(aTHX_ &args, "Apache2::RequestRec", r, + "PV", require_args, NULL); + ret = modperl_callback(aTHX_ ab->cb1_handler, r->pool, r, r->server, + args); + SvREFCNT_dec((SV*)args); + return ret; + } + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(modperl_ptr2obj(aTHX_ "Apache2::RequestRec", r))); + XPUSHs(sv_2mortal(newSVpv(require_args, 0))); + PUTBACK; + count = call_sv(ab->cb1, G_SCALAR); + SPAGAIN; + + if (count == 1) { + ret = (authz_status) POPi; + } + + PUTBACK; + FREETMPS; + LEAVE; + return ret; +} + +static const char *perl_parse_require_line(cmd_parms *cmd, + const char *require_line, + const void **parsed_require_line) +{ + SV *ret_sv; + char *ret = NULL; + int count; + + if (global_authz_providers == NULL) { + return ret; + } + + void *key; + apr_pool_userdata_get(&key, AUTHZ_PROVIDER_NAME_NOTE, cmd->temp_pool); + auth_callback *ab = apr_hash_get(global_authz_providers, (char *) key, + APR_HASH_KEY_STRING); + if (ab == NULL || ab->cb2 == NULL) { + return ret; + } + + modperl_interp_t *interp = modperl_interp_pool_select(cmd->server->process->pool, + cmd->server); + dTHXa(interp->perl); + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(modperl_ptr2obj(aTHX_ "Apache2::CmdParms", cmd))); + XPUSHs(sv_2mortal(newSVpv(require_line, 0))); + PUTBACK; + count = call_sv(ab->cb2, G_SCALAR); + SPAGAIN; + + if (count == 1) { + ret_sv = POPs; + if (SvOK(ret_sv)) { + char *tmp = SvPV_nolen(ret_sv); + if (*tmp != '\0') { + ret = apr_pstrdup(cmd->pool, tmp); + } + } + } + + PUTBACK; + FREETMPS; + LEAVE; + return ret; +} + +static authn_status perl_check_password(request_rec *r, const char *user, + const char *password) +{ + authn_status ret = AUTH_DENIED; + int count; + AV *args = Nullav; + + if (global_authn_providers == NULL) { + return ret; + } + + const char *key = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE); + auth_callback *ab = apr_hash_get(global_authn_providers, key, + APR_HASH_KEY_STRING); + if (ab == NULL || ab->cb1) { + return ret; + } + + MP_dTHX; + + if (ab->cb1 == NULL) { + if (ab->cb1_handler == NULL) { + return ret; + } + + modperl_handler_make_args(aTHX_ &args, "Apache2::RequestRec", r, + "PV", user, + "PV", password, NULL); + ret = modperl_callback(aTHX_ ab->cb1_handler, r->pool, r, r->server, + args); + SvREFCNT_dec((SV*)args); + return ret; + } + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(modperl_ptr2obj(aTHX_ "Apache2::RequestRec", r))); + XPUSHs(sv_2mortal(newSVpv(user, 0))); + XPUSHs(sv_2mortal(newSVpv(password, 0))); + PUTBACK; + count = call_sv(ab->cb1, G_SCALAR); + SPAGAIN; + + if (count == 1) { + ret = (authn_status) POPi; + } + + PUTBACK; + FREETMPS; + LEAVE; + return ret; +} + +static authn_status perl_get_realm_hash(request_rec *r, const char *user, + const char *realm, char **rethash) +{ + authn_status ret = AUTH_USER_NOT_FOUND; + int count; + SV *rh; + + if (global_authn_providers == NULL) { + return ret; + } + + const char *key = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE); + auth_callback *ab = apr_hash_get(global_authn_providers, key, + APR_HASH_KEY_STRING); + if (ab == NULL || ab->cb2) { + return ret; + } + + MP_dTHX; + rh = sv_2mortal(newSVpv("", 0)); + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(modperl_ptr2obj(aTHX_ "Apache2::RequestRec", r))); + XPUSHs(sv_2mortal(newSVpv(user, 0))); + XPUSHs(sv_2mortal(newSVpv(realm, 0))); + XPUSHs(newRV_noinc(rh)); + PUTBACK; + count = call_sv(ab->cb2, G_SCALAR); + SPAGAIN; + + if (count == 1) { + ret = (authn_status) POPi; + char *tmp = SvPV_nolen(rh); + if (*tmp != '\0') { + *rethash = apr_pstrdup(r->pool, tmp); + } + } + + PUTBACK; + FREETMPS; + LEAVE; + return ret; +} + +static const authz_provider authz_perl_provider = { perl_check_authorization, + perl_parse_require_line }; + +static const authn_provider authn_perl_provider = { perl_check_password, + perl_get_realm_hash }; + +static apr_status_t register_auth_provider(apr_pool_t *pool, + const char *provider_group, + const char *provider_name, + const char *provider_version, + auth_callback *ab, int type) +{ + void *provider_ = NULL; + + if (global_authz_providers == NULL) { + global_authz_providers = apr_hash_make(pool); + global_authn_providers = apr_hash_make(pool); + /* We have to use pre_cleanup here, otherwise this cleanup method + * would be called after another cleanup method which unloads + * mod_perl module. + */ + apr_pool_pre_cleanup_register(pool, NULL, + cleanup_perl_global_providers); + } + + if (strcmp(provider_group, AUTHZ_PROVIDER_GROUP) == 0) { + provider_ = (void *) &authz_perl_provider; + apr_hash_set(global_authz_providers, provider_name, + APR_HASH_KEY_STRING, ab); + } + else { + provider_ = (void *) &authn_perl_provider; + apr_hash_set(global_authn_providers, provider_name, + APR_HASH_KEY_STRING, ab); + } + + return ap_register_auth_provider(pool, provider_group, provider_name, + provider_version, provider_, type); + +} + +apr_status_t modperl_register_auth_provider(apr_pool_t *pool, + const char *provider_group, + const char *provider_name, + const char *provider_version, + SV *callback1, SV *callback2, + int type) +{ + char *provider_name_dup; + auth_callback *ab = NULL; + + provider_name_dup = apr_pstrdup(pool, provider_name); + ab = apr_pcalloc(pool, sizeof(auth_callback)); + ab->cb1 = callback1; + ab->cb2 = callback2; + + return register_auth_provider(pool, provider_group, provider_name_dup, + provider_version, ab, type); +} + +apr_status_t modperl_register_auth_provider_name(apr_pool_t *pool, + const char *provider_group, + const char *provider_name, + const char *provider_version, + const char *callback1, + const char *callback2, + int type) +{ + char *provider_name_dup; + auth_callback *ab = NULL; + + provider_name_dup = apr_pstrdup(pool, provider_name); + ab = apr_pcalloc(pool, sizeof(auth_callback)); + ab->cb1_handler = modperl_handler_new(pool, callback1); + if (callback2) { + ab->cb2_handler = modperl_handler_new(pool, callback2); + } + + return register_auth_provider(pool, provider_group, provider_name_dup, + provider_version, ab, type); +} Modified: perl/modperl/branches/httpd24/src/modules/perl/modperl_util.h URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/src/modules/perl/modperl_util.h?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/src/modules/perl/modperl_util.h (original) +++ perl/modperl/branches/httpd24/src/modules/perl/modperl_util.h Wed Feb 20 11:40:50 2013 @@ -151,4 +151,18 @@ SV *modperl_pnotes(pTHX_ HV **pnotes, SV U16 *modperl_code_attrs(pTHX_ CV *cv); +apr_status_t +modperl_register_auth_provider(apr_pool_t *pool, const char *provider_group, + const char *provider_name, + const char *provider_version, SV *callback1, + SV *callback2, int type); + +apr_status_t +modperl_register_auth_provider_name(apr_pool_t *pool, + const char *provider_group, + const char *provider_name, + const char *provider_version, + const char *callback1, + const char *callback2, int type); + #endif /* MODPERL_UTIL_H */ Modified: perl/modperl/branches/httpd24/xs/Apache2/RequestUtil/Apache2__RequestUtil.h URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/xs/Apache2/RequestUtil/Apache2__RequestUtil.h?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/xs/Apache2/RequestUtil/Apache2__RequestUtil.h (original) +++ perl/modperl/branches/httpd24/xs/Apache2/RequestUtil/Apache2__RequestUtil.h Wed Feb 20 11:40:50 2013 @@ -349,3 +349,49 @@ void mpxs_Apache2__RequestRec_child_term apr_pool_cleanup_register(r->pool, r->pool, child_terminate, apr_pool_cleanup_null); } + + + +static MP_INLINE +apr_status_t mpxs_ap_register_auth_provider(pTHX_ I32 items, SV **MARK, SV **SP) +{ + if (items != 7) + Perl_croak(aTHX_ "pool, provider_group, provider_name, " + "provider_version, callback1, callback2, type"); + + apr_pool_t *pool; + + if (SvROK(*MARK) && sv_derived_from(*MARK, "APR::Pool")) { + IV tmp = SvIV((SV*)SvRV(*MARK)); + if (tmp == 0) { + Perl_croak(aTHX_ "invalid pool object (already destroyed?)"); + } + pool = INT2PTR(APR__Pool, tmp); + } + else { + Perl_croak(aTHX_ SvROK(*MARK) ? + "pool is not of type APR::Pool" : + "pool is not a blessed reference"); + } + + MARK++; + const char *provider_group = (const char *)SvPV_nolen(*MARK); + MARK++; + const char *provider_name = (const char *)SvPV_nolen(*MARK); + MARK++; + const char *provider_version = (const char *)SvPV_nolen(*MARK); + MARK++; + SV *callback1 = newSVsv(*MARK); + MARK++; + SV *callback2 = NULL; + if (SvROK(*MARK)) { + callback2 = newSVsv(*MARK); + } + MARK++; + int type = (int)SvIV(*MARK); + + return modperl_register_auth_provider(pool, provider_group, provider_name, + provider_version, callback1, + callback2, type); +} + Modified: perl/modperl/branches/httpd24/xs/maps/apache2_functions.map URL: http://svn.apache.org/viewvc/perl/modperl/branches/httpd24/xs/maps/apache2_functions.map?rev=1448098&r1=1448097&r2=1448098&view=diff ============================================================================== --- perl/modperl/branches/httpd24/xs/maps/apache2_functions.map (original) +++ perl/modperl/branches/httpd24/xs/maps/apache2_functions.map Wed Feb 20 11:40:50 2013 @@ -37,6 +37,7 @@ MODULE=Apache2::RequestUtil ap_get_status_line + ap_register_auth_provider | mpxs_ | ... MODULE=Apache2::RequestUtil PACKAGE=guess ap_psignature | | r, prefix @@ -541,3 +542,6 @@ MODULE=Apache2::MPM PACKAGE=Apache2::M ?ap_mpm_set_pidfile ?ap_mpm_set_scoreboard ?ap_listen_pre_config + +MODULE=Apache2::Provider + ap_register_provider