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
This commit is contained in:
parent
5e165262f1
commit
8abd1ad101
@ -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.
|
||||
|
@ -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)
|
||||
@ -665,6 +677,64 @@ eli_attach(struct gctl_req *req)
|
||||
bzero(key, sizeof(key));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -363,6 +363,115 @@ g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
|
||||
bzero(&md, sizeof(md));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user