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