summaryrefslogtreecommitdiff
path: root/examples/monkeysphere-monitor-keys
blob: d121828c299ef372f55ac3191382553f08590973 (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. # Optionally, pass the path to a file that is changed every
  8. # time a user is added and this script will re-load the
  9. # list of directories to monitor to include new additions.
  10. #
  11. # If liblinux-inotify2-perl is installed, then the Linux
  12. # inotify method is used to determine if a file has changed.
  13. # Otherwise, a generic/cross platform library is used.
  14. #
  15. # Known bugs: with inotify, if you pass /etc/passwd as the
  16. # first argument, the script will not detect changes to the
  17. # file when a new user is added.
  18. use strict;
  19. use File::ChangeNotify;
  20. use File::Basename;
  21. sub get_home_dirs() {
  22. my @home_dirs;
  23. my @subdirs = ('.monkeysphere', '.ssh');
  24. # get list of users on the system
  25. while((my $name,my $passwd,my $uid,my $gid,my $gcos,my $dir,my $shell,my $home) = getpwent( )){
  26. # only monitor regular users
  27. if ( $uid >= 1000 ) {
  28. # The default watcher complains about non-existing directories
  29. # so you should include .monkeysphere and .ssh in /etc/skel
  30. # if you want them monitored for all users.
  31. for my $subdir (@subdirs) {
  32. if ( -d "$home/$subdir" ) {
  33. push(@home_dirs,"$home/$subdir");
  34. }
  35. }
  36. }
  37. }
  38. endpwent();
  39. return @home_dirs
  40. }
  41. sub get_watcher {
  42. my($rescan_file) = $_[0];
  43. my(@dirs) = get_home_dirs();
  44. my @filters = ('authorized_keys', 'authorized_user_ids');
  45. # if we have a rescan file that indicates when new users are added
  46. # then monitor that file as well (could be /etc/passwd)
  47. if ( -f "$rescan_file" ) {
  48. push(@dirs,dirname($rescan_file));
  49. push(@filters,basename($rescan_file));
  50. }
  51. # create combined file filters to limit our monitor
  52. my $filter = '^(' . join("|",@filters) . ')$';
  53. # return a watcher object
  54. return my $watcher =
  55. File::ChangeNotify->instantiate_watcher
  56. ( directories => [ @dirs ],
  57. filter => qr/$filter/,
  58. );
  59. }
  60. sub watch {
  61. my $watcher = $_[0];
  62. my $rescan_file = $_[1];
  63. while ( my @events = $watcher->wait_for_events() ) {
  64. my $rescan = 0;
  65. my @users;
  66. for my $event (@events) {
  67. if($event->path eq "$rescan_file") {
  68. $rescan = 1;
  69. } else {
  70. # if user deleted, file might not exist
  71. if( -f $event->path) {
  72. my $username = getpwuid((stat($event->path))[4]);
  73. push(@users,$username);
  74. }
  75. }
  76. }
  77. for my $user (@users) {
  78. my @args = ('u',$user);
  79. system 'monkeysphere-authentication', @args;
  80. }
  81. # rescan users if necessary
  82. if($rescan) {
  83. # return to loop so we can be re-run after re-reading the
  84. # user list
  85. return;
  86. }
  87. }
  88. }
  89. my $rescan_file = $ARGV[0];
  90. while(1) {
  91. my $watcher = get_watcher($rescan_file);
  92. watch($watcher, $rescan_file);
  93. }