Commit Graph
100 Commits
Author SHA1 Message Date
Nikos Mavrogiannopoulos 6a9b34d3c8 Move to a requirements-first approach [ci skip]
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-14 09:04:53 +02:00
Nikos Mavrogiannopoulos ec6c42ea1e ai: added security-auditor persona
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-13 13:36:46 +02:00
Nikos Mavrogiannopoulos 3fbeca3aec .gitignore/doc: removed legacy files
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-06-12 19:02:38 +02: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
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 ae021ecf58 Merge branch 'anyconnect-bye-packet' into 'master'
Handle AnyConnect BYE packet with reconnect intention (0x91)

Closes #732

See merge request openconnect/ocserv!555
2026-05-23 14:25:22 +00:00
Nikos Mavrogiannopoulos e5894dba7d NEWS: doc update
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-23 07:43:46 +02:00
Nikos Mavrogiannopoulos 2dd5956317 dtls_send: fix hang and buffer overread on persistent GNUTLS_E_AGAIN
Same two bugs as cstp_send (issue #638): the retry passed the original
data_size instead of the remaining byte count, and GNUTLS_E_AGAIN caused
an unbounded sleep loop.  Apply the same poll()-based fix bounded by
DEFAULT_SOCKET_TIMEOUT.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-23 07:39:51 +02: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 35e3d15a11 cstp_send: fix worker hang and buffer overread on TLS send
A worker could get permanently stuck when a client disappeared silently
(e.g. iOS roaming between WiFi and cellular): the TLS send loop retried
indefinitely on GNUTLS_E_AGAIN with no deadline, requiring SIGKILL to
recover.

A separate bug caused a buffer overread on partial sends: the retry used
the original data_size instead of the remaining byte count, so the send
pointer advanced past the end of the caller's buffer.

Resolves: #638

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-23 07:39:51 +02:00
Nikos Mavrogiannopoulos bb9bcd7461 main: remove cgroup support in favour of systemd resource controls
Native cgroup placement is removed. Delegating resource enforcement
to systemd eliminates the privileged /sys/fs/cgroup writes from
the main process and simplifies the code.

Administrators who previously relied on the 'cgroup' option should use
the [Service] section of the ocserv unit file instead; see
systemd.resource-control(5) for details.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-23 07:09:23 +02:00
Nikos Mavrogiannopoulos 25861ab602 Merge branch 'tmp-nettle4' into 'master'
Build against GNU Nettle 4

Closes #697

See merge request openconnect/ocserv!553
2026-05-21 06:35:54 +00: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 2dfb9acec5 Updated instructions for AI agents reporting vulnerabilities
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-19 16:57:44 +02:00
Nikos Mavrogiannopoulos 0b47ea457d Merge branch 'tmp-uninitialised-handle' into 'master'
Do not use uninitialised PAM/GnuTLS handles

Closes #722

See merge request openconnect/ocserv!547
2026-05-17 19:56:55 +00:00
Nikos Mavrogiannopoulos 6e658f00ae Merge branch 'tmp-NULL-dereference' into 'master'
Avoid NULL dereference in case of memory exhaustion

Closes #721

See merge request openconnect/ocserv!545
2026-05-16 20:20:49 +00: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
Nikos Mavrogiannopoulos aeaf5a0896 Merge branch 'tmp-seclog-trailing-newline' into 'master'
Avoid trailing `\n` in messages passed to logging

See merge request openconnect/ocserv!544
2026-05-12 18:02:45 +00:00
Nikos Mavrogiannopoulos 6c4a0aca93 Merge branch 'tmp-talloc_array' into 'master'
talloc_size() → talloc_array()

Closes #725

See merge request openconnect/ocserv!541
2026-05-12 05:21:44 +00:00
Nikos Mavrogiannopoulos 923187aa4c Merge branch 'tmp-strerror' into 'master'
Use strerror() and pass proper errno to it

Closes #723

See merge request openconnect/ocserv!542
2026-05-12 05:14:54 +00:00
Nikos Mavrogiannopoulos 93c08b5c83 Merge branch 'pam-service' into 'master'
Add service sub-option to PAM auth

Closes #718

See merge request openconnect/ocserv!539
2026-05-11 17:06:56 +00:00
Nikos Mavrogiannopoulos 2548a27b51 Merge branch 'tmp-AF_INET' into 'master'
Build on FreeBSD

See merge request openconnect/ocserv!514
2026-05-07 01:56:53 +00:00
Nikos Mavrogiannopoulos 22bbad4eb5 worker: add per-worker memory limit via RLIMIT_DATA
Introduce a per-worker heap cap as defense-in-depth against
memory-exhaustion DoS attacks. The limit uses RLIMIT_DATA rather
than RLIMIT_AS: since Linux 4.7 RLIMIT_DATA covers brk and private
anonymous mmap regions, i.e, the paths used by malloc and talloc, while
ignoring shared-library file mappings that inflate RLIMIT_AS without
reflecting actual allocation.

This aligns with haproxy's handling. See also:
https://github.com/torvalds/linux/commit/84638335900f1995495838fe1bd4870c43ec1f67
https://sources.debian.org/src/haproxy/3.2.17-1/src/limits.c?hl=486#L486
https://www.kernel.org/doc/html/latest/mm/overcommit-accounting.html

The cap is computed at worker startup by reading the data+stack field
from /proc/self/statm.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-06 13:54:40 +02: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 7efa74f8e8 protobuf files were removed from the repository
This is a follow-up to a65f2c22a2
which did not actually remove the files.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-03 19:15:55 +02:00
Nikos Mavrogiannopoulos 8e0f7f460a Merge branch 'tmp-llhttp_cb' into 'master'
llhttp callbacks should return -1 on error

See merge request openconnect/ocserv!537
2026-05-03 17:05:13 +00:00
Nikos Mavrogiannopoulos 8913ffadff doc: updated for nft/iptables dependencies
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-02 18:49:43 +02:00
Nikos Mavrogiannopoulos 4c85218f41 .gitignore: removed leftovers from autotools
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-02 17:21:42 +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 dcb1b8d24e Merge branch 'tmp-prefer-nft' into 'master'
meson: nftables is preferred unless only iptables is found

See merge request openconnect/ocserv!531
2026-05-02 15:09:43 +00: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
Nikos Mavrogiannopoulos dda2015aa4 meson: nftables is preferred unless iptables is explicitly requested
Relates: #709

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-01 22:17:04 +02:00
Nikos Mavrogiannopoulos c41b6d52de Merge branch 'tmp-CID-645850' into 'master'
Fix new Coverity Scan defect

See merge request openconnect/ocserv!530
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
Nikos Mavrogiannopoulos ac5ee6a10b Merge branch 'type-limits-warning' into 'master'
Fix compiler warning when PAM/RADIUS are disabled

See merge request openconnect/ocserv!529
2026-05-01 14:12:10 +00:00
Nikos Mavrogiannopoulos 4334978fd6 Merge branch 'tunnel-all-dns' into 'master'
Fix tunnel-all-dns ignored in user config

Closes #708

See merge request openconnect/ocserv!527
2026-04-27 03:54:29 +00: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 5137ba4309 ai: add AI policy
CONTRIBUTING.md: new AI Assistance Policy section stating that AI use is
assumed and requires no disclosure, that human accountability is what
matters, and that reviewers may request additional explanation for
submissions showing signs of unchecked generation.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-25 12:08:32 +02:00
Nikos Mavrogiannopoulos 855966cd95 ai: add AI guidance, personas
Introduce a structured AI assistance framework for the project:

- AGENTS.md: single, comprehensive AI guidance file for all tools
  (Claude Code, Codex, Copilot, Cursor). Covers the privilege-separation
  architecture invariant, build/test instructions, code style (including
  a rule against deep preprocessor conditionals), memory allocator policy,
  IPC modification procedure, module-specific doc pointers, and a
  contribution checklist split into agent-runnable and human-judgment items.
  Includes a security disclosure gate that redirects potential vulnerability
  reports to the confidential issue tracker before any public MR is opened.

- contrib/ai/personas/ocserv-core-dev.md: maintainer-facing persona with
  project-specific protocols for anti-hallucination (GnuTLS/protobuf/seccomp
  APIs), memory safety (talloc-first, gnutls_malloc exception), a taxonomy
  of ocserv-specific vulnerability classes, and a self-verification protocol
  that distinguishes what an agent can check automatically from what requires
  human judgment.

- contrib/ai/personas/ocserv-contributor.md: external-contributor-facing
  persona with mandatory architecture orientation, a prominent security
  disclosure gate, five hard guardrails (privilege boundary, syscall
  portability, GnuTLS-only, protobuf regeneration, talloc), and a
  step-by-step workflow for features, bug fixes, and security fixes.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-25 12:08:32 +02:00
Nikos Mavrogiannopoulos a65f2c22a2 protobuf source files are generated during release
Protobuf files are removed from the repository and are only
auto-generated during dist.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-23 19:21:27 +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 112afa683c config: treat expose-iroutes as a normal configuration option
That is store it in VhostConfig and avoid manual clearing of it.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-22 20:29: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 1228688fb2 Merge branch 'tmp-rfc1123' into 'master'
valid_hostname: enhance to cover RFC 1123 requirements

See merge request openconnect/ocserv!525
2026-04-22 11:20:05 +00:00
Nikos Mavrogiannopoulos caacc92c28 Merge branch 'doc-user-config' into 'master'
doc: clarify reload behavior for per-user/group configs

See merge request openconnect/ocserv!526
2026-04-21 18:58:01 +00:00
Nikos Mavrogiannopoulos 745d7883be design.md: include auth state in the diagram
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-21 19:19:32 +02:00
Nikos Mavrogiannopoulos 56055a2ed0 Merge branch 'udp-desync' into 'master'
Do not forward UDP until client is authenticated

Closes #706

See merge request openconnect/ocserv!522
2026-04-21 16:42:35 +00: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
Nikos Mavrogiannopoulos 0f7640bcea Merge branch 'tmp-claude' into 'master'
RFC 952 prohibits trailing hyphen

See merge request openconnect/ocserv!523
2026-04-18 13:43:36 +00:00
Nikos Mavrogiannopoulos c0e3aa6c5c Merge branch 'tmp-disable-adaptive-rate-limit' into 'master'
Add check to disable adaptive rate limiting

Closes #493

See merge request openconnect/ocserv!476
2026-04-18 13:32:07 +00:00
Nikos Mavrogiannopoulos da90b76b07 bumped versions
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-17 00:08:27 +02:00
Nikos Mavrogiannopoulos c520accb84 Released 1.4.2
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-16 23:27:59 +02:00
Nikos Mavrogiannopoulos 537e171664 worker-auth: require exact session_id length in cookie auth reply
recv_cookie_auth_reply() used > instead of != when validating
msg->session_id.len, allowing a shorter-than-expected length to
pass. ws->session_id is always consumed at full sizeof() by the
DTLS session setup; a short fill would leave stale tail bytes.
Align with the stricter != check used in recv_auth_reply().

proxy-proto: abort on zero-length unknown TLV in parse_ssl_tlvs()

An unknown TLV with length == 0 caused an infinite loop: the
AVAIL_HEADER_SIZE macro subtracted nothing and data did not
advance. Detect this and return early, consistent with how
AVAIL_HEADER_SIZE handles other malformed headers.

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-16 23:05:34 +02:00
Nikos Mavrogiannopoulos 5d0a4dadc4 NEWS: documented updates
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-04-16 22:53:37 +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