/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: 2024-09-09 01:36:41 UTC
  • Revision ID: teddy@recompile.se-20240909013641-6zu6kx2f7meu134k
Make all required directories when installing

When installing into a normal system, one can assume that target
directories, such as /usr/bin, already exists.  But when installing
into a subdirectory for the purpose of creating a package, one cannot
assume that all directories already exist.  Therefore, when
installing, we must not check if any directories exist, and must
instead always create any directories we want to install into.

* Makefile (confdir/mandos.conf, confdir/clients.conf, install-html):
  Use the "-D" option to "install" instead of creating the directory
  separately.
  (install-server): Move creation of $(CONFDIR) down to before it is
  needed.  Don't check if the $(TMPFILES) or $(SYSUSERS) directories
  exist; instead create them by using the "-D" option to "install".
  Create the $(PREFIX)/sbin directory.  Always use
  "--target-directory" if possible; i.e. if the file name is the same.
  Create the $(DBUSPOLICYDIR) and $(DESTDIR)/etc/init.d directories by
  using the "-D" option to "install".  Don't check if the $(SYSTEMD)
  directory exists; instead create it by using the "-D" option to
  "install".  Create the $(DESTDIR)/etc/default and $(MANDIR)/man8
  directories by using the "-D" option to "install".  Create the
  $(MANDIR)/man5 directories explicitly.
  (install-client-nokey): Remove unnecessary creation of the
  $(CONFDIR) directory.  Don't check if the $(SYSUSERS) directory
  exists; instead create it by using the "-D" option to "install".
  Move the "--directory" argument to be the first argument, for
  clarity.  Create the $(PREFIX)/sbin directory.  Use the "-D"
  argument to "install" when installing
  $(INITRAMFSTOOLS)/hooks/mandos,
  $(INITRAMFSTOOLS)/conf.d/mandos-conf,
  $(INITRAMFSTOOLS)/conf-hooks.d/zz-mandos,
  $(INITRAMFSTOOLS)/scripts/init-premount/mandos,
  $(INITRAMFSTOOLS)/scripts/local-premount/mandos,
  $(DRACUTMODULE)/ask-password-mandos.path, and
  $(DRACUTMODULE)/dracut-module/ask-password-mandos.service.  Create
  the $(MANDIR)/man8 directory.

Reported-By: Erich Eckner <erich@eckner.net>
Thanks: Erich Eckner <erich@eckner.net> for analysis

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-2022 Teddy Hogeborn
 
6
 * Copyright © 2008-2018, 2021-2022 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());