X-Git-Url: http://git.bytex64.net/?a=blobdiff_plain;f=builddeps%2Fscrypt-1.1.6%2Flib%2Futil%2Freadpass.c;fp=builddeps%2Fscrypt-1.1.6%2Flib%2Futil%2Freadpass.c;h=91f77e0e7b3dd548b6e65ef83789269632bfa92a;hb=46a8b671b3c707db689868d9b6544d272aa711a7;hp=0000000000000000000000000000000000000000;hpb=e35e2482b85c6e7bbac334a8496472a8b7b0d170;p=blerg.git diff --git a/builddeps/scrypt-1.1.6/lib/util/readpass.c b/builddeps/scrypt-1.1.6/lib/util/readpass.c new file mode 100644 index 0000000..91f77e0 --- /dev/null +++ b/builddeps/scrypt-1.1.6/lib/util/readpass.c @@ -0,0 +1,143 @@ +/*- + * Copyright 2009 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "scrypt_platform.h" + +#include +#include +#include +#include +#include + +#include "warn.h" + +#include "readpass.h" + +#define MAXPASSLEN 2048 + +/** + * tarsnap_getpass(passwd, prompt, confirmprompt, devtty) + * If ${devtty} is non-zero, read a password from /dev/tty if possible; if + * not, read from stdin. If reading from a tty (either /dev/tty or stdin), + * disable echo and prompt the user by printing ${prompt} to stderr. If + * ${confirmprompt} is non-NULL, read a second password (prompting if a + * terminal is being used) and repeat until the user enters the same password + * twice. Return the password as a malloced NUL-terminated string via + * ${passwd}. The obscure name is to avoid namespace collisions due to the + * getpass / readpass / readpassphrase / etc. functions in various libraries. + */ +int +tarsnap_readpass(char ** passwd, const char * prompt, + const char * confirmprompt, int devtty) +{ + FILE * readfrom; + char passbuf[MAXPASSLEN]; + char confpassbuf[MAXPASSLEN]; + struct termios term, term_old; + int usingtty; + + /* + * If devtty != 0, try to open /dev/tty; if that fails, or if devtty + * is zero, we'll read the password from stdin instead. + */ + if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) + readfrom = stdin; + + /* If we're reading from a terminal, try to disable echo. */ + if ((usingtty = isatty(fileno(readfrom))) != 0) { + if (tcgetattr(fileno(readfrom), &term_old)) { + warn("Cannot read terminal settings"); + goto err1; + } + memcpy(&term, &term_old, sizeof(struct termios)); + term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL; + if (tcsetattr(fileno(readfrom), TCSANOW, &term)) { + warn("Cannot set terminal settings"); + goto err1; + } + } + +retry: + /* If we have a terminal, prompt the user to enter the password. */ + if (usingtty) + fprintf(stderr, "%s: ", prompt); + + /* Read the password. */ + if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) { + warn("Cannot read password"); + goto err2; + } + + /* Confirm the password if necessary. */ + if (confirmprompt != NULL) { + if (usingtty) + fprintf(stderr, "%s: ", confirmprompt); + if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) { + warn("Cannot read password"); + goto err2; + } + if (strcmp(passbuf, confpassbuf)) { + fprintf(stderr, + "Passwords mismatch, please try again\n"); + goto retry; + } + } + + /* Terminate the string at the first "\r" or "\n" (if any). */ + passbuf[strcspn(passbuf, "\r\n")] = '\0'; + + /* If we changed terminal settings, reset them. */ + if (usingtty) + tcsetattr(fileno(readfrom), TCSANOW, &term_old); + + /* Close /dev/tty if we opened it. */ + if (readfrom != stdin) + fclose(readfrom); + + /* Copy the password out. */ + if ((*passwd = strdup(passbuf)) == NULL) { + warn("Cannot allocate memory"); + goto err1; + } + + /* Zero any stored passwords. */ + memset(passbuf, 0, MAXPASSLEN); + memset(confpassbuf, 0, MAXPASSLEN); + + /* Success! */ + return (0); + +err2: + /* Reset terminal settings if necessary. */ + if (usingtty) + tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old); +err1: + /* Close /dev/tty if we opened it. */ + if (readfrom != stdin) + fclose(readfrom); + + /* Failure! */ + return (-1); +}