/usr/share/monkeysphere/checkperms is in monkeysphere 0.35-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 | #!/usr/bin/perl -T
# checkperms: ensure as best we can that a given file can only be
# modified by the given user (or the superuser, naturally). This
# means checking file ownership and permissions all the way back to
# the root directory. Pass the file by its absolute path.
# example invocation:
# checkperms dkg /home/dkg/.monkeysphere/authorized_user_ids
# return values: zero if we believe the file and path can only be
# modified by the user. non-zero otherwise.
# see StrictModes in sshd_config(5) (and its implementation in
# OpenSSH's secure_filename() in auth.c) for the initial
# inspiration/rationale for this code.
# Author:
# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
# Started on: 2009-07-31 11:10:16-0400
# License: GPL v3 or later
use strict;
use Cwd qw(realpath); # found in debian in perl-base
use File::stat; # found in debian in perl-modules
use User::pwent; # found in debian in perl-modules
use Fcntl qw(:mode); # for S_IS* functions (in perl-base)
use File::Basename; # for dirname (in perl-modules)
my $username = shift;
my $path = shift;
defined($username) or die "You must pass a username and an absolute path.\n";
defined($path) or die "You must pass a username and an absolute path.\n";
my $pw = getpwnam($username) or die "no such user $username\n";
$path =~ m#^/# or die "path was not absolute (did not start with /)\n";
sub mslog {
my $level = shift;
# FIXME: check and compare the log level
if ($ENV{LOG_LEVEL} eq 'DEBUG') {
my $format = shift;
my $out = sprintf($format, @_);
$out =~ s/^/$ENV{LOG_PREFIX}/ ;
printf STDERR "%s", $out;
}
}
## return undef if permissions are OK. otherwise return an error string
sub permissions_ok {
my $user = shift;
my $path = shift;
# if we can't even stat the path, the permissions are not ok:
my $stat = lstat($path) or return "cannot stat '$path'";
while (S_ISLNK($stat->mode)) {
my $newpath = realpath($path) or return "cannot trace symlink '$path'";
mslog('DEBUG', "tracing link %s to %s\n", $path, $newpath);
$path = $newpath;
$stat = lstat($path) or return "cannot stat '$path'";
}
mslog('DEBUG', "checking '%s'\n", $path);
if (($stat->uid != $user->uid) &&
($stat->uid != 0)) {
return sprintf("improper ownership on '%s': owner ID %d is neither %s (ID %d) nor the superuser",
$path, $stat->uid, $user->name, $user->uid);
}
if ($stat->mode & S_IWGRP) {
return sprintf("improper group writability on '%s'", $path);
}
if ($stat->mode & S_IWOTH) {
return sprintf("improper other writability on '%s'", $path);
}
# see the rationalization in secure_filename() in auth.c in the
# OpenSSH sources for an explanation of this bailout (see also
# monkeysphere #675):
if ($path eq $user->dir) {
mslog('DEBUG', "stopping at %s's home directory '%s'\n", $user->name, $path);
return undef;
}
my $nextlevel = dirname($path);
if ($path eq $nextlevel) { # we bottom out at the root (/ in UNIX)
return undef;
}
return permissions_ok($user, $nextlevel);
}
my $err = permissions_ok($pw, $path);
if (defined($err)) {
printf(STDERR "%s%s\n", $ENV{LOG_PREFIX}, $err);
exit(1);
} else {
exit(0);
}
|