/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to plugins.d/splashy.c

  • Committer: Björn Påhlsson
  • Date: 2008-07-20 02:52:20 UTC
  • Revision ID: belorn@braxen-20080720025220-r5u0388uy9iu23h6
Added following support:
Pluginbased client handler
rewritten Mandos client
       Avahi instead of udp server discovery
       openpgp encrypted key support
Passprompt stand alone application for direct console input
Added logging for Mandos server

Show diffs side-by-side

added added

removed removed

Lines of Context:
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));
90
 
      if((sret == ((ssize_t)sizeof(exe_target)-1))
91
 
         and (memcmp(splashy_name, exe_target,
92
 
                     sizeof(exe_target)-1) == 0)){
93
 
        splashy_pid = pid;
94
 
        break;
95
 
      }
96
 
    }
97
 
    closedir(proc_dir);
98
 
  }
99
 
  if(splashy_pid == 0){
100
 
    free(prompt);
101
 
    return EXIT_FAILURE;
102
 
  }
103
 
  
104
 
  /* Set up the signal handler */
105
 
  {
106
 
    struct sigaction old_action,
107
 
      new_action = { .sa_handler = termination_handler,
108
 
                     .sa_flags = 0 };
109
 
    sigemptyset(&new_action.sa_mask);
110
 
    sigaddset(&new_action.sa_mask, SIGINT);
111
 
    sigaddset(&new_action.sa_mask, SIGHUP);
112
 
    sigaddset(&new_action.sa_mask, SIGTERM);
113
 
    ret = sigaction(SIGINT, NULL, &old_action);
114
 
    if(ret == -1){
115
 
      perror("sigaction");
116
 
      free(prompt);
117
 
      return EXIT_FAILURE;
118
 
    }
119
 
    if (old_action.sa_handler != SIG_IGN){
120
 
      ret = sigaction(SIGINT, &new_action, NULL);
121
 
      if(ret == -1){
122
 
        perror("sigaction");
123
 
        free(prompt);
124
 
        return EXIT_FAILURE;
125
 
      }
126
 
    }
127
 
    ret = sigaction(SIGHUP, NULL, &old_action);
128
 
    if(ret == -1){
129
 
      perror("sigaction");
130
 
      free(prompt);
131
 
      return EXIT_FAILURE;
132
 
    }
133
 
    if (old_action.sa_handler != SIG_IGN){
134
 
      ret = sigaction(SIGHUP, &new_action, NULL);
135
 
      if(ret == -1){
136
 
        perror("sigaction");
137
 
        free(prompt);
138
 
        return EXIT_FAILURE;
139
 
      }
140
 
    }
141
 
    ret = sigaction(SIGTERM, NULL, &old_action);
142
 
    if(ret == -1){
143
 
      perror("sigaction");
144
 
      free(prompt);
145
 
      return EXIT_FAILURE;
146
 
    }
147
 
    if (old_action.sa_handler != SIG_IGN){
148
 
      ret = sigaction(SIGTERM, &new_action, NULL);
149
 
      if(ret == -1){
150
 
        perror("sigaction");
151
 
        free(prompt);
152
 
        return EXIT_FAILURE;
153
 
      }
154
 
    }
155
 
  }
156
 
  
157
 
  /* Fork off the splashy command to prompt for password */
158
 
  pid_t splashy_command_pid = 0;
159
 
  if(not interrupted_by_signal){
160
 
    splashy_command_pid = fork();
161
 
    if(splashy_command_pid == -1){
162
 
      if(not interrupted_by_signal){
163
 
        perror("fork");
164
 
      }
165
 
      return EXIT_FAILURE;
166
 
    }
167
 
    /* Child */
168
 
    if(splashy_command_pid == 0){
169
 
      const char splashy_command[] = "/sbin/splashy_update";
170
 
      ret = execl(splashy_command, splashy_command, prompt,
171
 
                  (char *)NULL);
172
 
      if(not interrupted_by_signal and errno != ENOENT){
173
 
        /* Don't report "File not found", since splashy might not be
174
 
           installed. */
175
 
        perror("execl");
176
 
      }
177
 
      free(prompt);
178
 
      return EXIT_FAILURE;
179
 
    }
180
 
  }
181
 
  
182
 
  /* Parent */
183
 
  free(prompt);
184
 
  
185
 
  /* Wait for command to complete */
186
 
  int status;
187
 
  while(not interrupted_by_signal){
188
 
    waitpid(splashy_command_pid, &status, 0);
189
 
    if(not interrupted_by_signal
190
 
       and WIFEXITED(status) and WEXITSTATUS(status)==0){
191
 
      return EXIT_SUCCESS;
192
 
    }
193
 
  }
194
 
  kill(splashy_pid, SIGTERM);
195
 
  if(interrupted_by_signal){
196
 
    kill(splashy_command_pid, SIGTERM);
197
 
  }
198
 
 
199
 
  pid_t new_splashy_pid = fork();
200
 
  if(new_splashy_pid == 0){
201
 
    while(kill(splashy_pid, 0)){
202
 
      sleep(2);
203
 
      kill(splashy_pid, SIGKILL);
204
 
      sleep(1);
205
 
    }
206
 
    ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace our stdout */
207
 
    if(ret == -1){
208
 
      perror("dup2");
209
 
      _exit(EXIT_FAILURE);
210
 
    }
211
 
    execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
212
 
  }
213
 
  
214
 
  return EXIT_FAILURE;
215
 
}