Dear Subversion maintainers, We would like to avoid having to mention each of our subversion repositories inside an Apache configuration, so we use SVNParentPath.
However, this currently means we can only use a single authz configuration file. We'd like to be able to have a different file for each repository, to increase isolation. We've implemented a patch that allows this, by introducing a new Apache configuration directive: D. Example 4: Per-repository access file This configuration allows to use SVNParentPath but have different authz files per repository. <Location /svn> DAV svn SVNParentPath /path/to/reposparent AuthType Basic AuthName "Subversion repository" AuthUserFile /path/to/htpasswd/file AuthzSVNRepoRelativeAccessFile on Require valid-user </Location> NOTE: AuthzSVNRepoRelativeAccessFile on causes the authz file to be read from /path/to/reposparent/<repo>/conf/authz Is this something that might be included in subversion? [[[ Implement AuthzSVNRepoRelativeAccessFile to allow SVNParentPath to use a different authz configuration file for each repository. * subversion/mod_authz_svn/mod_authz_svn.c (get_access_conf) Check if AuthzSVNRepoRelativeAccessFile is on, and if so, load the conf/authz file from inside the repository being accessed rather than one which is statically configured in the Apache configuration. (subreq_bypass, access_checker, check_user_id, auth_checker) Recognise that it's valid not to have a AuthzSVNAccessFile if AuthzSVNRepoRelativeAccessFile is used. ]]] -- Nick Piper MEng MIET RHCE| #define Joint Lead Architect 250 Brook Drive, Green Park, Reading RG2 6UA | United Kingdom nick.pi...@logica.com | www.logica.com Logica UK Limited, registered in England & Wales (registered number 947968) Registered Office: 250 Brook Drive, Green Park, Reading RG2 6UA, United Kingdom
Index: subversion/mod_authz_svn/mod_authz_svn.c =================================================================== --- subversion/mod_authz_svn/mod_authz_svn.c (revision 1028364) +++ subversion/mod_authz_svn/mod_authz_svn.c (working copy) @@ -50,6 +50,7 @@ int authoritative; int anonymous; int no_auth_when_anon_ok; + int repo_relative_access_file; const char *base_path; const char *access_file; const char *force_username_case; @@ -103,6 +104,13 @@ "Set to 'On' to suppress authentication and authorization " "for requests which anonymous users are allowed to perform. " "(default is Off.)"), + AP_INIT_FLAG("AuthzSVNRepoRelativeAccessFile", ap_set_flag_slot, + (void *)APR_OFFSETOF(authz_svn_config_rec, + repo_relative_access_file), + OR_AUTHCFG, + "Set to 'On' to allow the AuthzSVNAccessFile to be relative " + "to the repository disk path. " + "(default is Off.)"), AP_INIT_TAKE1("AuthzForceUsernameCase", ap_set_string_slot, (void *)APR_OFFSETOF(authz_svn_config_rec, force_username_case), @@ -119,18 +127,34 @@ get_access_conf(request_rec *r, authz_svn_config_rec *conf) { const char *cache_key = NULL; + const char *access_file = NULL; + const char *repos_path = NULL; void *user_data = NULL; svn_authz_t *access_conf = NULL; svn_error_t *svn_err; + dav_error *dav_err; char errbuf[256]; + if (conf->repo_relative_access_file) { + dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path); + if (dav_err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, dav_err->desc); + return NULL; + } + access_file = apr_pstrcat(r->pool, repos_path, "/conf/authz", NULL); + } else { + access_file = conf->access_file; + } + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Path to authz file is %s", access_file); + cache_key = apr_pstrcat(r->pool, "mod_authz_svn:", - conf->access_file, (char *)NULL); + access_file, (char *)NULL); apr_pool_userdata_get(&user_data, cache_key, r->connection->pool); access_conf = user_data; if (access_conf == NULL) { - svn_err = svn_repos_authz_read(&access_conf, conf->access_file, + svn_err = svn_repos_authz_read(&access_conf, access_file, TRUE, r->connection->pool); if (svn_err) { @@ -516,7 +540,7 @@ username_to_authorize = get_username_to_authorize(r, conf); /* If configured properly, this should never be true, but just in case. */ - if (!conf->anonymous || !conf->access_file) + if (!conf->anonymous || !conf->access_file || !conf->repo_relative_access_file) { log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL); return HTTP_FORBIDDEN; @@ -580,7 +604,7 @@ int status; /* We are not configured to run */ - if (!conf->anonymous || !conf->access_file) + if (!conf->anonymous || ( !conf->access_file && !conf->repo_relative_access_file)) return DECLINED; if (ap_some_auth_required(r)) @@ -638,7 +662,7 @@ /* 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) + if ((!conf->access_file && !conf->repo_relative_access_file) || !conf->no_auth_when_anon_ok || r->user) return DECLINED; /* If anon access is allowed, return OK, preventing later modules @@ -665,7 +689,7 @@ int status; /* We are not configured to run */ - if (!conf->access_file) + if (!conf->access_file && !conf->repo_relative_access_file) return DECLINED; /* Previous hook (check_user_id) already did all the work, Index: subversion/mod_authz_svn/INSTALL =================================================================== --- subversion/mod_authz_svn/INSTALL (revision 1028364) +++ subversion/mod_authz_svn/INSTALL (working copy) @@ -79,7 +79,27 @@ though AuthzSVNAnonymous was set to 'No'. The AuthzSVNAnonymous directive prevents the anonymous access check from being run. + D. Example 4: Per-repository access file + This configuration allows to use SVNParentPath but have + different authz files per repository. + + <Location /svn> + DAV svn + SVNParentPath /path/to/reposparent + + AuthType Basic + AuthName "Subversion repository" + AuthUserFile /path/to/htpasswd/file + + AuthzSVNRepoRelativeAccessFile on + + Require valid-user + </Location> + + NOTE: AuthzSVNRepoRelativeAccessFile on causes the authz file + to be read from /path/to/reposparent/<repo>/conf/authz + 2. Specifying permissions The file format of the access file looks like this: