From cde58c22be7a17b7f807439362c4ebe17d4e9437 Mon Sep 17 00:00:00 2001 From: Grigory Trenin Date: Thu, 5 Mar 2026 16:32:38 -0500 Subject: [PATCH] protobuf: use 64-bit signed integers for timestamp fields Signed-off-by: Grigory Trenin --- NEWS | 1 + README.md | 4 +- src/ctl.proto | 8 +-- src/ipc.proto | 14 ++--- tests/meson.build | 2 +- tests/test-year-2038 | 122 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+), 14 deletions(-) create mode 100755 tests/test-year-2038 diff --git a/NEWS b/NEWS index 75568d09..bc2e6270 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ - Replaced autoconf/automake build system with meson (#699) - Added nftables-based ocserv-fw; requires ipcalc-ng/ipcalc (#397) - No longer need to duplicate global options in virtual hosts (#698) +- Timestamps in IPC messages extended to 64-bit for future date support - Fixed a bug where a correct password was rejected after a wrong password attempt in the same session (#323) - Aligned the default values for 'dpd' and 'mobile-dpd' options with diff --git a/README.md b/README.md index 0eeaac6b..e8c3ec7d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ apt-get install -y libpam0g-dev liblz4-dev libseccomp-dev \ libprotobuf-c-dev libtalloc-dev libllhttp-dev protobuf-c-compiler \ gperf iperf3 lcov libuid-wrapper libpam-wrapper libnss-wrapper \ libsocket-wrapper gss-ntlmssp haproxy iputils-ping freeradius \ - gawk gnutls-bin iproute2 jq tcpdump ipcalc + gawk gnutls-bin iproute2 jq tcpdump ipcalc faketime # For manpages apt-get install -y ronn ``` @@ -58,7 +58,7 @@ yum install -y pam-devel lz4-devel libseccomp-devel \ jansson-devel liboath-devel protobuf-c-devel libtalloc-devel \ llhttp-devel protobuf-c gperf iperf3 lcov uid_wrapper \ pam_wrapper nss_wrapper socket_wrapper gssntlmssp haproxy iputils \ - freeradius gawk gnutls-utils iproute jq tcpdump + freeradius gawk gnutls-utils iproute jq tcpdump faketime # For manpages yum install -y rubygem-ronn-ng ``` diff --git a/src/ctl.proto b/src/ctl.proto index a7b2e5c5..1d6af702 100644 --- a/src/ctl.proto +++ b/src/ctl.proto @@ -9,7 +9,7 @@ message status_rep required uint32 pid = 2; repeated uint32 sec_mod_pids = 3; required uint32 active_clients = 4; - required uint32 start_time = 5; + required int64 start_time = 5; required uint32 stored_tls_sessions = 7; required uint32 banned_ips = 8; required uint32 secmod_client_entries = 9; @@ -22,7 +22,7 @@ message status_rep required uint64 kbytes_out = 15; required uint32 min_mtu = 16; required uint32 max_mtu = 17; - required uint32 last_reset = 18; + required int64 last_reset = 18; required uint32 avg_auth_time = 19; required uint32 avg_session_mins = 20; required uint32 max_auth_time = 21; @@ -80,7 +80,7 @@ message user_info_rep required bytes safe_id = 32; /* a value derived from the cookie */ required string vhost = 33; - required uint64 session_start_time = 34; + required int64 session_start_time = 34; } message user_list_rep @@ -116,7 +116,7 @@ message ban_info_rep { required bytes ip = 1; required uint32 score = 2; - optional uint32 expires = 3; + optional int64 expires = 3; } message ban_list_rep diff --git a/src/ipc.proto b/src/ipc.proto index 0cbf809b..d6da5d09 100644 --- a/src/ipc.proto +++ b/src/ipc.proto @@ -83,7 +83,7 @@ message auth_cookie_reply_msg optional string ipv6_local = 10; required bytes sid = 11; - required uint64 session_start_time = 12; + required int64 session_start_time = 12; required bytes secmod_addr = 13; /* additional config */ @@ -137,7 +137,7 @@ message cli_stats_msg required uint64 bytes_in = 1; required uint64 bytes_out = 2; optional bytes sid = 3; - required uint32 uptime = 4; + required int64 uptime = 4; optional string remote_ip = 5; optional string ipv4 = 6; optional string ipv6 = 7; @@ -172,7 +172,7 @@ message worker_startup_msg required CONN_TYPE conn_type = 4; required string remote_ip_str = 5; required string our_ip_str = 6; - required uint64 session_start_time = 7; + required int64 session_start_time = 7; required bytes remote_addr = 8; required bytes our_addr = 9; required bytes sec_auth_init_hmac = 10; @@ -257,7 +257,7 @@ message sec_auth_init_msg optional string device_platform = 12; optional string device_type = 13; optional string vhost = 14; - required uint64 session_start_time = 15; + required int64 session_start_time = 15; required bytes hmac = 16; required string orig_remote_ip = 17; /* if proxy proto is in use this is the original IP that initiated the session */ @@ -320,7 +320,7 @@ message secm_session_open_msg message secm_session_close_msg { required bytes sid = 1; /* cookie */ - optional uint32 uptime = 3; + optional int64 uptime = 3; optional uint64 bytes_in = 4; optional uint64 bytes_out = 5; optional string ipv4 = 6; @@ -355,7 +355,7 @@ message secm_session_reply_msg optional string user_agent = 12; optional string device_platform = 13; optional string device_type = 14; - required uint64 session_start_time = 15; + required int64 session_start_time = 15; } /* internal struct */ @@ -369,7 +369,7 @@ message cookie_int_msg optional string groupname = 6; required string user_agent = 7; required string remote_ip = 8; - required uint32 expires = 9; + required int64 expires = 9; required uint32 status = 10; /* the authentication status (PS_*) */ required bool in_use = 11; required string vhost = 12; diff --git a/tests/meson.build b/tests/meson.build index 09f62623..3f2c4456 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -234,7 +234,7 @@ if get_option('root-tests') root_scripts = [ 'haproxy-connect', 'test-iroute', 'test-multi-cookie', - 'test-pass-script', 'idle-timeout', + 'test-pass-script', 'idle-timeout', 'test-year-2038', 'test-cookie-timeout', 'test-cookie-timeout-2', 'test-explicit-ip', 'test-cookie-invalidation', 'test-user-config', 'test-append-routes', 'test-ban', diff --git a/tests/test-year-2038 b/tests/test-year-2038 new file mode 100755 index 00000000..38836093 --- /dev/null +++ b/tests/test-year-2038 @@ -0,0 +1,122 @@ +#!/bin/bash +# +# Copyright (C) 2026 Grigory Trenin +# +# This file is part of ocserv. +# +# ocserv is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at +# your option) any later version. +# +# ocserv is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# Test ocserv compatibility with year 2038 + +OCCTL="${OCCTL:-../src/occtl/occtl}" +OCCTL_SOCKET=./occtl-faketime-$$.socket +SERV="${SERV:-../src/ocserv}" +srcdir=${srcdir:-.} +PIDFILE=ocserv-pid.$$.tmp +CLIPID=oc-pid.$$.tmp +PATH=${PATH}:/usr/sbin +OUTFILE=occtl-faketime.$$.tmp +USERNAME=test +FAKETIME_CMD=$(which faketime) +FAKETIME_DATE=2038-10-01 + +if test -z "${FAKETIME_CMD}";then + echo "you need faketime utility to run this test" + exit 77 +fi + +if test "${DISABLE_ASAN_BROKEN_TESTS}" = 1;then + echo "libfaketime has known issues with ASAN. Skipping test." + exit 77 +fi + +if test "$(getconf LONG_BIT)" = "32";then + echo "32-bit systems are natively Y2038-limited. Skipping test." + exit 77 +fi + +if test -z ${FAKETIME};then + exec ${FAKETIME_CMD} ${FAKETIME_DATE} $0 $* +fi + +echo "Testing whether ocserv works in year $(date +%Y)... " + +function finish { + set +e + echo " * Cleaning up..." + test -n "${PID}" && kill ${PID} >/dev/null 2>&1 + test -n "${PIDFILE}" && rm -f ${PIDFILE} >/dev/null 2>&1 + test -n "${CLIPID}" && kill $(cat ${CLIPID}) >/dev/null 2>&1 + test -n "${CLIPID}" && rm -f ${CLIPID} >/dev/null 2>&1 + test -n "${CONFIG}" && rm -f ${CONFIG} >/dev/null 2>&1 + rm -f ${OUTFILE} +} + +. `dirname $0`/common.sh +. `dirname $0`/random-net.sh +. `dirname $0`/ns.sh + +eval "${GETPORT}" + +# Run server +update_config test-traffic.config +if test "$VERBOSE" = 1;then + DEBUG="-d 3" +fi + +${CMDNS2} ${SERV} -p ${PIDFILE} -f -c ${CONFIG} ${DEBUG} & PID=$! + +sleep 4 + +# Run client +echo " * Connecting to ${ADDRESS}:${PORT}..." +( echo "test" | ${CMDNS1} ${OPENCONNECT} ${ADDRESS}:${PORT} -u ${USERNAME} --servercert=pin-sha256:xp3scfzy3rOQsv9NcOve/8YVVv+pHr4qNCXEXrNl5s8= -s ${srcdir}/scripts/vpnc-script --pid-file=${CLIPID} --passwd-on-stdin -b ) +if test $? != 0;then + echo "Could not connect to server" + exit 1 +fi + +set -e +echo " * ping remote address" +${CMDNS1} ping -c 3 ${VPNADDR} +set +e + +${OCCTL} -s ${OCCTL_SOCKET} show status >${OUTFILE} +if test $? != 0;then + echo "occtl show status failed!" + cat ${OUTFILE} + exit 1 +fi + +START_DATE=$(awk '/Up since:/ {print $3}' ${OUTFILE}) +if test "${START_DATE}" != "${FAKETIME_DATE}";then + echo "Incorrect server start date. Expected: ${FAKETIME_DATE}, found: ${START_DATE}" + exit 1 +fi + +${OCCTL} -s ${OCCTL_SOCKET} show user ${USERNAME} >${OUTFILE} +if test $? != 0;then + echo "occtl show user ${USERNAME} failed!" + cat ${OUTFILE} + exit 1 +fi + +START_DATE=$(awk '/Session started at:/ {print $4}' ${OUTFILE}) +if test "${START_DATE}" != "${FAKETIME_DATE}";then + echo "Incorrect session start date. Expected: ${FAKETIME_DATE}, found: ${START_DATE}" + exit 1 +fi + +exit 0