I've written a patch to cvs to allow access to be restricted to
read-only and to specific roots. The patch adds -d and -r options to
"cvs server" this can be very nice with command= restrictions in a
.ssh/authorized_keys file, but is of (very) limited use without ssh. 
This could be put in a users .cvsrc but that would be silly unless the
user has no shell access (eg thier shell is a script that runs "cvs
server"), that's the only non-ssh use I can think of for this patch but
since it doesn't interfere with anything else I think it would be worth
having.

Example:
command="/usr/bin/cvs server -d /home/cvs/root1 -r -d /home/cvs/root2"
in an authorized_keys file would restrict that key to having only
read-only access to /home/cvs/root1 and read-write access to
/home/cvs/root2.

My patch adds to the ChangeLog and NEWS files, but I couldn't figure out
where in cvs.texinfo this information belongs.

And of course: I grant permission to distribute this patch under the
terms of the GNU Public License.
                                                        - Tom
*** src/ChangeLog.orig  Mon Jun  4 13:40:09 2001
--- src/ChangeLog       Mon Jun  4 13:40:53 2001
***************
*** 1,0 ****
--- 1,6 ----
+ 2001-05-30  Tom Lear  <[EMAIL PROTECTED]>
+ 
+       * server.c (server): recognize -d & -r parameters to "cvs server"
+       (check_command_legal_p): check for SRVARG_RO global variable
+       (serve_root): check list SRVARG_Roots and possibly disallow access
+ 
*** src/server.c.orig   Wed May 30 15:23:43 2001
--- src/server.c        Wed May 30 15:14:36 2001
***************
*** 141,146 ****
--- 141,159 ----
  
  #endif /* AUTH_SERVER_SUPPORT */
  
+ /* This is for the server parameters -d & -r to select cvs root's allowed, and
+    possible read-only mode */
+ struct SRVARG_Root_Elem
+ {
+     char *root;
+     char ro;
+     struct SRVARG_Root_Elem *next;
+ };
+ 
+ struct SRVARG_Root_Elem *SRVARG_Roots = NULL;
+ 
+ char SRVARG_RO = 0;
+ 
  
  /* While processing requests, this buffer accumulates data to be sent to
     the client, and then once we are in do_cvs_command, we use it
***************
*** 749,757 ****
  {
      char *env;
      char *path;
!     
      if (error_pending()) return;
  
      if (!isabsolute (arg))
      {
        if (alloc_pending (80 + strlen (arg)))
--- 762,792 ----
  {
      char *env;
      char *path;
!     struct SRVARG_Root_Elem *root_ptr = SRVARG_Roots;
!     char root_allowed = 1;
! 
      if (error_pending()) return;
  
+     if (SRVARG_Roots) root_allowed=0;
+     while(root_ptr)
+     {
+         if (strcmp(arg, root_ptr->root) == 0)
+         {
+             root_allowed=1;
+             SRVARG_RO=root_ptr->ro;
+             root_ptr=NULL;
+         } else {
+           root_ptr=root_ptr->next;
+         }
+     }
+     if(!root_allowed)
+     {
+       if (alloc_pending (80 + strlen (arg)))
+           sprintf (pending_error_text,
+                    "E Root %s disallowed by server argument", arg);
+       return;
+     }
+ 
      if (!isabsolute (arg))
      {
        if (alloc_pending (80 + strlen (arg)))
***************
*** 2451,2456 ****
--- 2486,2498 ----
  check_command_legal_p (cmd_name)
      char *cmd_name;
  {
+     /* If this Root is considered read-only we may not want to run the command.
+      */
+     if (SRVARG_RO &&
+         lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY)
+     {
+         return 0;
+     }
      /* Right now, only pserver notices illegal commands -- namely,
       * write attempts by a read-only user.  Therefore, if CVS_Username
       * is not set, this just returns 1, because CVS_Username unset
***************
*** 4908,4913 ****
--- 4950,4958 ----
       int argc;
       char **argv;
  {
+     struct SRVARG_Root_Elem *root_ptr;
+     int c;
+ 
      if (argc == -1)
      {
        static const char *const msg[] =
***************
*** 4918,4924 ****
        };
        usage (msg);
      }
!     /* Ignore argc and argv.  They might be from .cvsrc.  */
  
      buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
                                       outbuf_memory_error);
--- 4963,4991 ----
        };
        usage (msg);
      }
!     /* parse args */
!     optind = 0;
!     while ((c = getopt (argc, argv, "+d:r")) != -1)
!     {
!         switch(c)
!         {
!             case 'd':
!                 root_ptr=malloc(sizeof(struct SRVARG_Root_Elem));
!                 root_ptr->root=optarg;
!                 root_ptr->ro=0;
!                 root_ptr->next=SRVARG_Roots;
!                 SRVARG_Roots=root_ptr;
!                 break;
!             case 'r':
!                 if (SRVARG_Roots) SRVARG_Roots->ro=1;
!                 break;
!             default:
!                 error_exit ();
!                 break;
!         }
!     }
!     argc -= optind;
!     argv += optind;
  
      buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
                                       outbuf_memory_error);
*** NEWS.orig   Mon Jun  4 13:54:41 2001
--- NEWS        Mon Jun  4 13:56:04 2001
***************
*** 1,0 ****
--- 1,2 ----
+ * Added new "cvs server" arguments -d and -r.
+ 

Reply via email to