/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/askpass-fifo.c

  • Committer: Teddy Hogeborn
  • Date: 2018-08-15 09:26:02 UTC
  • Revision ID: teddy@recompile.se-20180815092602-xoyb5s6gf8376i7u
mandos-client: Set system clock if necessary

* plugins.d/mandos-client.c (init_gpgme/import_key): If the system
  clock is not set, or set to january 1970, set the system clock to
  the more plausible value that is the mtime of the key file.  This is
  required by GnuPG to be able to import the keys.  (We can't pass the
  --ignore-time-conflict or the --ignore-valid-from options though
  GPGME.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*  -*- coding: utf-8 -*- */
2
2
/*
3
 
 * Passprompt - Read a password from a FIFO and output it
4
 
 * 
5
 
 * Copyright © 2008,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 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
 
3
 * Askpass-FIFO - Read a password from a FIFO and output it
 
4
 * 
 
5
 * Copyright © 2008-2018 Teddy Hogeborn
 
6
 * Copyright © 2008-2018 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 <https://www.fukt.bsnet.se/~belorn/> and
23
 
 * <https://www.fukt.bsnet.se/~teddy/>.
 
23
 * Contact the authors at <mandos@recompile.se>.
24
24
 */
25
25
 
26
26
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY() */
27
 
#include <sys/types.h>          /* ssize_t */
 
27
#include <sys/types.h>          /* uid_t, gid_t, ssize_t */
28
28
#include <sys/stat.h>           /* mkfifo(), S_IRUSR, S_IWUSR */
29
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(), 
 
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(),
33
39
                                   realloc(), EXIT_SUCCESS */
34
40
#include <fcntl.h>              /* open(), O_RDONLY */
35
41
#include <unistd.h>             /* read(), close(), write(),
36
42
                                   STDOUT_FILENO */
37
 
 
 
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
}
38
74
 
39
75
int main(__attribute__((unused))int argc,
40
76
         __attribute__((unused))char **argv){
41
77
  int ret = 0;
42
78
  ssize_t sret;
43
79
  
 
80
  uid = getuid();
 
81
  gid = getgid();
 
82
  
44
83
  /* Create FIFO */
45
84
  const char passfifo[] = "/lib/cryptsetup/passfifo";
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;
 
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
    }
50
104
  }
51
105
  
52
106
  /* Open FIFO */
53
 
  int fifo_fd = TEMP_FAILURE_RETRY(open(passfifo, O_RDONLY));
 
107
  int fifo_fd = open(passfifo, O_RDONLY);
54
108
  if(fifo_fd == -1){
55
 
    perror("open");
56
 
    return EXIT_FAILURE;
 
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");
57
136
  }
58
137
  
59
138
  /* Read from FIFO */
62
141
  {
63
142
    size_t buf_allocated = 0;
64
143
    const size_t blocksize = 1024;
65
 
    do{
 
144
    do {
66
145
      if(buf_len + blocksize > buf_allocated){
67
146
        char *tmp = realloc(buf, buf_allocated + blocksize);
68
147
        if(tmp == NULL){
69
 
          perror("realloc");
 
148
          error_plus(0, errno, "realloc");
70
149
          free(buf);
71
 
          return EXIT_FAILURE;
 
150
          return EX_OSERR;
72
151
        }
73
152
        buf = tmp;
74
153
        buf_allocated += blocksize;
75
154
      }
76
 
      sret = TEMP_FAILURE_RETRY(read(fifo_fd, buf + buf_len,
77
 
                                     buf_allocated - buf_len));
 
155
      sret = read(fifo_fd, buf + buf_len, buf_allocated - buf_len);
78
156
      if(sret == -1){
79
 
        perror("read");
 
157
        int e = errno;
80
158
        free(buf);
81
 
        return EXIT_FAILURE;
 
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
        }
82
172
      }
83
173
      buf_len += (size_t)sret;
84
 
    }while(sret != 0);
 
174
    } while(sret != 0);
85
175
  }
86
176
  
87
177
  /* Close FIFO */
88
 
  TEMP_FAILURE_RETRY(close(fifo_fd));
 
178
  close(fifo_fd);
89
179
  
90
180
  /* Print password to stdout */
91
181
  size_t written = 0;
92
182
  while(written < buf_len){
93
 
    sret = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, buf + written,
94
 
                                    buf_len - written));
 
183
    sret = write(STDOUT_FILENO, buf + written, buf_len - written);
95
184
    if(sret == -1){
96
 
      perror("write");
 
185
      int e = errno;
97
186
      free(buf);
98
 
      return EXIT_FAILURE;
 
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
      }
99
200
    }
100
201
    written += (size_t)sret;
101
202
  }
102
203
  free(buf);
103
204
  
 
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
  }
104
217
  return EXIT_SUCCESS;
105
218
}