0
0
mirror of https://github.com/OpenVPN/openvpn.git synced 2024-09-19 19:42:30 +02:00

Static-challenge concatenation option

Extend "--static-challenge" option to take a third
argument (= scrv1 or concat) to specify that the password and
response should be concatenated instead of using the
SCRV1 protocol. If unspecified, it defaults to "scrv1"
meaning that the SCRV1 protocol should be used.

v2: use scrv1|concat instead of 0|1 as option argument
    fix typos
v3: improve and correct documentation in management-notes.txt

Change-Id: I59a90446bfe73d8856516025a58a6f62cc98ab0d
Signed-off-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Frank Lichtenheld <frank@lichtenheld.com>
Message-Id: <20240719131407.75746-1-frank@lichtenheld.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28943.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
Selva Nair 2024-07-19 15:14:07 +02:00 committed by Gert Doering
parent 67124dcf31
commit 6f6a0f362f
7 changed files with 70 additions and 20 deletions

View File

@ -541,12 +541,15 @@ configuration.
Valid syntax:
::
static-challenge text echo
static-challenge text echo [format]
The ``text`` challenge text is presented to the user which describes what
information is requested. The ``echo`` flag indicates if the user's
input should be echoed on the screen. Valid ``echo`` values are
:code:`0` or :code:`1`.
:code:`0` or :code:`1`. The optional ``format`` indicates whether
the password and response should be combined using the SCRV1 protocol
(``format`` = :code:`scrv1`) or simply concatenated (``format`` = :code:`concat`).
:code:`scrv1` is the default.
See management-notes.txt in the OpenVPN distribution for a description of
the OpenVPN challenge/response protocol.

View File

@ -1320,14 +1320,20 @@ request.
OpenVPN's --static-challenge option is used to provide the
challenge text to OpenVPN and indicate whether or not the response
should be echoed.
should be echoed and how the response should be combined with the
password.
When credentials are needed and the --static-challenge option is
used, the management interface will send:
>PASSWORD:Need 'Auth' username/password SC:<ECHO>,<TEXT>
>PASSWORD:Need 'Auth' username/password SC:<flag>,<TEXT>
ECHO: "1" if response should be echoed, "0" to not echo
flag: an integer whose least significant bit is the ECHO flag and
the next significant bit is the FORMAT flag.
ECHO = (flag & 0x1) is 1 if response should be echoed, 0 to not echo
FORMAT = (flag & 0x2) is 1 if response should be concatenated with
password as plain text, 0 if response and password should be encoded
as described below. Thus flag could take values 0, 1, 2, or 3.
TEXT: challenge text that should be shown to the user to
facilitate their response
@ -1342,8 +1348,9 @@ should be echoed.
The management interface client in this case should add the static
challenge text to the auth dialog followed by a field for the user to
enter a response. Then the management interface client should pack the
password and response together into an encoded password and send:
enter a response. If flag = 0 or 1 (i.e., FORMAT=0), the management
interface client should pack the password and response together into
an encoded password and send:
username "Auth" <username>
password "Auth" "SCRV1:<password_base64>:<response_base64>"
@ -1354,6 +1361,12 @@ is the base 64 encoding of the password entered by the user, and
the user. The <password_base64> and/or the <response_base64> can be
empty strings.
If flag = 2 or 3 (i.e., FORMAT=1), the client should simply concatenate
password and response with no separator and send:
username "Auth" <username>
password "Auth" "<password><response>"
(As in all username/password responses described in the "COMMAND --
password and username" section above, the username can be in quotes,
and special characters such as double quotes or backslashes must be
@ -1361,10 +1374,15 @@ escaped. See the "Command Parsing" section above for more info.)
For example, if user "foo" entered "bar" as the password and 8675309
as the PIN, the following management interface commands should be
issued:
issued if flag = 0 or 1 (i.e., FORMAT = 0):
username "Auth" foo
password "Auth" "SCRV1:YmFy:ODY3NTMwOQ=="
("YmFy" is the base 64 encoding of "bar" and "ODY3NTMwOQ==" is the
base 64 encoding of "8675309".)
or, if flag = 2 or 3 (i.e., FORMAT = 1):
username "Auth" foo
password "Auth" "bar8675309"

View File

@ -3544,7 +3544,8 @@ management_query_user_pass(struct management *man,
if (sc)
{
buf_printf(&alert_msg, " SC:%d,%s",
BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO),
BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO)
|(BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_CONCAT) << 1),
sc);
}

View File

@ -439,6 +439,8 @@ get_user_pass_cr(struct user_pass *up,
{
msg(M_FATAL, "ERROR: could not retrieve static challenge response");
}
if (!(flags & GET_USER_PASS_STATIC_CHALLENGE_CONCAT))
{
if (openvpn_base64_encode(up->password, strlen(up->password), &pw64) == -1
|| openvpn_base64_encode(response, strlen(response), &resp64) == -1)
{
@ -451,6 +453,15 @@ get_user_pass_cr(struct user_pass *up,
string_clear(resp64);
free(resp64);
}
else
{
if (strlen(up->password) + strlen(response) >= USER_PASS_LEN)
{
msg(M_FATAL, "ERROR: could not concatenate password/static_response: string too long");
}
strncat(up->password, response, USER_PASS_LEN - strlen(up->password) - 1);
}
}
#endif /* ifdef ENABLE_MANAGEMENT */
}
}

View File

@ -92,6 +92,7 @@ struct auth_challenge_info {
*/
struct static_challenge_info {
#define SC_ECHO (1<<0) /* echo response when typed by user */
#define SC_CONCAT (1<<1) /* concatenate password and response and do not base64 encode */
unsigned int flags;
const char *challenge_text;
@ -118,6 +119,7 @@ struct static_challenge_info {};
#define GET_USER_PASS_STATIC_CHALLENGE_ECHO (1<<9) /* SCRV1 protocol -- echo response */
#define GET_USER_PASS_INLINE_CREDS (1<<10) /* indicates that auth_file is actually inline creds */
#define GET_USER_PASS_STATIC_CHALLENGE_CONCAT (1<<11) /* indicates password and response should be concatenated */
/**
* Retrieves the user credentials from various sources depending on the flags.

View File

@ -518,8 +518,10 @@ static const char usage_message[] =
" Add domains to DNS domain search list\n"
"--auth-retry t : How to handle auth failures. Set t to\n"
" none (default), interact, or nointeract.\n"
"--static-challenge t e : Enable static challenge/response protocol using\n"
"--static-challenge t e [<scrv1|concat>]: Enable static challenge/response protocol using\n"
" challenge text t, with e indicating echo flag (0|1)\n"
" and optional argument scrv1 or concat to use SCRV1 protocol or"
" concatenate response with password. Default is scrv1.\n"
"--connect-timeout n : when polling possible remote servers to connect to\n"
" in a round-robin fashion, spend no more than n seconds\n"
" waiting for a response before trying the next server.\n"
@ -7948,7 +7950,7 @@ add_option(struct options *options,
auth_retry_set(msglevel, p[1]);
}
#ifdef ENABLE_MANAGEMENT
else if (streq(p[0], "static-challenge") && p[1] && p[2] && !p[3])
else if (streq(p[0], "static-challenge") && p[1] && p[2] && !p[4])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
options->sc_info.challenge_text = p[1];
@ -7956,6 +7958,15 @@ add_option(struct options *options,
{
options->sc_info.flags |= SC_ECHO;
}
if (p[3] && streq(p[3], "concat"))
{
options->sc_info.flags |= SC_CONCAT;
}
else if (p[3] && !streq(p[3], "scrv1"))
{
msg(msglevel, "--static-challenge: unknown format indicator '%s'", p[3]);
goto err;
}
}
#endif
else if (streq(p[0], "msg-channel") && p[1])

View File

@ -315,6 +315,10 @@ auth_user_pass_setup(const char *auth_file, bool is_inline,
{
flags |= GET_USER_PASS_STATIC_CHALLENGE_ECHO;
}
if (sci->flags & SC_CONCAT)
{
flags |= GET_USER_PASS_STATIC_CHALLENGE_CONCAT;
}
get_user_pass_cr(&auth_user_pass,
auth_file,
UP_TYPE_AUTH,