/mandos/trunk

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

« 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
 
      free(exe_link);
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
 
  }
199
 
  
200
 
  pid_t new_splashy_pid = fork();
201
 
  if(new_splashy_pid == 0){
202
 
    /* Child; will become new splashy process */
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
 
}