/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/usplash.c

First version of a somewhat complete D-Bus server interface.  Also
change user/group name to "_mandos".

* debian/mandos.postinst: Rename old "mandos" user and group to
                          "_mandos"; create "_mandos" user and group
                          if none exist.
* debian/mandos-client.postinst: - '' -

* initramfs-tools-hook: Try "_mandos" before "mandos" as user and
                        group name.

* mandos (_datetime_to_dbus_struct): New; was previously local.
  (Client.started): Renamed to "last_started".  All users changed.
  (Client.started): New; boolean.
  (Client.dbus_object_path): New.
  (Client.check_command): Renamed to "checker_command".  All users
                          changed.
  (Client.__init__): Set and use "self.dbus_object_path".  Set
                     "self.started".
  (Client.start): Update "self.started".  Emit "self.PropertyChanged"
                  signals for both "started" and "last_started".
  (Client.stop): Update "self.started".  Emit "self.PropertyChanged"
                 signal for "started".
  (Client.checker_callback): Take additional "command" argument.  All
                             callers changed. Emit
                             "self.PropertyChanged" signal.
  (Client.bump_timeout): Emit "self.PropertyChanged" signal for
                         "last_checked_ok".
  (Client.start_checker): Emit "self.PropertyChanged" signal for
                          "checker_running".
  (Client.stop_checker): Emit "self.PropertyChanged" signal for
                         "checker_running".
  (Client.still_valid): Bug fix: use "getattr(self, started, False)"
                        instead of "self.started" in case this client
                        object is so new that the "started" attribute
                        has not been created yet.
  (Client.IntervalChanged, Client.CheckerIsRunning, Client.GetChecker,
  Client.GetCreated, Client.GetFingerprint, Client.GetHost,
  Client.GetInterval, Client.GetName, Client.GetStarted,
  Client.GetTimeout, Client.StateChanged, Client.TimeoutChanged):
  Removed; all callers changed.
  (Client.CheckerCompleted): Add "condition" and "command" arguments.
                             All callers changed.
  (Client.GetAllProperties, Client.PropertyChanged): New.
  (Client.StillValid): Renamed to "IsStillValid".
  (Client.StartChecker): Changed to its own function to avoid the
                         return value from "Client.start_checker()".
  (Client.Stop): Changed to its own function to avoid the return value
                 from "Client.stop()".
  (main): Try "_mandos" before "mandos" as user and group name.
          Removed inner function "remove_from_clients".  New inner
          class "MandosServer".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*  -*- coding: utf-8 -*- */
2
2
/*
3
 
 * Usplash - Read a password from usplash and output it
 
3
 * Passprompt - Read a password from usplash and output it
4
4
 * 
5
 
 * Copyright © 2008,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 Björn Påhlsson
 
5
 * Copyright © 2008 Teddy Hogeborn
 
6
 * Copyright © 2008 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 <https://www.fukt.bsnet.se/~belorn/> and
 
23
 * <https://www.fukt.bsnet.se/~teddy/>.
23
24
 */
24
25
 
25
26
#define _GNU_SOURCE             /* asprintf() */
41
42
                                   fork(), setuid(), geteuid(),
42
43
                                   setsid(), chdir(), dup2(),
43
44
                                   STDERR_FILENO, execv() */
44
 
#include <stdlib.h>             /* free(), EXIT_FAILURE, realloc(),
45
 
                                   EXIT_SUCCESS, malloc(), _exit() */
 
45
#include <stdlib.h>             /* free(), EXIT_FAILURE, strtoul(),
 
46
                                   realloc(), EXIT_SUCCESS, malloc(),
 
47
                                   _exit() */
46
48
#include <stdlib.h>             /* getenv() */
47
49
#include <dirent.h>             /* opendir(), readdir(), closedir() */
48
 
#include <inttypes.h>           /* intmax_t, strtoimax() */
49
50
#include <sys/stat.h>           /* struct stat, lstat(), S_ISLNK */
50
51
 
51
52
sig_atomic_t interrupted_by_signal = 0;
63
64
   */
64
65
  int ret;
65
66
  int fifo_fd;
66
 
  do {
 
67
  do{
67
68
    fifo_fd = open("/dev/.initramfs/usplash_fifo", O_WRONLY);
68
 
    if((fifo_fd == -1) and (errno != EINTR or interrupted_by_signal)){
 
69
    if(fifo_fd == -1 and (errno != EINTR or interrupted_by_signal)){
69
70
      return false;
70
71
    }
71
 
  } while(fifo_fd == -1);
 
72
  }while(fifo_fd == -1);
72
73
  
73
74
  const char *cmd_line;
74
75
  size_t cmd_line_len;
76
77
  if(arg == NULL){
77
78
    cmd_line = cmd;
78
79
    cmd_line_len = strlen(cmd);
79
 
  } else {
80
 
    do {
 
80
  }else{
 
81
    do{
81
82
      ret = asprintf(&cmd_line_alloc, "%s %s", cmd, arg);
82
83
      if(ret == -1 and (errno != EINTR or interrupted_by_signal)){
83
84
        int e = errno;
85
86
        errno = e;
86
87
        return false;
87
88
      }
88
 
    } while(ret == -1);
 
89
    }while(ret == -1);
89
90
    cmd_line = cmd_line_alloc;
90
91
    cmd_line_len = (size_t)ret + 1;
91
92
  }
92
93
  
93
94
  size_t written = 0;
94
 
  ssize_t sret = 0;
95
95
  while(not interrupted_by_signal and written < cmd_line_len){
96
 
    sret = write(fifo_fd, cmd_line + written,
97
 
                 cmd_line_len - written);
98
 
    if(sret == -1){
 
96
    ret = write(fifo_fd, cmd_line + written,
 
97
                cmd_line_len - written);
 
98
    if(ret == -1){
99
99
      if(errno != EINTR or interrupted_by_signal){
100
100
        int e = errno;
101
101
        close(fifo_fd);
106
106
        continue;
107
107
      }
108
108
    }
109
 
    written += (size_t)sret;
 
109
    written += (size_t)ret;
110
110
  }
111
111
  free(cmd_line_alloc);
112
 
  do {
 
112
  do{
113
113
    ret = close(fifo_fd);
114
114
    if(ret == -1 and (errno != EINTR or interrupted_by_signal)){
115
115
      return false;
116
116
    }
117
 
  } while(ret == -1);
 
117
  }while(ret == -1);
118
118
  if(interrupted_by_signal){
119
119
    return false;
120
120
  }
169
169
    for(struct dirent *proc_ent = readdir(proc_dir);
170
170
        proc_ent != NULL;
171
171
        proc_ent = readdir(proc_dir)){
172
 
      pid_t pid;
173
 
      {
174
 
        intmax_t tmpmax;
175
 
        char *tmp;
176
 
        errno = 0;
177
 
        tmpmax = strtoimax(proc_ent->d_name, &tmp, 10);
178
 
        if(errno != 0 or tmp == proc_ent->d_name or *tmp != '\0'
179
 
           or tmpmax != (pid_t)tmpmax){
180
 
          /* Not a process */
181
 
          continue;
182
 
        }
183
 
        pid = (pid_t)tmpmax;
 
172
      pid_t pid = (pid_t) strtoul(proc_ent->d_name, NULL, 10);
 
173
      if(pid == 0){
 
174
        /* Not a process */
 
175
        continue;
184
176
      }
185
177
      /* Find the executable name by doing readlink() on the
186
178
         /proc/<pid>/exe link */
200
192
        struct stat exe_stat;
201
193
        ret = lstat(exe_link, &exe_stat);
202
194
        if(ret == -1){
203
 
          if(errno == ENOENT){
204
 
            free(exe_link);
205
 
            continue;
206
 
          }
207
195
          perror("lstat");
208
196
          free(exe_link);
209
197
          free(prompt);
219
207
        
220
208
        sret = readlink(exe_link, exe_target, sizeof(exe_target));
221
209
        free(exe_link);
 
210
        if(sret == -1){
 
211
          continue;
 
212
        }
222
213
      }
223
214
      if((sret == ((ssize_t)sizeof(exe_target)-1))
224
215
         and (memcmp(usplash_name, exe_target,
251
242
          size_t cmdline_allocated = 0;
252
243
          char *tmp;
253
244
          const size_t blocksize = 1024;
254
 
          do {
 
245
          do{
255
246
            if(cmdline_len + blocksize > cmdline_allocated){
256
247
              tmp = realloc(cmdline, cmdline_allocated + blocksize);
257
248
              if(tmp == NULL){
365
356
    
366
357
    /* Open FIFO */
367
358
    int fifo_fd;
368
 
    do {
 
359
    do{
369
360
      fifo_fd = open("/dev/.initramfs/usplash_outfifo", O_RDONLY);
370
361
      if(fifo_fd == -1){
371
362
        if(errno != EINTR){
377
368
          break;
378
369
        }
379
370
      }
380
 
    } while(fifo_fd == -1);
 
371
    }while(fifo_fd == -1);
381
372
    if(interrupted_by_signal or an_error_occured){
382
373
      break;                    /* Big */
383
374
    }
385
376
    /* Read from FIFO */
386
377
    size_t buf_allocated = 0;
387
378
    const size_t blocksize = 1024;
388
 
    do {
 
379
    do{
389
380
      if(buf_len + blocksize > buf_allocated){
390
381
        char *tmp = realloc(buf, buf_allocated + blocksize);
391
382
        if(tmp == NULL){
396
387
        buf = tmp;
397
388
        buf_allocated += blocksize;
398
389
      }
399
 
      do {
 
390
      do{
400
391
        sret = read(fifo_fd, buf + buf_len, buf_allocated - buf_len);
401
392
        if(sret == -1){
402
393
          if(errno != EINTR){
408
399
            break;
409
400
          }
410
401
        }
411
 
      } while(sret == -1);
 
402
      }while(sret == -1);
412
403
      if(interrupted_by_signal or an_error_occured){
413
404
        break;
414
405
      }
415
406
      
416
407
      buf_len += (size_t)sret;
417
 
    } while(sret != 0);
 
408
    }while(sret != 0);
418
409
    close(fifo_fd);
419
410
    if(interrupted_by_signal or an_error_occured){
420
411
      break;                    /* Big */
432
423
    /* Print password to stdout */
433
424
    size_t written = 0;
434
425
    while(written < buf_len){
435
 
      do {
 
426
      do{
436
427
        sret = write(STDOUT_FILENO, buf + written, buf_len - written);
437
428
        if(sret == -1){
438
429
          if(errno != EINTR){
444
435
            break;
445
436
          }
446
437
        }
447
 
      } while(sret == -1);
 
438
      }while(sret == -1);
448
439
      if(interrupted_by_signal or an_error_occured){
449
440
        break;
450
441
      }
493
484
    /* Child; will become new usplash process */
494
485
    
495
486
    /* Make the effective user ID (root) the only user ID instead of
496
 
       the real user ID (_mandos) */
 
487
       the real user ID (mandos) */
497
488
    ret = setuid(geteuid());
498
489
    if(ret == -1){
499
490
      perror("setuid");