/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: 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
 * 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
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 Teddy Hogeborn
 
6
 * Copyright © 2008-2018 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
26
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
29
30
                                   SIG_IGN, kill(), SIGKILL */
30
31
#include <stddef.h>             /* NULL */
31
32
#include <stdlib.h>             /* getenv() */
32
 
#include <stdio.h>              /* asprintf(), perror() */
 
33
#include <stdio.h>              /* asprintf(), vasprintf(), vprintf(),
 
34
                                   fprintf() */
33
35
#include <stdlib.h>             /* EXIT_FAILURE, free(),
34
36
                                   EXIT_SUCCESS */
35
37
#include <sys/types.h>          /* pid_t, DIR, struct dirent,
42
44
                                   sleep(), dup2() STDERR_FILENO,
43
45
                                   STDOUT_FILENO, _exit(),
44
46
                                   pause() */
45
 
#include <string.h>             /* memcmp() */
46
 
#include <errno.h>              /* errno */
 
47
#include <string.h>             /* memcmp(), strerror() */
 
48
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
 
49
                                   ENOENT, ENAMETOOLONG, EMFILE,
 
50
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
 
51
                                   E2BIG, EFAULT, EIO, ETXTBSY,
 
52
                                   EISDIR, ELIBBAD, EPERM, EINTR,
 
53
                                   ECHILD */
 
54
#include <error.h>              /* error() */
47
55
#include <sys/wait.h>           /* waitpid(), WIFEXITED(),
48
56
                                   WEXITSTATUS() */
49
 
 
50
57
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
51
58
                                   EX_UNAVAILABLE */
 
59
#include <stdarg.h>             /* va_list, va_start(), ... */
52
60
 
53
61
sig_atomic_t interrupted_by_signal = 0;
54
62
int signal_received;
55
63
 
 
64
/* Function to use when printing errors */
 
65
__attribute__((format (gnu_printf, 3, 4)))
 
66
void error_plus(int status, int errnum, const char *formatstring,
 
67
                ...){
 
68
  va_list ap;
 
69
  char *text;
 
70
  int ret;
 
71
  
 
72
  va_start(ap, formatstring);
 
73
  ret = vasprintf(&text, formatstring, ap);
 
74
  if(ret == -1){
 
75
    fprintf(stderr, "Mandos plugin %s: ",
 
76
            program_invocation_short_name);
 
77
    vfprintf(stderr, formatstring, ap);
 
78
    fprintf(stderr, ": ");
 
79
    fprintf(stderr, "%s\n", strerror(errnum));
 
80
    error(status, errno, "vasprintf while printing error");
 
81
    return;
 
82
  }
 
83
  fprintf(stderr, "Mandos plugin ");
 
84
  error(status, errnum, "%s", text);
 
85
  free(text);
 
86
}
 
87
 
 
88
 
56
89
static void termination_handler(int signum){
57
90
  if(interrupted_by_signal){
58
91
    return;
105
138
    proc_dir = opendir("/proc");
106
139
    if(proc_dir == NULL){
107
140
      int e = errno;
108
 
      perror("opendir");
 
141
      error_plus(0, errno, "opendir");
109
142
      switch(e){
110
143
      case EACCES:
111
144
      case ENOTDIR:
147
180
        char *exe_link;
148
181
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
149
182
        if(ret == -1){
150
 
          perror("asprintf");
 
183
          error_plus(0, errno, "asprintf");
151
184
          exitstatus = EX_OSERR;
152
185
          goto failure;
153
186
        }
161
194
            continue;
162
195
          }
163
196
          int e = errno;
164
 
          perror("lstat");
 
197
          error_plus(0, errno, "lstat");
165
198
          free(exe_link);
166
199
          switch(e){
167
200
          case EACCES:
209
242
    sigemptyset(&new_action.sa_mask);
210
243
    ret = sigaddset(&new_action.sa_mask, SIGINT);
211
244
    if(ret == -1){
212
 
      perror("sigaddset");
 
245
      error_plus(0, errno, "sigaddset");
213
246
      exitstatus = EX_OSERR;
214
247
      goto failure;
215
248
    }
216
249
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
217
250
    if(ret == -1){
218
 
      perror("sigaddset");
 
251
      error_plus(0, errno, "sigaddset");
219
252
      exitstatus = EX_OSERR;
220
253
      goto failure;
221
254
    }
222
255
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
223
256
    if(ret == -1){
224
 
      perror("sigaddset");
 
257
      error_plus(0, errno, "sigaddset");
225
258
      exitstatus = EX_OSERR;
226
259
      goto failure;
227
260
    }
228
261
    ret = sigaction(SIGINT, NULL, &old_action);
229
262
    if(ret == -1){
230
 
      perror("sigaction");
 
263
      error_plus(0, errno, "sigaction");
231
264
      exitstatus = EX_OSERR;
232
265
      goto failure;
233
266
    }
234
267
    if(old_action.sa_handler != SIG_IGN){
235
268
      ret = sigaction(SIGINT, &new_action, NULL);
236
269
      if(ret == -1){
237
 
        perror("sigaction");
 
270
        error_plus(0, errno, "sigaction");
238
271
        exitstatus = EX_OSERR;
239
272
        goto failure;
240
273
      }
241
274
    }
242
275
    ret = sigaction(SIGHUP, NULL, &old_action);
243
276
    if(ret == -1){
244
 
      perror("sigaction");
 
277
      error_plus(0, errno, "sigaction");
245
278
      exitstatus = EX_OSERR;
246
279
      goto failure;
247
280
    }
248
281
    if(old_action.sa_handler != SIG_IGN){
249
282
      ret = sigaction(SIGHUP, &new_action, NULL);
250
283
      if(ret == -1){
251
 
        perror("sigaction");
 
284
        error_plus(0, errno, "sigaction");
252
285
        exitstatus = EX_OSERR;
253
286
        goto failure;
254
287
      }
255
288
    }
256
289
    ret = sigaction(SIGTERM, NULL, &old_action);
257
290
    if(ret == -1){
258
 
      perror("sigaction");
 
291
      error_plus(0, errno, "sigaction");
259
292
      exitstatus = EX_OSERR;
260
293
      goto failure;
261
294
    }
262
295
    if(old_action.sa_handler != SIG_IGN){
263
296
      ret = sigaction(SIGTERM, &new_action, NULL);
264
297
      if(ret == -1){
265
 
        perror("sigaction");
 
298
        error_plus(0, errno, "sigaction");
266
299
        exitstatus = EX_OSERR;
267
300
        goto failure;
268
301
      }
279
312
    goto failure;
280
313
  }
281
314
  if(splashy_command_pid == -1){
282
 
    perror("fork");
 
315
    error_plus(0, errno, "fork");
283
316
    exitstatus = EX_OSERR;
284
317
    goto failure;
285
318
  }
288
321
    if(not interrupted_by_signal){
289
322
      const char splashy_command[] = "/sbin/splashy_update";
290
323
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
291
 
      perror("execl");
 
324
      int e = errno;
 
325
      error_plus(0, errno, "execl");
 
326
      switch(e){
 
327
      case EACCES:
 
328
      case ENOENT:
 
329
      case ENOEXEC:
 
330
      case EINVAL:
 
331
        _exit(EX_UNAVAILABLE);
 
332
      case ENAMETOOLONG:
 
333
      case E2BIG:
 
334
      case ENOMEM:
 
335
      case EFAULT:
 
336
      case EIO:
 
337
      case EMFILE:
 
338
      case ENFILE:
 
339
      case ETXTBSY:
 
340
      default:
 
341
        _exit(EX_OSERR);
 
342
      case ENOTDIR:
 
343
      case ELOOP:
 
344
      case EISDIR:
 
345
#ifdef ELIBBAD
 
346
      case ELIBBAD:             /* Linux only */
 
347
#endif
 
348
      case EPERM:
 
349
        _exit(EX_OSFILE);
 
350
      }
292
351
    }
293
352
    free(prompt);
294
353
    _exit(EXIT_FAILURE);
313
372
      goto failure;
314
373
    }
315
374
    if(ret == -1){
316
 
      perror("waitpid");
 
375
      error_plus(0, errno, "waitpid");
317
376
      if(errno == ECHILD){
318
377
        splashy_command_pid = 0;
319
378
      }
351
410
         the real user ID (_mandos) */
352
411
      ret = setuid(geteuid());
353
412
      if(ret == -1){
354
 
        perror("setuid");
 
413
        error_plus(0, errno, "setuid");
355
414
      }
356
415
      
357
416
      setsid();
358
417
      ret = chdir("/");
359
418
      if(ret == -1){
360
 
        perror("chdir");
 
419
        error_plus(0, errno, "chdir");
361
420
      }
362
421
/*       if(fork() != 0){ */
363
422
/*      _exit(EXIT_SUCCESS); */
364
423
/*       } */
365
424
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
366
425
      if(ret == -1){
367
 
        perror("dup2");
 
426
        error_plus(0, errno, "dup2");
368
427
        _exit(EX_OSERR);
369
428
      }
370
429
      
371
430
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
372
431
      {
373
432
        int e = errno;
374
 
        perror("execl");
 
433
        error_plus(0, errno, "execl");
375
434
        switch(e){
376
435
        case EACCES:
377
436
        case ENOENT:
397
456
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
398
457
                                            &signal_action, NULL));
399
458
    if(ret == -1){
400
 
      perror("sigaction");
 
459
      error_plus(0, errno, "sigaction");
401
460
    }
402
461
    do {
403
462
      ret = raise(signal_received);
404
463
    } while(ret != 0 and errno == EINTR);
405
464
    if(ret != 0){
406
 
      perror("raise");
 
465
      error_plus(0, errno, "raise");
407
466
      abort();
408
467
    }
409
468
    TEMP_FAILURE_RETRY(pause());