100 Commits
Author SHA1 Message Date
Nikos Mavrogiannopoulos b6501f6661 Merge branch 'tmp-lease' into 'master'
Use network address as IPv6 lease start

Closes #714

See merge request openconnect/ocserv!543
2026-10-01 18:02:06 +00:00
Nikos Mavrogiannopoulos 67ae4d3ace tests: add test-ipv6-p2p for the server-side IPv6 address
Verifies that with a per-user /127 network the client is leased
network + 1 and the server takes the network address, that an explicit
IPv6 address equal to the server's /127 address is rejected, and that on
a wider network network + 1 is now leasable while the server takes the
network address. Replaces the p2p-net test, which could not connect
(ns.sh was not sourced) and had no occtl socket configured.

Relates: #714

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 22:12:55 +02:00
Nikos Mavrogiannopoulos 7fc0fb77c0 requirements: the server-side IPv6 tunnel address is the network address
Add REQ-MAIN-NET-006, the IPv6 counterpart of REQ-MAIN-NET-004: the
server takes the network address of ipv6-network, so on a /127
point-to-point network (RFC 6164) the client is leased the other address.
Document this in sample.config, noting that earlier versions used the
network address + 1.

Resolve the open OC-PROTO-CONN-007 / REQ-PROTO-CONN-007 notes: ocserv
follows "server address first" for both address families, and diverges
from the /127 recommendation for X-CSTP-Address-IP6 since it sends
ipv6-subnet-prefix.

Relates: #714

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 22:12:55 +02:00
Nikos Mavrogiannopoulos 0d3b4e82ed tests: keep the vpnc-script default route file per test run
tests/scripts/vpnc-script saved the default route to ./defaultroute,
which all tests running in parallel from build/tests share. A client
could thus restore another test's route in its own namespace ("Cannot
find device ocen1c<pid>"), leaving it without a route to the server.
Use a unique name per script.

Adds REQ-GEN-TEST-013.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 21:49:23 +02:00
Nikos Mavrogiannopoulos 8cb3c26dfb tests: detect network collisions from the routing table instead of ping
The generated-network subsystem accepted a network when its first host
address did not answer ping. That misses a local subnet whose other
hosts are in use, hosts that drop ICMP, and fails open when ping cannot
run at all (no CAP_NET_RAW in a container), since "no reply" and "ping
failed" look the same; each accepted draw also cost about two seconds.

Query the routing table instead: a drawn network or endpoint address is
redrawn while a route in any table lies inside it or covers it, which
includes the local addresses. Default routes and covering routes shorter
than the private block drawn from (e.g. a VPN client's 0.0.0.0/1) are
ignored. A failing ip command, or 100 rejected draws, aborts the test
instead of accepting the network. random-net.sh and random-net2.sh use
the same check for the ns.sh endpoint addresses.

Update REQ-GEN-TEST-011 accordingly, and REQ-GEN-TEST-012 to make ip a
hard dependency like ipcalc.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 21:48:32 +02:00
Nikos Mavrogiannopoulos d284915a77 tests: make test-iroute actually check the applied iroute
The check used a quoted right-hand side in [[ =~ ]], which bash treats
as a literal string, and a character class [vpns|tun] where an
alternation was meant; it never matched, so the test could not fail on
wrong route-add-cmd output. Compare the whole line with grep -Ex instead
and print the actual contents on failure.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 21:48:18 +02:00
Nikos Mavrogiannopoulos 2d240e02d3 tests: use generated networks and lint hard-coded addresses
Convert every test to REQ-GEN-TEST-010. Addresses configured on an
interface come from random-vpnnet.sh: templates use @VPNNET_BASE@ and
friends, keeping the original netmask and route formats; the vhost
tests allocate a distinct network per vhost with alloc_vpnnet4; the
firewall tests take the address of the blocked host from one; and the
RADIUS users file becomes a template materialized per test with
update_raddb(), so the tests no longer pin VPNNET to fixed ranges.
Addresses that are only data (routes, no-routes, iroutes, DNS servers,
Framed-Route, the pools of tests without a TUN device) move to
documentation ranges, keeping distinct networks distinct, and the
assertions follow; multiple-routes pushes 256 distinct routes, taken
from 198.18.0.0/15.

Add tests/check-test-addresses.py, run by the test-addresses-check job
in the preliminaries CI stage, which rejects any literal address outside
the ranges REQ-GEN-TEST-010 allows.

Relates: #714

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 21:48:14 +02:00
Nikos Mavrogiannopoulos 1e06cd36e0 tests: radius: use ping instead of iperf3 for the traffic step
The test only needs some traffic on the session for its accounting
checks, which require a non-zero Acct-Input-Octets. iperf3 through
the tunnel makes the worker exceed its RLIMIT_DATA headroom under
ASAN, which counts the sanitizer's shadow reservation as data.
Send pings instead.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 21:47:59 +02:00
Nikos Mavrogiannopoulos 7554fe920d tests: require generated VPN networks and make random-net.sh easy to use
Add REQ-GEN-TEST-010..012. Addresses a test configures on an interface
(VPN networks, explicit IPs, ...) must come from random-net.sh.
That way a test can never collide with the local network of the machine
running it.

common.sh substitutes @NAME@, @NAME_BASE@ and @NAME_ADDR@ for every
allocated network, adds @CONFIG_DIR@ and update_config_dir() to template
per-user and per-group config directories, adds update_raddb() to give a
RADIUS test a private raddb directory with a templated users file, and
fails with a clear message when a template uses a @VPN...@ placeholder
whose variable is unset, instead of producing a broken config.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-29 21:09:07 +02:00
Nikos Mavrogiannopoulos 979a1d5d99 Merge branch 'tmp-lease-ipv4' into 'master'
Fix IPv4 address lease for point-to-point /31 networks

See merge request openconnect/ocserv!559
2026-09-27 05:02:33 +00:00
Nikos Mavrogiannopoulos e6a8b6df07 ip-lease: factor the /31 netmask check into is_ipv4_p2p_mask()
Replace the duplicated mask31 byte arrays and memcmp() calls with a
single helper that compares the netmask against 255.255.255.254, and
refresh the src/ip-lease.c line citations in REQ-MAIN-NET-001/002/004.

Relates: #714

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@outlook.com>
2026-09-27 00:04:44 +02:00
Nikos Mavrogiannopoulos c588aa23f4 tests: add requirements and test for IPv4 /31 point-to-point leases
Verifies that a client with a per-user /31 network is leased the
non-network address while the server takes the network address, that
an explicit IP equal to the server's /31 address is rejected, and that
network/broadcast addresses remain reserved for /30 networks.

Relates: #714

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@outlook.com>
2026-09-27 00:01:20 +02:00
Nikos Mavrogiannopoulos b04e591b4c requirements: fix REQ-CONFIG-INIT-003 error-path citation; add NEWS entry
Relates: #759

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-26 23:28:06 +02:00
Nikos Mavrogiannopoulos 6f58414656 radius: standardize on radcli library
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-20 14:37:49 +02:00
Nikos Mavrogiannopoulos 73e5c15470 agents: updated promptkit protocols and requirements
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-20 14:27:15 +02:00
Nikos Mavrogiannopoulos f16daa89ef ocserv-core-dev: improved review protocol
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-20 13:27:05 +02:00
Nikos Mavrogiannopoulos 15bda6856d requirements: document the existing testing requirement
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-19 19:50:21 +02:00
Nikos Mavrogiannopoulos 9e1e983437 requirements: prevent fragile tests from being created or merged
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-19 19:34:22 +02:00
Nikos Mavrogiannopoulos d87625ecb6 doc update
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-19 06:47:50 +02:00
Nikos Mavrogiannopoulos df2302859f REQ-GEN-STYLE-003: removed
Removed introduced by mistake requirement. This is currently
under discussion in !579.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-19 06:45:57 +02:00
Nikos Mavrogiannopoulos 4a3ef2bf5d Merge branch 'mr589-graceful-shutdown' into 'master'
sec-mod: send accounting stop on server shutdown

Closes #643

See merge request openconnect/ocserv!589
2026-09-19 04:42:41 +00:00
Nikos Mavrogiannopoulos f433b0e8fb ocserv.8: include sample.config again
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-15 08:56:06 +02:00
Nikos Mavrogiannopoulos 46cd42a465 sample.config: documented no ordering guarantee of scripts
Resolves: #758

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-15 08:56:06 +02:00
Nikos Mavrogiannopoulos 4577a2a6ba README.md: explicitly call out ipcalc
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-13 18:43:37 +02:00
Nikos Mavrogiannopoulos 0f72ed3f21 meson: added option to disable the building of tests
Resolves: #760

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-13 17:51:35 +02:00
Nikos Mavrogiannopoulos 1355717a7d requirements: updated requirement for modifying vendored code
Also adds REQ-GEN-TECH-007 requiring that general improvements to
actively-maintained vendored subtrees be sent upstream first.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-09-12 12:08:43 +02:00
Nikos Mavrogiannopoulos 96a4baf9f9 certificate validation: do not use LOG_ERR when logging a missing optional certificate
When certificate authentication is configured as optional ensure that
there is sufficient information for tracing the authentication used
but do not log under LOG_ERR a missing certificate that was not required.

Resolves: #744

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-08-15 15:19:11 +02:00
Nikos Mavrogiannopoulos 143abadd27 tests: aligned the PAM launcher variants to use the simpler approach
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-08-14 07:35:19 +02:00
Nikos Mavrogiannopoulos cf598075de tests: simplified by reducing unnecessary launch functions
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-08-14 07:20:46 +02:00
Nikos Mavrogiannopoulos 77a3208f99 Fixed regression with CISCO Anyconnect clients and TLS 1.3
Resolves: #745

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-08-12 20:58:32 +02:00
Nikos Mavrogiannopoulos 9ed4342153 sec-mod: prevent malicious clients from piling up client_entry_st per pid
Malicious clients cannot send CMD_SEC_AUTH_INIT arbitrarily: a worker's
pid has one client_entry_st attached to it. A repeated SEC_AUTH_INIT
is accepted (replacing the previous entry) only when the prior
attempt already ended in PS_AUTH_FAILED with no session attached
(in_use == 0), matching the legitimate case for it (GSSAPI/certificate
falling back to the next auth method).

Resolves: #249

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-08-12 20:56:15 +02:00
Nikos Mavrogiannopoulos be6b5deea0 proc_to_zombie: removed dead definition
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-08-02 17:26:34 +02:00
Nikos Mavrogiannopoulos 2315b91894 ocserv.8.md: corrected SYNOPSIS
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-29 10:42:35 +02:00
Nikos Mavrogiannopoulos 1002c6fce7 README.md: document that this is only about Intune VPN
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-29 08:25:01 +02:00
Nikos Mavrogiannopoulos 77e06aec8a sec-mod, worker: harden TLS resumption cache against empty session data
A cached resume entry can end up with zero-length session_data, which is
not valid resumption data.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-28 08:07:07 +02:00
Nikos Mavrogiannopoulos 9e71c1b8b6 worker: use TLS 1.3 transparent rekey on TLS 1.3 CSTP sessions
TLS 1.3 has no renegotiation and provides transparent rekeys but this
was not used by the server. Instead rekey-method=ssl was silently
downgraded to new-tunnel, causing a full tunnel/TUN-device rebuild (and
a brief data-path interruption) on every rekey whenever a client
negotiated TLS 1.3.

This commit simplifies that handling by taking advantage of TLS 1.3's own
rekey mechanism instead: the server now performs the "ssl" rekey on
TLS 1.3 sessions via the standard TLS 1.3 KeyUpdate message.

TLS <= 1.2 rekey behavior (client-driven rehandshake, gated on RFC
5746 safe renegotiation) is unchanged.

Resolves: #745

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-28 08:07:07 +02:00
Nikos Mavrogiannopoulos 76987ccb82 tlslib, worker: remove dead code orphaned by the listen-clear-file removal
Commit 5cf457b4 ("Removed the listen-clear-file config option", Dec
2020) deleted the only code path that could ever construct a
SOCK_TYPE_UNIX worker connection, but left every branch that handled
it in place. Since then ws->session has been unconditionally non-NULL
and ws->conn_type unconditionally not SOCK_TYPE_UNIX for every worker,
making all of the following unreachable:

 - tlslib.c: recv_remaining(), _cstp_recv_packet() (the non-TLS CSTP
   reassembly path hardened in the previous commit), and
   tls_has_session_cert() (zero callers) deleted outright; cstp_cork/
   cstp_uncork/cstp_send/cstp_recv_packet/cstp_recv/cstp_close/
   cstp_fatal_close collapsed to their TLS-only body.
 - worker-http.c, worker-auth.c, worker-vpn.c, main.c: dead
   ws->session == NULL / ws->conn_type == SOCK_TYPE_UNIX branches
   removed or simplified to their live half.
 - worker-proxyproto.c: parse_ssl_tlvs() and its TLV structs/macros
   removed. This proxy-protocol SSL-CN extraction was itself only
   ever invoked from the same dead SOCK_TYPE_UNIX branch, so it has
   been as unreachable as the rest since 2020 despite a recent,
   otherwise-correct bug fix.
 - tests/cstp-recv.c deleted (exercised only the removed reassembly
   path); tests/proxyproto-v2.c trimmed to the still-live IPv6
   address-parsing regression test.
 - doc/sample.config: dropped the stale "TCP or UNIX socket" wording
   for listen-proxy-proto left over from the same 2020 removal; only
   a TCP socket is ever listened on for the proxy protocol now.

Narrows the worker's attack surface to the code paths a client can
actually reach, and removes a source of wasted maintenance effort.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-28 08:00:06 +02:00
Nikos Mavrogiannopoulos 879f723953 tlslib: harden recv_remaining() against truncated CSTP reads
recv_remaining() is used only on the non-TLS CSTP path (a UNIX socket
proxying plaintext CSTP in front of ocserv). On a recv() failure or
peer close mid-read, it discarded the error and returned whatever
partial byte count it had accumulated so far. Since every caller only
checks "ret <= 0" and otherwise trusts the count as a complete read,
a truncated body could come back as a positive, non-zero total that
looked like success: _cstp_recv_packet() would then report the full
8+pktlen size to its caller with only part of the buffer actually
populated from the network, feeding stale/uninitialized bytes into
parse_cstp_data() as if they were received client data.

Make the contract unambiguous: recv_remaining() now returns either
exactly the requested byte count or a negative error - never a
partial positive count a caller could mistake for success.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-28 08:00:06 +02:00
Nikos Mavrogiannopoulos d79eda6013 ip-util: reject routes with characters outside address/prefix syntax
ip_route_sanity_check() was a format normalizer, not a validator: any
dot-free route (all IPv6, or arbitrary text) returned success
unexamined, and a dotted-netmask IPv4 route passed through unchanged.
Since route_adddel() substitutes the validated route into
route-add-cmd/route-del-cmd and executes it via `/bin/sh -c` as root,
a route string carrying shell metacharacters that survived this check
was a root command-injection vector.

Rewrite the check to fully parse the route as an IPv4 or IPv6 address
plus prefix, or the literal keyword "default" (the documented
all-traffic-through-VPN shortcut, checked separately by config.c after
this function runs), and reject anything left over. Numeric IPv4
prefixes are still normalized to a dotted netmask as before.

Adds REQ-MAIN-SEC-008 and tests/route-sanity-check.c, confirmed
against real config/test usage (including "route = default") so the
stricter validation doesn't regress documented syntax.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-28 08:00:06 +02:00
Nikos Mavrogiannopoulos 5a9cddf606 main: validate AUTH_COOKIE_REQ cookie length before use
main read cookie.data[0] (to select sec_mod_instance_index) before
validating the cookie's length. A worker sending an empty cookie
unpacks with cookie.data == NULL (protobuf-c "required bytes"
semantics), so the read crashed the root main process, tearing down
every connected client.

Validate cookie.data/len immediately after unpacking, before the
first byte is read. handle_auth_cookie_req()'s own later check
remains as defense-in-depth.

Adds REQ-IPC-018.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-28 08:00:06 +02:00
Nikos Mavrogiannopoulos cdc9a5b5f4 Merge branch 'mr588-worker-seccomp-musl' into 'master'
worker-privs: allow munmap/mremap/madvise for isolated workers

Closes #749

See merge request openconnect/ocserv!588
2026-07-28 05:52:58 +00:00
Nikos Mavrogiannopoulos dde0a16df2 Merge branch 'tmp-coverity' into 'master'
Suppress Coverity Scan defect

See merge request openconnect/ocserv!596
2026-07-16 06:38:24 +00:00
Nikos Mavrogiannopoulos 6d4f96aa72 doc update
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-12 18:10:23 +02:00
Nikos Mavrogiannopoulos 26e76f9618 doc/requirements: align REQ-IPC-032 and REQ-AUTH-ACCT-002, add REQ-AUTH-ACCT-007
The previous commit dropped stats_st.uptime and the uptime fields of
cli_stats_msg/secm_session_close_msg, computing Acct-Session-Time directly
in sec-mod as now - e->created instead. Update the two requirements that
described the old IPC-carried, summed uptime, and add REQ-AUTH-ACCT-007 to
formally document the Acct-Session-Time definition (wall-clock lifetime of
the logical session, spanning cookie-resumed reconnects, bounded by
session-timeout and cookie-timeout) that was implicit in the fix, citing
tests/radius-reconnect-acct as its acceptance test.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-12 13:56:01 +02:00
Nikos Mavrogiannopoulos 96aa1f5ae7 tests: add reproducer for inflated RADIUS Acct-Session-Time across reconnects
A session that reconnects several times under the same cookie (roaming,
DPD, a new-tunnel rekey) currently reports an Acct-Session-Time far
larger than its real duration: each reconnected segment reports uptime
measured cumulatively from the original session start, and sec-mod sums
these cumulative per-segment values instead of taking the final one.

Add a test that drives three cookie-resumed segments (simulating
reconnects via SIGKILL, as tests/test-cookie-timeout does, so the
session survives between segments) with idle gaps in between, then
performs a clean final disconnect (SIGTERM), which ocserv reports as an
explicit user disconnect and closes the accounting session immediately.
It checks the Stop record's Acct-Session-Time is close to the real
elapsed wall-clock time rather than the sum of the individual segments'
cumulative uptimes.

This test currently fails against unpatched master.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-12 13:55:55 +02:00
Nikos Mavrogiannopoulos 0f7abd33ca auto-select group when a certificate provides enough information
When a certificate contains a single group there is no need to
request the user to select. Auto-select the group.

Resolves: #692

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-07-12 10:15:11 +02:00
Nikos Mavrogiannopoulos f3f74de305 tests: do not store environment information
This prevents accidental secret leakage.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 06:17:05 +02:00
Nikos Mavrogiannopoulos a53e6d4e25 .gitlab-ci.yml: do not store .tmp files as artifacts
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 06:16:37 +02:00
Nikos Mavrogiannopoulos bfe0d9ffd0 requirements: add REQ-CONFIG-SEC-002 for sup-config path-traversal hardening
Documents the intended hardening of get_sup_config() so that
username/groupname (attacker-influenced) can no longer be used to escape
per-user-dir/per-group-dir when looking up supplemental configuration.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 06:04:49 +02:00
Nikos Mavrogiannopoulos 5c57855e5c sup-config/file: reject path-traversal in username/groupname
Harden get_sup_config() by treating the username and groupname as
untrusted values.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 06:04:49 +02:00
Nikos Mavrogiannopoulos 5c0d4237f1 config: warn about select-group entries that exceed MAX_GROUPNAME_SIZE
Group names are stored in fixed-size (MAX_GROUPNAME_SIZE) worker
buffers, so a configured select-group entry that does not fit can
never be matched against a client-supplied group name. Warn the
administrator about such entries at config-load time, similar to
other configuration sanity checks in check_cfg().

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 06:04:49 +02:00
Nikos Mavrogiannopoulos 7fe325de46 ocserv-core-dev agent: validate requirements explicitly
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 06:02:56 +02:00
Nikos Mavrogiannopoulos bda207237a requirements: enhanced with general implementation requirements
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-17 05:35:02 +02:00
Nikos Mavrogiannopoulos cfb0e0a2b2 main: improved reporting of errors by main
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-15 22:23:24 +02:00
Nikos Mavrogiannopoulos a3ac48c2d4 Move to a requirements-first approach
Add doc/requirements/, a structured set of normative requirements
extracted from the current ocserv implementation (internal/*.md,
generated with the requirements-from-implementation protocol) and
from the OpenConnect/AnyConnect protocol sources, reconciled into
protocol/unified.md.

Update AGENTS.md so that new features and bug fixes are documented as
requirements first: find or add the relevant REQ-* entry (with
acceptance criteria) and update the implied tests before changing
code, and confirm in merge requests that existing requirements and
use-cases still hold.

This follows partially https://github.com/microsoft/PromptKit

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-15 18:54:38 +02:00
Nikos Mavrogiannopoulos 8e8efd33a6 ai: added security-auditor persona
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-15 18:54:23 +02:00
Nikos Mavrogiannopoulos 4f187578c3 .gitignore/doc: removed legacy files
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-14 18:08:00 +02:00
Nikos Mavrogiannopoulos ea253803e7 Merge branch 'tmp-make' into 'master'
Do not reference make

See merge request openconnect/ocserv!584
2026-06-14 13:26:20 +00:00
Nikos Mavrogiannopoulos 80ce55ae8f Merge branch 'tmp-CID-646042' into 'master'
Suppress Coverity Scan false positive

See merge request openconnect/ocserv!546
2026-06-13 05:45:25 +00:00
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 49f9956eee release.sh: do not reference make
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:35:33 +02:00
Nikos Mavrogiannopoulos a4a8126c7b doc update
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:30:26 +02:00
Nikos Mavrogiannopoulos b7a73b968d parse_data(): ensure sanity checks for safety
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:29:52 +02:00
Nikos Mavrogiannopoulos 9866624118 tun_write(): check input value for sanity
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:29:52 +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 77097440eb worker: fix heap buffer overflow in webvpncontext= cookie decoding
An unauthenticated client could send a Cookie header with a webvpncontext=
value long enough that its base64-decoded length far exceeded SID_SIZE (32
bytes).  The decoder wrote directly into ws->sid without a prior length
check, overwriting adjacent fields in worker_st and crashing the worker.

The webvpn= cookie already had the correct pattern: check decoded length
bounds before decoding, decode into the ws->buffer scratch area, then
memcpy into the target only on an exact-size match.  Apply the same
pattern to webvpncontext=.

Resolves: #719

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 235882cebf doc update
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-07 08:27:25 +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
Nikos Mavrogiannopoulos 117ed17d82 Merge branch 'tmp-729' into 'master'
Handle RADIUS Access-Challenge State as bytes

Closes #729

See merge request openconnect/ocserv!576
2026-06-06 15:16:33 +00:00
Nikos Mavrogiannopoulos b23c939d29 contrib: added protocols for requirements management
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-06 12:16:11 +02:00
Nikos Mavrogiannopoulos 14b5295e8f ocserv-core-dev: added root-cause-analysis protocol from promptkit
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-06 12:05:59 +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 bdb69162b4 pam: cleanup PAM session if user aborts during conversation
When a PAM conversation is open and the worker terminates, then
depending on the PAM module in use resources can remain in use
even after cleaning up of the used by coroutines memory. Address
this by gracefully terminating the conversation prior to cleaning
up.

Resolves: #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 0b11fdc5bf Merge branch 'tmp-fix-691' into 'master'
config: add syslog-facility option to allow routing logs independently

Closes #691

See merge request openconnect/ocserv!574
2026-06-05 12:50:03 +00:00
Nikos Mavrogiannopoulos f906b9cfbc ocserv.8.md: document that pid-file is available in config
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-03 19:53:21 +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 708f42a455 CONTRIBUTING.md/AGENTS.md: require tests to be self-diagnosing
This is to enable agents bring good tests that can be debugged
easily.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-31 22:33:53 +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
Nikos Mavrogiannopoulos 0e74eeffcc .triage-policies.yml: apply the wontfix label if closing automatically [ci skip]
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-31 13:11:20 +02:00
Nikos Mavrogiannopoulos 86fe12e989 .gitlab-ci.yml: removed unnecessary jobs from schedules [ci skip]
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-31 00:14:34 +02:00
Nikos Mavrogiannopoulos f0406217eb .gitlab-ci.yml: run and print debugging information [ci skip]
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-31 00:08:02 +02:00
Nikos Mavrogiannopoulos 7bf968617b .gitlab-ci.yml: do not depend our schedules on the coverity job
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-30 23:42:19 +02:00
Nikos Mavrogiannopoulos 9e46c9714e Merge branch 'tmp-LICENSE' into 'master'
Add LICENSE files of bundled sotware

See merge request openconnect/ocserv!562
2026-05-30 21:36:22 +00:00
Nikos Mavrogiannopoulos ce350a17e5 Merge branch 'tmp-llhttp' into 'master'
llhttp: updated to latest version 9.4.1

Closes #736

See merge request openconnect/ocserv!564
2026-05-30 21:28:00 +00:00
Nikos Mavrogiannopoulos bcc9d3bff7 .triage-policies.yml: close stale and unassigned issues
Automatically close issues that have been open for more than 6 months
without an assignee and without a linked merge request. Security-labeled
issues are excluded.

The motivation:

- Issues tend to stay open indefinitely under the implicit assumption that
  someone will eventually pick them up. In practice this rarely happens.
- The backlog keeps growing, making it harder to see what is actually
  being worked on.
- The number of contributors who turn an issue into a merge request is
  very small relative to the number of issues filed.
- The goal is to keep the issue tracker focused on work that is actively
  in progress, not as a wishlist.
- Hopefully this encourages a more active contribution culture: instead
  of "I have reported it, someone will pick it up", reporters are nudged
  to either own the fix or accept that it may not happen.

Resolves: #740
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-30 22:51:16 +02:00
Nikos Mavrogiannopoulos 0727bdbe1f worker: detect and handle errors in socket from main
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-30 22:49:07 +02:00
Nikos Mavrogiannopoulos 30f33ac9d1 tun_write/read were made macros in linux for write and read
This avoids an unnecessary function call.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-30 22:49:07 +02:00
Nikos Mavrogiannopoulos 2be9af605b tlslib: simplified by requiring gnutls 3.3.5
This removes the (unconditional) ZERO_COPY conditional.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-30 22:49:07 +02:00
Nikos Mavrogiannopoulos d3372cbcb4 worker: drain TUN in a burst loop to avoid per-packet epoll_wait()
Previously tun_watcher_cb() called tun_mainloop() exactly once per
libev wakeup and then returned, causing ev_run() to call epoll_wait()
again before the next packet.  At high packet rates the TUN device
stays continuously readable, so this wastes one epoll_wait() syscall
per packet (~20-30 µs each in the report) and keeps the worker nearly
idle while the TUN queue grows.  The result is severe packet loss on the
TUN→client path (74% loss reported at 900 Mbps in issue #423).

Fix by looping in tun_watcher_cb() up to TUN_BURST_MAX iterations before
yielding back to the event loop and making the tun fd non-blocking. That
resulted to a reorganization of tls_mainloop() / dtls_mainloop() via
parse_data() to queue packet when the tunfd isn't writeable.

Resolves: #423

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-30 22:49:07 +02:00
Nikos Mavrogiannopoulos f5231eab10 CONTRIBUTING.md: added rule on patches
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-26 13:06:55 +02:00
Nikos MavrogiannopoulosandDimitri Papadopoulos 8faa35d67a Merge branch 'tmp-736' into 'master'
Fix calculation of avg_auth_time acros sec-mod instances

Closes #736

See merge request openconnect/ocserv!560
2026-05-24 16:09:20 +02:00
Nikos Mavrogiannopoulos 0eb7313bca Merge branch 'tmp-736' into 'master'
Fix calculation of avg_auth_time acros sec-mod instances

Closes #736

See merge request openconnect/ocserv!560
2026-05-24 11:24:14 +00: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 6b74546a1b Merge branch 'tmp-pcl' into 'master'
Always use the bundled PCL library

Closes #663

See merge request openconnect/ocserv!565
2026-05-24 09:21:42 +00:00