Author: Robin H. Johnson Date: 2006-08-09 This patch allows a CVS server to deny usage of specific commands, based on input in the environment. Just set the CVS_BLOCK_REQUESTS env var with all of the commands you want, seperated by spaces. Eg: CVS_BLOCK_REQUESTS="Gzip-stream gzip-file-contents" would block ALL usage of compression. Please see the array 'struct request requests[]' in src/server.c for a full list of commands. Please note that if you block any commands marked as RQ_ESSENTIAL, CVS clients may fail! (This includes 'ci'!). See the companion cvs-custom.c for a wrapper that can enforce the environment variable for pserver setups. Signed-off-by: Robin H. Johnson diff -Nuar --exclude '*~' -U 10 cvs-1.12.12.orig/src/server.c cvs-1.12.12/src/server.c --- cvs-1.12.12.orig/src/server.c 2005-04-14 14:13:29.000000000 +0000 +++ cvs-1.12.12/src/server.c 2006-08-09 01:40:44.000000000 +0000 @@ -5836,43 +5836,90 @@ #undef REQ_LINE }; #endif /* SERVER_SUPPORT or CLIENT_SUPPORT */ #ifdef SERVER_SUPPORT /* * This server request is not ignored by the secondary. */ + +/* Hack by Robin H. Johnson . + * Allow the server ENV to specify what request types are to be ignored. + */ + +static char blocked_requests[BUFSIZ] = " "; + +static void build_blocked_requests() { + char *tmp = getenv("CVS_BLOCK_REQUESTS"); + + if (tmp != NULL && strlen(tmp) > 0) { + // move to our custom buffer + strncat(blocked_requests, tmp, sizeof(blocked_requests)-strlen(blocked_requests)); + //add a space on the end as well for searching + strncat(blocked_requests, " ", sizeof(blocked_requests)-strlen(blocked_requests)); + } + + // now blocked_requests contains the list of every request that we do not + // want to serve +} + +// returns 0 if we should serve this request +// use as if(checker(FOO)) continue; +static int serve_valid_requests_checker(char *reqname) { + char needle[BUFSIZ] = " "; + char *tmp; + + if(!blocked_requests || strlen(blocked_requests) < 2) + return 0; + + // we want to look for ' 'reqname' ' + snprintf(needle, sizeof(needle), " %s ", reqname); + + // now do the search + tmp = strstr(blocked_requests, needle); + + if (tmp != NULL) + return 1; + + return 0; + +} + static void serve_valid_requests (char *arg) { struct request *rq; /* Since this is processed in the first pass, don't reprocess it in the * second. * * We still print errors since new errors could have been generated in the * second pass. */ if (print_pending_error () #ifdef PROXY_SUPPORT || reprocessing #endif /* PROXY_SUPPORT */ ) return; + + build_blocked_requests(); buf_output0 (buf_to_net, "Valid-requests"); for (rq = requests; rq->name != NULL; rq++) { if (rq->func != NULL) { + if(serve_valid_requests_checker(rq->name)) + continue; buf_append_char (buf_to_net, ' '); buf_output0 (buf_to_net, rq->name); } } buf_output0 (buf_to_net, "\nok\n"); /* The client is waiting for the list of valid requests, so we must send the output now. */ buf_flush (buf_to_net, 1); } @@ -6353,20 +6400,24 @@ cmd += len; else if (cmd[len] == ' ') cmd += len + 1; else /* * The first len characters match, but it's a different * command. e.g. the command is "cooperate" but we matched * "co". */ continue; + // Ignore commands that we are supposed to ignore. + if(serve_valid_requests_checker(rq->name)) + continue; + if (!(rq->flags & RQ_ROOTLESS) && current_parsed_root == NULL) { /* For commands which change the way in which data is sent and received, for example Gzip-stream, this does the wrong thing. Since the client assumes that everything is being compressed, unconditionally, there is no way to give this error to the client without turning on