2005-11-28  Mark D. Baushke  <mdb@gnu.org>

	[bug #14900] Add 'cvs server' handling for --allow-root
	* root.c (root_allow_used): New function.
	* root.h (root_allow_used): Ditto.
	* server.c (serve_root): Call new function in server mode.
	* sanity.sh (server2-3): Fix typo in test name.
	(server2-5, server2-6): New tests for --allow-root feature.
	(proxy-init): Fix --allow-root instances for primary-wrapper
	to include the primary and the secondary in the list.
	(writeproxy-noredirect): Ditto.
	(writeproxy-ssh-noredirect): Ditto.

Index: src/root.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/root.c,v
retrieving revision 1.119
diff -u -p -r1.119 root.c
--- src/root.c	4 Sep 2005 05:17:53 -0000	1.119
+++ src/root.c	28 Nov 2005 21:40:13 -0000
@@ -294,6 +294,12 @@ root_allow_free (void)
 }
 
 bool
+root_allow_used (void)
+{
+    return root_allow != NULL;
+}
+
+bool
 root_allow_ok (const char *arg)
 {
     if (!root_allow)
Index: src/root.h
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/root.h,v
retrieving revision 1.21
diff -u -p -r1.21 root.h
--- src/root.h	4 Sep 2005 06:00:43 -0000	1.21
+++ src/root.h	28 Nov 2005 21:40:13 -0000
@@ -63,6 +63,7 @@ cvsroot_t *local_cvsroot (const char *di
 void Create_Root (const char *dir, const char *rootdir);
 void root_allow_add (const char *, const char *configPath);
 void root_allow_free (void);
+bool root_allow_used (void);
 bool root_allow_ok (const char *);
 struct config *get_root_allow_config (const char *arg, const char *configPath);
 const char *primary_root_translate (const char *root_in);
Index: src/sanity.sh
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/sanity.sh,v
retrieving revision 1.1104
diff -u -p -r1.1104 sanity.sh
--- src/sanity.sh	23 Nov 2005 01:29:08 -0000	1.1104
+++ src/sanity.sh	28 Nov 2005 21:40:17 -0000
@@ -2722,7 +2722,7 @@ export CVS_SERVER
 
 # No need to check the PID of the last client since we are testing with
 # Redirect disabled.
-proot_arg="--allow-root=$SECONDARY_CVSROOT_DIRNAME"
+proot_arg="--allow-root=$SECONDARY_CVSROOT_DIRNAME --allow-root=$PRIMARY_CVSROOT_DIRNAME"
 exec $CVS_SERVER \$proot_arg "\$@"
 EOF
 	cat <<EOF >$TESTDIR/primary-wrapper
@@ -31314,7 +31314,7 @@ ${CVSROOT_DIRNAME}dir1
 noop
 EOF
 
-	    dotest 2-3 "${servercvs} server" \
+	    dotest server2-3 "${servercvs} server" \
 "E protocol error: directory '${TESTDIR}' not within root '${CVSROOT_DIRNAME}'
 error  " <<EOF
 Root ${CVSROOT_DIRNAME}
@@ -31336,6 +31336,20 @@ ${CVSROOT_DIRNAME}
 Unchanged foo/bar
 noop
 EOF
+
+	    dotest server2-5 \
+"${servercvs} --allow-root=${CVSROOT_DIRNAME}.bad server" \
+"E Bad root ${CVSROOT_DIRNAME}
+error  " <<EOF
+Root ${CVSROOT_DIRNAME}
+noop
+EOF
+	    dotest server2-6 \
+"${servercvs} --allow-root=${CVSROOT_DIRNAME} server" \
+"ok" <<EOF
+Root ${CVSROOT_DIRNAME}
+noop
+EOF
 	    servercvs=$save_servercvs
 	  fi
 	  ;;
@@ -32301,7 +32315,7 @@ export CVS_SERVER
 
 # No need to check the PID of the last client since we are testing with
 # Redirect disabled.
-proot_arg="--allow-root $SECONDARY_CVSROOT_DIRNAME"
+proot_arg="--allow-root $SECONDARY_CVSROOT_DIRNAME --allow-root $PRIMARY_CVSROOT_DIRNAME"
 exec $servercvs \$proot_arg "\$@"
 EOF
 	  cat <<EOF >$TESTDIR/writeproxy-primary-wrapper
@@ -32676,7 +32690,7 @@ export CVS_SERVER
 
 # No need to check the PID of the last client since we are testing with
 # Redirect disabled.
-proot_arg="--allow-root=$SECONDARY_CVSROOT_DIRNAME"
+proot_arg="--allow-root=$SECONDARY_CVSROOT_DIRNAME --allow-root=$PRIMARY_CVSROOT_DIRNAME"
 exec $CVS_SERVER \$proot_arg "\$@"
 EOF
 	  cat <<EOF >$TESTDIR/writeproxy-primary-wrapper
Index: src/server.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/server.c,v
retrieving revision 1.452
diff -u -p -r1.452 server.c
--- src/server.c	18 Oct 2005 17:31:14 -0000	1.452
+++ src/server.c	28 Nov 2005 21:40:19 -0000
@@ -802,6 +802,19 @@ serve_root (char *arg)
 	return;
     }
 
+    /* We need to check :ext: server here, :pserver: checks happen below. */
+    if (root_allow_used() && !root_allow_ok (arg)
+# ifdef AUTH_SERVER_SUPPORT
+	&& Pserver_Repos == NULL
+# endif
+	)
+    {
+	if (alloc_pending (80 + strlen (arg)))
+	    sprintf (pending_error_text,
+		     "E Bad root %s", arg);
+	return;
+    }
+
     /* Set original_parsed_root here, not because it can be changed in the
      * client Redirect sense, but so we don't have to switch in code that
      * runs in both modes to decide which to print.
