| /* |
| * authz_pool.c : pool of authorization objects |
| * |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| */ |
| |
| |
| |
| #include "svn_checksum.h" |
| #include "svn_config.h" |
| #include "svn_error.h" |
| #include "svn_pools.h" |
| |
| #include "private/svn_dep_compat.h" |
| #include "private/svn_mutex.h" |
| #include "private/svn_object_pool.h" |
| #include "private/svn_subr_private.h" |
| #include "private/svn_repos_private.h" |
| #include "private/svn_string_private.h" |
| #include "private/svn_subr_private.h" |
| |
| #include "repos.h" |
| |
| /* Currently this structure is just a wrapper around a svn_config_t. |
| */ |
| struct svn_authz_t |
| { |
| svn_config_t *cfg; |
| }; |
| |
| /* The wrapper object structure that we store in the object pool. It |
| * combines the authz with the underlying config structures and their |
| * identifying keys. |
| */ |
| typedef struct authz_object_t |
| { |
| /* key = concatenation of AUTHZ_KEY and GROUPS_KEY */ |
| svn_membuf_t *key; |
| |
| /* keys used to identify AUTHZ_CFG and GROUPS_CFG */ |
| svn_membuf_t *authz_key; |
| svn_membuf_t *groups_key; |
| |
| /* r/o references to configurations from the configuration pool. |
| GROUPS_CFG may be NULL. */ |
| svn_config_t *authz_cfg; |
| svn_config_t *groups_cfg; |
| |
| /* Case-sensitive config. */ |
| svn_authz_t *authz; |
| } authz_object_t; |
| |
| /* Root data structure simply adding the config_pool to the basic object pool. |
| */ |
| struct svn_repos__authz_pool_t |
| { |
| /* authz_object_t object storage */ |
| svn_object_pool__t *object_pool; |
| |
| /* factory and storage of (shared) configuration objects */ |
| svn_repos__config_pool_t *config_pool; |
| }; |
| |
| /* Return a combination of AUTHZ_KEY and GROUPS_KEY, allocated in POOL. |
| * GROUPS_KEY may be NULL. |
| */ |
| static svn_membuf_t * |
| construct_key(svn_membuf_t *authz_key, |
| svn_membuf_t *groups_key, |
| apr_pool_t *pool) |
| { |
| svn_membuf_t *result = apr_pcalloc(pool, sizeof(*result)); |
| apr_size_t size; |
| if (groups_key) |
| { |
| size = authz_key->size + groups_key->size; |
| svn_membuf__create(result,size, pool); |
| memcpy(result->data, authz_key->data, authz_key->size); |
| memcpy((char *)result->data + authz_key->size, |
| groups_key->data, groups_key->size); |
| } |
| else |
| { |
| size = authz_key->size; |
| svn_membuf__create(result, size, pool); |
| memcpy(result->data, authz_key->data, authz_key->size); |
| } |
| |
| result->size = size; |
| return result; |
| } |
| |
| /* Implement svn_object_pool__getter_t on authz_object_t structures. |
| */ |
| static void * |
| getter(void *object, |
| void *baton, |
| apr_pool_t *pool) |
| { |
| return ((authz_object_t *)object)->authz; |
| } |
| |
| /* API implementation */ |
| |
| svn_error_t * |
| svn_repos__authz_pool_create(svn_repos__authz_pool_t **authz_pool, |
| svn_repos__config_pool_t *config_pool, |
| svn_boolean_t thread_safe, |
| apr_pool_t *pool) |
| { |
| svn_repos__authz_pool_t *result; |
| svn_object_pool__t *object_pool; |
| |
| /* there is no setter as we don't need to update existing authz */ |
| SVN_ERR(svn_object_pool__create(&object_pool, getter, NULL, thread_safe, |
| pool)); |
| |
| result = apr_pcalloc(pool, sizeof(*result)); |
| result->object_pool = object_pool; |
| result->config_pool = config_pool; |
| |
| *authz_pool = result; |
| return SVN_NO_ERROR; |
| } |
| |
| svn_error_t * |
| svn_repos__authz_pool_get(svn_authz_t **authz_p, |
| svn_repos__authz_pool_t *authz_pool, |
| const char *path, |
| const char *groups_path, |
| svn_boolean_t must_exist, |
| svn_repos_t *preferred_repos, |
| apr_pool_t *pool) |
| { |
| apr_pool_t *authz_ref_pool |
| = svn_object_pool__new_wrapper_pool(authz_pool->object_pool); |
| authz_object_t *authz_ref |
| = apr_pcalloc(authz_ref_pool, sizeof(*authz_ref)); |
| svn_boolean_t have_all_keys; |
| |
| /* read the configurations */ |
| SVN_ERR(svn_repos__config_pool_get(&authz_ref->authz_cfg, |
| &authz_ref->authz_key, |
| authz_pool->config_pool, |
| path, must_exist, TRUE, |
| preferred_repos, authz_ref_pool)); |
| have_all_keys = authz_ref->authz_key != NULL; |
| |
| if (groups_path) |
| { |
| SVN_ERR(svn_repos__config_pool_get(&authz_ref->groups_cfg, |
| &authz_ref->groups_key, |
| authz_pool->config_pool, |
| groups_path, must_exist, TRUE, |
| preferred_repos, authz_ref_pool)); |
| have_all_keys &= authz_ref->groups_key != NULL; |
| } |
| |
| /* fall back to standard implementation in case we don't have all the |
| * facts (i.e. keys). */ |
| if (!have_all_keys) |
| return svn_error_trace(svn_repos_authz_read2(authz_p, path, groups_path, |
| must_exist, pool)); |
| |
| /* all keys are known and lookup is unambigious. */ |
| authz_ref->key = construct_key(authz_ref->authz_key, |
| authz_ref->groups_key, |
| authz_ref_pool); |
| |
| SVN_ERR(svn_object_pool__lookup((void **)authz_p, authz_pool->object_pool, |
| authz_ref->key, NULL, pool)); |
| if (*authz_p) |
| { |
| svn_pool_destroy(authz_ref_pool); |
| return SVN_NO_ERROR; |
| } |
| |
| authz_ref->authz = apr_palloc(authz_ref_pool, sizeof(*authz_ref->authz)); |
| authz_ref->authz->cfg = authz_ref->authz_cfg; |
| |
| if (groups_path) |
| { |
| /* Easy out: we prohibit local groups in the authz file when global |
| groups are being used. */ |
| if (svn_config_has_section(authz_ref->authz->cfg, |
| SVN_CONFIG_SECTION_GROUPS)) |
| return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, |
| "Error reading authz file '%s' with " |
| "groups file '%s':" |
| "Authz file cannot contain any groups " |
| "when global groups are being used.", |
| path, groups_path); |
| |
| /* We simply need to add the [Groups] section to the authz config. |
| */ |
| svn_config__shallow_replace_section(authz_ref->authz->cfg, |
| authz_ref->groups_cfg, |
| SVN_CONFIG_SECTION_GROUPS); |
| } |
| |
| /* Make sure there are no errors in the configuration. */ |
| SVN_ERR(svn_repos__authz_validate(authz_ref->authz, authz_ref_pool)); |
| |
| SVN_ERR(svn_object_pool__insert((void **)authz_p, authz_pool->object_pool, |
| authz_ref->key, authz_ref, NULL, |
| authz_ref_pool, pool)); |
| |
| return SVN_NO_ERROR; |
| } |