/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:
33
33
                                   sigaction, sigemptyset(),
34
34
                                   sigaction(), sigaddset(), SIGINT,
35
35
                                   SIGQUIT, SIGHUP, SIGTERM */
36
 
#include <stddef.h>             /* NULL, size_t */
 
36
#include <stddef.h>             /* NULL, size_t, ssize_t */
37
37
#include <sys/types.h>          /* ssize_t */
38
38
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
39
 
                                   getopt_long */
 
39
                                   getopt_long, getenv() */
40
40
#include <stdio.h>              /* fprintf(), stderr, getline(),
41
41
                                   stdin, feof(), perror(), fputc(),
42
42
                                   stdout, getopt_long */
44
44
#include <iso646.h>             /* or, not */
45
45
#include <stdbool.h>            /* bool, false, true */
46
46
#include <string.h>             /* strlen, rindex, strncmp, strcmp */
47
 
#include <getopt.h>             /* getopt_long */
 
47
#include <argp.h>               /* struct argp_option, struct
 
48
                                   argp_state, struct argp,
 
49
                                   argp_parse(), error_t,
 
50
                                   ARGP_KEY_ARG, ARGP_KEY_END,
 
51
                                   ARGP_ERR_UNKNOWN */
48
52
 
49
53
volatile bool quit_now = false;
50
54
bool debug = false;
 
55
const char *argp_program_version = "password-prompt 1.0";
 
56
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
51
57
 
52
 
void termination_handler(__attribute__((unused))int signum){
 
58
static void termination_handler(__attribute__((unused))int signum){
53
59
  quit_now = true;
54
60
}
55
61
 
63
69
  struct sigaction old_action,
64
70
    new_action = { .sa_handler = termination_handler,
65
71
                   .sa_flags = 0 };
66
 
 
67
 
  while (true){
68
 
    static struct option long_options[] = {
69
 
      {"debug", no_argument, (int *)&debug, 1},
70
 
      {"prefix", required_argument, 0, 'p'},
71
 
      {0, 0, 0, 0} };
72
 
 
73
 
    int option_index = 0;
74
 
    ret = getopt_long (argc, argv, "p:", long_options, &option_index);
75
 
 
76
 
    if (ret == -1){
77
 
      break;
 
72
  {
 
73
    struct argp_option options[] = {
 
74
      { .name = "prefix", .key = 'p',
 
75
        .arg = "PREFIX", .flags = 0,
 
76
        .doc = "Prefix shown before the prompt", .group = 2 },
 
77
      { .name = "debug", .key = 128,
 
78
        .doc = "Debug mode", .group = 3 },
 
79
      { .name = NULL }
 
80
    };
 
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) {
 
86
      case 'p':
 
87
        prefix = arg;
 
88
        break;
 
89
      case 128:
 
90
        debug = true;
 
91
        break;
 
92
      case ARGP_KEY_ARG:
 
93
        argp_usage (state);
 
94
        break;
 
95
      case ARGP_KEY_END:
 
96
        break;
 
97
      default:
 
98
        return ARGP_ERR_UNKNOWN;
 
99
      }
 
100
      return 0;
78
101
    }
79
 
      
80
 
    switch(ret){
81
 
    case 0:
82
 
      break;
83
 
    case 'p':
84
 
      prefix = optarg;
85
 
      break;
86
 
    default:
87
 
      fprintf(stderr, "bad arguments\n");
88
 
      exit(EXIT_FAILURE);
 
102
  
 
103
    struct argp argp = { .options = options, .parser = parse_opt,
 
104
                         .args_doc = "",
 
105
                         .doc = "Mandos password-prompt -- Read and"
 
106
                         " output a password" };
 
107
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
108
    if (ret == ARGP_ERR_UNKNOWN){
 
109
      fprintf(stderr, "Unknown error while parsing arguments\n");
 
110
      return EXIT_FAILURE;
89
111
    }
90
112
  }
91
 
      
 
113
    
92
114
  if (debug){
93
115
    fprintf(stderr, "Starting %s\n", argv[0]);
94
116
  }
97
119
  }
98
120
  
99
121
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
 
122
    perror("tcgetattr");
100
123
    return EXIT_FAILURE;
101
124
  }
102
125
  
103
126
  sigemptyset(&new_action.sa_mask);
104
127
  sigaddset(&new_action.sa_mask, SIGINT);
105
 
  sigaddset(&new_action.sa_mask, SIGQUIT);
106
128
  sigaddset(&new_action.sa_mask, SIGHUP);
107
129
  sigaddset(&new_action.sa_mask, SIGTERM);
108
 
  sigaction(SIGINT, NULL, &old_action);
109
 
  if (old_action.sa_handler != SIG_IGN)
110
 
    sigaction(SIGINT, &new_action, NULL);
111
 
  sigaction(SIGQUIT, NULL, &old_action);
112
 
  if (old_action.sa_handler != SIG_IGN)
113
 
    sigaction(SIGQUIT, &new_action, NULL);
114
 
  sigaction(SIGHUP, NULL, &old_action);
115
 
  if (old_action.sa_handler != SIG_IGN)
116
 
    sigaction(SIGHUP, &new_action, NULL);
117
 
  sigaction(SIGTERM, NULL, &old_action);
118
 
  if (old_action.sa_handler != SIG_IGN)
119
 
    sigaction(SIGTERM, &new_action, NULL);
120
 
 
 
130
  ret = sigaction(SIGINT, NULL, &old_action);
 
131
  if(ret == -1){
 
132
    perror("sigaction");
 
133
    return EXIT_FAILURE;
 
134
  }
 
135
  if (old_action.sa_handler != SIG_IGN){
 
136
    ret = sigaction(SIGINT, &new_action, NULL);
 
137
    if(ret == -1){
 
138
      perror("sigaction");
 
139
      return EXIT_FAILURE;
 
140
    }
 
141
  }
 
142
  ret = sigaction(SIGHUP, NULL, &old_action);
 
143
  if(ret == -1){
 
144
    perror("sigaction");
 
145
    return EXIT_FAILURE;
 
146
  }
 
147
  if (old_action.sa_handler != SIG_IGN){
 
148
    ret = sigaction(SIGHUP, &new_action, NULL);
 
149
    if(ret == -1){
 
150
      perror("sigaction");
 
151
      return EXIT_FAILURE;
 
152
    }
 
153
  }
 
154
  ret = sigaction(SIGTERM, NULL, &old_action);
 
155
  if(ret == -1){
 
156
    perror("sigaction");
 
157
    return EXIT_FAILURE;
 
158
  }
 
159
  if (old_action.sa_handler != SIG_IGN){
 
160
    ret = sigaction(SIGTERM, &new_action, NULL);
 
161
    if(ret == -1){
 
162
      perror("sigaction");
 
163
      return EXIT_FAILURE;
 
164
    }
 
165
  }
 
166
  
121
167
  
122
168
  if (debug){
123
169
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
135
181
  }
136
182
  while(true){
137
183
    if (quit_now){
 
184
      if(debug){
 
185
        fprintf(stderr, "Interrupted by signal, exiting.\n");
 
186
      }
138
187
      status = EXIT_FAILURE;
139
188
      break;
140
189
    }
141
190
 
142
191
    if(prefix){
143
 
      fprintf(stderr, "%s Password: ", prefix);
144
 
    } else {
145
 
      fprintf(stderr, "Password: ");
146
 
    }      
 
192
      fprintf(stderr, "%s ", prefix);
 
193
    }
 
194
    {
 
195
      const char *cryptsource = getenv("cryptsource");
 
196
      const char *crypttarget = getenv("crypttarget");
 
197
      const char *const prompt
 
198
        = "Enter passphrase to unlock the disk";
 
199
      if(cryptsource == NULL){
 
200
        if(crypttarget == NULL){
 
201
          fprintf(stderr, "%s: ", prompt);
 
202
        } else {
 
203
          fprintf(stderr, "%s (%s): ", prompt, crypttarget);
 
204
        }
 
205
      } else {
 
206
        if(crypttarget == NULL){
 
207
          fprintf(stderr, "%s %s: ", prompt, cryptsource);
 
208
        } else {
 
209
          fprintf(stderr, "%s %s (%s): ", prompt, cryptsource,
 
210
                  crypttarget);
 
211
        }
 
212
      }
 
213
    }
147
214
    ret = getline(&buffer, &n, stdin);
148
215
    if (ret > 0){
149
 
      fprintf(stdout, "%s", buffer);
150
216
      status = EXIT_SUCCESS;
 
217
      /* Make n = data size instead of allocated buffer size */
 
218
      n = (size_t)ret;
 
219
      size_t written = 0;
 
220
      while(written < n){
 
221
        ret = write(STDOUT_FILENO, buffer + written, n - written);
 
222
        if(ret < 0){
 
223
          perror("write");
 
224
          status = EXIT_FAILURE;
 
225
          break;
 
226
        }
 
227
        written += (size_t)ret;
 
228
      }
151
229
      break;
152
230
    }
153
 
    // ret == 0 makes no other sence than to retry to read from stdin
154
231
    if (ret < 0){
155
232
      if (errno != EINTR and not feof(stdin)){
156
233
        perror("getline");
158
235
        break;
159
236
      }
160
237
    }
 
238
    /* if(ret == 0), then the only sensible thing to do is to retry to
 
239
       read from stdin */
161
240
    fputc('\n', stderr);
 
241
    if(debug and not quit_now){
 
242
      /* If quit_now is true, we were interrupted by a signal, and
 
243
         will print that later, so no need to show this too. */
 
244
      fprintf(stderr, "getline() returned 0, retrying.\n");
 
245
    }
162
246
  }
163
 
 
 
247
  
164
248
  if (debug){
165
249
    fprintf(stderr, "Restoring terminal attributes\n");
166
250
  }
167
251
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
168
252
    perror("tcsetattr+echo");
169
253
  }
170
 
 
 
254
  
171
255
  if (debug){
172
 
    fprintf(stderr, "%s is exiting\n", argv[0]);
 
256
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
 
257
            status);
173
258
  }
174
259
  
175
260
  return status;