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


Reply via email to