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