diff --git a/mod_absec.c b/mod_absec.c index fe501a6..2e9fc2d 100755 --- a/mod_absec.c +++ b/mod_absec.c @@ -52,11 +52,15 @@ #include "http_config.h" #include "http_core.h" #include "http_protocol.h" +#include "http_request.h" +#include "http_log.h" #include "ap_config.h" #include "apr_base64.h" #include "apr_strings.h" #include "apr_portable.h" #include "apr_user.h" +#include "ap_provider.h" +#include "mod_auth.h" #include #include @@ -259,26 +263,179 @@ static int absec_handler_first(request_rec *r) } //////////////////////////////////////////////////////////////// -static void absec_register_hooks(apr_pool_t *p) +//////////////////////////////////////////////////////////////// +// Validate user/pass +static authn_status authn_check_absec(request_rec *r, const char* user, const char* password) { - //ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST); - ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST); + ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : user : %s, pass : %s", user, password); + + int pam_result = check_user(user, password); + if ( (pam_result==PAM_ERROR_START) || (pam_result==PAM_ERROR_STOP) ) { + return HTTP_INTERNAL_SERVER_ERROR; + } + if (pam_result==PAM_ERROR_INVALID_CRED) { + ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : DENIED"); + return AUTH_DENIED; + } + ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : GRANTED"); + return AUTH_GRANTED; - // should use HOOK FIXUP + // Example code + /* + if (strcmp(user, "joe")) { + return AUTH_USER_NOT_FOUND; + } else { + if (strcmp(password, "poi")) { + return AUTH_DENIED; + } else { + return AUTH_GRANTED; + } + } + */ - // should use FILTER + // Possible return status + // AUTH_GENERAL_ERROR + // AUTH_USER_NOT_FOUND + // AUTH_USER_FOUND + // AUTH_DENIED + // AUTH_GRANTED } //////////////////////////////////////////////////////////////// +// Validate ressource access +static authz_status authz_check_absec(request_rec *r, const char *require_args, const void *parsed_require_args) +{ + char *user = r->user; + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : user : %s", user); + + //////// + /* http method validate the perm asked (r/w vs get/post,put) */ + ap_rprintf(r, "Before Method: %s
\r\n", r->method); + + int permmask = 0; + if (strcmp(r->method,"GET")==0) permmask=0444; // r + if (strcmp(r->method,"PUT")==0) permmask=0222; // w + if (strcmp(r->method,"POST")==0) permmask=0222; // w + if (strcmp(r->method,"DELETE")==0) permmask=0111; // x + + //////// + /* check file permission on filesystem */ + /* should include */ + struct stat fperm; + int status; + //status = stat(r->filename, &fperm); + status = perms_lookup(r, &fperm); + //ap_rprintf(r, "Result mysql: %d
\r\n", ); + if (status==-1) { + ap_rprintf(r, "stat erreur %d", errno); + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : stat erreur %d", errno); + return (OK); + } + //ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)
\r\n", fperm.st_mode, fperm.st_uid, fperm.st_gid, status); + + /* check if any permission (ogw) match method (get r, put/post w, delete x) */ + if ((fperm.st_mode & permmask)==0) { + /* no permission match, return don't even have to check user perms */ + ap_rprintf(r, "Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask); + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask); + return AUTHZ_DENIED; + } + + // If file is world accessible for asked method return content + if (fperm.st_mode & 0x7 & permmask) { + /* if so, return, no need to check user perms */ + //ap_rprintf(r, "Fichier public
\r\n"); + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier accessible a tous"); + return AUTHZ_GRANTED; + } + + if (!user) { + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : No user"); + return AUTHZ_DENIED_NO_USER; + } + + struct passwd *pw; + pw = getpwnam(user); + + // If file is user readable and user match return content + if ((fperm.st_uid==pw->pw_uid) && (fperm.st_mode & 0700 & permmask)) { + ap_rprintf(r, "Fichier propriƩtaire
\r\n"); + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier propriƩtaire
\r\n"); + return AUTHZ_GRANTED; + } + + // If file is group readable and primary group match return content + if ((fperm.st_gid==pw->pw_gid) && (fperm.st_mode & 0070 & permmask)) { + ap_rprintf(r, "Fichier groupe
\r\n"); + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier groupe
\r\n"); + return AUTHZ_GRANTED; + } + + ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : DENIED
\r\n"); + return AUTHZ_DENIED; + + if (r->user==NULL) { + return AUTHZ_DENIED; + } + + return AUTHZ_GRANTED; +} + +//////////////////////////////////////////////////////////////// +static const authn_provider authn_absec_provider = +{ + &authn_check_absec, + NULL +}; + +//////////////////////////////////////////////////////////////// +static const authz_provider authz_absec_provider = +{ + &authz_check_absec, + NULL +}; + +//////////////////////////////////////////////////////////////// +static void absec_register_hooks(apr_pool_t *p) +{ + //ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE); + //ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST); + //ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST); + + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "absec", "0", &authn_absec_provider, AP_AUTH_INTERNAL_PER_CONF); + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "absec", "0", &authz_absec_provider, AP_AUTH_INTERNAL_PER_CONF); +} + +//////////////////////////////////////////////////////////////// +static const command_rec absec_auth_basic_cmds[] = +{ +/* AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG, + "specify the auth providers for a directory or location"), + AP_INIT_FLAG("AuthBasicAuthoritative", set_authoritative, NULL, OR_AUTHCFG, + "Set to 'Off' to allow access control to be passed along to " + "lower modules if the UserID is not known to this module"), + AP_INIT_TAKE12("AuthBasicFake", add_basic_fake, NULL, OR_AUTHCFG, + "Fake basic authentication using the given expressions for " + "username and password, 'off' to disable. Password defaults " + "to 'password' if missing."), + AP_INIT_TAKE1("AuthBasicUseDigestAlgorithm", set_use_digest_algorithm, + NULL, OR_AUTHCFG, + "Set to 'MD5' to use the auth provider's authentication " + "check for digest auth, using a hash of 'user:realm:pass'"),*/ + {NULL} +}; + +//////////////////////////////////////////////////////////////// /* Dispatch list for API hooks */ -module AP_MODULE_DECLARE_DATA absec_module = { +module AP_MODULE_DECLARE_DATA absec_module; + +AP_DECLARE_MODULE(absec) = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ - NULL, /* table of config file commands */ - absec_register_hooks /* register hooks */ + absec_auth_basic_cmds, /* table of config file commands */ + absec_register_hooks /* register hooks */ };