/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: 2018-08-15 09:26:02 UTC
  • Revision ID: teddy@recompile.se-20180815092602-xoyb5s6gf8376i7u
mandos-client: Set system clock if necessary

* plugins.d/mandos-client.c (init_gpgme/import_key): If the system
  clock is not set, or set to january 1970, set the system clock to
  the more plausible value that is the mtime of the key file.  This is
  required by GnuPG to be able to import the keys.  (We can't pass the
  --ignore-time-conflict or the --ignore-valid-from options though
  GPGME.)

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 © 2008-2021 Teddy Hogeborn
6
 
 * Copyright © 2008-2021 Björn Påhlsson
 
5
 * Copyright © 2008-2018 Teddy Hogeborn
 
6
 * Copyright © 2008-2018 Björn Påhlsson
7
7
 * 
8
8
 * This file is part of Mandos.
9
9
 * 
23
23
 * Contact the authors at <mandos@recompile.se>.
24
24
 */
25
25
 
26
 
#define _GNU_SOURCE             /* strchrnul(), TEMP_FAILURE_RETRY(),
27
 
                                   getline(), asprintf(), O_CLOEXEC,
28
 
                                   scandirat(), pipe2() */
29
 
#include <argp.h>               /* argp_program_version,
30
 
                                   argp_program_bug_address,
31
 
                                   struct argp_option,
32
 
                                   struct argp_state, argp_error(),
33
 
                                   ARGP_NO_EXIT, argp_state_help,
34
 
                                   ARGP_HELP_STD_HELP,
35
 
                                   ARGP_HELP_USAGE, ARGP_HELP_EXIT_OK,
36
 
                                   ARGP_KEY_ARG, ARGP_ERR_UNKNOWN,
37
 
                                   struct argp, argp_parse(),
38
 
                                   ARGP_IN_ORDER, ARGP_NO_HELP */
39
 
#include <stdbool.h>            /* bool, false, true */
40
 
#include <sys/types.h>          /* pid_t, sig_atomic_t, uid_t, gid_t,
41
 
                                   getuid(), setgid(), setuid() */
 
26
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), getline(),
 
27
                                   O_CLOEXEC, pipe2() */
42
28
#include <stddef.h>             /* size_t, NULL */
43
 
#include <iso646.h>             /* or, and, not */
44
 
#include <string.h>             /* strcmp(), strdup(), strchrnul(),
45
 
                                   strncmp(), strlen(), strcpy(),
46
 
                                   strsep(), strchr(), strsignal() */
47
 
#include <stdlib.h>             /* malloc(), free(), reallocarray(),
48
 
                                   realloc(), EXIT_SUCCESS */
49
 
#include <errno.h>              /* errno, EINTR, ENOMEM, ECHILD,
50
 
                                   error_t, EINVAL, EMFILE, ENFILE,
51
 
                                   ENOENT, ESRCH */
52
 
#include <stdint.h>             /* SIZE_MAX */
53
 
#define _GNU_SOURCE             /* strchrnul(), TEMP_FAILURE_RETRY(),
54
 
                                   getline(), asprintf(), O_CLOEXEC,
55
 
                                   scandirat(), pipe2() */
56
 
#include <unistd.h>             /* TEMP_FAILURE_RETRY(), ssize_t,
57
 
                                   write(), STDOUT_FILENO, uid_t,
58
 
                                   gid_t, getuid(), fchown(), close(),
59
 
                                   symlink(), setgid(), setuid(),
60
 
                                   faccessat(), X_OK, pipe(), pipe2(),
61
 
                                   fork(), _exit(), dup2(), fexecve(),
62
 
                                   read(), getpass() */
 
29
#include <stdlib.h>             /* malloc(), exit(), EXIT_SUCCESS,
 
30
                                   realloc() */
 
31
#include <stdbool.h>            /* bool, true, false */
 
32
#include <stdio.h>              /* fileno(), fprintf(),
 
33
                                   stderr, STDOUT_FILENO, fclose() */
 
34
#include <sys/types.h>          /* fstat(), struct stat, waitpid(),
 
35
                                   WIFEXITED(), WEXITSTATUS(), wait(),
 
36
                                   pid_t, uid_t, gid_t, getuid(),
 
37
                                   getgid() */
 
38
#include <sys/select.h>         /* fd_set, select(), FD_ZERO(),
 
39
                                   FD_SET(), FD_ISSET(), FD_CLR */
 
40
#include <sys/wait.h>           /* wait(), waitpid(), WIFEXITED(),
 
41
                                   WEXITSTATUS(), WTERMSIG() */
 
42
#include <sys/stat.h>           /* struct stat, fstat(), S_ISREG() */
 
43
#include <iso646.h>             /* and, or, not */
 
44
#include <dirent.h>             /* struct dirent, scandirat() */
 
45
#include <unistd.h>             /* fcntl(), F_GETFD, F_SETFD,
 
46
                                   FD_CLOEXEC, write(), STDOUT_FILENO,
 
47
                                   struct stat, fstat(), close(),
 
48
                                   setgid(), setuid(), S_ISREG(),
 
49
                                   faccessat() pipe2(), fork(),
 
50
                                   _exit(), dup2(), fexecve(), read()
 
51
                                */
63
52
#include <fcntl.h>              /* fcntl(), F_GETFD, F_SETFD,
64
 
                                   FD_CLOEXEC, open(), O_RDONLY,
65
 
                                   O_CLOEXEC, openat() */
66
 
#include <sys/wait.h>           /* waitpid(), WNOHANG, WIFEXITED(),
67
 
                                   WEXITSTATUS(), WIFSIGNALED(),
68
 
                                   WTERMSIG(), wait() */
69
 
#include <error.h>              /* error() */
70
 
#include <stdio.h>              /* FILE, fprintf(), fopen(),
71
 
                                   getline(), fclose(), EOF,
72
 
                                   asprintf(), stderr */
73
 
#include <dirent.h>             /* struct dirent, scandirat(),
74
 
                                   alphasort() */
75
 
#include <sys/stat.h>           /* struct stat, fstat(), S_ISDIR(),
76
 
                                   lstat(), S_ISREG() */
77
 
#include <sys/select.h>         /* fd_set, FD_ZERO(), FD_SETSIZE,
78
 
                                   FD_SET(), select(), FD_CLR(),
79
 
                                   FD_ISSET() */
80
 
#include <signal.h>             /* struct sigaction, SA_NOCLDSTOP,
81
 
                                   sigemptyset(), sigaddset(),
82
 
                                   SIGCHLD, sigprocmask(), SIG_BLOCK,
83
 
                                   SIG_UNBLOCK, kill(), SIGTERM */
 
53
                                   FD_CLOEXEC, openat(), scandirat(),
 
54
                                   pipe2() */
 
55
#include <string.h>             /* strsep, strlen(), strsignal(),
 
56
                                   strcmp(), strncmp() */
 
57
#include <errno.h>              /* errno */
 
58
#include <argp.h>               /* struct argp_option, struct
 
59
                                   argp_state, struct argp,
 
60
                                   argp_parse(), ARGP_ERR_UNKNOWN,
 
61
                                   ARGP_KEY_END, ARGP_KEY_ARG,
 
62
                                   error_t */
 
63
#include <signal.h>             /* struct sigaction, sigemptyset(),
 
64
                                   sigaddset(), sigaction(),
 
65
                                   sigprocmask(), SIG_BLOCK, SIGCHLD,
 
66
                                   SIG_UNBLOCK, kill(), sig_atomic_t
 
67
                                */
 
68
#include <errno.h>              /* errno, EBADF */
 
69
#include <inttypes.h>           /* intmax_t, PRIdMAX, strtoimax() */
84
70
#include <sysexits.h>           /* EX_OSERR, EX_USAGE, EX_IOERR,
85
71
                                   EX_CONFIG, EX_UNAVAILABLE, EX_OK */
86
 
#include <inttypes.h>           /* intmax_t, strtoimax(), PRIdMAX */
87
 
#include <fnmatch.h>            /* fnmatch(), FNM_FILE_NAME,
88
 
                                   FNM_PERIOD, FNM_NOMATCH */
 
72
#include <errno.h>              /* errno */
 
73
#include <error.h>              /* error() */
 
74
#include <fnmatch.h>            /* fnmatch() */
89
75
 
90
76
#define BUFFER_SIZE 256
91
77
 
193
179
  /* Resize the pointed-to array to hold one more pointer */
194
180
  char **new_array = NULL;
195
181
  do {
196
 
#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26)
197
 
    new_array = reallocarray(*array, (size_t)((*len) + 2),
198
 
                             sizeof(char *));
199
 
#else
200
 
    if(((size_t)((*len) + 2)) > (SIZE_MAX / sizeof(char *))){
201
 
      /* overflow */
202
 
      new_array = NULL;
203
 
      errno = ENOMEM;
204
 
    } else {
205
 
      new_array = realloc(*array, (size_t)((*len) + 2)
206
 
                          * sizeof(char *));
207
 
    }
208
 
#endif
 
182
    new_array = realloc(*array, sizeof(char *)
 
183
                        * (size_t) ((*len) + 2));
209
184
  } while(new_array == NULL and errno == EINTR);
210
185
  /* Malloc check */
211
186
  if(new_array == NULL){
338
313
__attribute__((nonnull))
339
314
static void free_plugin(plugin *plugin_node){
340
315
  
341
 
  for(char **arg = (plugin_node->argv)+1; *arg != NULL; arg++){
 
316
  for(char **arg = plugin_node->argv; *arg != NULL; arg++){
342
317
    free(*arg);
343
318
  }
344
 
  free(plugin_node->name);
345
319
  free(plugin_node->argv);
346
320
  for(char **env = plugin_node->environ; *env != NULL; env++){
347
321
    free(*env);
590
564
    case '?':                   /* --help */
591
565
      state->flags &= ~(unsigned int)ARGP_NO_EXIT; /* force exit */
592
566
      argp_state_help(state, state->out_stream, ARGP_HELP_STD_HELP);
593
 
      __builtin_unreachable();
594
567
    case -3:                    /* --usage */
595
568
      state->flags &= ~(unsigned int)ARGP_NO_EXIT; /* force exit */
596
569
      argp_state_help(state, state->out_stream,
597
570
                      ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
598
 
      __builtin_unreachable();
599
571
    case 'V':                   /* --version */
600
572
      fprintf(state->out_stream, "%s\n", argp_program_version);
601
573
      exit(EXIT_SUCCESS);
611
583
      if(arg[0] == '\0'){
612
584
        break;
613
585
      }
614
 
#if __GNUC__ >= 7
615
 
      __attribute__((fallthrough));
616
 
#else
617
 
          /* FALLTHROUGH */
618
 
#endif
 
586
      /* FALLTHROUGH */
619
587
    default:
620
588
      return ARGP_ERR_UNKNOWN;
621
589
    }
733
701
        
734
702
        custom_argc += 1;
735
703
        {
736
 
#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26)
737
 
          char **new_argv = reallocarray(custom_argv, (size_t)custom_argc + 1,
738
 
                                         sizeof(char *));
739
 
#else
740
 
          char **new_argv = NULL;
741
 
          if(((size_t)custom_argc + 1) > (SIZE_MAX / sizeof(char *))){
742
 
            /* overflow */
743
 
            errno = ENOMEM;
744
 
          } else {
745
 
            new_argv = realloc(custom_argv, ((size_t)custom_argc + 1)
746
 
                               * sizeof(char *));
747
 
          }
748
 
#endif
 
704
          char **new_argv = realloc(custom_argv, sizeof(char *)
 
705
                                    * ((size_t)custom_argc + 1));
749
706
          if(new_argv == NULL){
750
 
            error(0, errno, "reallocarray");
 
707
            error(0, errno, "realloc");
751
708
            exitstatus = EX_OSERR;
752
709
            free(new_arg);
753
710
            free(org_line);
872
829
      }
873
830
      close(plugindir_fd);
874
831
    }
875
 
 
876
 
    /* Work around Debian bug #981302
877
 
       <https://bugs.debian.org/981302> */
878
 
    if(lstat("/dev/fd", &st) != 0 and errno == ENOENT){
879
 
      ret = symlink("/proc/self/fd", "/dev/fd");
880
 
      if(ret == -1){
881
 
        error(0, errno, "Failed to create /dev/fd symlink");
882
 
      }
883
 
    }
884
832
  }
885
833
  
886
834
  /* Lower permissions */
1145
1093
    
1146
1094
    new_plugin->pid = pid;
1147
1095
    new_plugin->fd = pipefd[0];
1148
 
 
1149
 
    if(debug){
1150
 
      fprintf(stderr, "Plugin %s started (PID %" PRIdMAX ")\n",
1151
 
              new_plugin->name, (intmax_t) (new_plugin->pid));
1152
 
    }
1153
 
 
 
1096
    
1154
1097
    /* Unblock SIGCHLD so signal handler can be run if this process
1155
1098
       has already completed */
1156
1099
    ret = (int)TEMP_FAILURE_RETRY(sigprocmask(SIG_UNBLOCK,