Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151572143
D9396.id24599.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D9396.id24599.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D9396: geli attach multiple providers (with kernel changes)
Attached
Detach File
Event Timeline
Log In to Comment