/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: Björn Påhlsson
  • Date: 2008-01-18 21:18:26 UTC
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: belorn@legolas-20080118211826-5rbwo54l4bwim5x2
Client:
        [Working version in initrd for booting]
        Added #ifdef DEBUG statements through out the program
        Added support to keep bouth tcp and udp up at the same time
        Catching several more error return codes that was unchecked.
        Starts the Network interface during startup.
        Added support for entering password on console
        Added error handling, like looping until a password has been received.
        Added cleanup handling so console state is always restored
                
removed:
        Old server.cpp [see next version]
        Test certificates

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
 
#define _GNU_SOURCE             /* getline() */
26
 
 
27
 
#include <termios.h>            /* struct termios, tcsetattr(),
28
 
                                   TCSAFLUSH, tcgetattr(), ECHO */
29
 
#include <unistd.h>             /* struct termios, tcsetattr(),
30
 
                                   STDIN_FILENO, TCSAFLUSH,
31
 
                                   tcgetattr(), ECHO */
32
 
#include <signal.h>             /* sig_atomic_t, raise(), struct
33
 
                                   sigaction, sigemptyset(),
34
 
                                   sigaction(), sigaddset(), SIGINT,
35
 
                                   SIGQUIT, SIGHUP, SIGTERM */
36
 
#include <stddef.h>             /* NULL, size_t */
37
 
#include <sys/types.h>          /* ssize_t */
38
 
#include <stdlib.h>             /* EXIT_SUCCESS, EXIT_FAILURE,
39
 
                                   getopt_long */
40
 
#include <stdio.h>              /* fprintf(), stderr, getline(),
41
 
                                   stdin, feof(), perror(), fputc(),
42
 
                                   stdout, getopt_long */
43
 
#include <errno.h>              /* errno, EINVAL */
44
 
#include <iso646.h>             /* or, not */
45
 
#include <stdbool.h>            /* bool, false, true */
46
 
#include <string.h>             /* strlen, rindex, strncmp, strcmp */
47
 
#include <argp.h>               /* struct argp_option,
48
 
                                   struct argp_state, struct argp,
49
 
                                   argp_parse() */
50
 
 
51
 
volatile bool quit_now = false;
52
 
bool debug = false;
53
 
const char *argp_program_version = "passprompt 0.9";
54
 
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
55
 
 
56
 
static void termination_handler(__attribute__((unused))int signum){
57
 
  quit_now = true;
58
 
}
59
 
 
60
 
int main(int argc, char **argv){
61
 
  ssize_t ret;
62
 
  size_t n;
63
 
  struct termios t_new, t_old;
64
 
  char *buffer = NULL;
65
 
  char *prefix = NULL;
66
 
  int status = EXIT_SUCCESS;
67
 
  struct sigaction old_action,
68
 
    new_action = { .sa_handler = termination_handler,
69
 
                   .sa_flags = 0 };
70
 
  {
71
 
    struct argp_option options[] = {
72
 
      { .name = "prefix", .key = 'p',
73
 
        .arg = "PREFIX", .flags = 0,
74
 
        .doc = "Prefix used before the passprompt", .group = 2 },
75
 
      { .name = "debug", .key = 128,
76
 
        .doc = "Debug mode", .group = 3 },
77
 
      { .name = NULL }
78
 
    };
79
 
  
80
 
    error_t parse_opt (int key, char *arg, struct argp_state *state) {
81
 
      /* Get the INPUT argument from `argp_parse', which we know is a
82
 
         pointer to our plugin list pointer. */
83
 
      switch (key) {
84
 
      case 'p':
85
 
        prefix = arg;
86
 
        break;
87
 
      case 128:
88
 
        debug = true;
89
 
        break;
90
 
      case ARGP_KEY_ARG:
91
 
        argp_usage (state);
92
 
        break;
93
 
      case ARGP_KEY_END:
94
 
        break;
95
 
      default:
96
 
        return ARGP_ERR_UNKNOWN;
97
 
      }
98
 
      return 0;
99
 
    }
100
 
  
101
 
    struct argp argp = { .options = options, .parser = parse_opt,
102
 
                         .args_doc = "",
103
 
                         .doc = "Mandos Passprompt -- Provides a passprompt" };
104
 
    argp_parse (&argp, argc, argv, 0, 0, NULL);
105
 
  }
106
 
    
107
 
  if (debug){
108
 
    fprintf(stderr, "Starting %s\n", argv[0]);
109
 
  }
110
 
  if (debug){
111
 
    fprintf(stderr, "Storing current terminal attributes\n");
112
 
  }
113
 
  
114
 
  if (tcgetattr(STDIN_FILENO, &t_old) != 0){
115
 
    return EXIT_FAILURE;
116
 
  }
117
 
  
118
 
  sigemptyset(&new_action.sa_mask);
119
 
  sigaddset(&new_action.sa_mask, SIGINT);
120
 
  sigaddset(&new_action.sa_mask, SIGHUP);
121
 
  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
 
 
132
 
  
133
 
  if (debug){
134
 
    fprintf(stderr, "Removing echo flag from terminal attributes\n");
135
 
  }
136
 
  
137
 
  t_new = t_old;
138
 
  t_new.c_lflag &= ~ECHO;
139
 
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
140
 
    perror("tcsetattr-echo");
141
 
    return EXIT_FAILURE;
142
 
  }
143
 
 
144
 
  if (debug){
145
 
    fprintf(stderr, "Waiting for input from stdin \n");
146
 
  }
147
 
  while(true){
148
 
    if (quit_now){
149
 
      status = EXIT_FAILURE;
150
 
      break;
151
 
    }
152
 
 
153
 
    if(prefix){
154
 
      fprintf(stderr, "%s Password: ", prefix);
155
 
    } else {
156
 
      fprintf(stderr, "Password: ");
157
 
    }      
158
 
    ret = getline(&buffer, &n, stdin);
159
 
    if (ret > 0){
160
 
      fprintf(stdout, "%s", buffer);
161
 
      status = EXIT_SUCCESS;
162
 
      break;
163
 
    }
164
 
    if (ret < 0){
165
 
      if (errno != EINTR and not feof(stdin)){
166
 
        perror("getline");
167
 
        status = EXIT_FAILURE;
168
 
        break;
169
 
      }
170
 
    }
171
 
    /* if(ret == 0), then the only sensible thing to do is to retry to
172
 
       read from stdin */
173
 
    fputc('\n', stderr);
174
 
  }
175
 
  
176
 
  if (debug){
177
 
    fprintf(stderr, "Restoring terminal attributes\n");
178
 
  }
179
 
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
180
 
    perror("tcsetattr+echo");
181
 
  }
182
 
  
183
 
  if (debug){
184
 
    fprintf(stderr, "%s is exiting\n", argv[0]);
185
 
  }
186
 
  
187
 
  return status;
188
 
}