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

  • Committer: Teddy Hogeborn
  • Date: 2011-12-31 20:07:11 UTC
  • mfrom: (535.1.9 wireless-network-hook)
  • Revision ID: teddy@recompile.se-20111231200711-6dli3r8drftem57r
Merge new wireless network hook.  Fix bridge network hook to use
hardware addresses instead of interface names.  Implement and document
new "CONNECT" environment variable for network hooks.

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-2011 Teddy Hogeborn
 
6
 * Copyright © 2008-2011 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
19
19
 * along with this program.  If not, see
20
20
 * <http://www.gnu.org/licenses/>.
21
21
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
22
 * Contact the authors at <mandos@recompile.se>.
23
23
 */
24
24
 
25
25
#define _GNU_SOURCE             /* getline(), asprintf() */
41
41
                                   getenv(), free() */
42
42
#include <dirent.h>             /* scandir(), alphasort() */
43
43
#include <stdio.h>              /* fprintf(), stderr, getline(),
44
 
                                   stdin, feof(), fputc()
45
 
                                */
 
44
                                   stdin, feof(), fputc(), vfprintf(),
 
45
                                   vasprintf() */
46
46
#include <errno.h>              /* errno, EBADF, ENOTTY, EINVAL,
47
47
                                   EFAULT, EFBIG, EIO, ENOSPC, EINTR
48
48
                                */
51
51
#include <stdbool.h>            /* bool, false, true */
52
52
#include <inttypes.h>           /* strtoumax() */
53
53
#include <sys/stat.h>           /* struct stat, lstat(), open() */
54
 
#include <string.h>             /* strlen, rindex, memcmp */
 
54
#include <string.h>             /* strlen, rindex, memcmp, strerror()
 
55
                                 */
55
56
#include <argp.h>               /* struct argp_option, struct
56
57
                                   argp_state, struct argp,
57
58
                                   argp_parse(), error_t,
60
61
#include <sysexits.h>           /* EX_SOFTWARE, EX_OSERR,
61
62
                                   EX_UNAVAILABLE, EX_IOERR, EX_OK */
62
63
#include <fcntl.h>              /* open() */
 
64
#include <stdarg.h>             /* va_list, va_start(), ... */
63
65
 
64
66
volatile sig_atomic_t quit_now = 0;
65
67
int signal_received;
66
68
bool debug = false;
67
69
const char *argp_program_version = "password-prompt " VERSION;
68
 
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
 
70
const char *argp_program_bug_address = "<mandos@recompile.se>";
69
71
 
70
72
/* Needed for conflict resolution */
71
73
const char plymouth_name[] = "plymouthd";
72
74
 
 
75
__attribute__((format (gnu_printf, 2, 3), nonnull(1)))
 
76
int fprintf_plus(FILE *stream, const char *format, ...){
 
77
  va_list ap;
 
78
  va_start (ap, format);
 
79
  
 
80
  TEMP_FAILURE_RETRY(fprintf(stream, "Mandos plugin %s: ",
 
81
                             program_invocation_short_name));
 
82
  return TEMP_FAILURE_RETRY(vfprintf(stream, format, ap));
 
83
}
 
84
 
 
85
/* Function to use when printing errors */
 
86
__attribute__((format (gnu_printf, 3, 4)))
 
87
void error_plus(int status, int errnum, const char *formatstring,
 
88
                ...){
 
89
  va_list ap;
 
90
  char *text;
 
91
  int ret;
 
92
  
 
93
  va_start(ap, formatstring);
 
94
  ret = vasprintf(&text, formatstring, ap);
 
95
  if (ret == -1){
 
96
    fprintf(stderr, "Mandos plugin %s: ",
 
97
            program_invocation_short_name);
 
98
    vfprintf(stderr, formatstring, ap);
 
99
    fprintf(stderr, ": %s\n", strerror(errnum));
 
100
    error(status, errno, "vasprintf while printing error");
 
101
    return;
 
102
  }
 
103
  fprintf(stderr, "Mandos plugin ");
 
104
  error(status, errnum, "%s", text);
 
105
  free(text);
 
106
}
 
107
 
73
108
static void termination_handler(int signum){
74
109
  if(quit_now){
75
110
    return;
84
119
     from the terminal.  Password-prompt will exit if it detects
85
120
     plymouth since plymouth performs the same functionality.
86
121
   */
 
122
  __attribute__((nonnull))
87
123
  int is_plymouth(const struct dirent *proc_entry){
88
124
    int ret;
89
125
    int cl_fd;
90
126
    {
91
 
      uintmax_t maxvalue;
 
127
      uintmax_t proc_id;
92
128
      char *tmp;
93
129
      errno = 0;
94
 
      maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
 
130
      proc_id = strtoumax(proc_entry->d_name, &tmp, 10);
95
131
      
96
132
      if(errno != 0 or *tmp != '\0'
97
 
         or maxvalue != (uintmax_t)((pid_t)maxvalue)){
 
133
         or proc_id != (uintmax_t)((pid_t)proc_id)){
98
134
        return 0;
99
135
      }
100
136
    }
103
139
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
104
140
                   proc_entry->d_name);
105
141
    if(ret == -1){
106
 
      error(0, errno, "asprintf");
 
142
      error_plus(0, errno, "asprintf");
107
143
      return 0;
108
144
    }
109
145
    
111
147
    cl_fd = open(cmdline_filename, O_RDONLY);
112
148
    free(cmdline_filename);
113
149
    if(cl_fd == -1){
114
 
      error(0, errno, "open");
 
150
      if(errno != ENOENT){
 
151
        error_plus(0, errno, "open");
 
152
      }
115
153
      return 0;
116
154
    }
117
155
    
127
165
        if(cmdline_len + blocksize + 1 > cmdline_allocated){
128
166
          tmp = realloc(cmdline, cmdline_allocated + blocksize + 1);
129
167
          if(tmp == NULL){
130
 
            error(0, errno, "realloc");
 
168
            error_plus(0, errno, "realloc");
131
169
            free(cmdline);
132
170
            close(cl_fd);
133
171
            return 0;
140
178
        sret = read(cl_fd, cmdline + cmdline_len,
141
179
                    cmdline_allocated - cmdline_len);
142
180
        if(sret == -1){
143
 
          error(0, errno, "read");
 
181
          error_plus(0, errno, "read");
144
182
          free(cmdline);
145
183
          close(cl_fd);
146
184
          return 0;
149
187
      } while(sret != 0);
150
188
      ret = close(cl_fd);
151
189
      if(ret == -1){
152
 
        error(0, errno, "close");
 
190
        error_plus(0, errno, "close");
153
191
        free(cmdline);
154
192
        return 0;
155
193
      }
181
219
    return 1;
182
220
  }
183
221
  
184
 
  struct dirent **direntries;
 
222
  struct dirent **direntries = NULL;
185
223
  int ret;
186
224
  ret = scandir("/proc", &direntries, is_plymouth, alphasort);
187
225
  if (ret == -1){
188
 
    error(1, errno, "scandir");
 
226
    error_plus(1, errno, "scandir");
189
227
  }
 
228
  free(direntries);
190
229
  return ret > 0;
191
230
}
192
231
 
221
260
      { .name = NULL }
222
261
    };
223
262
    
 
263
    __attribute__((nonnull(3)))
224
264
    error_t parse_opt (int key, char *arg, struct argp_state *state){
225
265
      errno = 0;
226
266
      switch (key){
262
302
    case ENOMEM:
263
303
    default:
264
304
      errno = ret;
265
 
      error(0, errno, "argp_parse");
 
305
      error_plus(0, errno, "argp_parse");
266
306
      return EX_OSERR;
267
307
    case EINVAL:
268
308
      return EX_USAGE;
286
326
  
287
327
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
288
328
    int e = errno;
289
 
    error(0, errno, "tcgetattr");
 
329
    error_plus(0, errno, "tcgetattr");
290
330
    switch(e){
291
331
    case EBADF:
292
332
    case ENOTTY:
299
339
  sigemptyset(&new_action.sa_mask);
300
340
  ret = sigaddset(&new_action.sa_mask, SIGINT);
301
341
  if(ret == -1){
302
 
    error(0, errno, "sigaddset");
 
342
    error_plus(0, errno, "sigaddset");
303
343
    return EX_OSERR;
304
344
  }
305
345
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
306
346
  if(ret == -1){
307
 
    error(0, errno, "sigaddset");
 
347
    error_plus(0, errno, "sigaddset");
308
348
    return EX_OSERR;
309
349
  }
310
350
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
311
351
  if(ret == -1){
312
 
    error(0, errno, "sigaddset");
 
352
    error_plus(0, errno, "sigaddset");
313
353
    return EX_OSERR;
314
354
  }
315
355
  /* Need to check if the handler is SIG_IGN before handling:
318
358
  */
319
359
  ret = sigaction(SIGINT, NULL, &old_action);
320
360
  if(ret == -1){
321
 
    error(0, errno, "sigaction");
 
361
    error_plus(0, errno, "sigaction");
322
362
    return EX_OSERR;
323
363
  }
324
364
  if(old_action.sa_handler != SIG_IGN){
325
365
    ret = sigaction(SIGINT, &new_action, NULL);
326
366
    if(ret == -1){
327
 
      error(0, errno, "sigaction");
 
367
      error_plus(0, errno, "sigaction");
328
368
      return EX_OSERR;
329
369
    }
330
370
  }
331
371
  ret = sigaction(SIGHUP, NULL, &old_action);
332
372
  if(ret == -1){
333
 
    error(0, errno, "sigaction");
 
373
    error_plus(0, errno, "sigaction");
334
374
    return EX_OSERR;
335
375
  }
336
376
  if(old_action.sa_handler != SIG_IGN){
337
377
    ret = sigaction(SIGHUP, &new_action, NULL);
338
378
    if(ret == -1){
339
 
      error(0, errno, "sigaction");
 
379
      error_plus(0, errno, "sigaction");
340
380
      return EX_OSERR;
341
381
    }
342
382
  }
343
383
  ret = sigaction(SIGTERM, NULL, &old_action);
344
384
  if(ret == -1){
345
 
    error(0, errno, "sigaction");
 
385
    error_plus(0, errno, "sigaction");
346
386
    return EX_OSERR;
347
387
  }
348
388
  if(old_action.sa_handler != SIG_IGN){
349
389
    ret = sigaction(SIGTERM, &new_action, NULL);
350
390
    if(ret == -1){
351
 
      error(0, errno, "sigaction");
 
391
      error_plus(0, errno, "sigaction");
352
392
      return EX_OSERR;
353
393
    }
354
394
  }
362
402
  t_new.c_lflag &= ~(tcflag_t)ECHO;
363
403
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
364
404
    int e = errno;
365
 
    error(0, errno, "tcsetattr-echo");
 
405
    error_plus(0, errno, "tcsetattr-echo");
366
406
    switch(e){
367
407
    case EBADF:
368
408
    case ENOTTY:
432
472
        sret = write(STDOUT_FILENO, buffer + written, n - written);
433
473
        if(sret < 0){
434
474
          int e = errno;
435
 
          error(0, errno, "write");
 
475
          error_plus(0, errno, "write");
436
476
          switch(e){
437
477
          case EBADF:
438
478
          case EFAULT:
454
494
      sret = close(STDOUT_FILENO);
455
495
      if(sret == -1){
456
496
        int e = errno;
457
 
        error(0, errno, "close");
 
497
        error_plus(0, errno, "close");
458
498
        switch(e){
459
499
        case EBADF:
460
500
          status = EX_OSFILE;
470
510
    if(sret < 0){
471
511
      int e = errno;
472
512
      if(errno != EINTR and not feof(stdin)){
473
 
        error(0, errno, "getline");
 
513
        error_plus(0, errno, "getline");
474
514
        switch(e){
475
515
        case EBADF:
476
516
          status = EX_UNAVAILABLE;
 
517
          break;
477
518
        case EIO:
478
519
        case EINVAL:
479
520
        default:
499
540
    fprintf(stderr, "Restoring terminal attributes\n");
500
541
  }
501
542
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
502
 
    error(0, errno, "tcsetattr+echo");
 
543
    error_plus(0, errno, "tcsetattr+echo");
503
544
  }
504
545
  
505
546
  if(quit_now){
507
548
    old_action.sa_handler = SIG_DFL;
508
549
    ret = sigaction(signal_received, &old_action, NULL);
509
550
    if(ret == -1){
510
 
      error(0, errno, "sigaction");
 
551
      error_plus(0, errno, "sigaction");
511
552
    }
512
553
    raise(signal_received);
513
554
  }