/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() */
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
                                */
51
52
#include <stdbool.h>            /* bool, false, true */
52
53
#include <inttypes.h>           /* strtoumax() */
53
54
#include <sys/stat.h>           /* struct stat, lstat(), open() */
54
 
#include <string.h>             /* strlen, rindex, memcmp */
 
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
    }
105
130
    ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
106
131
                   proc_entry->d_name);
107
132
    if(ret == -1){
108
 
      error(0, errno, "asprintf");
 
133
      error_plus(0, errno, "asprintf");
109
134
      return 0;
110
135
    }
111
136
    
113
138
    cl_fd = open(cmdline_filename, O_RDONLY);
114
139
    free(cmdline_filename);
115
140
    if(cl_fd == -1){
116
 
      error(0, errno, "open");
 
141
      if(errno != ENOENT){
 
142
        error_plus(0, errno, "open");
 
143
      }
117
144
      return 0;
118
145
    }
119
146
    
129
156
        if(cmdline_len + blocksize + 1 > cmdline_allocated){
130
157
          tmp = realloc(cmdline, cmdline_allocated + blocksize + 1);
131
158
          if(tmp == NULL){
132
 
            error(0, errno, "realloc");
 
159
            error_plus(0, errno, "realloc");
133
160
            free(cmdline);
134
161
            close(cl_fd);
135
162
            return 0;
142
169
        sret = read(cl_fd, cmdline + cmdline_len,
143
170
                    cmdline_allocated - cmdline_len);
144
171
        if(sret == -1){
145
 
          error(0, errno, "read");
 
172
          error_plus(0, errno, "read");
146
173
          free(cmdline);
147
174
          close(cl_fd);
148
175
          return 0;
151
178
      } while(sret != 0);
152
179
      ret = close(cl_fd);
153
180
      if(ret == -1){
154
 
        error(0, errno, "close");
 
181
        error_plus(0, errno, "close");
155
182
        free(cmdline);
156
183
        return 0;
157
184
      }
167
194
      cmdline_base = cmdline;
168
195
    }
169
196
    
170
 
    if((strcmp(cmdline_base, plymouth_name) != 0)
171
 
       and (strcmp(cmdline_base, plymouth_alt_name) != 0)){
 
197
    if(strcmp(cmdline_base, plymouth_name) != 0){
172
198
      if(debug){
173
 
        fprintf(stderr, "\"%s\" is not \"%s\" or \"%s\"\n",
174
 
                cmdline_base, plymouth_name, plymouth_alt_name);
 
199
        fprintf(stderr, "\"%s\" is not \"%s\"\n", cmdline_base,
 
200
                plymouth_name);
175
201
      }
176
202
      free(cmdline);
177
203
      return 0;
178
204
    }
179
 
    fprintf(stderr, "\"%s\" equals \"%s\" or \"%s\"\n",
180
 
            cmdline_base, plymouth_name, plymouth_alt_name);
 
205
    if(debug){
 
206
      fprintf(stderr, "\"%s\" equals \"%s\"\n", cmdline_base,
 
207
              plymouth_name);
 
208
    }
181
209
    free(cmdline);
182
210
    return 1;
183
211
  }
184
212
  
185
 
  struct dirent **direntries;
 
213
  struct dirent **direntries = NULL;
186
214
  int ret;
187
215
  ret = scandir("/proc", &direntries, is_plymouth, alphasort);
188
 
  if (ret == -1){
189
 
    error(1, errno, "scandir");
190
 
  }
 
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);
191
226
  return ret > 0;
192
227
}
193
228
 
222
257
      { .name = NULL }
223
258
    };
224
259
    
 
260
    __attribute__((nonnull(3)))
225
261
    error_t parse_opt (int key, char *arg, struct argp_state *state){
226
262
      errno = 0;
227
263
      switch (key){
263
299
    case ENOMEM:
264
300
    default:
265
301
      errno = ret;
266
 
      error(0, errno, "argp_parse");
 
302
      error_plus(0, errno, "argp_parse");
267
303
      return EX_OSERR;
268
304
    case EINVAL:
269
305
      return EX_USAGE;
274
310
    fprintf(stderr, "Starting %s\n", argv[0]);
275
311
  }
276
312
 
277
 
  if (conflict_detection()){
 
313
  if(conflict_detection()){
278
314
    if(debug){
279
315
      fprintf(stderr, "Stopping %s because of conflict\n", argv[0]);
280
316
    }
287
323
  
288
324
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
289
325
    int e = errno;
290
 
    error(0, errno, "tcgetattr");
 
326
    error_plus(0, errno, "tcgetattr");
291
327
    switch(e){
292
328
    case EBADF:
293
329
    case ENOTTY:
300
336
  sigemptyset(&new_action.sa_mask);
301
337
  ret = sigaddset(&new_action.sa_mask, SIGINT);
302
338
  if(ret == -1){
303
 
    error(0, errno, "sigaddset");
 
339
    error_plus(0, errno, "sigaddset");
304
340
    return EX_OSERR;
305
341
  }
306
342
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
307
343
  if(ret == -1){
308
 
    error(0, errno, "sigaddset");
 
344
    error_plus(0, errno, "sigaddset");
309
345
    return EX_OSERR;
310
346
  }
311
347
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
312
348
  if(ret == -1){
313
 
    error(0, errno, "sigaddset");
 
349
    error_plus(0, errno, "sigaddset");
314
350
    return EX_OSERR;
315
351
  }
316
352
  /* Need to check if the handler is SIG_IGN before handling:
319
355
  */
320
356
  ret = sigaction(SIGINT, NULL, &old_action);
321
357
  if(ret == -1){
322
 
    error(0, errno, "sigaction");
 
358
    error_plus(0, errno, "sigaction");
323
359
    return EX_OSERR;
324
360
  }
325
361
  if(old_action.sa_handler != SIG_IGN){
326
362
    ret = sigaction(SIGINT, &new_action, NULL);
327
363
    if(ret == -1){
328
 
      error(0, errno, "sigaction");
 
364
      error_plus(0, errno, "sigaction");
329
365
      return EX_OSERR;
330
366
    }
331
367
  }
332
368
  ret = sigaction(SIGHUP, NULL, &old_action);
333
369
  if(ret == -1){
334
 
    error(0, errno, "sigaction");
 
370
    error_plus(0, errno, "sigaction");
335
371
    return EX_OSERR;
336
372
  }
337
373
  if(old_action.sa_handler != SIG_IGN){
338
374
    ret = sigaction(SIGHUP, &new_action, NULL);
339
375
    if(ret == -1){
340
 
      error(0, errno, "sigaction");
 
376
      error_plus(0, errno, "sigaction");
341
377
      return EX_OSERR;
342
378
    }
343
379
  }
344
380
  ret = sigaction(SIGTERM, NULL, &old_action);
345
381
  if(ret == -1){
346
 
    error(0, errno, "sigaction");
 
382
    error_plus(0, errno, "sigaction");
347
383
    return EX_OSERR;
348
384
  }
349
385
  if(old_action.sa_handler != SIG_IGN){
350
386
    ret = sigaction(SIGTERM, &new_action, NULL);
351
387
    if(ret == -1){
352
 
      error(0, errno, "sigaction");
 
388
      error_plus(0, errno, "sigaction");
353
389
      return EX_OSERR;
354
390
    }
355
391
  }
363
399
  t_new.c_lflag &= ~(tcflag_t)ECHO;
364
400
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
365
401
    int e = errno;
366
 
    error(0, errno, "tcsetattr-echo");
 
402
    error_plus(0, errno, "tcsetattr-echo");
367
403
    switch(e){
368
404
    case EBADF:
369
405
    case ENOTTY:
433
469
        sret = write(STDOUT_FILENO, buffer + written, n - written);
434
470
        if(sret < 0){
435
471
          int e = errno;
436
 
          error(0, errno, "write");
 
472
          error_plus(0, errno, "write");
437
473
          switch(e){
438
474
          case EBADF:
439
475
          case EFAULT:
455
491
      sret = close(STDOUT_FILENO);
456
492
      if(sret == -1){
457
493
        int e = errno;
458
 
        error(0, errno, "close");
 
494
        error_plus(0, errno, "close");
459
495
        switch(e){
460
496
        case EBADF:
461
497
          status = EX_OSFILE;
471
507
    if(sret < 0){
472
508
      int e = errno;
473
509
      if(errno != EINTR and not feof(stdin)){
474
 
        error(0, errno, "getline");
 
510
        error_plus(0, errno, "getline");
475
511
        switch(e){
476
512
        case EBADF:
477
513
          status = EX_UNAVAILABLE;
 
514
          break;
478
515
        case EIO:
479
516
        case EINVAL:
480
517
        default:
500
537
    fprintf(stderr, "Restoring terminal attributes\n");
501
538
  }
502
539
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
503
 
    error(0, errno, "tcsetattr+echo");
 
540
    error_plus(0, errno, "tcsetattr+echo");
504
541
  }
505
542
  
506
543
  if(quit_now){
508
545
    old_action.sa_handler = SIG_DFL;
509
546
    ret = sigaction(signal_received, &old_action, NULL);
510
547
    if(ret == -1){
511
 
      error(0, errno, "sigaction");
 
548
      error_plus(0, errno, "sigaction");
512
549
    }
513
550
    raise(signal_received);
514
551
  }