On Mon, May 07, 2007 at 11:03:47AM -0400, Derek Price wrote:
> Excuse the cross-post.  Development discussions are more appropriately 
> sent to bug-cvs.  Please delete [EMAIL PROTECTED] from any replies.

Sorry, this started in my head as "how would you recommend running CVS
in order to avoid local access", and it subrepticiously morphed to dev
talk.

> Sylvain Beucler wrote:
> [summary of remote `cvs init' exploit]
> 
> >Currently the command is disabled for remote access, using a
> >quick'n'dirty patch ("if (server_active) exit(EXIT_FAILURE)").
> >
> >What would you recommend? Are there legitimate use for remote 'init'?
> >I wouldn't like users creating their private repositories at Savannah
> >either.
> 
> No, there really aren't any legitimate uses for `cvs init' via remote 
> access.  Anyone who is creating a new CVS repository or upgrading a CVS 
> server to use a new CVS executable presumably has local access to the 
> machine anyhow.
> 
> I've recommended something like your `hack' to customers in the past, 
> but I've never actually installed the change into CVS itself until a few 
> minutes ago (in stable - the merge to 1.12.x is still running through 
> the regression suite).  It should be incorporated into the 1.11.23 & 
> 1.12.14 releases.

Thanks.

By the way, I see that cvsnt does it somehow differently, by checking
whether 'cvs server' is run against a valid cvs repository - and fails
with an non-existing one.


> >Since we have numerous repositories, we hit command line limits for
> >pserver --allow-root (2700 * 2 * 20 / 1024 = 105KB, not counting
> >aliases). Besides, it is not really easy to change the 'pserver'
> >command line in xinetd each time a new project is created.
> >
> >To overcome this, we used Vincent Caron's patch
> >(https://mail.gna.org/public/savane-dev/2005-08/msg00042.html).
> 
> For starters, I've heard of an --allow-root-file patch which allows all 
> the roots to be specified in a file with only the file name being 
> specified on the command line.  The only reference I found to it in a 
> quick google search was in a savane-dev archive, however, and there were 
> some broken links so I couldn't figure out how to get the attachment:
> 
> https://mail.gna.org/public/savane-dev/2002-04/msg00373.html

I like it less, because the list of repositories has to be regularly
regenerated. That's also a X00kB file to read at each request, but
maybe that doesn't really matter.

I attach the patch (alternatively you can wget
http://savannah.gnu.org/file/cvs-1.10.8-rootfile.patch?file_id=1 -
given the file id, you can even guess the patch's venerable age). Its
origin is unclear.

Having looked at cvsnt, that's more or less what it does: all
repositories are either mentioned with --allow-root (deemed
deprecated) or listed in /etc/cvsnt/Pserver.


> [elide well known pserver abuses]
> 
> >Currently there's a hard-coded patch at Savannah which prevent parsing
> >CVSROOT/passwd for pserver; the root-owned pserver is also ran behind
> >the firewall, as it's only used internaly, and only for web
> >repositories (the public pserver is ran as user nobody). Of course
> >that's a pretty brute way to handle the situation.
> 
> [snip]
> 
> >- Permit the CVS administrator to disable CVSROOT/passwd
> >  authentication with a pserver command-line switch (a cracker might
> >  still switch to an unsecure PAM scheme, but that's less
> >  straightforward).
> >
> >- Or more generaly, specify the allowed authentication scheme in the
> >  pserver command line (this would be easier to secure) - overriding
> >  CVSROOT/config.
> 
> Could you send me the patch you mention?  I should be able to adapt it 
> to a command-line switch pretty easily.

I attach 99_savannah2, a patch against cvs-1.12.9 for Debian Sarge.

I just saw that there is now a way to specify a site-wide 'config'
file (-c switch); this could also be a cvs.conf option, something like
AnonymousAuth=yes (accepts 'anoncvs' and 'anonymous' only) and
CvsAuth=no (not CVSROOT/passwd processing).


> >[1]
> >http://web.archive.org/web/20040327105943/http://ccvs.cvshome.org/issues/show_bug.cgi?id=41
> >Unfortunately the old cvshome issue tracker appears to be down, and I
> >can't grab the patch anymore. Does somebody have it?
> 
> I pulled out and attached both patches from that issue from a backup of 
> the old Issuezilla.
> 
> I don't know if you still want the --allow-root-regexp patch merged into 
> 1.12.x, but I found some discussion in the archives and it sounds like 
> we were waiting on documentation and test cases for the change.

Yeah, that's what the bugzilla page says - I'll look into it. (Now the
processing is less straightforward since the list of allowed roots
changed from a table to a linked List. Maybe the list of paths could
be realpath'd, too)

For the record I also attach a more recent (2004) version of the patch
that I just got from Christian Bayle (but the patch is from Roland
Mas).

-- 
Sylvain
diff -ruN cvs-1.12.9-old/src/server.c cvs-1.12.9/src/server.c
--- cvs-1.12.9-old/src/server.c 2006-06-10 09:25:17.062718000 +0000
+++ cvs-1.12.9/src/server.c     2006-06-10 09:27:01.823700031 +0000
@@ -5901,6 +5901,16 @@
     int rc;
     char *host_user = NULL;
 
+    /* Never use CVSROOT/passwd for authentication. pserver running as
+       root + user local access + hooks would allow a user to become
+       somebody else. */
+    if ((strcmp(username, "anonymous") == 0)
+       || (strcmp(username, "anoncvs") == 0)) {
+      return xstrdup("nobody");
+    } else {
+      return NULL;
+    }
+
     /* First we see if this user has a password in the CVS-specific
        password file.  If so, that's enough to authenticate with.  If
        not, we'll check /etc/passwd or maybe whatever is configured via PAM. */
diff -ruN cvs-1.12.9-old/doc/cvs.texinfo cvs-1.12.9/doc/cvs.texinfo
--- cvs-1.12.9-old/doc/cvs.texinfo	2004-12-09 22:54:56.000000000 +0100
+++ cvs-1.12.9/doc/cvs.texinfo	2004-12-09 22:59:54.000000000 +0100
@@ -2398,6 +2398,10 @@
 different @sc{cvsroot} directory will not be allowed to
 connect.  If there is more than one @sc{cvsroot}
 directory which you want to allow, repeat the option.
+If there is a whole class of @sc{cvsroot}
+directories which you want to allow, you can also specify a
+regular expression with the @samp{--allow-root-regexp}
+option.  This option is repeatable, too.
 (Unfortunately, many versions of @code{inetd} have very small
 limits on the number of arguments and/or the total length
 of the command.  The usual solution to this problem is
@@ -8062,6 +8066,10 @@
 Specify legal @sc{cvsroot} directory.  See
 @ref{Password authentication server}.
 
[EMAIL PROTECTED] [EMAIL PROTECTED]
+Specify legal @sc{cvsroot} directories.  See
[EMAIL PROTECTED] authentication server}.
+
 @cindex Authentication, stream
 @cindex Stream authentication
 @item -a
@@ -11365,6 +11373,12 @@
 in @sc{cvs} 1.9 and older).  See @ref{Password
 authentication server}.
 
[EMAIL PROTECTED] [EMAIL PROTECTED]
+Specify a regular expression to be matched by legal
[EMAIL PROTECTED] directories (server only) (not in @sc{cvs}
+1.11.1 and older).  See @ref{Password authentication
+server}.
+
 @item -a
 Authenticate all communication (client only) (not in @sc{cvs}
 1.9 and older).  See @ref{Global options}.
@@ -14460,7 +14474,8 @@
 pserver server which chooses not to provide a
 specific reason for denying authorization.  Check that
 the username and password specified are correct and
-that the @code{CVSROOT} specified is allowed by @samp{--allow-root}
+that the @code{CVSROOT} specified is allowed by
[EMAIL PROTECTED] or @samp{--allow-root-regexp}
 in @file{inetd.conf}.  See @ref{Password authenticated}.
 
 @item cvs @var{command}: conflict: removed @var{file} was modified by second party
diff -ruN cvs-1.12.9-old/NEWS cvs-1.12.9/NEWS
--- cvs-1.12.9-old/NEWS	2004-12-09 22:54:57.000000000 +0100
+++ cvs-1.12.9/NEWS	2004-12-09 22:59:54.000000000 +0100
@@ -574,6 +574,10 @@
 should only really affect developers.  See the section of the INSTALL file
 about using the autotools if you are compiling CVS yourself.
 
+* A new command line option, --allow-root-regexp, was added.  It
+allows to specify a list of regular expressions for the repositories
+locations, in addition to the list of exact paths.
+
 Changes from 1.11.1 to 1.11.1p1:
 
 * Read only access was broken - now fixed.
diff -ruN cvs-1.12.9-old/src/ChangeLog cvs-1.12.9/src/ChangeLog
--- cvs-1.12.9-old/src/ChangeLog	2004-12-09 22:54:56.000000000 +0100
+++ cvs-1.12.9/src/ChangeLog	2004-12-09 23:03:04.000000000 +0100
@@ -1,3 +1,17 @@
+2004-12-09  Roland Mas  <[EMAIL PROTECTED]>
+
+	* root.c: Added new functions root_allow_regexp_add and
+	root_allow_regewp_ok, new variables root_allow_regexp_count,
+	root_allow_regexp_vector and root_allow_regexp_size.
+
+	* server.c (pserver_authenticate_connection): Use new
+	root_allow_regexp function.
+
+	* main.c (main): Use new root_allow_regexp_add function, declare
+	new --allow-root-regexp option parameter.
+
+	* NEWS: Documented these changes.
+
 2004-06-09  Derek Price  <[EMAIL PROTECTED]>
 
 	* commit.c, filesubr.c, history.c, server.c, wrapper.c: Various
diff -ruN cvs-1.12.9-old/src/cvs.h cvs-1.12.9/src/cvs.h
--- cvs-1.12.9-old/src/cvs.h	2004-12-09 22:54:56.000000000 +0100
+++ cvs-1.12.9/src/cvs.h	2004-12-09 23:07:57.000000000 +0100
@@ -447,8 +447,10 @@
 	__attribute__ ((__malloc__));
 void Create_Root (const char *dir, const char *rootdir);
 void root_allow_add (char *);
+void root_allow_regexp_add (char *);
 void root_allow_free (void);
 int root_allow_ok (char *);
+int root_allow_regexp_ok (char *);
 void set_default_pam_user (char *);
 
 char *previous_rev (RCSNode *rcs, const char *rev);
diff -ruN cvs-1.12.9-old/src/main.c cvs-1.12.9/src/main.c
--- cvs-1.12.9-old/src/main.c	2004-12-09 22:54:56.000000000 +0100
+++ cvs-1.12.9/src/main.c	2004-12-09 23:14:35.000000000 +0100
@@ -439,6 +439,7 @@
 	{"help-synonyms", 0, NULL, 2},
 	{"help-options", 0, NULL, 4},
 	{"allow-root", required_argument, NULL, 3},
+	{"allow-root-regexp", required_argument, NULL, 6},
 #ifdef HAVE_PAM
     {"default-pam-user", required_argument, NULL, 5},
 #endif
@@ -556,6 +557,10 @@
 		/* --allow-root */
 		root_allow_add (optarg);
 		break;
+	    case 6:
+		/* --allow-root-regexp */
+		root_allow_regexp_add (optarg);
+		break;
 #ifdef HAVE_PAM
            case 5:
                /* --default-pam-user */
diff -ruN cvs-1.12.9-old/src/root.c cvs-1.12.9/src/root.c
--- cvs-1.12.9-old/src/root.c	2004-12-09 22:54:56.000000000 +0100
+++ cvs-1.12.9/src/root.c	2004-12-09 23:28:43.000000000 +0100
@@ -181,6 +181,10 @@
 static char **root_allow_vector;
 static int root_allow_size;
 
+static int root_allow_regexp_count;
+static char **root_allow_regexp_vector;
+static int root_allow_regexp_size;
+
 void
 root_allow_add (char *arg)
 {
@@ -221,11 +225,53 @@
 }
 
 void
+root_allow_regexp_add (char *arg)
+{
+    char *p;
+
+    if (root_allow_regexp_size <= root_allow_regexp_count)
+    {
+	if (root_allow_regexp_size == 0)
+	{
+	    root_allow_regexp_size = 1;
+	    root_allow_regexp_vector =
+		(char **) xmalloc (root_allow_regexp_size * sizeof (char *));
+	}
+	else
+	{
+	    root_allow_regexp_size *= 2;
+	    root_allow_regexp_vector =
+		(char **) xrealloc (root_allow_regexp_vector,
+				   root_allow_regexp_size * sizeof (char *));
+	}
+
+	if (root_allow_regexp_vector == NULL)
+	{
+	no_memory:
+	    /* Strictly speaking, we're not supposed to output anything
+	       now.  But we're about to exit(), give it a try.  */
+	    printf ("E Fatal server error, aborting.\n\
+error ENOMEM Virtual memory exhausted.\n");
+
+	    exit (EXIT_FAILURE);
+	}
+    }
+    p = xmalloc (strlen (arg) + 1);
+    if (p == NULL)
+	goto no_memory;
+    strcpy (p, arg);
+    root_allow_regexp_vector[root_allow_regexp_count++] = p;
+}
+
+void
 root_allow_free (void)
 {
     if (root_allow_vector != NULL)
 	free_names (&root_allow_count, root_allow_vector);
     root_allow_size = 0;
+    if (root_allow_regexp_vector != NULL)
+	free_names (&root_allow_regexp_count, root_allow_regexp_vector);
+    root_allow_regexp_size = 0;
 }
 
 int
@@ -233,7 +279,7 @@
 {
     int i;
 
-    if (root_allow_count == 0)
+    if (root_allow_count == 0 && root_allow_regexp_count == 0)
     {
 	/* Probably someone upgraded from CVS before 1.9.10 to 1.9.10
 	   or later without reading the documentation about
@@ -250,12 +296,29 @@
     }
 
     for (i = 0; i < root_allow_count; ++i)
-	if (strcmp (root_allow_vector[i], arg) == 0)
-	    return 1;
+      if (strcmp (root_allow_vector[i], arg) == 0)
+          return 1;
     return 0;
 }
 
+int
+root_allow_regexp_ok (char *arg)
+{
+    int i, status;
+    regex_t   re;
 
+    for (i = 0; i < root_allow_regexp_count; ++i) {
+       if (regcomp(&re, root_allow_regexp_vector[i],
+		   REG_EXTENDED|REG_NOSUB) != 0) {
+          return 0;	  /* report error */
+       }
+       status = regexec(&re, arg, (size_t) 0, NULL, 0);
+       regfree(&re);
+       if (status == 0)
+	  return 1;
+    }
+    return 0;
+}
 
 /* This global variable holds the global -d option.  It is NULL if -d
    was not used, which means that we must get the CVSroot information
Les fichiers binaires cvs-1.12.9-old/src/.root.c.rej.swp et cvs-1.12.9/src/.root.c.rej.swp sont diff�rents.
diff -ruN cvs-1.12.9-old/src/server.c cvs-1.12.9/src/server.c
--- cvs-1.12.9-old/src/server.c	2004-12-09 22:54:56.000000000 +0100
+++ cvs-1.12.9/src/server.c	2004-12-09 22:59:54.000000000 +0100
@@ -6049,7 +6049,7 @@
     {
 	error (1, 0, "bad auth protocol end: %s", tmp);
     }
-    if (!root_allow_ok (repository))
+    if (!root_allow_ok (repository) && !root_allow_regexp_ok (repository))
     {
 	printf ("error 0 %s: no such repository\n", repository);
 #ifdef HAVE_SYSLOG_H
diff -u cvs-1.10.8_dist/src/cvs.h cvs-1.10.8/src/cvs.h
--- cvs-1.10.8_dist/src/cvs.h	Mon Jan  3 21:49:12 2000
+++ cvs-1.10.8/src/cvs.h	Fri Oct 20 13:56:11 2000
@@ -453,6 +453,7 @@
 void set_local_cvsroot PROTO((char *dir));
 void Create_Root PROTO((char *dir, char *rootdir));
 void root_allow_add PROTO ((char *));
+int root_allow_add_file PROTO ((char *));
 void root_allow_free PROTO ((void));
 int root_allow_ok PROTO ((char *));
 
diff -u cvs-1.10.8_dist/src/main.c cvs-1.10.8/src/main.c
--- cvs-1.10.8_dist/src/main.c	Tue Aug 17 19:16:25 1999
+++ cvs-1.10.8/src/main.c	Fri Oct 20 14:24:57 2000
@@ -426,6 +426,7 @@
 	{"help-synonyms", 0, NULL, 2},
 	{"help-options", 0, NULL, 4},
 	{"allow-root", required_argument, NULL, 3},
+	{"allow-root-file", required_argument, NULL, 5},
         {0, 0, 0, 0}
     };
     /* `getopt_long' stores the option index here, but right now we
@@ -529,6 +530,11 @@
 	    case 3:
 		/* --allow-root */
 		root_allow_add (optarg);
+		break;
+	    case 5:
+		/* --allow-root-file */
+		if ( root_allow_add_file(optarg) != 0)
+			exit(1);
 		break;
 	    case 'Q':
 		really_quiet = 1;
diff -u cvs-1.10.8_dist/src/root.c cvs-1.10.8/src/root.c
--- cvs-1.10.8_dist/src/root.c	Sun Mar  7 21:17:02 1999
+++ cvs-1.10.8/src/root.c	Fri Oct 20 14:32:34 2000
@@ -229,6 +229,61 @@
     root_allow_vector[root_allow_count++] = p;
 }
 
+int
+root_allow_add_file (fname)
+    char *fname;
+{
+    char *linebuf = NULL;
+    int num_red = 0;
+    size_t linebuf_len = 0;
+    FILE *fp;
+
+    fp = fopen (fname, "r");
+
+    if (fp == NULL)
+    {
+	 if (existence_error (errno))
+	 {
+		 /* The file containing allowed roots cannot open  */
+		 error (0, errno, "cannot open %s", fname);
+		 return(1);
+	 }
+    }
+    else  /* successfully opened allowed root file */
+    {
+         while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
+         {
+            /* Hmmm, is it worth importing my own readline
+                library into CVS?  It takes care of chopping
+                leading and trailing whitespace, "#" comments, and
+                newlines automatically when so requested.  Would
+                save some code here...  -kff */
+
+             /* Chop newline by hand before passing argument to root_allow_add . */
+             if (linebuf[num_red - 1] == '\n')
+                 linebuf[num_red - 1] = '\0';
+
+	     if (strlen(linebuf)> 0)
+		root_allow_add(linebuf);
+
+         }
+
+	 if (num_red < 0 && !feof (fp)) {
+	    error (0, errno, "cannot read %s", fname);
+	    return(1);
+	 }
+
+	 if (fclose (fp) < 0) {
+	    error (0, errno, "cannot close %s", fname);
+	    return(1);
+	 }
+
+     }
+	
+     return(0);
+}
+
+
 void
 root_allow_free ()
 {
_______________________________________________
Bug-cvs mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/bug-cvs

Reply via email to