/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 plugins.d/splashy.c

  • Committer: Teddy Hogeborn
  • Date: 2021-02-03 23:10:42 UTC
  • Revision ID: teddy@recompile.se-20210203231042-2z3egrvpo1zt7nej
mandos-ctl: Fix bad test for command.Remove and related minor issues

The test for command.Remove removes all clients from the spy server,
and then loops over all clients, looking for the corresponding Remove
command as recorded by the spy server.  But since since there aren't
any clients left after they were removed, no assertions are made, and
the test therefore does nothing.  Fix this.

In tests for command.Approve and command.Deny, add checks that clients
were not somehow removed by the command (in which case, likewise, no
assertions are made).

Add related checks to TestPropertySetterCmd.runTest; i.e. test that a
sequence is not empty before looping over it and making assertions.

* mandos-ctl (TestBaseCommands.test_Remove): Save a copy of the
  original "clients" dict, and loop over those instead.  Add assertion
  that all clients were indeed removed.  Also fix the code which looks
  for the Remove command, which now needs to actually work.
  (TestBaseCommands.test_Approve, TestBaseCommands.test_Deny): Add
  assertion that there are still clients before looping over them.
  (TestPropertySetterCmd.runTest): Add assertion that the list of
  values to get is not empty before looping over them.  Also add check
  that there are still clients before looping over clients.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Splashy - Read a password from splashy and output it
4
4
 * 
5
 
 * Copyright © 2008-2010 Teddy Hogeborn
6
 
 * Copyright © 2008-2010 Björn Påhlsson
7
 
 * 
8
 
 * This program is free software: you can redistribute it and/or
9
 
 * modify it under the terms of the GNU General Public License as
10
 
 * published by the Free Software Foundation, either version 3 of the
11
 
 * License, or (at your option) any later version.
12
 
 * 
13
 
 * This program is distributed in the hope that it will be useful, but
 
5
 * Copyright © 2008-2018, 2021 Teddy Hogeborn
 
6
 * Copyright © 2008-2018, 2021 Björn Påhlsson
 
7
 * 
 
8
 * This file is part of Mandos.
 
9
 * 
 
10
 * Mandos is free software: you can redistribute it and/or modify it
 
11
 * under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation, either version 3 of the License, or
 
13
 * (at your option) any later version.
 
14
 * 
 
15
 * Mandos is distributed in the hope that it will be useful, but
14
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
18
 * General Public License for more details.
17
19
 * 
18
20
 * You should have received a copy of the GNU General Public License
19
 
 * along with this program.  If not, see
20
 
 * <http://www.gnu.org/licenses/>.
 
21
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
21
22
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
23
 * Contact the authors at <mandos@recompile.se>.
23
24
 */
24
25
 
25
 
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
26
 
#include <signal.h>             /* sig_atomic_t, struct sigaction,
27
 
                                   sigemptyset(), sigaddset(), SIGINT,
28
 
                                   SIGHUP, SIGTERM, sigaction,
29
 
                                   SIG_IGN, kill(), SIGKILL */
30
 
#include <stddef.h>             /* NULL */
31
 
#include <stdlib.h>             /* getenv() */
32
 
#include <stdio.h>              /* asprintf() */
33
 
#include <stdlib.h>             /* EXIT_FAILURE, free(),
34
 
                                   EXIT_SUCCESS */
35
 
#include <sys/types.h>          /* pid_t, DIR, struct dirent,
36
 
                                   ssize_t */
37
 
#include <dirent.h>             /* opendir(), readdir(), closedir() */
38
 
#include <inttypes.h>           /* intmax_t, strtoimax() */
39
 
#include <sys/stat.h>           /* struct stat, lstat(), S_ISLNK */
40
 
#include <iso646.h>             /* not, or, and */
41
 
#include <unistd.h>             /* readlink(), fork(), execl(),
42
 
                                   sleep(), dup2() STDERR_FILENO,
43
 
                                   STDOUT_FILENO, _exit(),
44
 
                                   pause() */
45
 
#include <string.h>             /* memcmp() */
46
 
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
 
26
#define _GNU_SOURCE             /* vasprintf(),
 
27
                                   program_invocation_short_name,
 
28
                                   asprintf(), TEMP_FAILURE_RETRY() */
 
29
#include <sys/types.h>          /* sig_atomic_t, pid_t, setuid(),
 
30
                                   geteuid(), setsid() */
 
31
#include <stdarg.h>             /* va_list, va_start(), vfprintf() */
 
32
#include <stdio.h>              /* vasprintf(), fprintf(), stderr,
 
33
                                   vfprintf(), asprintf() */
 
34
#include <errno.h>              /* program_invocation_short_name,
 
35
                                   errno, EACCES, ENOTDIR, ELOOP,
47
36
                                   ENOENT, ENAMETOOLONG, EMFILE,
48
37
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
49
38
                                   E2BIG, EFAULT, EIO, ETXTBSY,
50
39
                                   EISDIR, ELIBBAD, EPERM, EINTR,
51
40
                                   ECHILD */
 
41
#include <string.h>             /* strerror(), memcmp() */
52
42
#include <error.h>              /* error() */
 
43
#include <stdlib.h>             /* free(), EXIT_FAILURE, getenv(),
 
44
                                   EXIT_SUCCESS, abort() */
 
45
#include <stddef.h>             /* NULL */
 
46
#include <dirent.h>             /* DIR, opendir(), struct dirent,
 
47
                                   readdir(), closedir() */
 
48
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
 
49
                                   EX_UNAVAILABLE */
 
50
#include <inttypes.h>           /* intmax_t, strtoimax() */
 
51
#include <iso646.h>             /* or, not, and */
 
52
#include <unistd.h>             /* ssize_t, readlink(), fork(),
 
53
                                   execl(), _exit(),
 
54
                                   TEMP_FAILURE_RETRY(), sleep(),
 
55
                                   setuid(), geteuid(), setsid(),
 
56
                                   chdir(), dup2(), STDERR_FILENO,
 
57
                                   STDOUT_FILENO, pause() */
 
58
#include <sys/stat.h>           /* struct stat, lstat(), S_ISLNK() */
 
59
#include <signal.h>             /* struct sigaction, sigemptyset(),
 
60
                                   sigaddset(), SIGINT, SIGHUP,
 
61
                                   SIGTERM, SIG_IGN, kill(), SIGKILL,
 
62
                                   SIG_DFL, raise() */
53
63
#include <sys/wait.h>           /* waitpid(), WIFEXITED(),
54
64
                                   WEXITSTATUS() */
55
 
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
56
 
                                   EX_UNAVAILABLE */
57
65
 
58
66
sig_atomic_t interrupted_by_signal = 0;
59
67
int signal_received;
60
68
 
 
69
/* Function to use when printing errors */
 
70
__attribute__((format (gnu_printf, 3, 4)))
 
71
void error_plus(int status, int errnum, const char *formatstring,
 
72
                ...){
 
73
  va_list ap;
 
74
  char *text;
 
75
  int ret;
 
76
  
 
77
  va_start(ap, formatstring);
 
78
  ret = vasprintf(&text, formatstring, ap);
 
79
  if(ret == -1){
 
80
    fprintf(stderr, "Mandos plugin %s: ",
 
81
            program_invocation_short_name);
 
82
    vfprintf(stderr, formatstring, ap);
 
83
    fprintf(stderr, ": ");
 
84
    fprintf(stderr, "%s\n", strerror(errnum));
 
85
    error(status, errno, "vasprintf while printing error");
 
86
    return;
 
87
  }
 
88
  fprintf(stderr, "Mandos plugin ");
 
89
  error(status, errnum, "%s", text);
 
90
  free(text);
 
91
}
 
92
 
 
93
 
61
94
static void termination_handler(int signum){
62
95
  if(interrupted_by_signal){
63
96
    return;
110
143
    proc_dir = opendir("/proc");
111
144
    if(proc_dir == NULL){
112
145
      int e = errno;
113
 
      error(0, errno, "opendir");
 
146
      error_plus(0, errno, "opendir");
114
147
      switch(e){
115
148
      case EACCES:
116
149
      case ENOTDIR:
152
185
        char *exe_link;
153
186
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
154
187
        if(ret == -1){
155
 
          error(0, errno, "asprintf");
 
188
          error_plus(0, errno, "asprintf");
156
189
          exitstatus = EX_OSERR;
157
190
          goto failure;
158
191
        }
166
199
            continue;
167
200
          }
168
201
          int e = errno;
169
 
          error(0, errno, "lstat");
 
202
          error_plus(0, errno, "lstat");
170
203
          free(exe_link);
171
204
          switch(e){
172
205
          case EACCES:
214
247
    sigemptyset(&new_action.sa_mask);
215
248
    ret = sigaddset(&new_action.sa_mask, SIGINT);
216
249
    if(ret == -1){
217
 
      error(0, errno, "sigaddset");
 
250
      error_plus(0, errno, "sigaddset");
218
251
      exitstatus = EX_OSERR;
219
252
      goto failure;
220
253
    }
221
254
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
222
255
    if(ret == -1){
223
 
      error(0, errno, "sigaddset");
 
256
      error_plus(0, errno, "sigaddset");
224
257
      exitstatus = EX_OSERR;
225
258
      goto failure;
226
259
    }
227
260
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
228
261
    if(ret == -1){
229
 
      error(0, errno, "sigaddset");
 
262
      error_plus(0, errno, "sigaddset");
230
263
      exitstatus = EX_OSERR;
231
264
      goto failure;
232
265
    }
233
266
    ret = sigaction(SIGINT, NULL, &old_action);
234
267
    if(ret == -1){
235
 
      error(0, errno, "sigaction");
 
268
      error_plus(0, errno, "sigaction");
236
269
      exitstatus = EX_OSERR;
237
270
      goto failure;
238
271
    }
239
272
    if(old_action.sa_handler != SIG_IGN){
240
273
      ret = sigaction(SIGINT, &new_action, NULL);
241
274
      if(ret == -1){
242
 
        error(0, errno, "sigaction");
 
275
        error_plus(0, errno, "sigaction");
243
276
        exitstatus = EX_OSERR;
244
277
        goto failure;
245
278
      }
246
279
    }
247
280
    ret = sigaction(SIGHUP, NULL, &old_action);
248
281
    if(ret == -1){
249
 
      error(0, errno, "sigaction");
 
282
      error_plus(0, errno, "sigaction");
250
283
      exitstatus = EX_OSERR;
251
284
      goto failure;
252
285
    }
253
286
    if(old_action.sa_handler != SIG_IGN){
254
287
      ret = sigaction(SIGHUP, &new_action, NULL);
255
288
      if(ret == -1){
256
 
        error(0, errno, "sigaction");
 
289
        error_plus(0, errno, "sigaction");
257
290
        exitstatus = EX_OSERR;
258
291
        goto failure;
259
292
      }
260
293
    }
261
294
    ret = sigaction(SIGTERM, NULL, &old_action);
262
295
    if(ret == -1){
263
 
      error(0, errno, "sigaction");
 
296
      error_plus(0, errno, "sigaction");
264
297
      exitstatus = EX_OSERR;
265
298
      goto failure;
266
299
    }
267
300
    if(old_action.sa_handler != SIG_IGN){
268
301
      ret = sigaction(SIGTERM, &new_action, NULL);
269
302
      if(ret == -1){
270
 
        error(0, errno, "sigaction");
 
303
        error_plus(0, errno, "sigaction");
271
304
        exitstatus = EX_OSERR;
272
305
        goto failure;
273
306
      }
284
317
    goto failure;
285
318
  }
286
319
  if(splashy_command_pid == -1){
287
 
    error(0, errno, "fork");
 
320
    error_plus(0, errno, "fork");
288
321
    exitstatus = EX_OSERR;
289
322
    goto failure;
290
323
  }
294
327
      const char splashy_command[] = "/sbin/splashy_update";
295
328
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
296
329
      int e = errno;
297
 
      error(0, errno, "execl");
 
330
      error_plus(0, errno, "execl");
298
331
      switch(e){
299
332
      case EACCES:
300
333
      case ENOENT:
344
377
      goto failure;
345
378
    }
346
379
    if(ret == -1){
347
 
      error(0, errno, "waitpid");
 
380
      error_plus(0, errno, "waitpid");
348
381
      if(errno == ECHILD){
349
382
        splashy_command_pid = 0;
350
383
      }
382
415
         the real user ID (_mandos) */
383
416
      ret = setuid(geteuid());
384
417
      if(ret == -1){
385
 
        error(0, errno, "setuid");
 
418
        error_plus(0, errno, "setuid");
386
419
      }
387
420
      
388
421
      setsid();
389
422
      ret = chdir("/");
390
423
      if(ret == -1){
391
 
        error(0, errno, "chdir");
 
424
        error_plus(0, errno, "chdir");
392
425
      }
393
426
/*       if(fork() != 0){ */
394
427
/*      _exit(EXIT_SUCCESS); */
395
428
/*       } */
396
429
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
397
430
      if(ret == -1){
398
 
        error(0, errno, "dup2");
 
431
        error_plus(0, errno, "dup2");
399
432
        _exit(EX_OSERR);
400
433
      }
401
434
      
402
435
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
403
436
      {
404
437
        int e = errno;
405
 
        error(0, errno, "execl");
 
438
        error_plus(0, errno, "execl");
406
439
        switch(e){
407
440
        case EACCES:
408
441
        case ENOENT:
428
461
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
429
462
                                            &signal_action, NULL));
430
463
    if(ret == -1){
431
 
      error(0, errno, "sigaction");
 
464
      error_plus(0, errno, "sigaction");
432
465
    }
433
466
    do {
434
467
      ret = raise(signal_received);
435
468
    } while(ret != 0 and errno == EINTR);
436
469
    if(ret != 0){
437
 
      error(0, errno, "raise");
 
470
      error_plus(0, errno, "raise");
438
471
      abort();
439
472
    }
440
473
    TEMP_FAILURE_RETRY(pause());