pass

A stripped down version of the standard unix password manager "pass"
git clone git://nocebo.space/pass
Log | Files | Refs | LICENSE

commit ccfdce0900819580b2f6b0941015ac2fbdc71809
parent d73960aadcda4fdf4f787cdf5f0b435873e57bc9
Author: Naveen Narayanan zerous <zerous@nocebo.space>
Date:   Sat, 23 Dec 2017 16:10:07 +0300

Add printpass, delete, and mkdirp. Add log.c

	- implement a common logging interface
	- use basename, readpassphrase
	- fixed compiler warnings

Diffstat:
Makefile | 3++-
log.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
pass.c | 282++++++++++++++++++++++++++++++++++++-------------------------------------------
pass.h | 3+++
readpassphrase.c | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
readpassphrase.h | 31+++++++++++++++++++++++++++++++
6 files changed, 414 insertions(+), 153 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,7 +3,8 @@ VERSION = 0.1 include config.mk OBJ = pass.o \ - log.o + log.o \ + readpassphrase.o BIN = pass diff --git a/log.c b/log.c @@ -1,4 +1,7 @@ #include <errno.h> +#include <gpgme.h> +#include <limits.h> +#include <sys/stat.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -13,7 +16,30 @@ static char *progname; static void vlog(char *msg, va_list ap) { + char file[PATH_MAX]; + const char *home; + FILE *fp; + struct stat sb; + if (debug) { + if (!(home = getenv("HOME"))) { + fprintf(stderr, "$HOME not set, cannot determine password-store location"); + exit(1); + } + snprintf(file, sizeof(file), "%s/.pass.log", home); + + if (!stat(file,&sb)) + remove(file); + else { + if((fp = fopen(file, "ab"))) { + fprintf(fp, "%s: ", progname); + vfprintf(fp, msg, ap); + fputc('\n', fp); + } else { + fprintf(stderr, "fopen %s: %s", file, strerror(errno)); + } + } + } else { fprintf(stderr, "%s: ", progname); vfprintf(stderr, msg, ap); fputc('\n', stderr); @@ -71,6 +97,41 @@ logwarnx(char *msg, ...) } void +loggpg(gpgme_error_t gerr, char *msg, ...) +{ + char buf[512]; + va_list ap; + + va_start(ap, msg); + snprintf(buf, sizeof(buf), "%s: %s", msg, gpgme_strerror(gerr)); + vlog(msg, ap); + va_end(ap); +} + +void +loggpgx(char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(msg, ap); + va_end(ap); +} + +void +fatalgpg(gpgme_error_t gerr, char *msg, ...) +{ + char buf[512]; + va_list ap; + + va_start(ap, msg); + snprintf(buf, sizeof(buf), "%s: %s", msg, gpgme_strerror(gerr)); + vlog(buf, ap); + va_end(ap); + exit(1); +} + +void fatal(char *msg, ...) { char buf[512]; diff --git a/pass.c b/pass.c @@ -1,9 +1,9 @@ -#include <err.h> #include <errno.h> #include <fcntl.h> #include <gpgme.h> #include <getopt.h> #include <limits.h> +#include <libgen.h> #include <locale.h> #include <pwd.h> #include <stdio.h> @@ -13,6 +13,9 @@ #include <unistd.h> #include "pass.h" +#include "readpassphrase.h" + +static char file[PATH_MAX]; void initgpgme(void) @@ -27,139 +30,96 @@ initgpgme(void) } void -find (char *item) -{ - (void)item; -} - -void -delete (char *item) +delete(char *item) { - (void)item; -} - -void -list(void) -{ - + char *home; + int r; + struct sb; + + if (!(home = getenv("HOME"))) + fatalx("$HOME not set, cannot determine password-store location"); + snprintf(file, sizeof(file), "%s/.password-store/%s.gpg", home, item); + printf("Are you sure you would like to delete %s? [y/N] ", item); + if ((r = getchar()) == 'N') + exit(0); + else if (r == 'y') { + if (remove(file)) { + if (debug) + logwarn("rm %s", item); + else { + fatal("rm %s", item); + } + } + printf("removed '%s'\n", file); + } } - void usage(void) { - return; + printf("usage\n"); + exit(0); } void printpass(char *item) { - char file[PATH_MAX], uid[128], buf[512]; + char buf[512]; const char* home; - int fin; - FILE* fp; - /*mode_t mode = S_IRWXU;*/ + int fin, a, ret; + gpgme_data_t in, out; gpgme_error_t gpgerr; gpgme_ctx_t ctx; - /*gpgme_key_t key;*/ - /*gpgme_key_t keys[2];*/ gpgme_protocol_t proto; - gpgme_decrypt_result_t res; - - /* - * Algo: - * Check if file exists - * If it does - * get the uid - * create gpg objects - * open file - * decrypt - * print data - */ - - (void)uid; initgpgme(); proto = GPGME_PROTOCOL_OpenPGP; if (!(home = getenv("HOME"))) - errx(1, "$HOME not set, cannot determine password-store location"); + fatalx("$HOME not set, cannot determine password-store location"); snprintf(file, sizeof(file), "%s/.password-store/%s.gpg", home, item); - /*printf("file: %s\n", file);*/ - /* Check if file exists */ fin = open(file, O_RDONLY); if (fin == -1) { - if (debug) fatal("%s is not in password store.", file); - else - errx(1, "%s is not in password store.", item); } - - - if (gpgme_err_code(gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) - errx(1, "gpme_new"); + gpgerr = gpgme_new(&ctx); + if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) { + fatalgpg(gpgerr, "Error: gpgme_new: %s"); + } gpgerr = gpgme_set_protocol(ctx, proto); if (gpgme_err_code(gpgerr) == GPG_ERR_INV_VALUE) - errx(1, "gpgme_set_protocol"); + fatalgpg(gpgerr, "Error: gpgme_set_protocol"); gpgerr = gpgme_data_new_from_file(&in, file, 1); if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) - err(1, "gpgme_data_new_from_fd: %s\n", gpgme_strerror(gpgerr)); + fatalgpg(gpgerr, "Error: gpgme_data_new_from_file"); gpgerr = gpgme_data_new(&out); if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) - err(1, "gpgme_data_new: %s\n", gpgme_strerror(gpgerr)); - - /* set ascii armor */ - /*gpgme_set_armor(ctx, 1);*/ + fatalgpg(gpgerr, "Error: gpgme_data_new"); /* decrypt */ gpgerr = gpgme_op_decrypt(ctx, in, out); if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) - err(1, " gpgme_op_decrypt: %s\n", gpgme_strerror(gpgerr)); - - (void)res; - /*res = gpgme_op_decrypt_result(ctx);*/ - /*printf("res: %s\n, %d\n, %s\n",*/ - /*res->unsupported_algorithm,*/ - /*res->wrong_key_usage,*/ - /*res->file_name);*/ - - /* print contents of data object */ - /*int ret = gpgme_data_seek(out, 0, SEEK_SET); */ - /*printf("here\n");*/ - /*if (ret) {*/ - /*printf("here\n");*/ - - /*printf("gpgme_data_get_encoding: %s", gpgme_data_get_encoding(out));*/ - + fatalgpg(gpgerr, "Error: gpgme_op_decrypt"); - int a, ret; ret = gpgme_data_seek(out, 0, SEEK_SET); if (ret) - err(1, "gpgme_data_seek"); + fatalx("gpgme_data_seek"); if ((a = gpgme_data_read(out, buf, 100)) > 0) { - /*printf("a : %d", a);*/ buf[a] = '\0'; } printf("%s\n", buf); - /*if ((gpgme_data_read(out, buf, 2)) > 0) {*/ - /*fwrite(buf, ret, 1, stdout);*/ - /*printf("%s", buf);*/ - /*}*/ - /*if (ret < 0)*/ - /*err(1, "can not find key: %s\n", gpgme_strerror(gpgerr));*/ - /*}*/ - - /*gpgme_key_release(key);*/ + gpgme_data_release(in); gpgme_data_release(out); gpgme_release(ctx); + close(fin); } @@ -172,7 +132,7 @@ getuserid(char *u) int i; if (!(home = getenv("HOME"))) - errx(1, "$HOME not set, cannot determine password-store location"); + fatalx("$HOME not set, cannot determine password-store location"); snprintf(file, sizeof(file), "%s/.password-store/.gpg-id", home); fp = fopen(file, "r"); @@ -182,40 +142,12 @@ getuserid(char *u) } void -insert(char *item) +mkdirp(const char *tp) { - char t[PATH_MAX]; - char *tp, *i, *gfile; - const char *home; - char file[PATH_MAX]; - FILE *fp, *fin, *fout; + char *i; int r; - char uid[128]; mode_t mode = S_IRWXU; - gpgme_data_t in, out; - gpgme_error_t gpgerr; - gpgme_ctx_t ctx; - gpgme_key_t key; - gpgme_key_t keys[2]; - gpgme_protocol_t proto; - - initgpgme(); - proto = GPGME_PROTOCOL_OpenPGP; - memcpy(t, item, strlen(item)+1); - if (!(home = getenv("HOME"))) - errx(1, "$HOME not set, cannot determine password-store location"); - snprintf(file, sizeof(file), "%s/.password-store", home); - - tp = t; - if ((i = strrchr(tp, '/'))) { - gfile = i + 1; - } else - gfile = item; -#ifdef DEBUG - printf("gfile: %s\n", gfile); -#endif - while ((i = strchr(tp, '/'))) { *i = '\0'; snprintf(file, sizeof(file), "%s/%s", file, tp); @@ -224,38 +156,81 @@ insert(char *item) if (errno == EEXIST) ; else - err(1, "mkdir"); + fatal("mkdir"); } tp = i + 1; } - snprintf(file, sizeof(file), "%s/%s", file, gfile); +} + +void +insert(char *item) +{ + gpgme_data_t in, out; + gpgme_error_t gpgerr; + gpgme_ctx_t ctx; + gpgme_key_t key; + gpgme_key_t keys[2]; + gpgme_protocol_t proto; + + char *filename, t[PATH_MAX]; + const char *home; + FILE *fp, *fin, *fout; + char uid[128], pass[128]; + + key = NULL; + + if (!(home = getenv("HOME"))) + fatalx("$HOME not set, cannot determine password-store location"); + snprintf(file, sizeof(file), "%s/.password-store", home); + + filename = basename(item); + mkdirp(item); - /* TO-DO: - * * Have to check if the file exists - * * if it does - * ask if user wants to overwrite the file - * * re-confirm password before writing to file - */ + snprintf(file, sizeof(file), "%s/%s", file, filename); + + snprintf(t, sizeof(t), "%s.gpg", file); + if ((fp = fopen(t, "r"))) { + printf("An entry already exists for %s. Overwrite it? [y/N] ", filename); + if (getchar() == 'N') { + logdbgx("Don't overwrite"); + exit(1); + } + } printf("file: %s\n", file); if (!(fp = fopen(file, "w+b"))) - err(1, "fopen"); - printf("Enter password for %s: ", item); - while ((r = getchar()) != '\n' && r != EOF) { - if (fputc(r, fp) == EOF) - err(1, "fputc"); + fatal("fopen: %s", file); + readpassphrase("Enter password: ", pass, 128, RPP_ECHO_OFF); + memcpy(t, pass, strlen(pass) + 1); + readpassphrase("Retype password: ", pass, 128, RPP_ECHO_OFF); + if (!strcmp(pass, t)) + { + int i = 0; + while(t[i] != '\0') { + if (fputc(t[i], fp) == EOF) + fatal("fputc: %s", file); + i++; + } + } else { + if (debug) + fatalx("Passwords don't match."); + else + fatalx("Passwords don't match."); } - fclose(fp); - getuserid(uid); - if (gpgme_err_code(gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) - errx(1, "gpme_new"); + proto = GPGME_PROTOCOL_OpenPGP; + initgpgme(); + gpgerr = gpgme_new(&ctx); + if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) + fatalgpg(gpgerr, "gpme_new"); gpgerr = gpgme_set_protocol(ctx, proto); if (gpgme_err_code(gpgerr) == GPG_ERR_INV_VALUE) - errx(1, "gpgme_set_protocol"); + fatalgpg(gpgerr, "gpgme_set_protocol"); + + gpgme_set_armor(ctx, 1); if (gpgme_op_keylist_start(ctx, uid, 0) != GPG_ERR_INV_VALUE) while (!(gpgerr = gpgme_op_keylist_next(ctx, &key))) { @@ -263,38 +238,36 @@ insert(char *item) break; } } - /* throw an error if the respective key isn't found */ if (gpgme_err_code(gpgerr) == GPG_ERR_EOF) - err(1, "can not find key: %s\n", gpgme_strerror(gpgerr)); + fatalgpg(gpgerr, "can not find key"); keys[0] = key; keys[1] = NULL; - /* set ascii armor */ - gpgme_set_armor(ctx, 1); - fin = fopen(file, "r"); memcpy(t, file, strlen(file) + 1); snprintf(file, sizeof(file), "%s.gpg", file); fout = fopen(file, "w"); + gpgerr = gpgme_data_new_from_stream(&in, fin); if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) - errx(1, "gpgme_data_new_from_file %s", gpgme_strerror(gpgerr)); + fatalgpg(gpgerr, "gpgme_data_new_from_stream"); gpgerr = gpgme_data_new_from_stream(&out, fout); gpgme_data_set_encoding(out, GPGME_DATA_ENCODING_ARMOR); if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) - errx(1, "gpgme_data_new: %s", gpgme_strerror(gpgerr)); + fatalgpg(gpgerr, "gpgme_data_new_from_stream"); gpgerr = gpgme_op_encrypt(ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) - errx(1, "gpgme_op_encrypt: %s", gpgme_strerror(gpgerr)); + fatalgpg(gpgerr, "gpgme_op_encrypt"); gpgme_key_release(key); gpgme_data_release(in); gpgme_data_release(out); gpgme_release(ctx); + fclose(fin); fclose(fout); if (remove(t)) @@ -311,7 +284,7 @@ isinit(void) /* check if .password-store exists */ struct stat sb; if (!(home = getenv("HOME"))) - errx(1, "$HOME not set, cannot determine password-store location"); + fatalx("$HOME not set, cannot determine password-store location"); snprintf(file, sizeof(file), "%s/.password-store", home); @@ -335,31 +308,36 @@ initpass(char *pgpid) FILE *gpg; mode_t mode = S_IRWXU; + if (!pgpid) { + usage(); + } + + if (!isinit()) { if (!(home = getenv("HOME"))) - errx(1, "$HOME not set, cannot determine password-store location"); + fatalx("$HOME not set, cannot determine password-store location"); snprintf(file, sizeof(file), "%s/.password-store", home); if (mkdir(file, mode)) - err(1, "mkdir"); + fatal("mkdir"); snprintf(file, sizeof(file), "%s/.password-store/.gpg-id", home); #ifdef DEBUG printf("file: %s", file); #endif if (!(gpg = fopen(file, "a"))) - err(1, "fopen"); + fatal("fopen"); if (fputs(pgpid, gpg) == EOF) - err(1, "fputs"); + fatal("fputs"); printf("Password store initialized for %s\n", pgpid); fclose(gpg); } else { - errx(1, "Password store initialized for %s\n", pgpid); + printf("Password store initialized for %s\n", pgpid); } } @@ -367,6 +345,12 @@ int main(int argc, char** argv) { debug = 0; + + for (char *s = *argv, i = 0; i < argc; i++) { + if (!strcmp("-d", s)) + debug = 1; + s++; + } if (debug) loginit("pass"); if (argc > 1) @@ -377,18 +361,12 @@ main(int argc, char** argv) initpass(*(argv + 1)); else if (!strcmp("insert", *argv)) insert(*(argv + 1)); - else if (!strcmp("ls", *argv)) - list(); else if (!strcmp("rm", *argv)) delete(*(argv + 1)); - else if (!strcmp("find", *argv)) - find(*(argv + 1)); else printpass(*argv); - } else { - list(); - } + } return 0; } diff --git a/pass.h b/pass.h @@ -9,3 +9,6 @@ void logwarn(char *, ...); void logwarnx(char *, ...); void fatal(char *, ...); void fatalx(char *, ...); +void loggpg(gpgme_error_t, char *, ...); +void loggpgx(char *, ...); +void fatalgpg(gpgme_error_t, char *, ...); diff --git a/readpassphrase.c b/readpassphrase.c @@ -0,0 +1,187 @@ +/* $OpenBSD: readpassphrase.c,v 1.25 2015/09/14 10:45:27 guenther Exp $ */ + +/* + * Copyright (c) 2000-2002, 2007, 2010 + * Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <pwd.h> +#include <signal.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#include "readpassphrase.h" + +#ifdef TCSASOFT +#define _T_FLUSH (TCSAFLUSH|TCSASOFT) +#else +#define _T_FLUSH (TCSAFLUSH) +#endif + +static volatile sig_atomic_t signo[_NSIG]; + +static void handler(int); + +char * +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) +{ + ssize_t nr; + int input, output, save_errno, i, need_restart; + char ch, *p, *end; + struct termios term, oterm; + struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou, savepipe; + + /* I suppose we could alloc on demand in this case (XXX). */ + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); + } + +restart: + for (i = 0; i < _NSIG; i++) + signo[i] = 0; + nr = -1; + save_errno = 0; + need_restart = 0; + /* + * Read and write to /dev/tty if available. If not, read from + * stdin and write to stderr unless a tty is required. + */ + if ((flags & RPP_STDIN) || + (input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if (flags & RPP_REQUIRE_TTY) { + errno = ENOTTY; + return(NULL); + } + input = STDIN_FILENO; + output = STDERR_FILENO; + } + + /* + * Turn off echo if possible. + * If we are using a tty but are not the foreground pgrp this will + * generate SIGTTOU, so do it *before* installing the signal handlers. + */ + if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { + memcpy(&term, &oterm, sizeof(term)); + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); +#ifdef VSTATUS + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + (void)tcsetattr(input, _T_FLUSH, &term); + } else { + memset(&term, 0, sizeof(term)); + term.c_lflag |= ECHO; + memset(&oterm, 0, sizeof(oterm)); + oterm.c_lflag |= ECHO; + } + + /* + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGXCPU and SIGVTALRM for now. + */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_handler = handler; + (void)sigaction(SIGALRM, &sa, &savealrm); + (void)sigaction(SIGHUP, &sa, &savehup); + (void)sigaction(SIGINT, &sa, &saveint); + (void)sigaction(SIGPIPE, &sa, &savepipe); + (void)sigaction(SIGQUIT, &sa, &savequit); + (void)sigaction(SIGTERM, &sa, &saveterm); + (void)sigaction(SIGTSTP, &sa, &savetstp); + (void)sigaction(SIGTTIN, &sa, &savettin); + (void)sigaction(SIGTTOU, &sa, &savettou); + + if (!(flags & RPP_STDIN)) + (void)write(output, prompt, strlen(prompt)); + end = buf + bufsiz - 1; + p = buf; + while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch &= 0x7f; + if (isalpha((unsigned char)ch)) { + if ((flags & RPP_FORCELOWER)) + ch = (char)tolower((unsigned char)ch); + if ((flags & RPP_FORCEUPPER)) + ch = (char)toupper((unsigned char)ch); + } + *p++ = ch; + } + } + *p = '\0'; + save_errno = errno; + if (!(term.c_lflag & ECHO)) + (void)write(output, "\n", 1); + + /* Restore old terminal settings and signals. */ + if (memcmp(&term, &oterm, sizeof(term)) != 0) { + while (tcsetattr(input, _T_FLUSH, &oterm) == -1 && + errno == EINTR && !signo[SIGTTOU]) + continue; + } + (void)sigaction(SIGALRM, &savealrm, NULL); + (void)sigaction(SIGHUP, &savehup, NULL); + (void)sigaction(SIGINT, &saveint, NULL); + (void)sigaction(SIGQUIT, &savequit, NULL); + (void)sigaction(SIGPIPE, &savepipe, NULL); + (void)sigaction(SIGTERM, &saveterm, NULL); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); + (void)sigaction(SIGTTOU, &savettou, NULL); + if (input != STDIN_FILENO) + (void)close(input); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + for (i = 0; i < _NSIG; i++) { + if (signo[i]) { + kill(getpid(), i); + switch (i) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + need_restart = 1; + } + } + } + if (need_restart) + goto restart; + + if (save_errno) + errno = save_errno; + return(nr == -1 ? NULL : buf); +} + +static void handler(int s) +{ + signo[s] = 1; +} diff --git a/readpassphrase.h b/readpassphrase.h @@ -0,0 +1,31 @@ +/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */ + +/* + * Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ +#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ + +char *readpassphrase(const char *, char *, size_t, int);