summaryrefslogtreecommitdiff
path: root/bin/ssh-forcecommand
blob: b8d647a812b87ad1b86d00841a100abe52af3d57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env perl
use strict;
use warnings;

my $conffile = shift or die("Usage: $0 <configfile>\n");
my $origcmd = $ENV{SSH_ORIGINAL_COMMAND} or die("No command\n");

my %command;
our $VERSION = '1.0';

open( my $conf, '<', $conffile ) or die("Can't open $conffile: $!\n");

while ( my $line = <$conf> ) {
	my ( $key, $value ) = ( $line =~ m{ ^ ([^=]+?) \s* = \s* (.+) $ }x );

	if ( $key and $value ) {
		$command{$key} = $value;
	}
}
close($conf) or die("Cannot close $conffile: $!\n");

if ( not $command{$origcmd} ) {
	die("Unknown command: $origcmd\n");
}

my $cmd = $command{$origcmd} or die "Unknown command: $origcmd\n";
exec $cmd;

__END__

=head1 NAME

ssh-forcecommand - Whitelist remote commands via ssh config

=head1 SYNOPSIS

In .ssh/authorized_keys:

	command="/usr/local/lib/ssh-forcecommand /etc/forcecommand/backup",no-agent-forwarding,no-port-
	forwarding,no-pty,no-X11-forwarding $key

=head1 VERSION

This is B<ssh-forcecommand> version 1.0

=head1 DESCRIPTION

B<ssh-forcecommand> is a trivial script to safely execute remote commands via
ssh.  It is especially aimed at automated remote commands (in which ssh keys
are not secured via password), where a compromise of the remote system could
also compromise the local system.

To prevent this, you can invoke ssh-forcecommand through the ssh
configuration, which will limit the remote system so that it can only execute a
set of statically defined commands. This way, compromising the local system is
made much more diffecult.

=head1 OPTIONS

None.

=head1 EXIT STATUS

If anything goes wrong, B<ssh-forcecommand> returns a non-zero value.
Otherwise, the exit status of the executed command is returned.

=head1 CONFIGURATION

For every public key you want to restrict to the forcecommand, add a line like
in SYNOPSIS to the F<.ssh/authorized_keys>.

command="..." sets the forcecommand, the other options disable potentially
dangerous stuff like port forwardig (Though that is not meant to be an
exhaustive list).

As you see, the forcecommand accepts exactly one argument, which is the config
defining the allowed commands.  This way, you can restrict different ssh keys
to different sets of commands.  A few example configs are provided with this
script, see the examples directory.

=head1 USAGE

Assuming you have the following line in your forcecommand config:

	home = tar -C / -cf - home

Now, on the remote system, this:

	ssh user@yourhost home

will translate to the following command on the system containing ssh-forcecommand:

	tar -C / -cf - home

The forcecommand is 100% static, variables or appending of stuff is not
supported.  No part of the original ssh command will be dynamically used in
the resulting command.  This makes ssh-forcecommand quite secure.

=head1 DEPENDENCIES

Nothing besides perl >= 5.10

=head1 BUGS AND LIMITATIONS

As already pointed out, B<ssh-forcecommand> is completely static and does not
support variables.  This is a design decision and will stay that way.

=head1 AUTHOR

Copyright (C) 2010,2011 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>

=head1 LICENSE

  0. You just DO WHAT THE FUCK YOU WANT TO.