getpass() tries to use /dev/tty by default, which requests input directly
from the user, which prevents a controlling process from writing the input
to stdin. Add a config option to always listen for input on stdin and
implement a replacement for getpass() that always reads from stdin. The
config option performs no TTY operations on stdin (eg, unlike getpass()
it does not disable echo) so the config option should only if vpnc is
spawned from another program and pipes are used for communication.
---
trunk/config.c | 34 +++++++++++++++++++++++++++++++++-
trunk/config.h | 2 ++
trunk/vpnc.c | 6 +++++-
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/trunk/config.c b/trunk/config.c
index e02a66f..fa7798b 100644
--- a/trunk/config.c
+++ b/trunk/config.c
@@ -128,6 +128,31 @@ static char *vpnc_getline(size_t *out_size, FILE *stream)
return buf;
}
+char *vpnc_getpass (const char *prompt, int always_stdin)
+{
+ char *buf = NULL;
+ size_t llen = 0;
+
+ /* Standard getpass() tries to open the TTY first so if the caller
+ * always wants to use stdin, roll our own naive implementation.
+ */
+
+ if (!always_stdin) {
+ buf = getpass(prompt);
+ return buf ? strdup (buf) : NULL;
+ }
+
+ fprintf(stderr, "%s", prompt);
+ setbuf(stdin, NULL);
+ buf = vpnc_getline(&llen, stdin);
+ if (buf != NULL && llen > 0 && buf[llen - 1] == '\n') {
+ /* Remove the newline. */
+ buf[llen - 1] = '\0';
+ }
+
+ return buf;
+}
+
static void config_deobfuscate(int obfuscated, int clear)
{
int ret, len = 0;
@@ -470,6 +495,13 @@ static const struct config_names_s {
"Don't ask anything, exit on missing options",
NULL
}, {
+ CONFIG_INTERACTIVE_STDIN, 0, 1,
+ "--interactive-stdin",
+ "InteractiveStdin",
+ NULL,
+ "Always look for interactive input on stdin instead of the TTY",
+ NULL
+ }, {
CONFIG_AUTH_MODE, 1, 1,
"--auth-mode",
"IKE Authmode ",
@@ -839,7 +871,7 @@ void do_config(int argc, char **argv)
switch (i) {
case CONFIG_IPSEC_SECRET:
case CONFIG_XAUTH_PASSWORD:
- s = strdup(getpass(""));
+ s = vpnc_getpass("", !!config[CONFIG_INTERACTIVE_STDIN]);
break;
case CONFIG_IPSEC_GATEWAY:
case CONFIG_IPSEC_ID:
diff --git a/trunk/config.h b/trunk/config.h
index 6fbd231..0460d83 100644
--- a/trunk/config.h
+++ b/trunk/config.h
@@ -59,6 +59,7 @@ enum config_enum {
CONFIG_AUTH_MODE,
CONFIG_CA_FILE,
CONFIG_CA_DIR,
+ CONFIG_INTERACTIVE_STDIN,
LAST_CONFIG
};
@@ -131,6 +132,7 @@ extern uint16_t opt_udpencapport;
extern void hex_dump(const char *str, const void *data, ssize_t len, const struct debug_strings *decode);
extern void do_config(int argc, char **argv);
+extern char *vpnc_getpass(const char *prompt, int always_stdin);
extern void (*logmsg)(int priority, const char *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
diff --git a/trunk/vpnc.c b/trunk/vpnc.c
index eaa29fa..9e548c4 100644
--- a/trunk/vpnc.c
+++ b/trunk/vpnc.c
@@ -2308,14 +2308,18 @@ static int do_phase2_xauth(struct sa_block *s)
(ap->type == ISAKMP_XAUTH_06_ATTRIB_USER_PASSWORD) ?
"Password" : "Passcode",
config[CONFIG_XAUTH_USERNAME], ntop_buf);
- pass = getpass(prompt);
+ pass = vpnc_getpass(prompt, !!config[CONFIG_INTERACTIVE_STDIN]);
free(prompt);
+ if (pass == NULL)
+ phase2_fatal(s, "failed to read password", reject);
+
na = new_isakmp_attribute(ap->type, NULL);
na->u.lots.length = strlen(pass);
na->u.lots.data = xallocc(na->u.lots.length);
memcpy(na->u.lots.data, pass, na->u.lots.length);
memset(pass, 0, na->u.lots.length);
+ free(pass);
} else {
na = new_isakmp_attribute(ap->type, NULL);
na->u.lots.length = strlen(config[CONFIG_XAUTH_PASSWORD]);
--
1.8.1.4
_______________________________________________
vpnc-devel mailing list
vpnc-devel@unix-ag.uni-kl.de
https://lists.unix-ag.uni-kl.de/mailman/listinfo/vpnc-devel
http://www.unix-ag.uni-kl.de/~massar/vpnc/
from the user, which prevents a controlling process from writing the input
to stdin. Add a config option to always listen for input on stdin and
implement a replacement for getpass() that always reads from stdin. The
config option performs no TTY operations on stdin (eg, unlike getpass()
it does not disable echo) so the config option should only if vpnc is
spawned from another program and pipes are used for communication.
---
trunk/config.c | 34 +++++++++++++++++++++++++++++++++-
trunk/config.h | 2 ++
trunk/vpnc.c | 6 +++++-
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/trunk/config.c b/trunk/config.c
index e02a66f..fa7798b 100644
--- a/trunk/config.c
+++ b/trunk/config.c
@@ -128,6 +128,31 @@ static char *vpnc_getline(size_t *out_size, FILE *stream)
return buf;
}
+char *vpnc_getpass (const char *prompt, int always_stdin)
+{
+ char *buf = NULL;
+ size_t llen = 0;
+
+ /* Standard getpass() tries to open the TTY first so if the caller
+ * always wants to use stdin, roll our own naive implementation.
+ */
+
+ if (!always_stdin) {
+ buf = getpass(prompt);
+ return buf ? strdup (buf) : NULL;
+ }
+
+ fprintf(stderr, "%s", prompt);
+ setbuf(stdin, NULL);
+ buf = vpnc_getline(&llen, stdin);
+ if (buf != NULL && llen > 0 && buf[llen - 1] == '\n') {
+ /* Remove the newline. */
+ buf[llen - 1] = '\0';
+ }
+
+ return buf;
+}
+
static void config_deobfuscate(int obfuscated, int clear)
{
int ret, len = 0;
@@ -470,6 +495,13 @@ static const struct config_names_s {
"Don't ask anything, exit on missing options",
NULL
}, {
+ CONFIG_INTERACTIVE_STDIN, 0, 1,
+ "--interactive-stdin",
+ "InteractiveStdin",
+ NULL,
+ "Always look for interactive input on stdin instead of the TTY",
+ NULL
+ }, {
CONFIG_AUTH_MODE, 1, 1,
"--auth-mode",
"IKE Authmode ",
@@ -839,7 +871,7 @@ void do_config(int argc, char **argv)
switch (i) {
case CONFIG_IPSEC_SECRET:
case CONFIG_XAUTH_PASSWORD:
- s = strdup(getpass(""));
+ s = vpnc_getpass("", !!config[CONFIG_INTERACTIVE_STDIN]);
break;
case CONFIG_IPSEC_GATEWAY:
case CONFIG_IPSEC_ID:
diff --git a/trunk/config.h b/trunk/config.h
index 6fbd231..0460d83 100644
--- a/trunk/config.h
+++ b/trunk/config.h
@@ -59,6 +59,7 @@ enum config_enum {
CONFIG_AUTH_MODE,
CONFIG_CA_FILE,
CONFIG_CA_DIR,
+ CONFIG_INTERACTIVE_STDIN,
LAST_CONFIG
};
@@ -131,6 +132,7 @@ extern uint16_t opt_udpencapport;
extern void hex_dump(const char *str, const void *data, ssize_t len, const struct debug_strings *decode);
extern void do_config(int argc, char **argv);
+extern char *vpnc_getpass(const char *prompt, int always_stdin);
extern void (*logmsg)(int priority, const char *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
diff --git a/trunk/vpnc.c b/trunk/vpnc.c
index eaa29fa..9e548c4 100644
--- a/trunk/vpnc.c
+++ b/trunk/vpnc.c
@@ -2308,14 +2308,18 @@ static int do_phase2_xauth(struct sa_block *s)
(ap->type == ISAKMP_XAUTH_06_ATTRIB_USER_PASSWORD) ?
"Password" : "Passcode",
config[CONFIG_XAUTH_USERNAME], ntop_buf);
- pass = getpass(prompt);
+ pass = vpnc_getpass(prompt, !!config[CONFIG_INTERACTIVE_STDIN]);
free(prompt);
+ if (pass == NULL)
+ phase2_fatal(s, "failed to read password", reject);
+
na = new_isakmp_attribute(ap->type, NULL);
na->u.lots.length = strlen(pass);
na->u.lots.data = xallocc(na->u.lots.length);
memcpy(na->u.lots.data, pass, na->u.lots.length);
memset(pass, 0, na->u.lots.length);
+ free(pass);
} else {
na = new_isakmp_attribute(ap->type, NULL);
na->u.lots.length = strlen(config[CONFIG_XAUTH_PASSWORD]);
--
1.8.1.4
_______________________________________________
vpnc-devel mailing list
vpnc-devel@unix-ag.uni-kl.de
https://lists.unix-ag.uni-kl.de/mailman/listinfo/vpnc-devel
http://www.unix-ag.uni-kl.de/~massar/vpnc/