/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/passprompt.c

  • Committer: Björn Påhlsson
  • Date: 2008-07-20 02:52:20 UTC
  • Revision ID: belorn@braxen-20080720025220-r5u0388uy9iu23h6
Added following support:
Pluginbased client handler
rewritten Mandos client
       Avahi instead of udp server discovery
       openpgp encrypted key support
Passprompt stand alone application for direct console input
Added logging for Mandos server

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
 
 
25
1
#define _GNU_SOURCE             /* getline() */
26
 
 
 
2
#define _FORTIFY_SOURCE 2
27
3
#include <termios.h>            /* struct termios, tcsetattr(),
28
4
                                   TCSAFLUSH, tcgetattr(), ECHO */
29
5
#include <unistd.h>             /* struct termios, tcsetattr(),
33
9
                                   sigaction, sigemptyset(),
34
10
                                   sigaction(), sigaddset(), SIGINT,
35
11
                                   SIGQUIT, SIGHUP, SIGTERM */
36
 
#include <stddef.h>             /* NULL, size_t, ssize_t */
 
12
#include <stddef.h>             /* NULL, size_t */
37
13
#include <sys/types.h>          /* ssize_t */
38
 
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
39
 
                                   getopt_long */
 
14
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE */
40
15
#include <stdio.h>              /* fprintf(), stderr, getline(),
41
16
                                   stdin, feof(), perror(), fputc(),
42
 
                                   stdout, getopt_long */
 
17
                                   stdout */
43
18
#include <errno.h>              /* errno, EINVAL */
44
19
#include <iso646.h>             /* or, not */
45
20
#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 */
52
21
 
53
22
volatile bool quit_now = false;
54
 
bool debug = false;
55
 
const char *argp_program_version = "passprompt 1.0";
56
 
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
57
23
 
58
 
static void termination_handler(__attribute__((unused))int signum){
 
24
void termination_handler(int signum){
59
25
  quit_now = true;
60
26
}
61
27
 
62
28
int main(int argc, char **argv){
63
 
  ssize_t ret;
 
29
  ssize_t ret = -1;
64
30
  size_t n;
65
31
  struct termios t_new, t_old;
66
32
  char *buffer = NULL;
67
 
  char *prefix = NULL;
68
33
  int status = EXIT_SUCCESS;
69
34
  struct sigaction old_action,
70
35
    new_action = { .sa_handler = termination_handler,
71
36
                   .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, "Unkown 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
 
  }
119
37
  
120
38
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
121
39
    return EXIT_FAILURE;
123
41
  
124
42
  sigemptyset(&new_action.sa_mask);
125
43
  sigaddset(&new_action.sa_mask, SIGINT);
 
44
  sigaddset(&new_action.sa_mask, SIGQUIT);
126
45
  sigaddset(&new_action.sa_mask, SIGHUP);
127
46
  sigaddset(&new_action.sa_mask, SIGTERM);
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
 
  }
 
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);
169
59
  
170
60
  t_new = t_old;
171
61
  t_new.c_lflag &= ~ECHO;
173
63
    perror("tcsetattr-echo");
174
64
    return EXIT_FAILURE;
175
65
  }
176
 
 
177
 
  if (debug){
178
 
    fprintf(stderr, "Waiting for input from stdin \n");
179
 
  }
 
66
  
180
67
  while(true){
181
68
    if (quit_now){
182
69
      status = EXIT_FAILURE;
183
70
      break;
184
71
    }
185
 
 
186
 
    if(prefix){
187
 
      fprintf(stderr, "%s Password: ", prefix);
188
 
    } else {
189
 
      fprintf(stderr, "Password: ");
190
 
    }      
 
72
    fprintf(stderr, "Password: ");
191
73
    ret = getline(&buffer, &n, stdin);
192
74
    if (ret > 0){
193
75
      fprintf(stdout, "%s", buffer);
194
76
      status = EXIT_SUCCESS;
195
77
      break;
196
78
    }
 
79
    // ret == 0 makes no other sence than to retry to read from stdin
197
80
    if (ret < 0){
198
81
      if (errno != EINTR and not feof(stdin)){
199
82
        perror("getline");
201
84
        break;
202
85
      }
203
86
    }
204
 
    /* if(ret == 0), then the only sensible thing to do is to retry to
205
 
       read from stdin */
206
87
    fputc('\n', stderr);
207
88
  }
208
 
  
209
 
  if (debug){
210
 
    fprintf(stderr, "Restoring terminal attributes\n");
211
 
  }
 
89
 
212
90
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
213
91
    perror("tcsetattr+echo");
214
92
  }
215
93
  
216
 
  if (debug){
217
 
    fprintf(stderr, "%s is exiting\n", argv[0]);
218
 
  }
219
 
  
220
94
  return status;
221
95
}