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