"Johan B.W. de Vries" <jo...@bluemoonit.net> writes:
> I've been trying to set up rssh with rsync 3.0.6, with some difficulty I
> made it work. I had to add the --protocol=29 or --protocol=26 command
> line argument to rsync, that was not a problem. However, I also had to
> modify rssh because all the patches I could find were either out of date
> or would not work. Since the bug I found was rather simple, I figured I
> could just post my solution here, hoping it'd get picket up some day.
The problem that you describe should be fixed by the attached patch, which
is applied to the Debian package. The fix you propose could open a
security vulnerability since it allows the --rsh flag to be passed to the
server. (This hopefully would be okay because the code should require
that the --server flag be passed, but it would be better to be safer.)
With the attached patch applied, you also won't need to use the --protocol
flag, since rssh will recognize -e used for protocol information.
--
Russ Allbery (ea...@eyrie.org) <http://www.eyrie.org/~eagle/>
From: Russ Allbery <r...@debian.org>
Date: Sat, 7 Dec 2013 18:32:56 -0800
Subject: Handle rsync v3 -e protocol option
As of rsync 3, rsync reused the -e option to pass protocol information
from the client to the server. We therefore cannot reject all -e
options to rsync, only ones not sent with --server or containing
something other than protocol information as an argument.
Also scan the rsync command line for any --rsh option and reject it as
well. This replaces and improves the upstream strategy for rejecting
that command-line option, taking advantage of the parsing added to
check the -e option.
Based on work by Robert Hardy.
Debian Bug#471803
---
util.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 72 insertions(+), 8 deletions(-)
diff --git a/util.c b/util.c
index ef1a5d8..b70899f 100644
--- a/util.c
+++ b/util.c
@@ -56,6 +56,7 @@
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif /* HAVE_LIBGEN_H */
+#include <regex.h>
/* LOCAL INCLUDES */
#include "pathnames.h"
@@ -198,6 +199,73 @@ bool check_command( char *cl, ShellOptions_t *opts, char *cmd, int cmdflag )
/*
+ * 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.
+ */
+static int rsync_e_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;
+ }
+
+ /* 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 ){
+ 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 @@ char *check_command_line( char **cl, ShellOptions_t *opts )
if ( check_command(*cl, opts, PATH_RSYNC, RSSH_ALLOW_RSYNC) ){
/* 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!");
+ return NULL;
}
return PATH_RSYNC;
}
------------------------------------------------------------------------------
Infragistics Professional
Build stunning WinForms apps today!
Reboot your WinForms applications with our WinForms controls.
Build a bridge from your legacy apps to the future.
http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk
_______________________________________________
rssh-discuss mailing list
rssh-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rssh-discuss