/* Validate access to the given user for the given path. This * function checks rules for exactly the given path, and first tries * to access a section specific to the given repository before falling * back to pan-repository rules. * * Update *access_granted to inform the caller of the outcome of the * lookup. Return a boolean indicating whether the access rights were * successfully determined. */ static svn_boolean_t authz_get_path_access(svn_config_t *cfg, const char *repos_name, const char *path, const char *user, svn_repos_authz_access_t required_access, svn_boolean_t *access_granted, apr_pool_t *pool) { const char *qualified_path; struct authz_lookup_baton baton = { 0 }; baton.config = cfg; baton.user = user; /* Try to locate a repository-specific block first. */ qualified_path = apr_pstrcat(pool, repos_name, ":", path, (char *)NULL); svn_config_enumerate2(cfg, qualified_path, authz_parse_line, &baton, pool); *access_granted = authz_access_is_granted(baton.allow, baton.deny, required_access); /* If the first test has determined access, stop now. */ if (authz_access_is_determined(baton.allow, baton.deny, required_access)) return TRUE; /* No repository specific rule, try pan-repository rules. */ svn_config_enumerate2(cfg, path, authz_parse_line, &baton, pool); *access_granted = authz_access_is_granted(baton.allow, baton.deny, required_access); return authz_access_is_determined(baton.allow, baton.deny, required_access); }
/* Walk through the authz CFG to check if USER has the REQUIRED_ACCESS * to any path within the REPOSITORY. Return TRUE if so. Use POOL * for temporary allocations. */ static svn_boolean_t authz_get_any_access(svn_config_t *cfg, const char *repos_name, const char *user, svn_repos_authz_access_t required_access, apr_pool_t *pool) { struct authz_lookup_baton baton = { 0 }; baton.config = cfg; baton.user = user; baton.required_access = required_access; baton.access = FALSE; /* Deny access by default. */ baton.repos_path = "/"; baton.qualified_repos_path = apr_pstrcat(pool, repos_name, ":/", SVN_VA_NULL); /* We could have used svn_config_enumerate2 for "repos_name:/". * However, this requires access for root explicitly (which the user * may not always have). So we end up enumerating the sections in * the authz CFG and stop on the first match with some access for * this user. */ svn_config_enumerate_sections2(cfg, authz_get_any_access_parser_cb, &baton, pool); /* If walking the configuration was inconclusive, deny access. */ if (!authz_access_is_determined(baton.allow, baton.deny, baton.required_access)) return FALSE; return baton.access; }
/* Callback to parse sections of the configuration file, looking for any kind of granted access. Implements the svn_config_section_enumerator2_t interface. */ static svn_boolean_t authz_get_any_access_parser_cb(const char *section_name, void *baton, apr_pool_t *pool) { struct authz_lookup_baton *b = baton; /* Does the section apply to the query? */ if (section_name[0] == '/' || strncmp(section_name, b->qualified_repos_path, strlen(b->qualified_repos_path)) == 0) { b->allow = b->deny = svn_authz_none; svn_config_enumerate2(b->config, section_name, authz_parse_line, baton, pool); b->access = authz_access_is_granted(b->allow, b->deny, b->required_access); /* Continue as long as we don't find a determined, granted access. */ return !(b->access && authz_access_is_determined(b->allow, b->deny, b->required_access)); } return TRUE; }
/* Callback to parse a section and update the authz_baton if the * section denies access to the subtree the baton describes. */ static svn_boolean_t authz_parse_section(const char *section_name, void *baton, apr_pool_t *pool) { struct authz_lookup_baton *b = baton; svn_boolean_t conclusive; /* Does the section apply to us? */ if (!is_applicable_section(b->qualified_repos_path, section_name) && !is_applicable_section(b->repos_path, section_name)) return TRUE; /* Work out what this section grants. */ b->allow = b->deny = 0; svn_config_enumerate2(b->config, section_name, authz_parse_line, b, pool); /* Has the section explicitly determined an access? */ conclusive = authz_access_is_determined(b->allow, b->deny, b->required_access); /* Is access granted OR inconclusive? */ b->access = authz_access_is_granted(b->allow, b->deny, b->required_access) || !conclusive; /* As long as access isn't conclusively denied, carry on. */ return b->access; }