[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] svnadmin create --owner --group patch (second attempt)

From: John Peacock <jpeacock_at_rowman.com>
Date: 2003-09-22 16:16:32 CEST

Branko Čibej wrote:
>
> Try getopt_tests.py.

Thanks, I'll take a look at it (probably not `til Wednesday).

>>+#if !( HAVE_UMASK && HAVE_SETUID && HAVE_SETGID )
>>
>>
>
> Urgh. We don't use spaces after open parens or before close parens.

Sorry! I come from the "whitespace is free" school, so I have to rigorously
supress my desire to lather everything in extra spaces... ;~)

>
>>+ printf ("WARNING: --owner and --group unavailable under Win32");
>
> 1. This warning isn't restricted to Win32 any more

Good point. How does "...unavailable on this platform" sound?

> 2. Use svn_handle_warning instead of printf

I see lots of examples using "printf()" and "fprintf(stderr," in the commandline
tools, and very few examples of using svn_handle_warning(). Since the error is
not being thrown by one of the svn_* functions, it didn't seem appropriate to
use that wrapper. There is always a point where encapsulation becomes needless
obfuscation; I'm not comfortable enough with svn code to know where that point is.

Thanks for taking the time to look over my code. I learn, but slowly. Having
good clean code makes it easier, I must say. New patch attached.

John

-- 
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Boulevard
Suite H
Lanham, MD  20706
301-459-3366 x.5010
fax 301-429-5748

------------
LOG MESSAGE
------------

Implement two new options to the 'svnadmin create' command to explicitely
create a new repository with rights appropriate for either

1) exclusive access by a single user/process
2) shared access by all members of an existing system group

This is likely to only be relevant to Unix-like operating systems,
where chmod(), setgid(), and setuid() are meaningful.

* configure.in
    Add tests to check for existance of chmod, setgid, and setuid

* subversion/svnadmin/main.c
    (#include) - need svn_private_config.h in order to get autoconf #define's

    (enum),(options_table),(cmd_table): add owner_id, group_id to option tables

    (subcommand_create): Add logic to get system UID and GID and switch
    current process to those values before calling svn_repos_create()

* doc/book/book/ch05.xml
    (svn-ch-5-sect-2): Add paragraph and link to discussion of --owner and
    --group options in svn-ch-5-sect-5.

    (svn-ch-5-sect-5): Document the use of --owner and --group to create
    the repository with specific rights for limited repository access.

Index: configure.in
===================================================================
--- configure.in (revision 6915)
+++ configure.in (working copy)
@@ -518,6 +518,12 @@
 esac
 AC_SUBST(INCLUDE_OUTPUTS)
 
+dnl
+dnl Check for support for umask, setuid, and setgid (needed by svnadmin)
+dnl
+
+AC_CHECK_FUNCS(umask setuid setgid)
+
 dnl Final step: create the Makefile ----------------------------
 
 AC_CONFIG_FILES([Makefile])
Index: subversion/svnadmin/main.c
===================================================================
--- subversion/svnadmin/main.c (revision 6915)
+++ subversion/svnadmin/main.c (working copy)
@@ -25,7 +25,7 @@
 #include "svn_subst.h"
 #include "svn_path.h"
 #include "svn_config.h"
-
+#include "svn_private_config.h"
 #include "svnadmin.h"
 
 
@@ -79,7 +79,9 @@
     svnadmin__force_uuid,
     svnadmin__parent_dir,
     svnadmin__bdb_txn_nosync,
- svnadmin__config_dir
+ svnadmin__config_dir,
+ svnadmin__owner_id,
+ svnadmin__group_id
   };
 
 /* Option codes and descriptions.
@@ -133,6 +135,12 @@
     {"config-dir", svnadmin__config_dir, 1,
      "read user configuration files from directory ARG"},
 
+ {"owner", svnadmin__owner_id, 1,
+ "create repository owned and usable by user ARG"},
+
+ {"group", svnadmin__group_id, 1,
+ "create repository owned and usable by group ARG"},
+
     {NULL}
   };
 
@@ -144,9 +152,13 @@
   {
     {"create", subcommand_create, {0},
      "usage: svnadmin create REPOS_PATH\n\n"
- "Create a new, empty repository at REPOS_PATH.\n",
+ "Create a new, empty repository at REPOS_PATH. The --owner and --group\n"
+ "options will create the repository with appropriate ownership and\n"
+ "permissions under most Unix-like O/S's (and do nothing on Win32), but\n"
+ "require that svnadmin be run as root.\n",
      {svnadmin__on_disk_template, svnadmin__in_repos_template,
- svnadmin__bdb_txn_nosync, svnadmin__config_dir} },
+ svnadmin__bdb_txn_nosync, svnadmin__config_dir,
+ svnadmin__owner_id, svnadmin__group_id} },
     
     {"createtxn", subcommand_createtxn, {0},
      "usage: svnadmin createtxn REPOS_PATH -r REVISION\n\n"
@@ -246,6 +258,8 @@
   const char *parent_dir;
 
   const char *config_dir; /* Overriding Configuration Directory */
+ const char *owner_id;
+ const char *group_id;
 };
 
 /* This implements `svn_opt_subcommand_t'. */
@@ -264,6 +278,58 @@
                     APR_HASH_KEY_STRING, "1");
     }
 
+ /* If the user requested the repository be created as a specific
+ * owner and/or group, we need to lookup the system UID/GID and
+ * switch the current process to that user and group before
+ * creating the repository. In this case, svnadmin must be run
+ * as root, in order to be able to switch to an arbitrary user
+ * and group. This feature does not work (currently) under Win32.
+ */
+ if (opt_state->owner_id)
+ {
+#if !(HAVE_UMASK && HAVE_SETUID && HAVE_SETGID)
+ svn_handle_warning (stderr, svn_error_create
+ (SVN_ERR_INCORRECT_PARAMS, NULL,
+ "--owner and --group unavailable on this platform"));
+#else
+ apr_uid_t retrieved_uid;
+ apr_gid_t retrieved_gid;
+ apr_status_t apr_err;
+
+ apr_err = apr_uid_get(&retrieved_uid, &retrieved_gid,
+ opt_state->owner_id, pool);
+
+ if (apr_err)
+ {
+ return svn_error_create
+ (apr_err, NULL, "failed to get owner's UID");
+ }
+
+ if (opt_state->group_id)
+ {
+ (void)umask(0007); /* permit group access */
+ apr_err = apr_gid_get(&retrieved_gid,
+ opt_state->group_id, pool);
+ if (apr_err)
+ {
+ return svn_error_create
+ (apr_err, NULL, "failed to get group's GID");
+ }
+ }
+ else
+ {
+ (void)umask(0077); /* no group access */
+ }
+
+ if ( setgid(retrieved_gid) != 0 )
+ return svn_error_create (SVN_ERR_INCORRECT_PARAMS, NULL,
+ "problem setting gid (must be root)");
+ if ( setuid(retrieved_uid) != 0 )
+ return svn_error_createf (SVN_ERR_INCORRECT_PARAMS, NULL,
+ "problem setting uid (must be root)");
+#endif
+ }
+
   SVN_ERR (svn_config_get_config (&config, opt_state->config_dir, pool));
   SVN_ERR (svn_repos_create (&repos, opt_state->repository_path,
                              opt_state->on_disk, opt_state->in_repos,
@@ -796,6 +862,12 @@
         opt_state.config_dir = apr_pstrdup (pool, svn_path_canonicalize(opt_arg,
                                                                        pool));
         break;
+ case svnadmin__group_id:
+ opt_state.group_id = apr_pstrdup (pool, opt_arg);
+ break;
+ case svnadmin__owner_id:
+ opt_state.owner_id = apr_pstrdup (pool, opt_arg);
+ break;
       default:
         {
           subcommand_help (NULL, NULL, pool);
Index: doc/book/book/ch05.xml
===================================================================
--- doc/book/book/ch05.xml (revision 6915)
+++ doc/book/book/ch05.xml (working copy)
@@ -170,6 +170,12 @@
       directory. Initially, revision 0 also has a single revision
       property, <literal>svn:date</literal>, set to the time at which
       the repository was created.</para>
+
+ <para>If you need to limit the local file:// access to the repository
+ to a specific user or share it with a specific group, please see
+ <xref linkend="svn-ch-5-sect-5"/>. You should also consult that
+ section for one way to set the repository permissions for access
+ via Apache or svnserver.</para>
           
     <para>You may have noticed that the path argument to
       <command>svnadmin</command> was just a regular filesystem path
@@ -2610,11 +2616,43 @@
       files? Assuming you have a Unix-like operating system, a
       straightforward approach might be to place every potential
       repository user into a new <literal>svn</literal> group, and
- make the repository wholly owned by that group. But even that's
- not enough, because a process may write to the database files
- using an unfriendly umask&mdash;one which prevents access by
- other users.</para>
+ make the repository wholly owned by that group. Fortunately,
+ <command>svnadmin create</command> has several options that
+ make this trivial under Unix-like operating systems.</para>
 
+ <para>If you want to initially create the repository so that it is
+ exclusively accessible by a single user (either because it is a
+ private repository accessed via file:// or because you will only
+ access the repository via a specific non-priveledged account under
+ Apache or svnserver), you can use the following commands:</para>
+
+ <screen>
+$ su [enter root password]
+# svnadmin create --owner nobody /path/to/repository
+</screen>
+
+ <para>which will create a repository owned by the 'nobody' user,
+ with exclusive (i.e. no group or other) rights.</para>
+
+ <para>On the other hand, if you want a group of local users to have
+ local file:// access (as well as possibly an Apache or svnserver
+ server), you can use something like the following commands:</para>
+
+ <screen>
+$ su [enter root password]
+# svnadmin create --group svn --owner admuser /path/to/repository
+</screen>
+
+ <para>which will create a repository owned by 'admuser' (typically
+ the user who will be managing the database, running recovery, etc).
+ The files will also have the group 'svn' (which needs to be created
+ and populated first), so that all users in that group will be able
+ to use file:// access.</para>
+
+ <para>But even that's not enough, because a process may write to the
+ database files using an unfriendly umask&mdash;one which prevents
+ access by other users.</para>
+
     <para>So the next step beyond setting up a common group for
       repository users is to force every repository-accessing process
       to use a sane umask. For users accessing the repository

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Sep 22 16:17:10 2003

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.