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