/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-03-10 18:03:38 UTC
  • Revision ID: teddy@recompile.se-20150310180338-pcxw6r2qmw9k6br9
Add ":!RSA" to GnuTLS priority string, to disallow non-DHE kx.

If Mandos was somehow made to use a non-ephemeral Diffie-Hellman key
exchange algorithm in the TLS handshake, any saved network traffic
could then be decrypted later if the Mandos client key was obtained.
By default, Mandos uses ephemeral DH key exchanges which does not have
this problem, but a non-ephemeral key exchange algorithm was still
enabled by default.  The simplest solution is to simply turn that off,
which ensures that Mandos will always use ephemeral DH key exchanges.

There is a "PFS" priority string specifier, but we can't use it because:

1. Security-wise, it is a mix between "NORMAL" and "SECURE128" - it
   enables a lot more algorithms than "SECURE256".

2. It is only available since GnuTLS 3.2.4.

Thanks to Andreas Fischer <af@bantuX.org> for reporting this issue.

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() */
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
 
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
    }
105
129
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
106
130
                   proc_entry->d_name);
107
131
    if(ret == -1){
108
 
      error(0, errno, "asprintf");
 
132
      error_plus(0, errno, "asprintf");
109
133
      return 0;
110
134
    }
111
135
    
113
137
    cl_fd = open(cmdline_filename, O_RDONLY);
114
138
    free(cmdline_filename);
115
139
    if(cl_fd == -1){
116
 
      error(0, errno, "open");
 
140
      if(errno != ENOENT){
 
141
        error_plus(0, errno, "open");
 
142
      }
117
143
      return 0;
118
144
    }
119
145
    
129
155
        if(cmdline_len + blocksize + 1 > cmdline_allocated){
130
156
          tmp = realloc(cmdline, cmdline_allocated + blocksize + 1);
131
157
          if(tmp == NULL){
132
 
            error(0, errno, "realloc");
 
158
            error_plus(0, errno, "realloc");
133
159
            free(cmdline);
134
160
            close(cl_fd);
135
161
            return 0;
142
168
        sret = read(cl_fd, cmdline + cmdline_len,
143
169
                    cmdline_allocated - cmdline_len);
144
170
        if(sret == -1){
145
 
          error(0, errno, "read");
 
171
          error_plus(0, errno, "read");
146
172
          free(cmdline);
147
173
          close(cl_fd);
148
174
          return 0;
151
177
      } while(sret != 0);
152
178
      ret = close(cl_fd);
153
179
      if(ret == -1){
154
 
        error(0, errno, "close");
 
180
        error_plus(0, errno, "close");
155
181
        free(cmdline);
156
182
        return 0;
157
183
      }
167
193
      cmdline_base = cmdline;
168
194
    }
169
195
    
170
 
    if((strcmp(cmdline_base, plymouth_name) != 0)
171
 
       and (strcmp(cmdline_base, plymouth_alt_name) != 0)){
 
196
    if(strcmp(cmdline_base, plymouth_name) != 0){
172
197
      if(debug){
173
 
        fprintf(stderr, "\"%s\" is not \"%s\" or \"%s\"\n",
174
 
                cmdline_base, plymouth_name, plymouth_alt_name);
 
198
        fprintf(stderr, "\"%s\" is not \"%s\"\n", cmdline_base,
 
199
                plymouth_name);
175
200
      }
176
201
      free(cmdline);
177
202
      return 0;
178
203
    }
179
 
    fprintf(stderr, "\"%s\" equals \"%s\" or \"%s\"\n",
180
 
            cmdline_base, plymouth_name, plymouth_alt_name);
 
204
    if(debug){
 
205
      fprintf(stderr, "\"%s\" equals \"%s\"\n", cmdline_base,
 
206
              plymouth_name);
 
207
    }
181
208
    free(cmdline);
182
209
    return 1;
183
210
  }
184
211
  
185
 
  struct dirent **direntries;
 
212
  struct dirent **direntries = NULL;
186
213
  int ret;
187
214
  ret = scandir("/proc", &direntries, is_plymouth, alphasort);
188
 
  if (ret == -1){
189
 
    error(1, errno, "scandir");
 
215
  if(ret == -1){
 
216
    error_plus(1, errno, "scandir");
190
217
  }
 
218
  free(direntries);
191
219
  return ret > 0;
192
220
}
193
221
 
222
250
      { .name = NULL }
223
251
    };
224
252
    
 
253
    __attribute__((nonnull(3)))
225
254
    error_t parse_opt (int key, char *arg, struct argp_state *state){
226
255
      errno = 0;
227
256
      switch (key){
263
292
    case ENOMEM:
264
293
    default:
265
294
      errno = ret;
266
 
      error(0, errno, "argp_parse");
 
295
      error_plus(0, errno, "argp_parse");
267
296
      return EX_OSERR;
268
297
    case EINVAL:
269
298
      return EX_USAGE;
274
303
    fprintf(stderr, "Starting %s\n", argv[0]);
275
304
  }
276
305
 
277
 
  if (conflict_detection()){
 
306
  if(conflict_detection()){
278
307
    if(debug){
279
308
      fprintf(stderr, "Stopping %s because of conflict\n", argv[0]);
280
309
    }
287
316
  
288
317
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
289
318
    int e = errno;
290
 
    error(0, errno, "tcgetattr");
 
319
    error_plus(0, errno, "tcgetattr");
291
320
    switch(e){
292
321
    case EBADF:
293
322
    case ENOTTY:
300
329
  sigemptyset(&new_action.sa_mask);
301
330
  ret = sigaddset(&new_action.sa_mask, SIGINT);
302
331
  if(ret == -1){
303
 
    error(0, errno, "sigaddset");
 
332
    error_plus(0, errno, "sigaddset");
304
333
    return EX_OSERR;
305
334
  }
306
335
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
307
336
  if(ret == -1){
308
 
    error(0, errno, "sigaddset");
 
337
    error_plus(0, errno, "sigaddset");
309
338
    return EX_OSERR;
310
339
  }
311
340
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
312
341
  if(ret == -1){
313
 
    error(0, errno, "sigaddset");
 
342
    error_plus(0, errno, "sigaddset");
314
343
    return EX_OSERR;
315
344
  }
316
345
  /* Need to check if the handler is SIG_IGN before handling:
319
348
  */
320
349
  ret = sigaction(SIGINT, NULL, &old_action);
321
350
  if(ret == -1){
322
 
    error(0, errno, "sigaction");
 
351
    error_plus(0, errno, "sigaction");
323
352
    return EX_OSERR;
324
353
  }
325
354
  if(old_action.sa_handler != SIG_IGN){
326
355
    ret = sigaction(SIGINT, &new_action, NULL);
327
356
    if(ret == -1){
328
 
      error(0, errno, "sigaction");
 
357
      error_plus(0, errno, "sigaction");
329
358
      return EX_OSERR;
330
359
    }
331
360
  }
332
361
  ret = sigaction(SIGHUP, NULL, &old_action);
333
362
  if(ret == -1){
334
 
    error(0, errno, "sigaction");
 
363
    error_plus(0, errno, "sigaction");
335
364
    return EX_OSERR;
336
365
  }
337
366
  if(old_action.sa_handler != SIG_IGN){
338
367
    ret = sigaction(SIGHUP, &new_action, NULL);
339
368
    if(ret == -1){
340
 
      error(0, errno, "sigaction");
 
369
      error_plus(0, errno, "sigaction");
341
370
      return EX_OSERR;
342
371
    }
343
372
  }
344
373
  ret = sigaction(SIGTERM, NULL, &old_action);
345
374
  if(ret == -1){
346
 
    error(0, errno, "sigaction");
 
375
    error_plus(0, errno, "sigaction");
347
376
    return EX_OSERR;
348
377
  }
349
378
  if(old_action.sa_handler != SIG_IGN){
350
379
    ret = sigaction(SIGTERM, &new_action, NULL);
351
380
    if(ret == -1){
352
 
      error(0, errno, "sigaction");
 
381
      error_plus(0, errno, "sigaction");
353
382
      return EX_OSERR;
354
383
    }
355
384
  }
363
392
  t_new.c_lflag &= ~(tcflag_t)ECHO;
364
393
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
365
394
    int e = errno;
366
 
    error(0, errno, "tcsetattr-echo");
 
395
    error_plus(0, errno, "tcsetattr-echo");
367
396
    switch(e){
368
397
    case EBADF:
369
398
    case ENOTTY:
433
462
        sret = write(STDOUT_FILENO, buffer + written, n - written);
434
463
        if(sret < 0){
435
464
          int e = errno;
436
 
          error(0, errno, "write");
 
465
          error_plus(0, errno, "write");
437
466
          switch(e){
438
467
          case EBADF:
439
468
          case EFAULT:
455
484
      sret = close(STDOUT_FILENO);
456
485
      if(sret == -1){
457
486
        int e = errno;
458
 
        error(0, errno, "close");
 
487
        error_plus(0, errno, "close");
459
488
        switch(e){
460
489
        case EBADF:
461
490
          status = EX_OSFILE;
471
500
    if(sret < 0){
472
501
      int e = errno;
473
502
      if(errno != EINTR and not feof(stdin)){
474
 
        error(0, errno, "getline");
 
503
        error_plus(0, errno, "getline");
475
504
        switch(e){
476
505
        case EBADF:
477
506
          status = EX_UNAVAILABLE;
 
507
          break;
478
508
        case EIO:
479
509
        case EINVAL:
480
510
        default:
500
530
    fprintf(stderr, "Restoring terminal attributes\n");
501
531
  }
502
532
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
503
 
    error(0, errno, "tcsetattr+echo");
 
533
    error_plus(0, errno, "tcsetattr+echo");
504
534
  }
505
535
  
506
536
  if(quit_now){
508
538
    old_action.sa_handler = SIG_DFL;
509
539
    ret = sigaction(signal_received, &old_action, NULL);
510
540
    if(ret == -1){
511
 
      error(0, errno, "sigaction");
 
541
      error_plus(0, errno, "sigaction");
512
542
    }
513
543
    raise(signal_received);
514
544
  }