GELI passphrase and/or key via command line or environment
vwe at freebsd.org
vwe at freebsd.org
Fri Sep 9 10:00:58 UTC 2011
On 01/-10/63 20:59, grarpamp wrote:
> For both init and attach (and even elsewhere where
> applicable), I'd like to be able to specify the passphrase
> and key material via the command line and/or the environment.
> Yes, we have -J/j and -K/k, but they only permit the use of files
> or standard in. And of course standard in is not an arbitrary
> file descriptor and as such is only usable once. So it cannot
> be used with both jay and kay. I use both jay and kay, and want
> to do so programmatically without blocking on keyboard input.
> In the current implementation, I cannot achieve this.
>
> I'm well aware of all security implications of command line
> and environment usage.
>
> Please offer your consideration of this feature request :)
> Thanks.
>
Hi!
I think since the -j/-J flags to geli(8) have been introduced, you may
play some tricks with the shell to redirect input (on stable/8 and later
systems).
For stable/7 systems the attached patch should do what you're looking
for. Please be aware, the (well tested) patch does a bit more than just
giving you the ability to read the passphrase from stdin (new -t cli
flag) but also makes some corrections if you're trying to backup and
restore an eli provider. That does not work well if the sizes do not
match and the attached patch fixes that also. I haven't tested for that
bug on stable/8 systems but I guess that bug hasn't been fixed yet.
HTH
Volker
-------------- next part --------------
--- sbin/geom/class/eli/geom_eli.c.orig 2009-06-17 17:26:12.000000000 +0200
+++ sbin/geom/class/eli/geom_eli.c 2009-11-10 09:26:25.000000000 +0100
@@ -73,18 +73,20 @@
static void eli_restore(struct gctl_req *req);
static void eli_clear(struct gctl_req *req);
static void eli_dump(struct gctl_req *req);
+static char *eli_get_passwd(struct gctl_req *, const char *, char *, size_t);
+static char *eli_get_stdin_passwd(void);
/*
* Available commands:
*
- * init [-bhPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov
+ * init [-bhPtv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov
* label - alias for 'init'
- * attach [-dprv] [-k keyfile] prov
+ * attach [-dprtv] [-k keyfile] prov
* 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
+ * setkey [-ptPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov
* delkey [-afv] [-n keyno] prov
* kill [-av] [prov ...]
* backup [-v] prov file
@@ -103,9 +105,10 @@
{ 'l', "keylen", &keylen, G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", §orsize, G_TYPE_NUMBER },
+ { 't', "password-from-stdin", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
- NULL, "[-bPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov"
+ NULL, "[-btPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov"
},
{ "label", G_FLAG_VERBOSE, eli_main,
{
@@ -117,6 +120,7 @@
{ 'l', "keylen", &keylen, G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", §orsize, G_TYPE_NUMBER },
+ { 't', "password-from-stdin", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
NULL, "- an alias for 'init'"
@@ -127,9 +131,10 @@
{ 'k', "keyfile", keyfile, G_TYPE_STRING },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'r', "readonly", NULL, G_TYPE_BOOL },
+ { 't', "password-from-stdin", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
- NULL, "[-dprv] [-k keyfile] prov"
+ NULL, "[-dtprv] [-k keyfile] prov"
},
{ "detach", 0, NULL,
{
@@ -174,9 +179,10 @@
{ 'n', "keyno", &keyno, G_TYPE_NUMBER },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
+ { 't', "password-from-stdin", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
- NULL, "[-pPv] [-n keyno] [-i iterations] [-k keyfile] [-K newkeyfile] prov"
+ NULL, "[-ptPv] [-n keyno] [-i iterations] [-k keyfile] [-K newkeyfile] prov"
},
{ "delkey", G_FLAG_VERBOSE, eli_main,
{
@@ -359,9 +365,9 @@
return (NULL);
}
for (;;) {
- p = readpassphrase(
- new ? "Enter new passphrase:" : "Enter passphrase:",
- buf1, sizeof(buf1), RPP_ECHO_OFF | RPP_REQUIRE_TTY);
+ p = eli_get_passwd(req,
+ new ? "Enter new passphrase: " : "Enter passphrase: ",
+ buf1, sizeof(buf1));
if (p == NULL) {
bzero(buf1, sizeof(buf1));
gctl_error(req, "Cannot read passphrase: %s.",
@@ -369,10 +375,9 @@
return (NULL);
}
- if (new) {
- p = readpassphrase("Reenter new passphrase: ",
- buf2, sizeof(buf2),
- RPP_ECHO_OFF | RPP_REQUIRE_TTY);
+ if (new && ! gctl_get_int(req, "password-from-stdin")) {
+ p = eli_get_passwd(req, "Reenter new passphrase: ",
+ buf2, sizeof(buf2));
if (p == NULL) {
bzero(buf1, sizeof(buf1));
gctl_error(req,
@@ -383,7 +388,11 @@
if (strcmp(buf1, buf2) != 0) {
bzero(buf2, sizeof(buf2));
- fprintf(stderr, "They didn't match.\n");
+ gctl_error(req, "Passphrases didn't match.");
+ /* Exit immediately if reading passwords from stdin. */
+ if (gctl_get_int(req, "password-from-stdin")) {
+ return (NULL);
+ }
continue;
}
bzero(buf2, sizeof(buf2));
@@ -444,7 +453,7 @@
return (-1);
}
if (read(fd, sector, sizeof(sector)) != sizeof(sector)) {
- gctl_error(req, "Cannot read metadata from %s: %s.",
+ gctl_error(req, "Cannot read metadata file %s: %s.",
prov, strerror(errno));
close(fd);
return (-1);
@@ -1167,6 +1176,12 @@
gctl_error(req, "MD5 hash mismatch: not a geli backup file?");
goto out;
}
+ if (md.md_provsize != mediasize) {
+ printf( "warning: size %llu does not match %llu\n",
+ md.md_provsize, mediasize);
+ md.md_provsize = mediasize;
+ eli_metadata_encode(&md, sector);
+ }
/* Write metadata from the provider. */
if (pwrite(provfd, sector, secsize, mediasize - secsize) !=
(ssize_t)secsize) {
@@ -1225,8 +1240,11 @@
for (i = 0; i < nargs; i++) {
name = gctl_get_ascii(req, "arg%d", i);
+ error = eli_metadata_read(req, name, &tmpmd);
+ /*
error = g_metadata_read(name, (unsigned char *)&tmpmd,
sizeof(tmpmd), G_ELI_MAGIC);
+ */
if (error != 0) {
fprintf(stderr, "Cannot read metadata from %s: %s.\n",
name, strerror(error));
@@ -1244,3 +1262,43 @@
printf("\n");
}
}
+
+
+static char *
+eli_get_passwd(struct gctl_req *req, const char *prompt, char *buf, size_t bufsiz)
+{
+ char *p = NULL;
+
+ if (gctl_get_int(req, "password-from-stdin")) {
+ p = eli_get_stdin_passwd();
+ strlcpy(buf, p, bufsiz);
+ } else {
+ p = readpassphrase(prompt, buf, bufsiz, RPP_ECHO_OFF | RPP_REQUIRE_TTY);
+ }
+
+ return p;
+}
+
+static char *
+eli_get_stdin_passwd(void)
+{
+ static char buf[BUFSIZ];
+ size_t len;
+
+ bzero(buf, sizeof(buf));
+
+ /*
+ * if no error is reported from fgets() and string at least contains
+ * the newline that ends the password, then replace the newline with
+ * a null terminator.
+ */
+ if (fgets(buf, sizeof(buf), stdin) != NULL) {
+ if ((len = strlen(buf)) > 0) {
+ if (buf[len-1] == '\n')
+ buf[len - 1] = 0;
+ }
+ }
+
+ return buf;
+}
+
More information about the freebsd-geom
mailing list