diff --git a/src/readpass.h b/include/pcp/readpass.h similarity index 87% rename from src/readpass.h rename to include/pcp/readpass.h index 477e942..b0714cb 100644 --- a/src/readpass.h +++ b/include/pcp/readpass.h @@ -35,9 +35,14 @@ #include #include +#include +#include +#include +#include + #include "defines.h" #include "context.h" -#include "pcp.h" +#include "util.h" #define MAXPASSLEN 2048 @@ -52,6 +57,13 @@ * ${passwd}. The obscure name is to avoid namespace collisions due to the * getpass / readpass / readpassphrase / etc. functions in various libraries. */ -int pcp_readpass(char **, const char *, const char *, int, char *); +int pcp_readpass(PCPCTX *ptx, char **passwd, const char *prompt, + const char *confirmprompt, int devtty, char *readfromfile); + +/** + from encfs getUserKey(). + +*/ +int pcp_readpass_fromprog(PCPCTX *ptx, char **passwd, const char *askpass); #endif /* !_READPASS_H_ */ diff --git a/src/readpass.c b/libpcp/readpass.c similarity index 58% rename from src/readpass.c rename to libpcp/readpass.c index 6ff7faa..6a3ac60 100644 --- a/src/readpass.c +++ b/libpcp/readpass.c @@ -39,7 +39,7 @@ * getpass / readpass / readpassphrase / etc. functions in various libraries. */ int -pcp_readpass(char ** passwd, const char * prompt, +pcp_readpass(PCPCTX *ptx, char ** passwd, const char * prompt, const char * confirmprompt, int devtty, char *readfromfile) { FILE * readfrom; @@ -58,6 +58,9 @@ pcp_readpass(char ** passwd, const char * prompt, */ if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) { if(readfromfile != NULL) { + // FIXME: check if readfromfile is executable, + // if yes, call askextpass(tobewritten) and + // read from the returned fd somehow if(readfromfile[0] == '-') { readfrom = stdin; } @@ -154,3 +157,114 @@ err1: /* Failure! */ return (-1); } + + +/***************************************************************************** + * Author: Valient Gough + * + ***************************************************************************** + * Copyright (c) 2004, Valient Gough + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * modified by tlinden@cpan.org (c++ => c, pcp api) + */ + +int pcp_readpass_fromprog(PCPCTX *ptx, char **passwd, const char *askpass) { + // have a child process run the command and get the result back to us. + int fds[2], pid; + int res; + char passbuf[MAXPASSLEN]; + + res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds); + if (res == -1) { + fatal(ptx, "Internal error: socketpair() failed"); + goto aerr1; + } + + pid = fork(); + if (pid == -1) { + fatal( ptx, "Internal error: fork() failed"); + close(fds[0]); + close(fds[1]); + goto aerr1; + } + + if (pid == 0) { + const char *argv[4]; + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = askpass; + argv[3] = 0; + + // child process.. run the command and send output to fds[0] + close(fds[1]); // we don't use the other half.. + + // make a copy of stdout and stderr descriptors, and set an environment + // variable telling where to find them, in case a child wants it.. + int stdOutCopy = dup(STDOUT_FILENO); + int stdErrCopy = dup(STDERR_FILENO); + + // replace STDOUT with our socket, which we'll used to receive the + // password.. + dup2(fds[0], STDOUT_FILENO); + + // ensure that STDOUT_FILENO and stdout/stderr are not closed on exec.. + fcntl(STDOUT_FILENO, F_SETFD, 0); // don't close on exec.. + fcntl(stdOutCopy, F_SETFD, 0); + fcntl(stdErrCopy, F_SETFD, 0); + + char tmpBuf[8]; + + snprintf(tmpBuf, sizeof(tmpBuf) - 1, "%i", stdOutCopy); + setenv("PCP_ENV_STDOUT", tmpBuf, 1); + + snprintf(tmpBuf, sizeof(tmpBuf) - 1, "%i", stdErrCopy); + setenv("PCP_ENV_STDERR", tmpBuf, 1); + + execvp(argv[0], (char *const *)argv); // returns only on error.. + + fatal(ptx, "Internal error: failed to exec program"); + goto aerr1; + } + + close(fds[0]); + + memset(passbuf, 0, MAXPASSLEN); + if ( recv(fds[1], passbuf, MAXPASSLEN, 0) <= 0) { + fatal(ptx, "Cannot read password\n"); + goto aerr1; + } + + + close(fds[1]); + + waitpid(pid, NULL, 0); + + /* Terminate the string at the first "\r" or "\n" (if any). */ + passbuf[strcspn(passbuf, "\r\n")] = '\0'; + + /* Copy the password out. */ + char *p = smalloc(strlen(passbuf) + 1); + memcpy(p, passbuf, strlen(passbuf) + 1 ); + *passwd = p; + + /* Zero any stored passwords. */ + memset(passbuf, 0, MAXPASSLEN); + + return 0; + + aerr1: + return -1; +} diff --git a/man/options.pod b/man/options.pod index 22efe89..48550e4 100644 --- a/man/options.pod +++ b/man/options.pod @@ -15,6 +15,7 @@ is -, read from stdin. This takes precedence over other uses of stdin elsewhere, see below for more details. + --extpass Use external program for password prompt. -i --keyid Specify a key id to import/export. -r --recipient Specify a recpipient, used for public key export and encryption. diff --git a/man/pcp1.1 b/man/pcp1.1 index c16bae7..884f198 100644 --- a/man/pcp1.1 +++ b/man/pcp1.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) +.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PCP1 1" -.TH PCP1 1 "2015-07-22" "PCP 0.3.0" "USER CONTRIBUTED DOCUMENTATION" +.TH PCP1 1 "2015-07-30" "PCP 0.3.1" "USER CONTRIBUTED DOCUMENTATION" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -161,6 +161,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography. \& \-x \-\-xpass Provide password. INSECURE! Use for testing \& or debugging only! \& \-X \-\-password\-file Read passphrase from . +\& \-\-extpass Use external program for password prompt. \& \-i \-\-keyid Specify a key id for various operations. \& \-r \-\-recipient Specify a recpipient, multiple allowed. \& \-t \-\-text Print textual representation of ojects. @@ -218,6 +219,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography. \& is \-, read from stdin. This takes \& precedence over other uses of stdin \& elsewhere, see below for more details. +\& \-\-extpass Use external program for password prompt. \& \-i \-\-keyid Specify a key id to import/export. \& \-r \-\-recipient Specify a recpipient, used for public \& key export and encryption. diff --git a/man/pcp1.html b/man/pcp1.html index 4b5effb..99691e5 100644 --- a/man/pcp1.html +++ b/man/pcp1.html @@ -7,7 +7,7 @@ - + @@ -89,6 +89,7 @@ -x --xpass <passwd> Provide password. INSECURE! Use for testing or debugging only! -X --password-file <file> Read passphrase from <file>. + --extpass <program> Use external program for password prompt. -i --keyid <id> Specify a key id for various operations. -r --recipient <string> Specify a recpipient, multiple allowed. -t --text Print textual representation of ojects. @@ -146,6 +147,7 @@ is -, read from stdin. This takes precedence over other uses of stdin elsewhere, see below for more details. + --extpass <program> Use external program for password prompt. -i --keyid <id> Specify a key id to import/export. -r --recipient <string> Specify a recpipient, used for public key export and encryption. diff --git a/man/pcp1.pod b/man/pcp1.pod index 1e5c28e..e463bfc 100644 --- a/man/pcp1.pod +++ b/man/pcp1.pod @@ -24,6 +24,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography. -x --xpass Provide password. INSECURE! Use for testing or debugging only! -X --password-file Read passphrase from . + --extpass Use external program for password prompt. -i --keyid Specify a key id for various operations. -r --recipient Specify a recpipient, multiple allowed. -t --text Print textual representation of ojects. @@ -81,6 +82,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography. is -, read from stdin. This takes precedence over other uses of stdin elsewhere, see below for more details. + --extpass Use external program for password prompt. -i --keyid Specify a key id to import/export. -r --recipient Specify a recpipient, used for public key export and encryption. diff --git a/src/pcp.c b/src/pcp.c index f048498..52fe527 100644 --- a/src/pcp.c +++ b/src/pcp.c @@ -66,6 +66,7 @@ int main (int argc, char **argv) { char *xpassfile = NULL; char *extra = NULL; plist_t *recipient = NULL; + char *askpass = NULL; FILE *in; errno = 0; @@ -93,6 +94,7 @@ int main (int argc, char **argv) { { "text", required_argument, NULL, 't' }, { "xpass", required_argument, NULL, 'x' }, { "password-file", required_argument, NULL, 'X' }, + { "extpass", required_argument, NULL, LONG_EXTPASS }, { "recipient", required_argument, NULL, 'r' }, /* key management */ @@ -271,6 +273,10 @@ int main (int argc, char **argv) { if(strncmp(xpass, "n/a", 3) == 0) xpass[0] = '\0'; break; + case LONG_EXTPASS: + askpass = malloc(strlen(optarg)+1); + strncpy(askpass, optarg, strlen(optarg)+1); + break; case 'r': p_add(&recipient, optarg); userec = 1; @@ -415,12 +421,18 @@ int main (int argc, char **argv) { } if(xpassfile != NULL) { - pcp_readpass(&xpass, "passphrase", NULL, 0, xpassfile); + if(pcp_readpass(ptx, &xpass, "passphrase", NULL, 0, xpassfile) != 0) + goto perr1; if(xpassfile[0] != '-') xpf = 0; free(xpassfile); } + if(askpass != NULL) { + if(pcp_readpass_fromprog(ptx, &xpass, askpass) != 0) + goto perr1; + } + /* check if there's some enviroment we could use */ if(usevault == 1) { char *_vaultfile = getenv("PCP_VAULT"); @@ -631,7 +643,8 @@ int main (int argc, char **argv) { break; } } - + + perr1: fatals_ifany(ptx); int e = ptx->pcp_exit; ptx_clean(ptx); @@ -646,6 +659,10 @@ int main (int argc, char **argv) { free(sigfile); if(xpass != NULL) sfree(xpass); + if(askpass != NULL) + free(askpass); + if(xpassfile != NULL) + free(xpassfile); if(recipient != NULL) p_clean(recipient); if(id != NULL) diff --git a/src/pcp.h b/src/pcp.h index 6dc1ce4..6216d85 100644 --- a/src/pcp.h +++ b/src/pcp.h @@ -85,6 +85,8 @@ #define PCP_HELP_INTRO "This is Pretty Curved Privacy. Licensed under the GPLv3. This is\n" \ "BETA software. Use with care. NOT intended for production use.\n" +#define LONG_EXTPASS 515 + /* some globals */ vault_t *vault; PCPCTX *ptx; diff --git a/src/usage.h b/src/usage.h index c305c20..e1d753e 100644 --- a/src/usage.h +++ b/src/usage.h @@ -19,6 +19,7 @@ "-x --xpass Provide password. INSECURE! Use for testing\n" \ " or debugging only!\n" \ "-X --password-file Read passphrase from .\n" \ +" --extpass Use external program for password prompt.\n" \ "-i --keyid Specify a key id for various operations.\n" \ "-r --recipient Specify a recpipient, multiple allowed.\n" \ "-t --text Print textual representation of ojects.\n" \ diff --git a/src/usage.txt b/src/usage.txt index f605590..50ec94a 100644 --- a/src/usage.txt +++ b/src/usage.txt @@ -17,6 +17,7 @@ General Options: -x --xpass Provide password. INSECURE! Use for testing or debugging only! -X --password-file Read passphrase from . + --extpass Use external program for password prompt. -i --keyid Specify a key id for various operations. -r --recipient Specify a recpipient, multiple allowed. -t --text Print textual representation of ojects.