/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
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
51
50
                                   ARGP_KEY_ARG, ARGP_KEY_END,
52
51
                                   ARGP_ERR_UNKNOWN */
53
52
 
54
 
volatile sig_atomic_t quit_now = 0;
 
53
volatile bool quit_now = false;
55
54
bool debug = false;
56
 
const char *argp_program_version = "password-prompt " VERSION;
 
55
const char *argp_program_version = "password-prompt 1.0";
57
56
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
58
57
 
59
58
static void termination_handler(__attribute__((unused))int signum){
60
 
  quit_now = 1;
 
59
  quit_now = true;
61
60
}
62
61
 
63
62
int main(int argc, char **argv){
79
78
        .doc = "Debug mode", .group = 3 },
80
79
      { .name = NULL }
81
80
    };
82
 
    
83
 
    error_t parse_opt (int key, char *arg, struct argp_state *state){
84
 
      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) {
85
86
      case 'p':
86
87
        prefix = arg;
87
88
        break;
89
90
        debug = true;
90
91
        break;
91
92
      case ARGP_KEY_ARG:
92
 
        argp_usage(state);
 
93
        argp_usage (state);
93
94
        break;
94
95
      case ARGP_KEY_END:
95
96
        break;
98
99
      }
99
100
      return 0;
100
101
    }
101
 
    
 
102
  
102
103
    struct argp argp = { .options = options, .parser = parse_opt,
103
104
                         .args_doc = "",
104
105
                         .doc = "Mandos password-prompt -- Read and"
105
106
                         " output a password" };
106
 
    ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
107
 
    if(ret == ARGP_ERR_UNKNOWN){
 
107
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
108
    if (ret == ARGP_ERR_UNKNOWN){
108
109
      fprintf(stderr, "Unknown error while parsing arguments\n");
109
110
      return EXIT_FAILURE;
110
111
    }
111
112
  }
112
 
  
113
 
  if(debug){
 
113
    
 
114
  if (debug){
114
115
    fprintf(stderr, "Starting %s\n", argv[0]);
115
116
  }
116
 
  if(debug){
 
117
  if (debug){
117
118
    fprintf(stderr, "Storing current terminal attributes\n");
118
119
  }
119
120
  
120
 
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
 
121
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
121
122
    perror("tcgetattr");
122
123
    return EXIT_FAILURE;
123
124
  }
131
132
    perror("sigaction");
132
133
    return EXIT_FAILURE;
133
134
  }
134
 
  if(old_action.sa_handler != SIG_IGN){
 
135
  if (old_action.sa_handler != SIG_IGN){
135
136
    ret = sigaction(SIGINT, &new_action, NULL);
136
137
    if(ret == -1){
137
138
      perror("sigaction");
143
144
    perror("sigaction");
144
145
    return EXIT_FAILURE;
145
146
  }
146
 
  if(old_action.sa_handler != SIG_IGN){
 
147
  if (old_action.sa_handler != SIG_IGN){
147
148
    ret = sigaction(SIGHUP, &new_action, NULL);
148
149
    if(ret == -1){
149
150
      perror("sigaction");
155
156
    perror("sigaction");
156
157
    return EXIT_FAILURE;
157
158
  }
158
 
  if(old_action.sa_handler != SIG_IGN){
 
159
  if (old_action.sa_handler != SIG_IGN){
159
160
    ret = sigaction(SIGTERM, &new_action, NULL);
160
161
    if(ret == -1){
161
162
      perror("sigaction");
164
165
  }
165
166
  
166
167
  
167
 
  if(debug){
 
168
  if (debug){
168
169
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
169
170
  }
170
171
  
171
172
  t_new = t_old;
172
173
  t_new.c_lflag &= ~ECHO;
173
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
 
174
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
174
175
    perror("tcsetattr-echo");
175
176
    return EXIT_FAILURE;
176
177
  }
177
178
 
178
 
  if(debug){
 
179
  if (debug){
179
180
    fprintf(stderr, "Waiting for input from stdin \n");
180
181
  }
181
182
  while(true){
182
 
    if(quit_now){
 
183
    if (quit_now){
183
184
      if(debug){
184
185
        fprintf(stderr, "Interrupted by signal, exiting.\n");
185
186
      }
194
195
      const char *cryptsource = getenv("cryptsource");
195
196
      const char *crypttarget = getenv("crypttarget");
196
197
      const char *const prompt
197
 
        = "Enter passphrase to unlock the disk";      
 
198
        = "Enter passphrase to unlock the disk";
198
199
      if(cryptsource == NULL){
199
200
        if(crypttarget == NULL){
200
201
          fprintf(stderr, "%s: ", prompt);
211
212
      }
212
213
    }
213
214
    ret = getline(&buffer, &n, stdin);
214
 
    if(ret > 0){
 
215
    if (ret > 0){
215
216
      status = EXIT_SUCCESS;
216
217
      /* Make n = data size instead of allocated buffer size */
217
218
      n = (size_t)ret;
218
 
      /* Strip final newline */
219
 
      if(n>0 and buffer[n-1] == '\n'){
220
 
        buffer[n-1] = '\0';     /* not strictly necessary */
221
 
        n--;
222
 
      }
223
219
      size_t written = 0;
224
220
      while(written < n){
225
221
        ret = write(STDOUT_FILENO, buffer + written, n - written);
232
228
      }
233
229
      break;
234
230
    }
235
 
    if(ret < 0){
236
 
      if(errno != EINTR and not feof(stdin)){
 
231
    if (ret < 0){
 
232
      if (errno != EINTR and not feof(stdin)){
237
233
        perror("getline");
238
234
        status = EXIT_FAILURE;
239
235
        break;
242
238
    /* if(ret == 0), then the only sensible thing to do is to retry to
243
239
       read from stdin */
244
240
    fputc('\n', stderr);
245
 
    if(debug and quit_now == 0){
246
 
      /* If quit_now is nonzero, we were interrupted by a signal, and
 
241
    if(debug and not quit_now){
 
242
      /* If quit_now is true, we were interrupted by a signal, and
247
243
         will print that later, so no need to show this too. */
248
244
      fprintf(stderr, "getline() returned 0, retrying.\n");
249
245
    }
250
246
  }
251
247
  
252
 
  free(buffer);
253
 
  
254
 
  if(debug){
 
248
  if (debug){
255
249
    fprintf(stderr, "Restoring terminal attributes\n");
256
250
  }
257
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
 
251
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
258
252
    perror("tcsetattr+echo");
259
253
  }
260
254
  
261
 
  if(debug){
 
255
  if (debug){
262
256
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
263
257
            status);
264
258
  }
265
 
  if(status == EXIT_SUCCESS){
266
 
    fputc('\n', stderr);
267
 
  }
268
259
  
269
260
  return status;
270
261
}