Must be applied after the patch to fix CR prompting.
---
doc/openvpn.8 | 8 +++++++-
src/openvpn/misc.c | 19 +++++++++++++------
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/doc/openvpn.8 b/doc/openvpn.8
index 1b9dcae..e806930 100644
--- a/doc/openvpn.8
+++ b/doc/openvpn.8
@@ -3800,7 +3800,13 @@ over the client's routing table.
Authenticate with server using username/password.
.B up
is a file containing username/password on 2 lines. If the
-password line is missing, OpenVPN will prompt for one.
+password line is missing or empty, OpenVPN will prompt for one.
+The third line of the file can be used to enter a response to
+a challenge, such as "push", "phone", etc., which can be used
+to eliminate an extra prompt for an unchanging text if your
+challenge/response setup uses push/callback two-factor auth
+(and can also be combined with an empty password line to still
+be prompted for your password).
If
.B up
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 83e10f7..4de4a17 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -1038,6 +1038,9 @@ get_user_pass_cr (struct user_pass *up,
bool from_authfile = (auth_file && !streq (auth_file, "stdin"));
bool username_from_stdin = false;
bool password_from_stdin = false;
+#ifdef ENABLE_CLIENT_CR
+ char response_buf[USER_PASS_LEN] = { '\0' };
+#endif
if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED)
msg (M_WARN, "Note: previous '%s' credentials failed", prefix);
@@ -1111,6 +1114,10 @@ get_user_pass_cr (struct user_pass *up,
if (fgets (password_buf, USER_PASS_LEN, fp) != NULL)
{
chomp (password_buf);
+#ifdef ENABLE_CLIENT_CR
+ if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && fgets
(response_buf, USER_PASS_LEN, fp) != NULL)
+ chomp (response_buf);
+#endif
}
if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0])
@@ -1138,15 +1145,14 @@ get_user_pass_cr (struct user_pass *up,
struct auth_challenge_info *ac = get_auth_challenge (auth_challenge,
&gc);
if (ac)
{
- char *response = (char *) gc_malloc (USER_PASS_LEN, false, &gc);
struct buffer packed_resp;
buf_set_write (&packed_resp, (uint8_t*)up->password,
USER_PASS_LEN);
msg (M_INFO|M_NOPREFIX, "CHALLENGE: %s", ac->challenge_text);
- if (!get_console_input ("Response:",
BOOL_CAST(ac->flags&CR_ECHO), response, USER_PASS_LEN))
+ if (!response_buf[0] && !get_console_input ("Response:",
BOOL_CAST(ac->flags&CR_ECHO), response_buf, USER_PASS_LEN))
msg (M_FATAL, "ERROR: could not read challenge response from
stdin");
strncpynt (up->username, ac->user, USER_PASS_LEN);
- buf_printf (&packed_resp, "CRV1::%s::%s", ac->state_id,
response);
+ buf_printf (&packed_resp, "CRV1::%s::%s", ac->state_id,
response_buf);
}
else
{
@@ -1177,15 +1183,16 @@ get_user_pass_cr (struct user_pass *up,
#ifdef ENABLE_CLIENT_CR
if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE))
{
- char *response = (char *) gc_malloc (USER_PASS_LEN, false, &gc);
struct buffer packed_resp;
char *pw64=NULL, *resp64=NULL;
msg (M_INFO|M_NOPREFIX, "CHALLENGE: %s", auth_challenge);
- if (!get_console_input ("Response:", BOOL_CAST(flags &
GET_USER_PASS_STATIC_CHALLENGE_ECHO), response, USER_PASS_LEN))
+ if (!response_buf[0] && !get_console_input ("Response:",
BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO), response_buf,
USER_PASS_LEN))
msg (M_FATAL, "ERROR: could not read static challenge response
from stdin");
+ else if (!response_buf[0] && (flags &
GET_USER_PASS_STATIC_CHALLENGE_ECHO))
+ msg (M_INFO|M_NOPREFIX, "Response: %s", response_buf);
if (openvpn_base64_encode(up->password, strlen(up->password),
&pw64) == -1
- || openvpn_base64_encode(response, strlen(response),
&resp64) == -1)
+ || openvpn_base64_encode(response_buf, strlen(response_buf),
&resp64) == -1)
msg (M_FATAL, "ERROR: could not base64-encode
password/static_response");
buf_set_write (&packed_resp, (uint8_t*)up->password,
USER_PASS_LEN);
buf_printf (&packed_resp, "SCRV1:%s:%s", pw64, resp64);
--
1.9.1