diff --git a/absec_mysql.c b/absec_mysql.c index b6db31a..0a43485 100644 --- a/absec_mysql.c +++ b/absec_mysql.c @@ -59,7 +59,7 @@ int perms_lookup(request_rec *r, struct stat *fperm) } if (cnt==0) { - sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri); + sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', %d, %d, %d)", r->uri, fperm->st_uid, fperm->st_gid, fperm->st_mode); if (mysql_query(conn, query)) { printf("%s\n", mysql_error(conn)); return(0); diff --git a/compile.sh b/compile.sh index f81073e..cb3b4ab 100755 --- a/compile.sh +++ b/compile.sh @@ -90,8 +90,6 @@ echo "Running test" ./abchgrp 200 / ./abls / -exit - echo "================" echo "Compiling apache absec module" echo "selected authen :" $ABSEC_AUTHEN_DEP $ABSEC_AUTHEN_FILE diff --git a/mod_absec.c b/mod_absec.c index b68523a..55fbb27 100755 --- a/mod_absec.c +++ b/mod_absec.c @@ -62,6 +62,8 @@ #include "ap_provider.h" #include "mod_auth.h" +#include + #include #include #include @@ -75,196 +77,71 @@ #include "absec_auto.h" //////////////////////////////////////////////////////////////// -/* Main routine - called after request processing */ -static int absec_handler_last(request_rec *r) +// Macro declaration du module +module AP_MODULE_DECLARE_DATA absec_module; + +//////////////////////////////////////////////////////////////// +// structure de configuration du module +typedef struct { + int default_uid; + int default_gid; + int default_perms; +} authnz_config_rec; + +static void *authnz_absec_config(apr_pool_t *pool, char *x) { - // Is this module really called? - if (strcmp(r->handler, "absec")) { - return DECLINED; - } + return apr_pcalloc(pool, sizeof(authnz_config_rec)); +} - //////// - /* http method validate the perm asked (r/w vs get/post,put) */ - ap_rprintf(r, "After Method: %s
\r\n", r->method); - int permmask = 0; - if (strcmp(r->method,"GET")!=0) +static const char* set_default_perms(cmd_parms* cmd, void* cfg, const char* val) { + int octal, decimal; + octal = atoi(val); + decimal = 0; + int i=0; + while (octal != 0) { - // Not a GET, it's too late to do anything - ap_rprintf(r, "Not a GET post treatement is too late!\n
"); - return (DECLINED); + decimal = decimal +(octal % 10)* pow(8, i++); + octal = octal / 10; } - r->content_type = "text/html"; - //ap_rprintf(r, "The sample page from mod_absec.c %s \n
", r->args); - ap_rprintf(r, "After GET Url: %s from %s \n
", r->filename, r->uri); - return (DECLINED); + ((authnz_config_rec*)cfg)->default_perms = decimal; + return NULL; +} + +static const char* set_default_uid(cmd_parms* cmd, void* cfg, const char* val) { + ((authnz_config_rec*)cfg)->default_uid = atoi(val); + return NULL; +} + +static const char* set_default_gid(cmd_parms* cmd, void* cfg, const char* val) { + ((authnz_config_rec*)cfg)->default_gid = atoi(val); + return NULL; } //////////////////////////////////////////////////////////////// -/* Main routine - called before request processing */ -static int absec_handler_first(request_rec *r) +static const command_rec absec_auth_basic_cmds[] = { - ap_rprintf(r, "handler first : Before Method: %s
\r\n", r->method); - // Is this module really called? - /*if (strcmp(r->handler, "absec")) { - ap_rprintf(r, "DECLINED
\r\n"); - return DECLINED; - }*/ - - - //////// - /* 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); - 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); - return (OK); - } - - // 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"); - return (DECLINED); - } - - //////// - /* Check if we have a basic auth user */ - const char* auth64p; - // Check if we have an auth header - auth64p = apr_table_get(r->headers_in,"Authorization"); - - // If no basic auth, ask for one - if (auth64p==NULL) { - r->content_type = "text/html"; - apr_table_setn(r->err_headers_out, - (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" - : "WWW-Authenticate", - apr_pstrcat(r->pool, "Basic realm=\"PAS DE USER ", ap_auth_name(r), - "\"", NULL)); - return HTTP_UNAUTHORIZED; - } - - //////// - /* Retrieve user/pass from http basic auth header */ - // Get the basic auth base64 string and decode it - // Start at char 6 to skip 'Basic ' - char *auth64; - auth64 = apr_pstrdup(r->pool, auth64p+6); - char *auth; - auth = apr_pcalloc(r->pool, 64); - apr_base64_decode(auth, auth64); - char *user; - char *pass; - user = apr_strtok(auth, ":", &pass); - - r->content_type = "text/html"; - ap_rprintf(r, "Url: %s from %s \n
", r->filename, r->uri); - //ap_rprintf(r, "Headers Authorization: %s \n
", auth64); - //ap_rprintf(r, "User/Pass: %s/%s \n
", user, pass); - - int pam_result = check_user(user, pass); - if ( (pam_result==PAM_ERROR_START) || (pam_result==PAM_ERROR_STOP) ) { - return HTTP_INTERNAL_SERVER_ERROR; - } - if (pam_result==PAM_ERROR_INVALID_CRED) { - r->content_type = "text/html"; - apr_table_setn(r->err_headers_out, - (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" - : "WWW-Authenticate", - apr_pstrcat(r->pool, "Basic realm=\"USER/PASS INVALIDE ", ap_auth_name(r), - "\"", NULL)); - return HTTP_UNAUTHORIZED; - } - - //////// - // Continue checking permission - - //////// - /* Retrieve user details from /etc/passwd to get uid and primary group */ - /* Should include */ - struct passwd *pw; - if((pw = getpwnam(user)) == NULL) - { - // Should never happend as already verified with PAM - ap_rprintf(r, "NULL \n
"); - apr_table_setn(r->err_headers_out, - (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" - : "WWW-Authenticate", - apr_pstrcat(r->pool, "Basic realm=\"USER INCONNU ", ap_auth_name(r), - "\"", NULL)); - // User cannot be found, unauthorized - return HTTP_UNAUTHORIZED; - } - - // 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"); - return (DECLINED); - } - - // 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"); - return (DECLINED); - } - - //////// - /* Check supplemental groups */ - /* Should include */ - //ap_rprintf(r, "Fichier propriƩtaire %d %d %o %o
\r\n", fperm.st_uid, i, fperm.st_mode, 0400); - gid_t grouplist[16]; - int grouplistsize = 16; - int groupreturn; - groupreturn = getgrouplist(user, pw->pw_gid, grouplist, &grouplistsize); - if (groupreturn >= 0) { - ap_rprintf(r, "OK liste des groupes (%d)
\r\n", grouplistsize); - for (int i=0; i\r\n"); - return (DECLINED); - } - } - } - - // else decline request - ap_rprintf(r, "Aucuns droits de voir le fichier
\r\n"); - apr_table_setn(r->err_headers_out, - (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" - : "WWW-Authenticate", - apr_pstrcat(r->pool, "Basic realm=\"NON AUTHORISE", ap_auth_name(r), - "\"", NULL)); - return HTTP_UNAUTHORIZED; - -} +/* AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG, + "specify the auth providers for a directory or location"),*/ + AP_INIT_TAKE1("ABSECDefaultPerms", set_default_perms, NULL, OR_AUTHCFG, + "Set to default octal value of perms "), + AP_INIT_TAKE1("ABSECDefaultUID", set_default_uid, NULL, OR_AUTHCFG, + "Set to default octal value of perms "), + AP_INIT_TAKE1("ABSECDefaultGID", set_default_gid, NULL, OR_AUTHCFG, + "Set to default octal value of perms "), +/* 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} +}; //////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// Validate user/pass +// Validate authentification (user/pass) static authn_status authn_check_absec(request_rec *r, const char* user, const char* password) { ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : user : %s, pass : %s", user, password); @@ -302,13 +179,13 @@ static authn_status authn_check_absec(request_rec *r, const char* user, const ch } //////////////////////////////////////////////////////////////// -// Validate ressource access +// Validate autorisation (ressource access) // request_rec contain user/pass if basic auth // it could also contain cookies if cookies based auth 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); + ap_log_rerror("mod_absec.c", 342, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : user : %s", user); //////// /* http method validate the perm asked (r/w vs get/post,put) */ @@ -320,10 +197,18 @@ static authz_status authz_check_absec(request_rec *r, const char *require_args, if (strcmp(r->method,"POST")==0) permmask=0222; // w if (strcmp(r->method,"DELETE")==0) permmask=0111; // x + authnz_config_rec *cfg = ap_get_module_config(r->per_dir_config, &absec_module); + struct stat fperm; + fperm.st_mode = cfg->default_perms; + ap_log_rerror("mod_absec.c", 329, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : default perms : %o", cfg->default_perms); + fperm.st_uid = cfg->default_uid; + ap_log_rerror("mod_absec.c", 329, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : default uid : %o", cfg->default_uid); + fperm.st_gid = cfg->default_gid; + ap_log_rerror("mod_absec.c", 329, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : default gid : %o", cfg->default_gid); + //////// /* check file permission on filesystem */ /* should include */ - struct stat fperm; int status; //status = stat(r->filename, &fperm); status = perms_lookup(r, &fperm); @@ -333,6 +218,7 @@ static authz_status authz_check_absec(request_rec *r, const char *require_args, 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) */ @@ -421,40 +307,15 @@ static const authz_provider authz_absec_provider = //////////////////////////////////////////////////////////////// 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; - AP_DECLARE_MODULE(absec) = { STANDARD20_MODULE_STUFF, - NULL, /* create per-dir config structures */ + authnz_absec_config, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */