/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugin-runner.c

  • Committer: Teddy Hogeborn
  • Date: 2008-12-10 01:26:02 UTC
  • mfrom: (237.1.2 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20081210012602-vhz3h75xkj24t340
First version of a somewhat complete D-Bus server interface.  Also
change user/group name to "_mandos".

* debian/mandos.postinst: Rename old "mandos" user and group to
                          "_mandos"; create "_mandos" user and group
                          if none exist.
* debian/mandos-client.postinst: - '' -

* initramfs-tools-hook: Try "_mandos" before "mandos" as user and
                        group name.

* mandos (_datetime_to_dbus_struct): New; was previously local.
  (Client.started): Renamed to "last_started".  All users changed.
  (Client.started): New; boolean.
  (Client.dbus_object_path): New.
  (Client.check_command): Renamed to "checker_command".  All users
                          changed.
  (Client.__init__): Set and use "self.dbus_object_path".  Set
                     "self.started".
  (Client.start): Update "self.started".  Emit "self.PropertyChanged"
                  signals for both "started" and "last_started".
  (Client.stop): Update "self.started".  Emit "self.PropertyChanged"
                 signal for "started".
  (Client.checker_callback): Take additional "command" argument.  All
                             callers changed. Emit
                             "self.PropertyChanged" signal.
  (Client.bump_timeout): Emit "self.PropertyChanged" signal for
                         "last_checked_ok".
  (Client.start_checker): Emit "self.PropertyChanged" signal for
                          "checker_running".
  (Client.stop_checker): Emit "self.PropertyChanged" signal for
                         "checker_running".
  (Client.still_valid): Bug fix: use "getattr(self, started, False)"
                        instead of "self.started" in case this client
                        object is so new that the "started" attribute
                        has not been created yet.
  (Client.IntervalChanged, Client.CheckerIsRunning, Client.GetChecker,
  Client.GetCreated, Client.GetFingerprint, Client.GetHost,
  Client.GetInterval, Client.GetName, Client.GetStarted,
  Client.GetTimeout, Client.StateChanged, Client.TimeoutChanged):
  Removed; all callers changed.
  (Client.CheckerCompleted): Add "condition" and "command" arguments.
                             All callers changed.
  (Client.GetAllProperties, Client.PropertyChanged): New.
  (Client.StillValid): Renamed to "IsStillValid".
  (Client.StartChecker): Changed to its own function to avoid the
                         return value from "Client.start_checker()".
  (Client.Stop): Changed to its own function to avoid the return value
                 from "Client.stop()".
  (main): Try "_mandos" before "mandos" as user and group name.
          Removed inner function "remove_from_clients".  New inner
          class "MandosServer".

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Mandos plugin runner - Run Mandos plugins
4
4
 *
5
 
 * Copyright © 2007-2008 Teddy Hogeborn & Björn Påhlsson
 
5
 * Copyright © 2008 Teddy Hogeborn
 
6
 * Copyright © 2008 Björn Påhlsson
6
7
 * 
7
8
 * This program is free software: you can redistribute it and/or
8
9
 * modify it under the terms of the GNU General Public License as
27
28
#include <stdlib.h>             /* malloc(), exit(), EXIT_FAILURE,
28
29
                                   EXIT_SUCCESS, realloc() */
29
30
#include <stdbool.h>            /* bool, true, false */
30
 
#include <stdio.h>              /* perror, popen(), fileno(),
31
 
                                   fprintf(), stderr, STDOUT_FILENO */
 
31
#include <stdio.h>              /* perror, fileno(), fprintf(),
 
32
                                   stderr, STDOUT_FILENO */
32
33
#include <sys/types.h>          /* DIR, opendir(), stat(), struct
33
34
                                   stat, waitpid(), WIFEXITED(),
34
35
                                   WEXITSTATUS(), wait(), pid_t,
46
47
                                   fcntl(), setuid(), setgid(),
47
48
                                   F_GETFD, F_SETFD, FD_CLOEXEC,
48
49
                                   access(), pipe(), fork(), close()
49
 
                                   dup2, STDOUT_FILENO, _exit(),
 
50
                                   dup2(), STDOUT_FILENO, _exit(),
50
51
                                   execv(), write(), read(),
51
52
                                   close() */
52
53
#include <fcntl.h>              /* fcntl(), F_GETFD, F_SETFD,
69
70
#define PDIR "/lib/mandos/plugins.d"
70
71
#define AFILE "/conf/conf.d/mandos/plugin-runner.conf"
71
72
 
72
 
const char *argp_program_version = "plugin-runner 1.0";
 
73
const char *argp_program_version = "plugin-runner " VERSION;
73
74
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
74
75
 
75
 
struct plugin;
76
 
 
77
76
typedef struct plugin{
78
77
  char *name;                   /* can be NULL or any plugin name */
79
78
  char **argv;
208
207
 * Descriptor Flags".
209
208
 * *Note File Descriptor Flags:(libc)Descriptor Flags.
210
209
 */
211
 
static int set_cloexec_flag(int fd)
212
 
{
 
210
static int set_cloexec_flag(int fd){
213
211
  int ret = fcntl(fd, F_GETFD, 0);
214
212
  /* If reading the flags failed, return error indication now. */
215
213
  if(ret < 0){
222
220
 
223
221
/* Mark processes as completed when they exit, and save their exit
224
222
   status. */
225
 
void handle_sigchld(__attribute__((unused)) int sig){
 
223
static void handle_sigchld(__attribute__((unused)) int sig){
226
224
  while(true){
227
225
    plugin *proc = plugin_list;
228
226
    int status;
253
251
}
254
252
 
255
253
/* Prints out a password to stdout */
256
 
bool print_out_password(const char *buffer, size_t length){
 
254
static bool print_out_password(const char *buffer, size_t length){
257
255
  ssize_t ret;
258
256
  for(size_t written = 0; written < length; written += (size_t)ret){
259
257
    ret = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, buffer + written,
473
471
      debug = true;
474
472
      break;
475
473
    case ARGP_KEY_ARG:
476
 
      fprintf(stderr, "Ignoring unknown argument \"%s\"\n", arg);
 
474
      /* Cryptsetup always passes an argument, which is an empty
 
475
         string if "none" was specified in /etc/crypttab.  So if
 
476
         argument was empty, we ignore it silently. */
 
477
      if(arg[0] != '\0'){
 
478
        fprintf(stderr, "Ignoring unknown argument \"%s\"\n", arg);
 
479
      }
477
480
      break;
478
481
    case ARGP_KEY_END:
479
482
      break;
698
701
      
699
702
      const char const *bad_suffixes[] = { "~", "#", ".dpkg-new",
700
703
                                           ".dpkg-old",
 
704
                                           ".dpkg-bak",
701
705
                                           ".dpkg-divert", NULL };
702
706
      for(const char **pre = bad_prefixes; *pre != NULL; pre++){
703
707
        size_t pre_len = strlen(*pre);
844
848
        perror("sigaction");
845
849
        _exit(EXIT_FAILURE);
846
850
      }
847
 
      ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask, NULL);
 
851
      ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL);
848
852
      if(ret < 0){
849
853
        perror("sigprocmask");
850
854
        _exit(EXIT_FAILURE);
851
855
      }
852
 
 
 
856
      
853
857
      ret = dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */
854
858
      if(ret == -1){
855
859
        perror("dup2");
905
909
    if (maxfd < new_plugin->fd){
906
910
      maxfd = new_plugin->fd;
907
911
    }
908
 
    
909
912
  }
910
913
  
911
914
  closedir(dir);
912
915
  dir = NULL;
913
 
 
 
916
  
914
917
  for(plugin *p = plugin_list; p != NULL; p = p->next){
915
918
    if(p->pid != 0){
916
919
      break;
921
924
      free_plugin_list();
922
925
    }
923
926
  }
924
 
 
 
927
  
925
928
  /* Main loop while running plugins exist */
926
929
  while(plugin_list){
927
930
    fd_set rfds = rfds_all;
967
970
            goto fallback;
968
971
          }
969
972
          
 
973
          plugin *next_plugin = proc->next;
 
974
          free_plugin(proc);
 
975
          proc = next_plugin;
 
976
          
970
977
          /* We are done modifying process list, so unblock signal */
971
978
          ret = sigprocmask (SIG_UNBLOCK, &sigchld_action.sa_mask,
972
979
                             NULL);
980
987
            break;
981
988
          }
982
989
          
983
 
          plugin *next_plugin = proc->next;
984
 
          free_plugin(proc);
985
 
          proc = next_plugin;
986
990
          continue;
987
991
        }
988
992
        
989
993
        /* This process exited nicely, so print its buffer */
990
 
 
 
994
        
991
995
        bool bret = print_out_password(proc->buffer,
992
996
                                       proc->buffer_length);
993
997
        if(not bret){
1059
1063
    perror("sigaction");
1060
1064
    exitstatus = EXIT_FAILURE;
1061
1065
  }
1062
 
 
 
1066
  
1063
1067
  if(custom_argv != NULL){
1064
1068
    for(char **arg = custom_argv+1; *arg != NULL; arg++){
1065
1069
      free(*arg);
1071
1075
    closedir(dir);
1072
1076
  }
1073
1077
  
1074
 
  /* Free the process list and kill the processes */
 
1078
  /* Kill the processes */
1075
1079
  for(plugin *p = plugin_list; p != NULL; p = p->next){
1076
1080
    if(p->pid != 0){
1077
1081
      close(p->fd);
1090
1094
  if(errno != ECHILD){
1091
1095
    perror("wait");
1092
1096
  }
1093
 
 
 
1097
  
1094
1098
  free_plugin_list();
1095
1099
  
1096
1100
  free(plugindir);