/* 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, SVN_VA_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); }
svn_error_t * svn_cache__make_memcache_from_config(svn_memcache_t **memcache_p, svn_config_t *config, apr_pool_t *pool) { int server_count; apr_pool_t *subpool = svn_pool_create(pool); server_count = svn_config_enumerate2(config, SVN_CACHE_CONFIG_CATEGORY_MEMCACHED_SERVERS, nop_enumerator, NULL, subpool); if (server_count == 0) { *memcache_p = NULL; svn_pool_destroy(subpool); return SVN_NO_ERROR; } if (server_count > APR_INT16_MAX) return svn_error_create(SVN_ERR_TOO_MANY_MEMCACHED_SERVERS, NULL, NULL); #ifdef SVN_HAVE_MEMCACHE { struct ams_baton b; svn_memcache_t *memcache = apr_pcalloc(pool, sizeof(*memcache)); apr_status_t apr_err = apr_memcache_create(pool, (apr_uint16_t)server_count, 0, /* flags */ &(memcache->c)); if (apr_err != APR_SUCCESS) return svn_error_wrap_apr(apr_err, _("Unknown error creating apr_memcache_t")); b.memcache = memcache->c; b.memcache_pool = pool; b.err = SVN_NO_ERROR; svn_config_enumerate2(config, SVN_CACHE_CONFIG_CATEGORY_MEMCACHED_SERVERS, add_memcache_server, &b, subpool); if (b.err) return b.err; *memcache_p = memcache; svn_pool_destroy(subpool); return SVN_NO_ERROR; } #else /* ! SVN_HAVE_MEMCACHE */ { return svn_error_create(SVN_ERR_NO_APR_MEMCACHE, NULL, NULL); } #endif /* SVN_HAVE_MEMCACHE */ }
/* 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; }
/* Callback to check the contents of the configuration section given by NAME. Use BATON for context and error reporting. */ static svn_boolean_t authz_validate_section(const char *name, void *baton, apr_pool_t *pool) { struct authz_validate_baton *b = baton; /* Use the group checking callback for the "groups" section... */ if (strcmp(name, "groups") == 0) svn_config_enumerate2(b->config, name, authz_validate_group, baton, pool); /* ...and the alias checking callback for "aliases"... */ else if (strcmp(name, "aliases") == 0) svn_config_enumerate2(b->config, name, authz_validate_alias, baton, pool); /* ...but for everything else use the rule checking callback. */ else { /* Validate the section's name. Skip the optional REPOS_NAME. */ const char *fspath = strchr(name, ':'); if (fspath) fspath++; else fspath = name; if (! svn_fspath__is_canonical(fspath)) { b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, "Section name '%s' contains non-canonical " "fspath '%s'", name, fspath); return FALSE; } svn_config_enumerate2(b->config, name, authz_validate_rule, baton, pool); } if (b->err) return FALSE; return TRUE; }
const char *svn_config_find_group(svn_config_t *cfg, const char *key, const char *master_section, apr_pool_t *pool) { struct search_groups_baton gb; gb.key = key; gb.match = NULL; gb.pool = pool; (void) svn_config_enumerate2(cfg, master_section, search_groups, &gb, pool); return gb.match; }
/* An implementation of svn_config_section_enumerator2_t. */ static svn_boolean_t parse_hooks_env_section(const char *name, void *baton, apr_pool_t *pool) { struct parse_hooks_env_section_baton *b = baton; struct parse_hooks_env_option_baton bo; bo.section = name; bo.hooks_env = b->hooks_env; (void)svn_config_enumerate2(b->cfg, name, parse_hooks_env_option, &bo, pool); return TRUE; }
/* Callback to check the contents of the configuration section given by NAME. Use BATON for context and error reporting. */ static svn_boolean_t authz_validate_section(const char *name, void *baton, apr_pool_t *pool) { struct authz_validate_baton *b = baton; /* If the section is the groups definition, use the group checking callback. Otherwise, use the rule checking callback. */ if (strncmp(name, "groups", 6) == 0) svn_config_enumerate2(b->config, name, authz_validate_group, baton, pool); else if (strncmp(name, "aliases", 7) == 0) svn_config_enumerate2(b->config, name, authz_validate_alias, baton, pool); else svn_config_enumerate2(b->config, name, authz_validate_rule, baton, pool); if (b->err) return FALSE; return TRUE; }
/* Copy group definitions from GROUPS_CFG to the resulting AUTHZ. * If AUTHZ already contains any group definition, report an error. * Use POOL for temporary allocations. */ static svn_error_t * authz_copy_groups(svn_authz_t *authz, svn_config_t *groups_cfg, apr_pool_t *pool) { /* Easy out: we prohibit local groups in the authz file when global groups are being used. */ if (svn_config_has_section(authz->cfg, SVN_CONFIG_SECTION_GROUPS)) { return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, "Authz file cannot contain any groups " "when global groups are being used."); } svn_config_enumerate2(groups_cfg, SVN_CONFIG_SECTION_GROUPS, authz_copy_group, authz->cfg, pool); return SVN_NO_ERROR; }
svn_error_t * svn_client__get_auto_props(apr_hash_t **properties, const char **mimetype, const char *path, svn_magic__cookie_t *magic_cookie, svn_client_ctx_t *ctx, apr_pool_t *pool) { svn_config_t *cfg; svn_boolean_t use_autoprops; auto_props_baton_t autoprops; /* initialisation */ autoprops.properties = apr_hash_make(pool); autoprops.filename = svn_dirent_basename(path, pool); autoprops.pool = pool; autoprops.mimetype = NULL; autoprops.have_executable = FALSE; *properties = autoprops.properties; cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING) : NULL; /* check that auto props is enabled */ SVN_ERR(svn_config_get_bool(cfg, &use_autoprops, SVN_CONFIG_SECTION_MISCELLANY, SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, FALSE)); /* search for auto props */ if (use_autoprops) svn_config_enumerate2(cfg, SVN_CONFIG_SECTION_AUTO_PROPS, auto_props_enumerator, &autoprops, pool); /* if mimetype has not been set check the file */ if (! autoprops.mimetype) { SVN_ERR(svn_io_detect_mimetype2(&autoprops.mimetype, path, ctx->mimetypes_map, pool)); /* If we got no mime-type, or if it is "application/octet-stream", * try to get the mime-type from libmagic. */ if (magic_cookie && (!autoprops.mimetype || strcmp(autoprops.mimetype, "application/octet-stream") == 0)) { const char *magic_mimetype; /* Since libmagic usually treats UTF-16 files as "text/plain", * svn_magic__detect_binary_mimetype() will return NULL for such * files. This is fine for now since we currently don't support * UTF-16-encoded text files (issue #2194). * Once we do support UTF-16 this code path will fail to detect * them as text unless the svn_io_detect_mimetype2() call above * returns "text/plain" for them. */ SVN_ERR(svn_magic__detect_binary_mimetype(&magic_mimetype, path, magic_cookie, pool, pool)); if (magic_mimetype) autoprops.mimetype = magic_mimetype; } if (autoprops.mimetype) apr_hash_set(autoprops.properties, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE), svn_string_create(autoprops.mimetype, pool)); } /* if executable has not been set check the file */ if (! autoprops.have_executable) { svn_boolean_t executable = FALSE; SVN_ERR(svn_io_is_file_executable(&executable, path, pool)); if (executable) apr_hash_set(autoprops.properties, SVN_PROP_EXECUTABLE, strlen(SVN_PROP_EXECUTABLE), svn_string_create_empty(pool)); } *mimetype = autoprops.mimetype; return SVN_NO_ERROR; }
svn_error_t * svn_client__get_auto_props(apr_hash_t **properties, const char **mimetype, const char *path, svn_client_ctx_t *ctx, apr_pool_t *pool) { svn_config_t *cfg; svn_boolean_t use_autoprops; auto_props_baton_t autoprops; /* initialisation */ autoprops.properties = apr_hash_make(pool); autoprops.filename = svn_path_basename(path, pool); autoprops.pool = pool; autoprops.mimetype = NULL; autoprops.have_executable = FALSE; *properties = autoprops.properties; cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING) : NULL; /* check that auto props is enabled */ SVN_ERR(svn_config_get_bool(cfg, &use_autoprops, SVN_CONFIG_SECTION_MISCELLANY, SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, FALSE)); /* search for auto props */ if (use_autoprops) svn_config_enumerate2(cfg, SVN_CONFIG_SECTION_AUTO_PROPS, auto_props_enumerator, &autoprops, pool); /* if mimetype has not been set check the file */ if (! autoprops.mimetype) { SVN_ERR(svn_io_detect_mimetype2(&autoprops.mimetype, path, ctx->mimetypes_map, pool)); if (autoprops.mimetype) apr_hash_set(autoprops.properties, SVN_PROP_MIME_TYPE, strlen(SVN_PROP_MIME_TYPE), svn_string_create(autoprops.mimetype, pool)); } /* Don't automatically set the svn:executable property on added items * on OS400. While OS400 supports the executable permission its use is * inconsistent at best. */ #ifndef AS400 /* if executable has not been set check the file */ if (! autoprops.have_executable) { svn_boolean_t executable = FALSE; SVN_ERR(svn_io_is_file_executable(&executable, path, pool)); if (executable) apr_hash_set(autoprops.properties, SVN_PROP_EXECUTABLE, strlen(SVN_PROP_EXECUTABLE), svn_string_create("", pool)); } #endif *mimetype = autoprops.mimetype; return SVN_NO_ERROR; }