/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

  • 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
19
18
 * along with this program.  If not, see
20
19
 * <http://www.gnu.org/licenses/>.
21
20
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
21
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
22
 * <https://www.fukt.bsnet.se/~teddy/>.
23
23
 */
24
24
 
25
25
#define _GNU_SOURCE             /* getline() */
32
32
#include <signal.h>             /* sig_atomic_t, raise(), struct
33
33
                                   sigaction, sigemptyset(),
34
34
                                   sigaction(), sigaddset(), SIGINT,
35
 
                                   SIGQUIT, SIGHUP, SIGTERM,
36
 
                                   raise() */
 
35
                                   SIGQUIT, SIGHUP, SIGTERM */
37
36
#include <stddef.h>             /* NULL, size_t, ssize_t */
38
37
#include <sys/types.h>          /* ssize_t */
39
38
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
51
50
                                   ARGP_KEY_ARG, ARGP_KEY_END,
52
51
                                   ARGP_ERR_UNKNOWN */
53
52
 
54
 
volatile sig_atomic_t quit_now = 0;
55
 
int signal_received;
 
53
volatile bool quit_now = false;
56
54
bool debug = false;
57
 
const char *argp_program_version = "password-prompt " VERSION;
 
55
const char *argp_program_version = "password-prompt 1.0";
58
56
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
59
57
 
60
 
static void termination_handler(int signum){
61
 
  if(quit_now){
62
 
    return;
63
 
  }
64
 
  quit_now = 1;
65
 
  signal_received = signum;
 
58
static void termination_handler(__attribute__((unused))int signum){
 
59
  quit_now = true;
66
60
}
67
61
 
68
62
int main(int argc, char **argv){
84
78
        .doc = "Debug mode", .group = 3 },
85
79
      { .name = NULL }
86
80
    };
87
 
    
88
 
    error_t parse_opt (int key, char *arg, struct argp_state *state){
89
 
      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) {
90
86
      case 'p':
91
87
        prefix = arg;
92
88
        break;
94
90
        debug = true;
95
91
        break;
96
92
      case ARGP_KEY_ARG:
97
 
        argp_usage(state);
 
93
        argp_usage (state);
98
94
        break;
99
95
      case ARGP_KEY_END:
100
96
        break;
103
99
      }
104
100
      return 0;
105
101
    }
106
 
    
 
102
  
107
103
    struct argp argp = { .options = options, .parser = parse_opt,
108
104
                         .args_doc = "",
109
105
                         .doc = "Mandos password-prompt -- Read and"
110
106
                         " output a password" };
111
 
    ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
112
 
    if(ret == ARGP_ERR_UNKNOWN){
 
107
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
108
    if (ret == ARGP_ERR_UNKNOWN){
113
109
      fprintf(stderr, "Unknown error while parsing arguments\n");
114
110
      return EXIT_FAILURE;
115
111
    }
116
112
  }
117
 
  
118
 
  if(debug){
 
113
    
 
114
  if (debug){
119
115
    fprintf(stderr, "Starting %s\n", argv[0]);
120
116
  }
121
 
  if(debug){
 
117
  if (debug){
122
118
    fprintf(stderr, "Storing current terminal attributes\n");
123
119
  }
124
120
  
125
 
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
 
121
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
126
122
    perror("tcgetattr");
127
123
    return EXIT_FAILURE;
128
124
  }
129
125
  
130
126
  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
 
  */
 
127
  sigaddset(&new_action.sa_mask, SIGINT);
 
128
  sigaddset(&new_action.sa_mask, SIGHUP);
 
129
  sigaddset(&new_action.sa_mask, SIGTERM);
150
130
  ret = sigaction(SIGINT, NULL, &old_action);
151
131
  if(ret == -1){
152
132
    perror("sigaction");
153
133
    return EXIT_FAILURE;
154
134
  }
155
 
  if(old_action.sa_handler != SIG_IGN){
 
135
  if (old_action.sa_handler != SIG_IGN){
156
136
    ret = sigaction(SIGINT, &new_action, NULL);
157
137
    if(ret == -1){
158
138
      perror("sigaction");
164
144
    perror("sigaction");
165
145
    return EXIT_FAILURE;
166
146
  }
167
 
  if(old_action.sa_handler != SIG_IGN){
 
147
  if (old_action.sa_handler != SIG_IGN){
168
148
    ret = sigaction(SIGHUP, &new_action, NULL);
169
149
    if(ret == -1){
170
150
      perror("sigaction");
176
156
    perror("sigaction");
177
157
    return EXIT_FAILURE;
178
158
  }
179
 
  if(old_action.sa_handler != SIG_IGN){
 
159
  if (old_action.sa_handler != SIG_IGN){
180
160
    ret = sigaction(SIGTERM, &new_action, NULL);
181
161
    if(ret == -1){
182
162
      perror("sigaction");
185
165
  }
186
166
  
187
167
  
188
 
  if(debug){
 
168
  if (debug){
189
169
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
190
170
  }
191
171
  
192
172
  t_new = t_old;
193
173
  t_new.c_lflag &= ~ECHO;
194
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
 
174
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
195
175
    perror("tcsetattr-echo");
196
176
    return EXIT_FAILURE;
197
177
  }
198
178
 
199
 
  if(debug){
 
179
  if (debug){
200
180
    fprintf(stderr, "Waiting for input from stdin \n");
201
181
  }
202
182
  while(true){
203
 
    if(quit_now){
 
183
    if (quit_now){
204
184
      if(debug){
205
185
        fprintf(stderr, "Interrupted by signal, exiting.\n");
206
186
      }
232
212
      }
233
213
    }
234
214
    ret = getline(&buffer, &n, stdin);
235
 
    if(ret > 0){
 
215
    if (ret > 0){
236
216
      status = EXIT_SUCCESS;
237
217
      /* Make n = data size instead of allocated buffer size */
238
218
      n = (size_t)ret;
239
 
      /* Strip final newline */
240
 
      if(n>0 and buffer[n-1] == '\n'){
241
 
        buffer[n-1] = '\0';     /* not strictly necessary */
242
 
        n--;
243
 
      }
244
219
      size_t written = 0;
245
220
      while(written < n){
246
221
        ret = write(STDOUT_FILENO, buffer + written, n - written);
253
228
      }
254
229
      break;
255
230
    }
256
 
    if(ret < 0){
257
 
      if(errno != EINTR and not feof(stdin)){
 
231
    if (ret < 0){
 
232
      if (errno != EINTR and not feof(stdin)){
258
233
        perror("getline");
259
234
        status = EXIT_FAILURE;
260
235
        break;
264
239
       read from stdin */
265
240
    fputc('\n', stderr);
266
241
    if(debug and not quit_now){
267
 
      /* 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
268
243
         will print that later, so no need to show this too. */
269
244
      fprintf(stderr, "getline() returned 0, retrying.\n");
270
245
    }
271
246
  }
272
247
  
273
 
  free(buffer);
274
 
  
275
 
  if(debug){
 
248
  if (debug){
276
249
    fprintf(stderr, "Restoring terminal attributes\n");
277
250
  }
278
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
 
251
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
279
252
    perror("tcsetattr+echo");
280
253
  }
281
254
  
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){
 
255
  if (debug){
293
256
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
294
257
            status);
295
258
  }
296
 
  if(status == EXIT_SUCCESS){
297
 
    fputc('\n', stderr);
298
 
  }
299
259
  
300
260
  return status;
301
261
}