Here is a first draft at an rsync proxy command for access control on
the client computer (as an attachment; I hope that's OK). I think that
remote root access is probably more secure than a non-privileged ssh
tunnel, because that still relies on a plain rsyncd password for security.

This is a Perl script that gives very limited access control. You can
restrict the read and write access paths, and it automatically rejects
paths with "/../". It restricts the rsync arguments, and may need
adjustment if you want arguments like "--backup-suffix=...". It also
executes rsync in a way that avoids sh processing.

There are many possibilities for developing this further. Comments are
welcome.

Joe Krahn
#!/usr/bin/perl
# File: BackupPC_rsync
# Author: Joe Krahn <[EMAIL PROTECTED]>
# (First draft; no version/license/copyright stuff yet)
#
# This is an rsync proxy to restrict access from the BackupPC server.
# It is intended to be defined as the command= option in the authorized_keys
# file, for example:
#   command="/usr/local/sbin/BackupPC_rsync"[,opt,opt] ssh-rsa ...
#
# You may want to add someor all of the follow resriction options as well:
#   from="<BackupPC-hostname>"
#   no-port-forwarding
#   no-agent-forwarding
#   no-X11-forwarding
#   no-pty
#
# Options for this file:
#
#   $log           Name of access log file.
#   $rsync         full path of the rsync executable.
#   $read_regexp   Perl RegExp for the allowed source path(s).
#   $write_regexp  Perl RegExp for the allowed destination path(s).
#   $nice          Nice level. In Linux, 19 is lowest. (See the setpriority 
system call)
#
# Access expressions may be blank or undefined to disallow read or write access.
# This example allows read and write access to /tmp and /home.
#
use strict;
my $log='/var/log/BackupPC_rsync.log';
my $rsync='/usr/bin/rsync';
my $write_regexp=qr/^\/(?:tmp|home)\//;
my $read_regexp=qr/^\/(?:tmp|home)\//;
my $nice=10;

my $now=localtime;
my $cmd=$ENV{SSH_ORIGINAL_COMMAND};

open F,">>$log";
printf F ('%s: COMMAND="%s"; ', scalar localtime, $cmd);

if ($cmd !~ s:^$rsync --server ::) { &fail('UNAUTHORIZED COMMAND'); }
my @command=($rsync,'--server');
while ($cmd =~ s/^(--?[A-Za-z0-9-]+(?:=\w+)?) *//) { push @command,$1; }
my $sender = ($command[2] eq '--sender');
if ( $cmd !~ m/^\. (\/(?:[\\].|[^\\])*\/) *$/ ) { &fail("INVALID ARGUMENTS AT 
\"$cmd\""); }
my $path = $1;
# Unescape special characters (BackupPC does not use quotes)
$path =~ s/\\(.)/$1/g;
# Check for and reject paths with /../ in them.
if ($path =~ m{/\.\./}) { &fail('INVALID PATH'); }
if ($command[2] eq '--sender') {
  if ($read_regexp eq '' or not defined $read_regexp) { &fail('READ ACCESS 
DISABLED'); }
  if ($path !~ $read_regexp) { &fail('DESTINATION PATH DISALLOWED'); }
} else {
  if ($write_regexp eq '' or not defined $write_regexp) { &fail('WRITE ACCESS 
DISABLED'); }
  if ($path !~ $write_regexp) { &fail('SOURCE PATH DISALLOWED'); }
}
push @command,'.',$path;
print F "ALLOWED\n";
close F;
setpriority(0,0,$nice);
# exec() is safer than system(), because it can use a pre-parsed
# argument list, which avoids sh argument processing.
exec(@command); # NO RETURN FROM THIS CALL

sub fail {
  my $err = $_[0];
  print F "DENIED: $err\n";
  close F;
  die "ACCESS DENIED: $err\n";
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
BackupPC-users mailing list
[email protected]
List:    https://lists.sourceforge.net/lists/listinfo/backuppc-users
Wiki:    http://backuppc.wiki.sourceforge.net
Project: http://backuppc.sourceforge.net/

Reply via email to