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