/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: 2008-12-10 01:26:02 UTC
  • mfrom: (237.1.2 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20081210012602-vhz3h75xkj24t340
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; mode: c; mode: orgtbl -*- */
 
1
/*  -*- coding: utf-8 -*- */
2
2
/*
3
 
 * Password-prompt - Read a password from the terminal and print it
 
3
 * Passprompt - Read a password from the terminal and print it
4
4
 * 
5
 
 * Copyright © 2008,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 Björn Påhlsson
 
5
 * Copyright © 2008 Teddy Hogeborn
 
6
 * Copyright © 2008 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 <https://www.fukt.bsnet.se/~belorn/> and
 
23
 * <https://www.fukt.bsnet.se/~teddy/>.
23
24
 */
24
25
 
25
26
#define _GNU_SOURCE             /* getline() */
32
33
#include <signal.h>             /* sig_atomic_t, raise(), struct
33
34
                                   sigaction, sigemptyset(),
34
35
                                   sigaction(), sigaddset(), SIGINT,
35
 
                                   SIGQUIT, SIGHUP, SIGTERM,
36
 
                                   raise() */
 
36
                                   SIGQUIT, SIGHUP, SIGTERM */
37
37
#include <stddef.h>             /* NULL, size_t, ssize_t */
38
38
#include <sys/types.h>          /* ssize_t */
39
39
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
44
44
#include <errno.h>              /* errno, EINVAL */
45
45
#include <iso646.h>             /* or, not */
46
46
#include <stdbool.h>            /* bool, false, true */
47
 
#include <string.h>             /* strlen, rindex */
 
47
#include <string.h>             /* strlen, rindex, strncmp, strcmp */
48
48
#include <argp.h>               /* struct argp_option, struct
49
49
                                   argp_state, struct argp,
50
50
                                   argp_parse(), error_t,
51
51
                                   ARGP_KEY_ARG, ARGP_KEY_END,
52
52
                                   ARGP_ERR_UNKNOWN */
53
53
 
54
 
volatile sig_atomic_t quit_now = 0;
55
 
int signal_received;
 
54
volatile bool quit_now = false;
56
55
bool debug = false;
57
56
const char *argp_program_version = "password-prompt " VERSION;
58
57
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
59
58
 
60
 
static void termination_handler(int signum){
61
 
  if(quit_now){
62
 
    return;
63
 
  }
64
 
  quit_now = 1;
65
 
  signal_received = signum;
 
59
static void termination_handler(__attribute__((unused))int signum){
 
60
  quit_now = true;
66
61
}
67
62
 
68
63
int main(int argc, char **argv){
84
79
        .doc = "Debug mode", .group = 3 },
85
80
      { .name = NULL }
86
81
    };
87
 
    
88
 
    error_t parse_opt (int key, char *arg, struct argp_state *state){
89
 
      switch (key){
 
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) {
90
87
      case 'p':
91
88
        prefix = arg;
92
89
        break;
94
91
        debug = true;
95
92
        break;
96
93
      case ARGP_KEY_ARG:
97
 
        argp_usage(state);
 
94
        argp_usage (state);
98
95
        break;
99
96
      case ARGP_KEY_END:
100
97
        break;
103
100
      }
104
101
      return 0;
105
102
    }
106
 
    
 
103
  
107
104
    struct argp argp = { .options = options, .parser = parse_opt,
108
105
                         .args_doc = "",
109
106
                         .doc = "Mandos password-prompt -- Read and"
110
107
                         " output a password" };
111
 
    ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
112
 
    if(ret == ARGP_ERR_UNKNOWN){
 
108
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
109
    if (ret == ARGP_ERR_UNKNOWN){
113
110
      fprintf(stderr, "Unknown error while parsing arguments\n");
114
111
      return EXIT_FAILURE;
115
112
    }
116
113
  }
117
 
  
118
 
  if(debug){
 
114
    
 
115
  if (debug){
119
116
    fprintf(stderr, "Starting %s\n", argv[0]);
120
117
  }
121
 
  if(debug){
 
118
  if (debug){
122
119
    fprintf(stderr, "Storing current terminal attributes\n");
123
120
  }
124
121
  
125
 
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
 
122
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
126
123
    perror("tcgetattr");
127
124
    return EXIT_FAILURE;
128
125
  }
129
126
  
130
127
  sigemptyset(&new_action.sa_mask);
131
 
  ret = sigaddset(&new_action.sa_mask, SIGINT);
132
 
  if(ret == -1){
133
 
    perror("sigaddset");
134
 
    return EXIT_FAILURE;
135
 
  }
136
 
  ret = sigaddset(&new_action.sa_mask, SIGHUP);
137
 
  if(ret == -1){
138
 
    perror("sigaddset");
139
 
    return EXIT_FAILURE;
140
 
  }
141
 
  ret = sigaddset(&new_action.sa_mask, SIGTERM);
142
 
  if(ret == -1){
143
 
    perror("sigaddset");
144
 
    return EXIT_FAILURE;
145
 
  }
146
 
  /* Need to check if the handler is SIG_IGN before handling:
147
 
     | [[info:libc:Initial Signal Actions]] |
148
 
     | [[info:libc:Basic Signal Handling]]  |
149
 
  */
 
128
  sigaddset(&new_action.sa_mask, SIGINT);
 
129
  sigaddset(&new_action.sa_mask, SIGHUP);
 
130
  sigaddset(&new_action.sa_mask, SIGTERM);
150
131
  ret = sigaction(SIGINT, NULL, &old_action);
151
132
  if(ret == -1){
152
133
    perror("sigaction");
153
134
    return EXIT_FAILURE;
154
135
  }
155
 
  if(old_action.sa_handler != SIG_IGN){
 
136
  if (old_action.sa_handler != SIG_IGN){
156
137
    ret = sigaction(SIGINT, &new_action, NULL);
157
138
    if(ret == -1){
158
139
      perror("sigaction");
164
145
    perror("sigaction");
165
146
    return EXIT_FAILURE;
166
147
  }
167
 
  if(old_action.sa_handler != SIG_IGN){
 
148
  if (old_action.sa_handler != SIG_IGN){
168
149
    ret = sigaction(SIGHUP, &new_action, NULL);
169
150
    if(ret == -1){
170
151
      perror("sigaction");
176
157
    perror("sigaction");
177
158
    return EXIT_FAILURE;
178
159
  }
179
 
  if(old_action.sa_handler != SIG_IGN){
 
160
  if (old_action.sa_handler != SIG_IGN){
180
161
    ret = sigaction(SIGTERM, &new_action, NULL);
181
162
    if(ret == -1){
182
163
      perror("sigaction");
185
166
  }
186
167
  
187
168
  
188
 
  if(debug){
 
169
  if (debug){
189
170
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
190
171
  }
191
172
  
192
173
  t_new = t_old;
193
 
  t_new.c_lflag &= ~(tcflag_t)ECHO;
194
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
 
174
  t_new.c_lflag &= ~ECHO;
 
175
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
195
176
    perror("tcsetattr-echo");
196
177
    return EXIT_FAILURE;
197
178
  }
198
179
 
199
 
  if(debug){
 
180
  if (debug){
200
181
    fprintf(stderr, "Waiting for input from stdin \n");
201
182
  }
202
183
  while(true){
203
 
    if(quit_now){
 
184
    if (quit_now){
204
185
      if(debug){
205
186
        fprintf(stderr, "Interrupted by signal, exiting.\n");
206
187
      }
232
213
      }
233
214
    }
234
215
    ret = getline(&buffer, &n, stdin);
235
 
    if(ret > 0){
 
216
    if (ret > 0){
236
217
      status = EXIT_SUCCESS;
237
218
      /* Make n = data size instead of allocated buffer size */
238
219
      n = (size_t)ret;
253
234
      }
254
235
      break;
255
236
    }
256
 
    if(ret < 0){
257
 
      if(errno != EINTR and not feof(stdin)){
 
237
    if (ret < 0){
 
238
      if (errno != EINTR and not feof(stdin)){
258
239
        perror("getline");
259
240
        status = EXIT_FAILURE;
260
241
        break;
264
245
       read from stdin */
265
246
    fputc('\n', stderr);
266
247
    if(debug and not quit_now){
267
 
      /* If quit_now is nonzero, we were interrupted by a signal, and
 
248
      /* If quit_now is true, we were interrupted by a signal, and
268
249
         will print that later, so no need to show this too. */
269
250
      fprintf(stderr, "getline() returned 0, retrying.\n");
270
251
    }
271
252
  }
272
 
  
 
253
 
273
254
  free(buffer);
274
255
  
275
 
  if(debug){
 
256
  if (debug){
276
257
    fprintf(stderr, "Restoring terminal attributes\n");
277
258
  }
278
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
 
259
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
279
260
    perror("tcsetattr+echo");
280
261
  }
281
262
  
282
 
  if(quit_now){
283
 
    sigemptyset(&old_action.sa_mask);
284
 
    old_action.sa_handler = SIG_DFL;
285
 
    ret = sigaction(signal_received, &old_action, NULL);
286
 
    if(ret == -1){
287
 
      perror("sigaction");
288
 
    }
289
 
    raise(signal_received);
290
 
  }
291
 
  
292
 
  if(debug){
 
263
  if (debug){
293
264
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
294
265
            status);
295
266
  }