mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-11-23 17:53:49 +08:00
Added support for static challenge/response protocol.
This includes the new "static-challenge" directive. See management/management-notes.txt for details on both static and dynamic challenge/response protocols. All client-side challenge/response code is #ifdefed on ENABLE_CLIENT_CR and can be removed from the build by commenting out the definition of ENABLE_CLIENT_CR in syshead.h. Version 2.1.3x. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7316 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
a114cb750e
commit
eab3e22f82
10
base64.c
10
base64.c
@ -42,6 +42,11 @@
|
||||
static char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/*
|
||||
* base64 encode input data of length size to malloced
|
||||
* buffer which is returned as *str. Returns string
|
||||
* length of *str.
|
||||
*/
|
||||
int
|
||||
base64_encode(const void *data, int size, char **str)
|
||||
{
|
||||
@ -116,6 +121,11 @@ token_decode(const char *token)
|
||||
return (marker << 24) | val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode base64 str, outputting data to buffer
|
||||
* at data of length size. Return length of
|
||||
* decoded data written or -1 on error or overflow.
|
||||
*/
|
||||
int
|
||||
base64_decode(const char *str, void *data, int size)
|
||||
{
|
||||
|
12
init.c
12
init.c
@ -343,7 +343,13 @@ init_query_passwords (struct context *c)
|
||||
#if P2MP
|
||||
/* Auth user/pass input */
|
||||
if (c->options.auth_user_pass_file)
|
||||
auth_user_pass_setup (c->options.auth_user_pass_file);
|
||||
{
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
auth_user_pass_setup (c->options.auth_user_pass_file, &c->options.sc_info);
|
||||
#else
|
||||
auth_user_pass_setup (c->options.auth_user_pass_file, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2085,6 +2091,10 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
|
||||
to.x509_track = options->x509_track;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
to.sci = &options->sc_info;
|
||||
#endif
|
||||
|
||||
/* TLS handshake authentication (--tls-auth) */
|
||||
if (options->tls_auth_file)
|
||||
{
|
||||
|
47
manage.c
47
manage.c
@ -606,25 +606,19 @@ man_up_finalize (struct management *man)
|
||||
{
|
||||
switch (man->connection.up_query_mode)
|
||||
{
|
||||
case UP_QUERY_DISABLED:
|
||||
man->connection.up_query.defined = false;
|
||||
break;
|
||||
case UP_QUERY_USER_PASS:
|
||||
if (strlen (man->connection.up_query.username) && strlen (man->connection.up_query.password))
|
||||
man->connection.up_query.defined = true;
|
||||
break;
|
||||
if (!strlen (man->connection.up_query.username))
|
||||
break;
|
||||
/* fall through */
|
||||
case UP_QUERY_PASS:
|
||||
if (strlen (man->connection.up_query.password))
|
||||
man->connection.up_query.defined = true;
|
||||
break;
|
||||
case UP_QUERY_NEED_OK:
|
||||
if (strlen (man->connection.up_query.password))
|
||||
man->connection.up_query.defined = true;
|
||||
break;
|
||||
case UP_QUERY_NEED_STR:
|
||||
if (strlen (man->connection.up_query.password))
|
||||
man->connection.up_query.defined = true;
|
||||
break;
|
||||
case UP_QUERY_DISABLED:
|
||||
man->connection.up_query.defined = false;
|
||||
break;
|
||||
default:
|
||||
ASSERT (0);
|
||||
}
|
||||
@ -665,16 +659,17 @@ man_query_user_pass (struct management *man,
|
||||
static void
|
||||
man_query_username (struct management *man, const char *type, const char *string)
|
||||
{
|
||||
const bool needed = (man->connection.up_query_mode == UP_QUERY_USER_PASS && man->connection.up_query_type);
|
||||
const bool needed = ((man->connection.up_query_mode == UP_QUERY_USER_PASS
|
||||
) && man->connection.up_query_type);
|
||||
man_query_user_pass (man, type, string, needed, "username", man->connection.up_query.username, USER_PASS_LEN);
|
||||
}
|
||||
|
||||
static void
|
||||
man_query_password (struct management *man, const char *type, const char *string)
|
||||
{
|
||||
const bool needed = ((man->connection.up_query_mode == UP_QUERY_USER_PASS
|
||||
|| man->connection.up_query_mode == UP_QUERY_PASS)
|
||||
&& man->connection.up_query_type);
|
||||
const bool needed = ((man->connection.up_query_mode == UP_QUERY_PASS
|
||||
|| man->connection.up_query_mode == UP_QUERY_USER_PASS
|
||||
) && man->connection.up_query_type);
|
||||
if (!string[0]) /* allow blank passwords to be passed through using the blank_up tag */
|
||||
string = blank_up;
|
||||
man_query_user_pass (man, type, string, needed, "password", man->connection.up_query.password, USER_PASS_LEN);
|
||||
@ -2843,7 +2838,8 @@ bool
|
||||
management_query_user_pass (struct management *man,
|
||||
struct user_pass *up,
|
||||
const char *type,
|
||||
const unsigned int flags)
|
||||
const unsigned int flags,
|
||||
const char *static_challenge)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
bool ret = false;
|
||||
@ -2856,7 +2852,9 @@ management_query_user_pass (struct management *man,
|
||||
const char *alert_type = NULL;
|
||||
const char *prefix = NULL;
|
||||
unsigned int up_query_mode = 0;
|
||||
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
const char *sc = NULL;
|
||||
#endif
|
||||
ret = true;
|
||||
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
|
||||
man->persist.special_state_msg = NULL;
|
||||
@ -2886,6 +2884,10 @@ management_query_user_pass (struct management *man,
|
||||
up_query_mode = UP_QUERY_USER_PASS;
|
||||
prefix = "PASSWORD";
|
||||
alert_type = "username/password";
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
if (static_challenge)
|
||||
sc = static_challenge;
|
||||
#endif
|
||||
}
|
||||
buf_printf (&alert_msg, ">%s:Need '%s' %s",
|
||||
prefix,
|
||||
@ -2895,6 +2897,13 @@ management_query_user_pass (struct management *man,
|
||||
if (flags & (GET_USER_PASS_NEED_OK | GET_USER_PASS_NEED_STR))
|
||||
buf_printf (&alert_msg, " MSG:%s", up->username);
|
||||
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
if (sc)
|
||||
buf_printf (&alert_msg, " SC:%d,%s",
|
||||
BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO),
|
||||
sc);
|
||||
#endif
|
||||
|
||||
man_wait_for_client_connection (man, &signal_received, 0, MWCC_PASSWORD_WAIT);
|
||||
if (signal_received)
|
||||
ret = false;
|
||||
@ -2908,7 +2917,7 @@ management_query_user_pass (struct management *man,
|
||||
man->connection.up_query_mode = up_query_mode;
|
||||
man->connection.up_query_type = type;
|
||||
|
||||
/* run command processing event loop until we get our username/password */
|
||||
/* run command processing event loop until we get our username/password/response */
|
||||
do
|
||||
{
|
||||
man_standalone_event_loop (man, &signal_received, 0);
|
||||
|
6
manage.h
6
manage.h
@ -365,7 +365,11 @@ void management_set_callback (struct management *man,
|
||||
|
||||
void management_clear_callback (struct management *man);
|
||||
|
||||
bool management_query_user_pass (struct management *man, struct user_pass *up, const char *type, const unsigned int flags);
|
||||
bool management_query_user_pass (struct management *man,
|
||||
struct user_pass *up,
|
||||
const char *type,
|
||||
const unsigned int flags,
|
||||
const char *static_challenge);
|
||||
|
||||
bool management_should_daemonize (struct management *man);
|
||||
bool management_would_hold (struct management *man);
|
||||
|
@ -836,3 +836,113 @@ mappings, when not in single quotations:
|
||||
interpret it as enclosing a parameter.
|
||||
\[SPACE] Pass a literal space or tab character, don't
|
||||
interpret it as a parameter delimiter.
|
||||
|
||||
Challenge/Response Protocol
|
||||
---------------------------
|
||||
|
||||
The OpenVPN Challenge/Response Protocol allows an OpenVPN server to
|
||||
generate challenge questions that are shown to the user, and to see
|
||||
the user's responses to those challenges. Based on the responses, the
|
||||
server can allow or deny access.
|
||||
|
||||
In this way, the OpenVPN Challenge/Response Protocol can be used
|
||||
to implement multi-factor authentication. Two different
|
||||
variations on the challenge/response protocol are supported: the
|
||||
"Dynamic" and "Static" protocols.
|
||||
|
||||
The basic idea of Challenge/Response is that the user must enter an
|
||||
additional piece of information, in addition to the username and
|
||||
password, to successfully authenticate. Normally, this information
|
||||
is used to prove that the user posesses a certain key-like device
|
||||
such as cryptographic token or a particular mobile phone.
|
||||
|
||||
Dynamic protocol:
|
||||
|
||||
The OpenVPN dynamic challenge/response protocol works by returning
|
||||
a specially formatted error message after initial successful
|
||||
authentication. This error message contains the challenge question,
|
||||
and is formatted as such:
|
||||
|
||||
CRV1:<flags>:<state_id>:<username_base64>:<challenge_text>
|
||||
|
||||
flags: a series of optional, comma-separated flags:
|
||||
E : echo the response when the user types it
|
||||
R : a response is required
|
||||
|
||||
state_id: an opaque string that should be returned to the server
|
||||
along with the response.
|
||||
|
||||
username_base64 : the username formatted as base64
|
||||
|
||||
challenge_text : the challenge text to be shown to the user
|
||||
|
||||
Example challenge:
|
||||
|
||||
CRV1:R,E:Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l:Y3Ix:Please enter token PIN
|
||||
|
||||
After showing the challenge_text and getting a response from the user
|
||||
(if R flag is specified), the client should submit the following
|
||||
auth creds back to the OpenVPN server:
|
||||
|
||||
Username: [username decoded from username_base64]
|
||||
Password: CRV1::<state_id>::<response_text>
|
||||
|
||||
Where state_id is taken from the challenge request and response_text
|
||||
is what the user entered in response to the challenge_text.
|
||||
If the R flag is not present, response_text may be the empty
|
||||
string.
|
||||
|
||||
Example response (suppose the user enters "8675309" for the token PIN):
|
||||
|
||||
Username: cr1 ("Y3Ix" base64 decoded)
|
||||
Password: CRV1::Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l::8675309
|
||||
|
||||
Static protocol:
|
||||
|
||||
The static protocol differs from the dynamic protocol in that the
|
||||
challenge question and response field is given to the user in the
|
||||
initial username/password dialog, and the username, password, and
|
||||
response are delivered back to the server in a single transaction.
|
||||
|
||||
The "static-challenge" directive is used to give the challenge text
|
||||
to OpenVPN and indicate whether or not the response should be echoed.
|
||||
|
||||
When the "static-challenge" directive is used, the management
|
||||
interface will respond as such when credentials are needed:
|
||||
|
||||
>PASSWORD:Need 'Auth' username/password SC:<ECHO>,<TEXT>
|
||||
|
||||
ECHO: "1" if response should be echoed, "0" to not echo
|
||||
TEXT: challenge text that should be shown to the user to
|
||||
facilitate their response
|
||||
|
||||
For example:
|
||||
|
||||
>PASSWORD:Need 'Auth' username/password SC:1,Please enter token PIN
|
||||
|
||||
The above notification indicates that OpenVPN needs a --auth-user-pass
|
||||
password plus a response to a static challenge ("Please enter token PIN").
|
||||
The "1" after the "SC:" indicates that the response 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 client should pack the password and response
|
||||
together into an encoded password:
|
||||
|
||||
username "Auth" foo
|
||||
password "Auth" "SCRV1:<BASE64_PASSWORD>:<BASE64_RESPONSE>"
|
||||
|
||||
For example, if the user entered "bar" as the password and 8675309
|
||||
as the PIN, the following management interface commands should be
|
||||
issued:
|
||||
|
||||
username "Auth" foo
|
||||
password "Auth" "SCRV1:Zm9v:ODY3NTMwOQ=="
|
||||
|
||||
Client-side support for challenge/response protocol:
|
||||
|
||||
Currently, the Access Server client and standalone OpenVPN
|
||||
client support both static and dynamic challenge/response
|
||||
protocols. However, any OpenVPN client UI that drives OpenVPN
|
||||
via the management interface needs to add explicit support
|
||||
for the challenge/response protocol.
|
||||
|
72
misc.c
72
misc.c
@ -1387,10 +1387,16 @@ get_user_pass_cr (struct user_pass *up,
|
||||
&& ((auth_file && streq (auth_file, "management")) || (from_stdin && (flags & GET_USER_PASS_MANAGEMENT)))
|
||||
&& management_query_user_pass_enabled (management))
|
||||
{
|
||||
const char *sc = NULL;
|
||||
|
||||
if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED)
|
||||
management_auth_failure (management, prefix, "previous auth credentials failed");
|
||||
|
||||
if (!management_query_user_pass (management, up, prefix, flags))
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE))
|
||||
sc = auth_challenge;
|
||||
#endif
|
||||
if (!management_query_user_pass (management, up, prefix, flags, sc))
|
||||
{
|
||||
if ((flags & GET_USER_PASS_NOFATAL) != 0)
|
||||
return false;
|
||||
@ -1422,7 +1428,7 @@ get_user_pass_cr (struct user_pass *up,
|
||||
else if (from_stdin)
|
||||
{
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
if (auth_challenge)
|
||||
if (auth_challenge && (flags & GET_USER_PASS_DYNAMIC_CHALLENGE))
|
||||
{
|
||||
struct auth_challenge_info *ac = get_auth_challenge (auth_challenge, &gc);
|
||||
if (ac)
|
||||
@ -1431,7 +1437,7 @@ get_user_pass_cr (struct user_pass *up,
|
||||
struct buffer packed_resp;
|
||||
|
||||
buf_set_write (&packed_resp, (uint8_t*)up->password, USER_PASS_LEN);
|
||||
msg (M_INFO, "CHALLENGE: %s", ac->challenge_text);
|
||||
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))
|
||||
msg (M_FATAL, "ERROR: could not read challenge response from stdin");
|
||||
strncpynt (up->username, ac->user, USER_PASS_LEN);
|
||||
@ -1461,6 +1467,28 @@ get_user_pass_cr (struct user_pass *up,
|
||||
|
||||
if (!get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN))
|
||||
msg (M_FATAL, "ERROR: could not not read %s password from stdin", prefix);
|
||||
|
||||
#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))
|
||||
msg (M_FATAL, "ERROR: could not read static challenge response from stdin");
|
||||
if (base64_encode(up->password, strlen(up->password), &pw64) == -1
|
||||
|| base64_encode(response, strlen(response), &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);
|
||||
string_clear(pw64);
|
||||
free(pw64);
|
||||
string_clear(resp64);
|
||||
free(resp64);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1528,42 +1556,8 @@ get_user_pass_cr (struct user_pass *up,
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
|
||||
/*
|
||||
* Parse a challenge message returned along with AUTH_FAILED.
|
||||
* The message is formatted as such:
|
||||
*
|
||||
* CRV1:<flags>:<state_id>:<username_base64>:<challenge_text>
|
||||
*
|
||||
* flags: a series of optional, comma-separated flags:
|
||||
* E : echo the response when the user types it
|
||||
* R : a response is required
|
||||
*
|
||||
* state_id: an opaque string that should be returned to the server
|
||||
* along with the response.
|
||||
*
|
||||
* username_base64 : the username formatted as base64
|
||||
*
|
||||
* challenge_text : the challenge text to be shown to the user
|
||||
*
|
||||
* Example challenge:
|
||||
*
|
||||
* CRV1:R,E:Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l:Y3Ix:Please enter token PIN
|
||||
*
|
||||
* After showing the challenge_text and getting a response from the user
|
||||
* (if R flag is specified), the client should submit the following
|
||||
* auth creds back to the OpenVPN server:
|
||||
*
|
||||
* Username: [username decoded from username_base64]
|
||||
* Password: CRV1::<state_id>::<response_text>
|
||||
*
|
||||
* Where state_id is taken from the challenge request and response_text
|
||||
* is what the user entered in response to the challenge_text.
|
||||
* If the R flag is not present, response_text may be the empty
|
||||
* string.
|
||||
*
|
||||
* Example response (suppose the user enters "8675309" for the token PIN):
|
||||
*
|
||||
* Username: cr1 ("Y3Ix" base64 decoded)
|
||||
* Password: CRV1::Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l::8675309
|
||||
* See management/management-notes.txt for more info on the
|
||||
* the dynamic challenge/response protocol implemented here.
|
||||
*/
|
||||
struct auth_challenge_info *
|
||||
get_auth_challenge (const char *auth_challenge, struct gc_arena *gc)
|
||||
|
15
misc.h
15
misc.h
@ -268,8 +268,19 @@ struct auth_challenge_info {
|
||||
|
||||
struct auth_challenge_info *get_auth_challenge (const char *auth_challenge, struct gc_arena *gc);
|
||||
|
||||
/*
|
||||
* Challenge response info on client as pushed by server.
|
||||
*/
|
||||
struct static_challenge_info {
|
||||
# define SC_ECHO (1<<0) /* echo response when typed by user */
|
||||
unsigned int flags;
|
||||
|
||||
const char *challenge_text;
|
||||
};
|
||||
|
||||
#else
|
||||
struct auth_challenge_info {};
|
||||
struct static_challenge_info {};
|
||||
#endif
|
||||
|
||||
bool get_console_input (const char *prompt, const bool echo, char *input, const int capacity);
|
||||
@ -285,6 +296,10 @@ bool get_console_input (const char *prompt, const bool echo, char *input, const
|
||||
#define GET_USER_PASS_NEED_STR (1<<5)
|
||||
#define GET_USER_PASS_PREVIOUS_CREDS_FAILED (1<<6)
|
||||
|
||||
#define GET_USER_PASS_DYNAMIC_CHALLENGE (1<<7) /* CRV1 protocol -- dynamic challenge */
|
||||
#define GET_USER_PASS_STATIC_CHALLENGE (1<<8) /* SCRV1 protocol -- static challenge */
|
||||
#define GET_USER_PASS_STATIC_CHALLENGE_ECHO (1<<9) /* SCRV1 protocol -- echo response */
|
||||
|
||||
bool get_user_pass_cr (struct user_pass *up,
|
||||
const char *auth_file,
|
||||
const char *prefix,
|
||||
|
15
openvpn.8
15
openvpn.8
@ -3362,6 +3362,21 @@ Note that while this option cannot be pushed, it can be controlled
|
||||
from the management interface.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-static\-challenge t e
|
||||
Enable static challenge/response protocol using challenge text
|
||||
.B t,
|
||||
with
|
||||
echo flag given by
|
||||
.B e
|
||||
(0|1).
|
||||
|
||||
The echo flag indicates whether or not the user's response
|
||||
to the challenge should be echoed.
|
||||
|
||||
See management\-notes.txt in the OpenVPN distribution for a
|
||||
description of the OpenVPN challenge/response protocol.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --server-poll-timeout n
|
||||
when polling possible remote servers to connect to
|
||||
in a round-robin fashion, spend no more than
|
||||
|
10
options.c
10
options.c
@ -443,6 +443,8 @@ static const char usage_message[] =
|
||||
" when connecting to a '--mode server' remote host.\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"
|
||||
" challenge text t, with e indicating echo flag (0|1)\n"
|
||||
"--server-poll-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"
|
||||
@ -5251,6 +5253,14 @@ add_option (struct options *options,
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
auth_retry_set (msglevel, p[1]);
|
||||
}
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
else if (streq (p[0], "static-challenge") && p[1] && p[2])
|
||||
{
|
||||
options->sc_info.challenge_text = p[1];
|
||||
if (atoi(p[2]))
|
||||
options->sc_info.flags |= SC_ECHO;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
else if (streq (p[0], "win-sys") && p[1])
|
||||
|
@ -426,6 +426,9 @@ struct options
|
||||
|
||||
const char *auth_user_pass_verify_script;
|
||||
bool auth_user_pass_verify_script_via_file;
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
struct static_challenge_info sc_info;
|
||||
#endif
|
||||
#if PORT_SHARE
|
||||
char *port_share_host;
|
||||
int port_share_port;
|
||||
|
32
ssl.c
32
ssl.c
@ -292,17 +292,35 @@ static char *auth_challenge; /* GLOBAL */
|
||||
#endif
|
||||
|
||||
void
|
||||
auth_user_pass_setup (const char *auth_file)
|
||||
auth_user_pass_setup (const char *auth_file, const struct static_challenge_info *sci)
|
||||
{
|
||||
auth_user_pass_enabled = true;
|
||||
if (!auth_user_pass.defined)
|
||||
{
|
||||
#if AUTO_USERID
|
||||
get_user_pass_auto_userid (&auth_user_pass, auth_file);
|
||||
#elif defined(ENABLE_CLIENT_CR)
|
||||
get_user_pass_cr (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE, auth_challenge);
|
||||
#else
|
||||
get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
|
||||
# ifdef ENABLE_CLIENT_CR
|
||||
if (auth_challenge) /* dynamic challenge/response */
|
||||
get_user_pass_cr (&auth_user_pass,
|
||||
auth_file,
|
||||
UP_TYPE_AUTH,
|
||||
GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_DYNAMIC_CHALLENGE,
|
||||
auth_challenge);
|
||||
else if (sci) /* static challenge response */
|
||||
{
|
||||
int flags = GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_STATIC_CHALLENGE;
|
||||
if (sci->flags & SC_ECHO)
|
||||
flags |= GET_USER_PASS_STATIC_CHALLENGE_ECHO;
|
||||
get_user_pass_cr (&auth_user_pass,
|
||||
auth_file,
|
||||
UP_TYPE_AUTH,
|
||||
flags,
|
||||
sci->challenge_text);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -3945,7 +3963,11 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)
|
||||
/* write username/password if specified */
|
||||
if (auth_user_pass_enabled)
|
||||
{
|
||||
auth_user_pass_setup (NULL);
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
auth_user_pass_setup (NULL, session->opt->sci);
|
||||
#else
|
||||
auth_user_pass_setup (NULL, NULL);
|
||||
#endif
|
||||
if (!write_string (buf, auth_user_pass.username, -1))
|
||||
goto error;
|
||||
if (!write_string (buf, auth_user_pass.password, -1))
|
||||
|
6
ssl.h
6
ssl.h
@ -516,6 +516,10 @@ struct tls_options
|
||||
const struct x509_track *x509_track;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
const struct static_challenge_info *sci;
|
||||
#endif
|
||||
|
||||
/* --gremlin bits */
|
||||
int gremlin;
|
||||
};
|
||||
@ -723,7 +727,7 @@ void get_highest_preference_tls_cipher (char *buf, int size);
|
||||
|
||||
void pem_password_setup (const char *auth_file);
|
||||
int pem_password_callback (char *buf, int size, int rwflag, void *u);
|
||||
void auth_user_pass_setup (const char *auth_file);
|
||||
void auth_user_pass_setup (const char *auth_file, const struct static_challenge_info *sc_info);
|
||||
void ssl_set_auth_nocache (void);
|
||||
void ssl_set_auth_token (const char *token);
|
||||
void ssl_purge_auth (const bool auth_user_pass_only);
|
||||
|
@ -683,7 +683,7 @@ socket_defined (const socket_descriptor_t sd)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do we support challenge/response authentication, as a console-based client?
|
||||
* Do we support challenge/response authentication as client?
|
||||
*/
|
||||
#define ENABLE_CLIENT_CR
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
dnl define the OpenVPN version
|
||||
define(PRODUCT_VERSION,[2.1.3w])
|
||||
define(PRODUCT_VERSION,[2.1.3x])
|
||||
dnl define the TAP version
|
||||
define(PRODUCT_TAP_ID,[tap0901])
|
||||
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
|
||||
|
Loading…
Reference in New Issue
Block a user