cryptdisks - A small tool to parse /etc/crypttab
authorAlex Hornung <ahornung@gmail.com>
Fri, 22 Oct 2010 21:03:30 +0000 (22:03 +0100)
committerAlex Hornung <ahornung@gmail.com>
Fri, 22 Oct 2010 21:39:37 +0000 (22:39 +0100)
etc/rc.d/Makefile
etc/rc.d/cryptdisks [new file with mode: 0644]
sbin/Makefile
sbin/cryptdisks/Makefile [new file with mode: 0644]
sbin/cryptdisks/cryptdisks.8 [new file with mode: 0644]
sbin/cryptdisks/cryptdisks.c [new file with mode: 0644]
share/man/man5/Makefile
share/man/man5/crypttab.5 [new file with mode: 0644]
share/man/man5/rc.conf.5

index 8e6d51e..a760884 100644 (file)
@@ -7,8 +7,8 @@
 #
 FILES= DAEMON LOGIN NETWORKING SERVERS abi accounting addswap adjkerntz \
        amd apm apmd atm1 atm2 atm3 \
-       battd bootconf bootparams btconfig bthcid ccd cleanvar \
-       cleartmp cron devd devfs dhclient diskless dmesg dumpon \
+       battd bootconf bootparams btconfig bthcid ccd cleanvar cryptdisks \
+       cleartmp cron cryptdisks devd devfs dhclient diskless dmesg dumpon \
        fixbootfile fsck ftpd hostapd hostname hotplugd \
        inetd initdiskless initrandom ip6fw ipfilter ipfs ipfw ipmon \
        ipnat ipsec ipxrouted isdnd jail \
diff --git a/etc/rc.d/cryptdisks b/etc/rc.d/cryptdisks
new file mode 100644 (file)
index 0000000..f792f7d
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+# PROVIDE: cryptdisks
+# REQUIRE:
+# BEFORE:  mountcritlocal localswap dumpon
+
+$_rc_subr_loaded . /etc/rc.subr
+
+name="cryptdisks"
+rcvar=$name
+start_cmd="cryptdisks_start"
+stop_cmd="cryptdisks_stop"
+CRYPTTAB="/etc/crypttab"
+
+ifs_restore="$IFS";
+
+cryptdisks_start()
+{
+       if [ ! -f $CRYPTTAB ]; then
+               warn "$CRYPTTAB does not exist"
+               return 1;
+       fi
+
+       if [ -x /sbin/dmsetup ]; then
+               /sbin/dmsetup version >/dev/null
+               if [ $? -ne 0 ]; then 
+                       warn "Device-mapper not present in kernel"
+                       return 1;
+               fi
+       fi
+
+       if [ ! -x /sbin/cryptdisks ]; then
+               warn "cryptdisks is not executable"
+               return 1;
+       fi
+
+       echo "Configuring crypto disks."
+       /sbin/cryptdisks -1
+}
+
+cryptdisks_stop()
+{
+        if [ ! -f $CRYPTTAB ]; then
+                warn "$CRYPTTAB does not exist"
+                return 1;
+        fi
+        if [ -x /sbin/dmsetup ]; then
+                /sbin/dmsetup version >/dev/null
+                if [ $? -ne 0 ]; then
+                        warn "Device-mapper not present in kernel"
+                        return 1;
+                fi
+        fi
+        if [ ! -x /sbin/cryptdisks ]; then
+                warn "cryptdisks is not executable"
+                return 1;
+        fi
+
+        echo "Unconfiguring crypto disks."
+        /sbin/cryptdisks -0
+
+}
+
+load_rc_config $name
+run_rc_command "$1"
index 4655bc6..b6ba284 100644 (file)
@@ -12,6 +12,7 @@ SUBDIR=       adjkerntz \
        ccdconfig \
        clri \
        comcontrol \
+       cryptdisks \
        devd \
        devfsctl \
        dhclient \
diff --git a/sbin/cryptdisks/Makefile b/sbin/cryptdisks/Makefile
new file mode 100644 (file)
index 0000000..0a82a57
--- /dev/null
@@ -0,0 +1,17 @@
+PROG=          cryptdisks
+MAN=           cryptdisks.8
+
+LDADD+=                -L${.CURDIR}/../../gnu/lib/libcryptsetup -lcryptsetup
+DPADD+=                ${.CURDIR}/../../gnu/lib/libcryptsetup/libcryptsetup.a
+
+LDADD+=                -L${.CURDIR}/../../gnu/lib/libluks -lluks
+DPADD+=                ${.CURDIR}/../../gnu/lib/libluks/libluks.a
+
+LDADD+=                -lprop -lcrypto
+
+LDADD+=                -L${.CURDIR}/../../gnu/lib/libdevmapper -ldevmapper
+DPADD+=                ${.CURDIR}/../../gnu/lib/libdevmapper/libdevmapper.a
+
+LDADD+=                -lprop -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/sbin/cryptdisks/cryptdisks.8 b/sbin/cryptdisks/cryptdisks.8
new file mode 100644 (file)
index 0000000..3775a77
--- /dev/null
@@ -0,0 +1,67 @@
+.\"
+.\" Copyright (c) 2010
+.\"    The DragonFly Project.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. Neither the name of The DragonFly Project nor the names of its
+.\"    contributors may be used to endorse or promote products derived
+.\"    from this software without specific, prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd October 22, 2010
+.Os
+.Dt CRYPTDISKS 8
+.Sh NAME
+.Nm cryptdisks
+.Nd process /etc/crypttab
+.Sh SYNOPSIS
+.Nm
+.Fl 0
+.Nm
+.Fl 1
+.Sh DESCRIPTION
+The
+.Nm
+parses the
+.Pa /etc/crypttab
+file and sets up all crypto volumes when
+.Fl 1
+is specified and closes them when
+.Fl 0
+is specified.
+.Sh FILES
+.Bl -tag -width ".Pa /etc/crypttab" -compact
+.It Pa /etc/crypttab
+configuration file of local crypto volumes
+.El
+.Sh SEE ALSO
+.Xr crypttab 5 ,
+.Xr cryptsetup 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Dx 2.9 .
+.Sh AUTHORS
+.An Alex Hornung
diff --git a/sbin/cryptdisks/cryptdisks.c b/sbin/cryptdisks/cryptdisks.c
new file mode 100644 (file)
index 0000000..368c503
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Alex Hornung <ahornung@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <err.h>
+
+#include <libcryptsetup.h>
+
+#define iswhitespace(X)        ((((X) == ' ') || ((X) == '\t'))?1:0)
+
+#define CRYPTDISKS_START       1
+#define CRYPTDISKS_STOP                2
+
+static int line_no = 1;
+
+static int yesDialog(char *msg __unused)
+{
+       return 1;
+}
+
+static void cmdLineLog(int level __unused, char *msg)
+{
+       printf("%s", msg);
+}
+
+static struct interface_callbacks cmd_icb = {
+       .yesDialog = yesDialog,
+       .log = cmdLineLog,
+};
+
+static void
+syntax_error(const char *fmt, ...)
+{
+       char buf[1024];
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+       errx(1, "crypttab: syntax error on line %d: %s\n", line_no, buf);
+}
+
+
+static int
+entry_check_num_args(char **tokens, int num)
+{
+       int i;
+
+       for (i = 0; tokens[i] != NULL; i++)
+               ;
+
+       if (i < num) {
+               syntax_error("at least %d tokens were expected but only %d were found", num, i);
+               return 1;
+       }
+       return 0;
+}
+
+static int
+entry_parser(char **tokens, int type)
+{
+       struct crypt_options co;
+       int r, error;
+
+       if (entry_check_num_args(tokens, 2) != 0)
+               return 1;
+
+       bzero(&co, sizeof(co));
+
+       co.icb = &cmd_icb;
+       co.name = tokens[0];
+       co.device = tokens[1];
+
+       error = crypt_isLuks(&co);
+       if (error) {
+               printf("crypttab: line %d: device %s is not a luks device\n",
+                   line_no, co.device);
+               return 1;
+       }
+
+       if (type == CRYPTDISKS_STOP) {
+               /* Check if the device is active */
+               r = crypt_query_device(&co);
+
+               /* If r > 0, then the device is active */
+               if (r <= 0)
+                       return 0;
+
+               /* Actually close the device */
+               crypt_remove_device(&co);
+       } else if (type == CRYPTDISKS_START) {
+               if ((tokens[2] != NULL) && (strcmp(tokens[2], "none") != 0)) {
+                       /* We got a keyfile */
+                       co.key_file = tokens[2];
+               }
+
+               /* Open the device */
+               crypt_luksOpen(&co);
+       }
+
+       return 0;
+}
+
+static int
+process_line(FILE* fd, int type)
+{
+       char buffer[4096];
+       char *tokens[256];
+       int c, n, i = 0;
+       int quote = 0;
+       int ret = 0;
+
+       while (((c = fgetc(fd)) != EOF) && (c != '\n')) {
+               buffer[i++] = (char)c;
+               if (i == (sizeof(buffer) -1))
+                       break;
+       }
+       buffer[i] = '\0';
+
+       if (feof(fd) || ferror(fd))
+               ret = 1;
+       c = 0;
+       while (((buffer[c] == ' ') || (buffer[c] == '\t')) && (c < i)) c++;
+       /*
+        * If this line effectively (after indentation) begins with the comment
+        * character #, we ignore the rest of the line.
+        */
+       if (buffer[c] == '#')
+               return 0;
+
+       tokens[0] = &buffer[c];
+       for (n = 1; c < i; c++) {
+               if (buffer[c] == '"') {
+                       quote = !quote;
+                       if (quote) {
+                               if ((c >= 1) && (&buffer[c] != tokens[n-1])) {
+                                       syntax_error("stray opening quote not at beginning of token");
+                                       /* NOTREACHED */
+                               }
+                               tokens[n-1] = &buffer[c+1];
+                       } else {
+                               if ((c < i-1) && (!iswhitespace(buffer[c+1]))) {
+                                       syntax_error("stray closing quote not at end of token");
+                                       /* NOTREACHED */
+                               }
+                               buffer[c] = '\0';
+                       }
+               }
+
+               if (quote) {
+                       continue;
+               }
+
+               if ((buffer[c] == ' ') || (buffer[c] == '\t')) {
+                       buffer[c++] = '\0';
+                       while ((iswhitespace(buffer[c])) && (c < i)) c++;
+                       tokens[n++] = &buffer[c--];
+               }
+       }
+       tokens[n] = NULL;
+
+       /*
+        * If there are not enough arguments for any function or it is
+        * a line full of whitespaces, we just return here. Or if a
+        * quote wasn't closed.
+        */
+       if ((quote) || (n < 2) || (tokens[0][0] == '\0'))
+               return ret;
+
+       entry_parser(tokens, type);
+
+       return ret;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+       FILE *fd;
+       int ch, start = 0, stop = 0;
+
+       while ((ch = getopt(argc, argv, "01")) != -1) {
+               switch (ch) {
+               case '1':
+                       start = 1;
+                       break;
+               case '0':
+                       stop = 1;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       if ((start && stop) || (!start && !stop))
+               errx(1, "please specify exactly one of -0 and -1");
+
+       fd = fopen("/etc/crypttab", "r");
+       if (fd == NULL)
+               err(1, "fopen");
+               /* NOTREACHED */
+
+       while (process_line(fd, (start) ? CRYPTDISKS_START : CRYPTDISKS_STOP) == 0)
+               ++line_no;
+
+       fclose(fd);
+       return 0;
+}
index 62dacbd..d1af3a4 100644 (file)
@@ -7,6 +7,7 @@ MAN=    acct.5 \
        a.out.5 \
        compilers.conf.5 \
        core.5 \
+       crypttab.5 \
        devfs.5 \
        devtab.5 \
        dir.5 \
diff --git a/share/man/man5/crypttab.5 b/share/man/man5/crypttab.5
new file mode 100644 (file)
index 0000000..212ec0e
--- /dev/null
@@ -0,0 +1,106 @@
+.\"
+.\" Copyright (c) 2010
+.\"    The DragonFly Project.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. Neither the name of The DragonFly Project nor the names of its
+.\"    contributors may be used to endorse or promote products derived
+.\"    from this software without specific, prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd October 22, 2010
+.Dt CRYPTTAB 5
+.Os
+.Sh NAME
+.Nm crypttab
+.Nd encrypted disk device table
+.Sh DESCRIPTION
+The
+.Nm
+file contains a list of the encrypted disk devices of the system. Each
+encrypted volume is described on a separate line; fields on each line are
+separated by tabs or spaces.
+
+.Pp
+The first field,
+.Pq Fa name ,
+contains the name of the resultant crypto volume device, which will
+be a node in
+.Pa /dev/mapper
+with the given
+.Pa name .
+.Pp
+The second field,
+.Pq Fa device ,
+is the underlying device on which the crypto volume resides and must be
+a full device path to a node in
+.Pa /dev .
+.Pp
+The third field,
+.Pq Fa keyfile ,
+is either the value
+.It Pa none
+or the full path on the file system to a keyfile to unlock the crypto
+volume.
+If
+.It Pa none
+is specified, the system will prompt for a password during the boot
+sequence.
+.Pp
+The fourth field,
+.Pq Fa options ,
+is currently unused on
+.Dx
+and should be either omitted or set to
+.It Pa none .
+
+.Sh FILES
+.Bl -tag -width ".Pa /etc/crypttab" -compact
+.It Pa /etc/crypttab
+The
+.Nm
+file resides in
+.Pa /etc .
+.El
+.Sh EXAMPLES
+The following line specifies a crypto volume without a keyfile, so
+that a password will be prompted during the boot sequence. Upon
+successful entry of the password the device
+.Pa /dev/mapper/vol1
+will be created.
+.Pp
+.Dl "vol1        /dev/da0s1b        none        none"
+.Pp
+The next example is as the one before but using a keyfile on
+.Pa /boot
+instead of an interactive password prompt.
+.Pp
+.Dl "vol1        /dev/da0s1b        /boot/keyfile.0      none"
+.Sh SEE ALSO
+.Xr cryptsetup 8
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Dx 2.9 .
index 6b9f053..ebd94d6 100644 (file)
@@ -2841,6 +2841,15 @@ to save
 to
 .Pa /var/run/dmesg.boot
 on boot.
+.It Va cryptdisks_enable
+.Pq Vt bool
+Set to
+.Dq Li YES
+to start all crypto volumes specified in the
+.Xr crypttab 5
+file during the boot sequence so they can be used during the local mounts
+specified in
+.Xr fstab 5 .
 .It Va rcshutdown_timeout
 .Pq Vt int
 If set, start a watchdog timer in the background which will terminate