summaryrefslogtreecommitdiff
path: root/examples/monkeysphere-monitor-keys
blob: 78df88e2a2e85e856634dc1ce25701d11bb19ee7 (plain)
  1. #!/bin/perl
  2. # This script runs in a loop, monitoring existing ~/.ssh and
  3. # ~/.monkeysphere directories for all users on the system. It's
  4. # designed to be started at system start time and should run
  5. # as root.
  6. #
  7. # File::ChangeNotify is cross platform - it will choose an
  8. # sub class for monitoring file system changes appropriate to
  9. # your operating system (if you are running Linux,
  10. # liblinux-inotify2-perl is recommended).
  11. use strict;
  12. use File::ChangeNotify;
  13. use File::Basename;
  14. sub get_home_dirs() {
  15. my @home_dirs;
  16. my @subdirs = ('.monkeysphere', '.ssh');
  17. # get list of users on the system
  18. while((my $name,my $passwd,my $uid,my $gid,my $gcos,my $dir,my $shell,my $home) = getpwent( )){
  19. # only monitor regular users
  20. if ( $uid >= 1000 ) {
  21. # The default watcher complains about non-existing directories
  22. # so you should include .monkeysphere and .ssh in /etc/skel
  23. # if you want them monitored for all users.
  24. for my $subdir (@subdirs) {
  25. if ( -d "$home/$subdir" ) {
  26. push(@home_dirs,"$home/$subdir");
  27. }
  28. }
  29. }
  30. }
  31. endpwent();
  32. return @home_dirs
  33. }
  34. sub get_watcher {
  35. my($rescan_file) = $_[0];
  36. my(@dirs) = get_home_dirs();
  37. my @filters = ('authorized_keys', 'authorized_user_ids');
  38. # if we have a rescan file that indicates when new users are added
  39. # then monitor that file as well (could be /etc/passwd)
  40. if ( -f "$rescan_file" ) {
  41. push(@dirs,dirname($rescan_file));
  42. push(@filters,basename($rescan_file));
  43. }
  44. # create combined file filters to limit our monitor
  45. my $filter = '^(' . join("|",@filters) . ')$';
  46. # return a watcher object
  47. return my $watcher =
  48. File::ChangeNotify->instantiate_watcher
  49. ( directories => [ @dirs ],
  50. filter => qr/$filter/,
  51. );
  52. }
  53. sub watch {
  54. my $watcher = $_[0];
  55. my $rescan_file = $_[1];
  56. while ( my @events = $watcher->wait_for_events() ) {
  57. my $rescan = 0;
  58. my @users;
  59. for my $event (@events) {
  60. if($event->path eq "$rescan_file") {
  61. $rescan = 1;
  62. } else {
  63. # if user deleted, file might not exist
  64. if( -f $event->path) {
  65. my $username = getpwuid((stat($event->path))[4]);
  66. push(@users,$username);
  67. }
  68. }
  69. }
  70. for my $user (@users) {
  71. my @args = ('u',$user);
  72. system 'monkeysphere-authentication', @args;
  73. }
  74. # rescan users if necessary
  75. if($rescan) {
  76. # return to loop so we can be re-run after re-reading the
  77. # user list
  78. return;
  79. }
  80. }
  81. }
  82. my $rescan_file = $ARGV[0];
  83. while(1) {
  84. my $watcher = get_watcher($rescan_file);
  85. watch($watcher, $rescan_file);
  86. }