/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: 2015-07-20 03:03:33 UTC
  • Revision ID: teddy@recompile.se-20150720030333-203m2aeblypcsfte
Bug fix for GnuTLS 3: be compatible with old 2048-bit DSA keys.

The mandos-keygen program in Mandos version 1.6.0 and older generated
2048-bit DSA keys, and when GnuTLS uses these it has trouble
connecting using the Mandos default priority string.  This was
previously fixed in Mandos 1.6.2, but the bug reappeared when using
GnuTLS 3, so the default priority string has to change again; this
time also the Mandos client has to change its default, so now the
server and the client should use the same default priority string:

SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA:+SIGN-DSA-SHA256

* mandos (main/server_defaults): Changed default priority string.
* mandos-options.xml (/section/para[id="priority_compat"]): Removed.
  (/section/para[id="priority"]): Changed default priority string.
* mandos.conf ([DEFAULT]/priority): - '' -
* mandos.conf.xml (OPTIONS/priority): Refer to the id "priority"
                                      instead of "priority_compat".
* mandos.xml (OPTIONS/--priority): - '' -
* plugins.d/mandos-client.c (main): Changed default priority string.

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-2014 Teddy Hogeborn
 
6
 * Copyright © 2008-2014 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() */
26
26
 
27
 
#include <termios.h>            /* struct termios, tcsetattr(),
 
27
#include <termios.h>            /* struct termios, tcsetattr(),
28
28
                                   TCSAFLUSH, tcgetattr(), ECHO */
29
29
#include <unistd.h>             /* struct termios, tcsetattr(),
30
30
                                   STDIN_FILENO, TCSAFLUSH,
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
                                */
50
50
#include <iso646.h>             /* or, not */
51
51
#include <stdbool.h>            /* bool, false, true */
52
52
#include <inttypes.h>           /* strtoumax() */
53
 
#include <sys/stat.h>           /* struct stat, lstat(), open() */
54
 
#include <string.h>             /* strlen, rindex, memcmp */
 
53
#include <sys/stat.h>           /* struct stat, lstat(), open() */
 
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
 
const char plymouth_alt_name[] = "plymouthd";
73
74
 
 
75
/* Function to use when printing errors */
 
76
__attribute__((format (gnu_printf, 3, 4)))
 
77
void error_plus(int status, int errnum, const char *formatstring,
 
78
                ...){
 
79
  va_list ap;
 
80
  char *text;
 
81
  int ret;
 
82
  
 
83
  va_start(ap, formatstring);
 
84
  ret = vasprintf(&text, formatstring, ap);
 
85
  if(ret == -1){
 
86
    fprintf(stderr, "Mandos plugin %s: ",
 
87
            program_invocation_short_name);
 
88
    vfprintf(stderr, formatstring, ap);
 
89
    fprintf(stderr, ": %s\n", strerror(errnum));
 
90
    error(status, errno, "vasprintf while printing error");
 
91
    return;
 
92
  }
 
93
  fprintf(stderr, "Mandos plugin ");
 
94
  error(status, errnum, "%s", text);
 
95
  free(text);
 
96
}
74
97
 
75
98
static void termination_handler(int signum){
76
99
  if(quit_now){
86
109
     from the terminal.  Password-prompt will exit if it detects
87
110
     plymouth since plymouth performs the same functionality.
88
111
   */
 
112
  __attribute__((nonnull))
89
113
  int is_plymouth(const struct dirent *proc_entry){
90
114
    int ret;
91
115
    int cl_fd;
92
116
    {
93
 
      uintmax_t maxvalue;
 
117
      uintmax_t proc_id;
94
118
      char *tmp;
95
119
      errno = 0;
96
 
      maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
 
120
      proc_id = strtoumax(proc_entry->d_name, &tmp, 10);
97
121
      
98
122
      if(errno != 0 or *tmp != '\0'
99
 
         or maxvalue != (uintmax_t)((pid_t)maxvalue)){
 
123
         or proc_id != (uintmax_t)((pid_t)proc_id)){
100
124
        return 0;
101
125
      }
102
126
    }
103
127
    
104
128
    char *cmdline_filename;
105
 
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline", proc_entry->d_name);
 
129
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
 
130
                   proc_entry->d_name);
106
131
    if(ret == -1){
107
 
      error(0, errno, "asprintf");
 
132
      error_plus(0, errno, "asprintf");
108
133
      return 0;
109
134
    }
110
135
    
111
 
    /* Open /proc/<pid>/cmdline  */
 
136
    /* Open /proc/<pid>/cmdline */
112
137
    cl_fd = open(cmdline_filename, O_RDONLY);
113
138
    free(cmdline_filename);
114
139
    if(cl_fd == -1){
115
 
      error(0, errno, "open");
 
140
      if(errno != ENOENT){
 
141
        error_plus(0, errno, "open");
 
142
      }
116
143
      return 0;
117
144
    }
118
145
    
128
155
        if(cmdline_len + blocksize + 1 > cmdline_allocated){
129
156
          tmp = realloc(cmdline, cmdline_allocated + blocksize + 1);
130
157
          if(tmp == NULL){
131
 
            error(0, errno, "realloc");
 
158
            error_plus(0, errno, "realloc");
132
159
            free(cmdline);
133
160
            close(cl_fd);
134
161
            return 0;
141
168
        sret = read(cl_fd, cmdline + cmdline_len,
142
169
                    cmdline_allocated - cmdline_len);
143
170
        if(sret == -1){
144
 
          error(0, errno, "read");
 
171
          error_plus(0, errno, "read");
145
172
          free(cmdline);
146
173
          close(cl_fd);
147
174
          return 0;
150
177
      } while(sret != 0);
151
178
      ret = close(cl_fd);
152
179
      if(ret == -1){
153
 
        error(0, errno, "close");
 
180
        error_plus(0, errno, "close");
154
181
        free(cmdline);
155
182
        return 0;
156
183
      }
166
193
      cmdline_base = cmdline;
167
194
    }
168
195
    
169
 
    if((strcmp(cmdline_base, plymouth_name) != 0)
170
 
       and (strcmp(cmdline_base, plymouth_alt_name) != 0)){
 
196
    if(strcmp(cmdline_base, plymouth_name) != 0){
 
197
      if(debug){
 
198
        fprintf(stderr, "\"%s\" is not \"%s\"\n", cmdline_base,
 
199
                plymouth_name);
 
200
      }
171
201
      free(cmdline);
172
202
      return 0;
173
203
    }
 
204
    if(debug){
 
205
      fprintf(stderr, "\"%s\" equals \"%s\"\n", cmdline_base,
 
206
              plymouth_name);
 
207
    }
174
208
    free(cmdline);
175
209
    return 1;
176
210
  }
177
 
 
178
 
  struct dirent **direntries;
 
211
  
 
212
  struct dirent **direntries = NULL;
179
213
  int ret;
180
214
  ret = scandir("/proc", &direntries, is_plymouth, alphasort);
181
 
  if (ret == -1){
182
 
    error(1, errno, "scandir");
 
215
  if(ret == -1){
 
216
    error_plus(1, errno, "scandir");
183
217
  }
 
218
  free(direntries);
184
219
  return ret > 0;
185
220
}
186
221
 
215
250
      { .name = NULL }
216
251
    };
217
252
    
 
253
    __attribute__((nonnull(3)))
218
254
    error_t parse_opt (int key, char *arg, struct argp_state *state){
219
255
      errno = 0;
220
256
      switch (key){
256
292
    case ENOMEM:
257
293
    default:
258
294
      errno = ret;
259
 
      error(0, errno, "argp_parse");
 
295
      error_plus(0, errno, "argp_parse");
260
296
      return EX_OSERR;
261
297
    case EINVAL:
262
298
      return EX_USAGE;
267
303
    fprintf(stderr, "Starting %s\n", argv[0]);
268
304
  }
269
305
 
270
 
  if (conflict_detection()){
 
306
  if(conflict_detection()){
271
307
    if(debug){
272
 
      fprintf(stderr, "Stopping %s because of conflict", argv[0]);
 
308
      fprintf(stderr, "Stopping %s because of conflict\n", argv[0]);
273
309
    }
274
310
    return EXIT_FAILURE;
275
311
  }
280
316
  
281
317
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
282
318
    int e = errno;
283
 
    error(0, errno, "tcgetattr");
 
319
    error_plus(0, errno, "tcgetattr");
284
320
    switch(e){
285
321
    case EBADF:
286
322
    case ENOTTY:
293
329
  sigemptyset(&new_action.sa_mask);
294
330
  ret = sigaddset(&new_action.sa_mask, SIGINT);
295
331
  if(ret == -1){
296
 
    error(0, errno, "sigaddset");
 
332
    error_plus(0, errno, "sigaddset");
297
333
    return EX_OSERR;
298
334
  }
299
335
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
300
336
  if(ret == -1){
301
 
    error(0, errno, "sigaddset");
 
337
    error_plus(0, errno, "sigaddset");
302
338
    return EX_OSERR;
303
339
  }
304
340
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
305
341
  if(ret == -1){
306
 
    error(0, errno, "sigaddset");
 
342
    error_plus(0, errno, "sigaddset");
307
343
    return EX_OSERR;
308
344
  }
309
345
  /* Need to check if the handler is SIG_IGN before handling:
312
348
  */
313
349
  ret = sigaction(SIGINT, NULL, &old_action);
314
350
  if(ret == -1){
315
 
    error(0, errno, "sigaction");
 
351
    error_plus(0, errno, "sigaction");
316
352
    return EX_OSERR;
317
353
  }
318
354
  if(old_action.sa_handler != SIG_IGN){
319
355
    ret = sigaction(SIGINT, &new_action, NULL);
320
356
    if(ret == -1){
321
 
      error(0, errno, "sigaction");
 
357
      error_plus(0, errno, "sigaction");
322
358
      return EX_OSERR;
323
359
    }
324
360
  }
325
361
  ret = sigaction(SIGHUP, NULL, &old_action);
326
362
  if(ret == -1){
327
 
    error(0, errno, "sigaction");
 
363
    error_plus(0, errno, "sigaction");
328
364
    return EX_OSERR;
329
365
  }
330
366
  if(old_action.sa_handler != SIG_IGN){
331
367
    ret = sigaction(SIGHUP, &new_action, NULL);
332
368
    if(ret == -1){
333
 
      error(0, errno, "sigaction");
 
369
      error_plus(0, errno, "sigaction");
334
370
      return EX_OSERR;
335
371
    }
336
372
  }
337
373
  ret = sigaction(SIGTERM, NULL, &old_action);
338
374
  if(ret == -1){
339
 
    error(0, errno, "sigaction");
 
375
    error_plus(0, errno, "sigaction");
340
376
    return EX_OSERR;
341
377
  }
342
378
  if(old_action.sa_handler != SIG_IGN){
343
379
    ret = sigaction(SIGTERM, &new_action, NULL);
344
380
    if(ret == -1){
345
 
      error(0, errno, "sigaction");
 
381
      error_plus(0, errno, "sigaction");
346
382
      return EX_OSERR;
347
383
    }
348
384
  }
356
392
  t_new.c_lflag &= ~(tcflag_t)ECHO;
357
393
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
358
394
    int e = errno;
359
 
    error(0, errno, "tcsetattr-echo");
 
395
    error_plus(0, errno, "tcsetattr-echo");
360
396
    switch(e){
361
397
    case EBADF:
362
398
    case ENOTTY:
426
462
        sret = write(STDOUT_FILENO, buffer + written, n - written);
427
463
        if(sret < 0){
428
464
          int e = errno;
429
 
          error(0, errno, "write");
 
465
          error_plus(0, errno, "write");
430
466
          switch(e){
431
467
          case EBADF:
432
468
          case EFAULT:
448
484
      sret = close(STDOUT_FILENO);
449
485
      if(sret == -1){
450
486
        int e = errno;
451
 
        error(0, errno, "close");
 
487
        error_plus(0, errno, "close");
452
488
        switch(e){
453
489
        case EBADF:
454
490
          status = EX_OSFILE;
464
500
    if(sret < 0){
465
501
      int e = errno;
466
502
      if(errno != EINTR and not feof(stdin)){
467
 
        error(0, errno, "getline");
 
503
        error_plus(0, errno, "getline");
468
504
        switch(e){
469
505
        case EBADF:
470
506
          status = EX_UNAVAILABLE;
 
507
          break;
471
508
        case EIO:
472
509
        case EINVAL:
473
510
        default:
477
514
        break;
478
515
      }
479
516
    }
480
 
    /* if(sret == 0), then the only sensible thing to do is to retry to
481
 
       read from stdin */
 
517
    /* if(sret == 0), then the only sensible thing to do is to retry
 
518
       to read from stdin */
482
519
    fputc('\n', stderr);
483
520
    if(debug and not quit_now){
484
521
      /* If quit_now is nonzero, we were interrupted by a signal, and
493
530
    fprintf(stderr, "Restoring terminal attributes\n");
494
531
  }
495
532
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
496
 
    error(0, errno, "tcsetattr+echo");
 
533
    error_plus(0, errno, "tcsetattr+echo");
497
534
  }
498
535
  
499
536
  if(quit_now){
501
538
    old_action.sa_handler = SIG_DFL;
502
539
    ret = sigaction(signal_received, &old_action, NULL);
503
540
    if(ret == -1){
504
 
      error(0, errno, "sigaction");
 
541
      error_plus(0, errno, "sigaction");
505
542
    }
506
543
    raise(signal_received);
507
544
  }