You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/11/28 06:52:28 UTC

svn commit: r1414537 - in /subversion/branches/in-repo-authz/subversion: include/svn_repos.h libsvn_repos/authz.c

Author: breser
Date: Wed Nov 28 05:52:27 2012
New Revision: 1414537

URL: http://svn.apache.org/viewvc?rev=1414537&view=rev
Log:
On the in-repo-authz branch: Add a svn_repos_authz_read2() API that knows how
to read config files from inside the repo.

* subversion/include/svn_repos.h
  (svn_repos_authz_read): Deprecate.
  (svn_repos_authz_read2): Add

* subversion/libsvn_repos/authz.c
  (svn_repos_authz_read2, authz_retrieve_config, authz_retrieve_config_url): Add
  

Modified:
    subversion/branches/in-repo-authz/subversion/include/svn_repos.h
    subversion/branches/in-repo-authz/subversion/libsvn_repos/authz.c

Modified: subversion/branches/in-repo-authz/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/include/svn_repos.h?rev=1414537&r1=1414536&r2=1414537&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/include/svn_repos.h (original)
+++ subversion/branches/in-repo-authz/subversion/include/svn_repos.h Wed Nov 28 05:52:27 2012
@@ -3147,16 +3147,15 @@ svn_repos_get_fs_build_parser(const svn_
  */
 typedef struct svn_authz_t svn_authz_t;
 
-/** Read authz configuration data from @a file (a file or registry
- * path) into @a *authz_p, allocated in @a pool.
- *
- * If @a file is not a valid authz rule file, then return
- * SVN_AUTHZ_INVALID_CONFIG.  The contents of @a *authz_p is then
- * undefined.  If @a must_exist is TRUE, a missing authz file is also
- * an error.
+/** 
+ * Similar to svn_repos_authz_read2(), but without support for
+ * authz files stored in a Subversion repository (absolute or
+ * relative URLs) and without the @a repos_root argument.
  *
  * @since New in 1.3.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_repos_authz_read(svn_authz_t **authz_p,
                      const char *file,
@@ -3164,6 +3163,29 @@ svn_repos_authz_read(svn_authz_t **authz
                      apr_pool_t *pool);
 
 /**
+ * Read authz configuration data from @a path (a file, repos relative
+ * url, an absolute file url, or a registry path) into @a *authz_p,
+ * allocated in @a pool.
+ *
+ * If @a path is not a valid authz rule file, then return 
+ * SVN_AUTHZ_INVALID_CONFIG.  The contents of @a *authz_p is then
+ * undefined.  If @a must_exist is TRUE, a missing authz file is also
+ * an error.
+ *
+ * If @path is a repos relative URL then @a repos_root must be set to
+ * the root of the repository the authz configuration will be used with.
+ *
+ * @since New in 1.8
+ */
+svn_error_t *
+svn_repos_authz_read2(svn_authz_t **authz_p,
+                      const char *path,
+                      svn_boolean_t must_exist,
+                      const char *repos_root,
+                      apr_pool_t *pool);
+
+
+/**
  * Check whether @a user can access @a path in the repository @a
  * repos_name with the @a required_access.  @a authz lists the ACLs to
  * check against.  Set @a *access_granted to indicate if the requested

Modified: subversion/branches/in-repo-authz/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/libsvn_repos/authz.c?rev=1414537&r1=1414536&r2=1414537&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/in-repo-authz/subversion/libsvn_repos/authz.c Wed Nov 28 05:52:27 2012
@@ -750,11 +750,192 @@ static svn_boolean_t authz_validate_sect
   return TRUE;
 }
 
+/* Retrieve the file at URL and then parse it as a config file placing the
+ * result into CFG_P allocated in POOL.
+ *
+ * If URL is not a valid authz rule file then return SVN_AUTHZ_INVALD_CONFIG
+ * as the error.  The contents of CFG_P is then undefined.  If MUST_EXIST is
+ * TRUE, a missing authz file is also an error.
+ *
+ * SCRATCH_POOL will be used for temporary allocations. */
+static svn_error_t *
+authz_retrieve_config_url(svn_config_t **cfg_p, const char *url,
+                          svn_boolean_t must_exist,
+                          apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  svn_repos_t *repos;
+  const char *repos_dirent;
+  const char *repos_root_dirent;
+  const char *fs_path;
+  svn_fs_t *fs;
+  svn_fs_root_t *root;
+  svn_revnum_t youngest_rev;
+  svn_node_kind_t node_kind;
+  svn_stream_t *contents;
+  const char *canon_url = svn_uri_canonicalize(url, scratch_pool);
+
+  SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dirent, canon_url,
+                                           scratch_pool));
+
+  /* Search for a repository in the full path. */
+  repos_root_dirent = svn_repos_find_root_path(repos_dirent, scratch_pool);
+  if (!repos_root_dirent)
+    return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+                             "Unable to find repository at '%s'", url);
+
+  /* Attempt to open a repository at url. */
+  SVN_ERR(svn_repos_open2(&repos, repos_root_dirent, NULL, scratch_pool));
+
+  fs_path = &repos_dirent[strlen(repos_root_dirent)];
+
+  /* Root path is always a directory so no reason to go any further */
+  if (*fs_path == '\0')
+    return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+                             "'%s' is not a file", url);
+
+  /* We skip some things that are non-important for how we're going to use
+   * this repo connection.  We do not set any capabilities since none of
+   * the current ones are important for what we're doing.  We also do not
+   * setup the environment that repos hooks would run under since we won't
+   * be triggering any. */
+
+  /* Get the filesystem. */
+  fs = svn_repos_fs(repos);
+
+  /* Find HEAD and the revision root */
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool));
+  SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, scratch_pool));
+
+  SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool));
+  if (node_kind == svn_node_none)
+    {
+      if (!must_exist)
+        {
+          SVN_ERR(svn_config_create(cfg_p, TRUE, scratch_pool));
+          return SVN_NO_ERROR;
+        }
+      else
+        {
+          return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+                                   "'%s' path not found", url);
+        }
+    }
+  else if (node_kind != svn_node_file)
+    {
+      return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+                               "'%s' is not a file", url);
+    }
+
+  SVN_ERR(svn_fs_file_contents(&contents, root, fs_path, scratch_pool));
+  err = svn_config_parse(cfg_p, contents, TRUE, result_pool);
+
+  /* Add the URL to the error stack since the parser doesn't have it. */
+  if (err != SVN_NO_ERROR)
+    return svn_error_createf(err->apr_err, err, 
+                             "Error parsing config file: %s:", url);
+
+  return SVN_NO_ERROR;
+}
+
+/* Given a PATH which might be a realative repo URL (^/), an absolute
+ * local repo URL (file://), an absolute path outside of the repo
+ * or a location in the Windows registry.
+ *
+ * Retrieve the configuration data that PATH points at and parse it into
+ * CFG_P allocated in POOL.
+ *
+ * If PATH is not a valid authz rule file then return SVN_AUTHZ_INVALD_CONFIG
+ * as the error.  The contents of CFG_P is then undefined.  If MUST_EXIST is
+ * TRUE, a missing authz file is also an error.
+ *
+ * REPOS_ROOT points at the root of the repos you are
+ * going to apply the authz against, can be NULL if you are sure that you
+ * don't have a repos relative URL in PATH. */
+static svn_error_t *
+authz_retrieve_config(svn_config_t **cfg_p, const char *path,
+                      svn_boolean_t must_exist, const char *repos_root,
+                      apr_pool_t *pool)
+{
+  if (svn_path_is_repos_relative_url(path))
+    {
+      const char *repos_root_url;
+      const char *abs_url;
+      svn_error_t *err;
+      apr_pool_t *scratch_pool = svn_pool_create(pool);
+
+      /* Convert the repos_root to a file schema URL first, so we can
+       * work out 
+       * ### Is path or repos_root guaranteed to be in internal format
+       * ### already on Windows?  I don't think so, need to test on Windows.
+       * ### If not this isn't going to work right since it'll construct a
+       * ### URL with blackslahes instead of forward slashes.  */
+      err = svn_uri_get_file_url_from_dirent(&repos_root_url, repos_root,
+                                             scratch_pool);
+
+      if (err == SVN_NO_ERROR)
+        err = svn_path_resolve_repos_relative_url(&abs_url, path,
+                                                  repos_root_url,
+                                                  scratch_pool);
+
+      if (err == SVN_NO_ERROR) 
+        err = authz_retrieve_config_url(cfg_p, abs_url, must_exist, pool,
+                                        scratch_pool);
+
+      /* Close the repos and streams we opened. */
+      svn_pool_destroy(scratch_pool);
+
+      return err;
+    }
+  else if (svn_path_is_url(path))
+    {
+      svn_error_t *err;
+      apr_pool_t *scratch_pool = svn_pool_create(pool); 
+
+      err = authz_retrieve_config_url(cfg_p, path, must_exist, pool,
+                                      scratch_pool);
+
+      /* Close the repos and streams we opened. */
+      svn_pool_destroy(scratch_pool);
+
+      return err;
+    }
+  else
+    {
+      /* Outside of repo file or Windows registry*/
+      SVN_ERR(svn_config_read2(cfg_p, path, must_exist, TRUE, pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 
 /*** Public functions. ***/
 
 svn_error_t *
+svn_repos_authz_read2(svn_authz_t **authz_p, const char *path,
+                      svn_boolean_t must_exist, const char *repos_root,
+                      apr_pool_t *pool)
+{
+  svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
+  struct authz_validate_baton baton = { 0 };
+
+  baton.err = SVN_NO_ERROR;
+  SVN_ERR(authz_retrieve_config(&authz->cfg, path, must_exist, repos_root,
+                                pool));
+  baton.config = authz->cfg;
+
+  /* Step through the entire rule file, stopping on error. */
+  svn_config_enumerate_sections2(authz->cfg, authz_validate_section,
+                                 &baton, pool);
+  SVN_ERR(baton.err);
+
+  *authz_p = authz;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
                      svn_boolean_t must_exist, apr_pool_t *pool)
 {
@@ -776,7 +957,6 @@ svn_repos_authz_read(svn_authz_t **authz
   return SVN_NO_ERROR;
 }
 
-
 svn_error_t *
 svn_repos_authz_check_access(svn_authz_t *authz, const char *repos_name,
                              const char *path, const char *user,