Allows to integrate UI, similar to ssh-askpass, program prompt user
for password and echo result to stdout.
Settings:
---
Password Helper /home/alonbl/vpnc/vpnc-getpass
Xauth interactive
---
vpn-getpass script for KDE:
---
prompt="$1"
exec kdialog --title "vpnc" --password "$prompt";
---
vpn-getpass script for KDE with SecurID:
---
prompt="$1"
pass="$(kdialog --title "vpnc" --password "$prompt")" || exit 1
otp="$(RSA_SecurID_getpasswd)" || exit 1
echo "${pass}${otp}"
exit 0
---
Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
---
config.c | 17 +++++++-
config.h | 1 +
vpnc.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
vpnc.h | 2 +
4 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/config.c b/config.c
index 0351e9b..90e8df5 100644
--- a/config.c
+++ b/config.c
@@ -469,6 +469,13 @@ static const struct config_names_s {
"Target network in dotted decimal or CIDR notation\n",
config_def_target_network
}, {
+ CONFIG_PASSWORD_HELPER, 1, 1,
+ "--password-helper",
+ "Password helper",
+ "<executable>",
+ "path to password program or helper name\n",
+ NULL
+ }, {
0, 0, 0, NULL, NULL, NULL, NULL, NULL
}
};
@@ -652,6 +659,7 @@ static void print_version(void)
void do_config(int argc, char **argv)
{
+ char _pass[1024];
char *s;
int i, c, known;
int got_conffile = 0, print_config = 0;
@@ -819,7 +827,14 @@ void do_config(int argc, char **argv)
switch (i) {
case CONFIG_IPSEC_SECRET:
case CONFIG_XAUTH_PASSWORD:
- s = strdup(getpass(""));
+ if (!vpnc_getpass(
+ config[CONFIG_PASSWORD_HELPER],
+ "",
+ _pass,
+ sizeof(_pass))) {
+ error(2, 0, "authentication unsuccessful");
+ }
+ s = _pass;
break;
case CONFIG_IPSEC_GATEWAY:
case CONFIG_IPSEC_ID:
diff --git a/config.h b/config.h
index 6fbd231..6c97801 100644
--- a/config.h
+++ b/config.h
@@ -59,6 +59,7 @@ enum config_enum {
CONFIG_AUTH_MODE,
CONFIG_CA_FILE,
CONFIG_CA_DIR,
+ CONFIG_PASSWORD_HELPER,
LAST_CONFIG
};
diff --git a/vpnc.c b/vpnc.c
index b3518b6..cc5f14f 100644
--- a/vpnc.c
+++ b/vpnc.c
@@ -37,6 +37,7 @@
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
+#include <sys/wait.h>
#include <gcrypt.h>
@@ -165,6 +166,128 @@ static struct sa_block *s_atexit_sa;
static void close_tunnel(struct sa_block *s);
+static int vpnc_getpass_program(const char * const program,
+ const char *const prompt, char *const input, const size_t input_size)
+{
+ int status;
+ pid_t pid = -1;
+ int fds[2] = {-1, -1};
+ int r = 0;
+ int rc;
+
+ if (input == NULL) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (program == NULL) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (pipe(fds) == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ if (pid == 0) {
+ close(fds[0]);
+ fds[0] = -1;
+
+ if (dup2(fds[1], 1) == -1)
+ _exit(1);
+
+ close(fds[1]);
+ fds[1] = -1;
+
+ execl(program, program, prompt, NULL);
+
+ _exit(1);
+ }
+
+ close(fds[1]);
+ fds[1] = -1;
+
+ while ((r = waitpid(pid, &status, 0)) == 0 ||
+ (r == -1 && errno == EINTR))
+ ;
+
+ if (r == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ if (!WIFEXITED(status)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (WEXITSTATUS(status) != 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (input != NULL) {
+ ssize_t bytes;
+
+ bytes = read(fds[0], input, input_size);
+ if (bytes == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ input[bytes] = '\0';
+
+ if (strlen(input) > 0 && input[(int)strlen(input)-1] == '\n')
+ input[(int)strlen(input)-1] = '\0';
+ /* DOS cygwin */
+ if (strlen(input) > 0 && input[(int)strlen(input)-1] == '\r')
+ input[(int)strlen(input)-1] = '\0';
+ }
+
+ rc = 0;
+
+out:
+ if (rc != 0) {
+ if (input)
+ memset(input, 0, input_size);
+ }
+
+ if (fds[0] != -1) {
+ close(fds[0]);
+ fds[0] = -1;
+ }
+
+ if (fds[1] != -1) {
+ close(fds[1]);
+ fds[1] = -1;
+ }
+
+ return rc;
+}
+
+int vpnc_getpass(const char * const helper, const char *const prompt,
+ char *const input, const size_t input_size)
+{
+ if (helper == NULL) {
+ char *pass = getpass(prompt);
+ if (pass == NULL)
+ return 0;
+ strncpy(input, pass, input_size);
+ memset(pass, 0, strlen(pass));
+ return 1;
+ } else {
+ return vpnc_getpass_program(helper, prompt, input,
+ input_size) == 0;
+ }
+}
+
void print_vid(const unsigned char *vid, uint16_t len) {
int vid_index = 0;
@@ -2327,7 +2450,8 @@ static int do_phase2_xauth(struct sa_block *s)
phase2_fatal(s, "noninteractive can't reuse password", reject);
error(2, 0, "authentication failed (requires interactive mode)");
} else if (seen_answer || passwd_used || config[CONFIG_XAUTH_INTERACTIVE]) {
- char *pass, *prompt = NULL;
+ char pass[1024];
+ char *prompt = NULL;
asprintf(&prompt, "%s for VPN %s@%s: ",
(ap->type == ISAKMP_XAUTH_06_ATTRIB_ANSWER) ?
@@ -2335,7 +2459,14 @@ 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);
+ if (!vpnc_getpass(
+ config[CONFIG_PASSWORD_HELPER],
+ prompt,
+ pass,
+ sizeof(pass))) {
+ free(prompt);
+ error(2, 0, "authentication unsuccessful");
+ }
free(prompt);
na = new_isakmp_attribute(ap->type, NULL);
diff --git a/vpnc.h b/vpnc.h
index 2bacc08..e9b54bc 100644
--- a/vpnc.h
+++ b/vpnc.h
@@ -27,5 +27,7 @@ void process_late_ike(struct sa_block *s, uint8_t *r_packet, ssize_t r_length);
void keepalive_ike(struct sa_block *s);
void dpd_ike(struct sa_block *s);
void print_vid(const unsigned char *vid, uint16_t len);
+int vpnc_getpass(const char * const helper, const char *const prompt,
+ char *const input, const size_t input_size);
#endif
--
1.8.3.2
_______________________________________________
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/
for password and echo result to stdout.
Settings:
---
Password Helper /home/alonbl/vpnc/vpnc-getpass
Xauth interactive
---
vpn-getpass script for KDE:
---
prompt="$1"
exec kdialog --title "vpnc" --password "$prompt";
---
vpn-getpass script for KDE with SecurID:
---
prompt="$1"
pass="$(kdialog --title "vpnc" --password "$prompt")" || exit 1
otp="$(RSA_SecurID_getpasswd)" || exit 1
echo "${pass}${otp}"
exit 0
---
Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
---
config.c | 17 +++++++-
config.h | 1 +
vpnc.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
vpnc.h | 2 +
4 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/config.c b/config.c
index 0351e9b..90e8df5 100644
--- a/config.c
+++ b/config.c
@@ -469,6 +469,13 @@ static const struct config_names_s {
"Target network in dotted decimal or CIDR notation\n",
config_def_target_network
}, {
+ CONFIG_PASSWORD_HELPER, 1, 1,
+ "--password-helper",
+ "Password helper",
+ "<executable>",
+ "path to password program or helper name\n",
+ NULL
+ }, {
0, 0, 0, NULL, NULL, NULL, NULL, NULL
}
};
@@ -652,6 +659,7 @@ static void print_version(void)
void do_config(int argc, char **argv)
{
+ char _pass[1024];
char *s;
int i, c, known;
int got_conffile = 0, print_config = 0;
@@ -819,7 +827,14 @@ void do_config(int argc, char **argv)
switch (i) {
case CONFIG_IPSEC_SECRET:
case CONFIG_XAUTH_PASSWORD:
- s = strdup(getpass(""));
+ if (!vpnc_getpass(
+ config[CONFIG_PASSWORD_HELPER],
+ "",
+ _pass,
+ sizeof(_pass))) {
+ error(2, 0, "authentication unsuccessful");
+ }
+ s = _pass;
break;
case CONFIG_IPSEC_GATEWAY:
case CONFIG_IPSEC_ID:
diff --git a/config.h b/config.h
index 6fbd231..6c97801 100644
--- a/config.h
+++ b/config.h
@@ -59,6 +59,7 @@ enum config_enum {
CONFIG_AUTH_MODE,
CONFIG_CA_FILE,
CONFIG_CA_DIR,
+ CONFIG_PASSWORD_HELPER,
LAST_CONFIG
};
diff --git a/vpnc.c b/vpnc.c
index b3518b6..cc5f14f 100644
--- a/vpnc.c
+++ b/vpnc.c
@@ -37,6 +37,7 @@
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
+#include <sys/wait.h>
#include <gcrypt.h>
@@ -165,6 +166,128 @@ static struct sa_block *s_atexit_sa;
static void close_tunnel(struct sa_block *s);
+static int vpnc_getpass_program(const char * const program,
+ const char *const prompt, char *const input, const size_t input_size)
+{
+ int status;
+ pid_t pid = -1;
+ int fds[2] = {-1, -1};
+ int r = 0;
+ int rc;
+
+ if (input == NULL) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (program == NULL) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (pipe(fds) == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ if (pid == 0) {
+ close(fds[0]);
+ fds[0] = -1;
+
+ if (dup2(fds[1], 1) == -1)
+ _exit(1);
+
+ close(fds[1]);
+ fds[1] = -1;
+
+ execl(program, program, prompt, NULL);
+
+ _exit(1);
+ }
+
+ close(fds[1]);
+ fds[1] = -1;
+
+ while ((r = waitpid(pid, &status, 0)) == 0 ||
+ (r == -1 && errno == EINTR))
+ ;
+
+ if (r == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ if (!WIFEXITED(status)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (WEXITSTATUS(status) != 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (input != NULL) {
+ ssize_t bytes;
+
+ bytes = read(fds[0], input, input_size);
+ if (bytes == -1) {
+ rc = -errno;
+ goto out;
+ }
+
+ input[bytes] = '\0';
+
+ if (strlen(input) > 0 && input[(int)strlen(input)-1] == '\n')
+ input[(int)strlen(input)-1] = '\0';
+ /* DOS cygwin */
+ if (strlen(input) > 0 && input[(int)strlen(input)-1] == '\r')
+ input[(int)strlen(input)-1] = '\0';
+ }
+
+ rc = 0;
+
+out:
+ if (rc != 0) {
+ if (input)
+ memset(input, 0, input_size);
+ }
+
+ if (fds[0] != -1) {
+ close(fds[0]);
+ fds[0] = -1;
+ }
+
+ if (fds[1] != -1) {
+ close(fds[1]);
+ fds[1] = -1;
+ }
+
+ return rc;
+}
+
+int vpnc_getpass(const char * const helper, const char *const prompt,
+ char *const input, const size_t input_size)
+{
+ if (helper == NULL) {
+ char *pass = getpass(prompt);
+ if (pass == NULL)
+ return 0;
+ strncpy(input, pass, input_size);
+ memset(pass, 0, strlen(pass));
+ return 1;
+ } else {
+ return vpnc_getpass_program(helper, prompt, input,
+ input_size) == 0;
+ }
+}
+
void print_vid(const unsigned char *vid, uint16_t len) {
int vid_index = 0;
@@ -2327,7 +2450,8 @@ static int do_phase2_xauth(struct sa_block *s)
phase2_fatal(s, "noninteractive can't reuse password", reject);
error(2, 0, "authentication failed (requires interactive mode)");
} else if (seen_answer || passwd_used || config[CONFIG_XAUTH_INTERACTIVE]) {
- char *pass, *prompt = NULL;
+ char pass[1024];
+ char *prompt = NULL;
asprintf(&prompt, "%s for VPN %s@%s: ",
(ap->type == ISAKMP_XAUTH_06_ATTRIB_ANSWER) ?
@@ -2335,7 +2459,14 @@ 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);
+ if (!vpnc_getpass(
+ config[CONFIG_PASSWORD_HELPER],
+ prompt,
+ pass,
+ sizeof(pass))) {
+ free(prompt);
+ error(2, 0, "authentication unsuccessful");
+ }
free(prompt);
na = new_isakmp_attribute(ap->type, NULL);
diff --git a/vpnc.h b/vpnc.h
index 2bacc08..e9b54bc 100644
--- a/vpnc.h
+++ b/vpnc.h
@@ -27,5 +27,7 @@ void process_late_ike(struct sa_block *s, uint8_t *r_packet, ssize_t r_length);
void keepalive_ike(struct sa_block *s);
void dpd_ike(struct sa_block *s);
void print_vid(const unsigned char *vid, uint16_t len);
+int vpnc_getpass(const char * const helper, const char *const prompt,
+ char *const input, const size_t input_size);
#endif
--
1.8.3.2
_______________________________________________
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/