From patchwork Wed Sep 30 03:13:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1493 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id +LHBJb+EdF+VYwAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:39 -0400 Received: from proxy5.mail.iad3b.rsapps.net ([172.31.255.6]) by director8.mail.ord1d.rsapps.net with LMTP id 4IefJb+EdF/7eAAAfY0hYg (envelope-from ) for ; Wed, 30 Sep 2020 09:14:39 -0400 Received: from smtp16.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy5.mail.iad3b.rsapps.net with LMTPS id yKNOHb+EdF8sLAAA13hMnw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:39 -0400 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: smtp16.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: e4894728-031e-11eb-9f4c-5254004ed364-1-1 Received: from [216.105.38.7] ([216.105.38.7:57224] helo=lists.sourceforge.net) by smtp16.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 74/FB-21728-EB4847F5; Wed, 30 Sep 2020 09:14:39 -0400 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 1kNbvV-0005go-If; Wed, 30 Sep 2020 13:13:45 +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 1kNbvR-0005g1-VZ for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=3J1dOmUJ9Rs2nHs+YGAoF+0EhoDTOBHbji+hd0vCyqw=; b=XHW+K3aSUmdYg2igci8HpKYpx+ 14KpDwLovN6CD0zzmdxtMxhAa9aw94G07StWIBkVPSiDUoqWCHuqUB9vebO3s6P3huPUK1dRPc/bn dLL+TdQI4zdlS2J1ZFmQFzCW/WzVwoMXpgC+CAAnZ14WtgYpTcW1jtlot7wfZ1TEzuXg=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=3J1dOmUJ9Rs2nHs+YGAoF+0EhoDTOBHbji+hd0vCyqw=; b=AnJD/ogJUocitC2odg85OfpxhR 4zLH+LezfUEANj2ftLPE0TM4a3GhiEbiH9WvAlHCyoCVoZAh4JP6MNAFku8OgmX5Fgp0ezOVIVcb/ kg/TUL7dwTM0fk5U3PD3TGA9xqW7oyTrcRHGtI6pE9gE2XnrypzyuMHYbsINoFmWB4qA=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNbvL-00EOO5-GS for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:41 +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 1kNbv4-0003nm-6L for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1355 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:07 +0200 Message-Id: <20200930131317.1299-3-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 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 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] X-Headers-End: 1kNbvL-00EOO5-GS Subject: [Openvpn-devel] [PATCH 01/11] Change pull request timeout use a timeout rather than a number 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 This commit changes the count n_sent_push_requests to time_t based push_request_timeout. This is more in line to our other timeouts which are also time based instead of number retries based. This does not change the behaviour but it prepares allowing to extend the pull request timeout during a pending authentication. As a user visible change we print the the time we waited for a timeout instead Also update the man page to actually document that hand-window controls this timeout. Signed-off-by: Arne Schwabe --- doc/man-sections/tls-options.rst | 4 ++++ src/openvpn/forward.c | 1 + src/openvpn/openvpn.h | 2 +- src/openvpn/push.c | 9 ++++++--- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/man-sections/tls-options.rst b/doc/man-sections/tls-options.rst index 8c2db7cd..4d9ee2dc 100644 --- a/doc/man-sections/tls-options.rst +++ b/doc/man-sections/tls-options.rst @@ -200,6 +200,10 @@ certificates and keys: https://github.com/OpenVPN/easy-rsa will still use our expiring key for up to ``--tran-window`` seconds to maintain continuity of transmission of tunnel data. + The ``--hand-window`` parameter also controls the amount of of time that + the OpenVPN client repeats the pull request until it times out on pull + requests until giving up. + --key file Local peer's private key in .pem format. Use the private key which was generated when you built your peer's certificate (see ``--cert file`` diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 7ed8d0d7..325f1373 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -292,6 +292,7 @@ check_connection_established(struct context *c) } #endif /* fire up push request right away (already 1s delayed) */ + c->c2.push_request_timeout = now + c->options.handshake_window; event_timeout_init(&c->c2.push_request_interval, 0, now); reset_coarse_timers(c); } diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index a7b59774..4630b33e 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -462,7 +462,7 @@ struct context_2 enum client_connect_status context_auth; struct event_timeout push_request_interval; - int n_sent_push_requests; + time_t push_request_timeout; bool did_pre_pull_restore; /* hash of pulled options, so we can compare when options change */ diff --git a/src/openvpn/push.c b/src/openvpn/push.c index e0d2eeaf..5fc3eb18 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -369,14 +369,17 @@ cleanup: bool send_push_request(struct context *c) { - const int max_push_requests = c->options.handshake_window / PUSH_REQUEST_INTERVAL; - if (++c->c2.n_sent_push_requests <= max_push_requests) + struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; + struct key_state *ks = &session->key[KS_PRIMARY]; + + if (c->c2.push_request_timeout > now) { return send_control_channel_string(c, "PUSH_REQUEST", D_PUSH); } else { - msg(D_STREAM_ERRORS, "No reply from server after sending %d push requests", max_push_requests); + msg(D_STREAM_ERRORS, "No reply from server to push requests in %ds", + (int)(now - ks->established)); c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */ c->sig->signal_text = "no-push-reply"; return false; From patchwork Wed Sep 30 03:13:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1495 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director11.mail.ord1d.rsapps.net ([172.28.255.1]) by backend30.mail.ord1d.rsapps.net with LMTP id CH4CNsGEdF8ECQAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:41 -0400 Received: from proxy9.mail.ord1c.rsapps.net ([172.28.255.1]) by director11.mail.ord1d.rsapps.net with LMTP id aHXsNcGEdF/LRAAAvGGmqA (envelope-from ) for ; Wed, 30 Sep 2020 09:14:41 -0400 Received: from smtp27.gate.ord1c ([172.28.255.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy9.mail.ord1c.rsapps.net with LMTPS id GJexNcGEdF/FPQAAgxtkuw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:41 -0400 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: smtp27.gate.ord1c.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: e5c1d0ba-031e-11eb-b246-b8ca3a655ab8-1-1 Received: from [216.105.38.7] ([216.105.38.7:55170] helo=lists.sourceforge.net) by smtp27.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id BB/74-08486-0C4847F5; Wed, 30 Sep 2020 09:14:40 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNbvY-0003To-GR; Wed, 30 Sep 2020 13:13:48 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNbvS-0003Sw-PG for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=9aVslo2bwgHozmTj3d7UQuchcM3ZdKkq9PRfIQml4A4=; b=Pm73w/GpmkQNpSVXRTsJSyFXVS VYrumJ0boYYrYsZzazZQesGvcDbaSMUuWamqzV2dLj/hi9PGdmQrCyxJCScLedM6FWqvV6JYOcwhK 7p/aNDIWA2QEESYS/IW3igNpJU+V1GVmwJplLSMD0o0I6rwlYPEXAZ1xEQCPeqZl6ORg=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=9aVslo2bwgHozmTj3d7UQuchcM3ZdKkq9PRfIQml4A4=; b=VgQgkVgEH1qEsT4RpkbzX+0VWQ 9p9vVzVg7ZYgAYqpZqULjXCpmPDFspkX+j9BUtJR34rmF+stem8kOBDMDEN+n/W0rkS8vI4NPW+jm dXd+5LeBfYopswVuxwet2rJANUQM07Mb6mhetClrtfmqWi4Zs0oXefmwg553M4yE+dmw=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNbvL-00EONj-EC for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:42 +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 1kNbv4-0003nr-8O for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1358 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:08 +0200 Message-Id: <20200930131317.1299-4-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNbvL-00EONj-EC Subject: [Openvpn-devel] [PATCH 02/11] Implement client side handling of AUTH_PENDING message 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 This allows a client to extend the timeout of pull-request response while waiting for the user to complete a pending authentication. A timeout of 60s for a normal authentication might still works for a simple 2FA (but still challenging). With a sophisticated (or overly complicated) web based authentication 60s are quite short. To avoid not detecting network problem in this phase, we use the constant sending of PUSH_REQUEST/AUTH_PENDING as keepalive signal and still timeout the session after the handshake window time. Signed-off-by: Arne Schwabe --- doc/man-sections/server-options.rst | 4 ++ doc/management-notes.txt | 39 ++++++++++++---- src/openvpn/forward.c | 11 ++++- src/openvpn/integer.h | 25 ++++++++++ src/openvpn/push.c | 72 ++++++++++++++++++++++++++++- src/openvpn/push.h | 9 ++++ src/openvpn/ssl.c | 3 ++ src/openvpn/ssl.h | 3 ++ src/openvpn/ssl_common.h | 1 + 9 files changed, 156 insertions(+), 11 deletions(-) diff --git a/doc/man-sections/server-options.rst b/doc/man-sections/server-options.rst index 5a689452..271c54d0 100644 --- a/doc/man-sections/server-options.rst +++ b/doc/man-sections/server-options.rst @@ -473,6 +473,10 @@ fast hardware. SSL/TLS authentication must be used in this mode. - bit 1: The peer supports peer-id floating mechanism - bit 2: The client expects a push-reply and the server may send this reply without waiting for a push-request first. + - bit 3: The client is capable of doing key derivation using + RFC5705 key material exporter. + - bit 4: The client is capable of accepting additional arguments + to the `AUTH_PENDING` message. :code:`IV_NCP=2` Negotiable ciphers, client supports ``--cipher`` pushed by diff --git a/doc/management-notes.txt b/doc/management-notes.txt index 61daaf07..99ba178a 100644 --- a/doc/management-notes.txt +++ b/doc/management-notes.txt @@ -600,14 +600,30 @@ to signal a pending authenticating to the client. A pending auth means that the connecting requires extra authentication like a one time password or doing a single sign one via web. - client-pending-auth {CID} {EXTRA} - -The server will send AUTH_PENDING and INFO_PRE,{EXTRA} to the client. -The client is expected to inform the user that authentication is pending and -display the extra information. For the format of EXTRA see below -For the OpenVPN server this is stateless operation and needs to be -followed by a client-deny/client-auth[-nt] command (that is the result of the -out of band authentication). + client-pending-auth {CID} {EXTRA} {TIMEOUT} + +The server will send AUTH_PENDING and INFO_PRE,{EXTRA} to the client. If the +client supports accepting keywords to AUTH_PENDING (announced via IV_PROTO), +TIMEOUT parameter will be also be announced to the client to allow it to modify +its own timeout. The client is expected to inform the user that authentication +is pending and display the extra information and also show the user the +remaining time to complete the auth if applicable. + +Receiving a AUTH_PENDING message will make the client change its timeout the +timeout proposed by the server, even if the timeout is shorter. +If the client does not receive a packet from the server for hand-window the +connection times out regardless of the timeout. This ensures that the connection +still times out relatively quickly in case of network problems. The client will +continously send PULL_REQUEST messages to the server until the timeout is reached. +This message also triggers an ACK message from the server that resets the +hand-window based timeout. + +Both client and server limit the maximum timeout to the smaller value of half the +--tls-reneg minimum time and --hand-window time (defaults to 60s). + +For the format of EXTRA see below. For the OpenVPN server this is a stateless +operation and needs to be followed by a client-deny/client-auth[-nt] command +(that is the result of the out of band authentication). Before issuing a client-pending-auth to a client instead of a client-auth/client-deny, the server should check the IV_SSO @@ -620,7 +636,7 @@ set setenv IV_SSO openurl,crtext The variable name IV_SSO is historic as AUTH_PENDING was first used -to signal single sign on support. To keep compatiblity with existing +to signal single sign on support. To keep compatibility with existing implementations the name IV_SSO is kept in lieu of a better name. openurl @@ -636,6 +652,11 @@ The space in a control message is limited, so this url should be kept short to avoid issues. If a loger url is required a URL that redirects to the longer URL should be sent instead. +A complete documentation how URLs should be handled on the client is available +in the openvpn3 repository: + +https://github.com/OpenVPN/openvpn3/blob/master/doc/webauth.md + url_proxy ======== To avoid issues with OpenVPN connection persist-tun and not able diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 325f1373..7d559544 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -233,6 +233,10 @@ check_incoming_control_channel(struct context *c) { receive_cr_response(c, &buf); } + else if (buf_string_match_head_str(&buf, "AUTH_PENDING")) + { + receive_auth_pending(c, &buf); + } else { msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(&buf)); @@ -292,7 +296,12 @@ check_connection_established(struct context *c) } #endif /* fire up push request right away (already 1s delayed) */ - c->c2.push_request_timeout = now + c->options.handshake_window; + /* We might receive a AUTH_PENDING request before we armed this + * timer. In that case we don't change the value */ + if (c->c2.push_request_timeout < now) + { + c->c2.push_request_timeout = now + c->options.handshake_window; + } event_timeout_init(&c->c2.push_request_interval, 0, now); reset_coarse_timers(c); } diff --git a/src/openvpn/integer.h b/src/openvpn/integer.h index 3755f43f..0c3511e6 100644 --- a/src/openvpn/integer.h +++ b/src/openvpn/integer.h @@ -39,6 +39,31 @@ /* * min/max functions */ +static inline unsigned int +max_uint(unsigned int x, unsigned int y) +{ + if (x > y) + { + return x; + } + else + { + return y; + } +} + +static inline unsigned int +min_uint(unsigned int x, unsigned int y) +{ + if (x < y) + { + return x; + } + else + { + return y; + } +} static inline int max_int(int x, int y) diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 5fc3eb18..44633dc6 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -231,6 +231,66 @@ receive_cr_response(struct context *c, const struct buffer *buffer) msg(D_PUSH, "CR response was sent by client ('%s')", m); } +/** + * Parse the keyword for the AUTH_PENDING request + * @param buffer buffer containing the keywords, the buffer's + * content will be modified by this function + * @param server_timeout timeout pushed by the server or unchanged + * if the server does not push a timeout + */ +static void +parse_auth_pending_keywords(const struct buffer *buffer, + unsigned int *server_timeout) +{ + struct buffer buf = *buffer; + + /* does the buffer start with "AUTH_PENDING," ? */ + if (!buf_advance(&buf, strlen("AUTH_PENDING")) + || !(buf_read_u8(&buf) == ',') || !BLEN(&buf)) + { + return; + } + + /* parse the keywords in the same way that push options are parsed */ + char line[OPTION_LINE_SIZE]; + + while (buf_parse(&buf, ',', line, sizeof(line))) + { + if (sscanf(line, "timeout %u", server_timeout) == 1) + { + ; + } + else + { + msg(D_PUSH, "ignoring AUTH_PENDING parameter: %s", line); + } + } +} + +void +receive_auth_pending(struct context *c, const struct buffer *buffer) +{ + if (!c->options.pull) + return; + + /* Cap the increase at the maximum time we are willing stay in the + * pending authentication state */ + unsigned int max_timeout = max_uint(c->options.renegotiate_seconds/2, + c->options.handshake_window); + + /* try to parse parameter keywords, default to hand-winow timeout if the + * server does not supply a timeout */ + unsigned int server_timeout = c->options.handshake_window; + parse_auth_pending_keywords(buffer, &server_timeout); + + msg(D_PUSH, "AUTH_PENDING received, extending handshake timeout from %us " + "to %us", c->options.handshake_window, + min_uint(max_timeout, server_timeout)); + + struct key_state *ks = &c->c2.tls_multi->session[TM_ACTIVE].key[KS_PRIMARY]; + c->c2.push_request_timeout = ks->established + min_uint(max_timeout, server_timeout); +} + /** * Add an option to the given push list by providing a format string. * @@ -372,7 +432,17 @@ send_push_request(struct context *c) struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; struct key_state *ks = &session->key[KS_PRIMARY]; - if (c->c2.push_request_timeout > now) + /* We timeout here under two conditions: + * a) we reached the hard limit of push_request_timeout + * b) we have not seen anything from the server in hand_window time + * + * for non auth-pending scenario, push_request_timeout is the same as + * hand_window timeout. For b) every PUSH_REQUEST is a acknowledged by + * the server by a P_ACK_V1 packet that reset the keepalive timer + */ + + if (c->c2.push_request_timeout > now + && (now - ks->peer_last_packet) < c->options.handshake_window) { return send_control_channel_string(c, "PUSH_REQUEST", D_PUSH); } diff --git a/src/openvpn/push.h b/src/openvpn/push.h index 2faf19a6..01847671 100644 --- a/src/openvpn/push.h +++ b/src/openvpn/push.h @@ -89,5 +89,14 @@ void send_restart(struct context *c, const char *kill_msg); */ void send_push_reply_auth_token(struct tls_multi *multi); +/** + * Parses an AUTH_PENDING message and if in pull mode extends the timeout + * + * @param c The context struct + * @param buffer Buffer containing the control message with AUTH_PENDING + */ +void +receive_auth_pending(struct context *c, const struct buffer *buffer); + #endif /* if P2MP */ #endif /* ifndef PUSH_H */ diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 3fcaa25f..c019c194 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -2218,6 +2218,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session) if(session->opt->pull) { iv_proto |= IV_PROTO_REQUEST_PUSH; + iv_proto |= IV_PROTO_AUTH_PENDING_KW; } buf_printf(&out, "IV_PROTO=%d\n", iv_proto); @@ -3669,6 +3670,8 @@ tls_pre_decrypt(struct tls_multi *multi, } } } + /* Remember that we received a valid control channel packet */ + ks->peer_last_packet = now; done: buf->len = 0; diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index 005628f6..cce61354 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -117,6 +117,9 @@ #define IV_PROTO_REQUEST_PUSH (1<<2) +/** Supports signaling keywords with AUTH_PENDING, e.g. timeout=xy */ +#define IV_PROTO_AUTH_PENDING_KW (1<<4) + /* Default field in X509 to be username */ #define X509_USERNAME_FIELD_DEFAULT "CN" diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 96897e48..d0a2c89b 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -178,6 +178,7 @@ struct key_state time_t established; /* when our state went S_ACTIVE */ time_t must_negotiate; /* key negotiation times out if not finished before this time */ time_t must_die; /* this object is destroyed at this time */ + time_t peer_last_packet; /* Last time we received a paket in this control session */ int initial_opcode; /* our initial P_ opcode */ struct session_id session_id_remote; /* peer's random session ID */ From patchwork Wed Sep 30 03:13:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1494 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id CIb3BsCEdF+VYwAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:40 -0400 Received: from proxy12.mail.iad3b.rsapps.net ([172.31.255.6]) by director10.mail.ord1d.rsapps.net with LMTP id yGfiBsCEdF80HgAApN4f7A (envelope-from ) for ; Wed, 30 Sep 2020 09:14:40 -0400 Received: from smtp13.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy12.mail.iad3b.rsapps.net with LMTPS id WIJXAMCEdF86AgAAEsW3lA (envelope-from ) for ; Wed, 30 Sep 2020 09:14:40 -0400 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: smtp13.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: e4f32404-031e-11eb-ad0f-5254001dfc40-1-1 Received: from [216.105.38.7] ([216.105.38.7:60178] helo=lists.sourceforge.net) by smtp13.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 10/BF-17202-FB4847F5; Wed, 30 Sep 2020 09:14:39 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNbvQ-0001CW-Bl; Wed, 30 Sep 2020 13:13:40 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNbvM-0001Bt-M1 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:36 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=azUFXrv0/frBXPnfqNXj9RtFawLkWPNaXtex1bBi1Wo=; b=ax42vsRfytelYjD/w0DFi3GcSl 7YYEcZ+1tfINhVcn2A77d1y/QJeJeKC1LYoWlxkco7+NfQNyHRaL8LRYV8NqGG/W8UzpmxtEQftD3 NP2VHJh/lkCIWBNNLNf4xltsi/n7axzM3U97LBmBADCvzFNFnis4ObCLqNuX+8ID0mtA=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=azUFXrv0/frBXPnfqNXj9RtFawLkWPNaXtex1bBi1Wo=; b=LHeVASU3PizzP5r2T7KGnfBnMG S2nPG7yR+Io6qh4JMNQ70rBeu6qEXLsg/40mefahd1+VODCKA1E4aNNyyezVZpWvU8E967MQXdobE bxQoXddpdhrXk5OSKjjs2cP5xTZVhgeVnaZe9BzdKKOfLYsorIs7TcnGP5kH0T5k2jpg=; 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 1kNbvH-00BNbT-Rx for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:36 +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 1kNbv4-0003nu-CE for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1361 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:09 +0200 Message-Id: <20200930131317.1299-5-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNbvH-00BNbT-Rx Subject: [Openvpn-devel] [PATCH 03/11] Implement server side of AUTH_PENDING with extending timeout 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 Signed-off-by: Arne Schwabe --- src/openvpn/manage.c | 26 +++++++++++++------ src/openvpn/manage.h | 3 ++- src/openvpn/multi.c | 27 +++----------------- src/openvpn/push.c | 55 +++++++++++++++++++++++++++++++++++++--- src/openvpn/push.h | 10 ++++++++ src/openvpn/ssl.c | 1 + src/openvpn/ssl_common.h | 1 + 7 files changed, 87 insertions(+), 36 deletions(-) diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c index 898cb3b3..8df60d7a 100644 --- a/src/openvpn/manage.c +++ b/src/openvpn/manage.c @@ -990,19 +990,26 @@ parse_cid(const char *str, unsigned long *cid) } static bool -parse_kid(const char *str, unsigned int *kid) +parse_uint(const char *str, const char* what, unsigned int *uint) { - if (sscanf(str, "%u", kid) == 1) + if (sscanf(str, "%u", uint) == 1) { return true; } else { - msg(M_CLIENT, "ERROR: cannot parse KID"); + msg(M_CLIENT, "ERROR: cannot parse %s", what); return false; } } +static bool +parse_kid(const char *str, unsigned int *kid) +{ + return parse_uint(str, "KID", kid); +} + + /** * Will send a notification to the client that succesful authentication * will require an additional step (web based SSO/2-factor auth/etc) @@ -1013,15 +1020,18 @@ parse_kid(const char *str, unsigned int *kid) * the information of the additional steps */ static void -man_client_pending_auth(struct management *man, const char *cid_str, const char *extra) +man_client_pending_auth(struct management *man, const char *cid_str, + const char *extra, const char *timeout_str) { unsigned long cid = 0; - if (parse_cid(cid_str, &cid)) + unsigned int timeout = 0; + if (parse_cid(cid_str, &cid) + && parse_uint(timeout_str, "TIMEOUT", &timeout)) { if (man->persist.callback.client_pending_auth) { bool ret = (*man->persist.callback.client_pending_auth) - (man->persist.callback.arg, cid, extra); + (man->persist.callback.arg, cid, extra, timeout); if (ret) { @@ -1582,9 +1592,9 @@ man_dispatch_command(struct management *man, struct status_output *so, const cha } else if (streq(p[0], "client-pending-auth")) { - if (man_need(man, p, 2, 0)) + if (man_need(man, p, 3, 0)) { - man_client_pending_auth(man, p[1], p[2]); + man_client_pending_auth(man, p[1], p[2], p[3]); } } #ifdef MANAGEMENT_PF diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h index 881bfb14..1c497427 100644 --- a/src/openvpn/manage.h +++ b/src/openvpn/manage.h @@ -176,7 +176,8 @@ struct management_callback struct buffer_list *cc_config); /* ownership transferred */ bool (*client_pending_auth) (void *arg, const unsigned long cid, - const char *url); + const char *extra, + unsigned int timeout); char *(*get_peer_info) (void *arg, const unsigned long cid); #endif #ifdef MANAGEMENT_PF diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 13738180..50e2e350 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -1771,28 +1771,6 @@ multi_client_connect_setenv(struct multi_context *m, gc_free(&gc); } -/** - * Extracts the IV_PROTO variable and returns its value or 0 - * if it cannot be extracted. - * - */ -static unsigned int -extract_iv_proto(const char *peer_info) -{ - - const char *optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; - if (optstr) - { - int proto = 0; - int r = sscanf(optstr, "IV_PROTO=%d", &proto); - if (r == 1 && proto > 0) - { - return proto; - } - } - return 0; -} - /** * Calculates the options that depend on the client capabilities * based on local options and available peer info @@ -3917,14 +3895,15 @@ management_kill_by_cid(void *arg, const unsigned long cid, const char *kill_msg) static bool management_client_pending_auth(void *arg, const unsigned long cid, - const char *extra) + const char *extra, + unsigned int timeout) { struct multi_context *m = (struct multi_context *) arg; struct multi_instance *mi = lookup_by_cid(m, cid); if (mi) { /* sends INFO_PRE and AUTH_PENDING messages to client */ - bool ret = send_auth_pending_messages(&mi->context, extra); + bool ret = send_auth_pending_messages(&mi->context, extra, timeout); multi_schedule_context_wakeup(m, mi); return ret; } diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 44633dc6..ece63650 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -347,26 +347,58 @@ send_auth_failed(struct context *c, const char *client_reason) gc_free(&gc); } + bool -send_auth_pending_messages(struct context *c, const char *extra) +send_auth_pending_messages(struct context *c, const char *extra, + unsigned int timeout) { - send_control_channel_string(c, "AUTH_PENDING", D_PUSH); + struct key_state *ks = &tls_multi->session[TM_ACTIVE].key[KS_PRIMARY]; static const char info_pre[] = "INFO_PRE,"; + struct tls_multi *tls_multi = c->c2.tls_multi; + const char *const peer_info = tls_multi->peer_info; + unsigned int proto = extract_iv_proto(peer_info); + + + /* Calculate the maximum timeout and subtract the time we already waited */ + unsigned int max_timeout = max_uint(tls_multi->opt.renegotiate_seconds/2, + tls_multi->opt.handshake_window); + max_timeout = max_timeout - (now - ks->initial); + timeout = min_uint(max_timeout, timeout); + + struct gc_arena gc = gc_new(); + if ((proto & IV_PROTO_AUTH_PENDING_KW) == 0) + { + send_control_channel_string(c, "AUTH_PENDING", D_PUSH); + } + else + { + static const char auth_pre[] = "AUTH_PENDING,timeout "; + // Assume a worst case of 8 byte uint64 in decimal which + // needs 20 bytes + size_t len = 20 + 1 + sizeof(auth_pre); + struct buffer buf = alloc_buf_gc(len, &gc); + buf_printf(&buf, auth_pre); + buf_printf(&buf, "%u", timeout); + send_control_channel_string(c, BSTR(&buf), D_PUSH); + } + size_t len = strlen(extra)+1 + sizeof(info_pre); if (len > PUSH_BUNDLE_SIZE) { + gc_free(&gc); return false; } - struct gc_arena gc = gc_new(); struct buffer buf = alloc_buf_gc(len, &gc); buf_printf(&buf, info_pre); buf_printf(&buf, "%s", extra); send_control_channel_string(c, BSTR(&buf), D_PUSH); + ks->auth_deferred_expire = now + timeout; + gc_free(&gc); return true; } @@ -1010,4 +1042,21 @@ remove_iroutes_from_push_route_list(struct options *o) } } +unsigned int +extract_iv_proto(const char *peer_info) +{ + + const char *optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; + if (optstr) + { + int proto = 0; + int r = sscanf(optstr, "IV_PROTO=%d", &proto); + if (r == 1 && proto > 0) + { + return proto; + } + } + return 0; +} + #endif /* if P2MP */ diff --git a/src/openvpn/push.h b/src/openvpn/push.h index 01847671..a2192114 100644 --- a/src/openvpn/push.h +++ b/src/openvpn/push.h @@ -89,6 +89,16 @@ void send_restart(struct context *c, const char *kill_msg); */ void send_push_reply_auth_token(struct tls_multi *multi); + +/** + * Extracts the IV_PROTO variable and returns its value or 0 + * if it cannot be extracted. + * + * @param peer_info peer info string to search for IV_PROTO + */ +unsigned int +extract_iv_proto(const char *peer_info); + /** * Parses an AUTH_PENDING message and if in pull mode extends the timeout * diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index c019c194..f0664a0f 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -2709,6 +2709,7 @@ tls_process(struct tls_multi *multi, buf = reliable_get_buf_output_sequenced(ks->send_reliable); if (buf) { + ks->initial = now; ks->must_negotiate = now + session->opt->handshake_window; ks->auth_deferred_expire = now + auth_deferred_expire_window(session->opt); diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index d0a2c89b..7ccd1abb 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -175,6 +175,7 @@ struct key_state struct key_state_ssl ks_ssl; /* contains SSL object and BIOs for the control channel */ + time_t initial; /* when we created this session */ time_t established; /* when our state went S_ACTIVE */ time_t must_negotiate; /* key negotiation times out if not finished before this time */ time_t must_die; /* this object is destroyed at this time */ From patchwork Wed Sep 30 03:13:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1498 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wI5rExqLdF++RwAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:41:46 -0400 Received: from proxy2.mail.ord1d.rsapps.net ([172.30.191.6]) by director10.mail.ord1d.rsapps.net with LMTP id WEJDExqLdF+0HgAApN4f7A (envelope-from ) for ; Wed, 30 Sep 2020 09:41:46 -0400 Received: from smtp1.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy2.mail.ord1d.rsapps.net with LMTPS id sCfPEhqLdF/LNAAAfawv4w (envelope-from ) for ; Wed, 30 Sep 2020 09:41:46 -0400 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: smtp1.gate.ord1d.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: ae0f0a44-0322-11eb-bc8f-5254002d775b-1-1 Received: from [216.105.38.7] ([216.105.38.7:41852] helo=lists.sourceforge.net) by smtp1.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id AF/47-23346-91B847F5; Wed, 30 Sep 2020 09:41:45 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNcLo-0002qa-Uj; Wed, 30 Sep 2020 13:40:56 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNcLm-0002qL-6B for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:40:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R2QQqX7QO5r53BBJDAKgW+EaDc0L7DMUOzoso5JOtiE=; b=FrzeX+iVi1X6+yTu38PYywg2Aw BGp9NDCd39mG9fFoqKXCyVho9/pVP4QkAQu1DOHbPtGpaydDFwqeSEL9k/FZ7jA2IBMBWKj6wV1Af 2qN20lBPmF7IpTv5Y9uhoEISxYdD+eMRFtOOFBdsS4gohqYCx36Gp6+2ihXlTBhgL3iY=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=R2QQqX7QO5r53BBJDAKgW+EaDc0L7DMUOzoso5JOtiE=; b=BS5BxhftVIRrgPnuH5sQ3/y4bV gFEeeSP4n3+eKbLbYr+2AcMgI5cEXcCjSuCEQMqmD5tZ8tJuYF4udSz2+R+P0Q9JKsznQsdi7Qr51 tmkQiWfpEToOixups85BU4avMG3JpMYBR1qo3EZvMIyIRqNkCeo6YGVdafPRZkBCzaZ4=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNcLd-00EQEQ-2U for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:40:54 +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 1kNbv4-0003nx-Ey for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1364 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:10 +0200 Message-Id: <20200930131317.1299-6-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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.0 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: 1kNcLd-00EQEQ-2U Subject: [Openvpn-devel] [PATCH 04/11] Introduce management client state for AUTH_PENDING notifications 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 This allows a UI client to display the correct state. Technically the client is still waiting for PUSH_REPLY but for every practical concern this is a different state as we are waiting for the pending authentication to finish. Signed-off-by: Arne Schwabe Acked-by: Lev Stipakov --- src/openvpn/manage.c | 3 +++ src/openvpn/manage.h | 2 ++ src/openvpn/push.c | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c index 8df60d7a..58ff0155 100644 --- a/src/openvpn/manage.c +++ b/src/openvpn/manage.c @@ -171,6 +171,9 @@ man_state_name(const int state) case OPENVPN_STATE_TCP_CONNECT: return "TCP_CONNECT"; + case OPENVPN_STATE_AUTH_PENDING: + return "AUTH_PENDING"; + default: return "?"; } diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h index 1c497427..1681e141 100644 --- a/src/openvpn/manage.h +++ b/src/openvpn/manage.h @@ -506,6 +506,8 @@ management_enable_def_auth(const struct management *man) #define OPENVPN_STATE_GET_CONFIG 9 /* Downloading configuration from server */ #define OPENVPN_STATE_RESOLVE 10 /* DNS lookup */ #define OPENVPN_STATE_TCP_CONNECT 11 /* Connecting to TCP server */ +#define OPENVPN_STATE_AUTH_PENDING 12 /* Waiting in auth-pending mode + * techhnically variant of GET_CONFIG */ #define OPENVPN_STATE_CLIENT_BASE 7 /* Base index of client-only states */ diff --git a/src/openvpn/push.c b/src/openvpn/push.c index ece63650..59f8f33c 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -248,12 +248,30 @@ parse_auth_pending_keywords(const struct buffer *buffer, if (!buf_advance(&buf, strlen("AUTH_PENDING")) || !(buf_read_u8(&buf) == ',') || !BLEN(&buf)) { +#ifdef ENABLE_MANAGEMENT + if (management) + { + management_set_state(management, OPENVPN_STATE_AUTH_PENDING, + "", NULL, NULL, NULL, NULL); + } +#endif + return; } /* parse the keywords in the same way that push options are parsed */ char line[OPTION_LINE_SIZE]; +#ifdef ENABLE_MANAGEMENT + /* Need to do the management notification with the keywords before + * buf_parse is called, as it will insert \0 bytes into the buffer */ + if (management) + { + management_set_state(management, OPENVPN_STATE_AUTH_PENDING, + BSTR(&buf), NULL, NULL, NULL, NULL); + } +#endif + while (buf_parse(&buf, ',', line, sizeof(line))) { if (sscanf(line, "timeout %u", server_timeout) == 1) From patchwork Wed Sep 30 03:13:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1497 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id CGnTMxSLdF/SRwAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:41:40 -0400 Received: from proxy15.mail.ord1d.rsapps.net ([172.30.191.6]) by director7.mail.ord1d.rsapps.net with LMTP id 0D25MxSLdF+/FAAAovjBpQ (envelope-from ) for ; Wed, 30 Sep 2020 09:41:40 -0400 Received: from smtp6.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy15.mail.ord1d.rsapps.net with LMTPS id sChxMxSLdF84LAAAAY1PeQ (envelope-from ) for ; Wed, 30 Sep 2020 09:41:40 -0400 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: smtp6.gate.ord1d.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: aac031ce-0322-11eb-a7d9-52540050e3e0-1-1 Received: from [216.105.38.7] ([216.105.38.7:48528] helo=lists.sourceforge.net) by smtp6.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 7E/72-09530-31B847F5; Wed, 30 Sep 2020 09:41:39 -0400 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 1kNcLi-0000ia-QM; Wed, 30 Sep 2020 13:40:50 +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 1kNcLi-0000iQ-44 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:40:50 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=C+sMPoyjejNeNGD9ZK/LV+xDLrtCX5EJFOZxsPiIWmU=; b=cfKO/q35TJ4/hkvRsSdfu2cbek WDNWu3F626iIkaPCAhUirOv0FFrTQj4zYd5utUydXWLs+XfeFpFrYju3drwYmOIOMO4SXGfwB8dOe rKxptiW466FW8YguzaUnDFMdPGc5Fm7ZK+wmGSQLUIBdZ5y4w6UHz7gbXpHP0gOn5q8M=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=C+sMPoyjejNeNGD9ZK/LV+xDLrtCX5EJFOZxsPiIWmU=; b=O1oRdNCz4/ipyA1yZgZTM1xkGI Jbfu+km8NAbF4tsAEp6qjdJayfB9vIDtCAWJ9SvCwojiK2PkBjP42AmZmqf22mPg+StsTsb9z4MsO e6tPqs/ydeMK8BJjSCjzN5xD4mWcULFXnPLQvKEzJwDVmj+8mIm6kz4WNYKmXd5VA0RQ=; 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 1kNcLd-00BPLc-LD for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:40:50 +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 1kNbv4-0003o0-HO for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1367 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:11 +0200 Message-Id: <20200930131317.1299-7-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNcLd-00BPLc-LD Subject: [Openvpn-devel] [PATCH 05/11] Change parameter of send_auth_pending_messages from context to tls_multi 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 This prepares send_auth_pending_messages to be used a in context that does not have context c available but also does not need to schedule an immediate sending of the message (auth plugin/script) Signed-off-by: Arne Schwabe Acked-by: Lev Stipakov --- src/openvpn/forward.c | 17 +++++++++-------- src/openvpn/forward.h | 9 +++++++++ src/openvpn/multi.c | 4 +++- src/openvpn/push.c | 9 ++++----- src/openvpn/push.h | 4 +++- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 7d559544..7c759a62 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -335,6 +335,14 @@ send_control_channel_string_dowork(struct tls_multi *multi, return stat; } +void reschedule_multi_process(struct context *c) +{ + + interval_action(&c->c2.tmp_int); + context_immediate_reschedule(c); /* ZERO-TIMEOUT */ +} + + bool send_control_channel_string(struct context *c, const char *str, int msglevel) { @@ -342,15 +350,8 @@ send_control_channel_string(struct context *c, const char *str, int msglevel) { bool ret = send_control_channel_string_dowork(c->c2.tls_multi, str, msglevel); - /* - * Reschedule tls_multi_process. - * NOTE: in multi-client mode, usually the below two statements are - * insufficient to reschedule the client instance object unless - * multi_schedule_context_wakeup(m, mi) is also called. - */ + reschedule_multi_process(c); - interval_action(&c->c2.tmp_int); - context_immediate_reschedule(c); /* ZERO-TIMEOUT */ return ret; } return true; diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index a8b19f69..4336db5a 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -317,6 +317,15 @@ bool send_control_channel_string_dowork(struct tls_multi *multi, const char *str, int msglevel); + +/** + * Reschedule tls_multi_process. + * NOTE: in multi-client mode, usually the below two statements are + * insufficient to reschedule the client instance object unless + * multi_schedule_context_wakeup(m, mi) is also called. + */ +void reschedule_multi_process(struct context *c); + #define PIPV4_PASSTOS (1<<0) #define PIP_MSSFIX (1<<1) /* v4 and v6 */ #define PIP_OUTGOING (1<<2) diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 50e2e350..e2454753 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3903,7 +3903,9 @@ management_client_pending_auth(void *arg, if (mi) { /* sends INFO_PRE and AUTH_PENDING messages to client */ - bool ret = send_auth_pending_messages(&mi->context, extra, timeout); + bool ret = send_auth_pending_messages(mi->context.c2.tls_multi, extra, + timeout); + reschedule_multi_process(&mi->context); multi_schedule_context_wakeup(m, mi); return ret; } diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 59f8f33c..58e20baa 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -367,14 +367,13 @@ send_auth_failed(struct context *c, const char *client_reason) bool -send_auth_pending_messages(struct context *c, const char *extra, +send_auth_pending_messages(struct tls_multi *tls_multi, const char *extra, unsigned int timeout) { struct key_state *ks = &tls_multi->session[TM_ACTIVE].key[KS_PRIMARY]; static const char info_pre[] = "INFO_PRE,"; - struct tls_multi *tls_multi = c->c2.tls_multi; const char *const peer_info = tls_multi->peer_info; unsigned int proto = extract_iv_proto(peer_info); @@ -388,7 +387,7 @@ send_auth_pending_messages(struct context *c, const char *extra, struct gc_arena gc = gc_new(); if ((proto & IV_PROTO_AUTH_PENDING_KW) == 0) { - send_control_channel_string(c, "AUTH_PENDING", D_PUSH); + send_control_channel_string_dowork(tls_multi, "AUTH_PENDING", D_PUSH); } else { @@ -399,7 +398,7 @@ send_auth_pending_messages(struct context *c, const char *extra, struct buffer buf = alloc_buf_gc(len, &gc); buf_printf(&buf, auth_pre); buf_printf(&buf, "%u", timeout); - send_control_channel_string(c, BSTR(&buf), D_PUSH); + send_control_channel_string_dowork(tls_multi, BSTR(&buf), D_PUSH); } @@ -413,7 +412,7 @@ send_auth_pending_messages(struct context *c, const char *extra, struct buffer buf = alloc_buf_gc(len, &gc); buf_printf(&buf, info_pre); buf_printf(&buf, "%s", extra); - send_control_channel_string(c, BSTR(&buf), D_PUSH); + send_control_channel_string_dowork(tls_multi, BSTR(&buf), D_PUSH); ks->auth_deferred_expire = now + timeout; diff --git a/src/openvpn/push.h b/src/openvpn/push.h index a2192114..377f94a6 100644 --- a/src/openvpn/push.h +++ b/src/openvpn/push.h @@ -77,7 +77,9 @@ void send_auth_failed(struct context *c, const char *client_reason); * doc/management-notes.txt under client-pending-auth for * more details on message format */ -bool send_auth_pending_messages(struct context *c, const char *extra); +bool +send_auth_pending_messages(struct tls_multi *tls_multi, const char *extra, + unsigned int timeout); void send_restart(struct context *c, const char *kill_msg); From patchwork Wed Sep 30 03:13:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1490 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id 4H/5Mr6EdF8jDgAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:38 -0400 Received: from proxy19.mail.iad3b.rsapps.net ([172.31.255.6]) by director7.mail.ord1d.rsapps.net with LMTP id 6CfCMr6EdF8VFAAAovjBpQ (envelope-from ) for ; Wed, 30 Sep 2020 09:14:38 -0400 Received: from smtp27.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy19.mail.iad3b.rsapps.net with LMTPS id APDELL6EdF/vVgAAIG4riQ (envelope-from ) for ; Wed, 30 Sep 2020 09:14:38 -0400 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: smtp27.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: e4130220-031e-11eb-ab3e-5254006b1ac1-1-1 Received: from [216.105.38.7] ([216.105.38.7:57204] helo=lists.sourceforge.net) by smtp27.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 92/6D-24529-EB4847F5; Wed, 30 Sep 2020 09:14:38 -0400 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 1kNbvL-0005ee-6b; Wed, 30 Sep 2020 13:13:35 +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 1kNbvJ-0005eN-I7 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:33 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=wCASOwRGG+xlfxRVRXQdRIyd+zrI76fEbvkzCCuLYhk=; b=et5nZwoCocPYksIvOz9eoBAqht ovDzLPeOyj4RUT9DgL/29YOhgLPE/Yx6m7SLfefzZrvDZqfzWv6HIr/8viweRDnjQQvbuOqrrlKDQ 9cLsTYilosIOLMydcmRml+uzTV4UBqVmeKJXENlo34P75P+ZBzLCrkokIY0q+70QU17w=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=wCASOwRGG+xlfxRVRXQdRIyd+zrI76fEbvkzCCuLYhk=; b=CTri9bDsgFtVGfE6DM/KIIG6de tAUTqR4ewBhFJqiq7dgPJlcJ+Lam1TeGW5obkQ+vjVBP2UrI8kVvSlnxkV2Je9aVM78mdVXLcGJuC +I3JF/UVug0z7TC+bp89vdb1vSN/HS4ITqHgM74G88Q1oVbI0766KEzPZ92MjYL8HrC4=; 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 1kNbvF-00BNbA-RF for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:33 +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 1kNbv4-0003o3-Jd for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1370 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:12 +0200 Message-Id: <20200930131317.1299-8-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNbvF-00BNbA-RF Subject: [Openvpn-devel] [PATCH 06/11] Add S_EXITCODE flag for openvpn_run_script to report exit code 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 This allows to use script that have more than just fail/sucess but also deferred as status Signed-off-by: Arne Schwabe Acked-by: Lev Stipakov --- src/openvpn/platform.c | 35 +++++++++++++++++++++++++++++++++++ src/openvpn/platform.h | 5 ++++- src/openvpn/run_command.c | 25 ++++++++++++++++--------- src/openvpn/run_command.h | 14 ++++++++++---- 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/openvpn/platform.c b/src/openvpn/platform.c index 53d07f9c..5545a133 100644 --- a/src/openvpn/platform.c +++ b/src/openvpn/platform.c @@ -240,6 +240,41 @@ platform_system_ok(int stat) #endif } +#ifdef _WIN32 +int +platform_ret_code(int stat) +{ + + if (stat >= 0 && stat < 255) + { + return stat; + } + else + { + return -1; + } +} +#else +int +platform_ret_code(int stat) +{ + if (!WIFEXITED(stat) || stat == -1) + { + return -1; + } + + int status = WEXITSTATUS(stat); + if (status >= 0 && status < 255) + { + return status; + } + else + { + return -1; + } +} +#endif + int platform_access(const char *path, int mode) { diff --git a/src/openvpn/platform.h b/src/openvpn/platform.h index 091fc9c4..c7f6aae1 100644 --- a/src/openvpn/platform.h +++ b/src/openvpn/platform.h @@ -119,9 +119,12 @@ void platform_mlockall(bool print_msg); /* Disable paging */ int platform_chdir(const char *dir); -/* interpret the status code returned by execve() */ +/** interpret the status code returned by execve() */ bool platform_system_ok(int stat); +/** Return a return code if valid and between 0 and 255, -1 otherwise */ +int platform_ret_code(int stat); + int platform_access(const char *path, int mode); void platform_sleep_milliseconds(unsigned int n); diff --git a/src/openvpn/run_command.c b/src/openvpn/run_command.c index 4c4adf97..c1dd102c 100644 --- a/src/openvpn/run_command.c +++ b/src/openvpn/run_command.c @@ -191,27 +191,34 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in /* * Wrapper around openvpn_execve */ -bool +int openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message) { struct gc_arena gc = gc_new(); const int stat = openvpn_execve(a, es, flags); int ret = false; - if (platform_system_ok(stat)) + if(flags & S_EXITCODE) + { + ret = platform_ret_code(stat); + if (ret != -1) { + goto done; + } + } + else if (platform_system_ok(stat)) { ret = true; + goto done; } - else + if (error_message) { - if (error_message) - { - msg(((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s", - error_message, - system_error_message(stat, &gc)); - } + msg(((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s", + error_message, + system_error_message(stat, &gc)); } +done: gc_free(&gc); + return ret; } diff --git a/src/openvpn/run_command.h b/src/openvpn/run_command.h index 7ccb13c6..e322ebd1 100644 --- a/src/openvpn/run_command.h +++ b/src/openvpn/run_command.h @@ -42,18 +42,24 @@ int script_security(void); void script_security_set(int level); /* openvpn_execve flags */ -#define S_SCRIPT (1<<0) -#define S_FATAL (1<<1) +#define S_SCRIPT (1<<0) +#define S_FATAL (1<<1) +/** Instead of returning 1/0 for success/fail, + * return exit code when between 0 and 255 and -1 otherwise */ +#define S_EXITCODE (1<<2) /* wrapper around the execve() call */ int openvpn_popen(const struct argv *a, const struct env_set *es); bool openvpn_execve_allowed(const unsigned int flags); -bool openvpn_execve_check(const struct argv *a, const struct env_set *es, +int openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message); -static inline bool +/** + * Will run a script and return the exit code if it + */ +static inline int openvpn_run_script(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook) { From patchwork Wed Sep 30 03:13:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1488 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id UKo6ObuEdF+0BwAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:35 -0400 Received: from proxy14.mail.ord1d.rsapps.net ([172.30.191.6]) by director10.mail.ord1d.rsapps.net with LMTP id aMUgObuEdF8BHQAApN4f7A (envelope-from ) for ; Wed, 30 Sep 2020 09:14:35 -0400 Received: from smtp35.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy14.mail.ord1d.rsapps.net with LMTPS id kJnFOLuEdF8qIwAAtEH5vw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:35 -0400 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: smtp35.gate.ord1c.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: e2510644-031e-11eb-b8b9-5452002f485d-1-1 Received: from [216.105.38.7] ([216.105.38.7:55094] helo=lists.sourceforge.net) by smtp35.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 4B/DC-08663-BB4847F5; Wed, 30 Sep 2020 09:14:35 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNbvY-0003TY-DS; Wed, 30 Sep 2020 13:13:48 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNbvS-0003Sx-PP for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=52azGsfVYwRRwK19+qcWDx8svjekIu17hCDo2HJqq/M=; b=TJCOiy1iaRPx5K2x9wopltvO29 LBCiuZT05p+vCkCafRfSm+WgdZISxgKnTMoLGAf0OqhGMMsF3EAEUpSB+zd0Ykr7yRfXGfu9H7YBW J0aSLabA4onyy3J20jHG/umOqp77xYOw4IoioIfZoUr63gHUox1yKQToDupYET6Gb7Ik=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=52azGsfVYwRRwK19+qcWDx8svjekIu17hCDo2HJqq/M=; b=V/YPupKtWHU7nArrYk38baXqXo LJfNNPIzP0/sBacFVrvaAgS0NC7bNsSyTEZ1hZvGnZZH3dp599dYJI4CLAM0S8d5giuyT6IVGRSav XpKLC81kWtyvbxPy4Zt/bs7BSZtuHpOryuVUkgZt3MzG2nCmyfrmQMw9NVsI0L6+sK8I=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNbvL-00EONl-F3 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:42 +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 1kNbv4-0003o6-NP for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1373 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:13 +0200 Message-Id: <20200930131317.1299-9-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNbvL-00EONl-F3 Subject: [Openvpn-devel] [PATCH 07/11] Refactor extract_var_peer_info into standalone function and add ssl_util.c 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 Our "natural" place for this function would be ssl.c but ssl.c has a lot of dependencies on all kinds of other compilation units so including ssl.c into unit tests is near impossible currently. Instead create a new file ssl_util.c that holds small utility functions like this one. Signed-off-by: Arne Schwabe Acked-by: Lev Stipakov --- src/openvpn/Makefile.am | 1 + src/openvpn/openvpn.vcxproj | 2 + src/openvpn/openvpn.vcxproj.filters | 6 +++ src/openvpn/ssl.c | 2 +- src/openvpn/ssl_ncp.c | 20 ++-------- src/openvpn/ssl_util.c | 59 ++++++++++++++++++++++++++++ src/openvpn/ssl_util.h | 49 +++++++++++++++++++++++ src/openvpn/ssl_verify.c | 1 + tests/unit_tests/openvpn/Makefile.am | 3 +- 9 files changed, 125 insertions(+), 18 deletions(-) create mode 100644 src/openvpn/ssl_util.c create mode 100644 src/openvpn/ssl_util.h diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 37b002c6..ec84929b 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -119,6 +119,7 @@ openvpn_SOURCES = \ ssl_openssl.c ssl_openssl.h \ ssl_mbedtls.c ssl_mbedtls.h \ ssl_ncp.c ssl_ncp.h \ + ssl_util.c ssl_util.h \ ssl_common.h \ ssl_verify.c ssl_verify.h ssl_verify_backend.h \ ssl_verify_openssl.c ssl_verify_openssl.h \ diff --git a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj index 3863854b..cf31940c 100644 --- a/src/openvpn/openvpn.vcxproj +++ b/src/openvpn/openvpn.vcxproj @@ -212,6 +212,7 @@ + @@ -300,6 +301,7 @@ + diff --git a/src/openvpn/openvpn.vcxproj.filters b/src/openvpn/openvpn.vcxproj.filters index cf5748c7..e8aed2c5 100644 --- a/src/openvpn/openvpn.vcxproj.filters +++ b/src/openvpn/openvpn.vcxproj.filters @@ -243,6 +243,9 @@ Source Files + + Source Files + @@ -509,6 +512,9 @@ Header Files + + Header Files + diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index f0664a0f..a125afa2 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -4138,4 +4138,4 @@ delayed_auth_pass_purge(void) { auth_user_pass.wait_for_push = false; purge_user_pass(&auth_user_pass, false); -} +} \ No newline at end of file diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c index 55496395..f4d755af 100644 --- a/src/openvpn/ssl_ncp.c +++ b/src/openvpn/ssl_ncp.c @@ -48,6 +48,7 @@ #include "common.h" #include "ssl_ncp.h" +#include "ssl_util.h" #include "openvpn.h" /** @@ -181,23 +182,10 @@ const char * tls_peer_ncp_list(const char *peer_info, struct gc_arena *gc) { /* Check if the peer sends the IV_CIPHERS list */ - const char *ncp_ciphers_start; - if (peer_info && (ncp_ciphers_start = strstr(peer_info, "IV_CIPHERS="))) + const char *iv_ciphers = extract_var_peer_info(peer_info,"IV_CIPHERS=", gc); + if (iv_ciphers) { - ncp_ciphers_start += strlen("IV_CIPHERS="); - const char *ncp_ciphers_end = strstr(ncp_ciphers_start, "\n"); - if (!ncp_ciphers_end) - { - /* IV_CIPHERS is at end of the peer_info list and no '\n' - * follows */ - ncp_ciphers_end = ncp_ciphers_start + strlen(ncp_ciphers_start); - } - - char *ncp_ciphers_peer = string_alloc(ncp_ciphers_start, gc); - /* NULL terminate the copy at the right position */ - ncp_ciphers_peer[ncp_ciphers_end - ncp_ciphers_start] = '\0'; - return ncp_ciphers_peer; - + return iv_ciphers; } else if (tls_peer_info_ncp_ver(peer_info)>=2) { diff --git a/src/openvpn/ssl_util.c b/src/openvpn/ssl_util.c new file mode 100644 index 00000000..90ec97f7 --- /dev/null +++ b/src/openvpn/ssl_util.c @@ -0,0 +1,59 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2020 OpenVPN Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#include "ssl_util.h" + +char * +extract_var_peer_info(const char *peer_info, const char *var, + struct gc_arena *gc) +{ + const char *var_start; + + if (peer_info && (var_start = strstr(peer_info, var))) + { + var_start += strlen(var); + const char *var_end = strstr(var_start, "\n"); + if (!var_end) + { + /* var is at end of the peer_info list and no '\n' + * follows */ + var_end = var_start + strlen(var_start); + } + + char *ncp_ciphers_peer = string_alloc(var_start, gc); + /* NULL terminate the copy at the right position */ + ncp_ciphers_peer[var_end - var_start] = '\0'; + return ncp_ciphers_peer; + } + else + { + return NULL; + } +} \ No newline at end of file diff --git a/src/openvpn/ssl_util.h b/src/openvpn/ssl_util.h new file mode 100644 index 00000000..21bded6b --- /dev/null +++ b/src/openvpn/ssl_util.h @@ -0,0 +1,49 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2020 OpenVPN Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file SSL utility function. This file (and its .c file) is designed to + * to be included in units/etc without pulling in a lot of dependencies + */ + +#ifndef SSL_UTIL_H_ +#define SSL_UTIL_H_ + +#include "buffer.h" + +/** + * Extracts a variable from peer info, the returned string will be allocated + * using the supplied gc_arena + * + * @param peer_info The peer's peer_info + * @param var The variable *including* =, e.g. IV_CIPHERS= + * + * @return The content of the variable as NULL terminated string or NULL if the + * variable cannot be found. + */ +char * +extract_var_peer_info(const char *peer_info, + const char *var, + struct gc_arena *gc); + +#endif \ No newline at end of file diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 97ccb93b..e7e62afa 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -46,6 +46,7 @@ #endif #include "auth_token.h" #include "push.h" +#include "ssl_util.h" /** Maximum length of common name */ #define TLS_USERNAME_LEN 64 diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index f0880a6b..50f3a02e 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -125,4 +125,5 @@ ncp_testdriver_SOURCES = test_ncp.c mock_msg.c \ $(openvpn_srcdir)/crypto_openssl.c \ $(openvpn_srcdir)/otime.c \ $(openvpn_srcdir)/packet_id.c \ - $(openvpn_srcdir)/platform.c + $(openvpn_srcdir)/platform.c \ + $(openvpn_srcdir)/ssl_util.c From patchwork Wed Sep 30 03:13:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1486 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.28.255.1]) by backend30.mail.ord1d.rsapps.net with LMTP id oHQ9NbqEdF8ECQAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:34 -0400 Received: from proxy2.mail.ord1c.rsapps.net ([172.28.255.1]) by director10.mail.ord1d.rsapps.net with LMTP id WMgxNbqEdF+aHQAApN4f7A (envelope-from ) for ; Wed, 30 Sep 2020 09:14:34 -0400 Received: from smtp9.gate.ord1c ([172.28.255.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy2.mail.ord1c.rsapps.net with LMTPS id OMKoNLqEdF86VAAA311kuQ (envelope-from ) for ; Wed, 30 Sep 2020 09:14:34 -0400 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: smtp9.gate.ord1c.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: e104ec9c-031e-11eb-96ed-0026b95bddb7-1-1 Received: from [216.105.38.7] ([216.105.38.7:41576] helo=lists.sourceforge.net) by smtp9.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 8C/DF-16801-8B4847F5; Wed, 30 Sep 2020 09:14:33 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNbvR-0001Ch-LI; Wed, 30 Sep 2020 13:13:41 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNbvO-0001CA-Th for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=sGy22pARY24nEP5WMcp722xOOKFmZnejoKS0UUFaDhs=; b=T4Uvm8p2LQ6Bw8cD43iLTGZ5LB 0a6yUfDha33S46hvlcZxJ52HnePwkXvqdQd20fbFvIymexJ0ZSRL8c+ryTmvCIMyeQ4RAL0xGVSab 7BCkikmSPjdSL5Gm0Av2OrKoRzbWIIPOYvFafKDsyh2s6WL+60YvkzjhvHTEIs6GsGes=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=sGy22pARY24nEP5WMcp722xOOKFmZnejoKS0UUFaDhs=; b=RyC+qcvmfR9iYdYeRms5XHBOsO lWXplf5Vzb832h/7do5blwrMsE0yT4n6vXJiOd+yIf/uJO1ynLVprE7G5Vb1fdE31o9zIL2TDFH/d rbFcl5VGKBnlfRS129SQ9bZ3l9TENRfcXdGBmMOy/xN0OkB39orlzw1ebnCl7AusZP0E=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNbvL-00EONm-F5 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:38 +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 1kNbv4-0003o9-SL for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1376 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:14 +0200 Message-Id: <20200930131317.1299-10-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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.0 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: 1kNbvL-00EONm-F5 Subject: [Openvpn-devel] [PATCH 08/11] Allow pending auth to be send from a auth plugin 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 Signed-off-by: Arne Schwabe --- doc/man-sections/generic-options.rst | 3 +- include/openvpn-plugin.h.in | 8 ++ src/openvpn/ssl.c | 2 +- src/openvpn/ssl_common.h | 1 + src/openvpn/ssl_verify.c | 165 ++++++++++++++++++++++++--- src/openvpn/ssl_verify.h | 2 +- 6 files changed, 165 insertions(+), 16 deletions(-) diff --git a/doc/man-sections/generic-options.rst b/doc/man-sections/generic-options.rst index d5f08839..32eeda68 100644 --- a/doc/man-sections/generic-options.rst +++ b/doc/man-sections/generic-options.rst @@ -409,7 +409,8 @@ which mode OpenVPN is configured as. * :code:`OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY` plug-in hooks returns success/failure via :code:`auth_control_file` when using deferred auth - method + method and pending authentification via :code:`pending_auth_file`. + * :code:`OPENVPN_PLUGIN_ENABLE_PF` plugin hook to pass filtering rules via ``pf_file`` diff --git a/include/openvpn-plugin.h.in b/include/openvpn-plugin.h.in index 64b20886..bb561643 100644 --- a/include/openvpn-plugin.h.in +++ b/include/openvpn-plugin.h.in @@ -567,6 +567,14 @@ OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_op * auth_control_file/client_connect_deferred_file * in the environmental variable list (envp). * + * Additionally the auth_pending_file can be written, which causes the openvpn + * server to send a pending auth request to the client. See doc/management.txt + * for more details on this authentication mechanism. The format of the + * auth_pending_file is + * line 1: timeout in seconds + * line 2: Pending auth method the client needs to support (e.g. openurl) + * line 3: EXTRA (e.g. OPEN_URL:http://www.example.com) + * * In addition the OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER and * OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2 are called when OpenVPN tries to * get the deferred result. For a V2 call implementing this function is diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index a125afa2..815f896e 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -994,7 +994,7 @@ key_state_free(struct key_state *ks, bool clear) packet_id_free(&ks->crypto_options.packet_id); #ifdef PLUGIN_DEF_AUTH - key_state_rm_auth_control_file(ks); + key_state_rm_auth_control_files(ks); #endif if (clear) diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 7ccd1abb..98afc88c 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -216,6 +216,7 @@ struct key_state unsigned int auth_control_status; time_t acf_last_mod; char *auth_control_file; + char *auth_pending_file; #endif }; diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index e7e62afa..fc3a1116 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -843,13 +843,129 @@ man_def_auth_test(const struct key_state *ks) #endif /* ifdef MANAGEMENT_DEF_AUTH */ #ifdef PLUGIN_DEF_AUTH +/** + * Removes auth_pending file from the file system + * and key_state structure + */ +static void +key_state_rm_auth_pending_file(struct key_state *ks) +{ + if (ks && ks->auth_pending_file) + { + platform_unlink(ks->auth_pending_file); + free(ks->auth_pending_file); + ks->auth_pending_file = NULL; + } +} -/* - * auth_control_file functions +/** + * Check peer_info if the client supports the requested pending auth method */ +static bool +check_auth_pending_method(const char *peer_info, const char *method) +{ + struct gc_arena gc = gc_new(); + + char *iv_sso = extract_var_peer_info(peer_info, "IV_SSO=", &gc); + if (!iv_sso) + { + gc_free(&gc); + return false; + } + + const char *client_method = strtok(iv_sso, ","); + bool supported = false; + + while (client_method) + { + if (0 == strcmp(client_method, method)) + { + supported = true; + break; + } + client_method = strtok(NULL, ":"); + } + + gc_free(&gc); + return supported; +} + +/** + * Checks if the deferred state should also send auth pending + * request to the client. Also removes the auth_pending control file + * + * @returns true if file was either processed sucessfully or did not + * exist at all + * @returns false The file had an invlaid format or another error occured + */ +static bool +key_state_check_auth_pending_file(struct key_state *ks, + struct tls_multi *multi) +{ + bool ret = true; + if (ks && ks->auth_pending_file) + { + struct buffer_list *lines = buffer_list_file(ks->auth_pending_file, + 1024); + if (lines && lines->head) + { + /* Must have at least three lines. further lines are ignored for + * forward compatibility */ + if (!lines->head || !lines->head->next || !lines->head->next->next) + { + msg(M_WARN, "auth pending control file is not at least " + "three lines long."); + buffer_list_free(lines); + return false; + } + struct buffer *timeout_buf = &lines->head->buf; + struct buffer *iv_buf = &lines->head->next->buf; + struct buffer *extra_buf = &lines->head->next->next->buf; + + /* Remove newline chars at the end of the lines */ + buf_chomp(timeout_buf); + buf_chomp(iv_buf); + buf_chomp(extra_buf); + + long timeout = strtol(BSTR(timeout_buf), NULL, 10); + if (timeout == 0) + { + msg(M_WARN, "could not parse auth pending file timeout"); + buffer_list_free(lines); + return false; + } + + const char* pending_method = BSTR(iv_buf); + if (!check_auth_pending_method(multi->peer_info, pending_method)) + { + char buf[128]; + openvpn_snprintf(buf, sizeof(buf), + "Authentication failed, required pending auth " + "method '%s' not supported", pending_method); + auth_set_client_reason(multi, buf); + msg(M_INFO, "Client does not supported auth pending method " + "'%s'", pending_method); + ret = false; + } + else + { + send_auth_pending_messages(multi, BSTR(extra_buf), timeout); + } + } + + buffer_list_free(lines); + } + key_state_rm_auth_pending_file(ks); + return ret; +} + +/** + * Removes auth_pending and auth_control files from file system + * and key_state structure + */ void -key_state_rm_auth_control_file(struct key_state *ks) +key_state_rm_auth_control_files(struct key_state *ks) { if (ks && ks->auth_control_file) { @@ -857,23 +973,34 @@ key_state_rm_auth_control_file(struct key_state *ks) free(ks->auth_control_file); ks->auth_control_file = NULL; } + key_state_rm_auth_pending_file(ks); } +/** + * Generates and creates the control files used for deferred authentification + * in the temporary directory. + * + * @return true if file creation was successful + */ static bool -key_state_gen_auth_control_file(struct key_state *ks, const struct tls_options *opt) +key_state_gen_auth_control_files(struct key_state *ks, const struct tls_options *opt) { struct gc_arena gc = gc_new(); - key_state_rm_auth_control_file(ks); + key_state_rm_auth_control_files(ks); const char *acf = platform_create_temp_file(opt->tmp_dir, "acf", &gc); - if (acf) + const char *apf = platform_create_temp_file(opt->tmp_dir, "apf", &gc); + + if (acf && apf) { ks->auth_control_file = string_alloc(acf, NULL); + ks->auth_pending_file = string_alloc(apf, NULL); setenv_str(opt->es, "auth_control_file", ks->auth_control_file); + setenv_str(opt->es, "auth_pending_file", ks->auth_pending_file); } gc_free(&gc); - return acf; + return (acf && apf); } static unsigned int @@ -905,6 +1032,8 @@ key_state_test_auth_control_file(struct key_state *ks) return ACF_DISABLED; } + + #endif /* ifdef PLUGIN_DEF_AUTH */ /* @@ -1067,7 +1196,7 @@ verify_user_pass_script(struct tls_session *session, struct tls_multi *multi, struct gc_arena gc = gc_new(); struct argv argv = argv_new(); const char *tmp_file = ""; - bool ret = false; + bool ret = OPENVPN_PLUGIN_FUNC_ERROR; /* Is username defined? */ if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen(up->username)) @@ -1172,7 +1301,7 @@ verify_user_pass_plugin(struct tls_session *session, struct tls_multi *multi, add_session_token_env(session, multi, up); #ifdef PLUGIN_DEF_AUTH /* generate filename for deferred auth control file */ - if (!key_state_gen_auth_control_file(ks, session->opt)) + if (!key_state_gen_auth_control_files(ks, session->opt)) { msg(D_TLS_ERRORS, "TLS Auth Error (%s): " "could not create deferred auth control file", __func__); @@ -1184,10 +1313,20 @@ verify_user_pass_plugin(struct tls_session *session, struct tls_multi *multi, retval = plugin_call(session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, NULL, NULL, session->opt->es); #ifdef PLUGIN_DEF_AUTH - /* purge auth control filename (and file itself) for non-deferred returns */ - if (retval != OPENVPN_PLUGIN_FUNC_DEFERRED) + if (retval == OPENVPN_PLUGIN_FUNC_DEFERRED) + { + /* Check if we the plugin has written the pending auth control + * file and send the pending auth to the client */ + if(!key_state_check_auth_pending_file(ks, multi)) + { + retval = OPENVPN_PLUGIN_FUNC_ERROR; + key_state_rm_auth_control_files(ks); + } + } + else { - key_state_rm_auth_control_file(ks); + /* purge auth control filename (and file itself) for non-deferred returns */ + key_state_rm_auth_control_files(ks); } #endif @@ -1256,7 +1395,7 @@ verify_user_pass_management(struct tls_session *session, #endif /* ifdef MANAGEMENT_DEF_AUTH */ -/* +/** * Main username/password verification entry point * * Will set session->ks[KS_PRIMARY].authenticated according to diff --git a/src/openvpn/ssl_verify.h b/src/openvpn/ssl_verify.h index b1ced956..5b413c57 100644 --- a/src/openvpn/ssl_verify.h +++ b/src/openvpn/ssl_verify.h @@ -93,7 +93,7 @@ int tls_authentication_status(struct tls_multi *multi, const int latency); * * @param ks The key state the remove the file for */ -void key_state_rm_auth_control_file(struct key_state *ks); +void key_state_rm_auth_control_files(struct key_state *ks); /** * Frees the given set of certificate hashes. From patchwork Wed Sep 30 03:13:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1492 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wKDfFL+EdF8ECQAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:39 -0400 Received: from proxy19.mail.ord1d.rsapps.net ([172.30.191.6]) by director12.mail.ord1d.rsapps.net with LMTP id sBCyFL+EdF/2EAAAIasKDg (envelope-from ) for ; Wed, 30 Sep 2020 09:14:39 -0400 Received: from smtp18.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy19.mail.ord1d.rsapps.net with LMTPS id qKN3FL+EdF93RQAAyH2SIw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:39 -0400 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: smtp18.gate.ord1c.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: e3fa9082-031e-11eb-9375-bc305bf00c68-1-1 Received: from [216.105.38.7] ([216.105.38.7:55128] helo=lists.sourceforge.net) by smtp18.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 52/2B-22577-DB4847F5; Wed, 30 Sep 2020 09:14:38 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNbvY-0003TO-Ar; Wed, 30 Sep 2020 13:13:48 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNbvO-0003Sd-TI for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=cO/1R7pmywiXFUbZJrE7qUobmeAA30xvDPdNhfsN/JU=; b=hkR2pokb1v+cTDwEejT8e8EN7d RK8OLVd2ZFCoBPk7P647j6QkSexgWR4vzyVs5oqHlKBSf3KxeVSzhMIKYus0zjISvZugDTFjwjlc9 gLFmba+zSf3ipwVD2mYoSBqVWH/xipC8r56JeUnbVdfNC0NIrHAyviDj/KhKKe5bQNBM=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=cO/1R7pmywiXFUbZJrE7qUobmeAA30xvDPdNhfsN/JU=; b=nRtxo8HzOzPTOAyPIHHTI3nXUu frGY0E1/kY0Y+gEvQz4t1SWd6CPgzb7yvCwYYHqQ5bVS5hCcsNY8fwhMNdl48jDQWKOKL6RDFMJdD gZO76Wk0fO8uiVlOnbsju7WcDS/atLdgl8MmkKcf1zxNruBo1cBqOH34JJhpI/P4Sfg8=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNbvL-00EOO9-Fu for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:38 +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 1kNbv4-0003oC-Up for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:18 +0200 Received: (nullmailer pid 1379 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:15 +0200 Message-Id: <20200930131317.1299-11-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 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 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] X-Headers-End: 1kNbvL-00EOO9-Fu Subject: [Openvpn-devel] [PATCH 09/11] Implement deferred auth for scripts 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 Signed-off-by: Arne Schwabe --- Changes.rst | 9 +++++ doc/man-sections/script-options.rst | 14 +++++++- src/openvpn/ssl_verify.c | 56 ++++++++++++++++++++++++----- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/Changes.rst b/Changes.rst index f67e1d76..7e60eb64 100644 --- a/Changes.rst +++ b/Changes.rst @@ -1,3 +1,12 @@ +Overview of changes in 2.6 +========================== + + +New features +------------ +Deferred auth support for scripts + The ``--auth-user-pass-verify`` script supports now deferred authentication. + Overview of changes in 2.5 ========================== diff --git a/doc/man-sections/script-options.rst b/doc/man-sections/script-options.rst index a4df6732..e0cc10c2 100644 --- a/doc/man-sections/script-options.rst +++ b/doc/man-sections/script-options.rst @@ -90,7 +90,19 @@ SCRIPT HOOKS The script should examine the username and password, returning a success exit code (:code:`0`) if the client's authentication request is to be - accepted, or a failure code (:code:`1`) to reject the client. + accepted, a failure code (:code:`1`) to reject the client, or a that + the authentication is deferred (:code:`2`). If the authentication is + deferred, the script must fork/start a background or another non-blocking + operation to continue the authentication in the background. When finshing + the authentication, a :code:`1` or :code:`0` must be written to the + file specified by the :code:`auth_control_file`. + + When deferred authentication is in use, the script can also request + pending authentication by writing to the file specified by the + :code:`auth_pending_file`. The first line must be the timeout in + seconds and the second line the EXTRA as documented in the + ``client-pending-auth`` section of `doc/management.txt`. + This directive is designed to enable a plugin-style interface for extending OpenVPN's authentication capabilities. diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index fc3a1116..5e15fa32 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -1189,14 +1189,14 @@ tls_authenticate_key(struct tls_multi *multi, const unsigned int mda_key_id, con /* * Verify the user name and password using a script */ -static bool +static int verify_user_pass_script(struct tls_session *session, struct tls_multi *multi, const struct user_pass *up) { struct gc_arena gc = gc_new(); struct argv argv = argv_new(); const char *tmp_file = ""; - bool ret = OPENVPN_PLUGIN_FUNC_ERROR; + int retval = OPENVPN_PLUGIN_FUNC_ERROR; /* Is username defined? */ if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen(up->username)) @@ -1247,10 +1247,45 @@ verify_user_pass_script(struct tls_session *session, struct tls_multi *multi, argv_parse_cmd(&argv, session->opt->auth_user_pass_verify_script); argv_printf_cat(&argv, "%s", tmp_file); + /* Add files needed for deferred auth */ + key_state_gen_auth_control_files(&session->key[KS_PRIMARY], + session->opt); + /* call command */ - ret = openvpn_run_script(&argv, session->opt->es, 0, - "--auth-user-pass-verify"); + int script_ret = openvpn_run_script(&argv, session->opt->es, S_EXITCODE, + "--auth-user-pass-verify"); + + switch (script_ret) + { + case 0: + retval = OPENVPN_PLUGIN_FUNC_SUCCESS; + break; + case 2: + retval = OPENVPN_PLUGIN_FUNC_DEFERRED; + break; + default: + retval = OPENVPN_PLUGIN_FUNC_ERROR; + break; + } +#ifdef ENABLE_DEF_AUTH + if (retval == OPENVPN_PLUGIN_FUNC_DEFERRED) + { + /* Check if we the plugin has written the pending auth control + * file and send the pending auth to the client */ + if(!key_state_check_auth_pending_file(&session->key[KS_PRIMARY], + multi)) + { + retval = OPENVPN_PLUGIN_FUNC_ERROR; + key_state_rm_auth_control_files(&session->key[KS_PRIMARY]); + } + } + else + { + /* purge auth control filename (and file itself) for non-deferred returns */ + key_state_rm_auth_control_files(&session->key[KS_PRIMARY]); + } +#endif if (!session->opt->auth_user_pass_verify_script_via_file) { setenv_del(session->opt->es, "password"); @@ -1269,7 +1304,7 @@ done: argv_free(&argv); gc_free(&gc); - return ret; + return retval; } /* @@ -1406,7 +1441,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi, struct tls_session *session) { int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS; - bool s2 = true; + int s2 = OPENVPN_PLUGIN_FUNC_SUCCESS; struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ #ifdef MANAGEMENT_DEF_AUTH @@ -1499,7 +1534,11 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi, #ifdef PLUGIN_DEF_AUTH || s1 == OPENVPN_PLUGIN_FUNC_DEFERRED #endif - ) && s2 + ) && + ((s2 == OPENVPN_PLUGIN_FUNC_SUCCESS) +#ifdef ENABLE_DEF_AUTH + || s2 == OPENVPN_PLUGIN_FUNC_DEFERRED) +#endif #ifdef MANAGEMENT_DEF_AUTH && man_def_auth != KMDA_ERROR #endif @@ -1507,7 +1546,8 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi, { ks->authenticated = KS_AUTH_TRUE; #ifdef PLUGIN_DEF_AUTH - if (s1 == OPENVPN_PLUGIN_FUNC_DEFERRED) + if (s1 == OPENVPN_PLUGIN_FUNC_DEFERRED + || s2 == OPENVPN_PLUGIN_FUNC_DEFERRED) { ks->authenticated = KS_AUTH_DEFERRED; } From patchwork Wed Sep 30 03:13:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1496 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id IBBuIMWEdF8ECQAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:45 -0400 Received: from proxy12.mail.ord1d.rsapps.net ([172.30.191.6]) by director7.mail.ord1d.rsapps.net with LMTP id AE1CIMWEdF+/FAAAovjBpQ (envelope-from ) for ; Wed, 30 Sep 2020 09:14:45 -0400 Received: from smtp28.gate.ord1c ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy12.mail.ord1d.rsapps.net with LMTPS id +GgGIMWEdF80QQAA7PHxkg (envelope-from ) for ; Wed, 30 Sep 2020 09:14:45 -0400 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: smtp28.gate.ord1c.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: e81b28a2-031e-11eb-bfa0-a0369f1890f1-1-1 Received: from [216.105.38.7] ([216.105.38.7:55218] helo=lists.sourceforge.net) by smtp28.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 33/37-11952-4C4847F5; Wed, 30 Sep 2020 09:14:44 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kNbva-0003Ub-N4; Wed, 30 Sep 2020 13:13:50 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kNbvZ-0003U2-5V for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:49 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=XV3+8wlYWe7SRZRGWD+EUZSHw3FfF7q2XvT8sLWXiNI=; b=krImWUnebah+aBFazASK7py2kJ KkdE58kOiVpIuaOCRwfws6Kr+vsr1enrH1e+TpXTyG5iooXbUwvNgnIN+8EqxkrxdMK7YnPpdpA+d 1EsWOZKZDflhb/Ij02HgPqQj+gghbVBXfgZwvtR1v8X2MfA0Z1p8+S6JNfcoGWRbtYcE=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=XV3+8wlYWe7SRZRGWD+EUZSHw3FfF7q2XvT8sLWXiNI=; b=JwmzwIJMDsduTrUhmDmJokKBQK P5YR17/in5KQq9SW37yPIPEhA0HvikAHTScSiPKb699FpKeO1ZzoYDRh47XFqhc/59Rf9RBwD3ci0 SOcV5alcE2LCun/N5hJCGAsnWlRWedoqNToL8op09xjpi9SrqcMJQBmIkM0an2NstI18=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kNbvL-00EONn-Ed for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:48 +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 1kNbv5-0003oF-19 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:19 +0200 Received: (nullmailer pid 1382 invoked by uid 10006); Wed, 30 Sep 2020 13:13:18 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:16 +0200 Message-Id: <20200930131317.1299-12-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNbvL-00EONn-Ed Subject: [Openvpn-devel] [PATCH 10/11] Implement --client-crresponse script options and plugin interface 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 This is allows scripts and pluginsto parse/react to a CR_RESPONSE message Signed-off-by: Arne Schwabe --- Changes.rst | 7 ++++ doc/man-sections/script-options.rst | 28 ++++++++++++- include/openvpn-plugin.h.in | 7 +++- src/openvpn/init.c | 1 + src/openvpn/options.c | 15 +++++++ src/openvpn/options.h | 1 + src/openvpn/push.c | 4 ++ src/openvpn/ssl_common.h | 1 + src/openvpn/ssl_verify.c | 63 +++++++++++++++++++++++++++++ src/openvpn/ssl_verify.h | 23 +++++++++++ 10 files changed, 147 insertions(+), 3 deletions(-) diff --git a/Changes.rst b/Changes.rst index 7e60eb64..0717c349 100644 --- a/Changes.rst +++ b/Changes.rst @@ -7,6 +7,13 @@ New features Deferred auth support for scripts The ``--auth-user-pass-verify`` script supports now deferred authentication. +Pending auth support for plugins and scripts + Both auth plugin and script can now signal pending authentication to + the client when using deferred authentication. The new ``client-crresponse`` + script option and ``OPENVPN_PLUGIN_CLIENT_CRRESPONSE`` plugin function can + be used to parse a client response to a ``CR_TEXT`` two factor challenge. + + Overview of changes in 2.5 ========================== diff --git a/doc/man-sections/script-options.rst b/doc/man-sections/script-options.rst index e0cc10c2..66bf3662 100644 --- a/doc/man-sections/script-options.rst +++ b/doc/man-sections/script-options.rst @@ -52,6 +52,11 @@ Script Order of Execution Executed in ``--mode server`` mode on new client connections, when the client is still untrusted. +#. ``--client-crresponse`` + + Execute in ``--mode server`` whenever a client sends a + :code:`CR_RESPONSE` message + SCRIPT HOOKS ------------ @@ -72,7 +77,7 @@ SCRIPT HOOKS double-quoted and/or escaped using a backslash, and should be separated by one or more spaces. - If ``method`` is set to :code:`via-env`, OpenVPN will call ``script`` + If ``method`` is set to :code:`via-env`, OpenVPN will call ``cmd`` with the environmental variables :code:`username` and :code:`password` set to the username/password strings provided by the client. *Beware* that this method is insecure on some platforms which make the environment @@ -80,7 +85,7 @@ SCRIPT HOOKS If ``method`` is set to :code:`via-file`, OpenVPN will write the username and password to the first two lines of a temporary file. The filename - will be passed as an argument to ``script``, and the file will be + will be passed as an argument to ``cmd``, and the file will be automatically deleted by OpenVPN after the script returns. The location of the temporary file is controlled by the ``--tmp-dir`` option, and will default to the current directory if unspecified. For security, @@ -123,6 +128,25 @@ SCRIPT HOOKS For a sample script that performs PAM authentication, see :code:`sample-scripts/auth-pam.pl` in the OpenVPN source distribution. +--client-crresponse + Executed when the client sends a text based challenge response. + + Valid syntax: + :: + + client-crresponse cmd method + + OpenVPN will write the response of the client into a temporary file. + The filename will be passed as an argument to ``cmd``, and the file will be + automatically deleted by OpenVPN after the script returns. + + The response is passed as is from the client. The script needs to check + itself if the input is valid, e.g. if the input is valid base64 encoding. + + The script can either directly write the result of the verification to + :code:`auth_control_file or further defer it. See ``--auth-user-pass-verify`` + for details. + --client-connect cmd Run command ``cmd`` on client connection. diff --git a/include/openvpn-plugin.h.in b/include/openvpn-plugin.h.in index bb561643..62e3c3b7 100644 --- a/include/openvpn-plugin.h.in +++ b/include/openvpn-plugin.h.in @@ -84,6 +84,10 @@ extern "C" { * FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_CLIENT_CONNECT_V2 * FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_LEARN_ADDRESS * + * The OPENVPN_PLUGIN_CLIENT_CRRESPONSE function is called when the client sends + * the CR_RESPONSE message, this is *typically* after OPENVPN_PLUGIN_TLS_FINAL + * but may also occur much later. + * * [Client session ensues] * * For each "TLS soft reset", according to reneg-sec option (or similar): @@ -131,7 +135,8 @@ extern "C" { #define OPENVPN_PLUGIN_ROUTE_PREDOWN 12 #define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER 13 #define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2 14 -#define OPENVPN_PLUGIN_N 15 +#define OPENVPN_PLUGIN_CLIENT_CRRESPONSE 15 +#define OPENVPN_PLUGIN_N 16 /* * Build a mask out of a set of plug-in types. diff --git a/src/openvpn/init.c b/src/openvpn/init.c index d1ad5c8f..6597b66a 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2940,6 +2940,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) to.auth_user_pass_verify_script = options->auth_user_pass_verify_script; to.auth_user_pass_verify_script_via_file = options->auth_user_pass_verify_script_via_file; + to.client_crresponse_script = options->client_crresponse_script; to.tmp_dir = options->tmp_dir; if (options->ccd_exclusive) { diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 3df803db..703927da 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -1286,6 +1286,7 @@ show_p2mp_parms(const struct options *o) SHOW_STR(client_connect_script); SHOW_STR(learn_address_script); SHOW_STR(client_disconnect_script); + SHOW_STR(client_crresponse_script); SHOW_STR(client_config_dir); SHOW_BOOL(ccd_exclusive); SHOW_STR(tmp_dir); @@ -2427,6 +2428,10 @@ options_postprocess_verify_ce(const struct options *options, const struct connec { msg(M_USAGE, "--client-connect requires --mode server"); } + if (options->client_crresponse_script) + { + msg(M_USAGE, "--client-crresponse requires --mode server"); + } if (options->client_disconnect_script) { msg(M_USAGE, "--client-disconnect requires --mode server"); @@ -7070,6 +7075,16 @@ add_option(struct options *options, set_user_script(options, &options->client_connect_script, p[1], "client-connect", true); } + else if (streq(p[0], "client-crresponse") && p[1]) + { + VERIFY_PERMISSION(OPT_P_SCRIPT); + if (!no_more_than_n_args(msglevel, p, 2, NM_QUOTE_HINT)) + { + goto err; + } + set_user_script(options, &options->client_crresponse_script, + p[1], "client-crresponse", true); + } else if (streq(p[0], "client-disconnect") && p[1]) { VERIFY_PERMISSION(OPT_P_SCRIPT); diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 877e9396..a63a1967 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -440,6 +440,7 @@ struct options const char *client_connect_script; const char *client_disconnect_script; const char *learn_address_script; + const char *client_crresponse_script; const char *client_config_dir; bool ccd_exclusive; bool disable; diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 58e20baa..e5c92e17 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -227,6 +227,10 @@ receive_cr_response(struct context *c, const struct buffer *buffer) management_notify_client_cr_response(key_id, mda, es, m); +#endif +#if ENABLE_PLUGIN + verify_crresponse_plugin(c->c2.tls_multi, m); + verify_crresponse_script(c->c2.tls_multi, m); #endif msg(D_PUSH, "CR response was sent by client ('%s')", m); } diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 98afc88c..87877c88 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -314,6 +314,7 @@ struct tls_options /* used for username/password authentication */ const char *auth_user_pass_verify_script; + const char *client_crresponse_script; bool auth_user_pass_verify_script_via_file; const char *tmp_dir; const char *auth_user_pass_file; diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 5e15fa32..7c71abfb 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -1307,6 +1307,69 @@ done: return retval; } +void +verify_crresponse_plugin(struct tls_multi *multi, const char *cr_response) +{ + struct tls_session *session = &multi->session[TM_ACTIVE]; + setenv_str(session->opt->es, "crresponse", cr_response); + + plugin_call(session->opt->plugins, OPENVPN_PLUGIN_CLIENT_CRRESPONSE, NULL, + NULL, session->opt->es); + + setenv_del(session->opt->es, "crresponse"); + +} +void +verify_crresponse_script(struct tls_multi *multi, const char *cr_response) +{ + + struct tls_session *session = &multi->session[TM_ACTIVE]; + + if (!session->opt->client_crresponse_script) + { + return; + } + struct argv argv = argv_new(); + struct gc_arena gc = gc_new(); + + setenv_str(session->opt->es, "script_type", "client-crresponse"); + + /* Since cr response might be sensitive, like a stupid way to query + * a password via 2FA, we pass it via file instead environment */ + const char *tmp_file = platform_create_temp_file(session->opt->tmp_dir, "cr", &gc); + if (tmp_file) + { + struct status_output *so = status_open(tmp_file, 0, -1, NULL, + STATUS_OUTPUT_WRITE); + status_printf(so, "%s", cr_response); + if (!status_close(so)) + { + msg(D_TLS_ERRORS, "TLS CR Response Error: could not write cr" + "responsed to file: %s", + tmp_file); + tls_deauthenticate(multi); + goto done; + } + } + else + { + msg(D_TLS_ERRORS, "TLS Auth Error: could not create write " + "username/password to temp file"); + } + + argv_parse_cmd(&argv, session->opt->client_crresponse_script); + argv_printf_cat(&argv, "%s", tmp_file); + + + if (!openvpn_run_script(&argv, session->opt->es, 0, "--client-crresponse")) + { + tls_deauthenticate(multi); + } +done: + argv_free(&argv); + gc_free(&gc); +} + /* * Verify the username and password using a plugin */ diff --git a/src/openvpn/ssl_verify.h b/src/openvpn/ssl_verify.h index 5b413c57..f355053a 100644 --- a/src/openvpn/ssl_verify.h +++ b/src/openvpn/ssl_verify.h @@ -185,6 +185,29 @@ tls_common_name_hash(const struct tls_multi *multi, const char **cn, uint32_t *c void verify_user_pass(struct user_pass *up, struct tls_multi *multi, struct tls_session *session); + + +/** + * Runs the --client-crresponse script if one is defined. + * + * As with the management interface the script is stateless in the sense that + * it does not directly participate in the authentication but rather should set + * the files for the deferred auth like the management commands. + * + */ +void +verify_crresponse_script(struct tls_multi *multi, const char *cr_response); + +/** + * Call the plugin OPENVPN_PLUGIN_CLIENT_CRRESPONSE. + * + * As with the management interface calling the plugin is stateless in the sense + * that it does not directly participate in the authentication but rather + * should set the files for the deferred auth like the management commands. + */ +void +verify_crresponse_plugin(struct tls_multi *multi, const char *cr_response); + /** * Perform final authentication checks, including locking of the cn, the allowed * certificate hashes, and whether a client config entry exists in the From patchwork Wed Sep 30 03:13: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: 1487 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wIBONLqEdF94QQAAIUCqbw (envelope-from ) for ; Wed, 30 Sep 2020 09:14:34 -0400 Received: from proxy13.mail.iad3b.rsapps.net ([172.31.255.6]) by director12.mail.ord1d.rsapps.net with LMTP id yBRENLqEdF+JEAAAIasKDg (envelope-from ) for ; Wed, 30 Sep 2020 09:14:34 -0400 Received: from smtp10.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy13.mail.iad3b.rsapps.net with LMTPS id AFrdLLqEdF9kGwAAvUvv+w (envelope-from ) for ; Wed, 30 Sep 2020 09:14:34 -0400 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: smtp10.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: e17d0240-031e-11eb-b778-52540055034d-1-1 Received: from [216.105.38.7] ([216.105.38.7:57062] helo=lists.sourceforge.net) by smtp10.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 06/C4-00711-9B4847F5; Wed, 30 Sep 2020 09:14:34 -0400 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 1kNbvT-0005gG-B6; Wed, 30 Sep 2020 13:13:43 +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 1kNbvM-0005ex-Lf for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:36 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=BgEER5d/Q0rTvs0Yp1pWNq3IxfXuyk/I4VoMXfdpPng=; b=mTQX5TuIPbaDU8LuQATwpDrHDW mZEs6AkFhgAI9fHozyB7eYrbMRqhzaHU3sYyXwpYnch1EpQrr8vLJWAUlZL2bdkP3Hrs2hw2zbnSK X2cU/pewsDG4Z7OLxYZWyseJCisONYFRSKKfuxCyuX2Dv650SQQzlxm74mR0FR5OoNbs=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=BgEER5d/Q0rTvs0Yp1pWNq3IxfXuyk/I4VoMXfdpPng=; b=c3n8aodeDTCqWpD8GiTL/YpJkQ bc+Tn79lH2C4CCHEFOcKiGBvxNG/didxGoWsOuWAWMzKDwCDK3RQoahBIiy2ykpcINUWFpSn0XyHd VoAAb5w1ZnbNh23QNg/OHREbKlyp8pYiVggALx+sLWuu6cG6sjcurNRkoqiraldkbaU0=; 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 1kNbvF-00BNbD-R2 for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 13:13:36 +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 1kNbv5-0003oI-3g for openvpn-devel@lists.sourceforge.net; Wed, 30 Sep 2020 15:13:19 +0200 Received: (nullmailer pid 1385 invoked by uid 10006); Wed, 30 Sep 2020 13:13:19 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Sep 2020 15:13:17 +0200 Message-Id: <20200930131317.1299-13-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200930131317.1299-1-arne@rfc2549.org> References: <20200930131317.1299-1-arne@rfc2549.org> 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: 1kNbvF-00BNbD-R2 Subject: [Openvpn-devel] [PATCH 11/11] Add example script demonstrating TOTP via auth-pending 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 Signed-off-by: Arne Schwabe --- Changes.rst | 2 + doc/man-sections/script-options.rst | 3 + sample/sample-scripts/totpauth.py | 107 ++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100755 sample/sample-scripts/totpauth.py diff --git a/Changes.rst b/Changes.rst index 0717c349..7b7d1491 100644 --- a/Changes.rst +++ b/Changes.rst @@ -13,6 +13,8 @@ Pending auth support for plugins and scripts script option and ``OPENVPN_PLUGIN_CLIENT_CRRESPONSE`` plugin function can be used to parse a client response to a ``CR_TEXT`` two factor challenge. + See ``sample/sample-scripts/totpauth.py`` for an example. + Overview of changes in 2.5 ========================== diff --git a/doc/man-sections/script-options.rst b/doc/man-sections/script-options.rst index 66bf3662..fff3d166 100644 --- a/doc/man-sections/script-options.rst +++ b/doc/man-sections/script-options.rst @@ -147,6 +147,9 @@ SCRIPT HOOKS :code:`auth_control_file or further defer it. See ``--auth-user-pass-verify`` for details. + For a sample script that implement TOTP (RFC 6238) based two-factor + authentication, see :code:`sample-scripts/totp.py`. + --client-connect cmd Run command ``cmd`` on client connection. diff --git a/sample/sample-scripts/totpauth.py b/sample/sample-scripts/totpauth.py new file mode 100755 index 00000000..95ac3529 --- /dev/null +++ b/sample/sample-scripts/totpauth.py @@ -0,0 +1,107 @@ +#! /usr/bin/python3 +# Copyright (c) 2020 OpenVPN Inc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import os +from base64 import standard_b64decode + +import pyotp + +import pprint + +# Example script demonstrating how to use the auth-pending API in +# OpenVPN. This script is provided under MIT license to allow easy +# modification for other purposes. +# +# To use this script add the following lines in the openvpn config + +# client-crresponse /path/to/totpauth.py +# auth-user-pass-verify /path/to/totpauth.py via-file +# auth-user-pass-optional +# auth-gen-token + +# Note that this script does NOT verify username/password +# It is only meant for querying additional 2FA when certificates are +# used to authenticate + +secrets = {"styx": "OS6JDNRK2BNUPQVX", + "apate": "IXWEMP7SK2QWSHTG"} + + +def main(): + # Get common name and script type from environment + script_type = os.environ['script_type'] + cn = os.environ['common_name'] + + if script_type == 'user-pass-verify': + # signal text based challenge response + + if cn in secrets: + extra = "CR_TEXT:E,R:Please enter your TOTP code!" + write_auth_pending(300, 'crtext', extra) + + # Signal authentication being deferred + sys.exit(2) + else: + # For unkown CN we report failure. Change to 0 + # to allow CNs without secret to auth without 2FA + sys.exit(1) + + elif script_type == 'client-crresponse': + response = None + + # Read the crresponse from the argument file + # and convert it into text. A failure because of bad user + # input (e.g. invalid base64) will make the script throw + # an error and make OpenVPN return AUTH_FAILED + with open(sys.argv[1], 'r') as crinput: + response = crinput.read() + response = standard_b64decode(response) + response = response.decode().strip() + + if cn not in secrets: + write_auth_control(1) + return + + totp = pyotp.TOTP(secrets[cn]) + + # Check if the code is valid (and also allow code +/-1) + if totp.verify(response, valid_window=1): + write_auth_control(1) + else: + write_auth_control(0) + else: + print(f"Unknown script type {script_type}") + sys.exit(1) + + +def write_auth_control(status): + with open(os.environ['auth_control_file'], 'w') as auth_control: + auth_control.write("%d" % status) + + +def write_auth_pending(timeout, method, extra): + with open(os.environ['auth_pending_file'], 'w') as auth_pending: + auth_pending.write("%d\n%s\n%s" % (timeout, method, extra)) + + +if __name__ == '__main__': + main()