/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/askpass-fifo.c

  • Committer: Teddy Hogeborn
  • Date: 2011-12-31 20:07:11 UTC
  • mfrom: (535.1.9 wireless-network-hook)
  • Revision ID: teddy@recompile.se-20111231200711-6dli3r8drftem57r
Merge new wireless network hook.  Fix bridge network hook to use
hardware addresses instead of interface names.  Implement and document
new "CONNECT" environment variable for network hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  -*- coding: utf-8 -*- */
 
2
/*
 
3
 * Askpass-FIFO - Read a password from a FIFO and output it
 
4
 * 
 
5
 * Copyright © 2008-2011 Teddy Hogeborn
 
6
 * Copyright © 2008-2011 Björn Påhlsson
 
7
 * 
 
8
 * This program is free software: you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License as
 
10
 * published by the Free Software Foundation, either version 3 of the
 
11
 * License, or (at your option) any later version.
 
12
 * 
 
13
 * This program is distributed in the hope that it will be useful, but
 
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * General Public License for more details.
 
17
 * 
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program.  If not, see
 
20
 * <http://www.gnu.org/licenses/>.
 
21
 * 
 
22
 * Contact the authors at <mandos@recompile.se>.
 
23
 */
 
24
 
 
25
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY() */
 
26
#include <sys/types.h>          /* ssize_t */
 
27
#include <sys/stat.h>           /* mkfifo(), S_IRUSR, S_IWUSR */
 
28
#include <iso646.h>             /* and */
 
29
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
 
30
                                   ENAMETOOLONG, ENOSPC, EROFS,
 
31
                                   ENOENT, EEXIST, EFAULT, EMFILE,
 
32
                                   ENFILE, ENOMEM, EBADF, EINVAL, EIO,
 
33
                                   EISDIR, EFBIG */
 
34
#include <error.h>              /* error() */
 
35
#include <stdio.h>              /* fprintf(), vfprintf(),
 
36
                                   vasprintf() */
 
37
#include <stdlib.h>             /* EXIT_FAILURE, NULL, size_t, free(),
 
38
                                   realloc(), EXIT_SUCCESS */
 
39
#include <fcntl.h>              /* open(), O_RDONLY */
 
40
#include <unistd.h>             /* read(), close(), write(),
 
41
                                   STDOUT_FILENO */
 
42
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
 
43
                                   EX_UNAVAILABLE, EX_IOERR */
 
44
#include <string.h>             /* strerror() */
 
45
#include <stdarg.h>             /* va_list, va_start(), ... */
 
46
 
 
47
 
 
48
/* Function to use when printing errors */
 
49
__attribute__((format (gnu_printf, 3, 4)))
 
50
void error_plus(int status, int errnum, const char *formatstring,
 
51
                ...){
 
52
  va_list ap;
 
53
  char *text;
 
54
  int ret;
 
55
  
 
56
  va_start(ap, formatstring);
 
57
  ret = vasprintf(&text, formatstring, ap);
 
58
  if (ret == -1){
 
59
    fprintf(stderr, "Mandos plugin %s: ",
 
60
            program_invocation_short_name);
 
61
    vfprintf(stderr, formatstring, ap);
 
62
    fprintf(stderr, ": ");
 
63
    fprintf(stderr, "%s\n", strerror(errnum));
 
64
    error(status, errno, "vasprintf while printing error");
 
65
    return;
 
66
  }
 
67
  fprintf(stderr, "Mandos plugin ");
 
68
  error(status, errnum, "%s", text);
 
69
  free(text);
 
70
}
 
71
 
 
72
int main(__attribute__((unused))int argc,
 
73
         __attribute__((unused))char **argv){
 
74
  int ret = 0;
 
75
  ssize_t sret;
 
76
  
 
77
  /* Create FIFO */
 
78
  const char passfifo[] = "/lib/cryptsetup/passfifo";
 
79
  ret = mkfifo(passfifo, S_IRUSR | S_IWUSR);
 
80
  if(ret == -1){
 
81
    int e = errno;
 
82
    switch(e){
 
83
    case EACCES:
 
84
    case ENOTDIR:
 
85
    case ELOOP:
 
86
      error_plus(EX_OSFILE, errno, "mkfifo");
 
87
    case ENAMETOOLONG:
 
88
    case ENOSPC:
 
89
    case EROFS:
 
90
    default:
 
91
      error_plus(EX_OSERR, errno, "mkfifo");
 
92
    case ENOENT:
 
93
      /* no "/lib/cryptsetup"? */
 
94
      error_plus(EX_UNAVAILABLE, errno, "mkfifo");
 
95
    case EEXIST:
 
96
      break;                    /* not an error */
 
97
    }
 
98
  }
 
99
  
 
100
  /* Open FIFO */
 
101
  int fifo_fd = open(passfifo, O_RDONLY);
 
102
  if(fifo_fd == -1){
 
103
    int e = errno;
 
104
    error_plus(0, errno, "open");
 
105
    switch(e){
 
106
    case EACCES:
 
107
    case ENOENT:
 
108
    case EFAULT:
 
109
      return EX_UNAVAILABLE;
 
110
    case ENAMETOOLONG:
 
111
    case EMFILE:
 
112
    case ENFILE:
 
113
    case ENOMEM:
 
114
    default:
 
115
      return EX_OSERR;
 
116
    case ENOTDIR:
 
117
    case ELOOP:
 
118
      return EX_OSFILE;
 
119
    }
 
120
  }
 
121
  
 
122
  /* Read from FIFO */
 
123
  char *buf = NULL;
 
124
  size_t buf_len = 0;
 
125
  {
 
126
    size_t buf_allocated = 0;
 
127
    const size_t blocksize = 1024;
 
128
    do {
 
129
      if(buf_len + blocksize > buf_allocated){
 
130
        char *tmp = realloc(buf, buf_allocated + blocksize);
 
131
        if(tmp == NULL){
 
132
          error_plus(0, errno, "realloc");
 
133
          free(buf);
 
134
          return EX_OSERR;
 
135
        }
 
136
        buf = tmp;
 
137
        buf_allocated += blocksize;
 
138
      }
 
139
      sret = read(fifo_fd, buf + buf_len, buf_allocated - buf_len);
 
140
      if(sret == -1){
 
141
        int e = errno;
 
142
        free(buf);
 
143
        errno = e;
 
144
        error_plus(0, errno, "read");
 
145
        switch(e){
 
146
        case EBADF:
 
147
        case EFAULT:
 
148
        case EINVAL:
 
149
        default:
 
150
          return EX_OSERR;
 
151
        case EIO:
 
152
          return EX_IOERR;
 
153
        case EISDIR:
 
154
          return EX_UNAVAILABLE;
 
155
        }
 
156
      }
 
157
      buf_len += (size_t)sret;
 
158
    } while(sret != 0);
 
159
  }
 
160
  
 
161
  /* Close FIFO */
 
162
  close(fifo_fd);
 
163
  
 
164
  /* Print password to stdout */
 
165
  size_t written = 0;
 
166
  while(written < buf_len){
 
167
    sret = write(STDOUT_FILENO, buf + written, buf_len - written);
 
168
    if(sret == -1){
 
169
      int e = errno;
 
170
      free(buf);
 
171
      errno = e;
 
172
      error_plus(0, errno, "write");
 
173
      switch(e){
 
174
      case EBADF:
 
175
      case EFAULT:
 
176
      case EINVAL:
 
177
        return EX_OSFILE;
 
178
      case EFBIG:
 
179
      case EIO:
 
180
      case ENOSPC:
 
181
      default:
 
182
        return EX_IOERR;
 
183
      }
 
184
    }
 
185
    written += (size_t)sret;
 
186
  }
 
187
  free(buf);
 
188
  
 
189
  ret = close(STDOUT_FILENO);
 
190
  if(ret == -1){
 
191
    int e = errno;
 
192
    error_plus(0, errno, "close");
 
193
    switch(e){
 
194
    case EBADF:
 
195
      return EX_OSFILE;
 
196
    case EIO:
 
197
    default:
 
198
      return EX_IOERR;
 
199
    }
 
200
  }
 
201
  return EXIT_SUCCESS;
 
202
}