Opened 5 months ago

Last modified 5 months ago

#1447 new Bug / Defect

Cannot reauthenticate clients using auth-token with management-client-auth

Reported by: jermy Owned by:
Priority: minor Milestone:
Component: Generic / unclassified Version: OpenVPN 2.5.4 (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords:


In order to implement MFA with both static and dynamic challenges, I've implemented a daemon to read CLIENT notifications from the Management Interface and send appropriate client-auth / client-deny responses.

To allow MFA clients to start logged in for a long time, I've also set auth-gen-token.

Basic/relevant lines of the server config are:

reneg-sec 3600
auth-gen-token 172800

management "/var/run/openvpn/vpn3.sock" unix

Relevant lines from the client config are:

static-challenge "Enter Verification Code" 1
auth-retry interact

The issue is that on token refresh, clients that support auth-token fail to re-authenticate. The server reports the token as valid, but also as deferred without notifying the management interface and the client connection is lost.

Typical server logs (verb 3) look like:

Jan 27 11:53:41 vpnserver ovpn-vpn3[11627]: TLS: Username/auth-token authentication succeeded for username 'vpnuser'
Jan 27 11:53:41 vpnserver ovpn-vpn3[11627]: TLS: Username/Password authentication deferred for username 'vpnuser'
Jan 27 11:53:41 vpnserver ovpn-vpn3[11627]: Control Channel: TLSv1.2, cipher TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384, peer certificate: 2048 bit RSA, signature: RSA-SHA256
Jan 27 11:53:41 vpnserver ovpn-vpn3[11627]: [vpnuser_profile] Peer Connection Initiated with [AF_INET6]
Jan 27 11:53:42 vpnserver ovpn-vpn3[11627]: PUSH: Received control message: 'PUSH_REQUEST'
Jan 27 11:53:47 vpnserver ovpn-vpn3[11627]: PUSH: Received control message: 'PUSH_REQUEST'
Jan 27 11:53:53 vpnserver ovpn-vpn3[11627]: PUSH: Received control message: 'PUSH_REQUEST'
Jan 27 11:53:58 vpnserver ovpn-vpn3[11627]: PUSH: Received control message: 'PUSH_REQUEST'
Jan 27 11:54:03 vpnserver ovpn-vpn3[11627]: PUSH: Received control message: 'PUSH_REQUEST'
Jan 27 11:54:08 vpnserver ovpn-vpn3[11627]: PUSH: Received control message: 'PUSH_REQUEST'
Jan 27 11:54:13 vpnserver ovpn-vpn3[11627]: [vpnuser_profile] Inactivity timeout (--ping-restart), restarting

In ssl_verify.c / verify_user_pass it looks like the token is validated...

        else if (ks->auth_token_state_flags == AUTH_TOKEN_HMAC_OK)
             * We do not want the EXPIRED or EMPTY USER flags here so check
             * for equality with AUTH_TOKEN_HMAC_OK
            msg(M_WARN, "TLS: Username/auth-token authentication "
                "succeeded for username '%s'",
            skip_auth = true;

...which the causes the management interface not to be notified...

    if (!skip_auth)
        if (man_def_auth == KMDA_DEF)
            man_def_auth = verify_user_pass_management(session, multi, up);

...but man_def_auth == KMDA_DEF means authenticated is set to the KS_AUTH_DEFERRED state...

        ks->authenticated = KS_AUTH_TRUE;
        if (plugin_status == OPENVPN_PLUGIN_FUNC_DEFERRED
            || script_status == OPENVPN_PLUGIN_FUNC_DEFERRED)
            ks->authenticated = KS_AUTH_DEFERRED;
        if (man_def_auth != KMDA_UNDEF)
            ks->authenticated = KS_AUTH_DEFERRED;

...and the connection is not re-authenticated.

It seems like an easy fix would be changing the last bit to:

        if (man_def_auth != KMDA_UNDEF && !skip_auth)
            ks->authenticated = KS_AUTH_DEFERRED;

But there may be a cleaner way to handle this.

In the circumstances, I'm now using auth-gen-token 172800 external-auth which sends all re-authentication requests to the daemon which can then be handled appropriately.

Change History (5)

comment:1 Changed 5 months ago by Selva Nair

The combined use of --auth-gen-token and --management-client-auth probably has never been tested and the behaviour reported here looks like a bug.

Have you tried pushing the auth-token from the management-client-auth handler (i.e the python script in this case) via the client-auth response, so that the entire auth process including reauth is handled in one place? That was the only way to use auth-token prior to the introduction of --auth-gen-token in 2.4. REAUTH vs CONNECT is indicated in the >CLIENT notification.

comment:2 Changed 5 months ago by jermy

I did try that (pushing an auth-token) earlier in development, but my main test client at the time was network-manager-openvpn (Ubuntu 20.04, version 1.8.12-1) which doesn't return auth-ticket to the server anyway. At the time, the sanitisation of auth-token/session_id values in logs separately made it difficult to work out if this handling was a server or client issue!

I was hoping to use auth-gen-token to shift the onus of re-authenticating clients away from my daemon and having to maintain its own state of authenticated sessions, but if I'm going to have to do that anyway, using external-auth until this issue is resolved works for me.

comment:3 Changed 5 months ago by tct

For testing purposes, you do not need Network-Manager. Simply run each Openvpn process via a systemd-unit file, openvpn-server@.service and openvpn-client@.service.

comment:4 Changed 5 months ago by jermy

This was more for integration tests - a lot of our users will be connecting through Ubuntu/Debian? so making sure those work straight up was important. Other users are using the standard client, and those are much more straightforward generally (apart from the usual issues with DNS updates on linux).

comment:5 Changed 5 months ago by Gert Döring

Auth-Tokens with Network-Manager do work, but NM has... ideas... on how things are supposed to work. The problem is when you do suspend/resume or change networks, NM will shutdown and restart openvpn - and there is no way to save the received auth-token anywhere in this case, so "back to 2FA".

Note: See TracTickets for help on using tickets.