/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: 2016-06-03 17:27:03 UTC
  • Revision ID: teddy@recompile.se-20160603172703-mc6tjor6rhq4xy74
mandos: Bug fix: Do multiprocessing cleanup correctly on exit

* mandos (main): Save module "multiprocessing" and open file "wnull"
                 as scope variables accessible by function cleanup(),
                 since the module and global variable may not be
                 accessible when the cleanup() function is run as
                 scheduled by atexit().

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,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 Björn Påhlsson
 
5
 * Copyright © 2008-2016 Teddy Hogeborn
 
6
 * Copyright © 2008-2016 Björn Påhlsson
7
7
 * 
8
8
 * This program is free software: you can redistribute it and/or
9
9
 * modify it under the terms of the GNU General Public License as
19
19
 * along with this program.  If not, see
20
20
 * <http://www.gnu.org/licenses/>.
21
21
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
22
 * Contact the authors at <mandos@recompile.se>.
23
23
 */
24
24
 
25
25
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
29
29
                                   SIG_IGN, kill(), SIGKILL */
30
30
#include <stddef.h>             /* NULL */
31
31
#include <stdlib.h>             /* getenv() */
32
 
#include <stdio.h>              /* asprintf(), perror() */
 
32
#include <stdio.h>              /* asprintf(), vasprintf(), vprintf(),
 
33
                                   fprintf() */
33
34
#include <stdlib.h>             /* EXIT_FAILURE, free(),
34
35
                                   EXIT_SUCCESS */
35
36
#include <sys/types.h>          /* pid_t, DIR, struct dirent,
42
43
                                   sleep(), dup2() STDERR_FILENO,
43
44
                                   STDOUT_FILENO, _exit(),
44
45
                                   pause() */
45
 
#include <string.h>             /* memcmp() */
 
46
#include <string.h>             /* memcmp(), strerror() */
46
47
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
47
48
                                   ENOENT, ENAMETOOLONG, EMFILE,
48
49
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
49
50
                                   E2BIG, EFAULT, EIO, ETXTBSY,
50
51
                                   EISDIR, ELIBBAD, EPERM, EINTR,
51
52
                                   ECHILD */
 
53
#include <error.h>              /* error() */
52
54
#include <sys/wait.h>           /* waitpid(), WIFEXITED(),
53
55
                                   WEXITSTATUS() */
54
56
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
55
57
                                   EX_UNAVAILABLE */
 
58
#include <stdarg.h>             /* va_list, va_start(), ... */
56
59
 
57
60
sig_atomic_t interrupted_by_signal = 0;
58
61
int signal_received;
59
62
 
 
63
/* Function to use when printing errors */
 
64
__attribute__((format (gnu_printf, 3, 4)))
 
65
void error_plus(int status, int errnum, const char *formatstring,
 
66
                ...){
 
67
  va_list ap;
 
68
  char *text;
 
69
  int ret;
 
70
  
 
71
  va_start(ap, formatstring);
 
72
  ret = vasprintf(&text, formatstring, ap);
 
73
  if(ret == -1){
 
74
    fprintf(stderr, "Mandos plugin %s: ",
 
75
            program_invocation_short_name);
 
76
    vfprintf(stderr, formatstring, ap);
 
77
    fprintf(stderr, ": ");
 
78
    fprintf(stderr, "%s\n", strerror(errnum));
 
79
    error(status, errno, "vasprintf while printing error");
 
80
    return;
 
81
  }
 
82
  fprintf(stderr, "Mandos plugin ");
 
83
  error(status, errnum, "%s", text);
 
84
  free(text);
 
85
}
 
86
 
 
87
 
60
88
static void termination_handler(int signum){
61
89
  if(interrupted_by_signal){
62
90
    return;
109
137
    proc_dir = opendir("/proc");
110
138
    if(proc_dir == NULL){
111
139
      int e = errno;
112
 
      perror("opendir");
 
140
      error_plus(0, errno, "opendir");
113
141
      switch(e){
114
142
      case EACCES:
115
143
      case ENOTDIR:
151
179
        char *exe_link;
152
180
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
153
181
        if(ret == -1){
154
 
          perror("asprintf");
 
182
          error_plus(0, errno, "asprintf");
155
183
          exitstatus = EX_OSERR;
156
184
          goto failure;
157
185
        }
165
193
            continue;
166
194
          }
167
195
          int e = errno;
168
 
          perror("lstat");
 
196
          error_plus(0, errno, "lstat");
169
197
          free(exe_link);
170
198
          switch(e){
171
199
          case EACCES:
213
241
    sigemptyset(&new_action.sa_mask);
214
242
    ret = sigaddset(&new_action.sa_mask, SIGINT);
215
243
    if(ret == -1){
216
 
      perror("sigaddset");
 
244
      error_plus(0, errno, "sigaddset");
217
245
      exitstatus = EX_OSERR;
218
246
      goto failure;
219
247
    }
220
248
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
221
249
    if(ret == -1){
222
 
      perror("sigaddset");
 
250
      error_plus(0, errno, "sigaddset");
223
251
      exitstatus = EX_OSERR;
224
252
      goto failure;
225
253
    }
226
254
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
227
255
    if(ret == -1){
228
 
      perror("sigaddset");
 
256
      error_plus(0, errno, "sigaddset");
229
257
      exitstatus = EX_OSERR;
230
258
      goto failure;
231
259
    }
232
260
    ret = sigaction(SIGINT, NULL, &old_action);
233
261
    if(ret == -1){
234
 
      perror("sigaction");
 
262
      error_plus(0, errno, "sigaction");
235
263
      exitstatus = EX_OSERR;
236
264
      goto failure;
237
265
    }
238
266
    if(old_action.sa_handler != SIG_IGN){
239
267
      ret = sigaction(SIGINT, &new_action, NULL);
240
268
      if(ret == -1){
241
 
        perror("sigaction");
 
269
        error_plus(0, errno, "sigaction");
242
270
        exitstatus = EX_OSERR;
243
271
        goto failure;
244
272
      }
245
273
    }
246
274
    ret = sigaction(SIGHUP, NULL, &old_action);
247
275
    if(ret == -1){
248
 
      perror("sigaction");
 
276
      error_plus(0, errno, "sigaction");
249
277
      exitstatus = EX_OSERR;
250
278
      goto failure;
251
279
    }
252
280
    if(old_action.sa_handler != SIG_IGN){
253
281
      ret = sigaction(SIGHUP, &new_action, NULL);
254
282
      if(ret == -1){
255
 
        perror("sigaction");
 
283
        error_plus(0, errno, "sigaction");
256
284
        exitstatus = EX_OSERR;
257
285
        goto failure;
258
286
      }
259
287
    }
260
288
    ret = sigaction(SIGTERM, NULL, &old_action);
261
289
    if(ret == -1){
262
 
      perror("sigaction");
 
290
      error_plus(0, errno, "sigaction");
263
291
      exitstatus = EX_OSERR;
264
292
      goto failure;
265
293
    }
266
294
    if(old_action.sa_handler != SIG_IGN){
267
295
      ret = sigaction(SIGTERM, &new_action, NULL);
268
296
      if(ret == -1){
269
 
        perror("sigaction");
 
297
        error_plus(0, errno, "sigaction");
270
298
        exitstatus = EX_OSERR;
271
299
        goto failure;
272
300
      }
283
311
    goto failure;
284
312
  }
285
313
  if(splashy_command_pid == -1){
286
 
    perror("fork");
 
314
    error_plus(0, errno, "fork");
287
315
    exitstatus = EX_OSERR;
288
316
    goto failure;
289
317
  }
293
321
      const char splashy_command[] = "/sbin/splashy_update";
294
322
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
295
323
      int e = errno;
296
 
      perror("execl");
 
324
      error_plus(0, errno, "execl");
297
325
      switch(e){
298
326
      case EACCES:
299
327
      case ENOENT:
313
341
      case ENOTDIR:
314
342
      case ELOOP:
315
343
      case EISDIR:
316
 
      case ELIBBAD:
 
344
#ifdef ELIBBAD
 
345
      case ELIBBAD:             /* Linux only */
 
346
#endif
317
347
      case EPERM:
318
348
        _exit(EX_OSFILE);
319
349
      }
341
371
      goto failure;
342
372
    }
343
373
    if(ret == -1){
344
 
      perror("waitpid");
 
374
      error_plus(0, errno, "waitpid");
345
375
      if(errno == ECHILD){
346
376
        splashy_command_pid = 0;
347
377
      }
379
409
         the real user ID (_mandos) */
380
410
      ret = setuid(geteuid());
381
411
      if(ret == -1){
382
 
        perror("setuid");
 
412
        error_plus(0, errno, "setuid");
383
413
      }
384
414
      
385
415
      setsid();
386
416
      ret = chdir("/");
387
417
      if(ret == -1){
388
 
        perror("chdir");
 
418
        error_plus(0, errno, "chdir");
389
419
      }
390
420
/*       if(fork() != 0){ */
391
421
/*      _exit(EXIT_SUCCESS); */
392
422
/*       } */
393
423
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
394
424
      if(ret == -1){
395
 
        perror("dup2");
 
425
        error_plus(0, errno, "dup2");
396
426
        _exit(EX_OSERR);
397
427
      }
398
428
      
399
429
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
400
430
      {
401
431
        int e = errno;
402
 
        perror("execl");
 
432
        error_plus(0, errno, "execl");
403
433
        switch(e){
404
434
        case EACCES:
405
435
        case ENOENT:
425
455
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
426
456
                                            &signal_action, NULL));
427
457
    if(ret == -1){
428
 
      perror("sigaction");
 
458
      error_plus(0, errno, "sigaction");
429
459
    }
430
460
    do {
431
461
      ret = raise(signal_received);
432
462
    } while(ret != 0 and errno == EINTR);
433
463
    if(ret != 0){
434
 
      perror("raise");
 
464
      error_plus(0, errno, "raise");
435
465
      abort();
436
466
    }
437
467
    TEMP_FAILURE_RETRY(pause());