/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-16 03:29:08 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080816032908-ihw7c05r2mnyk389
Add feature to specify custom environment variables for plugins.

* plugin-runner.c (plugin): New members "environ" and "envc" to
                            contain possible custom environment.
  (getplugin): Return NULL on failure instead of doing exit(); all
               callers changed.
  (add_to_char_array): New helper function for "add_argument" and
                       "add_environment".
  (addargument): Renamed to "add_argument".  Return bool.  Call
                 "add_to_char_array" to actually do things.
  (add_environment): New; analogous to "add_argument".
  (addcustomargument): Renamed to "add_to_argv" to avoid confusion
                       with "add_argument".
  (main): New options "--global-envs" and "--envs-for" to specify
          custom environment for plugins.  Print environment for
          plugins in debug mode.  Use asprintf instead of strcpy and
          strcat.  Use execve() for plugins with custom environments.
          Free environment for plugin when freeing plugin list.

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
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,
40
 
                                   getopt_long, getenv() */
 
39
                                   getopt_long */
41
40
#include <stdio.h>              /* fprintf(), stderr, getline(),
42
41
                                   stdin, feof(), perror(), fputc(),
43
42
                                   stdout, getopt_long */
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){
74
73
    struct argp_option options[] = {
75
74
      { .name = "prefix", .key = 'p',
76
75
        .arg = "PREFIX", .flags = 0,
77
 
        .doc = "Prefix shown before the prompt", .group = 2 },
 
76
        .doc = "Prefix used before the passprompt", .group = 2 },
78
77
      { .name = "debug", .key = 128,
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
 
                         .doc = "Mandos password-prompt -- Read and"
105
 
                         " output a password" };
106
 
    ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
107
 
    if(ret == ARGP_ERR_UNKNOWN){
 
105
                         .doc = "Mandos Passprompt -- Provides a passprompt" };
 
106
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
107
    if (ret == ARGP_ERR_UNKNOWN){
108
108
      fprintf(stderr, "Unknown error while parsing arguments\n");
109
109
      return EXIT_FAILURE;
110
110
    }
111
111
  }
112
 
  
113
 
  if(debug){
 
112
    
 
113
  if (debug){
114
114
    fprintf(stderr, "Starting %s\n", argv[0]);
115
115
  }
116
 
  if(debug){
 
116
  if (debug){
117
117
    fprintf(stderr, "Storing current terminal attributes\n");
118
118
  }
119
119
  
120
 
  if(tcgetattr(STDIN_FILENO, &t_old) != 0){
121
 
    perror("tcgetattr");
 
120
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
122
121
    return EXIT_FAILURE;
123
122
  }
124
123
  
131
130
    perror("sigaction");
132
131
    return EXIT_FAILURE;
133
132
  }
134
 
  if(old_action.sa_handler != SIG_IGN){
 
133
  if (old_action.sa_handler != SIG_IGN){
135
134
    ret = sigaction(SIGINT, &new_action, NULL);
136
135
    if(ret == -1){
137
136
      perror("sigaction");
143
142
    perror("sigaction");
144
143
    return EXIT_FAILURE;
145
144
  }
146
 
  if(old_action.sa_handler != SIG_IGN){
 
145
  if (old_action.sa_handler != SIG_IGN){
147
146
    ret = sigaction(SIGHUP, &new_action, NULL);
148
147
    if(ret == -1){
149
148
      perror("sigaction");
155
154
    perror("sigaction");
156
155
    return EXIT_FAILURE;
157
156
  }
158
 
  if(old_action.sa_handler != SIG_IGN){
 
157
  if (old_action.sa_handler != SIG_IGN){
159
158
    ret = sigaction(SIGTERM, &new_action, NULL);
160
159
    if(ret == -1){
161
160
      perror("sigaction");
164
163
  }
165
164
  
166
165
  
167
 
  if(debug){
 
166
  if (debug){
168
167
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
169
168
  }
170
169
  
171
170
  t_new = t_old;
172
171
  t_new.c_lflag &= ~ECHO;
173
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
 
172
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
174
173
    perror("tcsetattr-echo");
175
174
    return EXIT_FAILURE;
176
175
  }
177
176
 
178
 
  if(debug){
 
177
  if (debug){
179
178
    fprintf(stderr, "Waiting for input from stdin \n");
180
179
  }
181
180
  while(true){
182
 
    if(quit_now){
183
 
      if(debug){
184
 
        fprintf(stderr, "Interrupted by signal, exiting.\n");
185
 
      }
 
181
    if (quit_now){
186
182
      status = EXIT_FAILURE;
187
183
      break;
188
184
    }
189
185
 
190
186
    if(prefix){
191
 
      fprintf(stderr, "%s ", prefix);
192
 
    }
193
 
    {
194
 
      const char *cryptsource = getenv("cryptsource");
195
 
      const char *crypttarget = getenv("crypttarget");
196
 
      const char *const prompt
197
 
        = "Enter passphrase to unlock the disk";      
198
 
      if(cryptsource == NULL){
199
 
        if(crypttarget == NULL){
200
 
          fprintf(stderr, "%s: ", prompt);
201
 
        } else {
202
 
          fprintf(stderr, "%s (%s): ", prompt, crypttarget);
203
 
        }
204
 
      } else {
205
 
        if(crypttarget == NULL){
206
 
          fprintf(stderr, "%s %s: ", prompt, cryptsource);
207
 
        } else {
208
 
          fprintf(stderr, "%s %s (%s): ", prompt, cryptsource,
209
 
                  crypttarget);
210
 
        }
211
 
      }
212
 
    }
 
187
      fprintf(stderr, "%s Password: ", prefix);
 
188
    } else {
 
189
      fprintf(stderr, "Password: ");
 
190
    }      
213
191
    ret = getline(&buffer, &n, stdin);
214
 
    if(ret > 0){
 
192
    if (ret > 0){
 
193
      fprintf(stdout, "%s", buffer);
215
194
      status = EXIT_SUCCESS;
216
 
      /* Make n = data size instead of allocated buffer size */
217
 
      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
 
      size_t written = 0;
224
 
      while(written < n){
225
 
        ret = write(STDOUT_FILENO, buffer + written, n - written);
226
 
        if(ret < 0){
227
 
          perror("write");
228
 
          status = EXIT_FAILURE;
229
 
          break;
230
 
        }
231
 
        written += (size_t)ret;
232
 
      }
233
195
      break;
234
196
    }
235
 
    if(ret < 0){
236
 
      if(errno != EINTR and not feof(stdin)){
 
197
    if (ret < 0){
 
198
      if (errno != EINTR and not feof(stdin)){
237
199
        perror("getline");
238
200
        status = EXIT_FAILURE;
239
201
        break;
242
204
    /* if(ret == 0), then the only sensible thing to do is to retry to
243
205
       read from stdin */
244
206
    fputc('\n', stderr);
245
 
    if(debug and quit_now == 0){
246
 
      /* If quit_now is nonzero, we were interrupted by a signal, and
247
 
         will print that later, so no need to show this too. */
248
 
      fprintf(stderr, "getline() returned 0, retrying.\n");
249
 
    }
250
207
  }
251
208
  
252
 
  free(buffer);
253
 
  
254
 
  if(debug){
 
209
  if (debug){
255
210
    fprintf(stderr, "Restoring terminal attributes\n");
256
211
  }
257
 
  if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
 
212
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
258
213
    perror("tcsetattr+echo");
259
214
  }
260
215
  
261
 
  if(debug){
262
 
    fprintf(stderr, "%s is exiting with status %d\n", argv[0],
263
 
            status);
264
 
  }
265
 
  if(status == EXIT_SUCCESS){
266
 
    fputc('\n', stderr);
 
216
  if (debug){
 
217
    fprintf(stderr, "%s is exiting\n", argv[0]);
267
218
  }
268
219
  
269
220
  return status;