#include #include #include #include #include #define HEADER_LINES 5 /* Directories whose immediate sub-directories are the repositories we * trust */ char *cvsroot_containers[] = { "/cvsroot", "/webcvs", NULL }; int check_line (int, char *); extern char *index (const char *s, int c); int main (int argc, char *argv[]) { int i; char *line = malloc (BUFSIZ + 1); /* Read the pserver header */ for (i = 1; i <= HEADER_LINES; i++) { fgets (line, BUFSIZ, stdin); if (!check_line (i, line)) return 1; } /* Accept the request */ printf ("I LOVE YOU\n"); fflush (stdout); /* The rest of the stream can be parsed by 'cvs server' */ { char *const exec_args[] = { "cvs", "server", NULL }; execv ("/usr/bin/cvs", exec_args); } /* If we're here, there was an error in execv(3) */ printf ("error 0 Server error: %s. " "Please contact the system administrators.\n", strerror (errno)); return 1; } #define CVSROOT_LINE 2 /* We check the destination CVSROOT to avoid people trying to run * uncontrolled CVSROOT */ int check_line (int num_line, char *line) { /* 2nd line indicates the target repository */ /* Perl: chomp($line) =~ (^$cvsroot_container/[^/]+/?); */ char *buf = malloc (BUFSIZ + 1); if (num_line == CVSROOT_LINE) { char *path; int i = 0; int error = 1; char *found = NULL; /* Remove trailing new line */ strcpy (buf, line); buf[strlen (buf) - 1] = '\0'; while ((path = cvsroot_containers[i++]) != NULL) if (strncmp (buf, path, strlen(path)) == 0) found = path; if (found == NULL) error = 1; else { /* Reject empty sub-directories and sub-sub-directories */ char *subdir = buf + strlen(found); if (*subdir != '/' || *(subdir+1) == '\0') error = 1; else { char *slash_pos = strchr(subdir+1, '/'); if (slash_pos != NULL) error = 1; else error = 0; } } if (error) { printf ("error 0 Invalid path: %s\n", buf); return 0; } } return 1; }