/mandos/release

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

« back to all changes in this revision

Viewing changes to plugins.d/splashy.c

  • Committer: Teddy Hogeborn
  • Date: 2019-07-29 16:35:53 UTC
  • mto: This revision was merged to the branch mainline in revision 384.
  • Revision ID: teddy@recompile.se-20190729163553-1i442i2cbx64c537
Make tests and man page examples match

Make the tests test_manual_page_example[1-5] match exactly what is
written in the manual page, and add comments to manual page as
reminders to keep tests and manual page examples in sync.

* mandos-ctl (Test_commands_from_options.test_manual_page_example_1):
  Remove "--verbose" option, since the manual does not have it as the
  first example, and change assertion to match.
* mandos-ctl.xml (EXAMPLE): Add comments to all examples documenting
  which test function they correspond to.  Also remove unnecessary
  quotes from option arguments in fourth example, and clarify language
  slightly in fifth example.

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 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() */
 
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() */
 
47
#include <string.h>             /* memcmp(), strerror() */
46
48
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
47
49
                                   ENOENT, ENAMETOOLONG, EMFILE,
48
50
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
54
56
                                   WEXITSTATUS() */
55
57
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
56
58
                                   EX_UNAVAILABLE */
 
59
#include <stdarg.h>             /* va_list, va_start(), ... */
57
60
 
58
61
sig_atomic_t interrupted_by_signal = 0;
59
62
int signal_received;
60
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
 
61
89
static void termination_handler(int signum){
62
90
  if(interrupted_by_signal){
63
91
    return;
110
138
    proc_dir = opendir("/proc");
111
139
    if(proc_dir == NULL){
112
140
      int e = errno;
113
 
      error(0, errno, "opendir");
 
141
      error_plus(0, errno, "opendir");
114
142
      switch(e){
115
143
      case EACCES:
116
144
      case ENOTDIR:
152
180
        char *exe_link;
153
181
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
154
182
        if(ret == -1){
155
 
          error(0, errno, "asprintf");
 
183
          error_plus(0, errno, "asprintf");
156
184
          exitstatus = EX_OSERR;
157
185
          goto failure;
158
186
        }
166
194
            continue;
167
195
          }
168
196
          int e = errno;
169
 
          error(0, errno, "lstat");
 
197
          error_plus(0, errno, "lstat");
170
198
          free(exe_link);
171
199
          switch(e){
172
200
          case EACCES:
214
242
    sigemptyset(&new_action.sa_mask);
215
243
    ret = sigaddset(&new_action.sa_mask, SIGINT);
216
244
    if(ret == -1){
217
 
      error(0, errno, "sigaddset");
 
245
      error_plus(0, errno, "sigaddset");
218
246
      exitstatus = EX_OSERR;
219
247
      goto failure;
220
248
    }
221
249
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
222
250
    if(ret == -1){
223
 
      error(0, errno, "sigaddset");
 
251
      error_plus(0, errno, "sigaddset");
224
252
      exitstatus = EX_OSERR;
225
253
      goto failure;
226
254
    }
227
255
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
228
256
    if(ret == -1){
229
 
      error(0, errno, "sigaddset");
 
257
      error_plus(0, errno, "sigaddset");
230
258
      exitstatus = EX_OSERR;
231
259
      goto failure;
232
260
    }
233
261
    ret = sigaction(SIGINT, NULL, &old_action);
234
262
    if(ret == -1){
235
 
      error(0, errno, "sigaction");
 
263
      error_plus(0, errno, "sigaction");
236
264
      exitstatus = EX_OSERR;
237
265
      goto failure;
238
266
    }
239
267
    if(old_action.sa_handler != SIG_IGN){
240
268
      ret = sigaction(SIGINT, &new_action, NULL);
241
269
      if(ret == -1){
242
 
        error(0, errno, "sigaction");
 
270
        error_plus(0, errno, "sigaction");
243
271
        exitstatus = EX_OSERR;
244
272
        goto failure;
245
273
      }
246
274
    }
247
275
    ret = sigaction(SIGHUP, NULL, &old_action);
248
276
    if(ret == -1){
249
 
      error(0, errno, "sigaction");
 
277
      error_plus(0, errno, "sigaction");
250
278
      exitstatus = EX_OSERR;
251
279
      goto failure;
252
280
    }
253
281
    if(old_action.sa_handler != SIG_IGN){
254
282
      ret = sigaction(SIGHUP, &new_action, NULL);
255
283
      if(ret == -1){
256
 
        error(0, errno, "sigaction");
 
284
        error_plus(0, errno, "sigaction");
257
285
        exitstatus = EX_OSERR;
258
286
        goto failure;
259
287
      }
260
288
    }
261
289
    ret = sigaction(SIGTERM, NULL, &old_action);
262
290
    if(ret == -1){
263
 
      error(0, errno, "sigaction");
 
291
      error_plus(0, errno, "sigaction");
264
292
      exitstatus = EX_OSERR;
265
293
      goto failure;
266
294
    }
267
295
    if(old_action.sa_handler != SIG_IGN){
268
296
      ret = sigaction(SIGTERM, &new_action, NULL);
269
297
      if(ret == -1){
270
 
        error(0, errno, "sigaction");
 
298
        error_plus(0, errno, "sigaction");
271
299
        exitstatus = EX_OSERR;
272
300
        goto failure;
273
301
      }
284
312
    goto failure;
285
313
  }
286
314
  if(splashy_command_pid == -1){
287
 
    error(0, errno, "fork");
 
315
    error_plus(0, errno, "fork");
288
316
    exitstatus = EX_OSERR;
289
317
    goto failure;
290
318
  }
294
322
      const char splashy_command[] = "/sbin/splashy_update";
295
323
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
296
324
      int e = errno;
297
 
      error(0, errno, "execl");
 
325
      error_plus(0, errno, "execl");
298
326
      switch(e){
299
327
      case EACCES:
300
328
      case ENOENT:
344
372
      goto failure;
345
373
    }
346
374
    if(ret == -1){
347
 
      error(0, errno, "waitpid");
 
375
      error_plus(0, errno, "waitpid");
348
376
      if(errno == ECHILD){
349
377
        splashy_command_pid = 0;
350
378
      }
382
410
         the real user ID (_mandos) */
383
411
      ret = setuid(geteuid());
384
412
      if(ret == -1){
385
 
        error(0, errno, "setuid");
 
413
        error_plus(0, errno, "setuid");
386
414
      }
387
415
      
388
416
      setsid();
389
417
      ret = chdir("/");
390
418
      if(ret == -1){
391
 
        error(0, errno, "chdir");
 
419
        error_plus(0, errno, "chdir");
392
420
      }
393
421
/*       if(fork() != 0){ */
394
422
/*      _exit(EXIT_SUCCESS); */
395
423
/*       } */
396
424
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
397
425
      if(ret == -1){
398
 
        error(0, errno, "dup2");
 
426
        error_plus(0, errno, "dup2");
399
427
        _exit(EX_OSERR);
400
428
      }
401
429
      
402
430
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
403
431
      {
404
432
        int e = errno;
405
 
        error(0, errno, "execl");
 
433
        error_plus(0, errno, "execl");
406
434
        switch(e){
407
435
        case EACCES:
408
436
        case ENOENT:
428
456
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
429
457
                                            &signal_action, NULL));
430
458
    if(ret == -1){
431
 
      error(0, errno, "sigaction");
 
459
      error_plus(0, errno, "sigaction");
432
460
    }
433
461
    do {
434
462
      ret = raise(signal_received);
435
463
    } while(ret != 0 and errno == EINTR);
436
464
    if(ret != 0){
437
 
      error(0, errno, "raise");
 
465
      error_plus(0, errno, "raise");
438
466
      abort();
439
467
    }
440
468
    TEMP_FAILURE_RETRY(pause());