/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: 2019-02-10 03:50:20 UTC
  • Revision ID: teddy@recompile.se-20190210035020-nttr1tybgwwixueu
Show debconf note about new TLS key IDs

If mandos-client did not see TLS keys and had to create them, or if
mandos sees GnuTLS version 3.6.6 or later, show an important notice on
package installation about the importance of adding the new key_id
options to clients.conf on the Mandos server.

* debian/control (Package: mandos, Package: mandos-client): Depend on
                                                            debconf.
* debian/mandos-client.lintian-overrides: Override warnings.
* debian/mandos-client.postinst (create_keys): Show notice if new TLS
                                               key files were created.
* debian/mandos-client.templates: New.
* debian/mandos.lintian-overrides: Override warnings.
* debian/mandos.postinst (configure): If GnuTLS 3.6.6 or later is
                                      detected, show an important
                                      notice (once) about the new
                                      key_id option required in
                                      clients.conf.
* debian/mandos.templates: New.

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
7
 
 * 
8
 
 * This program is free software: you can redistribute it and/or
9
 
 * modify it under the terms of the GNU General Public License as
10
 
 * published by the Free Software Foundation, either version 3 of the
11
 
 * License, or (at your option) any later version.
12
 
 * 
13
 
 * This program is distributed in the hope that it will be useful, but
 
5
 * Copyright © 2008-2018 Teddy Hogeborn
 
6
 * Copyright © 2008-2018 Björn Påhlsson
 
7
 * 
 
8
 * This file is part of Mandos.
 
9
 * 
 
10
 * Mandos is free software: you can redistribute it and/or modify it
 
11
 * under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation, either version 3 of the License, or
 
13
 * (at your option) any later version.
 
14
 * 
 
15
 * Mandos is distributed in the hope that it will be useful, but
14
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
18
 * General Public License for more details.
17
19
 * 
18
20
 * You should have received a copy of the GNU General Public License
19
 
 * along with this program.  If not, see
20
 
 * <http://www.gnu.org/licenses/>.
 
21
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
21
22
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
23
 * Contact the authors at <mandos@recompile.se>.
23
24
 */
24
25
 
25
26
#define _GNU_SOURCE             /* getline(), asprintf() */
26
27
 
27
 
#include <termios.h>            /* struct termios, tcsetattr(),
 
28
#include <termios.h>            /* struct termios, tcsetattr(),
28
29
                                   TCSAFLUSH, tcgetattr(), ECHO */
29
30
#include <unistd.h>             /* struct termios, tcsetattr(),
30
31
                                   STDIN_FILENO, TCSAFLUSH,
41
42
                                   getenv(), free() */
42
43
#include <dirent.h>             /* scandir(), alphasort() */
43
44
#include <stdio.h>              /* fprintf(), stderr, getline(),
44
 
                                   stdin, feof(), fputc()
45
 
                                */
 
45
                                   stdin, feof(), fputc(), vfprintf(),
 
46
                                   vasprintf() */
46
47
#include <errno.h>              /* errno, EBADF, ENOTTY, EINVAL,
47
48
                                   EFAULT, EFBIG, EIO, ENOSPC, EINTR
48
49
                                */
50
51
#include <iso646.h>             /* or, not */
51
52
#include <stdbool.h>            /* bool, false, true */
52
53
#include <inttypes.h>           /* strtoumax() */
53
 
#include <sys/stat.h>           /* struct stat, lstat(), open() */
54
 
#include <string.h>             /* strlen, rindex, memcmp */
 
54
#include <sys/stat.h>           /* struct stat, lstat(), open() */
 
55
#include <string.h>             /* strlen, rindex, memcmp, strerror()
 
56
                                 */
55
57
#include <argp.h>               /* struct argp_option, struct
56
58
                                   argp_state, struct argp,
57
59
                                   argp_parse(), error_t,
60
62
#include <sysexits.h>           /* EX_SOFTWARE, EX_OSERR,
61
63
                                   EX_UNAVAILABLE, EX_IOERR, EX_OK */
62
64
#include <fcntl.h>              /* open() */
 
65
#include <stdarg.h>             /* va_list, va_start(), ... */
63
66
 
64
67
volatile sig_atomic_t quit_now = 0;
65
68
int signal_received;
66
69
bool debug = false;
67
70
const char *argp_program_version = "password-prompt " VERSION;
68
 
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
 
71
const char *argp_program_bug_address = "<mandos@recompile.se>";
69
72
 
70
73
/* Needed for conflict resolution */
71
74
const char plymouth_name[] = "plymouthd";
72
 
const char plymouth_alt_name[] = "plymouthd";
73
75
 
 
76
/* Function to use when printing errors */
 
77
__attribute__((format (gnu_printf, 3, 4)))
 
78
void error_plus(int status, int errnum, const char *formatstring,
 
79
                ...){
 
80
  va_list ap;
 
81
  char *text;
 
82
  int ret;
 
83
  
 
84
  va_start(ap, formatstring);
 
85
  ret = vasprintf(&text, formatstring, ap);
 
86
  if(ret == -1){
 
87
    fprintf(stderr, "Mandos plugin %s: ",
 
88
            program_invocation_short_name);
 
89
    vfprintf(stderr, formatstring, ap);
 
90
    fprintf(stderr, ": %s\n", strerror(errnum));
 
91
    error(status, errno, "vasprintf while printing error");
 
92
    return;
 
93
  }
 
94
  fprintf(stderr, "Mandos plugin ");
 
95
  error(status, errnum, "%s", text);
 
96
  free(text);
 
97
}
74
98
 
75
99
static void termination_handler(int signum){
76
100
  if(quit_now){
86
110
     from the terminal.  Password-prompt will exit if it detects
87
111
     plymouth since plymouth performs the same functionality.
88
112
   */
 
113
  __attribute__((nonnull))
89
114
  int is_plymouth(const struct dirent *proc_entry){
90
115
    int ret;
91
116
    int cl_fd;
92
117
    {
93
 
      uintmax_t maxvalue;
 
118
      uintmax_t proc_id;
94
119
      char *tmp;
95
120
      errno = 0;
96
 
      maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
 
121
      proc_id = strtoumax(proc_entry->d_name, &tmp, 10);
97
122
      
98
123
      if(errno != 0 or *tmp != '\0'
99
 
         or maxvalue != (uintmax_t)((pid_t)maxvalue)){
 
124
         or proc_id != (uintmax_t)((pid_t)proc_id)){
100
125
        return 0;
101
126
      }
102
127
    }
103
128
    
104
129
    char *cmdline_filename;
105
 
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline", proc_entry->d_name);
 
130
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
 
131
                   proc_entry->d_name);
106
132
    if(ret == -1){
107
 
      error(0, errno, "asprintf");
 
133
      error_plus(0, errno, "asprintf");
108
134
      return 0;
109
135
    }
110
136
    
111
 
    /* Open /proc/<pid>/cmdline  */
 
137
    /* Open /proc/<pid>/cmdline */
112
138
    cl_fd = open(cmdline_filename, O_RDONLY);
113
139
    free(cmdline_filename);
114
140
    if(cl_fd == -1){
115
 
      error(0, errno, "open");
 
141
      if(errno != ENOENT){
 
142
        error_plus(0, errno, "open");
 
143
      }
116
144
      return 0;
117
145
    }
118
146
    
128
156
        if(cmdline_len + blocksize + 1 > cmdline_allocated){
129
157
          tmp = realloc(cmdline, cmdline_allocated + blocksize + 1);
130
158
          if(tmp == NULL){
131
 
            error(0, errno, "realloc");
 
159
            error_plus(0, errno, "realloc");
132
160
            free(cmdline);
133
161
            close(cl_fd);
134
162
            return 0;
141
169
        sret = read(cl_fd, cmdline + cmdline_len,
142
170
                    cmdline_allocated - cmdline_len);
143
171
        if(sret == -1){
144
 
          error(0, errno, "read");
 
172
          error_plus(0, errno, "read");
145
173
          free(cmdline);
146
174
          close(cl_fd);
147
175
          return 0;
150
178
      } while(sret != 0);
151
179
      ret = close(cl_fd);
152
180
      if(ret == -1){
153
 
        error(0, errno, "close");
 
181
        error_plus(0, errno, "close");
154
182
        free(cmdline);
155
183
        return 0;
156
184
      }
166
194
      cmdline_base = cmdline;
167
195
    }
168
196
    
169
 
    if((strcmp(cmdline_base, plymouth_name) != 0)
170
 
       and (strcmp(cmdline_base, plymouth_alt_name) != 0)){
 
197
    if(strcmp(cmdline_base, plymouth_name) != 0){
 
198
      if(debug){
 
199
        fprintf(stderr, "\"%s\" is not \"%s\"\n", cmdline_base,
 
200
                plymouth_name);
 
201
      }
171
202
      free(cmdline);
172
203
      return 0;
173
204
    }
 
205
    if(debug){
 
206
      fprintf(stderr, "\"%s\" equals \"%s\"\n", cmdline_base,
 
207
              plymouth_name);
 
208
    }
174
209
    free(cmdline);
175
210
    return 1;
176
211
  }
177
 
 
178
 
  struct dirent **direntries;
 
212
  
 
213
  struct dirent **direntries = NULL;
179
214
  int ret;
180
215
  ret = scandir("/proc", &direntries, is_plymouth, alphasort);
181
 
  if (ret == -1){
182
 
    error(1, errno, "scandir");
183
 
  }
 
216
  if(ret == -1){
 
217
    error_plus(1, errno, "scandir");
 
218
  }
 
219
  {
 
220
    int i = ret;
 
221
    while(i--){
 
222
      free(direntries[i]);
 
223
    }
 
224
  }
 
225
  free(direntries);
184
226
  return ret > 0;
185
227
}
186
228
 
215
257
      { .name = NULL }
216
258
    };
217
259
    
 
260
    __attribute__((nonnull(3)))
218
261
    error_t parse_opt (int key, char *arg, struct argp_state *state){
219
262
      errno = 0;
220
263
      switch (key){
256
299
    case ENOMEM:
257
300
    default:
258
301
      errno = ret;
259
 
      error(0, errno, "argp_parse");
 
302
      error_plus(0, errno, "argp_parse");
260
303
      return EX_OSERR;
261
304
    case EINVAL:
262
305
      return EX_USAGE;
267
310
    fprintf(stderr, "Starting %s\n", argv[0]);
268
311
  }
269
312
 
270
 
  if (conflict_detection()){
 
313
  if(conflict_detection()){
271
314
    if(debug){
272
 
      fprintf(stderr, "Stopping %s because of conflict", argv[0]);
 
315
      fprintf(stderr, "Stopping %s because of conflict\n", argv[0]);
273
316
    }
274
317
    return EXIT_FAILURE;
275
318
  }
280
323
  
281
324
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
282
325
    int e = errno;
283
 
    error(0, errno, "tcgetattr");
 
326
    error_plus(0, errno, "tcgetattr");
284
327
    switch(e){
285
328
    case EBADF:
286
329
    case ENOTTY:
293
336
  sigemptyset(&new_action.sa_mask);
294
337
  ret = sigaddset(&new_action.sa_mask, SIGINT);
295
338
  if(ret == -1){
296
 
    error(0, errno, "sigaddset");
 
339
    error_plus(0, errno, "sigaddset");
297
340
    return EX_OSERR;
298
341
  }
299
342
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
300
343
  if(ret == -1){
301
 
    error(0, errno, "sigaddset");
 
344
    error_plus(0, errno, "sigaddset");
302
345
    return EX_OSERR;
303
346
  }
304
347
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
305
348
  if(ret == -1){
306
 
    error(0, errno, "sigaddset");
 
349
    error_plus(0, errno, "sigaddset");
307
350
    return EX_OSERR;
308
351
  }
309
352
  /* Need to check if the handler is SIG_IGN before handling:
312
355
  */
313
356
  ret = sigaction(SIGINT, NULL, &old_action);
314
357
  if(ret == -1){
315
 
    error(0, errno, "sigaction");
 
358
    error_plus(0, errno, "sigaction");
316
359
    return EX_OSERR;
317
360
  }
318
361
  if(old_action.sa_handler != SIG_IGN){
319
362
    ret = sigaction(SIGINT, &new_action, NULL);
320
363
    if(ret == -1){
321
 
      error(0, errno, "sigaction");
 
364
      error_plus(0, errno, "sigaction");
322
365
      return EX_OSERR;
323
366
    }
324
367
  }
325
368
  ret = sigaction(SIGHUP, NULL, &old_action);
326
369
  if(ret == -1){
327
 
    error(0, errno, "sigaction");
 
370
    error_plus(0, errno, "sigaction");
328
371
    return EX_OSERR;
329
372
  }
330
373
  if(old_action.sa_handler != SIG_IGN){
331
374
    ret = sigaction(SIGHUP, &new_action, NULL);
332
375
    if(ret == -1){
333
 
      error(0, errno, "sigaction");
 
376
      error_plus(0, errno, "sigaction");
334
377
      return EX_OSERR;
335
378
    }
336
379
  }
337
380
  ret = sigaction(SIGTERM, NULL, &old_action);
338
381
  if(ret == -1){
339
 
    error(0, errno, "sigaction");
 
382
    error_plus(0, errno, "sigaction");
340
383
    return EX_OSERR;
341
384
  }
342
385
  if(old_action.sa_handler != SIG_IGN){
343
386
    ret = sigaction(SIGTERM, &new_action, NULL);
344
387
    if(ret == -1){
345
 
      error(0, errno, "sigaction");
 
388
      error_plus(0, errno, "sigaction");
346
389
      return EX_OSERR;
347
390
    }
348
391
  }
356
399
  t_new.c_lflag &= ~(tcflag_t)ECHO;
357
400
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
358
401
    int e = errno;
359
 
    error(0, errno, "tcsetattr-echo");
 
402
    error_plus(0, errno, "tcsetattr-echo");
360
403
    switch(e){
361
404
    case EBADF:
362
405
    case ENOTTY:
426
469
        sret = write(STDOUT_FILENO, buffer + written, n - written);
427
470
        if(sret < 0){
428
471
          int e = errno;
429
 
          error(0, errno, "write");
 
472
          error_plus(0, errno, "write");
430
473
          switch(e){
431
474
          case EBADF:
432
475
          case EFAULT:
448
491
      sret = close(STDOUT_FILENO);
449
492
      if(sret == -1){
450
493
        int e = errno;
451
 
        error(0, errno, "close");
 
494
        error_plus(0, errno, "close");
452
495
        switch(e){
453
496
        case EBADF:
454
497
          status = EX_OSFILE;
464
507
    if(sret < 0){
465
508
      int e = errno;
466
509
      if(errno != EINTR and not feof(stdin)){
467
 
        error(0, errno, "getline");
 
510
        error_plus(0, errno, "getline");
468
511
        switch(e){
469
512
        case EBADF:
470
513
          status = EX_UNAVAILABLE;
 
514
          break;
471
515
        case EIO:
472
516
        case EINVAL:
473
517
        default:
477
521
        break;
478
522
      }
479
523
    }
480
 
    /* if(sret == 0), then the only sensible thing to do is to retry to
481
 
       read from stdin */
 
524
    /* if(sret == 0), then the only sensible thing to do is to retry
 
525
       to read from stdin */
482
526
    fputc('\n', stderr);
483
527
    if(debug and not quit_now){
484
528
      /* If quit_now is nonzero, we were interrupted by a signal, and
493
537
    fprintf(stderr, "Restoring terminal attributes\n");
494
538
  }
495
539
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
496
 
    error(0, errno, "tcsetattr+echo");
 
540
    error_plus(0, errno, "tcsetattr+echo");
497
541
  }
498
542
  
499
543
  if(quit_now){
501
545
    old_action.sa_handler = SIG_DFL;
502
546
    ret = sigaction(signal_received, &old_action, NULL);
503
547
    if(ret == -1){
504
 
      error(0, errno, "sigaction");
 
548
      error_plus(0, errno, "sigaction");
505
549
    }
506
550
    raise(signal_received);
507
551
  }