From patchwork Wed Dec 16 04:33:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1554 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wDg8OQsp2l/xEgAAIUCqbw (envelope-from ) for ; Wed, 16 Dec 2020 10:34:35 -0500 Received: from proxy10.mail.iad3b.rsapps.net ([172.31.255.6]) by director9.mail.ord1d.rsapps.net with LMTP id YPELOQsp2l+iNgAAalYnBA (envelope-from ) for ; Wed, 16 Dec 2020 10:34:35 -0500 Received: from smtp36.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy10.mail.iad3b.rsapps.net with LMTPS id MK6AMgsp2l+fZAAA/F5p9A (envelope-from ) for ; Wed, 16 Dec 2020 10:34:35 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp36.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 32d67f50-3fb4-11eb-b870-5254003a7283-1-1 Received: from [216.105.38.7] ([216.105.38.7:54598] helo=lists.sourceforge.net) by smtp36.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 14/CE-07797-A092ADF5; Wed, 16 Dec 2020 10:34:35 -0500 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kpYo7-0002Xm-Gc; Wed, 16 Dec 2020 15:33:39 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kpYo5-0002XL-KL for openvpn-devel@lists.sourceforge.net; Wed, 16 Dec 2020 15:33:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=6Qam6SwgNK0P9+CSpMPO4UcmMjBkH52bmo4x9hVfCaE=; b=TkEhuo+fUrE9DnNM46Z3jpUoI7 Z2lUQ/9TsA+0wPkxN/aP6T9ZtKJQrzz/J+ogdVQgmJKCi/Mbb/XS46qVR4Ybdf3DKta6YpaXWh1rf efqi+uXg9Fc8MUhNRd31HSrDvAs9QKE9/jFJ78HFGfuVQuCF63KWrhB/8nbP1Titj8Rs=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:MIME-Version: Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=6Qam6SwgNK0P9+CSpMPO4UcmMjBkH52bmo4x9hVfCaE=; b=GLhHBsAE6gfF+IDZOvWmi6keRi Y1ZqR1Ta4Jn2h/Nzyw9hlZ5m6L0JfUImzaWhCseuGvxGCLvdsp4t8TZhaNR9wqC8HDLlCf0/+R0KD AhEa/pGHFt/Oa7XNkxc0P6sM8aKrV+Pjzg8LHVIWfiXq5Y5FGg7NQ56h3mMit07UVQig=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kpYnx-00GWfc-8u for openvpn-devel@lists.sourceforge.net; Wed, 16 Dec 2020 15:33:37 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94 (FreeBSD)) (envelope-from ) id 1kpYnl-0004oa-IN for openvpn-devel@lists.sourceforge.net; Wed, 16 Dec 2020 16:33:17 +0100 Received: (nullmailer pid 20765 invoked by uid 10006); Wed, 16 Dec 2020 15:33:17 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 16 Dec 2020 16:33:17 +0100 Message-Id: <20201216153317.20718-1-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: rfc2549.org] 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1kpYnx-00GWfc-8u Subject: [Openvpn-devel] [PATCH] Implement auth-token-user X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Even for non username/password session using a auth token can make, e.g. for allowing a session to continue after a reconnect. Since without username openvpn does not have a username it will just ignore pushed auth-token command. This adds support for auth-token-user to set the username. The spec of using auth-token-user base64-encoded-user are the ones that OpenVPN3 already implements. Signed-off-by: Arne Schwabe --- doc/man-sections/client-options.rst | 6 +++++ src/openvpn/misc.c | 37 +++++++++++++++++++++++++---- src/openvpn/misc.h | 21 +++++++++++++--- src/openvpn/options.c | 5 ++++ src/openvpn/ssl.c | 12 +++++++--- src/openvpn/ssl.h | 2 ++ 6 files changed, 72 insertions(+), 11 deletions(-) diff --git a/doc/man-sections/client-options.rst b/doc/man-sections/client-options.rst index af21fbcd..63f82090 100644 --- a/doc/man-sections/client-options.rst +++ b/doc/man-sections/client-options.rst @@ -50,6 +50,12 @@ configuration. after a failed auth. Older clients will keep using the token value and react according to ``--auth-retry`` +--auth-token-user base64username + Companion option to ``--auth-token``. This options allows to override + the username used by the client when reauthenticating with the ``auth-token``. + It also allows to use ``--auth-token`` in setups that normally do not use + username and password. + --auth-user-pass Authenticate with server using username/password. diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index c0c72dd7..531f685c 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -510,22 +510,49 @@ void set_auth_token(struct user_pass *up, struct user_pass *tk, const char *token) { - if (strlen(token) && (up->defined || tk->defined)) + if (strlen(token)) { - /* auth-token has no password, so it needs the username - * either already set or copied from up */ strncpynt(tk->password, token, USER_PASS_LEN); - if (up->defined) + tk->token_defined = true; + + /* + * auth-token has no password, so it needs the username + * either already set or copied from up, or later set by + * --auth-token-user + * + * Do not overwrite the username if already set to avoid + * overwriting an auth-token + */ + if (up->defined && !tk->defined) { strncpynt(tk->username, up->username, USER_PASS_LEN); + tk->defined = true; } - tk->defined = true; } /* Cleans user/pass for nocache */ purge_user_pass(up, false); } +void +set_auth_token_user(struct user_pass *tk, const char *username) +{ + if (strlen(username)) + { + /* Clear the username before decoding to ensure no old material is left + * and also allow decoding to not use all sapce to ensure the last byte is + * always 0 */ + CLEAR(tk->username); + int len = openvpn_base64_decode(username, tk->username, USER_PASS_LEN - 1); + tk->defined = len > 0; + if (!tk->defined) + { + msg(D_PUSH, "Error decoding auth-token-username"); + } + } +} + + /* * Process string received by untrusted peer before * printing to console or log file. diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h index e4342b0d..5e7f230b 100644 --- a/src/openvpn/misc.h +++ b/src/openvpn/misc.h @@ -63,6 +63,9 @@ const char *hostname_randomize(const char *hostname, struct gc_arena *gc); struct user_pass { bool defined; + /* For auth-token username and token can be set indiviually, so + * we this second bool to track if the token (password) is defined */ + bool token_defined; bool nocache; /* max length of username/password */ @@ -145,19 +148,31 @@ void fail_user_pass(const char *prefix, void purge_user_pass(struct user_pass *up, const bool force); /** - * Sets the auth-token to token if a username is available from either - * up or already present in tk. The method will also purge up if + * Sets the auth-token to token. Ff a username is available from either + * up or already present in tk is the auth-token that will be used as default + * username for the token. The method will also purge up if * the auth-nocache option is active. * * @param up (non Auth-token) Username/password * @param tk auth-token userpass to set - * @param token token to use as password for the + * @param token token to use as password for the auth-token * * @note all parameters to this function must not be null. */ void set_auth_token(struct user_pass *up, struct user_pass *tk, const char *token); +/** + * Sets the auth-token username by base64 decoding the passed + * username + * + * @param tk auth-token userpass to set + * @param username base64 encoded username to set + * + * @note all parameters to this function must not be null. + */ +void set_auth_token_user(struct user_pass *tk, const char *username); + /* * Process string received by untrusted peer before * printing to console or log file. diff --git a/src/openvpn/options.c b/src/openvpn/options.c index ff3954d5..f9276e9a 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -8272,6 +8272,11 @@ add_option(struct options *options, } #endif } + else if (streq(p[0], "auth-token-user") && p[1] && !p[2]) + { + VERIFY_PERMISSION(OPT_P_ECHO); + ssl_set_auth_token_user(p[1]); + } else if (streq(p[0], "single-session") && !p[1]) { VERIFY_PERMISSION(OPT_P_GENERAL); diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index efbf688f..08ddc76e 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -445,6 +445,12 @@ ssl_set_auth_token(const char *token) set_auth_token(&auth_user_pass, &auth_token, token); } +void +ssl_set_auth_token_user(const char *username) +{ + set_auth_token_user(&auth_token, username); +} + /* * Cleans an auth token and checks if it was active */ @@ -2383,8 +2389,8 @@ key_method_2_write(struct buffer *buf, struct tls_session *session) } } - /* write username/password if specified */ - if (auth_user_pass_enabled) + /* write username/password if specified or we are using a auth-token*/ + if (auth_user_pass_enabled || (auth_token.token_defined && auth_token.defined)) { #ifdef ENABLE_MANAGEMENT auth_user_pass_setup(session->opt->auth_user_pass_file, session->opt->sci); @@ -2397,7 +2403,7 @@ key_method_2_write(struct buffer *buf, struct tls_session *session) * If we have a valid auth-token, send that instead of real * username/password */ - if (auth_token.defined) + if (auth_token.token_defined && auth_token.defined) { up = &auth_token; } diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index 56034540..5a77e701 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -440,6 +440,8 @@ void ssl_purge_auth(const bool auth_user_pass_only); void ssl_set_auth_token(const char *token); +void ssl_set_auth_token_user(const char *username); + bool ssl_clean_auth_token(void); #ifdef ENABLE_MANAGEMENT