subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1616738 - in /subversion/branches/authzperf/subversion: libsvn_repos/authz.h libsvn_repos/authz_parse.c tests/libsvn_repos/authz-test.c
Date Fri, 08 Aug 2014 12:58:49 GMT
Author: brane
Date: Fri Aug  8 12:58:49 2014
New Revision: 1616738

URL: http://svn.apache.org/r1616738
Log:
On the authzperf branch: Pre-calculate global rights for all users
mentioned in the authz file across all repositories.

* subversion/libsvn_repos/authz.h
  (authz_rights_t): New.
  (authz_global_rights_t): Redefine.
  (svn_authz_tng_t): New members has_anon_rights, anon_rights,
   has_authn_rights and authn_rights. Rename global_rights to
   user_rights and update its docstring.

* subversion/libsvn_repos/authz_parse.c
  (init_rights, init_global_rights): New.
  (create_ctor_baton): Initialize the new members of the authz structure.
  (prepare_global_rights): New.
  (add_alias_definition): Initialize the user's global rights.
  (add_access_entry, expand_group_callback): Likewise.
  (update_rights, update_global_rights): New.
  (update_user_rights): New hash iterator callback.
  (expand_acl_callback): Accumulate global rights for the ACL.
  (svn_authz__tng_parse): Remove obsolete initialization.

* subversion/tests/libsvn_repos/authz-test.c
  (print_repos_rights, print_user_rights): New hash iterator callbacks.
  (test_authz_parse_tng): Print accumulated global rights.

Modified:
    subversion/branches/authzperf/subversion/libsvn_repos/authz.h
    subversion/branches/authzperf/subversion/libsvn_repos/authz_parse.c
    subversion/branches/authzperf/subversion/tests/libsvn_repos/authz-test.c

Modified: subversion/branches/authzperf/subversion/libsvn_repos/authz.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_repos/authz.h?rev=1616738&r1=1616737&r2=1616738&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_repos/authz.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_repos/authz.h Fri Aug  8 12:58:49 2014
@@ -60,12 +60,9 @@ extern "C" {
 typedef struct authz_user_rules_t authz_user_rules_t;
 
 
-/* Accumulated global rights for (user, repository). */
-typedef struct authz_global_rights_t
+/* Accumulated rights for (user, repository). */
+typedef struct authz_rights_t
 {
-  /* Interned key of this instance in svn_authz_tng_t::global_rights. */
-  const char *key;
-
   /* The lowest level of access that the user has to every
      path in the repository. */
   svn_repos_authz_access_t min_access;
@@ -73,6 +70,26 @@ typedef struct authz_global_rights_t
   /* The highest level of access that the user has to
      any path in the repository. */
   svn_repos_authz_access_t max_access;
+} authz_rights_t;
+
+
+/* Accumulated global rights for a specific user. */
+typedef struct authz_global_rights_t
+{
+  /* The user name. */
+  const char *user;
+
+  /* Accumulated rights for this user across all repositories. */
+  authz_rights_t all_repos_rights;
+
+  /* Accumulated rights for this user from rules that are not
+     repository-specific. We use this to avoid a hash lookup for the
+     "any" repository rights. */
+  authz_rights_t any_repos_rights;
+
+  /* Accumulated rights for specific repositories.
+     The key is repository name, the value is an authz_rights_t*. */
+  apr_hash_t *per_repos_rights;
 } authz_global_rights_t;
 
 
@@ -82,9 +99,18 @@ typedef struct svn_authz_tng_t
   /* All ACLs from the authz file, in the order of definition. */
   apr_array_header_t *acls;
 
+  /* Globally accumulated rights for anonymous access. */
+  svn_boolean_t has_anon_rights;
+  authz_global_rights_t anon_rights;
+
+  /* Globally accumulated rights for authenticated users. */
+  svn_boolean_t has_authn_rights;
+  authz_global_rights_t authn_rights;
+
   /* Globally accumulated rights, for all concrete users mentioned
-     in the authz file, indexed by (user, repository). */
-  apr_hash_t *global_rights;
+     in the authz file. The key is the user name, the value is
+     an authz_global_rights_t*. */
+  apr_hash_t *user_rights;
 
   /* Fully recursively expanded group definitions, indexed by group name. */
   apr_hash_t *groups;

Modified: subversion/branches/authzperf/subversion/libsvn_repos/authz_parse.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_repos/authz_parse.c?rev=1616738&r1=1616737&r2=1616738&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_repos/authz_parse.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_repos/authz_parse.c Fri Aug  8 12:58:49
2014
@@ -109,7 +109,7 @@ typedef struct ctor_baton_t
   /* Temporary alias mappings. */
   apr_hash_t *parsed_aliases;
 
-  /* temporary parsed-acl definitions. */
+  /* Temporary parsed-acl definitions. */
   apr_array_header_t *parsed_acls;
 
   /* The temporary ACL we're currently constructing. */
@@ -140,6 +140,29 @@ static const char anon_access_token[] = 
 static const char authn_access_token[] = "$authenticated";
 
 
+/* Initialize a rights structure.
+   The minimum rights start with all available access and are later
+   bitwise-and'ed with actual access rights. The maximum rights begin
+   empty and are later bitwise-and'ed with actual rights. */
+static void init_rights(authz_rights_t *rights)
+{
+  rights->min_access = svn_authz_read | svn_authz_write;
+  rights->max_access = svn_authz_none;
+ }
+
+/* Initialize a global rights structure.
+   The USER string must be interned or statically initialized. */
+static void
+init_global_rights(authz_global_rights_t *gr, const char *user,
+                   apr_pool_t *result_pool)
+{
+  gr->user = user;
+  init_rights(&gr->all_repos_rights);
+  init_rights(&gr->any_repos_rights);
+  gr->per_repos_rights = apr_hash_make(result_pool);
+}
+
+
 /* Initialize a constuctor baton. */
 static ctor_baton_t *
 create_ctor_baton(apr_pool_t *result_pool,
@@ -149,6 +172,9 @@ create_ctor_baton(apr_pool_t *result_poo
   ctor_baton_t *const cb = apr_pcalloc(parser_pool, sizeof(*cb));
 
   svn_authz_tng_t *const authz = apr_pcalloc(result_pool, sizeof(*authz));
+  init_global_rights(&authz->anon_rights, anon_access_token, result_pool);
+  init_global_rights(&authz->authn_rights, authn_access_token, result_pool);
+  authz->user_rights = svn_hash__make(result_pool);
   authz->pool = result_pool;
 
   cb->authz = authz;
@@ -171,6 +197,21 @@ create_ctor_baton(apr_pool_t *result_poo
 }
 
 
+/* Create and store per-user global rights.
+   The USER string must be interned or statically initialized. */
+static void
+prepare_global_rights(ctor_baton_t *cb, const char *user)
+{
+  authz_global_rights_t *gr = svn_hash_gets(cb->authz->user_rights, user);
+  if (!gr)
+    {
+      gr = apr_palloc(cb->authz->pool, sizeof(*gr));
+      init_global_rights(gr, user, cb->authz->pool);
+      svn_hash_sets(cb->authz->user_rights, gr->user, gr);
+    }
+}
+
+
 /* Internalize a string that will be referenced by the parsed svn_authz_t.
    If LEN is (apr_size_t)-1, assume the string is NUL-terminated. */
 static const char *
@@ -395,6 +436,7 @@ add_alias_definition(ctor_baton_t *cb,
                      const char *option, const char *value)
 {
   const char *alias;
+  const char *user;
 
   if (strchr("@$&*~", *option))
     return svn_error_createf(
@@ -411,8 +453,11 @@ add_alias_definition(ctor_baton_t *cb,
         _("Can't override definition of alias '%s'"),
         alias);
 
-  svn_hash_sets(cb->parsed_aliases, alias,
-                intern_string(cb, value, -1));
+  user = intern_string(cb, value, -1);
+  svn_hash_sets(cb->parsed_aliases, alias, user);
+
+  /* Prepare the global rights struct for this user. */
+  prepare_global_rights(cb, user);
   return SVN_NO_ERROR;
 }
 
@@ -553,6 +598,10 @@ add_access_entry(ctor_baton_t *cb, const
                  ? apr_pstrdup(cb->parser_pool, key)
                  : ace->name);
           svn_hash_sets(aces, key, ace);
+
+          /* Prepare the global rights struct for this user. */
+          if (!aliased && *ace->name != '@')
+            prepare_global_rights(cb, ace->name);
         }
     }
 
@@ -645,7 +694,11 @@ expand_group_callback(void *baton,
       else if (*member != '@')
         {
           /* Add the member to the group. */
-          add_to_group(cb, group, intern_string(cb, member, -1));
+          const char *user = intern_string(cb, member, -1);
+          add_to_group(cb, group, user);
+
+          /* Prepare the global rights struct for this user. */
+          prepare_global_rights(cb, user);
         }
       else
         {
@@ -756,6 +809,63 @@ array_insert_ace(void *baton,
 }
 
 
+/* Update accumulated RIGHTS from ACCESS. */
+static void
+update_rights(authz_rights_t *rights,
+              svn_repos_authz_access_t access)
+{
+  rights->min_access &= access;
+  rights->max_access |= access;
+}
+
+
+/* Update a global RIGHTS based on REPOS and ACCESS. */
+static void
+update_global_rights(authz_global_rights_t *gr,
+                     const char *repos,
+                     svn_repos_authz_access_t access)
+{
+  update_rights(&gr->all_repos_rights, access);
+  if (0 == strcmp(repos, AUTHZ_ANY_REPOSITORY))
+    update_rights(&gr->any_repos_rights, access);
+  else
+    {
+      authz_rights_t *rights = svn_hash_gets(gr->per_repos_rights, repos);
+      if (rights)
+        update_rights(rights, access);
+      else
+        {
+          rights = apr_palloc(apr_hash_pool_get(gr->per_repos_rights),
+                              sizeof(*rights));
+          init_rights(rights);
+          update_rights(rights, access);
+          svn_hash_sets(gr->per_repos_rights, repos, rights);
+        }
+    }
+}
+
+
+/* Hash iterator to update global per-user rights from an ACL. */
+static svn_error_t *
+update_user_rights(void *baton,
+                   const void *key,
+                   apr_ssize_t klen,
+                   void *value,
+                   apr_pool_t *scratch_pool)
+{
+  const authz_acl_t *const acl = baton;
+  const char *const user = key;
+  authz_global_rights_t *const gr = value;
+  svn_repos_authz_access_t access;
+  svn_boolean_t has_access =
+    svn_authz__acl_get_access(&access, acl, user, acl->repos);
+
+  if (has_access)
+    update_global_rights(gr, acl->repos, access);
+  return SVN_NO_ERROR;
+}
+
+
 /* List iterator, expands/merges a parsed ACL into its final form and
    appends it to the authz info's ACL array. */
 static svn_error_t *
@@ -765,6 +875,7 @@ expand_acl_callback(void *baton,
 {
   ctor_baton_t *const cb = baton;
   parsed_acl_t *const pacl = item;
+  authz_acl_t *const acl = &pacl->acl;
 
   /* Expand and merge the aliased ACEs. */
   if (apr_hash_count(pacl->alias_aces))
@@ -777,22 +888,35 @@ expand_acl_callback(void *baton,
     }
 
   /* Make an array from the merged hashes. */
-  pacl->acl.user_access =
+  acl->user_access =
     apr_array_make(cb->authz->pool, apr_hash_count(pacl->aces),
                    sizeof(authz_ace_t));
   {
     insert_ace_baton_t iab;
-    iab.ace_array = pacl->acl.user_access;
+    iab.ace_array = acl->user_access;
     iab.cb = cb;
     SVN_ERR(svn_iter_apr_hash(NULL, pacl->aces,
                               array_insert_ace, &iab, scratch_pool));
   }
 
-  /* TODO: Calculate global access rules. */
-
-  /* And finally store the completed ACL into authz. */
-  APR_ARRAY_PUSH(cb->authz->acls, authz_acl_t) = pacl->acl;
+  /* Store the completed ACL into authz. */
+  APR_ARRAY_PUSH(cb->authz->acls, authz_acl_t) = *acl;
 
+  /* Update global access rights for this ACL. */
+  if (acl->has_anon_access)
+    {
+      cb->authz->has_anon_rights = TRUE;
+      update_global_rights(&cb->authz->anon_rights,
+                           acl->repos, acl->anon_access);
+    }
+  if (acl->has_authn_access)
+    {
+      cb->authz->has_authn_rights = TRUE;
+      update_global_rights(&cb->authz->authn_rights,
+                           acl->repos, acl->authn_access);
+    }
+  SVN_ERR(svn_iter_apr_hash(NULL, cb->authz->user_rights,
+                            update_user_rights, acl, scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -842,7 +966,6 @@ svn_authz__tng_parse(svn_authz_tng_t **a
 
   cb->authz->acls = apr_array_make(cb->authz->pool, cb->parsed_acls->nelts,
                                    sizeof(authz_acl_t));
-  cb->authz->global_rights = svn_hash__make(cb->authz->pool);
   SVN_ERR(svn_iter_apr_array(NULL, cb->parsed_acls,
                              expand_acl_callback, cb, cb->parser_pool));
 

Modified: subversion/branches/authzperf/subversion/tests/libsvn_repos/authz-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/tests/libsvn_repos/authz-test.c?rev=1616738&r1=1616737&r2=1616738&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/tests/libsvn_repos/authz-test.c (original)
+++ subversion/branches/authzperf/subversion/tests/libsvn_repos/authz-test.c Fri Aug  8 12:58:49
2014
@@ -73,6 +73,39 @@ access_string(svn_repos_authz_access_t a
     }
 }
 
+static svn_error_t *
+print_repos_rights(void *baton,
+                   const void *key, apr_ssize_t klen,
+                   void *val,
+                   apr_pool_t *pool)
+{
+  const char *repos = key;
+  authz_rights_t *rights = val;
+  printf("      %s = all:%s  some:%s\n", repos,
+         access_string(rights->min_access),
+         access_string(rights->max_access));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+print_user_rights(void *baton, const void *key, apr_ssize_t klen,
+                  void *val,
+                  apr_pool_t *pool)
+{
+  authz_global_rights_t *gr = val;
+
+  printf("   %s\n", gr->user);
+  printf("      [all] = all:%s  some:%s\n",
+         access_string(gr->all_repos_rights.min_access),
+         access_string(gr->all_repos_rights.max_access));
+  printf("      [any] = all:%s  some:%s\n",
+         access_string(gr->any_repos_rights.min_access),
+         access_string(gr->any_repos_rights.max_access));
+  SVN_ERR(svn_iter_apr_hash(NULL, gr->per_repos_rights,
+                            print_repos_rights, NULL, pool));
+  return SVN_NO_ERROR;
+}
+
 
 static svn_error_t *
 test_authz_parse_tng(const svn_test_opts_t *opts,
@@ -159,6 +192,15 @@ test_authz_parse_tng(const svn_test_opts
                             print_group, NULL, pool));
   printf("\n\n");
 
+  printf("[users]\n");
+  if (authz->has_anon_rights)
+    print_user_rights(NULL, NULL, 0, &authz->anon_rights, pool);
+  if (authz->has_authn_rights)
+    print_user_rights(NULL, NULL, 0, &authz->authn_rights, pool);
+  SVN_ERR(svn_iter_apr_hash(NULL, authz->user_rights,
+                            print_user_rights, NULL, pool));
+  printf("\n\n");
+
   return SVN_NO_ERROR;
 }
 



Mime
View raw message