📄 mod_authz_svn.c
字号:
* in the repository. This is to avoid operations that involve no * paths (commiting an empty revision, leaving a dangling * transaction in the FS) being granted by default, letting * unauthenticated users write some changes to the repository. * This was issue #2388. * * XXX: For now, requesting access to the entire repository always * XXX: succeeds, until we come up with a good way of figuring * XXX: this out. */ if (repos_path || (!repos_path && (authz_svn_type & svn_authz_write))) { svn_err = svn_repos_authz_check_access(access_conf, repos_name, repos_path, r->user, authz_svn_type, &authz_access_granted, r->pool); if (svn_err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, /* If it is an error code that APR can make sense of, then show it, otherwise, pass zero to avoid putting "APR does not understand this error code" in the error log. */ ((svn_err->apr_err >= APR_OS_START_USERERR && svn_err->apr_err < APR_OS_START_CANONERR) ? 0 : svn_err->apr_err), r, "Failed to perform access control: %s", svn_err_best_message(svn_err, errbuf, sizeof(errbuf))); svn_error_clear(svn_err); return DECLINED; } if (!authz_access_granted) return DECLINED; } /* XXX: MKCOL, MOVE, DELETE * XXX: Require write access to the parent dir of repos_path. */ /* XXX: PUT * XXX: If the path doesn't exist, require write access to the * XXX: parent dir of repos_path. */ /* Only MOVE and COPY have a second uri we have to check access to. */ if (r->method_number != M_MOVE && r->method_number != M_COPY) { return OK; } /* Check access on the destination repos_path. Again, skip this if repos_path == NULL (see above for explanations) */ if (repos_path) { svn_err = svn_repos_authz_check_access(access_conf, dest_repos_name, dest_repos_path, r->user, svn_authz_write |svn_authz_recursive, &authz_access_granted, r->pool); if (svn_err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, /* If it is an error code that APR can make sense of, then show it, otherwise, pass zero to avoid putting "APR does not understand this error code" in the error log. */ ((svn_err->apr_err >= APR_OS_START_USERERR && svn_err->apr_err < APR_OS_START_CANONERR) ? 0 : svn_err->apr_err), r, "Failed to perform access control: %s", svn_err_best_message(svn_err, errbuf, sizeof(errbuf))); svn_error_clear(svn_err); return DECLINED; } if (!authz_access_granted) return DECLINED; } /* XXX: MOVE and COPY, if the path doesn't exist yet, also * XXX: require write access to the parent dir of dest_repos_path. */ return OK;}/* Log a message indicating the access control decision made about a * request. FILE and LINE should be supplied via the APLOG_MARK macro. * ALLOWED is boolean. REPOS_PATH and DEST_REPOS_PATH are information * about the request. DEST_REPOS_PATH may be NULL. */static void log_access_verdict(const char *file, int line, const request_rec *r, int allowed, const char *repos_path, const char *dest_repos_path){ int level = allowed ? APLOG_INFO : APLOG_ERR; const char *verdict = allowed ? "granted" : "denied"; if (r->user) { if (dest_repos_path) { ap_log_rerror(file, line, level, 0, r, "Access %s: '%s' %s %s %s", verdict, r->user, r->method, repos_path, dest_repos_path); } else { ap_log_rerror(file, line, level, 0, r, "Access %s: '%s' %s %s", verdict, r->user, r->method, repos_path); } } else { if (dest_repos_path) { ap_log_rerror(file, line, level, 0, r, "Access %s: - %s %s %s", verdict, r->method, repos_path, dest_repos_path); } else { ap_log_rerror(file, line, level, 0, r, "Access %s: - %s %s", verdict, r->method, repos_path); } }}/* * Hooks */static int access_checker(request_rec *r){ authz_svn_config_rec *conf = ap_get_module_config(r->per_dir_config, &authz_svn_module); const char *repos_path; const char *dest_repos_path = NULL; int status; /* We are not configured to run */ if (!conf->anonymous || !conf->access_file) return DECLINED; if (ap_some_auth_required(r)) { /* It makes no sense to check if a location is both accessible * anonymous and by an authenticated user (in the same request!). */ if (ap_satisfies(r) != SATISFY_ANY) return DECLINED; /* If the user is trying to authenticate, let him. If anonymous * access is allowed, so is authenticated access, by definition * of the meaning of '*' in the access file. */ if (apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization")) { /* Given Satisfy Any is in effect, we have to forbid access * to let the auth_checker hook have a go at it. */ return HTTP_FORBIDDEN; } } /* If anon access is allowed, return OK */ status = req_check_access(r, conf, &repos_path, &dest_repos_path); if (status == DECLINED) { if (!conf->authoritative) return DECLINED; if (!ap_some_auth_required(r)) { log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path); } return HTTP_FORBIDDEN; } if (status != OK) return status; log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path); return OK;}static int check_user_id(request_rec *r){ authz_svn_config_rec *conf = ap_get_module_config(r->per_dir_config, &authz_svn_module); const char *repos_path; const char *dest_repos_path = NULL; int status; /* We are not configured to run, or, an earlier module has already * authenticated this request. */ if (!conf->access_file || !conf->no_auth_when_anon_ok || r->user) return DECLINED; /* If anon access is allowed, return OK, preventing later modules * from issuing an HTTP_UNAUTHORIZED. Also pass a note to our * auth_checker hook that access has already been checked. */ status = req_check_access(r, conf, &repos_path, &dest_repos_path); if (status == OK) { apr_table_setn(r->notes, "authz_svn-anon-ok", (const char*)1); log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path); return OK; } return status;}static int auth_checker(request_rec *r){ authz_svn_config_rec *conf = ap_get_module_config(r->per_dir_config, &authz_svn_module); const char *repos_path; const char *dest_repos_path = NULL; int status; /* We are not configured to run */ if (!conf->access_file) return DECLINED; /* Previous hook (check_user_id) already did all the work, * and, as a sanity check, r->user hasn't been set since then? */ if (!r->user && apr_table_get(r->notes, "authz_svn-anon-ok")) { return OK; } status = req_check_access(r, conf, &repos_path, &dest_repos_path); if (status == DECLINED) { if (conf->authoritative) { log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path); ap_note_auth_failure(r); return HTTP_FORBIDDEN; } return DECLINED; } if (status != OK) return status; log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path); return OK;}/* * Module flesh */static void register_hooks(apr_pool_t *p){ static const char * const mod_ssl[] = { "mod_ssl.c", NULL }; ap_hook_access_checker(access_checker, NULL, NULL, APR_HOOK_LAST); /* Our check_user_id hook must be before any module which will return * HTTP_UNAUTHORIZED (mod_auth_basic, etc.), but after mod_ssl, to * give SSLOptions +FakeBasicAuth a chance to work. */ ap_hook_check_user_id(check_user_id, mod_ssl, NULL, APR_HOOK_FIRST); ap_hook_auth_checker(auth_checker, NULL, NULL, APR_HOOK_FIRST);}module AP_MODULE_DECLARE_DATA authz_svn_module ={ STANDARD20_MODULE_STUFF, create_authz_svn_dir_config, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ authz_svn_cmds, /* command apr_table_t */ register_hooks /* register hooks */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -