summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2006-09-16 10:43:17 +0000
committerpjd <pjd@FreeBSD.org>2006-09-16 10:43:17 +0000
commit2e387b9b852a5ae8c2980ff133e33d076004f6bf (patch)
treed6a32a6317a6d83082fb42a45340d13d9d9c56f0
parentf5e129df20c2b3984d81e96cfffd8fe2979a18be (diff)
downloadFreeBSD-src-2e387b9b852a5ae8c2980ff133e33d076004f6bf.zip
FreeBSD-src-2e387b9b852a5ae8c2980ff133e33d076004f6bf.tar.gz
Add 'configure' subcommand which for now only allows setting and removing
of the BOOT flag. It can be performed on both attached and detached providers. Requested by: Matthias Lederhofer <matled@gmx.net> MFC after: 1 week
-rw-r--r--sbin/geom/class/eli/geli.819
-rw-r--r--sbin/geom/class/eli/geom_eli.c70
-rw-r--r--sys/geom/eli/g_eli.h8
-rw-r--r--sys/geom/eli/g_eli_ctl.c111
4 files changed, 204 insertions, 4 deletions
diff --git a/sbin/geom/class/eli/geli.8 b/sbin/geom/class/eli/geli.8
index 580b6e0..c2d588d 100644
--- a/sbin/geom/class/eli/geli.8
+++ b/sbin/geom/class/eli/geli.8
@@ -83,6 +83,10 @@ utility:
.Op Fl s Ar sectorsize
.Ar prov ...
.Nm
+.Cm configure
+.Op Fl bB
+.Ar prov ...
+.Nm
.Cm setkey
.Op Fl pPv
.Op Fl i Ar iterations
@@ -196,7 +200,7 @@ Allows to verify data integrity (data authentication).
The first argument to
.Nm
indicates an action to be performed:
-.Bl -tag -width ".Cm onetime"
+.Bl -tag -width ".Cm configure"
.It Cm init
Initialize provider which needs to be encrypted.
Here you can set up the cryptographic algorithm to use, key length, etc.
@@ -351,6 +355,19 @@ For more information, see the description of the
.Cm init
subcommand.
.El
+.It Cm configure
+Change configuration of the given providers.
+.Pp
+Additional options include:
+.Bl -tag -width ".Fl b"
+.It Fl b
+Set the BOOT flag on the given providers.
+For more information, see the description of the
+.Cm init
+subcommand.
+.It Fl B
+Remove the BOOT flag from the given providers.
+.El
.It Cm setkey
Change or setup (if not yet initialized) selected key.
There is one master key, which can be encrypted with two independent user keys.
diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c
index 3da4e83..0a82ccd 100644
--- a/sbin/geom/class/eli/geom_eli.c
+++ b/sbin/geom/class/eli/geom_eli.c
@@ -65,6 +65,7 @@ static char keyfile[] = "", newkeyfile[] = "";
static void eli_main(struct gctl_req *req, unsigned flags);
static void eli_init(struct gctl_req *req);
static void eli_attach(struct gctl_req *req);
+static void eli_configure(struct gctl_req *req);
static void eli_setkey(struct gctl_req *req);
static void eli_delkey(struct gctl_req *req);
static void eli_kill(struct gctl_req *req);
@@ -82,6 +83,7 @@ static void eli_dump(struct gctl_req *req);
* detach [-fl] prov ...
* stop - alias for 'detach'
* onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov ...
+ * configure [-bB] prov ...
* setkey [-pPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov
* delkey [-afv] [-n keyno] prov
* kill [-av] [prov ...]
@@ -156,6 +158,14 @@ struct g_command class_commands[] = {
},
"[-d] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov ..."
},
+ { "configure", G_FLAG_VERBOSE, eli_main,
+ {
+ { 'b', "boot", NULL, G_TYPE_NONE },
+ { 'B', "noboot", NULL, G_TYPE_NONE },
+ G_OPT_SENTINEL
+ },
+ "[-bB] prov ..."
+ },
{ "setkey", G_FLAG_VERBOSE, eli_main,
{
{ 'i', "iterations", &iterations, G_TYPE_NUMBER },
@@ -242,6 +252,8 @@ eli_main(struct gctl_req *req, unsigned flags)
eli_init(req);
else if (strcmp(name, "attach") == 0)
eli_attach(req);
+ else if (strcmp(name, "configure") == 0)
+ eli_configure(req);
else if (strcmp(name, "setkey") == 0)
eli_setkey(req);
else if (strcmp(name, "delkey") == 0)
@@ -666,6 +678,64 @@ eli_attach(struct gctl_req *req)
}
static void
+eli_configure_detached(struct gctl_req *req, const char *prov, int boot)
+{
+ struct g_eli_metadata md;
+
+ if (eli_metadata_read(req, prov, &md) == -1)
+ return;
+
+ if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) {
+ if (verbose)
+ printf("BOOT flag already configured for %s.\n", prov);
+ } else if (!boot && !(md.md_flags & G_ELI_FLAG_BOOT)) {
+ if (verbose)
+ printf("BOOT flag not configured for %s.\n", prov);
+ } else {
+ if (boot)
+ md.md_flags |= G_ELI_FLAG_BOOT;
+ else
+ md.md_flags &= ~G_ELI_FLAG_BOOT;
+ eli_metadata_store(req, prov, &md);
+ }
+ bzero(&md, sizeof(md));
+}
+
+static void
+eli_configure(struct gctl_req *req)
+{
+ const char *prov;
+ int i, nargs, boot, noboot;
+
+ nargs = gctl_get_int(req, "nargs");
+ if (nargs == 0) {
+ gctl_error(req, "Too few arguments.");
+ return;
+ }
+
+ boot = gctl_get_int(req, "boot");
+ noboot = gctl_get_int(req, "noboot");
+
+ if (boot && noboot) {
+ gctl_error(req, "Options -b and -B are mutually exclusive.");
+ return;
+ }
+ if (!boot && !noboot) {
+ gctl_error(req, "No option given.");
+ return;
+ }
+
+ /* First attached providers. */
+ gctl_issue(req);
+ /* Now the rest. */
+ for (i = 0; i < nargs; i++) {
+ prov = gctl_get_ascii(req, "arg%d", i);
+ if (!eli_is_attached(prov))
+ eli_configure_detached(req, prov, boot);
+ }
+}
+
+static void
eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md)
{
unsigned char key[G_ELI_USERKEYLEN];
diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h
index e24f314..5460eea 100644
--- a/sys/geom/eli/g_eli.h
+++ b/sys/geom/eli/g_eli.h
@@ -59,8 +59,9 @@
* 2 - Added G_ELI_FLAG_READONLY.
* - IV is generated from offset converted to little-endian
* (flag G_ELI_FLAG_NATIVE_BYTE_ORDER will be set for older versions).
+ * 3 - Added 'configure' subcommand.
*/
-#define G_ELI_VERSION 2
+#define G_ELI_VERSION 3
/* ON DISK FLAGS. */
/* Use random, onetime keys. */
@@ -228,7 +229,7 @@ eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
return (0);
}
static __inline int
-eli_metadata_decode_v1v2(const u_char *data, struct g_eli_metadata *md)
+eli_metadata_decode_v1v2v3(const u_char *data, struct g_eli_metadata *md)
{
MD5_CTX ctx;
const u_char *p;
@@ -264,7 +265,8 @@ eli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
break;
case 1:
case 2:
- error = eli_metadata_decode_v1v2(data, md);
+ case 3:
+ error = eli_metadata_decode_v1v2v3(data, md);
break;
default:
error = EINVAL;
diff --git a/sys/geom/eli/g_eli_ctl.c b/sys/geom/eli/g_eli_ctl.c
index e420af3..a788ba2 100644
--- a/sys/geom/eli/g_eli_ctl.c
+++ b/sys/geom/eli/g_eli_ctl.c
@@ -364,6 +364,115 @@ g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
}
static void
+g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
+{
+ struct g_eli_softc *sc;
+ struct g_eli_metadata md;
+ struct g_provider *pp;
+ struct g_consumer *cp;
+ char param[16];
+ const char *prov;
+ u_char *sector;
+ int *nargs, *boot, *noboot;
+ int error;
+ u_int i;
+
+ g_topology_assert();
+
+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+ if (nargs == NULL) {
+ gctl_error(req, "No '%s' argument.", "nargs");
+ return;
+ }
+ if (*nargs <= 0) {
+ gctl_error(req, "Missing device(s).");
+ return;
+ }
+
+ boot = gctl_get_paraml(req, "boot", sizeof(*boot));
+ if (boot == NULL) {
+ gctl_error(req, "No '%s' argument.", "boot");
+ return;
+ }
+ noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
+ if (noboot == NULL) {
+ gctl_error(req, "No '%s' argument.", "noboot");
+ return;
+ }
+ if (*boot && *noboot) {
+ gctl_error(req, "Options -b and -B are mutually exclusive.");
+ return;
+ }
+ if (!*boot && !*noboot) {
+ gctl_error(req, "No option given.");
+ return;
+ }
+
+ for (i = 0; i < *nargs; i++) {
+ snprintf(param, sizeof(param), "arg%d", i);
+ prov = gctl_get_asciiparam(req, param);
+ if (prov == NULL) {
+ gctl_error(req, "No 'arg%d' argument.", i);
+ return;
+ }
+ sc = g_eli_find_device(mp, prov);
+ if (sc == NULL) {
+ /*
+ * We ignore not attached providers, userland part will
+ * take care of them.
+ */
+ G_ELI_DEBUG(1, "Skipping configuration of not attached "
+ "provider %s.", prov);
+ continue;
+ }
+ if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
+ G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
+ prov);
+ continue;
+ } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
+ G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
+ prov);
+ continue;
+ }
+ if (sc->sc_flags & G_ELI_FLAG_RO) {
+ gctl_error(req, "Cannot change configuration of "
+ "read-only provider %s.", prov);
+ continue;
+ }
+ cp = LIST_FIRST(&sc->sc_geom->consumer);
+ pp = cp->provider;
+ error = g_eli_read_metadata(mp, pp, &md);
+ if (error != 0) {
+ gctl_error(req,
+ "Cannot read metadata from %s (error=%d).",
+ prov, error);
+ continue;
+ }
+
+ if (*boot) {
+ md.md_flags |= G_ELI_FLAG_BOOT;
+ sc->sc_flags |= G_ELI_FLAG_BOOT;
+ } else {
+ md.md_flags &= ~G_ELI_FLAG_BOOT;
+ sc->sc_flags &= ~G_ELI_FLAG_BOOT;
+ }
+
+ sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
+ eli_metadata_encode(&md, sector);
+ error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
+ pp->sectorsize);
+ if (error != 0) {
+ gctl_error(req,
+ "Cannot store metadata on %s (error=%d).",
+ prov, error);
+ }
+ bzero(&md, sizeof(md));
+ bzero(sector, sizeof(sector));
+ free(sector, M_ELI);
+ }
+}
+
+static void
g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
{
struct g_eli_softc *sc;
@@ -710,6 +819,8 @@ g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
g_eli_ctl_detach(req, mp);
else if (strcmp(verb, "onetime") == 0)
g_eli_ctl_onetime(req, mp);
+ else if (strcmp(verb, "configure") == 0)
+ g_eli_ctl_configure(req, mp);
else if (strcmp(verb, "setkey") == 0)
g_eli_ctl_setkey(req, mp);
else if (strcmp(verb, "delkey") == 0)
OpenPOWER on IntegriCloud