blob: f8ac52835876ed4616fff4561ad00bd5dcbaf41d [file] [log] [blame]
/*
* 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;
}