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