Index: branches/2019Q1/shells/rssh/Makefile =================================================================== --- branches/2019Q1/shells/rssh/Makefile (revision 494950) +++ branches/2019Q1/shells/rssh/Makefile (revision 494951) @@ -1,34 +1,34 @@ # Created by: enigmatyc # $FreeBSD$ PORTNAME= rssh PORTVERSION= 2.3.4 -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= shells security MASTER_SITES= SF MAINTAINER= jharris@widomaker.com COMMENT= Restricted Secure SHell only for sftp/scp/rdist/rsync/CVS LICENSE= BSD2CLAUSE LICENSE_FILE= ${WRKSRC}/LICENSE GNU_CONFIGURE= yes USES= cpe CPE_VENDOR= pizzashack USE_CSTD= gnu89 OPTIONS_DEFINE= RDIST RSYNC3 RDIST_DESC= rdist support RDIST_RUN_DEPENDS= rdist6:net/rdist6 RDIST_CONFIGURE_ON= --with-rdist=${LOCALBASE}/bin/rdist6 RSYNC3_DESC= rsync3 support (Debian patch) RSYNC3_EXTRA_PATCHES= ${FILESDIR}/optional-patch-util.c post-patch: @${REINPLACE_CMD} -E -e 's,(\$$\(DESTDIR\)\$$\(sysconfdir\)/\$$\$$f),\1.dist,g' \ -e 's,u\+s ,u+s $$\(DESTDIR\),g' \ ${WRKSRC}/Makefile.in .include Index: branches/2019Q1/shells/rssh/files/optional-patch-util.c =================================================================== --- branches/2019Q1/shells/rssh/files/optional-patch-util.c (revision 494950) +++ branches/2019Q1/shells/rssh/files/optional-patch-util.c (revision 494951) @@ -1,103 +1,122 @@ ---- util.c.orig 2012-11-27 12:14:49.000000000 +1100 -+++ util.c 2013-01-09 17:52:54.000000000 +1100 +Verifies the command line options for rysnc. This is an updated version that +tightens the argument checking and requires to run rsync in server mode. +Taken from Debian ("0007-Verify-rsync-command-options"). +--- util.c.orig 2012-11-27 01:14:49 UTC ++++ util.c @@ -56,6 +56,7 @@ #ifdef HAVE_LIBGEN_H #include #endif /* HAVE_LIBGEN_H */ +#include /* LOCAL INCLUDES */ #include "pathnames.h" -@@ -198,6 +199,73 @@ +@@ -198,6 +199,71 @@ bool check_command( char *cl, ShellOptions_t *opts, ch /* -+ * rsync_e_okay() - take the command line passed to rssh and look for an -e -+ * option. If one is found, make sure --server is provided -+ * and the option contains only the protocol information. -+ * Also check for and reject any --rsh option. Returns FALSE -+ * if the command line should not be allowed, TRUE if it is -+ * okay. ++ * rsync_okay() - require --server on all rsh command lines, check that -e ++ * contains only protocol information, and reject any --rsh, ++ * --config, or --daemon option. Returns FALSE if the command ++ * line should not be allowed, TRUE if it is okay. + */ -+static int rsync_e_okay( char **vec ) ++static int rsync_okay( char **vec ) +{ + regex_t re; + int server = FALSE; + int e_found = FALSE; + + /* + * rsync will send -e, followed by either just "." (meaning no special + * protocol) or "N.N" (meaning a pre-release protocol version), + * followed by some number of alphabetic flags indicating various + * supported options. There may be other options between - and the e, + * but -e will always be the last option in the string. A typical + * option passed by the client is "-ltpre.iL". + * + * Note that if --server is given, this should never be parsed as a + * shell, but we'll tightly verify it anyway, just in case. + * + * This regex matches the acceptable flags containing -e, so if it + * does not match, the command line should be rejected. + */ + static const char pattern[] + = "^-[a-df-zA-Z]*e[0-9]*\\.[0-9]*[a-zA-Z]*$"; + + /* + * Only recognize --server if it's the first option. rsync itself + * always passes it that way, and if it's not the first argument, it + * could be hidden from the server as an argument to some other + * option. + */ -+ if ( vec && vec[0] && vec[1] && strcmp(vec[1], "--server") == 0 ){ -+ server = TRUE; -+ } ++ if ( !(vec && vec[0] && vec[1] && strcmp(vec[1], "--server") == 0) ) ++ return FALSE; + + /* Check the remaining options for -e or --rsh. */ + if ( regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0 ){ + return FALSE; + } + while (vec && *vec){ -+ if ( strcmp(*vec, "--") == 0 ) break; + if ( strcmp(*vec, "--rsh") == 0 -+ || strncmp(*vec, "--rsh=", strlen("--rsh=")) == 0 ){ ++ || strcmp(*vec, "--daemon") == 0 ++ || strcmp(*vec, "--config") == 0 ++ || strncmp(*vec, "--rsh=", strlen("--rsh=")) == 0 ++ || strncmp(*vec, "--config=", strlen("--config=")) == 0 ){ + regfree(&re); + return FALSE; + } + if ( strncmp(*vec, "--", 2) != 0 && opt_exist(*vec, 'e') ){ + e_found = TRUE; + if ( regexec(&re, *vec, 0, NULL, 0) != 0 ){ + regfree(&re); + return FALSE; + } + } + vec++; + } + regfree(&re); -+ if ( e_found && !server ) return FALSE; + return TRUE; +} + + +/* * check_command_line() - take the command line passed to rssh, and verify * that the specified command is one the user is * allowed to run and validate the arguments. Return the -@@ -230,14 +298,10 @@ +@@ -229,16 +295,27 @@ char *check_command_line( char **cl, ShellOptions_t *o + } if ( check_command(*cl, opts, PATH_RSYNC, RSSH_ALLOW_RSYNC) ){ - /* filter -e option */ +- /* filter -e option */ - if ( opt_filter(cl, 'e') ) return NULL; - while (cl && *cl){ - if ( strstr(*cl, "--rsh" ) ){ - fprintf(stderr, "\ninsecure --rsh= not allowed."); - log_msg("insecure --rsh option in rsync command line!"); - return NULL; - } - cl++; -+ if ( !rsync_e_okay(cl) ){ -+ fprintf(stderr, "\ninsecure -e or --rsh option not allowed."); -+ log_msg("insecure -e or --rsh option in rsync command line!"); ++ if ( !rsync_okay(cl) ){ ++ fprintf(stderr, "\ninsecure rsync options not allowed."); ++ log_msg("insecure rsync options in rsync command line!"); + return NULL; } ++ ++ /* ++ * rsync is linked with popt, which recognizes a configuration ++ * file ~/.popt that can, among other things, define aliases. ++ * If someone can write to the home directory of the rssh ++ * user, they can upload a ~/.popt file that contains ++ * something like "rsync alias --server --rsh" and then ++ * execute commands they upload. popt does not try to read ++ * its configuration file if HOME is not set, so unset HOME to ++ * disable this behavior. ++ */ ++ if ( unsetenv("HOME") < 0 ){ ++ log_msg("cannot unsetenv() HOME"); ++ return NULL; ++ } ++ return PATH_RSYNC; } + /* No match, return NULL */ Index: branches/2019Q1/shells/rssh/files/patch-log.c =================================================================== --- branches/2019Q1/shells/rssh/files/patch-log.c (nonexistent) +++ branches/2019Q1/shells/rssh/files/patch-log.c (revision 494951) @@ -0,0 +1,22 @@ +Workaround for basename(3) that is POSIX compliant since r308264 in FreeBSD 12 +--- log.c.orig 2012-11-27 00:25:13 UTC ++++ log.c +@@ -93,10 +93,14 @@ char *log_make_ident( const char *name ) + } + /* assign new value to ident from name */ + if ( !name ) return (ident = NULL); +- ident = strdup(basename((char*)name)); +- /* remove leading '-' from ident, if there is one */ +- if ( ident[0] == '-' ){ +- temp = strdup(ident + 1); ++ /* clone name in case basename() is POSIX-compliant */ ++ temp = strdup ((char *) name); ++ /* always pass writeable string to basename() */ ++ ident = strdup (basename (temp)); ++ free (temp); ++ /* safely remove leading '-' from ident, if there is one */ ++ if ((ident != NULL) && (ident[0] == '-')){ ++ temp = strdup(&ident[1]); + free(ident); + ident = temp; + } Property changes on: branches/2019Q1/shells/rssh/files/patch-log.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: branches/2019Q1/shells/rssh/files/patch-rssh__chroot__helper.c =================================================================== --- branches/2019Q1/shells/rssh/files/patch-rssh__chroot__helper.c (nonexistent) +++ branches/2019Q1/shells/rssh/files/patch-rssh__chroot__helper.c (revision 494951) @@ -0,0 +1,29 @@ +Workaround for basename(3) that is POSIX compliant since r308264 in FreeBSD 12 + +Incorporates also a patch to check the command line after chroot. Taken from +Debian ("0010-Check-command-line-after-chroot.patch") + +--- rssh_chroot_helper.c.orig 2006-12-21 22:22:35 UTC ++++ rssh_chroot_helper.c +@@ -159,7 +159,7 @@ int main( int argc, char **argv ) + opts.chroot_path = NULL; + + /* figure out our name, and give it to the log module */ +- progname = strdup(log_make_ident(basename(argv[0]))); ++ progname = strdup(log_make_ident(basename(strdup (argv[0])))); + + /* get user's passwd info */ + if ( (temp = getpwuid(getuid())) ){ +@@ -217,6 +217,12 @@ int main( int argc, char **argv ) + if ( !(argvec = build_arg_vector(argv[2], 0)) ) + ch_fatal_error("build_arg_vector()", argv[2], + "bad expansion"); ++ ++ /* check the command for safety */ ++ if ( !check_command_line(argvec, &opts) ){ ++ fprintf(stderr, "\n"); ++ exit(1); ++ } + + /* + * This is the old way to figure out what program to run. Since we're Property changes on: branches/2019Q1/shells/rssh/files/patch-rssh__chroot__helper.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: branches/2019Q1/shells/rssh/files/patch-util.c =================================================================== --- branches/2019Q1/shells/rssh/files/patch-util.c (nonexistent) +++ branches/2019Q1/shells/rssh/files/patch-util.c (revision 494951) @@ -0,0 +1,105 @@ +Workaround for basename(3) that is POSIX compliant since r308264 in FreeBSD 12 + +Fixes buffer allocation for the fail message. Taken from Debian +("0003-Fix-buffer-allocation-buffer-for-fail-message"). + +Tightens the check for scp command line arguments that fixes also +"CVE-2019-1000018". Taken from Debian ("0009-Verify-scp-command-options"). +Please note that with this patch the scp option "-3" can no longer be used. + +--- util.c.orig 2012-11-27 01:14:49 UTC ++++ util.c +@@ -84,7 +84,7 @@ void fail( int flags, int argc, char **argv ) + /* create msg indicating what is allowed */ + if ( !size ) cmd = "This user is locked out."; + else { +- size += 18; ++ size += 18 + 1; + if ( !(cmd = (char *)malloc(size)) ){ + log_msg("fatal error: out of mem allocating log msg"); + exit(1); +@@ -165,6 +165,7 @@ bool check_command( char *cl, ShellOptions_t *opts, ch + { + char *prog; /* basename of cmd */ + char *tmp = cl; ++ char *tmp2 = NULL; + bool need_free = FALSE; + bool rc = FALSE; + int i; +@@ -186,11 +187,17 @@ bool check_command( char *cl, ShellOptions_t *opts, ch + } + + /* compare tmp to cmd and prog for match */ +- prog = basename(cmd); ++ tmp2 = strdup (cmd); ++ if (tmp2 == NULL) { ++ log_msg ("strdup() failed in check_command()"); ++ return FALSE; ++ } ++ prog = basename(tmp2); + if ( !(strcmp(tmp, cmd)) || !(strcmp(tmp, prog))){ + log_msg("cmd '%s' approved", prog); + rc = TRUE; + } ++ free (tmp2); + } + if (need_free) free(tmp); + return rc; +@@ -198,6 +205,43 @@ bool check_command( char *cl, ShellOptions_t *opts, ch + + + /* ++ * scp_okay() - take the command line and check that it is a hopefully-safe scp ++ * server command line, accepting only very specific options. ++ * Returns FALSE if the command line should not be allowed, TRUE ++ * if it is okay. ++ */ ++static int scp_okay( char **vec ) ++{ ++ int saw_f_or_t = FALSE; ++ ++ for ( vec++; vec && *vec; vec++ ){ ++ /* Allowed options. */ ++ if ( strcmp(*vec, "-v") == 0 ) continue; ++ if ( strcmp(*vec, "-r") == 0 ) continue; ++ if ( strcmp(*vec, "-p") == 0 ) continue; ++ if ( strcmp(*vec, "-d") == 0 ) continue; ++ if ( strcmp(*vec, "-f") == 0 || strcmp(*vec, "-pf") == 0 ){ ++ saw_f_or_t = TRUE; ++ continue; ++ } ++ if ( strcmp(*vec, "-t") == 0 || strcmp(*vec, "-pt") == 0 ){ ++ saw_f_or_t = TRUE; ++ continue; ++ } ++ ++ /* End of arguments. */ ++ if ( strcmp(*vec, "--") == 0 ) break; ++ ++ /* Any other argument is not allowed. */ ++ if ( *vec[0] == '-' ) return FALSE; ++ } ++ ++ /* Either -f or -t must have been given. */ ++ return saw_f_or_t; ++} ++ ++ ++/* + * check_command_line() - take the command line passed to rssh, and verify + * that the specified command is one the user is + * allowed to run and validate the arguments. Return the +@@ -212,8 +256,11 @@ char *check_command_line( char **cl, ShellOptions_t *o + return PATH_SFTP_SERVER; + + if ( check_command(*cl, opts, PATH_SCP, RSSH_ALLOW_SCP) ){ +- /* filter -S option */ +- if ( opt_filter(cl, 'S') ) return NULL; ++ if ( !scp_okay(cl) ){ ++ fprintf(stderr, "\ninsecure scp option not allowed."); ++ log_msg("insecure scp option in scp command line"); ++ return NULL; ++ } + return PATH_SCP; + } + Property changes on: branches/2019Q1/shells/rssh/files/patch-util.c ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: branches/2019Q1 =================================================================== --- branches/2019Q1 (revision 494950) +++ branches/2019Q1 (revision 494951) Property changes on: branches/2019Q1 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r494837