2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <ahornung@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 #include <libcryptsetup.h>
47 #define _iswhitespace(X) ((((X) == ' ') || ((X) == '\t'))?1:0)
49 #define CRYPTDISKS_START 1
50 #define CRYPTDISKS_STOP 2
52 static void syntax_error(const char *, ...) __printflike(1, 2);
54 static int line_no = 1;
56 static int iswhitespace(char c)
58 return _iswhitespace(c);
61 static int iscomma(char c)
66 static int yesDialog(char *msg __unused)
71 static void cmdLineLog(int level __unused, char *msg)
76 static struct interface_callbacks cmd_icb = {
77 .yesDialog = yesDialog,
82 syntax_error(const char *fmt, ...)
88 vsnprintf(buf, sizeof(buf), fmt, ap);
90 errx(1, "crypttab: syntax error on line %d: %s\n", line_no, buf);
95 entry_check_num_args(char **tokens, int num)
99 for (i = 0; tokens[i] != NULL; i++)
103 syntax_error("at least %d tokens were expected but only %d "
104 "were found", num, i);
111 line_tokenize(char *buffer, int (*is_sep)(char), char comment_char, char **tokens)
116 i = strlen(buffer) + 1;
119 /* Skip leading white-space */
120 while ((_iswhitespace(buffer[c])) && (c < i)) c++;
123 * If this line effectively (after indentation) begins with the comment
124 * character, we ignore the rest of the line.
126 if (buffer[c] == comment_char)
129 tokens[0] = &buffer[c];
130 for (n = 1; c < i; c++) {
131 if (buffer[c] == '"') {
134 if ((c >= 1) && (&buffer[c] != tokens[n-1])) {
136 syntax_error("stray opening quote not "
137 "at beginning of token");
141 tokens[n-1] = &buffer[c+1];
144 if ((c < i-1) && (!is_sep(buffer[c+1]))) {
146 syntax_error("stray closing quote not "
160 if (is_sep(buffer[c])) {
162 while ((_iswhitespace(buffer[c])) && (c < i)) c++;
163 tokens[n++] = &buffer[c--];
177 parse_crypt_options(struct crypt_options *co, char *option)
179 char *parameter, *endptr;
182 unsigned long long ullval;
186 parameter = strchr(option, '=');
187 noparam = (parameter == NULL);
194 if (strcmp(option, "tries") == 0) {
196 syntax_error("The option 'tries' needs a parameter");
199 lval = strtol(parameter, &endptr, 10);
201 syntax_error("The option 'tries' expects an integer "
202 "parameter, not '%s'", parameter);
205 co->tries = (int)lval;
206 } else if (strcmp(option, "timeout") == 0) {
208 syntax_error("The option 'timeout' needs a parameter");
211 ullval = strtoull(parameter, &endptr, 10);
213 syntax_error("The option 'timeout' expects an integer "
214 "parameter, not '%s'", parameter);
217 co->timeout = ullval;
218 } else if (strcmp(option, "keyscript") == 0) {
220 syntax_error("The option 'keyscript' needs a parameter");
223 /* Allocate safe key memory */
224 buf = alloc_safe_mem(8192);
226 err(1, "Could not allocate safe memory");
229 fd = popen(parameter, "r");
231 syntax_error("The 'keyscript' file could not be run");
234 if ((fread(buf, 1, sizeof(buf), fd)) == 0)
235 syntax_error("The 'keyscript' program failed");
239 /* Get rid of trailing new-line */
240 if ((endptr = strrchr(buf, '\n')) != NULL)
243 co->passphrase = buf;
244 } else if (strcmp(option, "none") == 0) {
245 /* Valid option, does nothing */
247 syntax_error("Unknown option: %s", option);
255 entry_parser(char **tokens, char **options, int type)
257 struct crypt_options co;
260 if (entry_check_num_args(tokens, 2) != 0)
263 bzero(&co, sizeof(co));
268 co.device = tokens[1];
270 /* (Try to) parse extra options */
271 for (i = 0; options[i] != NULL; i++)
272 parse_crypt_options(&co, options[i]);
274 /* Verify that the device is indeed a LUKS-formatted device */
275 error = crypt_isLuks(&co);
277 printf("crypttab: line %d: device %s is not a luks device\n",
282 if (type == CRYPTDISKS_STOP) {
283 /* Check if the device is active */
284 r = crypt_query_device(&co);
286 /* If r > 0, then the device is active */
290 /* Actually close the device */
291 crypt_remove_device(&co);
292 } else if (type == CRYPTDISKS_START) {
293 if ((tokens[2] != NULL) && (strcmp(tokens[2], "none") != 0)) {
294 /* We got a keyfile */
295 co.key_file = tokens[2];
298 /* Open the device */
306 process_line(FILE* fd, int type)
314 while (((c = fgetc(fd)) != EOF) && (c != '\n')) {
315 buffer[i++] = (char)c;
316 if (i == (sizeof(buffer) -1))
321 if (feof(fd) || ferror(fd))
325 n = line_tokenize(buffer, &iswhitespace, '#', tokens);
328 * If there are not enough arguments for any function or it is
329 * a line full of whitespaces, we just return here. Or if a
330 * quote wasn't closed.
332 if ((n < 2) || (tokens[0][0] == '\0'))
336 * If there are at least 4 tokens, one of them (the last) is a list
341 i = line_tokenize(tokens[3], &iscomma, '#', options);
343 syntax_error("Invalid expression in options token");
347 entry_parser(tokens, options, type);
354 main(int argc, char *argv[])
357 int ch, start = 0, stop = 0;
359 while ((ch = getopt(argc, argv, "01")) != -1) {
375 atexit(check_and_purge_safe_mem);
377 if ((start && stop) || (!start && !stop))
378 errx(1, "please specify exactly one of -0 and -1");
380 fd = fopen("/etc/crypttab", "r");
385 while (process_line(fd, (start) ? CRYPTDISKS_START : CRYPTDISKS_STOP) == 0)