/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/splashy.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
 * Splashy - Read a password from splashy and output it
4
4
 * 
5
 
 * Copyright © 2008,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 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             /* TEMP_FAILURE_RETRY(), asprintf() */
29
29
                                   SIG_IGN, kill(), SIGKILL */
30
30
#include <stddef.h>             /* NULL */
31
31
#include <stdlib.h>             /* getenv() */
32
 
#include <stdio.h>              /* asprintf(), perror() */
 
32
#include <stdio.h>              /* asprintf(), vasprintf(), vprintf(),
 
33
                                   fprintf() */
33
34
#include <stdlib.h>             /* EXIT_FAILURE, free(),
34
35
                                   EXIT_SUCCESS */
35
36
#include <sys/types.h>          /* pid_t, DIR, struct dirent,
42
43
                                   sleep(), dup2() STDERR_FILENO,
43
44
                                   STDOUT_FILENO, _exit(),
44
45
                                   pause() */
45
 
#include <string.h>             /* memcmp() */
46
 
#include <errno.h>              /* errno */
 
46
#include <string.h>             /* memcmp(), strerror() */
 
47
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
 
48
                                   ENOENT, ENAMETOOLONG, EMFILE,
 
49
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
 
50
                                   E2BIG, EFAULT, EIO, ETXTBSY,
 
51
                                   EISDIR, ELIBBAD, EPERM, EINTR,
 
52
                                   ECHILD */
 
53
#include <error.h>              /* error() */
47
54
#include <sys/wait.h>           /* waitpid(), WIFEXITED(),
48
55
                                   WEXITSTATUS() */
49
 
 
50
56
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
51
57
                                   EX_UNAVAILABLE */
 
58
#include <stdarg.h>             /* va_list, va_start(), ... */
52
59
 
53
60
sig_atomic_t interrupted_by_signal = 0;
54
61
int signal_received;
55
62
 
 
63
/* Function to use when printing errors */
 
64
__attribute__((format (gnu_printf, 3, 4)))
 
65
void error_plus(int status, int errnum, const char *formatstring,
 
66
                ...){
 
67
  va_list ap;
 
68
  char *text;
 
69
  int ret;
 
70
  
 
71
  va_start(ap, formatstring);
 
72
  ret = vasprintf(&text, formatstring, ap);
 
73
  if(ret == -1){
 
74
    fprintf(stderr, "Mandos plugin %s: ",
 
75
            program_invocation_short_name);
 
76
    vfprintf(stderr, formatstring, ap);
 
77
    fprintf(stderr, ": ");
 
78
    fprintf(stderr, "%s\n", strerror(errnum));
 
79
    error(status, errno, "vasprintf while printing error");
 
80
    return;
 
81
  }
 
82
  fprintf(stderr, "Mandos plugin ");
 
83
  error(status, errnum, "%s", text);
 
84
  free(text);
 
85
}
 
86
 
 
87
 
56
88
static void termination_handler(int signum){
57
89
  if(interrupted_by_signal){
58
90
    return;
105
137
    proc_dir = opendir("/proc");
106
138
    if(proc_dir == NULL){
107
139
      int e = errno;
108
 
      perror("opendir");
 
140
      error_plus(0, errno, "opendir");
109
141
      switch(e){
110
142
      case EACCES:
111
143
      case ENOTDIR:
147
179
        char *exe_link;
148
180
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
149
181
        if(ret == -1){
150
 
          perror("asprintf");
 
182
          error_plus(0, errno, "asprintf");
151
183
          exitstatus = EX_OSERR;
152
184
          goto failure;
153
185
        }
161
193
            continue;
162
194
          }
163
195
          int e = errno;
164
 
          perror("lstat");
 
196
          error_plus(0, errno, "lstat");
165
197
          free(exe_link);
166
198
          switch(e){
167
199
          case EACCES:
209
241
    sigemptyset(&new_action.sa_mask);
210
242
    ret = sigaddset(&new_action.sa_mask, SIGINT);
211
243
    if(ret == -1){
212
 
      perror("sigaddset");
 
244
      error_plus(0, errno, "sigaddset");
213
245
      exitstatus = EX_OSERR;
214
246
      goto failure;
215
247
    }
216
248
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
217
249
    if(ret == -1){
218
 
      perror("sigaddset");
 
250
      error_plus(0, errno, "sigaddset");
219
251
      exitstatus = EX_OSERR;
220
252
      goto failure;
221
253
    }
222
254
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
223
255
    if(ret == -1){
224
 
      perror("sigaddset");
 
256
      error_plus(0, errno, "sigaddset");
225
257
      exitstatus = EX_OSERR;
226
258
      goto failure;
227
259
    }
228
260
    ret = sigaction(SIGINT, NULL, &old_action);
229
261
    if(ret == -1){
230
 
      perror("sigaction");
 
262
      error_plus(0, errno, "sigaction");
231
263
      exitstatus = EX_OSERR;
232
264
      goto failure;
233
265
    }
234
266
    if(old_action.sa_handler != SIG_IGN){
235
267
      ret = sigaction(SIGINT, &new_action, NULL);
236
268
      if(ret == -1){
237
 
        perror("sigaction");
 
269
        error_plus(0, errno, "sigaction");
238
270
        exitstatus = EX_OSERR;
239
271
        goto failure;
240
272
      }
241
273
    }
242
274
    ret = sigaction(SIGHUP, NULL, &old_action);
243
275
    if(ret == -1){
244
 
      perror("sigaction");
 
276
      error_plus(0, errno, "sigaction");
245
277
      exitstatus = EX_OSERR;
246
278
      goto failure;
247
279
    }
248
280
    if(old_action.sa_handler != SIG_IGN){
249
281
      ret = sigaction(SIGHUP, &new_action, NULL);
250
282
      if(ret == -1){
251
 
        perror("sigaction");
 
283
        error_plus(0, errno, "sigaction");
252
284
        exitstatus = EX_OSERR;
253
285
        goto failure;
254
286
      }
255
287
    }
256
288
    ret = sigaction(SIGTERM, NULL, &old_action);
257
289
    if(ret == -1){
258
 
      perror("sigaction");
 
290
      error_plus(0, errno, "sigaction");
259
291
      exitstatus = EX_OSERR;
260
292
      goto failure;
261
293
    }
262
294
    if(old_action.sa_handler != SIG_IGN){
263
295
      ret = sigaction(SIGTERM, &new_action, NULL);
264
296
      if(ret == -1){
265
 
        perror("sigaction");
 
297
        error_plus(0, errno, "sigaction");
266
298
        exitstatus = EX_OSERR;
267
299
        goto failure;
268
300
      }
279
311
    goto failure;
280
312
  }
281
313
  if(splashy_command_pid == -1){
282
 
    perror("fork");
 
314
    error_plus(0, errno, "fork");
283
315
    exitstatus = EX_OSERR;
284
316
    goto failure;
285
317
  }
288
320
    if(not interrupted_by_signal){
289
321
      const char splashy_command[] = "/sbin/splashy_update";
290
322
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
291
 
      perror("execl");
 
323
      int e = errno;
 
324
      error_plus(0, errno, "execl");
 
325
      switch(e){
 
326
      case EACCES:
 
327
      case ENOENT:
 
328
      case ENOEXEC:
 
329
      case EINVAL:
 
330
        _exit(EX_UNAVAILABLE);
 
331
      case ENAMETOOLONG:
 
332
      case E2BIG:
 
333
      case ENOMEM:
 
334
      case EFAULT:
 
335
      case EIO:
 
336
      case EMFILE:
 
337
      case ENFILE:
 
338
      case ETXTBSY:
 
339
      default:
 
340
        _exit(EX_OSERR);
 
341
      case ENOTDIR:
 
342
      case ELOOP:
 
343
      case EISDIR:
 
344
#ifdef ELIBBAD
 
345
      case ELIBBAD:             /* Linux only */
 
346
#endif
 
347
      case EPERM:
 
348
        _exit(EX_OSFILE);
 
349
      }
292
350
    }
293
351
    free(prompt);
294
352
    _exit(EXIT_FAILURE);
313
371
      goto failure;
314
372
    }
315
373
    if(ret == -1){
316
 
      perror("waitpid");
 
374
      error_plus(0, errno, "waitpid");
317
375
      if(errno == ECHILD){
318
376
        splashy_command_pid = 0;
319
377
      }
351
409
         the real user ID (_mandos) */
352
410
      ret = setuid(geteuid());
353
411
      if(ret == -1){
354
 
        perror("setuid");
 
412
        error_plus(0, errno, "setuid");
355
413
      }
356
414
      
357
415
      setsid();
358
416
      ret = chdir("/");
359
417
      if(ret == -1){
360
 
        perror("chdir");
 
418
        error_plus(0, errno, "chdir");
361
419
      }
362
420
/*       if(fork() != 0){ */
363
421
/*      _exit(EXIT_SUCCESS); */
364
422
/*       } */
365
423
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
366
424
      if(ret == -1){
367
 
        perror("dup2");
 
425
        error_plus(0, errno, "dup2");
368
426
        _exit(EX_OSERR);
369
427
      }
370
428
      
371
429
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
372
430
      {
373
431
        int e = errno;
374
 
        perror("execl");
 
432
        error_plus(0, errno, "execl");
375
433
        switch(e){
376
434
        case EACCES:
377
435
        case ENOENT:
397
455
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
398
456
                                            &signal_action, NULL));
399
457
    if(ret == -1){
400
 
      perror("sigaction");
 
458
      error_plus(0, errno, "sigaction");
401
459
    }
402
460
    do {
403
461
      ret = raise(signal_received);
404
462
    } while(ret != 0 and errno == EINTR);
405
463
    if(ret != 0){
406
 
      perror("raise");
 
464
      error_plus(0, errno, "raise");
407
465
      abort();
408
466
    }
409
467
    TEMP_FAILURE_RETRY(pause());