Connect OpenConnect to the TLS socket, and watch it negotiate LCP/IPCP/IP6CP with its peer, and reject CCP:
# Add noipv4,noipv6 to cookie to try those
./openconnect --protocol=nullppp --cookie hdlc --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --dump localhost:5556
David Woodhouse [Wed, 6 May 2020 21:10:42 +0000 (22:10 +0100)]
add support for PPP-based protocols
This started out as the 'f5' branch, which was then rebased (by DL) onto a
more recent master as 'ppp_rebased'.
This was then squashed down into a single commit, with all of the bits
depending on "real" PPP-based VPN protocols removed, so that only the shell
of generic PPP support remains, including PPP protocol negotation (LCP,
IPCP, IP6CP) and mainloop.
Almost all of this code was done by David Woodhouse and Daniel Lenski in
May 2020, with a few more recent bugfixes by DL in early February 2021.
The remaining shell supports two different encapsulations of PPP:
- PPP_ENCAP_RFC1661: Plain PPP. “Synchronous” in the ’90s-era language,
because the start and end of the frame are known from external means.
In modern instances, this is because they arrive in a complete packet with
a known length from its lower-level encapsulation. (TLS or DTLS records in
our expected use cases.)
This is what `pppd sync` does.
- PPP_ENCAP_RFC1662: “PPP in HDLC-like framing.”
This is what `pppd` without `sync` does.
The following commits will add tests to demonstrate the functionality of
OpenConnect's PPP implementation at the level of this generic encapsulation.
Daniel Lenski [Mon, 8 Feb 2021 19:38:19 +0000 (11:38 -0800)]
factor out internal_split_cookies from auth-juniper.c
This is useful for other protocols that use HTTP cookies for authentication, and may
need a way to handoff >1 cookie from the authentication phase to the connection phase.
Improve it slightly by allowing it to set a "default" HTTP cookie if the
authcookie string doesn't contain '=', since most protocols really only NEED
one cookie for the connection phase to work.
This allows shortcuts (like `openconnect --protocol=nc -C 'foobar'` → 'Cookie: DSID=foobar'
or `openconnect --protocol=fortinet -C 'ABCD123456=='` → 'Cookie: SVPNCOOKIE=ABCD123456==') without limiting
the ability to store multiple cookies if/when useful.
Daniel Lenski [Mon, 11 May 2020 22:34:34 +0000 (15:34 -0700)]
oncp_control_queue → tcp_control_queue
This is a queue for outgoing packets which must be sent over the
TCP-based transport; that is, they cannot be sent over the
UDP-based transport.
This queue was initially used by oNCP protocol for ESP enable/disable
packets, and it is now also used by Pulse. It will likely be used for
control packets by some PPP-based protocols as well.
Renaming it to TCP control queue to emphasize its cross-protocol
nature (cf. https://gitlab.com/openconnect/openconnect/-/merge_requests/151).
David Woodhouse [Sat, 27 Mar 2021 15:00:34 +0000 (15:00 +0000)]
Cast GetVolumeInformationByHandleW to (void *)
The 64-bit Windows build was complaining of pointer type mismatches but
I'm fairly sure it was a false positive:
../ssl.c: In function 'openconnect_passphrase_from_fsid':
../ssl.c:598:9: warning: cast between incompatible function types from 'FARPROC' {aka 'long long int (*)()'} to 'BOOL (*)(void *, WCHAR *, DWORD, DWORD *, DWORD *, DWORD *, WCHAR *, DWORD)' {aka 'int (*)(void *, short unsigned int *, long unsigned int, long unsigned int *, long unsigned int *, long unsigned int *, short unsigned int *, long unsigned int)'} [-Wcast-function-type]
598 | func = (GVIBH)GetProcAddress(kernlib, "GetVolumeInformationByHandleW");
| ^
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
David Woodhouse [Fri, 26 Mar 2021 15:54:39 +0000 (15:54 +0000)]
Fix obsolete-server-crypto in the GnuTLS build not the OpenSSL one.
We're clearing OpenSSL capabilities in the GnuTLS tests to work around
a SoftHSM bug, which is what confused me into putting the XFAIL in the
wrong case.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
David Woodhouse [Fri, 26 Mar 2021 15:38:16 +0000 (15:38 +0000)]
Add obsolete-server-crypto to XFAIL tests in Fedora package
The Fedora specfile explicitly sets the GnuTLS priority string to
include @OPENCONNECT but the test sets GNUTLS_SYSTEM_PRIORITY_FILE
to point to /dev/null so that stops working. Just XFAIL the test for
now so the builds start working again. More thinking required...
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
David Woodhouse [Fri, 26 Mar 2021 15:34:17 +0000 (15:34 +0000)]
Fix up string handling for ciphersuite_config
Sure it isn't C++ and std::string, but we *have* a method for appending
strings to a dynamic buffer. We don't need this snprintf("%s%s%s%s%s")
nonsense.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
David Woodhouse [Fri, 26 Mar 2021 14:52:40 +0000 (14:52 +0000)]
Fix pfs test for out-of-tree builds
Originally we generated config files from autoconf, so we had:
• ${srcdir}/tests/configs/test-foo.in
• ${builddir}/tests/configs/test-foo
Later, we wanted to generate files more dynamically at runtime with
different contents, so we added the update_config() function in
tests/common.sh which did its own substitution to a temporary file,
from
• $(srcdir}/tests/configs/test-foo
The pfs and obsolete-server-crypto tests appear to use a broken hybrid
of the two, first creating ${builddir}/tests/configs/test-foo from
autoconf and then attempting to use ${srcdir}/tests/configs/test-foo
at runtime. The latter isn't going to exist if ${srcdir} != ${builddir}.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
David Woodhouse [Fri, 26 Mar 2021 14:03:10 +0000 (14:03 +0000)]
Drop web page handling
The web site is handled by a cron job; if we wanted to flip that
over to pull from gitlab instead of git.infradead.org it would
be simple enough to it. Let's keep it in the same place for now.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Daniel Lenski [Tue, 23 Mar 2021 17:55:19 +0000 (10:55 -0700)]
MingW32 builds: generate NSIS installers for Windows
nsiswrapper is a rather dodgy Perl script (looks like it hasn't actually
been updated since ~2009) with one indispensable function: it can
automatically find required DLLs and bundle them into the installer.
1. The `PATH` variable must be set to include DLL locations (why `PATH`?️)
2. It mixes up its stdout and stderr, so `--verbose` can't be used without
`--run`. (Argh…)
3. It doesn't try to normalize the paths of the bundled files, so
`./x` and `$PWD/x` result in different directory structures.
Daniel Lenski [Tue, 16 Mar 2021 21:40:18 +0000 (14:40 -0700)]
cstp: don't send X-AnyConnect-Platform header
1. Cisco AnyConnect 4.8+ no longer sends it, and some newer servers reject
any client which sends it (see #101)… including older versions of Cisco's
own client. (Great job, Cisco 🤦🏻♂️.)
2. We can't find any evidence of older Cisco servers which *do* require this
header to be present in order to authenticate the client.
3. It's redundant. Any server that wants to know the client's platform as
soon as it receives the initial XML POST already has it. (It's in the
<device-id> tag in addition to the header.)
If there actually are any servers that *do* require this header to identify
and authenticate the client/platform, then the `--local-id` mechanism of
!103 is probably the right way to ensure that it is sent.
Daniel Lenski [Mon, 22 Feb 2021 03:17:42 +0000 (19:17 -0800)]
return EPERM, not EINVAL, when GP gateways reject the cookie upon get-config or GET-tunnel
Tested against 2 real GlobalProtect gateway servers, which both exhibit
these error behaviors:
1. 'GET /ssl-vpn/config' with bogus 'portal' field in cookie
=> XML error "Portal name not found"
2. 'GET /ssl-vpn/config' with 'user', 'authcookie', or 'portal' fields missing from cookie
=> HTTP/1.1 200, plaintext "errors getting SSL/VPN config"
3. 'GET /ssl-vpn-tunnel' with bogus 'user' or 'authcookie'
=> HTTP/1.1 504 (Gateway Timeout)
Daniel Lenski [Thu, 13 Jun 2019 15:53:27 +0000 (10:53 -0500)]
ensure that openconnect_disable_{dtls,ipv6} do nothing if vpninfo has ever been connected
Both openconnect_disable_dtls() and openconnect_disable_ipv6() now return
int (0 or -EINVAL), and are used in CLI argument processing.
Ideally, we would allow these to be used when IPv6 or DTLS/ESP are not currently
in use, but we do not have sufficiently reliable cross-protocol indicators of these.
The main use case for both of these functions is disable a problematic feature
prior to initial connection.
Daniel Lenski [Wed, 5 Jun 2019 03:30:30 +0000 (20:30 -0700)]
add openconnect_disable_dtls() API function
This also adds the API function to the Java bindings.
The immediate motivation is that there are a lot of Android users with
MTU-related issues (https://github.com/cernekee/ics-openconnect), and
disabling UDP/DTLS/ESP is a good temporary band-aid.
Daniel Lenski [Sat, 20 Feb 2021 00:05:09 +0000 (00:05 +0000)]
Try to generate static website using GitLab pages
Based on the example at https://gitlab.com/pages/plain-html, and ocserv's configuration (https://gitlab.com/openconnect/ocserv/blob/master/.gitlab-ci.yml)
Daniel Lenski [Mon, 25 Jan 2021 07:39:39 +0000 (23:39 -0800)]
allow specification of multiple certificate fingerprints on command-line via --servercert
Server certificates will be accepted if they match *any* of the provided fingerprints.
Behavior with `--servercert` is otherwise unchanged; it still disables system trust
stores, meaning that _only_ certificates matching the provided fingerprints will be
accepted if it is specified one or more times.
This will allow the use of `--servercert` to non-interactively connect to a server which
has a non-trusted certificate and redirects to one or more other servers with non-trusted
certificates. (See #25 for a real case.)
Daniel Lenski [Fri, 22 Jan 2021 00:27:23 +0000 (16:27 -0800)]
with --allow-insecure-crypto, additionally attempt to disable insecure systemwide minimum crypto settings
Because openconnect_set_allow_insecure_crypto() now does more than just attempt to reenable 3DES and ARC4,
its failure to enable those ciphers should not be treated as fatal, but merely a warning.
Setting the appropriate environment variable (GNUTLS_SYSTEM_PRIORITY_FILE or OPENSSL_CONF) to `/dev/null`
*before* crypto library initialization should ensure that a systemwide crypto configuration file doesn't
set a minimum crypto requirement which would override the user choice.
See https://gitlab.com/openconnect/openconnect/-/issues/211#note_482161646 for discussion of GnuTLS
settings, and https://www.openssl.org/docs/man1.1.1/man5/config.html for OpenSSL.
Daniel Lenski [Fri, 22 Jan 2021 02:01:42 +0000 (18:01 -0800)]
add openconnect__win32_setenv function to compat.c
Based on:
* POSIX-compatible `setenv` implementation for Windows: https://stackoverflow.com/a/23616164
* Enabling Windows "secure API" getenv_s and _putenv_s functions in MinGW:
* Using -DMINGW_HAS_SECURE_API: https://stackoverflow.com/a/51977723
* By manually defining their prototypes: https://stackoverflow.com/a/51977723
* Apparently, only newer versions of MinGW follow the MINGW_HAS_SECURE_API flag, and
autodetecting them is quite hard.
Tom Carroll [Sat, 16 Jan 2021 07:37:42 +0000 (23:37 -0800)]
Use separate counters for inner and outer loop.
The inner and outer loop share a counter. The inner loop resets the
counter to zero when entering the loop. I don't believe this is the
intention from an examination of the code. Have inner and outer loops
use separate counters.
Signed-off-by: Tom Carroll <incentivedesign@gmail.com>
Tom Carroll [Fri, 8 Jan 2021 19:26:48 +0000 (11:26 -0800)]
Free pcerts array for all assign_privkey paths.
Ensure the array pcerts is free'd for both success/fail paths. The function
gnutls_certificate_set_key() is odd as it takes ownership of the contents of
pcerts, but not the pcerts array itself. See:
Elias Norberg [Fri, 1 May 2020 12:08:02 +0000 (14:08 +0200)]
Always set security level to 0 for openssl versions >= 1.1.0
In version 1.1.0 of OpenSSL, a security level was introduced that enforces specific settings for certificates etc.
This PR sets the security level to 0, to retain the functionality that
previous versions of openssl had, and preventing errors like:
140088222534656:error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak:../ssl/ssl_rsa.c:310
See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_security_level.html for more information about security levels.
Signed-off-by: Elias Norberg <elias@aisle.se> Signed-off-by: Daniel Lenski <dlenski@gmail.com>
Daniel Lenski [Tue, 5 Jan 2021 04:48:20 +0000 (20:48 -0800)]
defer the switch to syslog until AFTER the tunnel is fully up,
This way, initial connection information and background PID will be usefully
printed to the console, as will errors which prevent the tunnel from being
started (and thus cause OpenConnect to abort as soon as it's established
a connection to the server).
Daniel Lenski [Thu, 24 Sep 2020 23:54:57 +0000 (16:54 -0700)]
Add `openconnect_get_auth_expiration` function to library and JNI
This allows protocols to save the moment when a session's authentication
(`vpninfo->cookie`) is expected to expire and no longer be useful for
reconnection.
The motivation is to eventually allow front-ends to know whether
reauthentication is needed, or whether they should try using a cached
cookie.
Current state:
- AnyConnect protocol: expiration is determined from the CONNECT
response header `X-CSTP-Session-Timeout-Remaining` (with
`X-CSTP-Session-Timeout` or `X-CSTP-Lease-Duration` as upper bounds in its
absence)
- GlobalProtect protocol: expiration is determined from the `<lifetime>` tag of
the XML config.
- Juniper Network Connect protocol: no currently known way to determine
expiration. The `DSID` cookie is a standard HTTP cookie, so perhaps its
expiration timestamp is intended for this purpose; however, I can find
no real-world case where it has an expiration timestamp set.
- None of the currently-supported protocols provide the expiration
timestamp until the connection phase, so it can't be obtained for
export by the `--authenticate` option.
Daniel Lenski [Mon, 30 Nov 2020 22:21:21 +0000 (14:21 -0800)]
GP: explicitly warn when server has a missing ESP configuration
I'm tired of OpenConnect getting blamed for lack of ESP connectivity when in
fact literally every example that has been investigated since 2017 turned
out to be due to a missing server configuration, broken server
configuration, or network UDP blockage.