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>
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>
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>
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>
Do not forward DTLS packets until the client is authenticated to
prevent the race between AUTH_COOKIE_REP and CMD_UDP_FD messages
on the command socket.
Closes#706
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
Several options had hardcoded or named defaults in apply_default_conf()
that diverged from the values documented in doc/sample.config, leading
to silent behaviour differences for servers running without explicit
configuration.
Relates: #680
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
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>
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>
Freeradius deployments may send groups in the Class attribute using a
comma as separator (e.g. "OU=group1,group2") rather than the semicolon
that ocserv expects by default. Add a group-separator option to the
radius auth configuration to allow this to be changed:
auth = "radius[config=...,group-separator=comma]"
Accepted values are 'semicolon' (default) and 'comma'. The literal
character is not accepted in the config syntax as it conflicts with the
key=value pair delimiter.
Resolves: #428
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
Corrected bugs that prevented a correct password from being accepted after
a wrong one in the same session:
- worker-auth.c: a stale webvpncontext SID cookie caused a reconnecting
client to skip SEC_AUTH_INIT and jump directly to SEC_AUTH_CONT with
a PS_AUTH_FAILED session, which sec-mod rejects.
- auth/plain.c: the 'failed' flag was sticky across retry attempts, so a
correct password following a wrong one was still treated as failure.
Refactored into 'unknown_user' (sticky, for timing protection) and a
local 'wrong_pass' (fresh each call). crypt() is now always called
regardless of whether the user exists to normalise response timing and
prevent username enumeration.
Resolves: #323
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
Add 'terminate user', 'terminate id' and 'terminate session' commands
to occtl that disconnect users and invalidate their session cookies,
preventing reconnection with cached credentials.
Short session IDs are resolved to full safe_id by fetching the cookie
list from sec-mod via CTL_CMD_LIST_COOKIES with prefix matching and
ambiguity detection. Active sessions trigger a warning before
invalidation.
Add integration tests for all three terminate commands.
Signed-off-by: Ivan Verbin <verbinivan@gmail.com>
- Fixes an issue #599 where the session timeout could be bypassed
by reconnecting, such as through a laptop lid close/open cycle.
- Adds 'Session started at:' field to 'occtl show user' output.
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
The hostname validation was rejecting any hostname containg a '.'
character (eg: 'MacBook-Air.local'). This was overly restrictive and
prevented the HOSTNAME environment variable from being populated for
a signifficant number of clients, particularly on macOS.
Strip the domain suffix from such hostnames instead of discarding them.
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
- Increase the width from 14 to 15 characters for 'show bans' and
'show ban points' commands. This ensures proper column alignment
for all valid IPv4 addresses.
- Reduce Score column to 10 characters since UINT_MAX is typically
10 digits.
- Remove unnecessary (unsinged int) cast since 'score' is an actual
unsigned int.
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
Currently 'ocserv' sends session accounting statistics at irregular intervals.
For example, if 'stats-report-time' is set to 60, the actual intervals may vary
between 50, 60, 70, or even 80 seconds. Moreover, these intervals are not
constant - they fluctuate arbitrarily with each statistics update.
This behavior was intentionally introduced to avoid worker processes acting
simultaneously in scenarios like server restarts, where all clients reconnect
at the same time, which could impose heavy load on the secmod process.
However, it causes issues for RADIUS servers that require accurate and
consistent timing.
Summary of changes:
- Apply randomization only once when the timer is initially set up, affecting
only the first timer firing. All subsequent firings will occur at regular
intervals relative to the first one.
- Remove fuzzing from 'interim_update_secs'. This value originates either from
RADIUS or from 'stats-report-time' and should not be altered.
Closes: #630
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
This ensures all subsequent worker communications reach the original
secmod instance that authenticated the client, enabling correct session
accounting after IP address changes.
Closes: #674
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
The previous condition for resetting a ban score was insufficient.
It failed to reset the score for a client that had just exited a ban,
and also incorrectly reset the score of a currently banned client,
causing premature unbans.
Closes: #678
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
Added current timestamp comparison to ensure only active bans
are shown by 'occtl show ip bans'.
Closes: #675.
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>
Existing code used the loop index 'i == 0' to determine when to print
column headers. However, a 'continue' statement inside the loop could
skip the 'i = 0' iteration, causing the headers to never be printed.
Introduced a separate boolean 'header_printed' variable to track
whether headers have been printed.
Closes: #677
Signed-off-by: Grigory Trenin <grigory.trenin@gmail.com>