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