Sun Dec 26 11:01:00 CET 2010 lele@metapensiero.it * Tolerate any option for darcs initialize Darcs may add the kind of repository after the repodir option, like "--darcs-2" or "--hashed". Thu Dec 23 13:30:48 CET 2010 lele@metapensiero.it * Allow only relative and simple paths for repodir argument Wed Dec 22 19:04:49 CET 2010 lele@metapensiero.it * Better way to validate a darcs command line This is more resilient against small differences in the syntax used by old and new darcs versions. Mon Dec 20 19:23:46 CET 2010 lele@metapensiero.it * Allow darcs initialize, to handle repository creation with darcs put Mon Dec 20 19:14:57 CET 2010 lele@metapensiero.it * Minimal check against code injection on darcs transfer-mode Mon Dec 20 17:25:14 CET 2010 lele@metapensiero.it * Temporary hack to darcs apply verification The actual command contains a double space between "--all" and "--repodir", most probably a side-effect of the code that eventually inserts "--debug"... This should be rewritten in a more robust way. Mon Dec 20 17:22:06 CET 2010 lele@metapensiero.it * Fix bad usage of strncat Code was erroneously using strncat, with the intention of limiting the destination size. But strncat does not work that way, the size argument is applied on the source, not on the destination. Mon Dec 20 17:20:52 CET 2010 lele@metapensiero.it * Fixed size for darcs which is now the last command, without space Mon Dec 20 16:14:21 CET 2010 lele@metapensiero.it * Typo Mon Dec 20 16:12:11 CET 2010 lele@metapensiero.it * Allow darcs transfer-mode, used by recent darcses Mon Dec 20 09:46:27 CET 2010 lele@metapensiero.it * Applied and rectified rssh-2.2.3-darcs.patch diff -rN -u old-rssh-2.3.3/Makefile.in new-rssh-2.3.3/Makefile.in --- old-rssh-2.3.3/Makefile.in 2010-12-27 09:44:24.378915000 +0100 +++ new-rssh-2.3.3/Makefile.in 2010-12-27 09:44:24.388915000 +0100 @@ -200,6 +200,7 @@ psdir = @psdir@ rdist_path = @rdist_path@ rsync_path = @rsync_path@ +darcs_path = @darcs_path@ sbindir = @sbindir@ scp_path = @scp_path@ sftp_path = @sftp_path@ diff -rN -u old-rssh-2.3.3/README new-rssh-2.3.3/README --- old-rssh-2.3.3/README 2010-12-27 09:44:24.378915000 +0100 +++ new-rssh-2.3.3/README 2010-12-27 09:44:24.388915000 +0100 @@ -10,8 +10,8 @@ The purpose of rssh is to allow system administrators to restrict ssh access to a particular host. It can be used to provide scp access, sftp access, or -both, and now also cvs, rdist, and rsync. Formerly, this was done based on -the name of the shell binary (or symlink to it), but is now done via config +both, and now also cvs, rdist, rsync, and darcs. Formerly, this was done based +on the name of the shell binary (or symlink to it), but is now done via config file. IMPORTANT: If you do not want your users to be able to circumvent rssh, read the diff -rN -u old-rssh-2.3.3/configure new-rssh-2.3.3/configure --- old-rssh-2.3.3/configure 2010-12-27 09:44:24.368915000 +0100 +++ new-rssh-2.3.3/configure 2010-12-27 09:44:24.388915000 +0100 @@ -644,6 +644,7 @@ defcflags static rsync_path +darcs_path rdist_path cvs_path sftp_path @@ -1387,6 +1388,7 @@ --with-cvs specify path to cvs binary --with-rdist specify path to rdist binary --with-rsync specify path to rsync binary + --with-darcs specify path to darcs binary Some influential environment variables: CC C compiler command @@ -5868,7 +5870,7 @@ fi -# CVS, rdist, and rsync might not be installed. But we don't want to force +# CVS, rdist, rsync and darcs might not be installed. But we don't want to force # the user to configure bogus paths, so default to /usr/bin/* # Check for cvs binary @@ -5996,6 +5998,7 @@ fi + # Check for rsync binary @@ -6059,6 +6062,70 @@ fi + +# Check for darcs binary + + +# Check whether --with-darcs or --without-darcs was given. +if test "${with_darcs+set}" = set; then + withval="$with_darcs" + darcs_path="$withval" +else + darcs_path="" +fi; + +# Extract the first word of "darcs", so it can be a program name with args. +set dummy darcs; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_darcs_path+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $darcs_path in + [\\/]* | ?:[\\/]*) + ac_cv_path_darcs_path="$darcs_path" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_darcs_path="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +darcs_path=$ac_cv_path_darcs_path + +if test -n "$darcs_path"; then + echo "$as_me:$LINENO: result: $darcs_path" >&5 +echo "${ECHO_T}$darcs_path" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test -z "$darcs_path"; then + { echo "$as_me:$LINENO: WARNING: can't find darcs - using /usr/bin/darcs. Use --with-darcs to override" >&5 +echo "$as_me: WARNING: can't find darcs - using /usr/bin/darcs. Use --with-darcs to override" >&2;} + darcs_path=/usr/bin/darcs +fi + +if ! test -x "$darcs_path"; then + { echo "$as_me:$LINENO: WARNING: specified darcs binary does not exist" >&5 +echo "$as_me: WARNING: specified darcs binary does not exist" >&2;} +fi + + + # disable static configuration # Check whether --enable-static was given. diff -rN -u old-rssh-2.3.3/configure.ac new-rssh-2.3.3/configure.ac --- old-rssh-2.3.3/configure.ac 2010-12-27 09:44:24.358915000 +0100 +++ new-rssh-2.3.3/configure.ac 2010-12-27 09:44:24.398915000 +0100 @@ -117,7 +117,7 @@ fi -# CVS, rdist, and rsync might not be installed. But we don't want to force +# CVS, rdist, rsync and darcs might not be installed. But we don't want to force # the user to configure bogus paths, so default to /usr/bin/* # Check for cvs binary @@ -152,7 +152,6 @@ AC_MSG_WARN([specified rdist binary does not exist]) fi - # Check for rsync binary AC_ARG_WITH(rsync, @@ -169,6 +168,21 @@ AC_MSG_WARN([specified rsync binary does not exist]) fi +# Check for darcs binary + +AC_ARG_WITH(darcs, +[ --with-darcs specify path to darcs binary], +[darcs_path="$withval"], [darcs_path=""]) + +AC_PATH_PROG(darcs_path, darcs, [], []) +if test -z "$darcs_path"; then + AC_MSG_WARN([can't find darcs - using /usr/bin/darcs. Use --with-darcs to override]) + darcs_path=/usr/bin/darcs +fi + +if ! test -x "$darcs_path"; then + AC_MSG_WARN([specified darcs binary does not exist]) +fi # disable static configuration @@ -200,6 +214,7 @@ AC_SUBST(cvs_path) AC_SUBST(rdist_path) AC_SUBST(rsync_path) +AC_SUBST(darcs_path) AC_SUBST(prefix) AC_SUBST(sysconfdir) AC_SUBST(libexecdir) diff -rN -u old-rssh-2.3.3/main.c.in new-rssh-2.3.3/main.c.in --- old-rssh-2.3.3/main.c.in 2010-12-27 09:44:24.338915000 +0100 +++ new-rssh-2.3.3/main.c.in 2010-12-27 09:44:24.398915000 +0100 @@ -217,6 +217,8 @@ argvec[1] = "4"; else if ( !(strcmp(*cmd, PATH_RSYNC)) ) argvec[1] = "5"; + else if ( !(strcmp(*cmd, PATH_DARCS)) ) + argvec[1] = "6"; else { log_set_priority(LOG_ERR); log_msg("fatal error identifying the correct command " @@ -265,7 +267,8 @@ printf("%20s = %s\n", "sftp server binary", PATH_SFTP_SERVER); printf("%20s = %s\n", "cvs binary path", PATH_CVS); printf("%20s = %s\n", "rdist binary path", PATH_RDIST); - printf("%20s = %s\n\n", "rsync binary path", PATH_RSYNC); + printf("%20s = %s\n", "rsync binary path", PATH_RSYNC); + printf("%20s = %s\n\n", "darcs binary path", PATH_DARCS); } diff -rN -u old-rssh-2.3.3/pathnames.h.in new-rssh-2.3.3/pathnames.h.in --- old-rssh-2.3.3/pathnames.h.in 2010-12-27 09:44:24.338915000 +0100 +++ new-rssh-2.3.3/pathnames.h.in 2010-12-27 09:44:24.408915000 +0100 @@ -36,6 +36,7 @@ #define PATH_CVS "@cvs_path@" #define PATH_RDIST "@rdist_path@" #define PATH_RSYNC "@rsync_path@" +#define PATH_DARCS "@darcs_path@" /* these generally are overridden by the makefile */ #ifndef PATH_RSSH_CONFIG diff -rN -u old-rssh-2.3.3/rssh.1 new-rssh-2.3.3/rssh.1 --- old-rssh-2.3.3/rssh.1 2010-12-27 09:44:24.328915000 +0100 +++ new-rssh-2.3.3/rssh.1 2010-12-27 09:44:24.408915000 +0100 @@ -18,7 +18,7 @@ allowing a user whose shell is configured to .B rssh to use one or more of the command(s) \fBscp\fP(1), \fBsftp\fP(1) -\fBcvs\fP(1), \fBrdist\fP(1), and \fBrsync\fP(1), and +\fBcvs\fP(1), \fBrdist\fP(1), \fBrsync\fP(1) and \fBdarcs\fP(1), and .I only those commands. It is intended primarily to work with OpenSSH (see http://www.openssh.com), but may work with other implementations. @@ -200,7 +200,7 @@ problematical cases were found which were likely to be common. .P The alternative would have been to include a complete command-line parser for -rcp, rdist, and rsync; this was way out of the scope of this project. In +rcp, rdist, rsync and darcs; this was way out of the scope of this project. In practice, the existing parser should suffice. If, however, you find cases where it does not, please post details to the rssh mailing list. Details about how to post to the mailing list can be found at the rssh homepage. diff -rN -u old-rssh-2.3.3/rssh.conf new-rssh-2.3.3/rssh.conf --- old-rssh-2.3.3/rssh.conf 2010-12-27 09:44:24.328915000 +0100 +++ new-rssh-2.3.3/rssh.conf 2010-12-27 09:44:24.408915000 +0100 @@ -11,6 +11,7 @@ #allowcvs #allowrdist #allowrsync +#allowdarcs # set the default umask umask = 022 @@ -28,24 +29,25 @@ ########################################## # EXAMPLES of configuring per-user options -#user=rudy:077:00010: # the path can simply be left out to not chroot -#user=rudy:077:00010 # the ending colon is optional +#user=rudy:077:000010: # the path can simply be left out to not chroot +#user=rudy:077:000010 # the ending colon is optional -#user=rudy:011:00100: # cvs, with no chroot -#user=rudy:011:01000: # rdist, with no chroot -#user=rudy:011:10000: # rsync, with no chroot -#user="rudy:011:00001:/usr/local/chroot" # whole user string can be quoted -#user=rudy:01"1:00001:/usr/local/chroot" # or somewhere in the middle, freak! -#user=rudy:'011:00001:/usr/local/chroot' # single quotes too +#user=rudy:011:000100: # cvs, with no chroot +#user=rudy:011:001000: # rdist, with no chroot +#user=rudy:011:010000: # rsync, with no chroot +#user=rudy:011:100000: # darcs, with no chroot +#user="rudy:011:000001:/usr/local/chroot" # whole user string can be quoted +#user=rudy:01"1:000001:/usr/local/chroot" # or somewhere in the middle, freak! +#user=rudy:'011:000001:/usr/local/chroot' # single quotes too # if your chroot_path contains spaces, it must be quoted... # In the following examples, the chroot_path is "/usr/local/my chroot" -#user=rudy:011:00001:"/usr/local/my chroot" # scp with chroot -#user=rudy:011:00010:"/usr/local/my chroot" # sftp with chroot -#user=rudy:011:00011:"/usr/local/my chroot" # both with chroot +#user=rudy:011:000001:"/usr/local/my chroot" # scp with chroot +#user=rudy:011:000010:"/usr/local/my chroot" # sftp with chroot +#user=rudy:011:000011:"/usr/local/my chroot" # both with chroot # Spaces before or after the '=' are fine, but spaces in chrootpath need # quotes. -#user = "rudy:011:00001:/usr/local/my chroot" -#user = "rudy:011:00001:/usr/local/my chroot" # neither do comments at line end +#user = "rudy:011:000001:/usr/local/my chroot" +#user = "rudy:011:000001:/usr/local/my chroot" # neither do comments at line end diff -rN -u old-rssh-2.3.3/rssh.conf.5 new-rssh-2.3.3/rssh.conf.5 --- old-rssh-2.3.3/rssh.conf.5 2010-12-27 09:44:24.218915000 +0100 +++ new-rssh-2.3.3/rssh.conf.5 2010-12-27 09:44:24.408915000 +0100 @@ -49,6 +49,11 @@ Tells the shell that rsync is allowed. .RE .P +.B allowdarcs +.RS +Tells the shell that darcs is allowed. +.RE +.P .B umask .RS Sets the umask value for file creations in the scp/sftp session. This is @@ -122,9 +127,9 @@ .RE .B access bits .RS -Five binary digits, which indicate whether the user is allowed to use rsync, -rdist, cvs, sftp, and scp, in that order. One means the command is allowed, -zero means it is not. +Six binary digits, which indicate whether the user is allowed to use darcs, +rsync, rdist, cvs, sftp, and scp, in that order. One means the command is +allowed, zero means it is not. .RE .B path .RS @@ -135,7 +140,7 @@ .P For example, you might have something like this: .P -user = luser:022:00001: +user = luser:022:000001: .P This does the following: for the user with the username "luser", set the umask to 022, disallow sftp, and allow scp. Because there is no chroot path @@ -148,7 +153,7 @@ chrootpath keyword. Remember that if there are spaces in the path, you need to quote it, something like this: .P -user = "luser:022:00001:/usr/local/chroot dir" +user = "luser:022:000001:/usr/local/chroot dir" .P See the default rssh.conf file for more examples. .RE diff -rN -u old-rssh-2.3.3/rssh.conf.5.in new-rssh-2.3.3/rssh.conf.5.in --- old-rssh-2.3.3/rssh.conf.5.in 2010-12-27 09:44:24.198915001 +0100 +++ new-rssh-2.3.3/rssh.conf.5.in 2010-12-27 09:44:24.408915000 +0100 @@ -49,6 +49,11 @@ Tells the shell that rsync is allowed. .RE .P +.B allowdarcs +.RS +Tells the shell that darcs is allowed. +.RE +.P .B umask .RS Sets the umask value for file creations in the scp/sftp session. This is @@ -122,9 +127,9 @@ .RE .B access bits .RS -Five binary digits, which indicate whether the user is allowed to use rsync, -rdist, cvs, sftp, and scp, in that order. One means the command is allowed, -zero means it is not. +Six binary digits, which indicate whether the user is allowed to use darcs, +rsync, rdist, cvs, sftp, and scp, in that order. One means the command is +allowed, zero means it is not. .RE .B path .RS @@ -135,7 +140,7 @@ .P For example, you might have something like this: .P -user = luser:022:00001: +user = luser:022:000001: .P This does the following: for the user with the username "luser", set the umask to 022, disallow sftp, and allow scp. Because there is no chroot path @@ -148,7 +153,7 @@ chrootpath keyword. Remember that if there are spaces in the path, you need to quote it, something like this: .P -user = "luser:022:00001:/usr/local/chroot dir" +user = "luser:022:000001:/usr/local/chroot dir" .P See the default rssh.conf file for more examples. .RE diff -rN -u old-rssh-2.3.3/rssh.h new-rssh-2.3.3/rssh.h --- old-rssh-2.3.3/rssh.h 2010-12-27 09:44:24.188915001 +0100 +++ new-rssh-2.3.3/rssh.h 2010-12-27 09:44:24.408915000 +0100 @@ -46,6 +46,7 @@ #define RSSH_ALLOW_CVS (1 << 2) #define RSSH_ALLOW_RDIST (1 << 3) #define RSSH_ALLOW_RSYNC (1 << 4) -#define RSSH_USE_CHROOT (1 << 5) +#define RSSH_ALLOW_DARCS (1 << 5) +#define RSSH_USE_CHROOT (1 << 6) #endif /* _rssh_h */ diff -rN -u old-rssh-2.3.3/rssh_chroot_helper.c new-rssh-2.3.3/rssh_chroot_helper.c --- old-rssh-2.3.3/rssh_chroot_helper.c 2010-12-27 09:44:24.178915001 +0100 +++ new-rssh-2.3.3/rssh_chroot_helper.c 2010-12-27 09:44:24.408915000 +0100 @@ -254,6 +254,9 @@ case 5: cmd_path = PATH_RSYNC; break; + case 6: + cmd_path = PATH_DARCS; + break; default: log_msg("invalid command specified"); exit(2); diff -rN -u old-rssh-2.3.3/rsshconf.c new-rssh-2.3.3/rsshconf.c --- old-rssh-2.3.3/rsshconf.c 2010-12-27 09:44:24.178915001 +0100 +++ new-rssh-2.3.3/rsshconf.c 2010-12-27 09:44:24.408915000 +0100 @@ -71,6 +71,7 @@ "allowcvs", "allowrdist", "allowrsync", + "allowdarcs", "chrootpath", "logfacility", "umask", @@ -87,7 +88,7 @@ int get_keyword( const char *line, char *keyword, int *end ); int eat_char_token( const char tokchar, const char *line, bool colon, - bool ign_spc ); + bool ign_spc ); int process_umask( ShellOptions_t *opts, const char *line, const int lineno ); int process_user( ShellOptions_t *opts, const char *line, const int lineno ); @@ -106,6 +107,9 @@ int process_allow_rsync( ShellOptions_t *opts, const char *line, const int lineno ); +int process_allow_darcs( ShellOptions_t *opts, const char *line, + const int lineno ); + int get_token( const char *str, char *buf, const int buflen, const bool colon, const bool ign_spc ); @@ -220,21 +224,26 @@ return FALSE; return TRUE; case 6: + /* allow darcs */ + if ( !(process_allow_darcs(opts, line + pos, lineno) ) ) + return FALSE; + return TRUE; + case 7: /* default chroot path */ if ( !(process_chroot_path(opts, line + pos, lineno) ) ) return FALSE; return TRUE; - case 7: + case 8: /* syslog log facility */ if ( !(process_log_facility(opts, line + pos, lineno) ) ) return FALSE; return TRUE; - case 8: + case 9: /* set the user's umask */ if ( !(process_umask(opts, line + pos, lineno) ) ) return FALSE; return TRUE; - case 9: + case 10: /* user */ if ( !(process_user(opts, line + pos, lineno) ) ) return FALSE; @@ -557,6 +566,31 @@ } +/* + * process_allow_darcs() - make sure there are no tokens after the keyword, + * other than a possible comment. If there are + * additional tokens other than comments, there is a + * syntax error, and FALSE is returned. Otherwise, the + * line is ok, so opts are set to allow darcs, and TRUE + * is returned. + */ +int process_allow_darcs( ShellOptions_t *opts, + const char *line, + const int lineno ) +{ + int pos; + + if ( !(pos = eat_comment(line)) ){ + log_msg("line %d: syntax error parsing config file", lineno); + return FALSE; + } + log_set_priority(LOG_INFO); + log_msg("allowing darcs to all users"); + opts->shell_flags |= RSSH_ALLOW_DARCS; + return TRUE; +} + + int process_chroot_path( ShellOptions_t *opts, const char *line, const int lineno ) @@ -854,6 +888,7 @@ bool allow_cvs; bool allow_rdist; bool allow_rsync; + bool allow_darcs; /* make space for user options */ if ( !(temp = (char *)malloc(CFG_LINE_LEN + 1)) ){ @@ -926,7 +961,7 @@ return FALSE; } if ( !validate_access(axs, &allow_sftp, &allow_scp, &allow_cvs, - &allow_rdist, &allow_rsync) ){ + &allow_rdist, &allow_rsync, &allow_darcs) ){ if (log){ log_set_priority(LOG_ERR); log_msg("syntax error parsing access bits, line %d", lineno); @@ -1000,6 +1035,10 @@ if (log) log_msg("allowing rsync to user %s", user); opts->shell_flags |= RSSH_ALLOW_RSYNC; } + if ( allow_darcs ){ + log_msg("allowing darcs to user %s", user); + opts->shell_flags |= RSSH_ALLOW_DARCS; + } if ( path ){ if (log) log_msg("chrooting %s to %s", user, path); opts->shell_flags |= RSSH_USE_CHROOT; diff -rN -u old-rssh-2.3.3/util.c new-rssh-2.3.3/util.c --- old-rssh-2.3.3/util.c 2010-12-27 09:44:24.128915001 +0100 +++ new-rssh-2.3.3/util.c 2010-12-27 09:44:24.408915000 +0100 @@ -79,7 +79,8 @@ if ( flags & RSSH_ALLOW_SFTP ) size += 5; if ( flags & RSSH_ALLOW_CVS ) size += 4; if ( flags & RSSH_ALLOW_RDIST ) size += 6; - if ( flags & RSSH_ALLOW_RSYNC ) size += 5; /* last one, no space */ + if ( flags & RSSH_ALLOW_RSYNC ) size += 6; + if ( flags & RSSH_ALLOW_DARCS ) size += 5; /* last one, no space */ /* create msg indicating what is allowed */ if ( !size ) cmd = "This user is locked out."; @@ -90,17 +91,19 @@ exit(1); } cmd[0] = '\0'; - strncat(cmd, "Allowed commands: ", size); + strcat(cmd, "Allowed commands: "); if ( flags & RSSH_ALLOW_SCP ) - strncat(cmd, "scp ", size); + strcat(cmd, "scp "); if ( flags & RSSH_ALLOW_SFTP ) - strncat(cmd, "sftp ", size); + strcat(cmd, "sftp "); if ( flags & RSSH_ALLOW_CVS ) - strncat(cmd, "cvs ", size); + strcat(cmd, "cvs "); if ( flags & RSSH_ALLOW_RDIST ) - strncat(cmd, "rdist ", size); + strcat(cmd, "rdist "); if ( flags & RSSH_ALLOW_RSYNC ) - strncat(cmd, "rsync", size); + strcat(cmd, "rsync "); + if ( flags & RSSH_ALLOW_DARCS ) + strcat(cmd, "darcs"); } /* print error message to user and log attempt */ @@ -245,9 +248,137 @@ return PATH_RSYNC; } + if ( check_command(cl, opts, PATH_DARCS, RSSH_ALLOW_DARCS) ){ + /* Only allow: darcs apply --repodir '/some/path' + * or: darcs transfer-mode --repodir /some/path + * or: darcs initialize --repodir='/some/path' --darcs-2 --hashed */ + if ( valid_darcs_apply(cl) || + valid_darcs_transfer_mode(cl) || + valid_darcs_initialize(cl) ) + return PATH_DARCS; + } + return NULL; } +/* + * valid_darcs_subcomand() - takes a list of chunks and validate the + * given command line. Each chunk may be an + * arbitrary string or "%", the placeholder + * for a pathname, or "-" that matches zero + * or more simple options without any argument + * at the end of the command. + * Ignoring spaces, returns 1 if all chunks match. + */ +int valid_darcs_subcomand( char **chunks, char *cl ) +{ + char *chunk, *filename; + int chunk_len; + for ( chunk = *chunks; *chunks; chunk = *++chunks ){ + /* '-' can match zero options */ + if ( ! *cl ) return *chunk == '-' ? 1 : 0; + chunk_len = strlen(chunk); + if ( chunk_len == 1 ){ + if ( *chunk == '%' ){ + if ( *cl == '\'' ){ + /* a quoted filename */ + cl++; + filename = cl; + while ( *cl && ( *cl != '\'' || *(cl-1) == '\\' ) ) cl++; + if ( *cl != '\'' ) return 0; + else cl++; + } else { + /* an unlimited filename: reject shell tricks */ + filename = cl; + while ( *cl ){ + if ( *cl == ';' || + *cl == '&' || + *cl == '|' || + *cl == '$' || + *cl == '`' ) + return 0; + cl++; + } + } + /* Allow only relative and simple paths */ + if ( ! *filename || *filename == '/' || + /* Reject some/../../other tricks */ + strstr( filename, "/." ) || strstr( filename, "./" ) ) + return 0; + } else if ( *chunk == '-' ){ + /* zero or more simple options */ + while ( *cl && *cl == '-' ){ + while ( *cl && + *cl != ' ' && + *cl != ';' && + *cl != '&' && + *cl != '|' && + *cl != '$' && + *cl != '`' ) cl++; + while ( *cl && *cl==' ' ) cl++; + } + } + } else { + if ( strncmp( chunk, cl, chunk_len ) ) return 0; + cl += chunk_len; + /* if the chunk is an option, allow either a + space or an equal sign as separator */ + if ( *chunk == '-' && *cl == '=' ) cl++; + } + /* skip spaces */ + while ( *cl && *cl==' ' ) cl++; + } + /* must consume the whole command line */ + return ! *cl; +} + +/* + * valid_darcs_apply() - takes a command line string as send by the darcs + * apply command to commit changes to the remote repo. + * this string must be of the kind: + * + * darcs apply --all --repodir '/some/path' + * + * anything else is not a valid darcs apply command. + * + */ +int valid_darcs_apply( char *cl ) +{ + char *chunks[] = {"darcs", "apply", "--all", "--repodir", "%", NULL}; + return valid_darcs_subcomand(chunks, cl); +} + +/* + * valid_darcs_transfer_mode() - takes a command line string as send by the darcs + * push command to transfer changes to the remote repo. + * this string must be of the kind: + * + * darcs transfer-mode --repodir /some/path + * + * anything else is not a valid darcs transfer-mode command. + * + */ +int valid_darcs_transfer_mode( char *cl ) +{ + char *chunks[] = {"darcs", "transfer-mode", "--repodir", "%", NULL}; + return valid_darcs_subcomand(chunks, cl); +} + +/* + * valid_darcs_initialize() - takes a command line string as send by the darcs + * put command to initialize a new remote repo. + * this string must be of the kind: + * + * darcs initialize --repodir='/some/path' --darcs-2 --hashed + * + * anything else is not a valid darcs initialize command. + * + */ +int valid_darcs_initialize( char *cl ) +{ + char *chunks[] = {"darcs", "initialize", "--repodir", "%", "-", NULL}; + return valid_darcs_subcomand(chunks, cl); +} /* * extract_root() - takes a root directory and the full path to some other @@ -309,22 +440,24 @@ * same name, and returns FALSE if the bits are not valid */ int validate_access( const char *temp, bool *allow_sftp, bool *allow_scp, - bool *allow_cvs, bool *allow_rdist, bool *allow_rsync ) + bool *allow_cvs, bool *allow_rdist, bool *allow_rsync, + bool *allow_darcs) { int i; -#define NUM_ACCESS_BITS 5 +#define NUM_ACCESS_BITS 6 if ( strlen(temp) != NUM_ACCESS_BITS ) return FALSE; /* make sure the bits are valid */ for ( i = 0; i < NUM_ACCESS_BITS; i++ ) if ( temp[i] < '0' || temp[i] > '1' ) return FALSE; /* This is easier to read if we allign the = */ - *allow_rsync = temp[0] - '0'; - *allow_rdist = temp[1] - '0'; - *allow_cvs = temp[2] - '0'; - *allow_sftp = temp[3] - '0'; - *allow_scp = temp[4] - '0'; + *allow_darcs = temp[0] - '0'; + *allow_rsync = temp[1] - '0'; + *allow_rdist = temp[2] - '0'; + *allow_cvs = temp[3] - '0'; + *allow_sftp = temp[4] - '0'; + *allow_scp = temp[5] - '0'; return TRUE; } diff -rN -u old-rssh-2.3.3/util.h new-rssh-2.3.3/util.h --- old-rssh-2.3.3/util.h 2010-12-27 09:44:24.108915001 +0100 +++ new-rssh-2.3.3/util.h 2010-12-27 09:44:24.408915000 +0100 @@ -37,7 +37,8 @@ char *extract_root( char *root, char *path ); int validate_umask( const char *temp, int *mask ); int validate_access( const char *temp, bool *allow_sftp, bool *allow_scp, - bool *allow_cvs, bool *allow_rdist, bool *allow_rsync ); + bool *allow_cvs, bool *allow_rdist, bool *allow_rsync, + bool *allow_darcs ); bool opt_exist( char *cl, char opt ); char *get_username( void );