/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
/*  -*- coding: utf-8 -*- */
 
2
/*
 
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
 
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * General Public License for more details.
 
19
 * 
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
 
22
 * 
 
23
 * Contact the authors at <mandos@recompile.se>.
 
24
 */
 
25
 
 
26
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY() */
 
27
#include <sys/types.h>          /* uid_t, gid_t, ssize_t */
 
28
#include <sys/stat.h>           /* mkfifo(), S_IRUSR, S_IWUSR */
 
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(),
 
39
                                   realloc(), EXIT_SUCCESS */
 
40
#include <fcntl.h>              /* open(), O_RDONLY */
 
41
#include <unistd.h>             /* read(), close(), write(),
 
42
                                   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
}
 
74
 
 
75
int main(__attribute__((unused))int argc,
 
76
         __attribute__((unused))char **argv){
 
77
  int ret = 0;
 
78
  ssize_t sret;
 
79
  
 
80
  uid = getuid();
 
81
  gid = getgid();
 
82
  
 
83
  /* Create FIFO */
 
84
  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
    }
 
104
  }
 
105
  
 
106
  /* Open FIFO */
 
107
  int fifo_fd = open(passfifo, O_RDONLY);
 
108
  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");
 
136
  }
 
137
  
 
138
  /* Read from FIFO */
 
139
  char *buf = NULL;
 
140
  size_t buf_len = 0;
 
141
  {
 
142
    size_t buf_allocated = 0;
 
143
    const size_t blocksize = 1024;
 
144
    do {
 
145
      if(buf_len + blocksize > buf_allocated){
 
146
        char *tmp = realloc(buf, buf_allocated + blocksize);
 
147
        if(tmp == NULL){
 
148
          error_plus(0, errno, "realloc");
 
149
          free(buf);
 
150
          return EX_OSERR;
 
151
        }
 
152
        buf = tmp;
 
153
        buf_allocated += blocksize;
 
154
      }
 
155
      sret = read(fifo_fd, buf + buf_len, buf_allocated - buf_len);
 
156
      if(sret == -1){
 
157
        int e = errno;
 
158
        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
        }
 
172
      }
 
173
      buf_len += (size_t)sret;
 
174
    } while(sret != 0);
 
175
  }
 
176
  
 
177
  /* Close FIFO */
 
178
  close(fifo_fd);
 
179
  
 
180
  /* Print password to stdout */
 
181
  size_t written = 0;
 
182
  while(written < buf_len){
 
183
    sret = write(STDOUT_FILENO, buf + written, buf_len - written);
 
184
    if(sret == -1){
 
185
      int e = errno;
 
186
      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
      }
 
200
    }
 
201
    written += (size_t)sret;
 
202
  }
 
203
  free(buf);
 
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
  }
 
217
  return EXIT_SUCCESS;
 
218
}