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/