~siretart/cryptsetup/debian

« back to all changes in this revision

Viewing changes to debian/passdev.c

  • Committer: Reinhard Tartler
  • Date: 2008-06-13 19:35:34 UTC
  • Revision ID: siretart@tauware.de-20080613193534-oeqhbxi7r0q4lk51
import cryptsetup_1.0.6-2.dsc

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _BSD_SOURCE
 
2
#include <stdio.h>
 
3
#include <stdlib.h>
 
4
#include <stdarg.h>
 
5
#include <stdbool.h>
 
6
#include <unistd.h>
 
7
#include <sys/types.h>
 
8
#include <sys/stat.h>
 
9
#include <sys/wait.h>
 
10
#include <string.h>
 
11
#include <fcntl.h>
 
12
#include <sys/mount.h>
 
13
 
 
14
static bool do_debug = false;
 
15
 
 
16
static void
 
17
debug(const char *fmt, ...)
 
18
{
 
19
        va_list ap;
 
20
 
 
21
        if (!do_debug)
 
22
                return;
 
23
        va_start(ap, fmt);
 
24
        vfprintf(stderr, fmt, ap);
 
25
        va_end(ap);
 
26
}
 
27
 
 
28
static bool
 
29
do_mount(const char *device, const char *dir)
 
30
{
 
31
        pid_t pid;
 
32
        pid_t wpid;
 
33
        int status;
 
34
        char *fstypes[] = { "ext3", "ext2", "vfat", "reiserfs", "xfs", "isofs", "udf" };
 
35
        int fsindex;
 
36
 
 
37
        if (!device || !dir)
 
38
                return false;
 
39
 
 
40
        for (fsindex = 0;
 
41
             fsindex < (sizeof(fstypes) / sizeof(fstypes[0]));
 
42
             fsindex++)
 
43
        {
 
44
                pid = fork();
 
45
                if (pid < 0) {
 
46
                        /* Error */
 
47
                        return false;
 
48
                } else if (pid > 0) {
 
49
                        /* We're in the parent process */
 
50
                        do {
 
51
                                wpid = waitpid(pid, &status, 0);
 
52
                        } while (!WIFEXITED(status) && !WIFSIGNALED(status));
 
53
                        if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS)
 
54
                                return true;
 
55
 
 
56
                        /* Let's try another fstype */
 
57
                        continue;
 
58
                } else {
 
59
                        /* We're in the child process */
 
60
                        debug("Mounting %s at %s\n", device, dir);
 
61
                        close(STDIN_FILENO);
 
62
                        close(STDOUT_FILENO);
 
63
                        close(STDERR_FILENO);
 
64
                        open("/dev/null", O_RDONLY, 0);
 
65
                        open("/dev/null", O_WRONLY, 0);
 
66
                        open("/dev/null", O_WRONLY, 0);
 
67
                        execl("/bin/mount", "/bin/mount", "-n", "-t",
 
68
                              fstypes[fsindex],
 
69
                              /*"ext3,ext2,vfat,reiserfs,xfs,isofs,udf",*/
 
70
                              "-o", "noatime,nodiratime,nodev,noexec,nosuid,ro",
 
71
                              device, dir, (char *)NULL);
 
72
 
 
73
                        /* If execl works, we won't end up here */
 
74
                        exit(EXIT_FAILURE);
 
75
                }
 
76
        }
 
77
 
 
78
        /* We've tried all fstypes with no luck */
 
79
        return false;
 
80
}
 
81
 
 
82
int
 
83
main(int argc, char **argv, char **envp)
 
84
{
 
85
        char *debugval;
 
86
        char *devpath;
 
87
        char *filepath;
 
88
        struct stat st;
 
89
        char *tmppath;
 
90
        char tpath[] = "/tmp/passdev.XXXXXX";
 
91
        char *keypath;
 
92
        int fd;
 
93
        size_t toread;
 
94
        size_t bytesread;
 
95
        char *keybuffer;
 
96
        size_t towrite;
 
97
        size_t byteswritten;
 
98
        ssize_t bytes;
 
99
 
 
100
        /* We only take one argument */
 
101
        if (argc != 2) {
 
102
                fprintf(stderr, "Incorrect number of arguments");
 
103
                goto error;
 
104
        }
 
105
 
 
106
        /* If DEBUG=1 is in the environment, enable debug messages */
 
107
        debugval = getenv("DEBUG");
 
108
        if (debugval && atoi(debugval) > 0)
 
109
                do_debug = true;
 
110
 
 
111
        /* Split string into device and path */
 
112
        devpath = argv[1];
 
113
        filepath = strchr(devpath, ':');
 
114
        if (!filepath || !(*filepath) || !(*(filepath + 1))) {
 
115
                fprintf(stderr, "Invalid key path");
 
116
                goto error;
 
117
        }
 
118
        *filepath = '\0';
 
119
        filepath++;
 
120
        debug("Path is %p and filepath is %p\n", devpath, filepath);
 
121
 
 
122
        /* Wait until device is available */
 
123
        if (access(devpath, F_OK)) {
 
124
                debug("Waiting for %s\n", devpath);
 
125
                while(access(devpath, F_OK))
 
126
                        sleep(1);
 
127
        }
 
128
 
 
129
        /* Make sure device is a blockdev */
 
130
        if (stat(devpath, &st)) {
 
131
                fprintf(stderr, "Unable to stat %s\n", devpath);
 
132
                goto error;
 
133
        } else if (!S_ISBLK(st.st_mode)) {
 
134
                fprintf(stderr, "%s is no block device\n", devpath);
 
135
                goto error;
 
136
        }
 
137
 
 
138
        /* Create a tmp dir where we mount the device */
 
139
        tmppath = mkdtemp(tpath);
 
140
        if (!tmppath) {
 
141
                fprintf(stderr, "Failed to create temporary directory\n");
 
142
                goto error;
 
143
        }
 
144
 
 
145
        /* Ok, mount it */
 
146
        if (!do_mount(devpath, tmppath)) {
 
147
                fprintf(stderr, "Failed to mount %s\n", devpath);
 
148
                goto error_rmdir;
 
149
        }
 
150
 
 
151
        /* Generate the full path to the keyfile */
 
152
        keypath = malloc(strlen(tmppath) + 1 + strlen(filepath) + 1);
 
153
        if (!keypath) {
 
154
                fprintf(stderr, "Failed to allocate memory\n");
 
155
                goto error_umount;
 
156
        }
 
157
        sprintf(keypath, "%s/%s", tmppath, filepath);
 
158
 
 
159
        /* Check that the keyfile exists */
 
160
        if (access(keypath, F_OK)) {
 
161
                fprintf(stderr, "Keyfile doesn't exist\n");
 
162
                goto error_free;
 
163
        }
 
164
 
 
165
        /* Get the size of the keyfile */
 
166
        if (stat(keypath, &st)) {
 
167
                fprintf(stderr, "Unable to stat keyfile\n");
 
168
                goto error_free;
 
169
        }
 
170
 
 
171
        /* Check the size of the keyfile */
 
172
        if (st.st_size < 0) {
 
173
                fprintf(stderr, "Invalid keyfile size\n");
 
174
                goto error_free;
 
175
        }
 
176
        toread = (size_t)st.st_size;
 
177
 
 
178
        /* Open the keyfile */
 
179
        if ((fd = open(keypath, O_RDONLY)) < 0) {
 
180
                fprintf(stderr, "Failed to open keyfile\n");
 
181
                goto error_free;
 
182
        }
 
183
 
 
184
        /* Allocate a buffer for the keyfile contents */
 
185
        keybuffer = malloc(toread);
 
186
        if (!keybuffer) {
 
187
                fprintf(stderr, "Failed to allocate memory\n");
 
188
                goto error_close;
 
189
                exit(EXIT_FAILURE);
 
190
        }
 
191
 
 
192
        /* Read the keyfile */
 
193
        bytesread = 0;
 
194
        while (bytesread < toread) {
 
195
                bytes = read(fd, keybuffer + bytesread, toread - bytesread);
 
196
                if (bytes <= 0) {
 
197
                        fprintf(stderr, "Failed to read entire key\n");
 
198
                        goto error_keybuffer;
 
199
                }
 
200
                bytesread += bytes;
 
201
        }
 
202
 
 
203
        /* Clean up */
 
204
        close(fd);
 
205
        free(keypath);
 
206
        umount(tmppath);
 
207
        rmdir(tmppath);
 
208
 
 
209
        /* Write result */
 
210
        byteswritten = 0;
 
211
        towrite = toread;
 
212
        while (byteswritten < towrite) {
 
213
                bytes = write(STDOUT_FILENO, keybuffer + byteswritten,
 
214
                              towrite - byteswritten);
 
215
                if (bytes <= 0) {
 
216
                        fprintf(stderr, "Failed to write entire key\n");
 
217
                        memset(keybuffer, 0, toread);
 
218
                        free(keybuffer);
 
219
                        goto error;
 
220
                }
 
221
                byteswritten += bytes;
 
222
        }
 
223
 
 
224
        /* Clean up */
 
225
        memset(keybuffer, 0, toread);
 
226
        free(keybuffer);
 
227
 
 
228
        /* Done */
 
229
        exit(EXIT_SUCCESS);
 
230
 
 
231
        /* Error handling */
 
232
error_keybuffer:
 
233
        memset(keybuffer, 0, toread);
 
234
        free(keybuffer);
 
235
error_close:
 
236
        close(fd);
 
237
error_free:
 
238
        free(keypath);
 
239
error_umount:
 
240
        umount(tmppath);
 
241
error_rmdir:
 
242
        rmdir(tmppath);
 
243
error:
 
244
        exit(EXIT_FAILURE);
 
245
}
 
246