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:
Pawel Jakub Dawidek 2006-09-16 10:43:17 +00:00
parent 5e165262f1
commit 8abd1ad101
4 changed files with 204 additions and 4 deletions

View File

@ -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.

View File

@ -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)
{

View File

@ -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;

View File

@ -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)