From owner-freebsd-bugs@FreeBSD.ORG Wed Aug 15 12:50:04 2007 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3223A16A468 for ; Wed, 15 Aug 2007 12:50:04 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 0D3BE13C474 for ; Wed, 15 Aug 2007 12:50:04 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.1/8.14.1) with ESMTP id l7FCo3GH056039 for ; Wed, 15 Aug 2007 12:50:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.1/8.14.1/Submit) id l7FCo3G8056030; Wed, 15 Aug 2007 12:50:03 GMT (envelope-from gnats) Resent-Date: Wed, 15 Aug 2007 12:50:03 GMT Resent-Message-Id: <200708151250.l7FCo3G8056030@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Volker Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7F1EE16A41B for ; Wed, 15 Aug 2007 12:45:10 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 69E7213C465 for ; Wed, 15 Aug 2007 12:45:10 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.1/8.14.1) with ESMTP id l7FCjA5E011006 for ; Wed, 15 Aug 2007 12:45:10 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.1/8.14.1/Submit) id l7FCjAqp011005; Wed, 15 Aug 2007 12:45:10 GMT (envelope-from nobody) Message-Id: <200708151245.l7FCjAqp011005@www.freebsd.org> Date: Wed, 15 Aug 2007 12:45:10 GMT From: Volker To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/115547: [PATCH] for GEOM Eli to get password from stdin (useful for non-interactive scripting) X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Aug 2007 12:50:04 -0000 >Number: 115547 >Category: kern >Synopsis: [PATCH] for GEOM Eli to get password from stdin (useful for non-interactive scripting) >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Aug 15 12:50:03 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Volker >Release: >Organization: FreeNAS main developer >Environment: >Description: To get GEOM Eli working in our project (http://www.freenas.org) i had to enhance the geli userland application. The original code does not support non-interactive scripting, e.g. when creating or initializing GEOM Eli filesystem, because the password has to be entered interactively on the console. Because our project is administrated via WebGUI it is not possible to do that. With the patch you can enter the password non-interactively as following: (/bin/echo $passphrase; /bin/echo $passphrase) | /sbin/geli init -t -v -e $ealgo $disk The code has been taken from the Samba tool 'smbpasswd'. The patch itself has been done for CURRENT. I think this is also useful for other users. Greetings Volker /usr/src/sbin/geom/class/eli: --- geom_eli.c.orig Mon Aug 6 10:18:42 2007 +++ geom_eli.c Mon Aug 6 10:36:02 2007 @@ -73,13 +73,15 @@ 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 ... @@ -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_NONE }, G_OPT_SENTINEL }, - NULL, "[-bPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov" + NULL, "[-bPtv] [-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_NONE }, 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_NONE }, G_OPT_SENTINEL }, - NULL, "[-dprv] [-k keyfile] prov" + NULL, "[-dprtv] [-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_NONE }, G_OPT_SENTINEL }, - NULL, "[-pPv] [-n keyno] [-i iterations] [-k keyfile] [-K newkeyfile] prov" + NULL, "[-pPtv] [-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.", @@ -370,9 +376,8 @@ } if (new) { - p = readpassphrase("Reenter new passphrase: ", - buf2, sizeof(buf2), - RPP_ECHO_OFF | RPP_REQUIRE_TTY); + 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)); @@ -1244,3 +1253,42 @@ 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; +} + >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted: