X-Git-Url: https://git.sesse.net/?p=itkacl;a=blobdiff_plain;f=libapache2-mod-authz-itkacl-0.5%2Fmod_authz_itkacl.c;fp=libapache2-mod-authz-itkacl-0.5%2Fmod_authz_itkacl.c;h=d892e781e71d0f080b31d7479e5890c4f9cb2e42;hp=0000000000000000000000000000000000000000;hb=0022fb1b09dd6a4ef8d8a1d5766762603b6b0a2a;hpb=de9a4d80bde793f8d6b266fa3c0e55ee618ecc1b diff --git a/libapache2-mod-authz-itkacl-0.5/mod_authz_itkacl.c b/libapache2-mod-authz-itkacl-0.5/mod_authz_itkacl.c new file mode 100644 index 0000000..d892e78 --- /dev/null +++ b/libapache2-mod-authz-itkacl-0.5/mod_authz_itkacl.c @@ -0,0 +1,187 @@ +/* + * ITKACL module, (C) 2004-2011 Steinar H. Gunderson + */ + +#define MODAUTHITKACL_VERSION "0.4" + +#include "apr_strings.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +module AP_MODULE_DECLARE_DATA authz_itkacl_module; + +extern int itkacl_check(const char * const realm, const char * const user, + char *errmsg, size_t errmsg_size); + +typedef struct { + int authoritative; +} authz_itkacl_config_rec; + +static void *authz_itkacl_dir_create_config(apr_pool_t *p, char *d) +{ + authz_itkacl_config_rec *conf = apr_palloc(p, sizeof(*conf)); + + conf->authoritative = 1; /* keep the fortress secure by default */ + return conf; +} + +static const command_rec authz_itkacl_cmds[] = +{ + AP_INIT_FLAG("AuthzITKACLAuthoritative", ap_set_flag_slot, + (void *)APR_OFFSETOF(authz_itkacl_config_rec, authoritative), + OR_AUTHCFG, + "Set to 'Off' to allow access control to be passed along to " + "lower modules if the 'require user' or 'require valid-user' " + "statement is not met. (default: On)."), + {NULL} +}; + +static int fail(request_rec *r, authz_itkacl_config_rec *conf) +{ + if (conf->authoritative) { + ap_note_auth_failure(r); + return HTTP_UNAUTHORIZED; + } else { + return DECLINED; + } +} + +static int handle_require(request_rec *r, authz_itkacl_config_rec *conf, const char *username, const char *acl_path) +{ + char errmsg[1024]; + int ret; + + ret = itkacl_check(acl_path, username, errmsg, 1024); + if (ret == 0) { + return OK; + } + + if (ret == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "error during itkacl check for %s on %s: %s", + username, acl_path, errmsg); + } + + return HTTP_UNAUTHORIZED; +} + +static int authz_itkacl_authorize_user(request_rec *r) +{ + char *username, *ptr; + const apr_array_header_t *reqs_arr = ap_requires(r); + unsigned i; + require_line *reqs; + authz_itkacl_config_rec *conf = (authz_itkacl_config_rec *) + ap_get_module_config(r->per_dir_config, &authz_itkacl_module); + + if (reqs_arr == NULL) + return DECLINED; + + /* strip the domain part (FIXME: use the alias module instead?) */ + username = strdup(r->user); + ptr = strchr(username, '@'); + if (ptr != NULL) + ptr[0] = 0; + + reqs = (require_line *)reqs_arr->elts; + for (i = 0; i < reqs_arr->nelts; ++i) { + const char *t, *w; + + if (!(reqs[i].method_mask & (AP_METHOD_BIT << (r->method_number)))) + continue; + + t = reqs[i].requirement; + w = ap_getword_white(r->pool, &t); + + if (strcasecmp(w, "valid-user") == 0) { + free(username); + return OK; + } + + if (strcasecmp(w, "itkacl") == 0) { + const char *acl_path; + + acl_path = ap_getword_conf(r->pool, &t); + if (acl_path == NULL || strcmp(acl_path, "") == 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "'Require itkacl' needs an argument"); + return fail(r, conf); + } + + if (strcasecmp(acl_path, "anyof") == 0) { + int num_seen = 0, ret; + while ((acl_path = ap_getword_conf(r->pool, &t)) != NULL) { + ret = handle_require(r, conf, username, acl_path); + if (ret == OK) { + free(username); + return ret; + } + ++num_seen; + } + if (num_seen == 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Missing arguments after 'Require itkacl anyof'"); + } else if (ret == HTTP_UNAUTHORIZED) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "%s failed itkacl check for (multiple paths)", + username, acl_path); + ret = fail(r, conf); + } + free(username); + return ret; + } else { + /* check that there are no more arguments */ + w = ap_getword_conf(r->pool, &t); + if (w != NULL && strcmp(w, "") != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Excess arguments ('%s') after Require itkacl %s; " + "did you mean 'Require itkacl anyof ...'?", + w, acl_path); + return fail(r, conf); + } + + int ret = handle_require(r, conf, username, acl_path); + if (ret == HTTP_UNAUTHORIZED) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "%s failed itkacl check for %s", + username, acl_path); + ret = fail(r, conf); + } + free(username); + return ret; + } + } + } + + free(username); + return DECLINED; +} + +static int authz_itkacl_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) +{ + ap_add_version_component(p, "mod_auth_itkacl/" MODAUTHITKACL_VERSION); + return OK; +} + +void authz_itkacl_register_hooks(apr_pool_t *p) +{ + ap_hook_post_config(authz_itkacl_init_handler, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_auth_checker(authz_itkacl_authorize_user, NULL, NULL, APR_HOOK_MIDDLE); +} + +module AP_MODULE_DECLARE_DATA authz_itkacl_module = +{ + STANDARD20_MODULE_STUFF, + authz_itkacl_dir_create_config, + NULL, + NULL, + NULL, + authz_itkacl_cmds, + authz_itkacl_register_hooks +};