Skip to content
Commits on Source (3)
......@@ -73,7 +73,6 @@ install: all installman
install src/monkeysphere-authentication-keys-for-user $(DESTDIR)$(PREFIX)/share/monkeysphere
install -m 0644 src/share/common $(DESTDIR)$(PREFIX)/share/monkeysphere
install -m 0644 replaced/src/share/defaultenv $(DESTDIR)$(PREFIX)/share/monkeysphere
install -m 0755 src/share/checkperms $(DESTDIR)$(PREFIX)/share/monkeysphere
install -m 0755 src/share/keytrans $(DESTDIR)$(PREFIX)/share/monkeysphere
ln -sf ../share/monkeysphere/keytrans $(DESTDIR)$(PREFIX)/bin/pem2openpgp
ln -sf ../share/monkeysphere/keytrans $(DESTDIR)$(PREFIX)/bin/openpgp2ssh
......
......@@ -20,7 +20,9 @@ Dependencies
Monkeysphere depends on:
* GnuPG >= 2.1.17
* find (POSIX or GNU should both work)
* Perl
* lockfile-progs or procmail's lockfile
* Bash
* OpenSSH's ssh-keygen utility (>= 6.0)
* base64 (coreutils or fourmilab)
......@@ -56,8 +56,7 @@ post-build {
# fix perl shebang line to point to macports perl install
exec sed -i .tmp -e "s|^#!/usr/bin/perl -T$|#!/opt/local/bin/perl -T|" \
${worksrcpath}/src/share/keytrans \
${worksrcpath}/src/share/checkperms
${worksrcpath}/src/share/keytrans
# remove leftover sed cruft
exec find ${worksrcpath} -name *.tmp -delete
......
......@@ -131,11 +131,15 @@ check_service_name() {
[ -n "$name" ] || \
failure "You must supply a service name to check"
printf '%s' "$name" | perl -n -e '($str = $_) =~ s/\s//g ; exit !(lc($str) eq $_);' || \
[[ "$name" = "${name,,}" ]] || \
failure "Not a valid service name: '$name'
Service names should be canonicalized to all lower-case,
with no whitespace"
Service names should be canonicalized to all lower-case."
[[ "$name" = "${name//$' \n\r\t'/}" ]] || \
failure "Not a valid service name: '$name'
Service names should not contain whitespace."
[[ "$name" =~ ^[a-z0-9./:-]+$ ]] || \
failure "Not a valid service name: '$name'
......
#!/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);
}
......@@ -417,6 +417,43 @@ touch_key_file_or_fail() {
fi
}
check_perms() {
local username="$1"
local pathname="$2"
if [ -z "$username" ]; then
log error 'missing username'
return 1
fi
if [ -z "$pathname" ]; then
log error 'missing pathname'
return 1
fi
if ! [[ "$pathname" =~ ^/ ]]; then
log error 'pathname must be absolute (did not start with a /)'
return 1
fi
local homedir=$(realpath "$(get_homedir "$username")")
local cur=$(realpath "$pathname")
local -a paths=("$cur")
while [ "$cur" != "/" ] && [ "$cur" != "$homedir" ]; do
cur="${cur%/*}"
if [ -z "$cur" ]; then
cur=/
fi
paths+=("$cur")
done
log debug "$(printf 'checking permissions on %s\n' "${paths[@]}")"
local trouble=$(find "${paths[@]}" -maxdepth 0 \( \! \( -uid 0 -o -user "$username" \) \) -o -perm /go+w)
if [ -n "$trouble" ]; then
log error "$(printf 'bad ownership or permissions on file(s): %s' "${trouble//$'\n'/, }")"
return 1
fi
}
# check that a file is properly owned, and that all it's parent
# directories are not group/other writable
check_key_file_permissions() {
......@@ -431,7 +468,7 @@ check_key_file_permissions() {
return 0
fi
log debug "checking path permission '$path'..."
"${SYSSHAREDIR}/checkperms" "$uname" "$path"
check_perms "$uname" "$path"
}
# return a list of all users on the system
......
......@@ -67,7 +67,7 @@ EOF
if [ -z "$CORE_FPR" ] ; then
log info "setting up Monkeysphere authentication trust core..."
local CORE_UID=$(printf "Monkeysphere authentication trust core UID (random string: %s)" $(dd if=/dev/urandom bs=21 count=1 2>/dev/null | perl -MMIME::Base64 -ne 'print encode_base64($_)'))
local CORE_UID=$(printf "Monkeysphere authentication trust core UID (random string: %s)" $(dd if=/dev/urandom bs=21 count=1 2>/dev/null | base64))
printf "generating monkeysphere authentication trust core RSA key:\nsize: %d bits\nuid: '%s'\n" "$CORE_KEYLENGTH" "$CORE_UID" | log debug
gpg_core --pinentry-mode=loopback --passphrase '' --quick-generate-key "$CORE_UID" "rsa$CORE_KEYLENGTH" cert \
......
......@@ -165,7 +165,7 @@ export DISPLAY=monkeys
## we cannot do proper directory permissions checking if the current
## working directory has unsatisfactory permissions:
if "$MONKEYSPHERE_SYSSHAREDIR"/checkperms $(whoami) "$TEMPDIR"; then
if bash -c "$(printf 'source %q/common && check_perms %q %q' "$MONKEYSPHERE_SYSSHAREDIR" "$(whoami)" "$TEMPDIR")"; then
echo "Permissions on temporary directory '$TEMPDIR' are OK for permissions checks."
TEMPDIR_PERMISSIONS_SAFE=yes
else
......