/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/password-prompt.c

Convert some programs to use the exit codes from <sysexits.h>.  Change
all programs using the "argp" parsing functions to use them correctly;
checking return value, using argp_error() to report parse errors etc.

* plugin-runner.c: Use <sysexits.h> exit codes.  Always use fallback,
                   even on option errors, except for "--help", etc.
  (getplugin): Make sure "errno" is set correctly on return.
  (main): Declare our own "--help", "--usage", and "--version"
          options which do not cause the fallback to be invoked.
          In all other options, use fallback on any error.
  (parse_opt, parse_opt_config_file): Reset errno at start and return
                                      errno.  No need to check "arg"
                                      for NULL.  New "--help",
                                      "--usage", and "--version"
                                      options.
  (parse_opt): Accept empty string as global option.  Do not print
               errors which will be detected and reported later.  Do
               "argp_error()" on parse error or empty plugin names.
* plugins.d/mandos-client.c: Use <sysexits.h> exit codes.  Do not
                             return successful exit code on "--help",
                             etc. since this would give the wrong
                             message to "plugin-runner".
  (main): Declare our own "--help", "--usage", and "--version"
          options which do not return a successful exit code.
  (parse_opt): Reset errno at start and return errno.  Do
               "argp_error()" on parse errors.  New "--help",
               "--usage", and "--version" options.
* plugins.d/password-prompt.c: Use exit codes from <sysexits.h>.  Do
                               not return successful exit code on
                               "--help", etc. since this would give
                               the wrong message to "plugin-runner".
  (main): Declare our own "--help", "--usage", and "--version" options
          which do not return a successful exit code.  Do
          close(STDOUT_FILENO) after writing to check its return code.
  (parse_opt): Reset errno at start and return errno.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Password-prompt - Read a password from the terminal and print it
4
4
 * 
5
 
 * Copyright © 2008-2010 Teddy Hogeborn
6
 
 * Copyright © 2008-2010 Björn Påhlsson
 
5
 * Copyright © 2008,2009 Teddy Hogeborn
 
6
 * Copyright © 2008,2009 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
39
39
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
40
40
                                   getenv() */
41
41
#include <stdio.h>              /* fprintf(), stderr, getline(),
42
 
                                   stdin, feof(), fputc()
 
42
                                   stdin, feof(), perror(), fputc()
43
43
                                */
44
44
#include <errno.h>              /* errno, EBADF, ENOTTY, EINVAL,
45
45
                                   EFAULT, EFBIG, EIO, ENOSPC, EINTR
46
46
                                */
47
 
#include <error.h>              /* error() */
48
47
#include <iso646.h>             /* or, not */
49
48
#include <stdbool.h>            /* bool, false, true */
50
 
#include <string.h>             /* strlen, rindex */
 
49
#include <string.h>             /* strlen, rindex, strncmp, strcmp */
51
50
#include <argp.h>               /* struct argp_option, struct
52
51
                                   argp_state, struct argp,
53
52
                                   argp_parse(), error_t,
71
70
}
72
71
 
73
72
int main(int argc, char **argv){
74
 
  ssize_t sret;
75
 
  int ret;
 
73
  ssize_t ret;
76
74
  size_t n;
77
75
  struct termios t_new, t_old;
78
76
  char *buffer = NULL;
141
139
    case ENOMEM:
142
140
    default:
143
141
      errno = ret;
144
 
      error(0, errno, "argp_parse");
 
142
      perror("argp_parse");
145
143
      return EX_OSERR;
146
144
    case EINVAL:
147
145
      return EX_USAGE;
157
155
  
158
156
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
159
157
    int e = errno;
160
 
    error(0, errno, "tcgetattr");
 
158
    perror("tcgetattr");
161
159
    switch(e){
162
160
    case EBADF:
163
161
    case ENOTTY:
170
168
  sigemptyset(&new_action.sa_mask);
171
169
  ret = sigaddset(&new_action.sa_mask, SIGINT);
172
170
  if(ret == -1){
173
 
    error(0, errno, "sigaddset");
 
171
    perror("sigaddset");
174
172
    return EX_OSERR;
175
173
  }
176
174
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
177
175
  if(ret == -1){
178
 
    error(0, errno, "sigaddset");
 
176
    perror("sigaddset");
179
177
    return EX_OSERR;
180
178
  }
181
179
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
182
180
  if(ret == -1){
183
 
    error(0, errno, "sigaddset");
 
181
    perror("sigaddset");
184
182
    return EX_OSERR;
185
183
  }
186
184
  /* Need to check if the handler is SIG_IGN before handling:
189
187
  */
190
188
  ret = sigaction(SIGINT, NULL, &old_action);
191
189
  if(ret == -1){
192
 
    error(0, errno, "sigaction");
 
190
    perror("sigaction");
193
191
    return EX_OSERR;
194
192
  }
195
193
  if(old_action.sa_handler != SIG_IGN){
196
194
    ret = sigaction(SIGINT, &new_action, NULL);
197
195
    if(ret == -1){
198
 
      error(0, errno, "sigaction");
 
196
      perror("sigaction");
199
197
      return EX_OSERR;
200
198
    }
201
199
  }
202
200
  ret = sigaction(SIGHUP, NULL, &old_action);
203
201
  if(ret == -1){
204
 
    error(0, errno, "sigaction");
 
202
    perror("sigaction");
205
203
    return EX_OSERR;
206
204
  }
207
205
  if(old_action.sa_handler != SIG_IGN){
208
206
    ret = sigaction(SIGHUP, &new_action, NULL);
209
207
    if(ret == -1){
210
 
      error(0, errno, "sigaction");
 
208
      perror("sigaction");
211
209
      return EX_OSERR;
212
210
    }
213
211
  }
214
212
  ret = sigaction(SIGTERM, NULL, &old_action);
215
213
  if(ret == -1){
216
 
    error(0, errno, "sigaction");
 
214
    perror("sigaction");
217
215
    return EX_OSERR;
218
216
  }
219
217
  if(old_action.sa_handler != SIG_IGN){
220
218
    ret = sigaction(SIGTERM, &new_action, NULL);
221
219
    if(ret == -1){
222
 
      error(0, errno, "sigaction");
 
220
      perror("sigaction");
223
221
      return EX_OSERR;
224
222
    }
225
223
  }
233
231
  t_new.c_lflag &= ~(tcflag_t)ECHO;
234
232
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
235
233
    int e = errno;
236
 
    error(0, errno, "tcsetattr-echo");
 
234
    perror("tcsetattr-echo");
237
235
    switch(e){
238
236
    case EBADF:
239
237
    case ENOTTY:
260
258
      fprintf(stderr, "%s ", prefix);
261
259
    }
262
260
    {
263
 
      const char *cryptsource = getenv("CRYPTTAB_SOURCE");
264
 
      const char *crypttarget = getenv("CRYPTTAB_NAME");
265
 
      /* Before cryptsetup 1.1.0~rc2 */
266
 
      if(cryptsource == NULL){
267
 
        cryptsource = getenv("cryptsource");
268
 
      }
269
 
      if(crypttarget == NULL){
270
 
        crypttarget = getenv("crypttarget");
271
 
      }
272
 
      const char *const prompt1 = "Unlocking the disk";
273
 
      const char *const prompt2 = "Enter passphrase";
 
261
      const char *cryptsource = getenv("cryptsource");
 
262
      const char *crypttarget = getenv("crypttarget");
 
263
      const char *const prompt
 
264
        = "Enter passphrase to unlock the disk";
274
265
      if(cryptsource == NULL){
275
266
        if(crypttarget == NULL){
276
 
          fprintf(stderr, "%s to unlock the disk: ", prompt2);
 
267
          fprintf(stderr, "%s: ", prompt);
277
268
        } else {
278
 
          fprintf(stderr, "%s (%s)\n%s: ", prompt1, crypttarget,
279
 
                  prompt2);
 
269
          fprintf(stderr, "%s (%s): ", prompt, crypttarget);
280
270
        }
281
271
      } else {
282
272
        if(crypttarget == NULL){
283
 
          fprintf(stderr, "%s %s\n%s: ", prompt1, cryptsource,
284
 
                  prompt2);
 
273
          fprintf(stderr, "%s %s: ", prompt, cryptsource);
285
274
        } else {
286
 
          fprintf(stderr, "%s %s (%s)\n%s: ", prompt1, cryptsource,
287
 
                  crypttarget, prompt2);
 
275
          fprintf(stderr, "%s %s (%s): ", prompt, cryptsource,
 
276
                  crypttarget);
288
277
        }
289
278
      }
290
279
    }
291
 
    sret = getline(&buffer, &n, stdin);
292
 
    if(sret > 0){
 
280
    ret = getline(&buffer, &n, stdin);
 
281
    if(ret > 0){
293
282
      status = EXIT_SUCCESS;
294
283
      /* Make n = data size instead of allocated buffer size */
295
 
      n = (size_t)sret;
 
284
      n = (size_t)ret;
296
285
      /* Strip final newline */
297
286
      if(n > 0 and buffer[n-1] == '\n'){
298
287
        buffer[n-1] = '\0';     /* not strictly necessary */
300
289
      }
301
290
      size_t written = 0;
302
291
      while(written < n){
303
 
        sret = write(STDOUT_FILENO, buffer + written, n - written);
304
 
        if(sret < 0){
 
292
        ret = write(STDOUT_FILENO, buffer + written, n - written);
 
293
        if(ret < 0){
305
294
          int e = errno;
306
 
          error(0, errno, "write");
 
295
          perror("write");
307
296
          switch(e){
308
297
          case EBADF:
309
298
          case EFAULT:
320
309
          }
321
310
          break;
322
311
        }
323
 
        written += (size_t)sret;
 
312
        written += (size_t)ret;
324
313
      }
325
 
      sret = close(STDOUT_FILENO);
326
 
      if(sret == -1){
 
314
      ret = close(STDOUT_FILENO);
 
315
      if(ret == -1){
327
316
        int e = errno;
328
 
        error(0, errno, "close");
 
317
        perror("close");
329
318
        switch(e){
330
319
        case EBADF:
331
320
          status = EX_OSFILE;
338
327
      }
339
328
      break;
340
329
    }
341
 
    if(sret < 0){
 
330
    if(ret < 0){
342
331
      int e = errno;
343
332
      if(errno != EINTR and not feof(stdin)){
344
 
        error(0, errno, "getline");
 
333
        perror("getline");
345
334
        switch(e){
346
335
        case EBADF:
347
336
          status = EX_UNAVAILABLE;
354
343
        break;
355
344
      }
356
345
    }
357
 
    /* if(sret == 0), then the only sensible thing to do is to retry to
 
346
    /* if(ret == 0), then the only sensible thing to do is to retry to
358
347
       read from stdin */
359
348
    fputc('\n', stderr);
360
349
    if(debug and not quit_now){
370
359
    fprintf(stderr, "Restoring terminal attributes\n");
371
360
  }
372
361
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
373
 
    error(0, errno, "tcsetattr+echo");
 
362
    perror("tcsetattr+echo");
374
363
  }
375
364
  
376
365
  if(quit_now){
378
367
    old_action.sa_handler = SIG_DFL;
379
368
    ret = sigaction(signal_received, &old_action, NULL);
380
369
    if(ret == -1){
381
 
      error(0, errno, "sigaction");
 
370
      perror("sigaction");
382
371
    }
383
372
    raise(signal_received);
384
373
  }