/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() */
67
67
int signal_received;
68
68
bool debug = false;
69
69
const char *argp_program_version = "password-prompt " VERSION;
70
 
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
 
70
const char *argp_program_bug_address = "<mandos@recompile.se>";
71
71
 
72
72
/* Needed for conflict resolution */
73
73
const char plymouth_name[] = "plymouthd";
74
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
 
75
85
/* Function to use when printing errors */
 
86
__attribute__((format (gnu_printf, 3, 4)))
76
87
void error_plus(int status, int errnum, const char *formatstring,
77
88
                ...){
78
89
  va_list ap;
85
96
    fprintf(stderr, "Mandos plugin %s: ",
86
97
            program_invocation_short_name);
87
98
    vfprintf(stderr, formatstring, ap);
88
 
    fprintf(stderr, ": ");
89
 
    fprintf(stderr, "%s\n", strerror(errnum));
 
99
    fprintf(stderr, ": %s\n", strerror(errnum));
90
100
    error(status, errno, "vasprintf while printing error");
91
101
    return;
92
102
  }
109
119
     from the terminal.  Password-prompt will exit if it detects
110
120
     plymouth since plymouth performs the same functionality.
111
121
   */
 
122
  __attribute__((nonnull))
112
123
  int is_plymouth(const struct dirent *proc_entry){
113
124
    int ret;
114
125
    int cl_fd;
115
126
    {
116
 
      uintmax_t maxvalue;
 
127
      uintmax_t proc_id;
117
128
      char *tmp;
118
129
      errno = 0;
119
 
      maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
 
130
      proc_id = strtoumax(proc_entry->d_name, &tmp, 10);
120
131
      
121
132
      if(errno != 0 or *tmp != '\0'
122
 
         or maxvalue != (uintmax_t)((pid_t)maxvalue)){
 
133
         or proc_id != (uintmax_t)((pid_t)proc_id)){
123
134
        return 0;
124
135
      }
125
136
    }
128
139
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
129
140
                   proc_entry->d_name);
130
141
    if(ret == -1){
131
 
      error(0, errno, "asprintf");
 
142
      error_plus(0, errno, "asprintf");
132
143
      return 0;
133
144
    }
134
145
    
137
148
    free(cmdline_filename);
138
149
    if(cl_fd == -1){
139
150
      if(errno != ENOENT){
140
 
        error(0, errno, "open");
 
151
        error_plus(0, errno, "open");
141
152
      }
142
153
      return 0;
143
154
    }
154
165
        if(cmdline_len + blocksize + 1 > cmdline_allocated){
155
166
          tmp = realloc(cmdline, cmdline_allocated + blocksize + 1);
156
167
          if(tmp == NULL){
157
 
            error(0, errno, "realloc");
 
168
            error_plus(0, errno, "realloc");
158
169
            free(cmdline);
159
170
            close(cl_fd);
160
171
            return 0;
167
178
        sret = read(cl_fd, cmdline + cmdline_len,
168
179
                    cmdline_allocated - cmdline_len);
169
180
        if(sret == -1){
170
 
          error(0, errno, "read");
 
181
          error_plus(0, errno, "read");
171
182
          free(cmdline);
172
183
          close(cl_fd);
173
184
          return 0;
176
187
      } while(sret != 0);
177
188
      ret = close(cl_fd);
178
189
      if(ret == -1){
179
 
        error(0, errno, "close");
 
190
        error_plus(0, errno, "close");
180
191
        free(cmdline);
181
192
        return 0;
182
193
      }
208
219
    return 1;
209
220
  }
210
221
  
211
 
  struct dirent **direntries;
 
222
  struct dirent **direntries = NULL;
212
223
  int ret;
213
224
  ret = scandir("/proc", &direntries, is_plymouth, alphasort);
214
225
  if (ret == -1){
215
 
    error(1, errno, "scandir");
 
226
    error_plus(1, errno, "scandir");
216
227
  }
 
228
  free(direntries);
217
229
  return ret > 0;
218
230
}
219
231
 
248
260
      { .name = NULL }
249
261
    };
250
262
    
 
263
    __attribute__((nonnull(3)))
251
264
    error_t parse_opt (int key, char *arg, struct argp_state *state){
252
265
      errno = 0;
253
266
      switch (key){
289
302
    case ENOMEM:
290
303
    default:
291
304
      errno = ret;
292
 
      error(0, errno, "argp_parse");
 
305
      error_plus(0, errno, "argp_parse");
293
306
      return EX_OSERR;
294
307
    case EINVAL:
295
308
      return EX_USAGE;
313
326
  
314
327
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
315
328
    int e = errno;
316
 
    error(0, errno, "tcgetattr");
 
329
    error_plus(0, errno, "tcgetattr");
317
330
    switch(e){
318
331
    case EBADF:
319
332
    case ENOTTY:
326
339
  sigemptyset(&new_action.sa_mask);
327
340
  ret = sigaddset(&new_action.sa_mask, SIGINT);
328
341
  if(ret == -1){
329
 
    error(0, errno, "sigaddset");
 
342
    error_plus(0, errno, "sigaddset");
330
343
    return EX_OSERR;
331
344
  }
332
345
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
333
346
  if(ret == -1){
334
 
    error(0, errno, "sigaddset");
 
347
    error_plus(0, errno, "sigaddset");
335
348
    return EX_OSERR;
336
349
  }
337
350
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
338
351
  if(ret == -1){
339
 
    error(0, errno, "sigaddset");
 
352
    error_plus(0, errno, "sigaddset");
340
353
    return EX_OSERR;
341
354
  }
342
355
  /* Need to check if the handler is SIG_IGN before handling:
345
358
  */
346
359
  ret = sigaction(SIGINT, NULL, &old_action);
347
360
  if(ret == -1){
348
 
    error(0, errno, "sigaction");
 
361
    error_plus(0, errno, "sigaction");
349
362
    return EX_OSERR;
350
363
  }
351
364
  if(old_action.sa_handler != SIG_IGN){
352
365
    ret = sigaction(SIGINT, &new_action, NULL);
353
366
    if(ret == -1){
354
 
      error(0, errno, "sigaction");
 
367
      error_plus(0, errno, "sigaction");
355
368
      return EX_OSERR;
356
369
    }
357
370
  }
358
371
  ret = sigaction(SIGHUP, NULL, &old_action);
359
372
  if(ret == -1){
360
 
    error(0, errno, "sigaction");
 
373
    error_plus(0, errno, "sigaction");
361
374
    return EX_OSERR;
362
375
  }
363
376
  if(old_action.sa_handler != SIG_IGN){
364
377
    ret = sigaction(SIGHUP, &new_action, NULL);
365
378
    if(ret == -1){
366
 
      error(0, errno, "sigaction");
 
379
      error_plus(0, errno, "sigaction");
367
380
      return EX_OSERR;
368
381
    }
369
382
  }
370
383
  ret = sigaction(SIGTERM, NULL, &old_action);
371
384
  if(ret == -1){
372
 
    error(0, errno, "sigaction");
 
385
    error_plus(0, errno, "sigaction");
373
386
    return EX_OSERR;
374
387
  }
375
388
  if(old_action.sa_handler != SIG_IGN){
376
389
    ret = sigaction(SIGTERM, &new_action, NULL);
377
390
    if(ret == -1){
378
 
      error(0, errno, "sigaction");
 
391
      error_plus(0, errno, "sigaction");
379
392
      return EX_OSERR;
380
393
    }
381
394
  }
389
402
  t_new.c_lflag &= ~(tcflag_t)ECHO;
390
403
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
391
404
    int e = errno;
392
 
    error(0, errno, "tcsetattr-echo");
 
405
    error_plus(0, errno, "tcsetattr-echo");
393
406
    switch(e){
394
407
    case EBADF:
395
408
    case ENOTTY:
459
472
        sret = write(STDOUT_FILENO, buffer + written, n - written);
460
473
        if(sret < 0){
461
474
          int e = errno;
462
 
          error(0, errno, "write");
 
475
          error_plus(0, errno, "write");
463
476
          switch(e){
464
477
          case EBADF:
465
478
          case EFAULT:
481
494
      sret = close(STDOUT_FILENO);
482
495
      if(sret == -1){
483
496
        int e = errno;
484
 
        error(0, errno, "close");
 
497
        error_plus(0, errno, "close");
485
498
        switch(e){
486
499
        case EBADF:
487
500
          status = EX_OSFILE;
497
510
    if(sret < 0){
498
511
      int e = errno;
499
512
      if(errno != EINTR and not feof(stdin)){
500
 
        error(0, errno, "getline");
 
513
        error_plus(0, errno, "getline");
501
514
        switch(e){
502
515
        case EBADF:
503
516
          status = EX_UNAVAILABLE;
 
517
          break;
504
518
        case EIO:
505
519
        case EINVAL:
506
520
        default:
526
540
    fprintf(stderr, "Restoring terminal attributes\n");
527
541
  }
528
542
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
529
 
    error(0, errno, "tcsetattr+echo");
 
543
    error_plus(0, errno, "tcsetattr+echo");
530
544
  }
531
545
  
532
546
  if(quit_now){
534
548
    old_action.sa_handler = SIG_DFL;
535
549
    ret = sigaction(signal_received, &old_action, NULL);
536
550
    if(ret == -1){
537
 
      error(0, errno, "sigaction");
 
551
      error_plus(0, errno, "sigaction");
538
552
    }
539
553
    raise(signal_received);
540
554
  }