/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/askpass-fifo.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
 
 * Askpass-FIFO - Read a password from a FIFO and output it
 
3
 * Passprompt - Read a password from a FIFO and output it
4
4
 * 
5
 
 * Copyright © 2008-2014 Teddy Hogeborn
6
 
 * Copyright © 2008-2014 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@recompile.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             /* TEMP_FAILURE_RETRY() */
26
 
#include <sys/types.h>          /* uid_t, gid_t, ssize_t */
 
27
#include <sys/types.h>          /* ssize_t */
27
28
#include <sys/stat.h>           /* mkfifo(), S_IRUSR, S_IWUSR */
28
29
#include <iso646.h>             /* and */
29
 
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
30
 
                                   ENAMETOOLONG, ENOSPC, EROFS,
31
 
                                   ENOENT, EEXIST, EFAULT, EMFILE,
32
 
                                   ENFILE, ENOMEM, EBADF, EINVAL, EIO,
33
 
                                   EISDIR, EFBIG */
34
 
#include <error.h>              /* error() */
35
 
#include <stdio.h>              /* fprintf(), vfprintf(),
36
 
                                   vasprintf() */
37
 
#include <stdlib.h>             /* EXIT_FAILURE, NULL, size_t, free(),
 
30
#include <errno.h>              /* errno, EEXIST */
 
31
#include <stdio.h>              /* perror() */
 
32
#include <stdlib.h>             /* EXIT_FAILURE, NULL, size_t, free(), 
38
33
                                   realloc(), EXIT_SUCCESS */
39
34
#include <fcntl.h>              /* open(), O_RDONLY */
40
35
#include <unistd.h>             /* read(), close(), write(),
41
36
                                   STDOUT_FILENO */
42
 
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
43
 
                                   EX_UNAVAILABLE, EX_IOERR */
44
 
#include <string.h>             /* strerror() */
45
 
#include <stdarg.h>             /* va_list, va_start(), ... */
46
 
 
47
 
uid_t uid = 65534;
48
 
gid_t gid = 65534;
49
 
 
50
 
/* Function to use when printing errors */
51
 
__attribute__((format (gnu_printf, 3, 4)))
52
 
void error_plus(int status, int errnum, const char *formatstring,
53
 
                ...){
54
 
  va_list ap;
55
 
  char *text;
56
 
  int ret;
57
 
  
58
 
  va_start(ap, formatstring);
59
 
  ret = vasprintf(&text, formatstring, ap);
60
 
  if(ret == -1){
61
 
    fprintf(stderr, "Mandos plugin %s: ",
62
 
            program_invocation_short_name);
63
 
    vfprintf(stderr, formatstring, ap);
64
 
    fprintf(stderr, ": ");
65
 
    fprintf(stderr, "%s\n", strerror(errnum));
66
 
    error(status, errno, "vasprintf while printing error");
67
 
    return;
68
 
  }
69
 
  fprintf(stderr, "Mandos plugin ");
70
 
  error(status, errnum, "%s", text);
71
 
  free(text);
72
 
}
 
37
 
73
38
 
74
39
int main(__attribute__((unused))int argc,
75
40
         __attribute__((unused))char **argv){
76
41
  int ret = 0;
77
42
  ssize_t sret;
78
43
  
79
 
  uid = getuid();
80
 
  gid = getgid();
81
 
  
82
44
  /* Create FIFO */
83
45
  const char passfifo[] = "/lib/cryptsetup/passfifo";
84
 
  ret = mkfifo(passfifo, S_IRUSR | S_IWUSR);
85
 
  if(ret == -1){
86
 
    int e = errno;
87
 
    switch(e){
88
 
    case EACCES:
89
 
    case ENOTDIR:
90
 
    case ELOOP:
91
 
      error_plus(EX_OSFILE, errno, "mkfifo");
92
 
    case ENAMETOOLONG:
93
 
    case ENOSPC:
94
 
    case EROFS:
95
 
    default:
96
 
      error_plus(EX_OSERR, errno, "mkfifo");
97
 
    case ENOENT:
98
 
      /* no "/lib/cryptsetup"? */
99
 
      error_plus(EX_UNAVAILABLE, errno, "mkfifo");
100
 
    case EEXIST:
101
 
      break;                    /* not an error */
102
 
    }
 
46
  ret = TEMP_FAILURE_RETRY(mkfifo(passfifo, S_IRUSR | S_IWUSR));
 
47
  if(ret == -1 and errno != EEXIST){
 
48
    perror("mkfifo");
 
49
    return EXIT_FAILURE;
103
50
  }
104
51
  
105
52
  /* Open FIFO */
106
 
  int fifo_fd = open(passfifo, O_RDONLY);
 
53
  int fifo_fd = TEMP_FAILURE_RETRY(open(passfifo, O_RDONLY));
107
54
  if(fifo_fd == -1){
108
 
    int e = errno;
109
 
    error_plus(0, errno, "open");
110
 
    switch(e){
111
 
    case EACCES:
112
 
    case ENOENT:
113
 
    case EFAULT:
114
 
      return EX_UNAVAILABLE;
115
 
    case ENAMETOOLONG:
116
 
    case EMFILE:
117
 
    case ENFILE:
118
 
    case ENOMEM:
119
 
    default:
120
 
      return EX_OSERR;
121
 
    case ENOTDIR:
122
 
    case ELOOP:
123
 
      return EX_OSFILE;
124
 
    }
125
 
  }
126
 
  
127
 
  /* Lower group privileges  */
128
 
  if(setgid(gid) == -1){
129
 
    error_plus(0, errno, "setgid");
130
 
  }
131
 
  
132
 
  /* Lower user privileges */
133
 
  if(setuid(uid) == -1){
134
 
    error_plus(0, errno, "setuid");
 
55
    perror("open");
 
56
    return EXIT_FAILURE;
135
57
  }
136
58
  
137
59
  /* Read from FIFO */
140
62
  {
141
63
    size_t buf_allocated = 0;
142
64
    const size_t blocksize = 1024;
143
 
    do {
 
65
    do{
144
66
      if(buf_len + blocksize > buf_allocated){
145
67
        char *tmp = realloc(buf, buf_allocated + blocksize);
146
68
        if(tmp == NULL){
147
 
          error_plus(0, errno, "realloc");
 
69
          perror("realloc");
148
70
          free(buf);
149
 
          return EX_OSERR;
 
71
          return EXIT_FAILURE;
150
72
        }
151
73
        buf = tmp;
152
74
        buf_allocated += blocksize;
153
75
      }
154
 
      sret = read(fifo_fd, buf + buf_len, buf_allocated - buf_len);
 
76
      sret = TEMP_FAILURE_RETRY(read(fifo_fd, buf + buf_len,
 
77
                                     buf_allocated - buf_len));
155
78
      if(sret == -1){
156
 
        int e = errno;
 
79
        perror("read");
157
80
        free(buf);
158
 
        errno = e;
159
 
        error_plus(0, errno, "read");
160
 
        switch(e){
161
 
        case EBADF:
162
 
        case EFAULT:
163
 
        case EINVAL:
164
 
        default:
165
 
          return EX_OSERR;
166
 
        case EIO:
167
 
          return EX_IOERR;
168
 
        case EISDIR:
169
 
          return EX_UNAVAILABLE;
170
 
        }
 
81
        return EXIT_FAILURE;
171
82
      }
172
83
      buf_len += (size_t)sret;
173
 
    } while(sret != 0);
 
84
    }while(sret != 0);
174
85
  }
175
86
  
176
87
  /* Close FIFO */
177
 
  close(fifo_fd);
 
88
  TEMP_FAILURE_RETRY(close(fifo_fd));
178
89
  
179
90
  /* Print password to stdout */
180
91
  size_t written = 0;
181
92
  while(written < buf_len){
182
 
    sret = write(STDOUT_FILENO, buf + written, buf_len - written);
 
93
    sret = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, buf + written,
 
94
                                    buf_len - written));
183
95
    if(sret == -1){
184
 
      int e = errno;
 
96
      perror("write");
185
97
      free(buf);
186
 
      errno = e;
187
 
      error_plus(0, errno, "write");
188
 
      switch(e){
189
 
      case EBADF:
190
 
      case EFAULT:
191
 
      case EINVAL:
192
 
        return EX_OSFILE;
193
 
      case EFBIG:
194
 
      case EIO:
195
 
      case ENOSPC:
196
 
      default:
197
 
        return EX_IOERR;
198
 
      }
 
98
      return EXIT_FAILURE;
199
99
    }
200
100
    written += (size_t)sret;
201
101
  }
202
102
  free(buf);
203
103
  
204
 
  ret = close(STDOUT_FILENO);
205
 
  if(ret == -1){
206
 
    int e = errno;
207
 
    error_plus(0, errno, "close");
208
 
    switch(e){
209
 
    case EBADF:
210
 
      return EX_OSFILE;
211
 
    case EIO:
212
 
    default:
213
 
      return EX_IOERR;
214
 
    }
215
 
  }
216
104
  return EXIT_SUCCESS;
217
105
}