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