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/12/05 22:30:48 UTC

svn commit: r1417655 - in /subversion/branches/in-repo-authz/subversion/svnserve: serve.c server.h svnserve.c

Author: breser
Date: Wed Dec  5 21:30:47 2012
New Revision: 1417655

URL: http://svn.apache.org/viewvc?rev=1417655&view=rev
Log:
Add support for in-repo-authz to svnserve.

svnserve's behavior with --config-file seems less than ideal with this,
see this email thread for more details:
http://mail-archives.apache.org/mod_mbox/subversion-dev/201212.mbox/%3CCADkdwvQp%2B_OAqVmsniF_JkgrBVETNkUkUa39f1%2BKmXTBYzR%2BjA%40mail.gmail.com%3E

* subversion/svnserve/serve.c
  (load_configs): Split into load_pwdb_config() and load_authz_config().
  (load_pwdb_config): Split out of load_configs() with no changes..
  (load_authz_config): Split out of load_configs(), with code changes to
    support in-repo-authz.
  (find_repos): Switch to using load_pwdb_config() and load_authz_config()
    instead of load_configs().  Also means it's calling svn_config_read2()
    directly now.  If the authz_repos_relative server baton flag is set
    to true load authzdb even if the config is already populated.
  (serve): Copy authz_repos_relative tristate flag to the server baton
    from the params structure.

* subversion/svnserve/server.h
  (server_baton_t,serve_params_t): Add authz_repos_relative member.
  (load_configs): Split into load_pwd_config() and load_authz_config().
  (load_pwdb_config,load_authz_config): Add.

* subversion/svnserve/svnserve.c
  (main): Switch to using load_pwdb_config() and load_authz_config() instead of
    load_configs().  Also means it's calling svn_config_read2() directly now.
    Initialize the authz_repos_relative member of the params struct.

Modified:
    subversion/branches/in-repo-authz/subversion/svnserve/serve.c
    subversion/branches/in-repo-authz/subversion/svnserve/server.h
    subversion/branches/in-repo-authz/subversion/svnserve/svnserve.c

Modified: subversion/branches/in-repo-authz/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/svnserve/serve.c?rev=1417655&r1=1417654&r2=1417655&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/svnserve/serve.c (original)
+++ subversion/branches/in-repo-authz/subversion/svnserve/serve.c Wed Dec  5 21:30:47 2012
@@ -221,23 +221,17 @@ static svn_error_t *log_command(server_b
   return log_write(b->log_file, line, nbytes, pool);
 }
 
-svn_error_t *load_configs(svn_config_t **cfg,
-                          svn_config_t **pwdb,
-                          svn_authz_t **authzdb,
-                          enum username_case_type *username_case,
-                          const char *filename,
-                          svn_boolean_t must_exist,
-                          const char *base,
-                          server_baton_t *server,
-                          svn_ra_svn_conn_t *conn,
-                          apr_pool_t *pool)
+svn_error_t *load_pwdb_config(svn_config_t **pwdb,
+                              svn_config_t *cfg,
+                              const char *base,
+                              server_baton_t *server,
+                              svn_ra_svn_conn_t *conn,
+                              apr_pool_t *pool)
 {
-  const char *pwdb_path, *authzdb_path;
+  const char *pwdb_path;
   svn_error_t *err;
 
-  SVN_ERR(svn_config_read2(cfg, filename, must_exist, FALSE, pool));
-
-  svn_config_get(*cfg, &pwdb_path, SVN_CONFIG_SECTION_GENERAL,
+  svn_config_get(cfg, &pwdb_path, SVN_CONFIG_SECTION_GENERAL,
                  SVN_CONFIG_OPTION_PASSWORD_DB, NULL);
 
   *pwdb = NULL;
@@ -284,16 +278,58 @@ svn_error_t *load_configs(svn_config_t *
         }
     }
 
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *load_authz_config(svn_authz_t **authzdb,
+                               enum username_case_type *username_case,
+                               svn_tristate_t *authz_repos_relative,
+                               svn_config_t *cfg,
+                               const char *base,
+                               const char *repos_root,
+                               server_baton_t *server,
+                               svn_ra_svn_conn_t *conn,
+                               apr_pool_t *pool)
+{
+  const char *authzdb_path;
+  svn_error_t *err;
+
   /* Read authz configuration. */
-  svn_config_get(*cfg, &authzdb_path, SVN_CONFIG_SECTION_GENERAL,
+  svn_config_get(cfg, &authzdb_path, SVN_CONFIG_SECTION_GENERAL,
                  SVN_CONFIG_OPTION_AUTHZ_DB, NULL);
   if (authzdb_path)
     {
       const char *case_force_val;
 
-      authzdb_path = svn_dirent_canonicalize(authzdb_path, pool);
-      authzdb_path = svn_dirent_join(base, authzdb_path, pool);
-      err = svn_repos_authz_read(authzdb, authzdb_path, TRUE, pool);
+      if (svn_tristate_unknown == *authz_repos_relative)
+        {
+          /* Find out if the authzdb is repos relative if we didn't
+           * already know. */
+          if (svn_path_is_repos_relative_url(authzdb_path))
+            *authz_repos_relative = svn_tristate_true;
+          else
+            *authz_repos_relative = svn_tristate_false;
+        }
+
+      if (!server && svn_tristate_true == *authz_repos_relative)
+        {
+          /* Called during startup with a repos relative URL, since we
+           * don't know the repos yet, skip loading the authzdb. */
+          *authzdb = NULL;
+          *username_case = CASE_ASIS;
+          return SVN_NO_ERROR;
+        }
+
+      if (svn_tristate_false == *authz_repos_relative &&
+          !svn_path_is_url(authzdb_path))
+        {
+          /* Canonicalize and add the base onto authzdb_path (if needed)
+           * when authzdb_path is not a URL (repos relative or absolute). */
+          authzdb_path = svn_dirent_canonicalize(authzdb_path, pool);
+          authzdb_path = svn_dirent_join(base, authzdb_path, pool);
+        }
+      err = svn_repos_authz_read2(authzdb, authzdb_path, TRUE,
+                                 repos_root, pool);
       if (err)
         {
           if (server)
@@ -313,7 +349,7 @@ svn_error_t *load_configs(svn_config_t *
 
       /* Are we going to be case-normalizing usernames when we consult
        * this authz file? */
-      svn_config_get(*cfg, &case_force_val, SVN_CONFIG_SECTION_GENERAL,
+      svn_config_get(cfg, &case_force_val, SVN_CONFIG_SECTION_GENERAL,
                      SVN_CONFIG_OPTION_FORCE_USERNAME_CASE, NULL);
       if (case_force_val)
         {
@@ -329,6 +365,7 @@ svn_error_t *load_configs(svn_config_t *
     {
       *authzdb = NULL;
       *username_case = CASE_ASIS;
+      *authz_repos_relative = svn_tristate_false;
     }
 
   return SVN_NO_ERROR;
@@ -3138,14 +3175,31 @@ static svn_error_t *find_repos(const cha
     b->repos_name = b->authz_repos_name;
   b->repos_name = svn_path_uri_encode(b->repos_name, pool);
 
-  /* If the svnserve configuration files have not been loaded then
-     load them from the repository. */
+  /* If the svnserve configuration has not been loaded then load it from the
+   * repository. */
   if (NULL == b->cfg)
-    SVN_ERR(load_configs(&b->cfg, &b->pwdb, &b->authzdb, &b->username_case,
-                         svn_repos_svnserve_conf(b->repos, pool), FALSE,
-                         svn_repos_conf_dir(b->repos, pool),
-                         b, conn,
-                         pool));
+    {
+      const char *conf_dir = svn_repos_conf_dir(b->repos, pool);
+
+      SVN_ERR(svn_config_read2(&b->cfg, svn_repos_svnserve_conf(b->repos, pool),
+                               FALSE, /* must_exist */
+                               FALSE, /* section_names_case_sensitive */
+                               pool));
+      SVN_ERR(load_pwdb_config(&b->pwdb, b->cfg, conf_dir, b, conn, pool));
+      SVN_ERR(load_authz_config(&b->authzdb, &b->username_case, 
+                                &b->authz_repos_relative, b->cfg,
+                                conf_dir, repos_root, b, conn, pool));
+    }
+  /* svnserve.conf has been loaded but authz is repos relative so it needs
+   * to be loaded */
+  else if (svn_tristate_true == b->authz_repos_relative)
+    {
+      const char *conf_dir = svn_repos_conf_dir(b->repos, pool);
+
+      SVN_ERR(load_authz_config(&b->authzdb, &b->username_case, 
+                                &b->authz_repos_relative, b->cfg,
+                                conf_dir, repos_root, b, conn, pool));
+    }
 
 #ifdef SVN_HAVE_SASL
   /* Should we use Cyrus SASL? */
@@ -3352,6 +3406,7 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
   b.cfg = params->cfg;
   b.pwdb = params->pwdb;
   b.authzdb = params->authzdb;
+  b.authz_repos_relative = params->authz_repos_relative;
   b.realm = NULL;
   b.log_file = params->log_file;
   b.pool = pool;

Modified: subversion/branches/in-repo-authz/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/svnserve/server.h?rev=1417655&r1=1417654&r2=1417655&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/svnserve/server.h (original)
+++ subversion/branches/in-repo-authz/subversion/svnserve/server.h Wed Dec  5 21:30:47 2012
@@ -45,6 +45,7 @@ typedef struct server_baton_t {
   svn_config_t *cfg;       /* Parsed repository svnserve.conf */
   svn_config_t *pwdb;      /* Parsed password database */
   svn_authz_t *authzdb;    /* Parsed authz rules */
+  svn_tristate_t authz_repos_relative; /* authzdb is repos relative URL */
   const char *authz_repos_name; /* The name of the repository for authz */
   const char *realm;       /* Authentication realm */
   const char *repos_url;   /* URL to base of repository */
@@ -105,6 +106,11 @@ typedef struct serve_params_t {
      authorization database. */
   svn_authz_t *authzdb;
 
+  /* Tristate value that is true if the authz file is repos relative and needs
+   * to be loaded for each access, false if it is not and unknown if this
+   * hasn't been determined yet. */
+  svn_tristate_t authz_repos_relative;
+
   /* A filehandle open for writing logs to; possibly NULL. */
   apr_file_t *log_file;
 
@@ -145,31 +151,45 @@ typedef struct serve_params_t {
 svn_error_t *serve(svn_ra_svn_conn_t *conn, serve_params_t *params,
                    apr_pool_t *pool);
 
-/* Load a svnserve configuration file located at FILENAME into CFG,
-   and if such as found, then:
+/* Provided a parsed svnserve configuration in CFG then set *PWDB to any
+   referenced password database
+
+   BASE may be specified as the base path to any referenced password files
+   found in CFG 
 
-    - set *PWDB to any referenced password database,
-    - set *AUTHZDB to any referenced authorization database, and
+   If SERVER is not NULL, log the real errors with SERVER and CONN but
+   return generic errors to the client.  CONN must not be NULL if SERVER
+   is not NULL. */
+svn_error_t *load_pwdb_config(svn_config_t **pwdb,
+                              svn_config_t *cfg, 
+                              const char *base,
+                              server_baton_t *server,
+                              svn_ra_svn_conn_t *conn,
+                              apr_pool_t *pool);
+
+/* Provided a parsed svnserve configuration in CFG then:
+
+    - set *AUTHZDB to any referenced authorized database,
+    - set *AUTHZ_REPOS_RELATIVE to a tristate represening if authorization
+      is a repos relative URL, and
     - set *USERNAME_CASE to the enumerated value of the
       'force-username-case' configuration value (or its default).
 
-   If MUST_EXIST is true and FILENAME does not exist, then return an
-   error.  BASE may be specified as the base path to any referenced
-   password and authorization files found in FILENAME.
+   BASE may be specified as the base path to any referenced password files
+   found in CFG 
 
    If SERVER is not NULL, log the real errors with SERVER and CONN but
    return generic errors to the client.  CONN must not be NULL if SERVER
    is not NULL. */
-svn_error_t *load_configs(svn_config_t **cfg,
-                          svn_config_t **pwdb,
-                          svn_authz_t **authzdb,
-                          enum username_case_type *username_case,
-                          const char *filename,
-                          svn_boolean_t must_exist,
-                          const char *base,
-                          server_baton_t *server,
-                          svn_ra_svn_conn_t *conn,
-                          apr_pool_t *pool);
+svn_error_t *load_authz_config(svn_authz_t **authzdb,
+                               enum username_case_type *username_case,
+                               svn_tristate_t *authz_repos_relative,
+                               svn_config_t *cfg,
+                               const char *base,
+                               const char *repos_root,
+                               server_baton_t *server,
+                               svn_ra_svn_conn_t *conn,
+                               apr_pool_t *pool);
 
 /* Initialize the Cyrus SASL library. POOL is used for allocations. */
 svn_error_t *cyrus_init(apr_pool_t *pool);

Modified: subversion/branches/in-repo-authz/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/svnserve/svnserve.c?rev=1417655&r1=1417654&r2=1417655&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/in-repo-authz/subversion/svnserve/svnserve.c Wed Dec  5 21:30:47 2012
@@ -506,6 +506,7 @@ int main(int argc, const char *argv[])
   params.cfg = NULL;
   params.pwdb = NULL;
   params.authzdb = NULL;
+  params.authz_repos_relative = svn_tristate_unknown;
   params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
   params.log_file = NULL;
   params.vhost = FALSE;
@@ -747,11 +748,23 @@ int main(int argc, const char *argv[])
   /* If a configuration file is specified, load it and any referenced
    * password and authorization files. */
   if (config_filename)
-    SVN_INT_ERR(load_configs(&params.cfg, &params.pwdb, &params.authzdb,
-                             &params.username_case, config_filename, TRUE,
-                             svn_dirent_dirname(config_filename, pool),
-                             NULL, NULL, /* server baton, conn */
-                             pool));
+    {
+      const char *base = svn_dirent_dirname(config_filename, pool);
+
+      SVN_INT_ERR(svn_config_read2(&params.cfg, config_filename,
+                                   TRUE, /* must_exist */
+                                   FALSE, /* section_names_case_sensitive */
+                                   pool));
+      SVN_INT_ERR(load_pwdb_config(&params.pwdb, params.cfg, base,
+                                   NULL, NULL, /* server baton, conn */
+                                   pool));
+
+      SVN_INT_ERR(load_authz_config(&params.authzdb, &params.username_case,
+                                    &params.authz_repos_relative, params.cfg,
+                                    base, NULL, /* repos_root */
+                                    NULL, NULL, /*server baton, conn */
+                                    pool));
+    }
 
   if (log_filename)
     SVN_INT_ERR(svn_io_file_open(&params.log_file, log_filename,