/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
237.1.2 by Teddy Hogeborn
Further steps towards a D-Bus server interface, plus minor syntax
1
/*  -*- coding: utf-8 -*- */
2
/*
261 by Teddy Hogeborn
* plugins.d/askpass-fifo.c: Fix name in header.
3
 * Usplash - Read a password from usplash and output it
237.1.2 by Teddy Hogeborn
Further steps towards a D-Bus server interface, plus minor syntax
4
 * 
466 by Teddy Hogeborn
Update copyright year to "2011" wherever appropriate.
5
 * Copyright © 2008-2011 Teddy Hogeborn
6
 * Copyright © 2008-2011 Björn Påhlsson
237.1.2 by Teddy Hogeborn
Further steps towards a D-Bus server interface, plus minor syntax
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
 * 
363 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
22
 * Contact the authors at <mandos@fukt.bsnet.se>.
237.1.2 by Teddy Hogeborn
Further steps towards a D-Bus server interface, plus minor syntax
23
 */
24
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
25
#define _GNU_SOURCE		/* asprintf(), TEMP_FAILURE_RETRY() */
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
26
#include <signal.h>		/* sig_atomic_t, struct sigaction,
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
27
				   sigemptyset(), sigaddset(), SIGINT,
28
				   SIGHUP, SIGTERM, sigaction(),
29
				   SIG_IGN, kill(), SIGKILL */
30
#include <stdbool.h>		/* bool, false, true */
31
#include <fcntl.h>		/* open(), O_WRONLY, O_RDONLY */
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
32
#include <iso646.h>		/* and, or, not*/
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
33
#include <errno.h>		/* errno, EINTR */
24.1.155 by Björn Påhlsson
mandos server: Added debuglevel that adjust at what level information
34
#include <error.h>
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
35
#include <sys/types.h>		/* size_t, ssize_t, pid_t, DIR, struct
36
				   dirent */
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
37
#include <stddef.h>		/* NULL */
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
38
#include <string.h>		/* strlen(), memcmp(), strerror() */
39
#include <stdio.h>		/* asprintf(), vasprintf(), vprintf(), fprintf() */
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
40
#include <unistd.h>		/* close(), write(), readlink(),
41
				   read(), STDOUT_FILENO, sleep(),
42
				   fork(), setuid(), geteuid(),
43
				   setsid(), chdir(), dup2(),
44
				   STDERR_FILENO, execv() */
264 by Teddy Hogeborn
* plugin-runner.c (main): Use "sscanf" instead of "strtol"; using the
45
#include <stdlib.h>		/* free(), EXIT_FAILURE, realloc(),
24.1.151 by Björn Påhlsson
New graphical boot supported: Plymouth
46
				   EXIT_SUCCESS, malloc(), _exit(),
47
				   getenv() */
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
48
#include <dirent.h>		/* opendir(), readdir(), closedir() */
311 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
49
#include <inttypes.h>		/* intmax_t, strtoimax() */
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
50
#include <sys/stat.h>		/* struct stat, lstat(), S_ISLNK */
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
51
#include <sysexits.h>		/* EX_OSERR, EX_UNAVAILABLE */
431 by teddy at bsnet
* debian/watch: Also watch for "*.tar.xz" files.
52
#include <argz.h>		/* argz_count(), argz_extract() */
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
53
#include <stdarg.h>		/* va_list, va_start(), ... */
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
54
55
sig_atomic_t interrupted_by_signal = 0;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
56
int signal_received;
57
const char usplash_name[] = "/sbin/usplash";
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
58
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
59
/* Function to use when printing errors */
60
void error_plus(int status, int errnum, const char *formatstring, ...){
61
  va_list ap;
62
  char *text;
63
  int ret;
64
  
65
  va_start(ap, formatstring);
66
  ret = vasprintf(&text, formatstring, ap);
67
  if (ret == -1){
68
    fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name);
69
    vfprintf(stderr, formatstring, ap);
70
    fprintf(stderr, ": ");
71
    fprintf(stderr, "%s\n", strerror(errnum));
72
    error(status, errno, "vasprintf while printing error");
73
    return;
74
  }
75
  fprintf(stderr, "Mandos plugin ");
76
  error(status, errnum, "%s", text);
77
  free(text);
78
}
79
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
80
static void termination_handler(int signum){
81
  if(interrupted_by_signal){
82
    return;
83
  }
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
84
  interrupted_by_signal = 1;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
85
  signal_received = signum;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
86
}
87
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
88
static bool usplash_write(int *fifo_fd_r,
89
			  const char *cmd, const char *arg){
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
90
  /* 
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
91
   * usplash_write(&fd, "TIMEOUT", "15") will write "TIMEOUT 15\0"
92
   * usplash_write(&fd, "PULSATE", NULL) will write "PULSATE\0"
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
93
   * SEE ALSO
94
   *         usplash_write(8)
95
   */
96
  int ret;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
97
  if(*fifo_fd_r == -1){
98
    ret = open("/dev/.initramfs/usplash_fifo", O_WRONLY);
99
    if(ret == -1){
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
100
      return false;
101
    }
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
102
    *fifo_fd_r = ret;
103
  }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
104
  
105
  const char *cmd_line;
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
106
  size_t cmd_line_len;
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
107
  char *cmd_line_alloc = NULL;
108
  if(arg == NULL){
109
    cmd_line = cmd;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
110
    cmd_line_len = strlen(cmd) + 1;
363 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
111
  } else {
112
    do {
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
113
      ret = asprintf(&cmd_line_alloc, "%s %s", cmd, arg);
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
114
      if(ret == -1){
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
115
	int e = errno;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
116
	TEMP_FAILURE_RETRY(close(*fifo_fd_r));
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
117
	errno = e;
118
	return false;
119
      }
363 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
120
    } while(ret == -1);
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
121
    cmd_line = cmd_line_alloc;
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
122
    cmd_line_len = (size_t)ret + 1;
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
123
  }
124
  
125
  size_t written = 0;
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
126
  ssize_t sret = 0;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
127
  while(written < cmd_line_len){
128
    sret = write(*fifo_fd_r, cmd_line + written,
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
129
		 cmd_line_len - written);
130
    if(sret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
131
      int e = errno;
132
      TEMP_FAILURE_RETRY(close(*fifo_fd_r));
133
      free(cmd_line_alloc);
134
      errno = e;
135
      return false;
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
136
    }
257.1.2 by Mooie
Fixed warnings in the 64 bit build. Added explicit cast to int for
137
    written += (size_t)sret;
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
138
  }
139
  free(cmd_line_alloc);
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
140
  
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
141
  return true;
142
}
143
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
144
/* Create prompt string */
145
char *makeprompt(void){
146
  int ret = 0;
147
  char *prompt;
148
  const char *const cryptsource = getenv("cryptsource");
149
  const char *const crypttarget = getenv("crypttarget");
150
  const char prompt_start[] = "Enter passphrase to unlock the disk";
151
  
152
  if(cryptsource == NULL){
153
    if(crypttarget == NULL){
154
      ret = asprintf(&prompt, "%s: ", prompt_start);
155
    } else {
156
      ret = asprintf(&prompt, "%s (%s): ", prompt_start,
157
		     crypttarget);
158
    }
159
  } else {
160
    if(crypttarget == NULL){
161
      ret = asprintf(&prompt, "%s %s: ", prompt_start, cryptsource);
162
    } else {
163
      ret = asprintf(&prompt, "%s %s (%s): ", prompt_start,
164
		     cryptsource, crypttarget);
165
    }
166
  }
167
  if(ret == -1){
168
    return NULL;
169
  }
170
  return prompt;
171
}
172
173
pid_t find_usplash(char **cmdline_r, size_t *cmdline_len_r){
174
  int ret = 0;
175
  ssize_t sret = 0;
176
  char *cmdline = NULL;
177
  size_t cmdline_len = 0;
178
  DIR *proc_dir = opendir("/proc");
179
  if(proc_dir == NULL){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
180
    error_plus(0, errno, "opendir");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
181
    return -1;
182
  }
183
  errno = 0;
184
  for(struct dirent *proc_ent = readdir(proc_dir);
185
      proc_ent != NULL;
186
      proc_ent = readdir(proc_dir)){
187
    pid_t pid;
188
    {
189
      intmax_t tmpmax;
190
      char *tmp;
191
      tmpmax = strtoimax(proc_ent->d_name, &tmp, 10);
192
      if(errno != 0 or tmp == proc_ent->d_name or *tmp != '\0'
193
	 or tmpmax != (pid_t)tmpmax){
194
	/* Not a process */
195
	errno = 0;
196
	continue;
197
      }
198
      pid = (pid_t)tmpmax;
199
    }
200
    /* Find the executable name by doing readlink() on the
201
       /proc/<pid>/exe link */
202
    char exe_target[sizeof(usplash_name)];
203
    {
204
      /* create file name string */
205
      char *exe_link;
206
      ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
207
      if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
208
	error_plus(0, errno, "asprintf");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
209
	goto fail_find_usplash;
210
      }
211
      
212
      /* Check that it refers to a symlink owned by root:root */
213
      struct stat exe_stat;
214
      ret = lstat(exe_link, &exe_stat);
215
      if(ret == -1){
216
	if(errno == ENOENT){
217
	  free(exe_link);
218
	  continue;
219
	}
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
220
	error_plus(0, errno, "lstat");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
221
	free(exe_link);
222
	goto fail_find_usplash;
223
      }
224
      if(not S_ISLNK(exe_stat.st_mode)
225
	 or exe_stat.st_uid != 0
226
	 or exe_stat.st_gid != 0){
227
	free(exe_link);
228
	continue;
229
      }
230
	
231
      sret = readlink(exe_link, exe_target, sizeof(exe_target));
232
      free(exe_link);
233
    }
234
    /* Compare executable name */
235
    if((sret != ((ssize_t)sizeof(exe_target)-1))
236
       or (memcmp(usplash_name, exe_target,
237
		  sizeof(exe_target)-1) != 0)){
238
      /* Not it */
239
      continue;
240
    }
241
    /* Found usplash */
242
    /* Read and save the command line of usplash in "cmdline" */
243
    {
244
      /* Open /proc/<pid>/cmdline  */
245
      int cl_fd;
246
      {
247
	char *cmdline_filename;
248
	ret = asprintf(&cmdline_filename, "/proc/%s/cmdline",
249
		       proc_ent->d_name);
250
	if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
251
	  error_plus(0, errno, "asprintf");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
252
	  goto fail_find_usplash;
253
	}
254
	cl_fd = open(cmdline_filename, O_RDONLY);
255
	free(cmdline_filename);
256
	if(cl_fd == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
257
	  error_plus(0, errno, "open");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
258
	  goto fail_find_usplash;
259
	}
260
      }
261
      size_t cmdline_allocated = 0;
262
      char *tmp;
263
      const size_t blocksize = 1024;
264
      do {
265
	/* Allocate more space? */
266
	if(cmdline_len + blocksize > cmdline_allocated){
267
	  tmp = realloc(cmdline, cmdline_allocated + blocksize);
268
	  if(tmp == NULL){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
269
	    error_plus(0, errno, "realloc");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
270
	    close(cl_fd);
271
	    goto fail_find_usplash;
272
	  }
273
	  cmdline = tmp;
274
	  cmdline_allocated += blocksize;
275
	}
276
	/* Read data */
277
	sret = read(cl_fd, cmdline + cmdline_len,
278
		    cmdline_allocated - cmdline_len);
279
	if(sret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
280
	  error_plus(0, errno, "read");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
281
	  close(cl_fd);
282
	  goto fail_find_usplash;
283
	}
284
	cmdline_len += (size_t)sret;
285
      } while(sret != 0);
286
      ret = close(cl_fd);
287
      if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
288
	error_plus(0, errno, "close");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
289
	goto fail_find_usplash;
290
      }
291
    }
292
    /* Close directory */
293
    ret = closedir(proc_dir);
294
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
295
      error_plus(0, errno, "closedir");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
296
      goto fail_find_usplash;
297
    }
298
    /* Success */
299
    *cmdline_r = cmdline;
300
    *cmdline_len_r = cmdline_len;
301
    return pid;
302
  }
303
  
304
 fail_find_usplash:
305
  
306
  free(cmdline);
307
  if(proc_dir != NULL){
308
    int e = errno;
309
    closedir(proc_dir);
310
    errno = e;
311
  }
312
  return 0;
313
}
314
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
315
int main(__attribute__((unused))int argc,
316
	 __attribute__((unused))char **argv){
317
  int ret = 0;
318
  ssize_t sret;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
319
  int fifo_fd = -1;
320
  int outfifo_fd = -1;
321
  char *buf = NULL;
322
  size_t buf_len = 0;
323
  pid_t usplash_pid = -1;
324
  bool usplash_accessed = false;
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
325
  int status = EXIT_FAILURE;	/* Default failure exit status */
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
326
  
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
327
  char *prompt = makeprompt();
328
  if(prompt == NULL){
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
329
    status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
330
    goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
331
  }
332
  
333
  /* Find usplash process */
334
  char *cmdline = NULL;
335
  size_t cmdline_len = 0;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
336
  usplash_pid = find_usplash(&cmdline, &cmdline_len);
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
337
  if(usplash_pid == 0){
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
338
    status = EX_UNAVAILABLE;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
339
    goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
340
  }
341
  
342
  /* Set up the signal handler */
343
  {
344
    struct sigaction old_action,
345
      new_action = { .sa_handler = termination_handler,
346
		     .sa_flags = 0 };
347
    sigemptyset(&new_action.sa_mask);
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
348
    ret = sigaddset(&new_action.sa_mask, SIGINT);
349
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
350
      error_plus(0, errno, "sigaddset");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
351
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
352
      goto failure;
353
    }
354
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
355
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
356
      error_plus(0, errno, "sigaddset");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
357
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
358
      goto failure;
359
    }
360
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
361
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
362
      error_plus(0, errno, "sigaddset");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
363
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
364
      goto failure;
365
    }
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
366
    ret = sigaction(SIGINT, NULL, &old_action);
367
    if(ret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
368
      if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
369
	error_plus(0, errno, "sigaction");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
370
	status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
371
      }
372
      goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
373
    }
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
374
    if(old_action.sa_handler != SIG_IGN){
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
375
      ret = sigaction(SIGINT, &new_action, NULL);
376
      if(ret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
377
	if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
378
	  error_plus(0, errno, "sigaction");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
379
	  status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
380
	}
381
	goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
382
      }
383
    }
384
    ret = sigaction(SIGHUP, NULL, &old_action);
385
    if(ret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
386
      if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
387
	error_plus(0, errno, "sigaction");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
388
	status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
389
      }
390
      goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
391
    }
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
392
    if(old_action.sa_handler != SIG_IGN){
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
393
      ret = sigaction(SIGHUP, &new_action, NULL);
394
      if(ret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
395
	if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
396
	  error_plus(0, errno, "sigaction");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
397
	  status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
398
	}
399
	goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
400
      }
401
    }
402
    ret = sigaction(SIGTERM, NULL, &old_action);
403
    if(ret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
404
      if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
405
	error_plus(0, errno, "sigaction");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
406
	status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
407
      }
408
      goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
409
    }
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
410
    if(old_action.sa_handler != SIG_IGN){
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
411
      ret = sigaction(SIGTERM, &new_action, NULL);
412
      if(ret == -1){
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
413
	if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
414
	  error_plus(0, errno, "sigaction");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
415
	  status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
416
	}
417
	goto failure;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
418
      }
419
    }
420
  }
421
  
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
422
  usplash_accessed = true;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
423
  /* Write command to FIFO */
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
424
  if(not usplash_write(&fifo_fd, "TIMEOUT", "0")){
425
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
426
      error_plus(0, errno, "usplash_write");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
427
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
428
    }
429
    goto failure;
430
  }
431
  
432
  if(interrupted_by_signal){
433
    goto failure;
434
  }
435
  
436
  if(not usplash_write(&fifo_fd, "INPUTQUIET", prompt)){
437
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
438
      error_plus(0, errno, "usplash_write");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
439
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
440
    }
441
    goto failure;
442
  }
443
  
444
  if(interrupted_by_signal){
445
    goto failure;
446
  }
447
  
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
448
  free(prompt);
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
449
  prompt = NULL;
450
  
451
  /* Read reply from usplash */
452
  /* Open FIFO */
453
  outfifo_fd = open("/dev/.initramfs/usplash_outfifo", O_RDONLY);
454
  if(outfifo_fd == -1){
455
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
456
      error_plus(0, errno, "open");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
457
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
458
    }
459
    goto failure;
460
  }
461
  
462
  if(interrupted_by_signal){
463
    goto failure;
464
  }
465
  
466
  /* Read from FIFO */
467
  size_t buf_allocated = 0;
468
  const size_t blocksize = 1024;
469
  do {
470
    /* Allocate more space */
471
    if(buf_len + blocksize > buf_allocated){
472
      char *tmp = realloc(buf, buf_allocated + blocksize);
473
      if(tmp == NULL){
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
474
	if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
475
	  error_plus(0, errno, "realloc");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
476
	  status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
477
	}
478
	goto failure;
479
      }
480
      buf = tmp;
481
      buf_allocated += blocksize;
482
    }
483
    sret = read(outfifo_fd, buf + buf_len,
484
		buf_allocated - buf_len);
485
    if(sret == -1){
486
      if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
487
	error_plus(0, errno, "read");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
488
	status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
489
      }
490
      TEMP_FAILURE_RETRY(close(outfifo_fd));
491
      goto failure;
492
    }
493
    if(interrupted_by_signal){
494
      break;
495
    }
496
    
497
    buf_len += (size_t)sret;
498
  } while(sret != 0);
499
  ret = close(outfifo_fd);
500
  if(ret == -1){
501
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
502
      error_plus(0, errno, "close");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
503
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
504
    }
505
    goto failure;
506
  }
507
  outfifo_fd = -1;
508
  
509
  if(interrupted_by_signal){
510
    goto failure;
511
  }
512
  
513
  if(not usplash_write(&fifo_fd, "TIMEOUT", "15")){
514
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
515
      error_plus(0, errno, "usplash_write");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
516
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
517
    }
518
    goto failure;
519
  }
520
  
521
  if(interrupted_by_signal){
522
    goto failure;
523
  }
524
  
525
  ret = close(fifo_fd);
526
  if(ret == -1){
527
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
528
      error_plus(0, errno, "close");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
529
      status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
530
    }
531
    goto failure;
532
  }
533
  fifo_fd = -1;
534
  
535
  /* Print password to stdout */
536
  size_t written = 0;
537
  while(written < buf_len){
538
    do {
539
      sret = write(STDOUT_FILENO, buf + written, buf_len - written);
540
      if(sret == -1){
541
	if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
542
	  error_plus(0, errno, "write");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
543
	  status = EX_OSERR;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
544
	}
545
	goto failure;
546
      }
547
    } while(sret == -1);
548
    
549
    if(interrupted_by_signal){
550
      goto failure;
551
    }
552
    written += (size_t)sret;
553
  }
554
  free(buf);
555
  buf = NULL;
556
  
557
  if(interrupted_by_signal){
558
    goto failure;
559
  }
560
  
561
  free(cmdline);
562
  return EXIT_SUCCESS;
563
  
564
 failure:
565
  
566
  free(buf);
567
  
568
  free(prompt);
569
  
570
  /* If usplash was never accessed, we can stop now */
571
  if(not usplash_accessed){
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
572
    return status;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
573
  }
574
  
575
  /* Close FIFO */
576
  if(fifo_fd != -1){
577
    ret = (int)TEMP_FAILURE_RETRY(close(fifo_fd));
578
    if(ret == -1 and errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
579
      error_plus(0, errno, "close");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
580
    }
581
    fifo_fd = -1;
582
  }
583
  
584
  /* Close output FIFO */
585
  if(outfifo_fd != -1){
586
    ret = (int)TEMP_FAILURE_RETRY(close(outfifo_fd));
587
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
588
      error_plus(0, errno, "close");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
589
    }
590
  }
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
591
  
431 by teddy at bsnet
* debian/watch: Also watch for "*.tar.xz" files.
592
  /* Create argv for new usplash*/
432 by teddy at bsnet
* plugins.d/usplash.c (main): BUG FIX: allocate space for the final
593
  char **cmdline_argv = malloc((argz_count(cmdline, cmdline_len) + 1)
431 by teddy at bsnet
* debian/watch: Also watch for "*.tar.xz" files.
594
			       * sizeof(char *)); /* Count args */
595
  if(cmdline_argv == NULL){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
596
    error_plus(0, errno, "malloc");
431 by teddy at bsnet
* debian/watch: Also watch for "*.tar.xz" files.
597
    return status;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
598
  }
431 by teddy at bsnet
* debian/watch: Also watch for "*.tar.xz" files.
599
  argz_extract(cmdline, cmdline_len, cmdline_argv); /* Create argv */
600
  
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
601
  /* Kill old usplash */
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
602
  kill(usplash_pid, SIGTERM);
603
  sleep(2);
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
604
  while(kill(usplash_pid, 0) == 0){
605
    kill(usplash_pid, SIGKILL);
606
    sleep(1);
607
  }
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
608
  
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
609
  pid_t new_usplash_pid = fork();
610
  if(new_usplash_pid == 0){
611
    /* Child; will become new usplash process */
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
612
    
613
    /* Make the effective user ID (root) the only user ID instead of
265 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix; do not accept a "d" character after
614
       the real user ID (_mandos) */
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
615
    ret = setuid(geteuid());
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
616
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
617
      error_plus(0, errno, "setuid");
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
618
    }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
619
    
620
    setsid();
621
    ret = chdir("/");
24.1.148 by Björn Påhlsson
half working on-demand password and approved code
622
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
623
      error_plus(0, errno, "chdir");
24.1.148 by Björn Påhlsson
half working on-demand password and approved code
624
      _exit(EX_OSERR);
625
    }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
626
/*     if(fork() != 0){ */
627
/*       _exit(EXIT_SUCCESS); */
628
/*     } */
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
629
    ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace our stdout */
630
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
631
      error_plus(0, errno, "dup2");
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
632
      _exit(EX_OSERR);
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
633
    }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
634
    
635
    execv(usplash_name, cmdline_argv);
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
636
    if(not interrupted_by_signal){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
637
      error_plus(0, errno, "execv");
223 by Teddy Hogeborn
* .bzrignore (plugins.d/askpass-fifo): Added.
638
    }
213 by Teddy Hogeborn
* plugins.d/usplash.c (main): Bug fix: Do not free "cmdline" too soon.
639
    free(cmdline);
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
640
    free(cmdline_argv);
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
641
    _exit(EX_OSERR);
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
642
  }
213 by Teddy Hogeborn
* plugins.d/usplash.c (main): Bug fix: Do not free "cmdline" too soon.
643
  free(cmdline);
212 by Teddy Hogeborn
* plugins.d/usplash.c (usplash_write): Move "cmd_line_len" up.
644
  free(cmdline_argv);
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
645
  sleep(2);
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
646
  if(not usplash_write(&fifo_fd, "PULSATE", NULL)){
647
    if(errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
648
      error_plus(0, errno, "usplash_write");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
649
    }
650
  }
651
  
652
  /* Close FIFO (again) */
373 by Teddy Hogeborn
* plugins.d/usplash.c (main): Bug fix: only close FIFO if opened.
653
  if(fifo_fd != -1){
654
    ret = (int)TEMP_FAILURE_RETRY(close(fifo_fd));
655
    if(ret == -1 and errno != EINTR){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
656
      error_plus(0, errno, "close");
373 by Teddy Hogeborn
* plugins.d/usplash.c (main): Bug fix: only close FIFO if opened.
657
    }
658
    fifo_fd = -1;
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
659
  }
660
  
661
  if(interrupted_by_signal){
662
    struct sigaction signal_action = { .sa_handler = SIG_DFL };
663
    sigemptyset(&signal_action.sa_mask);
664
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
665
					    &signal_action, NULL));
666
    if(ret == -1){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
667
      error_plus(0, errno, "sigaction");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
668
    }
669
    do {
670
      ret = raise(signal_received);
671
    } while(ret != 0 and errno == EINTR);
672
    if(ret != 0){
24.1.174 by Björn Påhlsson
* Makefile (CFLAGS): Added "-lrt" to include real time library.
673
      error_plus(0, errno, "raise");
369 by Teddy Hogeborn
* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
674
      abort();
675
    }
676
    TEMP_FAILURE_RETRY(pause());
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
677
  }
678
  
396 by Teddy Hogeborn
* plugins.d/usplash.c: Use <sysexits.h> exit codes.
679
  return status;
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
680
}