summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie McClelland <jm@mayfirst.org>2010-12-19 00:01:19 -0500
committerJamie McClelland <jm@mayfirst.org>2010-12-19 00:01:19 -0500
commitca9b8d2ac9cb21d9a175bf18b95696ba01485a87 (patch)
tree90ead00557be87d79e61a63792388b5665ffc0f4
parente03138491af7bc0aa9c9387339689ebd9c685f65 (diff)
first attempt at closing #499 (changes to user authorized_keys files not
immediately incorporated)
-rw-r--r--examples/monkeysphere-monitor-keys102
1 files changed, 102 insertions, 0 deletions
diff --git a/examples/monkeysphere-monitor-keys b/examples/monkeysphere-monitor-keys
new file mode 100644
index 0000000..d121828
--- /dev/null
+++ b/examples/monkeysphere-monitor-keys
@@ -0,0 +1,102 @@
+#!/bin/perl
+
+# This script runs in a loop, monitoring existing ~/.ssh and
+# ~/.monkeysphere directories for all users on the system. It's
+# designed to be started at system start time and should run
+# as root.
+#
+# Optionally, pass the path to a file that is changed every
+# time a user is added and this script will re-load the
+# list of directories to monitor to include new additions.
+#
+# If liblinux-inotify2-perl is installed, then the Linux
+# inotify method is used to determine if a file has changed.
+# Otherwise, a generic/cross platform library is used.
+#
+# Known bugs: with inotify, if you pass /etc/passwd as the
+# first argument, the script will not detect changes to the
+# file when a new user is added.
+
+use strict;
+use File::ChangeNotify;
+use File::Basename;
+
+sub get_home_dirs() {
+ my @home_dirs;
+ my @subdirs = ('.monkeysphere', '.ssh');
+ # get list of users on the system
+ while((my $name,my $passwd,my $uid,my $gid,my $gcos,my $dir,my $shell,my $home) = getpwent( )){
+ # only monitor regular users
+ if ( $uid >= 1000 ) {
+ # The default watcher complains about non-existing directories
+ # so you should include .monkeysphere and .ssh in /etc/skel
+ # if you want them monitored for all users.
+ for my $subdir (@subdirs) {
+ if ( -d "$home/$subdir" ) {
+ push(@home_dirs,"$home/$subdir");
+ }
+ }
+ }
+ }
+ endpwent();
+ return @home_dirs
+}
+
+sub get_watcher {
+ my($rescan_file) = $_[0];
+ my(@dirs) = get_home_dirs();
+ my @filters = ('authorized_keys', 'authorized_user_ids');
+
+ # if we have a rescan file that indicates when new users are added
+ # then monitor that file as well (could be /etc/passwd)
+ if ( -f "$rescan_file" ) {
+ push(@dirs,dirname($rescan_file));
+ push(@filters,basename($rescan_file));
+ }
+ # create combined file filters to limit our monitor
+ my $filter = '^(' . join("|",@filters) . ')$';
+
+ # return a watcher object
+ return my $watcher =
+ File::ChangeNotify->instantiate_watcher
+ ( directories => [ @dirs ],
+ filter => qr/$filter/,
+ );
+}
+
+sub watch {
+ my $watcher = $_[0];
+ my $rescan_file = $_[1];
+
+ while ( my @events = $watcher->wait_for_events() ) {
+ my $rescan = 0;
+ my @users;
+ for my $event (@events) {
+ if($event->path eq "$rescan_file") {
+ $rescan = 1;
+ } else {
+ # if user deleted, file might not exist
+ if( -f $event->path) {
+ my $username = getpwuid((stat($event->path))[4]);
+ push(@users,$username);
+ }
+ }
+ }
+ for my $user (@users) {
+ my @args = ('u',$user);
+ system 'monkeysphere-authentication', @args;
+ }
+ # rescan users if necessary
+ if($rescan) {
+ # return to loop so we can be re-run after re-reading the
+ # user list
+ return;
+ }
+ }
+}
+
+my $rescan_file = $ARGV[0];
+while(1) {
+ my $watcher = get_watcher($rescan_file);
+ watch($watcher, $rescan_file);
+}