Commit Graph
554 Commits
Author SHA1 Message Date
Nikos Mavrogiannopoulos 29dd18ddc5 tests: add SIGKILL fallback in cleanup_client_server
Ensure that ocserv is killed within bounded time by falling
back to a SIGKILL if ocserv does not stop on time.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-11 15:40:37 +02:00
Nikos Mavrogiannopoulos eeef24e520 tests: do not skip if /usr/sbin/ip is missing
This is to prevent an accidental skipping of the test.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-11 15:40:37 +02:00
Nikos Mavrogiannopoulos 826fe0ff30 tests: attempt to fix disconnect-user race that caused 300 s timeouts
After the occtl disconnect, poll 'occtl show user test' until the
session is gone before attempting the reconnect.  This guarantees that
session_close() has already returned and main's event loop is free to
process the reconnect worker's AUTH_COOKIE_REQ.

Addresses intermittent failures observed in the Fedora, CentOS9, and
CentOS10 CI jobs.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-11 15:40:37 +02:00
Nikos Mavrogiannopoulos 3f4a1f0e68 tests: reduce parallelization in asan
Often certain tests when run under asan will fail with out of memory.
Reduce parallelization for these tests when run under asan to reduce
memory pressure.

Example:
https://gitlab.com/openconnect/ocserv/-/jobs/14724892759

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-11 15:40:37 +02:00
Nikos Mavrogiannopoulos 6d778ebadb tests: pam-stack-guard: guard against tail optimizations of gcc
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-10 20:52:56 +02:00
Nikos Mavrogiannopoulos c5c921528d worker: reject client MTU below MIN_MTU to prevent unsigned underflow
DATA_MTU(ws, mtu) performs unsigned subtraction.  A client advertising
X-CSTP-Base-MTU or X-CSTP-MTU smaller than the combined DTLS overhead
(IP + UDP + DTLS record + crypto) causes the result to wrap to ~UINT_MAX,
which then reaches memset(), tun_read(), and IPC calls.

Fix: enforce MIN_MTU(ws) (800 for IPv4, 1280 for IPv6) as the lower
bound when accepting client-supplied link_mtu and tunnel_mtu values.
Values below the floor are logged and ignored; the server's own MTU
is used instead.  Add a defense-in-depth lower-bound check in
link_mtu_set() and a runtime assert after calc_mtu_values() that fires
in CI if a future cipher or protocol change erodes the safety margin.

Resolves: #717

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:29:52 +02:00
Nikos Mavrogiannopoulos 8aa1022696 tests: add reproducer for oversized webvpncontext=/webvpn= cookie overflow
Sending a Cookie header with a webvpncontext= value whose base64-decoded
length exceeds SID_SIZE crashes the worker with SIGSEGV before it can
send an HTTP response.  The test detects both pre- and post-response
crashes: a connection reset (HTTP 000) and a "died with sigsegv" entry
in the server log respectively.

Relates: #719

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:29:52 +02:00
Nikos Mavrogiannopoulos bd97e44234 Merge branch 'fix-cached-group-select' into 'master'
Fix cached group-select handling

Closes #742

See merge request openconnect/ocserv!570
2026-06-07 06:24:15 +00:00
Mikhail Chodorenko d72074e9eb Fix cached group-select handling
Ignore unknown cached group-select values during the initial auth form request so they do not suppress the configured group list. Keep valid group values and friendly labels selected first, and defer unlisted group names to sec-mod once real authentication data is present so hidden groups continue to work. Declare UTF-8 in XML auth response Content-Type headers so clients decode localized group labels correctly.

Resolves: #742

Signed-off-by: Mikhail Chodorenko <chodorenko@gmail.com>
2026-06-06 23:41:11 +02:00
Nikos Mavrogiannopoulos 0dafa7b005 tests: add regression test for pam_auth_deinit coroutine safety
Add test-pam-abort, which verifies that pam_auth_deinit() correctly
resumes a suspended PAM coroutine before calling pam_end().

The test posts a username-only HTTP request to trigger SEC_AUTH_INIT,
leaving the PAM coroutine suspended in PAM_S_WAIT_FOR_PASS while the
worker exits without sending a password.  The stale pre-auth entry is
cleaned up by the sec-mod maintenance cycle (driven by the new
sec-mod-db-cleanup-time config knob, set to 3 s in the test config).

Bug detection is provided by pam_abort_test.so, a small PAM module that
registers a pam_set_data() cleanup which calls abort() if pam_end() fires
while conv->conv() has not yet returned.  Without the fix, sec-mod would
abort and the subsequent authentication check would fail.

Relates: #741

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-06 08:12:13 +02:00
Nikos Mavrogiannopoulos 74ec165316 pam: increase coroutine stack to 8 MB and add guard page
Certain pam modules such as pam_sss with AD/Kerberos and multi-factor
authentication requires significantly more stack than the previous
1 MB limit.

On Linux, allocate the coroutine stack with mmap and place a PROT_NONE
guard page immediately below it.  This turns a stack overflow into an
immediate SIGSEGV rather than silent corruption of adjacent heap memory
to better detect similar cases.

Fixes: #657
Relates: #619

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-06 08:12:13 +02:00
Nikos Mavrogiannopoulos 0f5c628048 config: add syslog-facility option to allow routing logs independently
ocserv always logged to the syslog daemon(3) facility, making it
impossible to route its messages separately from other daemons.
Adds a syslog-facility config key (and --syslog-facility CLI flag)
accepting daemon/user/auth/authpriv/local0-local7; defaults to daemon.

Resolves: #691

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-03 19:52:36 +02:00
Nikos Mavrogiannopoulos e01968060b ocserv: exit with error code on error
Relates: #615

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-31 22:32:20 +02:00
Dimitri Papadopoulos 34be9e368e tests: whichcommand -v
Use `command -v` instead of `which` because:
* It's built into the shell, avoiding an external dependency on the
  `which` package on Fedora 44.
* It works across all POSIX-compliant shells.
* It's standard across Linux distributions. For example, Fedora 44
  lacks the `which` package by default.

Signed-off-by: Dimitri Papadopoulos <3350651-DimitriPapadopoulos@users.noreply.gitlab.com>
2026-05-31 14:17:33 +02:00
Nikos Mavrogiannopoulos efd41d300f Merge branch 'tmp-711' into 'master'
Set `sa` before attempting to set `sa->sin6_family`

Closes #711

See merge request openconnect/ocserv!554
2026-05-24 09:22:08 +00:00
Nikos Mavrogiannopoulos 1b6e22246d Test proxy protocol parser with IPv6 packet
Relates: #711

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-23 14:52:01 +00:00
Nikos Mavrogiannopoulos d2b78d48ca tests: add live reproducer for cstp_send() hang on frozen peer (issue #638)
Connects an openconnect client, floods ICMP traffic so the server
accumulates ICMP replies in cstp_send(), then freezes the client with
SIGSTOP to prevent the TCP receive buffer from draining.  Asserts that
the worker session disappears from occtl within DEFAULT_SOCKET_TIMEOUT
plus margin, which would never happen with the old infinite retry loop.

Relates: #638

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-23 07:39:51 +02:00
Nikos Mavrogiannopoulos 788b1a2b30 Merge branch 'tmp-fix-716' into 'master'
worker: stop HTTP parser at message boundary to prevent request pipelining confusion

Closes #716

See merge request openconnect/ocserv!549
2026-05-21 06:34:06 +00:00
Nikos Mavrogiannopoulos 583f0c0be5 worker: fix ICMPv6 misclassification as data traffic affecting idle-timeout
ICMPv6 was never excluded from idle-timeout accounting because is_data()
inspected data[9] for both IPv4 and IPv6.  Offset 9 is the Protocol field
in the IPv4 fixed header (RFC 791), but the Next Header field in the IPv6
fixed header sits at offset 6 (RFC 8200 §3).  As a result, the idle timer
was reset on every ICMPv6 packet, preventing the server from disconnecting
clients that were sending only control traffic.

Resolves: #724
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-19 20:14:21 +02:00
Nikos Mavrogiannopoulos bf23e0d549 /svc handler: add the owasp headers for consistency
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-19 20:11:33 +02:00
Nikos Mavrogiannopoulos e567f92e64 Removed unnecessary CA and certificate handlers
This removes certificate and CA handlers not used by the openconnect
client. This is a hardening measure to further reduce the attack surface
of the worker process.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-19 20:11:33 +02:00
Nikos Mavrogiannopoulos 01f2787ab6 worker: reject HTTP pipelining to prevent request confusion
When two HTTP requests arrived in the same TLS read buffer, a single
llhttp_execute() call would fire callbacks for both requests inline.
Because http_req_reset() is not called between them, ws->req ended up
reflecting the second request's URL and headers, silently discarding
the first.  In the worst case, body bytes from the first request
accumulated alongside the second request's body.

Fix this by registering an on_message_begin callback that returns
HPE_PAUSED when an existing message is detected.

Resolves: #716

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-15 06:42:24 +02:00
Grigory Trenin 61f013ae3a pam: add 'service' sub-option to auth directive
This allows users to specify a custom PAM service name, enabling
per-virtual-host PAM stacks.For example:
auth = "pam[service=vpn1,gid-min=1000]"

Resolves: #718

Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
2026-05-08 21:00:07 -04:00
Nikos Mavrogiannopoulos 4303a12f60 worker: harden HTTP request header size limits
Bound memory growth in the worker for unauthenticated connections by
enforcing HTTP headers limit in addition to HTTP body limit.

Resolves: #712

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-06 13:54:21 +02:00
Nikos Mavrogiannopoulos 9c44e09356 ocserv-fw-nftables: replace ipcalc with pure-shell mask_to_prefix
ipcalc was used only to convert dotted-decimal subnet masks to CIDR
prefix lengths (e.g. 255.255.0.0 -> 16), replaced with a POSIX shell
script.

Relates: #709

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-02 17:21:38 +02:00
Nikos Mavrogiannopoulos 465d3ce383 Merge branch 'tmp-framed-ipv6' into 'master'
radius-auth: fix Framed-IPv6-Prefix routes being silently dropped

Closes #710

See merge request openconnect/ocserv!532
2026-05-01 20:21:09 +00:00
Dimitri Papadopoulos OrfanosandNikos Mavrogiannopoulos c0b282576e Fix new Coverity Scan defect
This adds checks in memory allocation, to address the following issue reported by coverity:
** CID 645850:       Null pointer dereferences  (FORWARD_NULL) /tests/ban-ips.c: 84           in main()

Signed-off-by: default avatarDimitri Papadopoulos <3350651-DimitriPapadopoulos@users.noreply.gitlab.com>
2026-05-01 19:26:45 +00:00
Nikos Mavrogiannopoulos e7d79e232d radius-auth: fix Framed-IPv6-Prefix routes being silently dropped
When processing a RADIUS Access-Accept with Framed-IPv6-Prefix, the code
passed the wrong value for it. Corrected by passing the actual prefix.

Fixes: #710

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-01 16:31:38 +02:00
Grigory Trenin a79e2f1cd5 Respect tunnel-all-dns in per-user/group config
Ensure that 'tunnel-all-dns' setting is honoured when overridden
in user or group-specific configuration files.

Resolves: #708

Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
2026-04-26 21:05:06 -04:00
Nikos Mavrogiannopoulos 54e3244b45 tests: fix radius failures with radcli 1.5.0
radcli 1.5.0 validates Message-Authenticator in RADIUS responses
CVE-2024-3596 (BlastRADIUS) and silently discards responses that lack
it.  Make sure that the Message-Authenticator message is known to
the client via the dictionary.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-25 19:40:56 +02:00
Nikos Mavrogiannopoulos 5148c723cb tests: fix flaky radius tests by waiting for server readiness
All six radius tests used a fixed sleep 4 after starting radiusd and
ocserv.  On slow or ASAN-instrumented hosts (CentOS 10 CI) this is
insufficient: freeradius with -xx debug logging takes longer than 4
seconds to load its modules, and even after binding UDP 1812 it continues
initializing its user database before it can process auth requests.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-25 17:20:38 +02:00
Nikos Mavrogiannopoulos 58a67f14f3 config: extend vhost_inherit_static_config to cover vhost-scoped fields
All [scope: vhost (non-reloadable)] fields in static_cfg_st now inherit
from the default vhost when not explicitly set in a named-vhost section,
consistent with how ReloadableConfig fields already behave.  This means
a named vhost that shares the same TLS cert, CA, auth method, or PKCS#11
pins as the default no longer has to repeat them.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-23 10:51:26 +02:00
Nikos Mavrogiannopoulos 836e6f0785 config: fix scope annotation and vhost guards for global-only options
NetworkConfig.name ('device' key) is global-only: the parser calls
error_on_vhost() and tun.c always reads it from the default vhost.
Annotate it as [scope: global] in cfg.proto to match the implementation.

Also add missing error_on_vhost() guards to the deprecated aliases
'use-seccomp' (for isolate-workers), 'use-dbus' (for use-occtl) and
'min-reauth-time' (for ban-time). Their canonical replacements already
reject vhost use; the aliases did not.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-22 20:29:24 +02:00
Nikos Mavrogiannopoulos 139ff827d9 config: restructure per-vhost configuration for clarity and maintainability
Introduce a protobuf-generated ReloadableConfig (cfg.proto) to hold all
fields that reload on SIGHUP, and separate them from static_cfg_st, which
holds fields that require a server restart.  Named vhosts inherit from the
default vhost via a pack/unpack round-trip. Adding a new config field
only requires editing cfg.proto.  Struct and accessor names (ReloadableConfig,
static_cfg_st, GETRCONFIG, GETSCONFIG) now reflect each field's lifetime.
A new unit test covers the full inheritance path.

Resolves: #705

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-22 20:29:15 +02:00
Nikos Mavrogiannopoulos a9f42c892c valid_hostname: enhance to cover RFC 1123 requirements
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-18 15:51:20 +02:00
Dimitri Papadopoulos c4767470eb RFC 952 prohibits trailing hyphen, not only leading hyphen
Signed-off-by: Dimitri Papadopoulos <3350651-DimitriPapadopoulos@users.noreply.gitlab.com>
2026-04-17 22:33:11 +02:00
Nikos Mavrogiannopoulos bc961061d1 worker: fix PP2_SUBTYPE_SSL_CN parsed as top-level TLV instead of sub-TLV
Per proxy protocol v2 spec §2.2.6, PP2_SUBTYPE_SSL_CN (0x22) is a
sub-TLV inside the PP2_TYPE_SSL body, not a top-level TLV in the TLV
stream.  The previous code looked for 0x22 at the top level, where
haproxy never sends it, so client certificate CN was never extracted
via proxy protocol.

Fix parse_ssl_tlvs() to scan the bytes after the fixed pp2_tlv_ssl
header as a nested sub-TLV loop when cert_auth_ok is set.

Also fix htons() -> ntohs() for the TLV length byte-swap (functionally
identical but semantically correct for a network-to-host conversion),
and update the misleading comment that claimed the field was
little-endian.

Add tests/proxyproto-v2.c, a unit test that feeds a binary proxy
protocol v2 packet with PP2_TYPE_SSL + PP2_SUBTYPE_SSL_CN sub-TLV
through parse_proxy_proto_header() and verifies that cert_auth_ok and
cert_username are populated correctly.  Also covers verify!=0, missing
CERT_SESS flag, no CN sub-TLV, and TCP conn_type (TLV parsing skipped).

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-16 22:46:41 +02:00
Nikos Mavrogiannopoulos d3eceef085 Merge branch '64bit-timestamps' into 'master'
protobuf: use 64-bit signed integers for timestamp fields

See merge request openconnect/ocserv!506
2026-04-14 19:03:05 +00:00
Grigory Trenin cde58c22be protobuf: use 64-bit signed integers for timestamp fields
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
2026-04-14 13:59:05 -04:00
Grigory Trenin db125634b8 Allow using no-udp option in vhosts
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
2026-04-14 13:26:32 -04:00
Nikos Mavrogiannopoulos 611eb00527 config: add scope annotations and validation script
Add machine-readable [scope: X] annotations to doc/sample.config and
src/vpn.h struct fields to document which config options are permanent,
global-only, per-vhost, or per-user/group overridable.

Scope vocabulary:
  global (non-reloadable)  -- in perm_cfg_st; requires restart; cannot differ per vhost
  vhost (non-reloadable)   -- in perm_cfg_st; requires restart; can differ per vhost
  global            -- in cfg_st; reloadable; cannot be set in [vhost:] sections
  vhost             -- in cfg_st; reloadable; can differ per vhost
  vhost user        -- in cfg_st; reloadable; also overridable per user/group

Add tests/check-config-scope.py: a script that cross-checks the annotations
against the actual code:
  (a) every option in sample.config has a [scope:] annotation
  (b-c) [global] options match error_on_vhost() calls in config.c
  (d-e) [vhost user] options match handlers in src/sup-config/file.c
  (f) every field in cfg_st and perm_cfg_st has a [scope:] comment

Also fix a pre-existing bug in src/sup-config/file.c: the tunnel-all-dns
option was compared using an underscore ("tunnel_all_dns") instead of
the correct dash ("tunnel-all-dns"), silently ignoring the per-user
setting.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-14 18:57:45 +02:00
Nikos Mavrogiannopoulos 05cf33adb7 tests: added tests for multiple ocpasswd options
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-13 22:43:52 +02:00
Nikos Mavrogiannopoulos db50c02cbd Merge branch 'tmp-radius-group-separator' into 'master'
radius: add group-separator option for OU= Class attributes

Closes #428

See merge request openconnect/ocserv!513
2026-04-10 04:29:39 +00:00
Grigory Trenin bf12b9fe9c Fix global option inheritance for virtual hosts
Ensure global options are properly copied to virtual hosts when not
explicitly specified.

This change also:
- Documents global options that cannot be overridden in virtual hosts.
- Adds a 'VIRTUAL HOSTS' section to the man page to clarify behavior.

Closes #698

Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
2026-04-09 20:20:45 -04:00
Nikos Mavrogiannopoulos 89a40dde31 tests: add radius-multi-group-comma test for group-separator=comma
Regression test for the group-separator=comma option: verifies that
OU= Class attributes with comma-separated group names (as sent by
Freeradius) are correctly parsed when group-separator=comma is set.

Relates: #428

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-06 21:27:28 +02:00
Nikos Mavrogiannopoulos 85b4d19f0a tests: check that empty password with correct OTP fails when password is set
Regression test: a user with both a password and OTP configured must not
be able to authenticate by supplying an empty password (even with the
correct OTP).

Relates: #323
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-03 13:58:18 +02:00
Nikos Mavrogiannopoulos c45e3467bb tests: check for the case where a password is incorrectly entered
This is a reproducer for the issue reported in #323

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-03 12:29:01 +02:00
Nikos Mavrogiannopoulos b25a1e7d81 tests: check for IPv6 handling issue
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-02 23:04:29 +02:00
Nikos Mavrogiannopoulos 3db9ecd259 tests: fixed flaky condition in disconnect-user
Ensure the client is killed eventually to prevent an openconnect
re-connect to keep the test up.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-03-29 21:13:28 +02:00
Nikos Mavrogiannopoulos fd3235784f tests: gssapi tests were moved to a specific testsuite
They are skipped in Ubuntu 22.04.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-03-29 17:32:23 +02:00