/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: 2016-03-17 20:40:55 UTC
  • Revision ID: teddy@recompile.se-20160317204055-bhsh5xsidq7w5cxu
Client: Fix plymouth agent; broken since 1.7.2.

Fix an very old memory bug in the plymouth agent (which has been
present since its apperance in version 1.2), but which was only
recently detected at run time due to the new -fsanitize=address
compile- time flag, which has been used since version 1.7.2.  This
detection of a memory access violation causes the program to abort,
making the Plymouth graphical boot system unable to accept interactive
input of passwords when using the Mandos client.

* plugins.d/plymouth.c (exec_and_wait): Fix memory allocation bug when
  allocating new_argv.  Also tolerate a zero-length argv.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Askpass-FIFO - Read a password from a FIFO and output it
4
4
 * 
5
 
 * Copyright © 2008,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 Björn Påhlsson
 
5
 * Copyright © 2008-2016 Teddy Hogeborn
 
6
 * Copyright © 2008-2016 Björn Påhlsson
7
7
 * 
8
8
 * This program is free software: you can redistribute it and/or
9
9
 * modify it under the terms of the GNU General Public License as
19
19
 * along with this program.  If not, see
20
20
 * <http://www.gnu.org/licenses/>.
21
21
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
22
 * Contact the authors at <mandos@recompile.se>.
23
23
 */
24
24
 
25
25
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY() */
26
 
#include <sys/types.h>          /* ssize_t */
 
26
#include <sys/types.h>          /* uid_t, gid_t, ssize_t */
27
27
#include <sys/stat.h>           /* mkfifo(), S_IRUSR, S_IWUSR */
28
28
#include <iso646.h>             /* and */
29
29
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
31
31
                                   ENOENT, EEXIST, EFAULT, EMFILE,
32
32
                                   ENFILE, ENOMEM, EBADF, EINVAL, EIO,
33
33
                                   EISDIR, EFBIG */
34
 
#include <stdio.h>              /* perror() */
 
34
#include <error.h>              /* error() */
 
35
#include <stdio.h>              /* fprintf(), vfprintf(),
 
36
                                   vasprintf() */
35
37
#include <stdlib.h>             /* EXIT_FAILURE, NULL, size_t, free(),
36
38
                                   realloc(), EXIT_SUCCESS */
37
39
#include <fcntl.h>              /* open(), O_RDONLY */
39
41
                                   STDOUT_FILENO */
40
42
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
41
43
                                   EX_UNAVAILABLE, EX_IOERR */
42
 
 
 
44
#include <string.h>             /* strerror() */
 
45
#include <stdarg.h>             /* va_list, va_start(), ... */
 
46
 
 
47
uid_t uid = 65534;
 
48
gid_t gid = 65534;
 
49
 
 
50
/* Function to use when printing errors */
 
51
__attribute__((format (gnu_printf, 3, 4)))
 
52
void error_plus(int status, int errnum, const char *formatstring,
 
53
                ...){
 
54
  va_list ap;
 
55
  char *text;
 
56
  int ret;
 
57
  
 
58
  va_start(ap, formatstring);
 
59
  ret = vasprintf(&text, formatstring, ap);
 
60
  if(ret == -1){
 
61
    fprintf(stderr, "Mandos plugin %s: ",
 
62
            program_invocation_short_name);
 
63
    vfprintf(stderr, formatstring, ap);
 
64
    fprintf(stderr, ": ");
 
65
    fprintf(stderr, "%s\n", strerror(errnum));
 
66
    error(status, errno, "vasprintf while printing error");
 
67
    return;
 
68
  }
 
69
  fprintf(stderr, "Mandos plugin ");
 
70
  error(status, errnum, "%s", text);
 
71
  free(text);
 
72
}
43
73
 
44
74
int main(__attribute__((unused))int argc,
45
75
         __attribute__((unused))char **argv){
46
76
  int ret = 0;
47
77
  ssize_t sret;
48
78
  
 
79
  uid = getuid();
 
80
  gid = getgid();
 
81
  
49
82
  /* Create FIFO */
50
83
  const char passfifo[] = "/lib/cryptsetup/passfifo";
51
84
  ret = mkfifo(passfifo, S_IRUSR | S_IWUSR);
52
85
  if(ret == -1){
53
86
    int e = errno;
54
 
    perror("mkfifo");
55
87
    switch(e){
56
88
    case EACCES:
57
89
    case ENOTDIR:
58
90
    case ELOOP:
59
 
      return EX_OSFILE;
 
91
      error_plus(EX_OSFILE, errno, "mkfifo");
60
92
    case ENAMETOOLONG:
61
93
    case ENOSPC:
62
94
    case EROFS:
63
95
    default:
64
 
      return EX_OSERR;
 
96
      error_plus(EX_OSERR, errno, "mkfifo");
65
97
    case ENOENT:
66
 
      return EX_UNAVAILABLE;    /* no "/lib/cryptsetup"? */
 
98
      /* no "/lib/cryptsetup"? */
 
99
      error_plus(EX_UNAVAILABLE, errno, "mkfifo");
67
100
    case EEXIST:
68
101
      break;                    /* not an error */
69
102
    }
73
106
  int fifo_fd = open(passfifo, O_RDONLY);
74
107
  if(fifo_fd == -1){
75
108
    int e = errno;
76
 
    perror("open");
 
109
    error_plus(0, errno, "open");
77
110
    switch(e){
78
111
    case EACCES:
79
112
    case ENOENT:
91
124
    }
92
125
  }
93
126
  
 
127
  /* Lower group privileges  */
 
128
  if(setgid(gid) == -1){
 
129
    error_plus(0, errno, "setgid");
 
130
  }
 
131
  
 
132
  /* Lower user privileges */
 
133
  if(setuid(uid) == -1){
 
134
    error_plus(0, errno, "setuid");
 
135
  }
 
136
  
94
137
  /* Read from FIFO */
95
138
  char *buf = NULL;
96
139
  size_t buf_len = 0;
101
144
      if(buf_len + blocksize > buf_allocated){
102
145
        char *tmp = realloc(buf, buf_allocated + blocksize);
103
146
        if(tmp == NULL){
104
 
          perror("realloc");
 
147
          error_plus(0, errno, "realloc");
105
148
          free(buf);
106
149
          return EX_OSERR;
107
150
        }
113
156
        int e = errno;
114
157
        free(buf);
115
158
        errno = e;
116
 
        perror("read");
 
159
        error_plus(0, errno, "read");
117
160
        switch(e){
118
161
        case EBADF:
119
162
        case EFAULT:
141
184
      int e = errno;
142
185
      free(buf);
143
186
      errno = e;
144
 
      perror("write");
 
187
      error_plus(0, errno, "write");
145
188
      switch(e){
146
189
      case EBADF:
147
190
      case EFAULT:
161
204
  ret = close(STDOUT_FILENO);
162
205
  if(ret == -1){
163
206
    int e = errno;
164
 
    perror("close");
 
207
    error_plus(0, errno, "close");
165
208
    switch(e){
166
209
    case EBADF:
167
210
      return EX_OSFILE;