Page MenuHomeFreeBSD

D9396.id24599.diff
No OneTemporary

D9396.id24599.diff

Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf
+++ etc/defaults/rc.conf
@@ -77,6 +77,8 @@
# GELI disk encryption configuration.
geli_devices="" # List of devices to automatically attach in addition to
# GELI devices listed in /etc/fstab.
+geli_groups="" # List of groups containing devices to automatically
+ # attach with the same keyfiles and passphrase
geli_tries="" # Number of times to attempt attaching geli device.
# If empty, kern.geom.eli.tries will be used.
geli_default_flags="" # Default flags for geli(8).
@@ -88,6 +90,11 @@
#geli_da1_flags="-p -k /etc/geli/da1.keys"
#geli_da1_autodetach="NO"
#geli_mirror_home_flags="-k /etc/geli/home.keys"
+#geli_groups="storage backup"
+#geli_storage_flags="-k /etc/geli/storage.keys"
+#geli_storage_devices="ada0 ada1"
+#geli_backup_flags="-j /etc/geli/backup.passfile -k /etc/geli/backup.keys"
+#geli_backup_devices="ada2 ada3"
root_rw_mount="YES" # Set to NO to inhibit remounting root read-write.
root_hold_delay="30" # Time to wait for root mount hold release.
Index: etc/rc.d/geli
===================================================================
--- etc/rc.d/geli
+++ etc/rc.d/geli
@@ -72,6 +72,24 @@
done
fi
done
+
+ for group in ${geli_groups}; do
+ group_=`ltr ${group} '/-' '_'`
+
+ eval "flags=\${geli_${group_}_flags}"
+ if [ -z "${flags}" ]; then
+ flags=${geli_default_flags}
+ fi
+
+ eval "providers=\${geli_${group_}_devices}"
+ if [ -z "${providers}" ]; then
+ echo "No devices listed in geli group ${group}."
+ break
+ fi
+
+ echo "Configuring Disk Encryption for geli group ${group}, containing ${providers}."
+ geli attach ${flags} ${providers}
+ done
}
geli_stop()
Index: sbin/geom/class/eli/geli.8
===================================================================
--- sbin/geom/class/eli/geli.8
+++ sbin/geom/class/eli/geli.8
@@ -70,7 +70,7 @@
.Op Fl dprv
.Op Fl j Ar passfile
.Op Fl k Ar keyfile
-.Ar prov
+.Ar prov ...
.Nm
.Cm detach
.Op Fl fl
@@ -379,21 +379,24 @@
features available.
.El
.It Cm attach
-Attach the given provider.
-The encrypted Master Key will be loaded from the metadata and decrypted
-using the given passphrase/keyfile and a new GEOM provider will be created
-using the given provider's name with an
+Attach the given providers.
+The encrypted Master Keys will be loaded from the metadata and decrypted
+using the given passphrase/keyfile and new GEOM providers will be created
+using the given providers' names with an
.Qq .eli
suffix.
+Multiple providers can only be attached with a single
+.Cm attach
+command if they all use the same passphrase and keyfiles.
.Pp
Additional options include:
.Bl -tag -width ".Fl j Ar passfile"
.It Fl d
-If specified, a decrypted provider will be detached automatically on last close.
+If specified, the decrypted providers will be detached automatically on last close.
This can help with scarce memory so the user does not have to remember to detach the
-provider after unmounting the file system.
-It only works when the provider was opened for writing, so it will not work if
-the file system on the provider is mounted read-only.
+providers after unmounting the file system.
+It only works when the providers were opened for writing, so it will not work if
+the file system on the providers are mounted read-only.
Probably a better choice is the
.Fl l
option for the
@@ -407,6 +410,7 @@
option for the
.Cm init
subcommand.
+The same passfiles will be used for all listed providers.
.It Fl k Ar keyfile
Specifies a file which contains the keyfile component of the User Key
(or part of it).
@@ -415,14 +419,15 @@
option for the
.Cm init
subcommand.
+The same keyfiles will be used for all listed providers.
.It Fl p
-Do not use a passphrase as a component of the User Key.
+Do not use a passphrase as a component of the User Keys.
Cannot be combined with the
.Fl j
option.
.It Fl r
-Attach read-only provider.
-It will not be opened for writing.
+Attach read-only providers.
+They will not be opened for writing.
.El
.It Cm detach
Detach the given providers, which means remove the devfs entry
Index: sbin/geom/class/eli/geom_eli.c
===================================================================
--- sbin/geom/class/eli/geom_eli.c
+++ sbin/geom/class/eli/geom_eli.c
@@ -60,6 +60,13 @@
#define GELI_BACKUP_DIR "/var/backups/"
#define GELI_ENC_ALGO "aes"
+#define BUFSIZE 1024
+
+/*
+ * Passphrase cached when attaching multiple providers, in order to be more
+ * user-friendly if they are using the same passphrase.
+ */
+static char cached_passphrase[BUFSIZE] = "";
static void eli_main(struct gctl_req *req, unsigned flags);
static void eli_init(struct gctl_req *req);
@@ -84,7 +91,7 @@
*
* init [-bgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov
* label - alias for 'init'
- * attach [-dprv] [-j passfile] [-k keyfile] prov
+ * attach [-dprv] [-j passfile] [-k keyfile] prov ...
* detach [-fl] prov ...
* stop - alias for 'detach'
* onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov
@@ -267,8 +274,6 @@
static int verbose = 0;
-#define BUFSIZE 1024
-
static int
eli_protect(struct gctl_req *req)
{
@@ -474,6 +479,10 @@
bool nopassphrase;
int nfiles;
+ /*
+ * Return error if the 'do not use passphrase' flag is given, and a
+ * passfile was provided.
+ */
nopassphrase =
gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase");
if (nopassphrase) {
@@ -486,20 +495,32 @@
return (0);
}
+ /*
+ * Return error if using a provider which does not require a passphrase,
+ * but the 'do not use passphrase' flag was not given.
+ */
if (!new && md->md_iterations == -1) {
gctl_error(req, "Missing -p flag.");
return (-1);
}
passbuf[0] = '\0';
- nfiles = eli_genkey_files(req, new, "passfile", NULL, passbuf,
- sizeof(passbuf));
- if (nfiles == -1)
- return (-1);
- else if (nfiles == 0) {
- if (eli_genkey_passphrase_prompt(req, new, passbuf,
- sizeof(passbuf)) == -1) {
+
+ /* Use cached passphrase if defined. */
+ if (strcmp(cached_passphrase, "") != 0) {
+ memcpy(passbuf, cached_passphrase, sizeof(passbuf));
+ } else {
+ nfiles = eli_genkey_files(req, new, "passfile", NULL, passbuf,
+ sizeof(passbuf));
+ if (nfiles == -1)
return (-1);
+ else if (nfiles == 0) {
+ if (eli_genkey_passphrase_prompt(req, new, passbuf,
+ sizeof(passbuf)) == -1) {
+ return (-1);
+ }
}
+ /* Cache the passphrase for other providers. */
+ memcpy(cached_passphrase, passbuf, sizeof(passbuf));
}
/*
* Field md_iterations equal to -1 means "choose some sane
@@ -876,37 +897,53 @@
eli_attach(struct gctl_req *req)
{
struct g_eli_metadata md;
- unsigned char key[G_ELI_USERKEYLEN];
const char *prov;
off_t mediasize;
- int nargs;
+ char param[16];
+ int i, nargs;
nargs = gctl_get_int(req, "nargs");
- if (nargs != 1) {
- gctl_error(req, "Invalid number of arguments.");
+ if (nargs == 0) {
+ gctl_error(req, "Too few arguments.");
return;
}
- prov = gctl_get_ascii(req, "arg0");
- if (eli_metadata_read(req, prov, &md) == -1)
- return;
+ /* Use a 2D array for storing the derived keys (1 row per provider) */
+ unsigned char key[nargs][G_ELI_USERKEYLEN];
- mediasize = g_get_mediasize(prov);
- if (md.md_provsize != (uint64_t)mediasize) {
- gctl_error(req, "Provider size mismatch.");
- return;
- }
+ /* Generate the derived key for each provider */
+ for (i = 0; i < nargs; i++) {
+ prov = gctl_get_ascii(req, "arg%d", i);
- if (eli_genkey(req, &md, key, false) == NULL) {
- bzero(key, sizeof(key));
- return;
+ if (eli_metadata_read(req, prov, &md) == -1)
+ return;
+
+ mediasize = g_get_mediasize(prov);
+ if (md.md_provsize != (uint64_t)mediasize) {
+ gctl_error(req, "Provider size mismatch.");
+ return;
+ }
+
+ if (eli_genkey(req, &md, key[i], false) == NULL) {
+ bzero(key, sizeof(key));
+ return;
+ }
+
+ snprintf(param, sizeof(param), "key%d", i);
+ gctl_ro_param(req, param, sizeof(key[i]), key[i]);
}
- gctl_ro_param(req, "key", sizeof(key), key);
if (gctl_issue(req) == NULL) {
- if (verbose)
- printf("Attached to %s.\n", prov);
+ if (verbose) {
+ printf("Attached to");
+ for (i = 0; i < nargs; i++) {
+ printf(" %s", gctl_get_ascii(req, "arg%d", i));
+ }
+ printf(".\n");
+ }
}
+
+ /* Clear each of the derived keys from the 2D array */
bzero(key, sizeof(key));
}
Index: share/man/man5/rc.conf.5
===================================================================
--- share/man/man5/rc.conf.5
+++ share/man/man5/rc.conf.5
@@ -1931,6 +1931,13 @@
Note that .eli devices from
.Pa /etc/fstab
are automatically appended to this list.
+.It Va geli_groups
+.Pq Vt str
+List of groups containing devices to automatically attach on boot with the same
+keyfiles and passphrase.
+This must be accompanied with a corresponding
+.Va geli_ Ns Ao Ar group Ac Ns Va _devices
+variable.
.It Va geli_tries
.Pq Vt int
Number of times user is asked for the pass-phrase.
@@ -1944,6 +1951,8 @@
when configuring disk encryption.
Flags can be configured for every device separately by defining
.Va geli_ Ns Ao Ar device Ac Ns Va _flags
+variable, and for every group separately by defining
+.Va geli_ Ns Ao Ar group Ac Ns Va _flags
variable.
.It Va geli_autodetach
.Pq Vt str
Index: sys/geom/eli/g_eli_ctl.c
===================================================================
--- sys/geom/eli/g_eli_ctl.c
+++ sys/geom/eli/g_eli_ctl.c
@@ -57,8 +57,9 @@
struct g_provider *pp;
const char *name;
u_char *key, mkey[G_ELI_DATAIVKEYLEN];
+ char param[16], argname[16];
int *nargs, *detach, *readonly;
- int keysize, error;
+ int i, keysize, error;
u_int nkey;
g_topology_assert();
@@ -68,8 +69,8 @@
gctl_error(req, "No '%s' argument.", "nargs");
return;
}
- if (*nargs != 1) {
- gctl_error(req, "Invalid number of arguments.");
+ if (*nargs == 0) {
+ gctl_error(req, "Too few arguments.");
return;
}
@@ -85,63 +86,72 @@
return;
}
- name = gctl_get_asciiparam(req, "arg0");
- if (name == NULL) {
- gctl_error(req, "No 'arg%u' argument.", 0);
- return;
- }
- if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
- name += strlen("/dev/");
- pp = g_provider_by_name(name);
- if (pp == NULL) {
- gctl_error(req, "Provider %s is invalid.", name);
- return;
- }
- error = g_eli_read_metadata(mp, pp, &md);
- if (error != 0) {
- gctl_error(req, "Cannot read metadata from %s (error=%d).",
- name, error);
- return;
- }
- if (md.md_keys == 0x00) {
+ if (*detach && *readonly) {
bzero(&md, sizeof(md));
- gctl_error(req, "No valid keys on %s.", pp->name);
+ gctl_error(req, "Options -d and -r are mutually exclusive.");
return;
}
- key = gctl_get_param(req, "key", &keysize);
- if (key == NULL || keysize != G_ELI_USERKEYLEN) {
- bzero(&md, sizeof(md));
- gctl_error(req, "No '%s' argument.", "key");
- return;
- }
+ /* Attach each provider in the request */
+ for (i = 0; i < *nargs; i++) {
+ snprintf(argname, sizeof(argname), "arg%d", i);
+ name = gctl_get_asciiparam(req, argname);
+ if (name == NULL) {
+ gctl_error(req, "No '%s' argument.", argname);
+ continue;
+ }
+ if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
+ name += strlen("/dev/");
+ pp = g_provider_by_name(name);
+ if (pp == NULL) {
+ gctl_error(req, "Provider %s is invalid.", name);
+ continue;
+ }
+ error = g_eli_read_metadata(mp, pp, &md);
+ if (error != 0) {
+ gctl_error(req, "Cannot read metadata from %s (error=%d).",
+ name, error);
+ continue;
+ }
+ if (md.md_keys == 0x00) {
+ bzero(&md, sizeof(md));
+ gctl_error(req, "No valid keys on %s.", pp->name);
+ continue;
+ }
- error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
- bzero(key, keysize);
- if (error == -1) {
- bzero(&md, sizeof(md));
- gctl_error(req, "Wrong key for %s.", pp->name);
- return;
- } else if (error > 0) {
- bzero(&md, sizeof(md));
- gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
- pp->name, error);
- return;
- }
- G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
+ /* Get the derived key for this provider from the request */
+ snprintf(param, sizeof(param), "key%d", i);
+ key = gctl_get_param(req, param, &keysize);
+ if (key == NULL || keysize != G_ELI_USERKEYLEN) {
+ bzero(&md, sizeof(md));
+ gctl_error(req, "No '%s' argument.", param);
+ continue;
+ }
- if (*detach && *readonly) {
+ /* Decrypt the master key for this provider */
+ error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
+ bzero(key, keysize);
+ if (error == -1) {
+ bzero(&md, sizeof(md));
+ gctl_error(req, "Wrong key for %s.", pp->name);
+ continue;
+ } else if (error > 0) {
+ bzero(&md, sizeof(md));
+ gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
+ pp->name, error);
+ continue;
+ }
+ G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
+
+ /* Create the new GEOM provider using the master key */
+ if (*detach)
+ md.md_flags |= G_ELI_FLAG_WO_DETACH;
+ if (*readonly)
+ md.md_flags |= G_ELI_FLAG_RO;
+ g_eli_create(req, mp, pp, &md, mkey, nkey);
+ bzero(mkey, sizeof(mkey));
bzero(&md, sizeof(md));
- gctl_error(req, "Options -d and -r are mutually exclusive.");
- return;
}
- if (*detach)
- md.md_flags |= G_ELI_FLAG_WO_DETACH;
- if (*readonly)
- md.md_flags |= G_ELI_FLAG_RO;
- g_eli_create(req, mp, pp, &md, mkey, nkey);
- bzero(mkey, sizeof(mkey));
- bzero(&md, sizeof(md));
}
static struct g_eli_softc *

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 10, 6:41 AM (9 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31206961
Default Alt Text
D9396.id24599.diff (13 KB)

Event Timeline