/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-08-29 05:53:59 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080829055359-wkdasnyxtylmnxus
* mandos.xml (EXAMPLE): Replaced all occurences of command name with
                        "&COMMANDNAME;".

* plugins.d/password-prompt.c (main): Improved some documentation
                                      strings.  Do perror() of
                                      tcgetattr() fails.  Add debug
                                      output if interrupted by signal.
                                      Loop over write() instead of
                                      using fwrite() when outputting
                                      password.  Add debug output if
                                      getline() returns 0, unless it
                                      was caused by a signal.  Add
                                      exit status code to debug
                                      output.

* plugins.d/password-prompt.xml: Changed all single quotes to double
                                 quotes for consistency.  Removed
                                 <?xml-stylesheet>.
  (ENTITY TIMESTAMP): New.  Automatically updated by Emacs time-stamp
                      by using Emacs local variables.
  (/refentry/refentryinfo/title): Changed to "Mandos Manual".
  (/refentry/refentryinfo/productname): Changed to "Mandos".
  (/refentry/refentryinfo/date): New; set to "&TIMESTAMP;".
  (/refentry/refentryinfo/copyright): Split copyright holders.
  (/refentry/refnamediv/refpurpose): Improved wording.
  (SYNOPSIS): Fix to use correct markup.  Add short options.
  (DESCRIPTION, OPTIONS): Improved wording.
  (OPTIONS): Improved wording.  Use more correct markup.  Document
             short options.
  (EXIT STATUS): Add text.
  (ENVIRONMENT): Document use of "cryptsource" and "crypttarget".
  (FILES): REMOVED.
  (BUGS): Add text.
  (EXAMPLE): Added some examples.
  (SECURITY): Added text.
  (SEE ALSO): Remove reference to mandos(8).  Add reference to
              crypttab(5).

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