Ignore auth-nocache for auth-user-pass if auth-token is pushed

When the auth-token option is pushed from the server to the client,
the latter has to ignore the auth-nocache directive (if specified).

The password will now be substituted by the unique token, therefore
it can't be wiped out, otherwise the next renegotiation will fail.

Trac: #840
Cc: David Sommerseth <openvpn@sf.lists.topphemmelig.net>
Signed-off-by: Antonio Quartulli <a@unstable.cc>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <20170225004014.28638-1-a@unstable.cc>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14194.html
Signed-off-by: David Sommerseth <davids@openvpn.net>
This commit is contained in:
Antonio Quartulli 2017-02-25 08:40:14 +08:00 committed by David Sommerseth
parent 22046a8834
commit 571165360d
No known key found for this signature in database
GPG key ID: 86CF944C9671FDF2
5 changed files with 54 additions and 2 deletions

View file

@ -1382,6 +1382,18 @@ initialization_sequence_completed(struct context *c, const unsigned int flags)
/* If we delayed UID/GID downgrade or chroot, do it now */
do_uid_gid_chroot(c, true);
/*
* In some cases (i.e. when receiving auth-token via
* push-reply) the auth-nocache option configured on the
* client is overridden; for this reason we have to wait
* for the push-reply message before attempting to wipe
* the user/pass entered by the user
*/
if (c->options.mode == MODE_POINT_TO_POINT)
{
delayed_auth_pass_purge();
}
/* Test if errors */
if (flags & ISC_ERRORS)
{

View file

@ -1430,7 +1430,11 @@ purge_user_pass(struct user_pass *up, const bool force)
secure_memzero(up, sizeof(*up));
up->nocache = nocache;
}
else if (!warn_shown)
/*
* don't show warning if the pass has been replaced by a token: this is an
* artificial "auth-nocache"
*/
else if (!warn_shown && (!up->tokenized))
{
msg(M_WARN, "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this");
warn_shown = true;
@ -1444,6 +1448,7 @@ set_auth_token(struct user_pass *up, const char *token)
{
CLEAR(up->password);
strncpynt(up->password, token, USER_PASS_LEN);
up->tokenized = true;
}
}

View file

@ -201,6 +201,8 @@ struct user_pass
{
bool defined;
bool nocache;
bool tokenized; /* true if password has been substituted by a token */
bool wait_for_push; /* true if this object is waiting for a push-reply */
/* max length of username/password */
#ifdef ENABLE_PKCS11

View file

@ -451,6 +451,8 @@ ssl_set_auth_nocache(void)
{
passbuf.nocache = true;
auth_user_pass.nocache = true;
/* wait for push-reply, because auth-token may invert nocache */
auth_user_pass.wait_for_push = true;
}
/*
@ -459,6 +461,14 @@ ssl_set_auth_nocache(void)
void
ssl_set_auth_token(const char *token)
{
if (auth_user_pass.nocache)
{
msg(M_INFO,
"auth-token received, disabling auth-nocache for the "
"authentication token");
auth_user_pass.nocache = false;
}
set_auth_token(&auth_user_pass, token);
}
@ -2383,7 +2393,21 @@ key_method_2_write(struct buffer *buf, struct tls_session *session)
{
goto error;
}
purge_user_pass(&auth_user_pass, false);
/* if auth-nocache was specified, the auth_user_pass object reaches
* a "complete" state only after having received the push-reply
* message.
* This is the case because auth-token statement in a push-reply would
* invert its nocache.
*
* For this reason, skip the purge operation here if no push-reply
* message has been received yet.
*
* This normally happens upon first negotiation only.
*/
if (!auth_user_pass.wait_for_push)
{
purge_user_pass(&auth_user_pass, false);
}
}
else
{
@ -4226,6 +4250,13 @@ done:
return BSTR(&out);
}
void
delayed_auth_pass_purge(void)
{
auth_user_pass.wait_for_push = false;
purge_user_pass(&auth_user_pass, false);
}
#else /* if defined(ENABLE_CRYPTO) */
static void
dummy(void)

View file

@ -598,6 +598,8 @@ void extract_x509_field_test(void);
*/
bool is_hard_reset(int op, int key_method);
void delayed_auth_pass_purge(void);
#endif /* ENABLE_CRYPTO */
#endif /* ifndef OPENVPN_SSL_H */