/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to plugins.d/password-prompt.c

First version of a somewhat complete D-Bus server interface.  Also
change user/group name to "_mandos".

* debian/mandos.postinst: Rename old "mandos" user and group to
                          "_mandos"; create "_mandos" user and group
                          if none exist.
* debian/mandos-client.postinst: - '' -

* initramfs-tools-hook: Try "_mandos" before "mandos" as user and
                        group name.

* mandos (_datetime_to_dbus_struct): New; was previously local.
  (Client.started): Renamed to "last_started".  All users changed.
  (Client.started): New; boolean.
  (Client.dbus_object_path): New.
  (Client.check_command): Renamed to "checker_command".  All users
                          changed.
  (Client.__init__): Set and use "self.dbus_object_path".  Set
                     "self.started".
  (Client.start): Update "self.started".  Emit "self.PropertyChanged"
                  signals for both "started" and "last_started".
  (Client.stop): Update "self.started".  Emit "self.PropertyChanged"
                 signal for "started".
  (Client.checker_callback): Take additional "command" argument.  All
                             callers changed. Emit
                             "self.PropertyChanged" signal.
  (Client.bump_timeout): Emit "self.PropertyChanged" signal for
                         "last_checked_ok".
  (Client.start_checker): Emit "self.PropertyChanged" signal for
                          "checker_running".
  (Client.stop_checker): Emit "self.PropertyChanged" signal for
                         "checker_running".
  (Client.still_valid): Bug fix: use "getattr(self, started, False)"
                        instead of "self.started" in case this client
                        object is so new that the "started" attribute
                        has not been created yet.
  (Client.IntervalChanged, Client.CheckerIsRunning, Client.GetChecker,
  Client.GetCreated, Client.GetFingerprint, Client.GetHost,
  Client.GetInterval, Client.GetName, Client.GetStarted,
  Client.GetTimeout, Client.StateChanged, Client.TimeoutChanged):
  Removed; all callers changed.
  (Client.CheckerCompleted): Add "condition" and "command" arguments.
                             All callers changed.
  (Client.GetAllProperties, Client.PropertyChanged): New.
  (Client.StillValid): Renamed to "IsStillValid".
  (Client.StartChecker): Changed to its own function to avoid the
                         return value from "Client.start_checker()".
  (Client.Stop): Changed to its own function to avoid the return value
                 from "Client.stop()".
  (main): Try "_mandos" before "mandos" as user and group name.
          Removed inner function "remove_from_clients".  New inner
          class "MandosServer".

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  -*- coding: utf-8 -*- */
 
2
/*
 
3
 * Passprompt - Read a password from the terminal and print it
 
4
 * 
 
5
 * Copyright © 2008 Teddy Hogeborn
 
6
 * Copyright © 2008 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
 
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * General Public License for more details.
 
17
 * 
 
18
 * 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
 * 
 
22
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
23
 * <https://www.fukt.bsnet.se/~teddy/>.
 
24
 */
 
25
 
1
26
#define _GNU_SOURCE             /* getline() */
2
 
#define _FORTIFY_SOURCE 2
 
27
 
3
28
#include <termios.h>            /* struct termios, tcsetattr(),
4
29
                                   TCSAFLUSH, tcgetattr(), ECHO */
5
30
#include <unistd.h>             /* struct termios, tcsetattr(),
9
34
                                   sigaction, sigemptyset(),
10
35
                                   sigaction(), sigaddset(), SIGINT,
11
36
                                   SIGQUIT, SIGHUP, SIGTERM */
12
 
#include <stddef.h>             /* NULL, size_t */
 
37
#include <stddef.h>             /* NULL, size_t, ssize_t */
13
38
#include <sys/types.h>          /* ssize_t */
14
39
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
15
 
                                   getopt_long */
 
40
                                   getopt_long, getenv() */
16
41
#include <stdio.h>              /* fprintf(), stderr, getline(),
17
42
                                   stdin, feof(), perror(), fputc(),
18
43
                                   stdout, getopt_long */
20
45
#include <iso646.h>             /* or, not */
21
46
#include <stdbool.h>            /* bool, false, true */
22
47
#include <string.h>             /* strlen, rindex, strncmp, strcmp */
23
 
#include <getopt.h>             /* getopt_long */
 
48
#include <argp.h>               /* struct argp_option, struct
 
49
                                   argp_state, struct argp,
 
50
                                   argp_parse(), error_t,
 
51
                                   ARGP_KEY_ARG, ARGP_KEY_END,
 
52
                                   ARGP_ERR_UNKNOWN */
24
53
 
25
54
volatile bool quit_now = false;
26
55
bool debug = false;
 
56
const char *argp_program_version = "password-prompt " VERSION;
 
57
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
27
58
 
28
 
void termination_handler(int signum){
 
59
static void termination_handler(__attribute__((unused))int signum){
29
60
  quit_now = true;
30
61
}
31
62
 
39
70
  struct sigaction old_action,
40
71
    new_action = { .sa_handler = termination_handler,
41
72
                   .sa_flags = 0 };
42
 
 
43
 
  while (true){
44
 
    static struct option long_options[] = {
45
 
      {"debug", no_argument, (int *)&debug, 1},
46
 
      {"prefix", required_argument, 0, 'p'},
47
 
      {0, 0, 0, 0} };
48
 
 
49
 
    int option_index = 0;
50
 
    ret = getopt_long (argc, argv, "p:", long_options, &option_index);
51
 
 
52
 
    if (ret == -1){
53
 
      break;
 
73
  {
 
74
    struct argp_option options[] = {
 
75
      { .name = "prefix", .key = 'p',
 
76
        .arg = "PREFIX", .flags = 0,
 
77
        .doc = "Prefix shown before the prompt", .group = 2 },
 
78
      { .name = "debug", .key = 128,
 
79
        .doc = "Debug mode", .group = 3 },
 
80
      { .name = NULL }
 
81
    };
 
82
  
 
83
    error_t parse_opt (int key, char *arg, struct argp_state *state) {
 
84
      /* Get the INPUT argument from `argp_parse', which we know is a
 
85
         pointer to our plugin list pointer. */
 
86
      switch (key) {
 
87
      case 'p':
 
88
        prefix = arg;
 
89
        break;
 
90
      case 128:
 
91
        debug = true;
 
92
        break;
 
93
      case ARGP_KEY_ARG:
 
94
        argp_usage (state);
 
95
        break;
 
96
      case ARGP_KEY_END:
 
97
        break;
 
98
      default:
 
99
        return ARGP_ERR_UNKNOWN;
 
100
      }
 
101
      return 0;
54
102
    }
55
 
      
56
 
    switch(ret){
57
 
    case 0:
58
 
      break;
59
 
    case 'p':
60
 
      prefix = optarg;
61
 
      break;
62
 
    default:
63
 
      fprintf(stderr, "bad arguments\n");
64
 
      exit(EXIT_FAILURE);
 
103
  
 
104
    struct argp argp = { .options = options, .parser = parse_opt,
 
105
                         .args_doc = "",
 
106
                         .doc = "Mandos password-prompt -- Read and"
 
107
                         " output a password" };
 
108
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
109
    if (ret == ARGP_ERR_UNKNOWN){
 
110
      fprintf(stderr, "Unknown error while parsing arguments\n");
 
111
      return EXIT_FAILURE;
65
112
    }
66
113
  }
67
 
      
 
114
    
68
115
  if (debug){
69
116
    fprintf(stderr, "Starting %s\n", argv[0]);
70
117
  }
73
120
  }
74
121
  
75
122
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
 
123
    perror("tcgetattr");
76
124
    return EXIT_FAILURE;
77
125
  }
78
126
  
79
127
  sigemptyset(&new_action.sa_mask);
80
128
  sigaddset(&new_action.sa_mask, SIGINT);
81
 
  sigaddset(&new_action.sa_mask, SIGQUIT);
82
129
  sigaddset(&new_action.sa_mask, SIGHUP);
83
130
  sigaddset(&new_action.sa_mask, SIGTERM);
84
 
  sigaction(SIGINT, NULL, &old_action);
85
 
  if (old_action.sa_handler != SIG_IGN)
86
 
    sigaction(SIGINT, &new_action, NULL);
87
 
  sigaction(SIGQUIT, NULL, &old_action);
88
 
  if (old_action.sa_handler != SIG_IGN)
89
 
    sigaction(SIGQUIT, &new_action, NULL);
90
 
  sigaction(SIGHUP, NULL, &old_action);
91
 
  if (old_action.sa_handler != SIG_IGN)
92
 
    sigaction(SIGHUP, &new_action, NULL);
93
 
  sigaction(SIGTERM, NULL, &old_action);
94
 
  if (old_action.sa_handler != SIG_IGN)
95
 
    sigaction(SIGTERM, &new_action, NULL);
96
 
 
 
131
  ret = sigaction(SIGINT, NULL, &old_action);
 
132
  if(ret == -1){
 
133
    perror("sigaction");
 
134
    return EXIT_FAILURE;
 
135
  }
 
136
  if (old_action.sa_handler != SIG_IGN){
 
137
    ret = sigaction(SIGINT, &new_action, NULL);
 
138
    if(ret == -1){
 
139
      perror("sigaction");
 
140
      return EXIT_FAILURE;
 
141
    }
 
142
  }
 
143
  ret = sigaction(SIGHUP, NULL, &old_action);
 
144
  if(ret == -1){
 
145
    perror("sigaction");
 
146
    return EXIT_FAILURE;
 
147
  }
 
148
  if (old_action.sa_handler != SIG_IGN){
 
149
    ret = sigaction(SIGHUP, &new_action, NULL);
 
150
    if(ret == -1){
 
151
      perror("sigaction");
 
152
      return EXIT_FAILURE;
 
153
    }
 
154
  }
 
155
  ret = sigaction(SIGTERM, NULL, &old_action);
 
156
  if(ret == -1){
 
157
    perror("sigaction");
 
158
    return EXIT_FAILURE;
 
159
  }
 
160
  if (old_action.sa_handler != SIG_IGN){
 
161
    ret = sigaction(SIGTERM, &new_action, NULL);
 
162
    if(ret == -1){
 
163
      perror("sigaction");
 
164
      return EXIT_FAILURE;
 
165
    }
 
166
  }
 
167
  
97
168
  
98
169
  if (debug){
99
170
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
111
182
  }
112
183
  while(true){
113
184
    if (quit_now){
 
185
      if(debug){
 
186
        fprintf(stderr, "Interrupted by signal, exiting.\n");
 
187
      }
114
188
      status = EXIT_FAILURE;
115
189
      break;
116
190
    }
117
191
 
118
192
    if(prefix){
119
 
      fprintf(stderr, "%s Password: ", prefix);
120
 
    } else {
121
 
      fprintf(stderr, "Password: ");
122
 
    }      
 
193
      fprintf(stderr, "%s ", prefix);
 
194
    }
 
195
    {
 
196
      const char *cryptsource = getenv("cryptsource");
 
197
      const char *crypttarget = getenv("crypttarget");
 
198
      const char *const prompt
 
199
        = "Enter passphrase to unlock the disk";
 
200
      if(cryptsource == NULL){
 
201
        if(crypttarget == NULL){
 
202
          fprintf(stderr, "%s: ", prompt);
 
203
        } else {
 
204
          fprintf(stderr, "%s (%s): ", prompt, crypttarget);
 
205
        }
 
206
      } else {
 
207
        if(crypttarget == NULL){
 
208
          fprintf(stderr, "%s %s: ", prompt, cryptsource);
 
209
        } else {
 
210
          fprintf(stderr, "%s %s (%s): ", prompt, cryptsource,
 
211
                  crypttarget);
 
212
        }
 
213
      }
 
214
    }
123
215
    ret = getline(&buffer, &n, stdin);
124
216
    if (ret > 0){
125
 
      fprintf(stdout, "%s", buffer);
126
217
      status = EXIT_SUCCESS;
 
218
      /* Make n = data size instead of allocated buffer size */
 
219
      n = (size_t)ret;
 
220
      /* Strip final newline */
 
221
      if(n>0 and buffer[n-1] == '\n'){
 
222
        buffer[n-1] = '\0';     /* not strictly necessary */
 
223
        n--;
 
224
      }
 
225
      size_t written = 0;
 
226
      while(written < n){
 
227
        ret = write(STDOUT_FILENO, buffer + written, n - written);
 
228
        if(ret < 0){
 
229
          perror("write");
 
230
          status = EXIT_FAILURE;
 
231
          break;
 
232
        }
 
233
        written += (size_t)ret;
 
234
      }
127
235
      break;
128
236
    }
129
 
    // ret == 0 makes no other sence than to retry to read from stdin
130
237
    if (ret < 0){
131
238
      if (errno != EINTR and not feof(stdin)){
132
239
        perror("getline");
134
241
        break;
135
242
      }
136
243
    }
 
244
    /* if(ret == 0), then the only sensible thing to do is to retry to
 
245
       read from stdin */
137
246
    fputc('\n', stderr);
 
247
    if(debug and not quit_now){
 
248
      /* If quit_now is true, we were interrupted by a signal, and
 
249
         will print that later, so no need to show this too. */
 
250
      fprintf(stderr, "getline() returned 0, retrying.\n");
 
251
    }
138
252
  }
139
253
 
 
254
  free(buffer);
 
255
  
140
256
  if (debug){
141
257
    fprintf(stderr, "Restoring terminal attributes\n");
142
258
  }
143
259
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
144
260
    perror("tcsetattr+echo");
145
261
  }
146
 
 
 
262
  
147
263
  if (debug){
148
 
    fprintf(stderr, "%s is exiting\n", argv[0]);
 
264
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
 
265
            status);
 
266
  }
 
267
  if(status == EXIT_SUCCESS){
 
268
    fputc('\n', stderr);
149
269
  }
150
270
  
151
271
  return status;