xref: /freebsd-13-stable/contrib/subversion/subversion/libsvn_repos/authz.h (revision b7ec5dea64b6513b41316a38cc72efa9139bc4ae)
1 /* authz.h : authz parsing and searching, private to libsvn_repos
2  *
3  * ====================================================================
4  *    Licensed to the Apache Software Foundation (ASF) under one
5  *    or more contributor license agreements.  See the NOTICE file
6  *    distributed with this work for additional information
7  *    regarding copyright ownership.  The ASF licenses this file
8  *    to you under the Apache License, Version 2.0 (the
9  *    "License"); you may not use this file except in compliance
10  *    with the License.  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *    Unless required by applicable law or agreed to in writing,
15  *    software distributed under the License is distributed on an
16  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  *    KIND, either express or implied.  See the License for the
18  *    specific language governing permissions and limitations
19  *    under the License.
20  * ====================================================================
21  */
22 
23 #ifndef SVN_REPOS_AUTHZ_H
24 #define SVN_REPOS_AUTHZ_H
25 
26 #include <apr_hash.h>
27 #include <apr_pools.h>
28 #include <apr_tables.h>
29 
30 #include "svn_config.h"
31 #include "svn_error.h"
32 #include "svn_io.h"
33 #include "svn_repos.h"
34 
35 #include "private/svn_string_private.h"
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif /* __cplusplus */
40 
41 
42 /*
43  *   Authz and global group file parsing
44  */
45 
46 /* A dictionary of rules that are specific to a particular
47    (user, repository) combination. */
48 typedef struct authz_user_rules_t authz_user_rules_t;
49 
50 
51 /* Access rights in an ACL.
52  *
53  * This enum is different from and incompatible with
54  * svn_repos_authz_access_t, because it has different semantics and
55  * encodes rights that are not and should never be exposed in the
56  * public API.
57  */
58 typedef enum authz_access_t
59 {
60   /*
61    * Individual access flags
62    */
63 
64   /* TODO: Future extension for lookup/traverse access.
65   authz_access_lookup_flag = 0x10, */
66 
67   /* Read access allows listing directory entries, reading file
68      contents and reading properties of files and directories. */
69   authz_access_read_flag = 0x20,
70 
71   /* Write access allows adding, removing and renaming directory
72      entries, modifying file contents and adding, removing and
73      modifying properties of files and directories. */
74   authz_access_write_flag = 0x40,
75 
76   /*
77    * Combined access flags
78    */
79 
80   /* No access. */
81   authz_access_none = 0,
82 
83 
84   /* TODO: Lookup access is a synonym for the lookup flag.
85   authz_access_lookup = authz_access_lookup_flag, */
86 
87   /* Read access (TODO: implies lookup access). */
88   authz_access_read = authz_access_read_flag /* TODO: | authz_access_lookup */,
89 
90   /* Write access implies read (TODO: and lookup) access. */
91   authz_access_write = authz_access_write_flag | authz_access_read
92 } authz_access_t;
93 
94 
95 /* Accumulated rights for (user, repository). */
96 typedef struct authz_rights_t
97 {
98   /* The lowest level of access that the user has to every
99      path in the repository. */
100   authz_access_t min_access;
101 
102   /* The highest level of access that the user has to
103      any path in the repository. */
104   authz_access_t max_access;
105 } authz_rights_t;
106 
107 
108 /* Accumulated global rights for a specific user. */
109 typedef struct authz_global_rights_t
110 {
111   /* The user name. */
112   const char *user;
113 
114   /* Accumulated rights for this user from rules that are not
115      repository-specific. We use this to avoid a hash lookup for the
116      "any" repository rights. */
117   authz_rights_t any_repos_rights;
118 
119   /* Accumulated rights for this user across all repositories. */
120   authz_rights_t all_repos_rights;
121 
122   /* Accumulated rights for specific repositories.
123      The key is repository name, the value is an authz_rights_t*. */
124   apr_hash_t *per_repos_rights;
125 } authz_global_rights_t;
126 
127 
128 /* Immutable authorization info */
129 typedef struct authz_full_t
130 {
131   /* All ACLs from the authz file, in the order of definition. */
132   apr_array_header_t *acls;
133 
134   /* Globally accumulated rights for anonymous access. */
135   svn_boolean_t has_anon_rights;
136   authz_global_rights_t anon_rights;
137 
138   /* Globally accumulated rights for authenticated users. */
139   svn_boolean_t has_authn_rights;
140   authz_global_rights_t authn_rights;
141 
142   /* Globally accumulated rights from inverted selectors. */
143   svn_boolean_t has_neg_rights;
144   authz_global_rights_t neg_rights;
145 
146   /* Globally accumulated rights, for all concrete users mentioned
147      in the authz file. The key is the user name, the value is
148      an authz_global_rights_t*. */
149   apr_hash_t *user_rights;
150 
151   /* The pool from which all the parsed authz data is allocated.
152      This is the RESULT_POOL passed to svn_authz__tng_parse.
153 
154      It's a good idea to dedicate a pool for the authz structure, so
155      that the whole authz representation can be deallocated by
156      destroying the pool. */
157   apr_pool_t *pool;
158 } authz_full_t;
159 
160 
161 /* Dynamic authorization info */
162 struct svn_authz_t
163 {
164   /* The parsed and pre-processed contents of the authz file. */
165   authz_full_t *full;
166 
167   /* Identifies the authz model content
168    * (a hash value that can be used for e.g. cache lookups). */
169   svn_membuf_t *authz_id;
170 
171   /* Rules filtered for a particular user-repository combination.
172    * May be NULL. */
173   authz_user_rules_t *filtered;
174 
175   /* The pool from which all the parsed authz data is allocated.
176      This is the RESULT_POOL passed to svn_authz__tng_parse.
177 
178      It's a good idea to dedicate a pool for the authz structure, so
179      that the whole authz representation can be deallocated by
180      destroying the pool. */
181   apr_pool_t *pool;
182 };
183 
184 
185 /* Rule path segment descriptor. */
186 typedef struct authz_rule_segment_t
187 {
188   /* The segment type. */
189   enum {
190     /* A literal string match.
191        The path segment must exactly match the pattern.
192 
193        Note: Make sure this is always the first constant in the
194              enumeration, otherwise rules that match the repository
195              root will not sort first in the ACL list and the implicit
196              default no-access ACE will not be applied correctly. */
197     authz_rule_literal,
198 
199     /* A prefix match: a literal string followed by '*'.
200        The path segment must begin with the literal prefix. */
201     authz_rule_prefix,
202 
203     /* A suffix match: '*' followed by a literal string.
204        The path segment must end with the literal suffix.
205        The pattern is stored reversed, so that the matching code can
206        perform a prefix match on the reversed path segment. */
207     authz_rule_suffix,
208 
209     /* '*'
210        Matches any single non-empty path segment.
211        The pattern will be an empty string. */
212     authz_rule_any_segment,
213 
214     /* '**'
215        Matches any sequence of zero or more path segments.
216        The pattern will be an empty string. */
217     authz_rule_any_recursive,
218 
219     /* Any other glob/fnmatch pattern. */
220     authz_rule_fnmatch
221   } kind;
222 
223   /* The pattern for this path segment.
224      Any no-op fnmatch escape sequences (i.e., those that do not
225      escape a wildcard or character class) are stripped from the
226      string.
227 
228      The pattern string will be interned; therefore, two identical
229      rule patterns will always contain the same pointer value and
230      equality can therefore be tested by comparing the pointer
231      values and segment kinds. */
232   svn_string_t pattern;
233 } authz_rule_segment_t;
234 
235 /* Rule path descriptor. */
236 typedef struct authz_rule_t
237 {
238   /* The repository that this rule applies to. This will be the empty
239      string string if a the rule did not name a repository. The
240      repository name is interned. */
241   const char *repos;
242 
243   /* The number of segments in the rule path. */
244   int len;
245 
246   /* The array of path segments for this rule. Will be NULL for the
247      repository root. */
248   authz_rule_segment_t *path;
249 } authz_rule_t;
250 
251 
252 /* An access control list defined by access rules. */
253 typedef struct authz_acl_t
254 {
255   /* The sequence number of the ACL stores the order in which access
256      rules were defined in the authz file. The authz lookup code
257      selects the highest-numbered ACL from amongst a set of equivalent
258      matches. */
259   int sequence_number;
260 
261   /* The parsed rule. */
262   authz_rule_t rule;
263 
264 
265   /* Access rights for anonymous users. */
266   svn_boolean_t has_anon_access;
267   authz_access_t anon_access;
268 
269   /* Access rights for authenticated users. */
270   svn_boolean_t has_authn_access;
271   authz_access_t authn_access;
272 
273   /* Access rights from inverted selectors. */
274   svn_boolean_t has_neg_access;
275   authz_access_t neg_access;
276 
277   /* All other user- or group-specific access rights.
278      Aliases are replaced with their definitions, rules for the same
279      user or group are merged. */
280   apr_array_header_t *user_access;
281 } authz_acl_t;
282 
283 
284 /* An access control entry in authz_acl_t::user_access. */
285 typedef struct authz_ace_t
286 {
287   /* The name of the alias, user or group that this ACE applies to. */
288   const char *name;
289 
290   /* The set of group members, when NAME is the name of a group.
291      We store this reference in the ACE to save a hash lookup when
292      resolving access for group ACEs.
293    */
294   apr_hash_t *members;
295 
296   /* True if this is an inverse-match rule. */
297   svn_boolean_t inverted;
298 
299   /* The access rights defined by this ACE. */
300   authz_access_t access;
301 } authz_ace_t;
302 
303 
304 /* Parse authz definitions from RULES and optional global group
305  * definitions from GROUPS, returning an immutable, in-memory
306  * representation of all the rules, groups and aliases.
307  *
308  * **AUTHZ and its contents will be allocated from RESULT_POOL.
309  * The function uses SCRATCH_POOL for temporary allocations.
310  */
311 svn_error_t *
312 svn_authz__parse(authz_full_t **authz,
313                  svn_stream_t *rules,
314                  svn_stream_t *groups,
315                  svn_repos_authz_warning_func_t warning_func,
316                  void *warning_baton,
317                  apr_pool_t *result_pool,
318                  apr_pool_t *scratch_pool);
319 
320 
321 /* Reverse a STRING of length LEN in place. */
322 void
323 svn_authz__reverse_string(char *string, apr_size_t len);
324 
325 
326 /* Compare two rules in lexical order by path only. */
327 int
328 svn_authz__compare_paths(const authz_rule_t *a, const authz_rule_t *b);
329 
330 /* Compare two rules in path lexical order, then repository lexical order. */
331 int
332 svn_authz__compare_rules(const authz_rule_t *a, const authz_rule_t *b);
333 
334 
335 /*
336  *   Authorization lookup
337  */
338 
339 /* The "anonymous" user for authz queries. */
340 #define AUTHZ_ANONYMOUS_USER ((const char*)"")
341 
342 /* Rules with this repository name apply to all repositories. */
343 #define AUTHZ_ANY_REPOSITORY ((const char*)"")
344 
345 /* Check if the ACL applies to the REPOS pair. */
346 svn_boolean_t
347 svn_authz__acl_applies_to_repo(const authz_acl_t *acl,
348                                const char *repos);
349 
350 /* Check if the ACL applies to the (USER, REPOS) pair.  If it does,
351  * and ACCESS is not NULL, set *ACCESS to the actual access rights for
352  * the user in this repository.
353  */
354 svn_boolean_t
355 svn_authz__get_acl_access(authz_access_t *access,
356                           const authz_acl_t *acl,
357                           const char *user, const char *repos);
358 
359 
360 /* Set *RIGHTS to the accumulated global access rights calculated in
361  * AUTHZ for (USER, REPOS).
362  * Return TRUE if the rights are explicit (i.e., an ACL for REPOS
363  * applies to USER, or REPOS is AUTHZ_ANY_REPOSITORY).
364  */
365 svn_boolean_t
366 svn_authz__get_global_rights(authz_rights_t *rights,
367                              const authz_full_t *authz,
368                              const char *user, const char *repos);
369 
370 
371 #ifdef __cplusplus
372 }
373 #endif /* __cplusplus */
374 
375 #endif /* SVN_REPOS_AUTHZ_H */
376