/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-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
/*  -*- coding: utf-8 -*- */
 
2
/*
 
3
 * Passprompt - Read a password from the terminal and print it
 
4
 *
 
5
 * Copyright © 2007-2008 Teddy Hogeborn & Björn Påhlsson
 
6
 * 
 
7
 * This program is free software: you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License as
 
9
 * published by the Free Software Foundation, either version 3 of the
 
10
 * License, or (at your option) any later version.
 
11
 * 
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * General Public License for more details.
 
16
 * 
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program.  If not, see
 
19
 * <http://www.gnu.org/licenses/>.
 
20
 * 
 
21
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
22
 * <https://www.fukt.bsnet.se/~teddy/>.
 
23
 */
 
24
 
1
25
#define _GNU_SOURCE             /* getline() */
2
 
#define _FORTIFY_SOURCE 2
 
26
 
3
27
#include <termios.h>            /* struct termios, tcsetattr(),
4
28
                                   TCSAFLUSH, tcgetattr(), ECHO */
5
29
#include <unistd.h>             /* struct termios, tcsetattr(),
9
33
                                   sigaction, sigemptyset(),
10
34
                                   sigaction(), sigaddset(), SIGINT,
11
35
                                   SIGQUIT, SIGHUP, SIGTERM */
12
 
#include <stddef.h>             /* NULL, size_t */
 
36
#include <stddef.h>             /* NULL, size_t, ssize_t */
13
37
#include <sys/types.h>          /* ssize_t */
14
 
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE */
 
38
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
 
39
                                   getopt_long */
15
40
#include <stdio.h>              /* fprintf(), stderr, getline(),
16
41
                                   stdin, feof(), perror(), fputc(),
17
 
                                   stdout */
 
42
                                   stdout, getopt_long */
18
43
#include <errno.h>              /* errno, EINVAL */
19
44
#include <iso646.h>             /* or, not */
20
45
#include <stdbool.h>            /* bool, false, true */
 
46
#include <string.h>             /* strlen, rindex, strncmp, strcmp */
 
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 */
21
52
 
22
53
volatile bool quit_now = false;
 
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>";
23
57
 
24
 
void termination_handler(int signum){
 
58
static void termination_handler(__attribute__((unused))int signum){
25
59
  quit_now = true;
26
60
}
27
61
 
28
62
int main(int argc, char **argv){
29
 
  ssize_t ret = -1;
 
63
  ssize_t ret;
30
64
  size_t n;
31
65
  struct termios t_new, t_old;
32
66
  char *buffer = NULL;
 
67
  char *prefix = NULL;
33
68
  int status = EXIT_SUCCESS;
34
69
  struct sigaction old_action,
35
70
    new_action = { .sa_handler = termination_handler,
36
71
                   .sa_flags = 0 };
 
72
  {
 
73
    struct argp_option options[] = {
 
74
      { .name = "prefix", .key = 'p',
 
75
        .arg = "PREFIX", .flags = 0,
 
76
        .doc = "Prefix used before the passprompt", .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;
 
101
    }
 
102
  
 
103
    struct argp argp = { .options = options, .parser = parse_opt,
 
104
                         .args_doc = "",
 
105
                         .doc = "Mandos Passprompt -- Provides a passprompt" };
 
106
    ret = argp_parse (&argp, argc, argv, 0, 0, NULL);
 
107
    if (ret == ARGP_ERR_UNKNOWN){
 
108
      fprintf(stderr, "Unknown error while parsing arguments\n");
 
109
      return EXIT_FAILURE;
 
110
    }
 
111
  }
 
112
    
 
113
  if (debug){
 
114
    fprintf(stderr, "Starting %s\n", argv[0]);
 
115
  }
 
116
  if (debug){
 
117
    fprintf(stderr, "Storing current terminal attributes\n");
 
118
  }
37
119
  
38
120
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
39
121
    return EXIT_FAILURE;
41
123
  
42
124
  sigemptyset(&new_action.sa_mask);
43
125
  sigaddset(&new_action.sa_mask, SIGINT);
44
 
  sigaddset(&new_action.sa_mask, SIGQUIT);
45
126
  sigaddset(&new_action.sa_mask, SIGHUP);
46
127
  sigaddset(&new_action.sa_mask, SIGTERM);
47
 
  sigaction(SIGINT, NULL, &old_action);
48
 
  if (old_action.sa_handler != SIG_IGN)
49
 
    sigaction(SIGINT, &new_action, NULL);
50
 
  sigaction(SIGQUIT, NULL, &old_action);
51
 
  if (old_action.sa_handler != SIG_IGN)
52
 
    sigaction(SIGQUIT, &new_action, NULL);
53
 
  sigaction(SIGHUP, NULL, &old_action);
54
 
  if (old_action.sa_handler != SIG_IGN)
55
 
    sigaction(SIGHUP, &new_action, NULL);
56
 
  sigaction(SIGTERM, NULL, &old_action);
57
 
  if (old_action.sa_handler != SIG_IGN)
58
 
    sigaction(SIGTERM, &new_action, NULL);
 
128
  ret = sigaction(SIGINT, NULL, &old_action);
 
129
  if(ret == -1){
 
130
    perror("sigaction");
 
131
    return EXIT_FAILURE;
 
132
  }
 
133
  if (old_action.sa_handler != SIG_IGN){
 
134
    ret = sigaction(SIGINT, &new_action, NULL);
 
135
    if(ret == -1){
 
136
      perror("sigaction");
 
137
      return EXIT_FAILURE;
 
138
    }
 
139
  }
 
140
  ret = sigaction(SIGHUP, NULL, &old_action);
 
141
  if(ret == -1){
 
142
    perror("sigaction");
 
143
    return EXIT_FAILURE;
 
144
  }
 
145
  if (old_action.sa_handler != SIG_IGN){
 
146
    ret = sigaction(SIGHUP, &new_action, NULL);
 
147
    if(ret == -1){
 
148
      perror("sigaction");
 
149
      return EXIT_FAILURE;
 
150
    }
 
151
  }
 
152
  ret = sigaction(SIGTERM, NULL, &old_action);
 
153
  if(ret == -1){
 
154
    perror("sigaction");
 
155
    return EXIT_FAILURE;
 
156
  }
 
157
  if (old_action.sa_handler != SIG_IGN){
 
158
    ret = sigaction(SIGTERM, &new_action, NULL);
 
159
    if(ret == -1){
 
160
      perror("sigaction");
 
161
      return EXIT_FAILURE;
 
162
    }
 
163
  }
 
164
  
 
165
  
 
166
  if (debug){
 
167
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
 
168
  }
59
169
  
60
170
  t_new = t_old;
61
171
  t_new.c_lflag &= ~ECHO;
63
173
    perror("tcsetattr-echo");
64
174
    return EXIT_FAILURE;
65
175
  }
66
 
  
 
176
 
 
177
  if (debug){
 
178
    fprintf(stderr, "Waiting for input from stdin \n");
 
179
  }
67
180
  while(true){
68
181
    if (quit_now){
69
182
      status = EXIT_FAILURE;
70
183
      break;
71
184
    }
72
 
    fprintf(stderr, "Password: ");
 
185
 
 
186
    if(prefix){
 
187
      fprintf(stderr, "%s Password: ", prefix);
 
188
    } else {
 
189
      fprintf(stderr, "Password: ");
 
190
    }      
73
191
    ret = getline(&buffer, &n, stdin);
74
192
    if (ret > 0){
75
193
      fprintf(stdout, "%s", buffer);
76
194
      status = EXIT_SUCCESS;
77
195
      break;
78
196
    }
79
 
    // ret == 0 makes no other sence than to retry to read from stdin
80
197
    if (ret < 0){
81
198
      if (errno != EINTR and not feof(stdin)){
82
199
        perror("getline");
84
201
        break;
85
202
      }
86
203
    }
 
204
    /* if(ret == 0), then the only sensible thing to do is to retry to
 
205
       read from stdin */
87
206
    fputc('\n', stderr);
88
207
  }
89
 
 
 
208
  
 
209
  if (debug){
 
210
    fprintf(stderr, "Restoring terminal attributes\n");
 
211
  }
90
212
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
91
213
    perror("tcsetattr+echo");
92
214
  }
93
215
  
 
216
  if (debug){
 
217
    fprintf(stderr, "%s is exiting\n", argv[0]);
 
218
  }
 
219
  
94
220
  return status;
95
221
}