/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 <argp.h>               /* struct argp_option,
48
 
                                   struct argp_state, struct argp,
49
 
                                   argp_parse() */
 
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 */
50
52
 
51
53
volatile bool quit_now = false;
52
54
bool debug = false;
53
 
const char *argp_program_version = "passprompt 0.9";
 
55
const char *argp_program_version = "password-prompt 1.0";
54
56
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
55
57
 
56
58
static void termination_handler(__attribute__((unused))int signum){
71
73
    struct argp_option options[] = {
72
74
      { .name = "prefix", .key = 'p',
73
75
        .arg = "PREFIX", .flags = 0,
74
 
        .doc = "Prefix used before the passprompt", .group = 2 },
 
76
        .doc = "Prefix shown before the prompt", .group = 2 },
75
77
      { .name = "debug", .key = 128,
76
78
        .doc = "Debug mode", .group = 3 },
77
79
      { .name = NULL }
100
102
  
101
103
    struct argp argp = { .options = options, .parser = parse_opt,
102
104
                         .args_doc = "",
103
 
                         .doc = "Mandos Passprompt -- Provides a passprompt" };
104
 
    argp_parse (&argp, argc, argv, 0, 0, NULL);
 
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;
 
111
    }
105
112
  }
106
113
    
107
114
  if (debug){
112
119
  }
113
120
  
114
121
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
 
122
    perror("tcgetattr");
115
123
    return EXIT_FAILURE;
116
124
  }
117
125
  
119
127
  sigaddset(&new_action.sa_mask, SIGINT);
120
128
  sigaddset(&new_action.sa_mask, SIGHUP);
121
129
  sigaddset(&new_action.sa_mask, SIGTERM);
122
 
  sigaction(SIGINT, NULL, &old_action);
123
 
  if (old_action.sa_handler != SIG_IGN)
124
 
    sigaction(SIGINT, &new_action, NULL);
125
 
  sigaction(SIGHUP, NULL, &old_action);
126
 
  if (old_action.sa_handler != SIG_IGN)
127
 
    sigaction(SIGHUP, &new_action, NULL);
128
 
  sigaction(SIGTERM, NULL, &old_action);
129
 
  if (old_action.sa_handler != SIG_IGN)
130
 
    sigaction(SIGTERM, &new_action, NULL);
131
 
 
 
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
  
132
167
  
133
168
  if (debug){
134
169
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
146
181
  }
147
182
  while(true){
148
183
    if (quit_now){
 
184
      if(debug){
 
185
        fprintf(stderr, "Interrupted by signal, exiting.\n");
 
186
      }
149
187
      status = EXIT_FAILURE;
150
188
      break;
151
189
    }
152
190
 
153
191
    if(prefix){
154
 
      fprintf(stderr, "%s Password: ", prefix);
155
 
    } else {
156
 
      fprintf(stderr, "Password: ");
157
 
    }      
 
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
    }
158
214
    ret = getline(&buffer, &n, stdin);
159
215
    if (ret > 0){
160
 
      fprintf(stdout, "%s", buffer);
161
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
      }
162
229
      break;
163
230
    }
164
231
    if (ret < 0){
171
238
    /* if(ret == 0), then the only sensible thing to do is to retry to
172
239
       read from stdin */
173
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
    }
174
246
  }
175
247
  
176
248
  if (debug){
181
253
  }
182
254
  
183
255
  if (debug){
184
 
    fprintf(stderr, "%s is exiting\n", argv[0]);
 
256
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
 
257
            status);
185
258
  }
186
259
  
187
260
  return status;