]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_repos/authz_pool.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_repos / authz_pool.c
1 /*
2  * authz_pool.c :  pool of authorization objects
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23
24 \f
25
26 #include "svn_checksum.h"
27 #include "svn_config.h"
28 #include "svn_error.h"
29 #include "svn_pools.h"
30
31 #include "private/svn_dep_compat.h"
32 #include "private/svn_mutex.h"
33 #include "private/svn_object_pool.h"
34 #include "private/svn_subr_private.h"
35 #include "private/svn_repos_private.h"
36 #include "private/svn_string_private.h"
37 #include "private/svn_subr_private.h"
38
39 #include "repos.h"
40
41 /* Currently this structure is just a wrapper around a svn_config_t.
42  */
43 struct svn_authz_t
44 {
45   svn_config_t *cfg;
46 };
47
48 /* The wrapper object structure that we store in the object pool.  It
49  * combines the authz with the underlying config structures and their
50  * identifying keys.
51  */
52 typedef struct authz_object_t
53 {
54   /* key = concatenation of AUTHZ_KEY and GROUPS_KEY */
55   svn_membuf_t *key;
56
57   /* keys used to identify AUTHZ_CFG and GROUPS_CFG */
58   svn_membuf_t *authz_key;
59   svn_membuf_t *groups_key;
60
61   /* r/o references to configurations from the configuration pool.
62      GROUPS_CFG may be NULL. */
63   svn_config_t *authz_cfg;
64   svn_config_t *groups_cfg;
65
66   /* Case-sensitive config. */
67   svn_authz_t *authz;
68 } authz_object_t;
69
70 /* Root data structure simply adding the config_pool to the basic object pool.
71  */
72 struct svn_repos__authz_pool_t
73 {
74   /* authz_object_t object storage */
75   svn_object_pool__t *object_pool;
76
77   /* factory and storage of (shared) configuration objects */
78   svn_repos__config_pool_t *config_pool;
79 };
80
81 /* Return a combination of AUTHZ_KEY and GROUPS_KEY, allocated in POOL.
82  * GROUPS_KEY may be NULL.
83  */
84 static svn_membuf_t *
85 construct_key(svn_membuf_t *authz_key,
86               svn_membuf_t *groups_key,
87               apr_pool_t *pool)
88 {
89   svn_membuf_t *result = apr_pcalloc(pool, sizeof(*result));
90   apr_size_t size;
91   if (groups_key)
92     {
93       size = authz_key->size + groups_key->size;
94       svn_membuf__create(result,size, pool);
95       memcpy(result->data, authz_key->data, authz_key->size);
96       memcpy((char *)result->data + authz_key->size,
97              groups_key->data, groups_key->size);
98     }
99   else
100     {
101       size = authz_key->size;
102       svn_membuf__create(result, size, pool);
103       memcpy(result->data, authz_key->data, authz_key->size);
104     }
105
106   result->size = size;
107   return result;
108 }
109
110 /* Implement svn_object_pool__getter_t on authz_object_t structures.
111  */
112 static void *
113 getter(void *object,
114        void *baton,
115        apr_pool_t *pool)
116 {
117   return ((authz_object_t *)object)->authz;
118 }
119
120 /* API implementation */
121
122 svn_error_t *
123 svn_repos__authz_pool_create(svn_repos__authz_pool_t **authz_pool,
124                              svn_repos__config_pool_t *config_pool,
125                              svn_boolean_t thread_safe,
126                              apr_pool_t *pool)
127 {
128   svn_repos__authz_pool_t *result;
129   svn_object_pool__t *object_pool;
130
131   /* there is no setter as we don't need to update existing authz */
132   SVN_ERR(svn_object_pool__create(&object_pool, getter, NULL, thread_safe,
133                                   pool));
134
135   result = apr_pcalloc(pool, sizeof(*result));
136   result->object_pool = object_pool;
137   result->config_pool = config_pool;
138
139   *authz_pool = result;
140   return SVN_NO_ERROR;
141 }
142
143 svn_error_t *
144 svn_repos__authz_pool_get(svn_authz_t **authz_p,
145                           svn_repos__authz_pool_t *authz_pool,
146                           const char *path,
147                           const char *groups_path,
148                           svn_boolean_t must_exist,
149                           svn_repos_t *preferred_repos,
150                           apr_pool_t *pool)
151 {
152   apr_pool_t *authz_ref_pool
153     = svn_object_pool__new_wrapper_pool(authz_pool->object_pool);
154   authz_object_t *authz_ref
155     = apr_pcalloc(authz_ref_pool, sizeof(*authz_ref));
156   svn_boolean_t have_all_keys;
157
158   /* read the configurations */
159   SVN_ERR(svn_repos__config_pool_get(&authz_ref->authz_cfg,
160                                      &authz_ref->authz_key,
161                                      authz_pool->config_pool,
162                                      path, must_exist, TRUE,
163                                      preferred_repos, authz_ref_pool));
164   have_all_keys = authz_ref->authz_key != NULL;
165
166   if (groups_path)
167     {
168       SVN_ERR(svn_repos__config_pool_get(&authz_ref->groups_cfg,
169                                          &authz_ref->groups_key,
170                                          authz_pool->config_pool,
171                                          groups_path, must_exist, TRUE,
172                                          preferred_repos, authz_ref_pool));
173       have_all_keys &= authz_ref->groups_key != NULL;
174     }
175
176   /* fall back to standard implementation in case we don't have all the
177    * facts (i.e. keys). */
178   if (!have_all_keys)
179     return svn_error_trace(svn_repos_authz_read2(authz_p, path, groups_path,
180                                                  must_exist, pool));
181
182   /* all keys are known and lookup is unambigious. */
183   authz_ref->key = construct_key(authz_ref->authz_key,
184                                  authz_ref->groups_key,
185                                  authz_ref_pool);
186
187   SVN_ERR(svn_object_pool__lookup((void **)authz_p, authz_pool->object_pool,
188                                   authz_ref->key, NULL, pool));
189   if (*authz_p)
190     {
191       svn_pool_destroy(authz_ref_pool);
192       return SVN_NO_ERROR;
193     }
194
195   authz_ref->authz = apr_palloc(authz_ref_pool, sizeof(*authz_ref->authz));
196   authz_ref->authz->cfg = authz_ref->authz_cfg;
197
198   if (groups_path)
199     {
200       /* Easy out: we prohibit local groups in the authz file when global
201          groups are being used. */
202       if (svn_config_has_section(authz_ref->authz->cfg,
203                                  SVN_CONFIG_SECTION_GROUPS))
204         return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
205                                  "Error reading authz file '%s' with "
206                                  "groups file '%s':"
207                                  "Authz file cannot contain any groups "
208                                  "when global groups are being used.",
209                                  path, groups_path);
210
211       /* We simply need to add the [Groups] section to the authz config.
212        */
213       svn_config__shallow_replace_section(authz_ref->authz->cfg,
214                                           authz_ref->groups_cfg,
215                                           SVN_CONFIG_SECTION_GROUPS);
216     }
217
218   /* Make sure there are no errors in the configuration. */
219   SVN_ERR(svn_repos__authz_validate(authz_ref->authz, authz_ref_pool));
220
221   SVN_ERR(svn_object_pool__insert((void **)authz_p, authz_pool->object_pool,
222                                   authz_ref->key, authz_ref, NULL,
223                                   authz_ref_pool, pool));
224
225   return SVN_NO_ERROR;
226 }