Index | Thread | Search

From:
Martijn van Duren <openbsd+tech@list.imperialat.at>
Subject:
snmpd: Use a proper engine context
To:
tech@openbsd.org
Date:
Sun, 9 Nov 2025 13:34:59 +0100

Download raw body.

Thread
  • Theo Buehler:

    snmpd: move smi_getticks to appl_sysuptime

  • This diff adds support for persistent engine information.
    Having persistent engine support allows us to properly increment our
    engineBoots on every restart as per RFC. We currently violate the RFC
    in 2 ways:
    - We have engineBoots set to 0, while engineBoots needs to be 1+
    - We use the unix timestamp as our engineTime. This means we don't
      start at 0 as per the RFC, and we're vulnerable for the 2038 unix
      timestamp overflow (engineBoots is a 32 bit integer).
    
    I'm storing the information in a local/remote agnostic way (simply based
    on engineid), so that if we want to properly support remote engines over
    SNMPv3 the fundamentals are there (trap receiving, inform sending,
    proxy, ...)
    
    This diff only contains the snmpd bits. To test this diff
    /var/db/snmpd needs to be manually created. I want to create the
    directory as _snmpd:_snmpd/755. Right now everything is relatively
    open since the data stored there are public secrets. I am not
    expecting us to support creating users via snmp set, or store anything
    else that needs to be a secret, and even if we would I think those
    permissions should be easy enough to fix with a current.html entry.
    However, I'm not attached to the colour of this bikeshed.
    
    Thoughts? Ok?
    
    martijn@
    
    diff 033841d6245fb04a471b798741c0003f8568f241 5e087a57dbc4d05b0a2844969c879a87775b3ab0
    commit - 033841d6245fb04a471b798741c0003f8568f241
    commit + 5e087a57dbc4d05b0a2844969c879a87775b3ab0
    blob - d3b17ba026afe2cb332d3ab85da99b5445e141c6
    blob + 38e3a120ff14245f93d06c25edcfa4efd0c9d267
    --- usr.sbin/snmpd/application_internal.c
    +++ usr.sbin/snmpd/application_internal.c
    @@ -530,14 +530,16 @@ struct ber_element *
     appl_internal_engine(struct ber_oid *oid)
     {
     	if (ober_oid_cmp(&OID(MIB_snmpEngineID, 0), oid) == 0)
    -		return ober_add_nstring(NULL, snmpd_env->sc_engineid.value,
    -		    snmpd_env->sc_engineid.length);
    +		return ober_add_nstring(NULL, snmpd_env->sc_engine.id.value,
    +		    snmpd_env->sc_engine.id.length);
     	else if (ober_oid_cmp(&OID(MIB_snmpEngineBoots, 0), oid) == 0)
    -		return ober_add_integer(NULL, snmpd_env->sc_engine_boots);
    +		return ober_add_integer(NULL, snmpd_env->sc_engine.boots);
     	else if (ober_oid_cmp(&OID(MIB_snmpEngineTime, 0), oid) == 0)
    -		return ober_add_integer(NULL, snmpd_engine_time());
    +		return ober_add_integer(
    +		    NULL, engine_time(&snmpd_env->sc_engine));
     	else if (ober_oid_cmp(&OID(MIB_snmpEngineMaxMsgSize, 0), oid) == 0)
    -		return ober_add_integer(NULL, READ_BUF_SIZE);
    +		return ober_add_integer(NULL,
    +		    snmpd_env->sc_engine.msg_max_size);
     	return NULL;
     }
     
    blob - 7a6d4fe36f628994247b05825f9572c556859d9d
    blob + a417b679f7102c52c6eebe79cdb5c617ca328ee9
    --- usr.sbin/snmpd/engine.c
    +++ usr.sbin/snmpd/engine.c
    @@ -16,11 +16,202 @@
      * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      */
     
    +#include <sys/stat.h>
    +#include <sys/types.h>
    +
    +#include <dirent.h>
    +#include <errno.h>
    +#include <fcntl.h>
    +#include <stdint.h>
    +#include <stdio.h>
    +#include <stdlib.h>
     #include <string.h>
    +#include <unistd.h>
     
    +#include "log.h"
     #include "snmpd.h"
    +#include "snmp.h"
     
    +int engine_cmp(struct engine *, struct engine *);
    +
    +RB_HEAD(engines, engine) engines = RB_INITIALIZER(&engines);
    +RB_PROTOTYPE_STATIC(engines, engine, entry, engine_cmp);
    +
    +void
    +engine_load(void)
    +{
    +	struct engine buf, *engine;
    +	struct timespec mnow, rnow, rmeasure, diff;
    +	char path[PATH_MAX];
    +	DIR *d;
    +	struct dirent *entry;
    +	FILE *f;
    +	int fd;
    +
    +	RB_INSERT(engines, &engines, &snmpd_env->sc_engine);
    +
    +	snprintf(path, sizeof(path), "%s/%s", SNMPD_DB, "engines");
    +	if ((d = opendir(path)) == NULL) {
    +		if (errno != ENOENT)
    +			log_warn("Failed to open %s", path);
    +		return;
    +	}
    +
    +	while ((entry = readdir(d)) != NULL) {
    +		if (entry->d_name[0] == '.')
    +			continue;
    +		if (entry->d_namlen / 2 > sizeof(buf.id.value))
    +			continue;
    +		if (fromhexstr(buf.id.value,
    +		    entry->d_name, entry->d_namlen) == NULL)
    +			continue;
    +		buf.id.length = entry->d_namlen / 2;
    +
    +		if ((fd = openat(dirfd(d), entry->d_name, O_RDONLY)) == -1) {
    +			log_warn("Failed to open db for engine %s",
    +			    entry->d_name);
    +			continue;
    +		}
    +		if ((f = fdopen(fd, "r")) == NULL) {
    +			log_warn("Failed to open db for engine %s",
    +			    entry->d_name);
    +			close(fd);
    +			continue;
    +		}
    +
    +		if (fscanf(f, "%lld.%09ld\n%d\n%d\n%d\n",
    +		    &rmeasure.tv_sec, &rmeasure.tv_nsec,
    +		    &buf.boots, &buf.time, &buf.msg_max_size) != 5 ||
    +		    fgetc(f) != EOF || !feof(f)) {
    +			fclose(f);
    +			continue;
    +		}
    +		fclose(f);
    +
    +		if ((engine = RB_FIND(engines, &engines, &buf)) == NULL) {
    +			if ((engine = calloc(1, sizeof(*engine))) == NULL)
    +				fatal("malloc");
    +			engine->id = buf.id;
    +			RB_INSERT(engines, &engines, engine);
    +		}
    +
    +		if (clock_gettime(CLOCK_MONOTONIC, &mnow) == -1 ||
    +		    clock_gettime(CLOCK_REALTIME, &rnow) == -1)
    +			fatal("clock_gettime");
    +
    +		timespecsub(&rnow, &rmeasure, &diff);
    +
    +		engine->boots = buf.boots;
    +		engine->time = buf.time;
    +		timespecsub(&mnow, &diff, &engine->measure);
    +		engine->msg_max_size = buf.msg_max_size;
    +	}
    +	closedir(d);
    +}
    +
    +void
    +engine_store(struct engine *engine)
    +{
    +	if (proc_compose(&snmpd_env->sc_ps, PROC_PARENT, IMSG_DB_ENGINE,
    +	    engine, sizeof(*engine)) == -1)
    +		fatal("Failed to store engine");
    +}
    +
    +void
    +engine_do_store(struct engine *engine)
    +{
    +	char path[PATH_MAX], tmppath[PATH_MAX], dbpath[PATH_MAX];
    +	struct timespec rnow, mnow, rmeasure, diff;
    +	FILE *f;
    +
    +	snprintf(path, sizeof(path), "%s/engines/%s", SNMPD_DB,
    +	    tohexstr(engine->id.value, engine->id.length));
    +	snprintf(tmppath, sizeof(tmppath), "%s/engines/.%s", SNMPD_DB,
    +	    tohexstr(engine->id.value, engine->id.length));
    +
    +	if ((f = fopen(tmppath, "w")) == NULL) {
    +		if (errno != ENOENT)
    +			fatal("Failed to open db for engine %s",
    +			    tohexstr(engine->id.value, engine->id.length));
    +		snprintf(dbpath, sizeof(dbpath), "%s/engines", SNMPD_DB);
    +		if (mkdir(dbpath, 0755) == -1)
    +			fatal("Failed to create db directory %s", dbpath);
    +		if ((f = fopen(tmppath, "w")) == NULL)
    +			fatal("Failed to open db for engine %s",
    +			    tohexstr(engine->id.value, engine->id.length));
    +	}
    +
    +	/*
    +	 * Use real time
    +	 * It's less consistent, but it survives across reboots
    +	 */
    +	if (clock_gettime(CLOCK_MONOTONIC, &mnow) == -1 ||
    +	    clock_gettime(CLOCK_REALTIME, &rnow) == -1)
    +		fatal("clock_gettime");
    +	timespecsub(&mnow, &engine->measure, &diff);
    +	timespecsub(&rnow, &diff, &rmeasure);
    +
    +	if (fprintf(f, "%lld.%09ld\n%d\n%d\n%d\n",
    +	    rmeasure.tv_sec, rmeasure.tv_nsec,
    +	    engine->boots, engine->time, engine->msg_max_size) < 0 ||
    +	    fclose(f) != 0)
    +		fatal("Failed to write db for engine %s",
    +		    tohexstr(engine->id.value, engine->id.length));
    +
    +	if (rename(tmppath, path) == -1)
    +		fatal("Failed to save db for engine %s",
    +		    tohexstr(engine->id.value, engine->id.length));
    +}
    +
     int
    +engine_in_window(struct engine *engine, int boots, int time)
    +{
    +	struct timespec now, diff;
    +	int min, max, etime;
    +
    +	if (boots < 0 ||	/* Should be 1, but we previously used 0 */
    +	    time < 0)
    +		return 0;
    +	if (engine->boots > boots)
    +		return 0;
    +	if (engine->boots == boots) {
    +		etime = engine_time(engine);
    +		min = etime - SNMP_MAX_TIMEWINDOW >= 0 ?
    +		    etime - SNMP_MAX_TIMEWINDOW : 0;
    +		max = INT_MAX - etime < SNMP_MAX_TIMEWINDOW ? 
    +		    etime + SNMP_MAX_TIMEWINDOW : INT_MAX;
    +		return time > min || time < max ? 1 : 0;
    +	}
    +
    +	if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
    +		fatal("clock_gettime");
    +	timespecsub(&now, &engine->measure, &diff);
    +
    +	/* Assume no more than 1 restart per second */
    +	if ((boots - engine->boots) + time > diff.tv_sec + SNMP_MAX_TIMEWINDOW)
    +		return 0;
    +	return 1;
    +}
    +
    +int32_t
    +engine_time(struct engine *engine)
    +{
    +	struct timespec now, diff;
    +
    +	if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
    +		fatal("clock_gettime");
    +	timespecsub(&now, &engine->measure, &diff);
    +
    +	return engine->time + diff.tv_sec;
    +}
    +
    +int
    +engine_cmp(struct engine *e1, struct engine *e2)
    +{
    +	return engineid_cmp(&e1->id, &e2->id);
    +}
    +
    +int
     engineid_cmp(struct engineid *e1, struct engineid *e2)
     {
     	size_t min;
    @@ -33,3 +224,5 @@ engineid_cmp(struct engineid *e1, struct engineid *e2)
     		return 0;
     	return e1->length < e2->length ? -1 : 1;
     }
    +
    +RB_GENERATE_STATIC(engines, engine, entry, engine_cmp);
    blob - 555bc4050d03fd1f3b54d4ea4a745cb9fa3cfc21
    blob + c4aff3b132d1e6c7f7374dc4db4ef6a0e2069a94
    --- usr.sbin/snmpd/parse.y
    +++ usr.sbin/snmpd/parse.y
    @@ -308,11 +308,11 @@ main		: LISTEN ON listen_udptcp
     			    axm_entry);
     		}
     		| engineid_local {
    -			if (conf->sc_engineid.length != 0) {
    +			if (conf->sc_engine.id.length != 0) {
     				yyerror("Redefinition of engineid");
     				YYERROR;
     			}
    -			conf->sc_engineid = $1;
    +			conf->sc_engine.id = $1;
     		}
     		| READONLY COMMUNITY STRING	{
     			if (strlcpy(conf->sc_rdcommunity, $3,
    @@ -1875,18 +1875,19 @@ parse_config(const char *filename, u_int flags)
     
     
     	/* Must be identical to enginefmt_local:HOSTHASH */
    -	if (conf->sc_engineid.length == 0) {
    +	if (conf->sc_engine.id.length == 0) {
     		if (gethostname(hostname, sizeof(hostname)) == -1)
     			fatal("gethostname");
    -		memcpy(conf->sc_engineid.value, &npen, sizeof(npen));
    -		conf->sc_engineid.length += sizeof(npen);
    -		conf->sc_engineid.value[conf->sc_engineid.length++] =
    +		memcpy(conf->sc_engine.id.value, &npen, sizeof(npen));
    +		conf->sc_engine.id.length += sizeof(npen);
    +		conf->sc_engine.id.value[conf->sc_engine.id.length++] =
     		    SNMP_ENGINEID_FMT_HH;
    -		memcpy(conf->sc_engineid.value + conf->sc_engineid.length,
    +		memcpy(conf->sc_engine.id.value + conf->sc_engine.id.length,
     		    SHA256(hostname, strlen(hostname), sha256),
    -		    sizeof(conf->sc_engineid.value) - conf->sc_engineid.length);
    -		conf->sc_engineid.length = sizeof(conf->sc_engineid.value);
    -		conf->sc_engineid.value[0] |= SNMP_ENGINEID_NEW;
    +		    sizeof(conf->sc_engine.id.value) -
    +		    conf->sc_engine.id.length);
    +		conf->sc_engine.id.length = sizeof(conf->sc_engine.id.value);
    +		conf->sc_engine.id.value[0] |= SNMP_ENGINEID_NEW;
     	}
     
     	/* Setup default listen addresses */
    blob - 85581e7ee9b020d658101571df8bf8a761d7b5f6
    blob + a03638609ecb51531e7722614db3cbb505817be1
    --- usr.sbin/snmpd/snmpd.c
    +++ usr.sbin/snmpd/snmpd.c
    @@ -218,8 +218,6 @@ main(int argc, char *argv[])
     	log_init(debug, LOG_DAEMON);
     	log_setverbose(verbose);
     
    -	env->sc_engine_boots = 0;
    -
     	proc_init(ps, procs, nitems(procs), debug, argc0, argv0, proc_id);
     
     	log_procinit("parent");
    @@ -244,7 +242,10 @@ main(int argc, char *argv[])
     	proc_connect(ps);
     	snmpd_backend(env);
     
    -	if (pledge("stdio dns sendfd proc exec id", NULL) == -1)
    +	if (unveil("/", "x") == -1 ||
    +	    unveil(SNMPD_DB, "rwc") == -1)
    +		fatal("unveil");
    +	if (pledge("stdio dns sendfd proc exec id rpath wpath cpath", NULL) == -1)
     		fatal("pledge");
     
     	event_dispatch();
    @@ -288,9 +289,16 @@ check_child(pid_t pid, const char *pname)
     int
     snmpd_dispatch_snmpe(int fd, struct privsep_proc *p, struct imsg *imsg)
     {
    +	struct engine *engine;
    +
     	switch (imsg->hdr.type) {
     	case IMSG_TRAP_EXEC:
     		return (traphandler_priv_recvmsg(p, imsg));
    +	case IMSG_DB_ENGINE:
    +		IMSG_SIZE_CHECK(imsg, engine);
    +		engine = imsg->data;
    +		engine_do_store(engine);
    +		return 0;
     	default:
     		break;
     	}
    @@ -319,24 +327,6 @@ snmpd_socket_af(struct sockaddr_storage *ss, int type)
     	return fd;
     }
     
    -u_long
    -snmpd_engine_time(void)
    -{
    -	struct timeval	 now;
    -
    -	/*
    -	 * snmpEngineBoots should be stored in a non-volatile storage.
    -	 * snmpEngineTime is the number of seconds since snmpEngineBoots
    -	 * was last incremented. We don't rely on non-volatile storage.
    -	 * snmpEngineBoots is set to zero and snmpEngineTime to the system
    -	 * clock. Hence, the tuple (snmpEngineBoots, snmpEngineTime) is
    -	 * still unique and protects us against replay attacks. It only
    -	 * 'expires' a little bit sooner than the RFC3414 method.
    -	 */
    -	gettimeofday(&now, NULL);
    -	return now.tv_sec;
    -}
    -
     void
     snmpd_backend(struct snmpd *env)
     {
    blob - 5fefd671b71a9cea26758de538109e8e871cb2e1
    blob + 14f17359358d8f3673d358db35da6f34fc44bd3e
    --- usr.sbin/snmpd/snmpd.h
    +++ usr.sbin/snmpd/snmpd.h
    @@ -49,6 +49,7 @@
     #define CONF_FILE		"/etc/snmpd.conf"
     #define SNMPD_BACKEND		"/usr/libexec/snmpd"                                                                                                                                                                                                                                                                        
     #define SNMPD_USER		"_snmpd"
    +#define SNMPD_DB		"/var/db/snmpd"
     #define SNMP_PORT		"161"
     #define SNMPTRAP_PORT		"162"
     
    @@ -68,10 +69,7 @@
     #define SNMP_USM_KEYLEN		64
     #define SNMP_CIPHER_KEYLEN	16
     
    -#define SMALL_READ_BUF_SIZE	1024
     #define READ_BUF_SIZE		65535
    -#define	RT_BUF_SIZE		16384
    -#define	MAX_RTSOCK_BUF		(2 * 1024 * 1024)
     
     #define SNMP_ENGINEID_OLD	0x00
     #define SNMP_ENGINEID_NEW	0x80	/* RFC3411 */
    @@ -90,7 +88,8 @@ enum imsg_type {
     	IMSG_CTL_VERBOSE,
     	IMSG_CTL_PROCFD,
     	IMSG_TRAP_EXEC,
    -	IMSG_AX_FD
    +	IMSG_AX_FD,
    +	IMSG_DB_ENGINE
     };
     
     struct imsgev {
    @@ -184,6 +183,15 @@ struct engineid {
     	size_t			 length;
     };
     
    +struct engine {
    +	struct engineid		 id;
    +	int32_t			 boots;
    +	int32_t			 time;
    +	struct timespec		 measure;
    +	int			 msg_max_size;
    +	RB_ENTRY(engine)	 entry;
    +};
    +
     #define MSG_HAS_AUTH(m)		(((m)->sm_flags & SNMP_MSGFLAG_AUTH) != 0)
     #define MSG_HAS_PRIV(m)		(((m)->sm_flags & SNMP_MSGFLAG_PRIV) != 0)
     #define MSG_SECLEVEL(m)		((m)->sm_flags & SNMP_MSGFLAG_SECMASK)
    @@ -405,13 +413,12 @@ struct snmpd {
     	const char		*sc_confpath;
     	struct addresslist	 sc_addresses;
     	struct axmasterlist	 sc_agentx_masters;
    -	u_int32_t		 sc_engine_boots;
     
     	char			 sc_rdcommunity[SNMPD_MAXCOMMUNITYLEN];
     	char			 sc_rwcommunity[SNMPD_MAXCOMMUNITYLEN];
     	char			 sc_trcommunity[SNMPD_MAXCOMMUNITYLEN];
     
    -	struct engineid		 sc_engineid;
    +	struct engine		 sc_engine;
     
     	struct snmp_stats	 sc_stats;
     	struct snmp_system	 sc_system;
    @@ -448,6 +455,11 @@ struct snmpd	*parse_config(const char *, u_int);
     int		 cmdline_symset(char *);
     
     /* engine.c */
    +void		 engine_load(void);
    +void		 engine_store(struct engine *);
    +void		 engine_do_store(struct engine *);
    +int32_t		 engine_time(struct engine *);
    +int		 engine_in_window(struct engine *, int, int);
     int		 engineid_cmp(struct engineid *, struct engineid *);
     
     /* snmpe.c */
    @@ -471,7 +483,6 @@ void		 smi_debug_elements(struct ber_element *);
     
     /* snmpd.c */
     int		 snmpd_socket_af(struct sockaddr_storage *, int);
    -u_long		 snmpd_engine_time(void);
     
     /* usm.c */
     void		 usm_generate_keys(void);
    blob - 67dcfc523ad4171ad87ab71a2c21aca7cc639187
    blob + 1c61ba3db3a24540ffed4d8352db4b6330bb4333
    --- usr.sbin/snmpd/snmpe.c
    +++ usr.sbin/snmpd/snmpe.c
    @@ -74,6 +74,7 @@ snmpe(struct privsep *ps, struct privsep_proc *p)
     	if ((setlocale(LC_CTYPE, "en_US.UTF-8")) == NULL)
     		fatal("setlocale(LC_CTYPE, \"en_US.UTF-8\")");
     
    +	engine_load();
     	appl();
     
     	/* bind SNMP UDP/TCP sockets */
    @@ -90,6 +91,13 @@ snmpe_init(struct privsep *ps, struct privsep_proc *p,
     	struct snmpd		*env = ps->ps_env;
     	struct address		*h;
     
    +	if (clock_gettime(CLOCK_MONOTONIC, &env->sc_engine.measure) == -1)
    +		fatal("clock_gettime");
    +	env->sc_engine.boots++;
    +	env->sc_engine.time = 0;
    +	env->sc_engine.msg_max_size = READ_BUF_SIZE;
    +	engine_store(&env->sc_engine);
    +
     	usm_generate_keys();
     	appl_init();
     
    @@ -114,7 +122,7 @@ snmpe_init(struct privsep *ps, struct privsep_proc *p,
     		fatal("pledge");
     
     	log_info("snmpe %s: ready",
    -	    tohexstr(env->sc_engineid.value, env->sc_engineid.length));
    +	    tohexstr(env->sc_engine.id.value, env->sc_engine.id.length));
     	trap_init();
     }
     
    @@ -851,7 +859,8 @@ snmpe_encode(struct snmp_message *msg)
     	pdu = epdu = ober_add_sequence(NULL);
     	if (msg->sm_version == SNMP_V3) {
     		if ((epdu = ober_printf_elements(epdu, "xs{",
    -		    snmpd_env->sc_engineid.value, snmpd_env->sc_engineid.length,
    +		    snmpd_env->sc_engine.id.value,
    +		    snmpd_env->sc_engine.id.length,
     		    msg->sm_ctxname)) == NULL) {
     			ober_free_elements(pdu);
     			return -1;
    blob - 11446e02974afa4f87a43e7a8454f110a749b015
    blob + 614c15f37a0c6c0dd879e31e8536610480371903
    --- usr.sbin/snmpd/trap.c
    +++ usr.sbin/snmpd/trap.c
    @@ -107,9 +107,9 @@ trap_send(struct ber_oid *oid, struct ber_element *elm
     			msg->sm_flags = tr->ta_seclevel != -1 ?
     			    tr->ta_seclevel : snmpd_env->sc_min_seclevel;
     			msg->sm_secmodel = SNMP_SEC_USM;
    -			msg->sm_engine_time = snmpd_engine_time();
    -			msg->sm_engine_boots = snmpd_env->sc_engine_boots;
    -			msg->sm_ctxengineid = snmpd_env->sc_engineid;
    +			msg->sm_engine_time = engine_time(&snmpd_env->sc_engine);
    +			msg->sm_engine_boots = snmpd_env->sc_engine.boots;
    +			msg->sm_ctxengineid = snmpd_env->sc_engine.id;
     			(void)strlcpy(msg->sm_username, tr->ta_usmusername,
     			    sizeof(msg->sm_username));
     			msg->sm_user = tr->ta_usmuser;
    blob - b38eaa9d4b02a389eae9ea5f7c8808e4c32cf9e5
    blob + 6a5feaab219a1c1d3d35c020662096686513b2fe
    --- usr.sbin/snmpd/usm.c
    +++ usr.sbin/snmpd/usm.c
    @@ -273,8 +273,7 @@ usm_decode(struct snmp_message *msg, struct ber_elemen
     	char			*engineidv;
     	char			*user;
     	char			*digest, *salt;
    -	u_long			 now;
    -	long long		 engine_boots, engine_time;
    +	long long		 boots, time;
     
     	bzero(&ber, sizeof(ber));
     	offs = ober_getpos(elm);
    @@ -299,7 +298,7 @@ usm_decode(struct snmp_message *msg, struct ber_elemen
     #endif
     
     	if (ober_scanf_elements(usm, "{xiixpxx$", &engineidv, &engineid.length,
    -	    &engine_boots, &engine_time, &user, &userlen, &offs2,
    +	    &boots, &time, &user, &userlen, &offs2,
     	    &digest, &digestlen, &salt, &saltlen) != 0) {
     		*errp = "cannot decode USM params";
     		msg->sm_flags &= SNMP_MSGFLAG_REPORT;
    @@ -307,8 +306,8 @@ usm_decode(struct snmp_message *msg, struct ber_elemen
     	}
     
     	log_debug("USM: engineid '%s', engine boots %lld, engine time %lld, "
    -	    "user '%s'", tohexstr(engineidv, engineid.length), engine_boots,
    -	    engine_time, user);
    +	    "user '%s'", tohexstr(engineidv, engineid.length), boots,
    +	    time, user);
     
     	if (engineid.length > sizeof(engineid.value) ||
     	    userlen > SNMPD_MAXUSERNAMELEN ||
    @@ -320,7 +319,7 @@ usm_decode(struct snmp_message *msg, struct ber_elemen
     	}
     
     	memcpy(engineid.value, engineidv, engineid.length);
    -	if (engineid_cmp(&snmpd_env->sc_engineid, &engineid) != 0) {
    +	if (engineid_cmp(&snmpd_env->sc_engine.id, &engineid) != 0) {
     		*errp = "unknown engine id";
     		msg->sm_usmerr = OIDVAL_usmErrEngineId;
     		stats->snmp_usmnosuchengine++;
    @@ -328,8 +327,8 @@ usm_decode(struct snmp_message *msg, struct ber_elemen
     		goto done;
     	}
     
    -	msg->sm_engine_boots = (u_int32_t)engine_boots;
    -	msg->sm_engine_time = (u_int32_t)engine_time;
    +	msg->sm_engine_boots = boots;
    +	msg->sm_engine_time = time;
     
     	memcpy(msg->sm_username, user, userlen);
     	msg->sm_username[userlen] = '\0';
    @@ -374,11 +373,7 @@ usm_decode(struct snmp_message *msg, struct ber_elemen
     	}
     
     	if (MSG_HAS_AUTH(msg)) {
    -		now = snmpd_engine_time();
    -		if (engine_boots != snmpd_env->sc_engine_boots ||
    -		    engine_time < (long long)(now - SNMP_MAX_TIMEWINDOW) ||
    -		    engine_time > (long long)(now + SNMP_MAX_TIMEWINDOW)) {
    -			*errp = "out of time window";
    +		if (!engine_in_window(&snmpd_env->sc_engine, boots, time)) {
     			msg->sm_usmerr = OIDVAL_usmErrTimeWindow;
     			stats->snmp_usmtimewindow++;
     			goto done;
    @@ -434,10 +429,10 @@ usm_encode(struct snmp_message *msg, struct ber_elemen
     	} else
     		saltlen = 0;
     
    -	msg->sm_engine_boots = (u_int32_t)snmpd_env->sc_engine_boots;
    -	msg->sm_engine_time = (u_int32_t)snmpd_engine_time();
    +	msg->sm_engine_boots = snmpd_env->sc_engine.boots;
    +	msg->sm_engine_time = engine_time(&snmpd_env->sc_engine);
     	if ((a = ober_printf_elements(usm, "xdds",
    -	    snmpd_env->sc_engineid.value, snmpd_env->sc_engineid.length,
    +	    snmpd_env->sc_engine.id.value, snmpd_env->sc_engine.id.length,
     	    msg->sm_engine_boots, msg->sm_engine_time,
     	    msg->sm_username)) == NULL)
     		goto done;
    @@ -718,16 +713,16 @@ usm_passwd2key(const EVP_MD *md, char *passwd, int *ma
     
     	/* Localize the key */
     #ifdef DEBUG
    -	assert(snmpd_env->sc_engineid_len <= SNMPD_MAXENGINEIDLEN);
    +	assert(snmpd_env->sc_engine.id.length <= SNMPD_MAXENGINEIDLEN);
     #endif
     	memcpy(pwbuf, keybuf, dlen);
    -	memcpy(pwbuf + dlen, snmpd_env->sc_engineid.value,
    -	    snmpd_env->sc_engineid.length);
    -	memcpy(pwbuf + dlen + snmpd_env->sc_engineid.length, keybuf, dlen);
    +	memcpy(pwbuf + dlen, snmpd_env->sc_engine.id.value,
    +	    snmpd_env->sc_engine.id.length);
    +	memcpy(pwbuf + dlen + snmpd_env->sc_engine.id.length, keybuf, dlen);
     
     	if (!EVP_DigestInit_ex(ctx, md, NULL) ||
     	    !EVP_DigestUpdate(ctx, pwbuf,
    -	    2 * dlen + snmpd_env->sc_engineid.length) ||
    +	    2 * dlen + snmpd_env->sc_engine.id.length) ||
     	    !EVP_DigestFinal_ex(ctx, keybuf, &dlen)) {
     		EVP_MD_CTX_free(ctx);
     		return NULL;
    
    
  • Theo Buehler:

    snmpd: move smi_getticks to appl_sysuptime