/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
1
#define _GNU_SOURCE		/* asprintf() */
2
#include <signal.h>		/* sig_atomic_t, struct sigaction,
3
				   sigemptyset(), sigaddset(),
4
				   sigaction, SIGINT, SIG_IGN, SIGHUP,
5
				   SIGTERM, kill(), SIGKILL */
6
#include <stddef.h>		/* NULL */
7
#include <stdlib.h>		/* getenv() */
8
#include <stdio.h>		/* asprintf(), perror() */
9
#include <stdlib.h>		/* EXIT_FAILURE, EXIT_SUCCESS,
10
				   strtoul(), free() */
11
#include <sys/types.h>		/* pid_t, DIR, struct dirent,
12
				   ssize_t */
13
#include <dirent.h>		/* opendir(), readdir(), closedir() */
14
#include <unistd.h>		/* readlink(), fork(), execl(),
15
				   _exit */
16
#include <string.h>		/* memcmp() */
17
#include <iso646.h>		/* and */
18
#include <errno.h>		/* errno */
19
#include <sys/wait.h>		/* waitpid(), WIFEXITED(),
20
				   WEXITSTATUS() */
21
22
sig_atomic_t interrupted_by_signal = 0;
23
24
static void termination_handler(__attribute__((unused))int signum){
25
  interrupted_by_signal = 1;
26
}
27
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
28
int main(__attribute__((unused))int argc,
29
	 __attribute__((unused))char **argv){
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
30
  int ret = 0;
31
  
32
  /* Create prompt string */
33
  char *prompt = NULL;
34
  {
35
    const char *const cryptsource = getenv("cryptsource");
36
    const char *const crypttarget = getenv("crypttarget");
37
    const char *const prompt_start = "getpass "
38
      "Enter passphrase to unlock the disk";
39
    
40
    if(cryptsource == NULL){
41
      if(crypttarget == NULL){
42
	ret = asprintf(&prompt, "%s: ", prompt_start);
43
      } else {
44
	ret = asprintf(&prompt, "%s (%s): ", prompt_start,
45
		       crypttarget);
46
      }
47
    } else {
48
      if(crypttarget == NULL){
49
	ret = asprintf(&prompt, "%s %s: ", prompt_start, cryptsource);
50
      } else {
51
	ret = asprintf(&prompt, "%s %s (%s): ", prompt_start,
52
		       cryptsource, crypttarget);
53
      }
54
    }
55
    if(ret == -1){
56
      return EXIT_FAILURE;
57
    }
58
  }
59
  
60
  /* Find splashy process */
61
  pid_t splashy_pid = 0;
62
  {
63
    const char splashy_name[] = "/sbin/splashy";
64
    DIR *proc_dir = opendir("/proc");
65
    if(proc_dir == NULL){
66
      free(prompt);
67
      perror("opendir");
68
      return EXIT_FAILURE;
69
    }
70
    for(struct dirent *proc_ent = readdir(proc_dir);
71
	proc_ent != NULL;
72
	proc_ent = readdir(proc_dir)){
73
      pid_t pid = (pid_t) strtoul(proc_ent->d_name, NULL, 10);
74
      if(pid == 0){
75
	/* Not a process */
76
	continue;
77
      }
78
      /* Find the executable name by doing readlink() on the
79
	 /proc/<pid>/exe link */
80
      char exe_target[sizeof(splashy_name)];
208 by Teddy Hogeborn
* Makefile (PLUGINS): Added "plugins.d/usplash".
81
      ssize_t sret;
82
      {
83
	char *exe_link;
84
	ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
85
	if(ret == -1){
86
	  perror("asprintf");
87
	  free(prompt);
88
	  closedir(proc_dir);
89
	  return EXIT_FAILURE;
90
	}
91
	sret = readlink(exe_link, exe_target, sizeof(exe_target));
92
	free(exe_link);
93
      }
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
94
      if((sret == ((ssize_t)sizeof(exe_target)-1))
95
	 and (memcmp(splashy_name, exe_target,
96
		     sizeof(exe_target)-1) == 0)){
97
	splashy_pid = pid;
98
	break;
99
      }
100
    }
101
    closedir(proc_dir);
102
  }
103
  if(splashy_pid == 0){
104
    free(prompt);
105
    return EXIT_FAILURE;
106
  }
107
  
108
  /* Set up the signal handler */
109
  {
110
    struct sigaction old_action,
111
      new_action = { .sa_handler = termination_handler,
112
		     .sa_flags = 0 };
113
    sigemptyset(&new_action.sa_mask);
114
    sigaddset(&new_action.sa_mask, SIGINT);
115
    sigaddset(&new_action.sa_mask, SIGHUP);
116
    sigaddset(&new_action.sa_mask, SIGTERM);
117
    ret = sigaction(SIGINT, NULL, &old_action);
118
    if(ret == -1){
119
      perror("sigaction");
120
      free(prompt);
121
      return EXIT_FAILURE;
122
    }
123
    if (old_action.sa_handler != SIG_IGN){
124
      ret = sigaction(SIGINT, &new_action, NULL);
125
      if(ret == -1){
126
	perror("sigaction");
127
	free(prompt);
128
	return EXIT_FAILURE;
129
      }
130
    }
131
    ret = sigaction(SIGHUP, NULL, &old_action);
132
    if(ret == -1){
133
      perror("sigaction");
134
      free(prompt);
135
      return EXIT_FAILURE;
136
    }
137
    if (old_action.sa_handler != SIG_IGN){
138
      ret = sigaction(SIGHUP, &new_action, NULL);
139
      if(ret == -1){
140
	perror("sigaction");
141
	free(prompt);
142
	return EXIT_FAILURE;
143
      }
144
    }
145
    ret = sigaction(SIGTERM, NULL, &old_action);
146
    if(ret == -1){
147
      perror("sigaction");
148
      free(prompt);
149
      return EXIT_FAILURE;
150
    }
151
    if (old_action.sa_handler != SIG_IGN){
152
      ret = sigaction(SIGTERM, &new_action, NULL);
153
      if(ret == -1){
154
	perror("sigaction");
155
	free(prompt);
156
	return EXIT_FAILURE;
157
      }
158
    }
159
  }
160
  
161
  /* Fork off the splashy command to prompt for password */
162
  pid_t splashy_command_pid = 0;
163
  if(not interrupted_by_signal){
164
    splashy_command_pid = fork();
165
    if(splashy_command_pid == -1){
166
      if(not interrupted_by_signal){
167
	perror("fork");
168
      }
169
      return EXIT_FAILURE;
170
    }
171
    /* Child */
172
    if(splashy_command_pid == 0){
173
      const char splashy_command[] = "/sbin/splashy_update";
174
      ret = execl(splashy_command, splashy_command, prompt,
175
		  (char *)NULL);
176
      if(not interrupted_by_signal and errno != ENOENT){
177
	/* Don't report "File not found", since splashy might not be
178
	   installed. */
179
	perror("execl");
180
      }
181
      free(prompt);
182
      return EXIT_FAILURE;
183
    }
184
  }
185
  
186
  /* Parent */
187
  free(prompt);
188
  
189
  /* Wait for command to complete */
190
  int status;
191
  while(not interrupted_by_signal){
192
    waitpid(splashy_command_pid, &status, 0);
193
    if(not interrupted_by_signal
194
       and WIFEXITED(status) and WEXITSTATUS(status)==0){
195
      return EXIT_SUCCESS;
196
    }
197
  }
198
  kill(splashy_pid, SIGTERM);
199
  if(interrupted_by_signal){
200
    kill(splashy_command_pid, SIGTERM);
201
  }
207 by Teddy Hogeborn
* plugins.d/splashy.c (main): Bug fix: free "exe_link".
202
  
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
203
  pid_t new_splashy_pid = fork();
204
  if(new_splashy_pid == 0){
207 by Teddy Hogeborn
* plugins.d/splashy.c (main): Bug fix: free "exe_link".
205
    /* Child; will become new splashy process */
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
206
    while(kill(splashy_pid, 0)){
207
      sleep(2);
208
      kill(splashy_pid, SIGKILL);
209
      sleep(1);
210
    }
211
    ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace our stdout */
212
    if(ret == -1){
213
      perror("dup2");
214
      _exit(EXIT_FAILURE);
215
    }
216
    execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
217
  }
218
  
219
  return EXIT_FAILURE;
220
}