-/* $OpenBSD: servconf.c,v 1.437 2025/11/25 00:52:00 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.438 2025/12/05 07:49:45 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
options->per_source_penalty.max_sources6 = -1;
options->per_source_penalty.overflow_mode = -1;
options->per_source_penalty.overflow_mode6 = -1;
- options->per_source_penalty.penalty_crash = -1;
- options->per_source_penalty.penalty_authfail = -1;
- options->per_source_penalty.penalty_noauth = -1;
- options->per_source_penalty.penalty_grace = -1;
- options->per_source_penalty.penalty_refuseconnection = -1;
- options->per_source_penalty.penalty_max = -1;
- options->per_source_penalty.penalty_min = -1;
+ options->per_source_penalty.penalty_crash = -1.0;
+ options->per_source_penalty.penalty_authfail = -1.0;
+ options->per_source_penalty.penalty_noauth = -1.0;
+ options->per_source_penalty.penalty_grace = -1.0;
+ options->per_source_penalty.penalty_refuseconnection = -1.0;
+ options->per_source_penalty.penalty_max = -1.0;
+ options->per_source_penalty.penalty_min = -1.0;
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
if (options->per_source_penalty.overflow_mode6 == -1)
options->per_source_penalty.overflow_mode6 = options->per_source_penalty.overflow_mode;
- if (options->per_source_penalty.penalty_crash == -1)
- options->per_source_penalty.penalty_crash = 90;
- if (options->per_source_penalty.penalty_grace == -1)
- options->per_source_penalty.penalty_grace = 10;
- if (options->per_source_penalty.penalty_authfail == -1)
- options->per_source_penalty.penalty_authfail = 5;
- if (options->per_source_penalty.penalty_noauth == -1)
- options->per_source_penalty.penalty_noauth = 1;
- if (options->per_source_penalty.penalty_refuseconnection == -1)
- options->per_source_penalty.penalty_refuseconnection = 10;
- if (options->per_source_penalty.penalty_min == -1)
- options->per_source_penalty.penalty_min = 15;
- if (options->per_source_penalty.penalty_max == -1)
- options->per_source_penalty.penalty_max = 600;
+ if (options->per_source_penalty.penalty_crash < 0.0)
+ options->per_source_penalty.penalty_crash = 90.0;
+ if (options->per_source_penalty.penalty_grace < 0.0)
+ options->per_source_penalty.penalty_grace = 10.0;
+ if (options->per_source_penalty.penalty_authfail < 0.0)
+ options->per_source_penalty.penalty_authfail = 5.0;
+ if (options->per_source_penalty.penalty_noauth < 0.0)
+ options->per_source_penalty.penalty_noauth = 1.0;
+ if (options->per_source_penalty.penalty_refuseconnection < 0.0)
+ options->per_source_penalty.penalty_refuseconnection = 10.0;
+ if (options->per_source_penalty.penalty_min < 0.0)
+ options->per_source_penalty.penalty_min = 15.0;
+ if (options->per_source_penalty.penalty_max < 0.0)
+ options->per_source_penalty.penalty_max = 600.0;
if (options->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
{
char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword;
int cmdline = 0, *intptr, value, value2, value3, n, port, oactive, r;
+ double dvalue, *doubleptr = NULL;
int ca_only = 0, found = 0;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
const char *q = NULL;
found = 1;
+ intptr = NULL;
+ doubleptr = NULL;
value = -1;
value2 = 0;
/* Allow no/yes only in first position */
options->per_source_penalty.enabled = value2;
continue;
} else if ((q = strprefix(arg, "crash:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_crash;
+ doubleptr = &options->per_source_penalty.penalty_crash;
} else if ((q = strprefix(arg, "authfail:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_authfail;
+ doubleptr = &options->per_source_penalty.penalty_authfail;
} else if ((q = strprefix(arg, "noauth:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_noauth;
+ doubleptr = &options->per_source_penalty.penalty_noauth;
} else if ((q = strprefix(arg, "grace-exceeded:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_grace;
+ doubleptr = &options->per_source_penalty.penalty_grace;
} else if ((q = strprefix(arg, "refuseconnection:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_refuseconnection;
+ doubleptr = &options->per_source_penalty.penalty_refuseconnection;
} else if ((q = strprefix(arg, "max:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_max;
+ doubleptr = &options->per_source_penalty.penalty_max;
} else if ((q = strprefix(arg, "min:", 0)) != NULL) {
- intptr = &options->per_source_penalty.penalty_min;
+ doubleptr = &options->per_source_penalty.penalty_min;
} else if ((q = strprefix(arg, "max-sources4:", 0)) != NULL) {
intptr = &options->per_source_penalty.max_sources4;
if ((errstr = atoi_err(q, &value)) != NULL)
fatal("%s line %d: unsupported %s keyword %s",
filename, linenum, keyword, arg);
}
- /* If no value was parsed above, assume it's a time */
- if (value == -1 && (value = convtime(q)) == -1) {
- fatal("%s line %d: invalid %s time value.",
- filename, linenum, keyword);
- }
- if (*activep && *intptr == -1) {
- *intptr = value;
- /* any option implicitly enables penalties */
- options->per_source_penalty.enabled = 1;
+
+ if (doubleptr != NULL) {
+ if ((dvalue = convtime_double(q)) < 0) {
+ fatal("%s line %d: invalid %s time value.",
+ filename, linenum, keyword);
+ }
+ if (*activep && *doubleptr < 0.0) {
+ *doubleptr = dvalue;
+ options->per_source_penalty.enabled = 1;
+ }
+ } else if (intptr != NULL) {
+ if (*activep && *intptr == -1) {
+ *intptr = value;
+ options->per_source_penalty.enabled = 1;
+ }
+ } else {
+ fatal_f("%s line %d: internal error",
+ filename, linenum);
}
}
if (!found) {
printf("\n");
if (o->per_source_penalty.enabled) {
- printf("persourcepenalties crash:%d authfail:%d noauth:%d "
- "grace-exceeded:%d refuseconnection:%d max:%d min:%d "
+ printf("persourcepenalties crash:%f authfail:%f noauth:%f "
+ "grace-exceeded:%f refuseconnection:%f max:%f min:%f "
"max-sources4:%d max-sources6:%d "
"overflow:%s overflow6:%s\n",
o->per_source_penalty.penalty_crash,
*/
struct penalty {
struct xaddr addr;
- time_t expiry;
+ double expiry;
int active;
const char *reason;
RB_ENTRY(penalty) by_addr;
}
static void
-expire_penalties_from_tree(time_t now, const char *t,
+expire_penalties_from_tree(double now, const char *t,
struct penalties_by_expiry *by_expiry,
struct penalties_by_addr *by_addr, size_t *npenaltiesp)
{
}
static void
-expire_penalties(time_t now)
+expire_penalties(double now)
{
expire_penalties_from_tree(now, "ipv4",
&penalties_by_expiry4, &penalties_by_addr4, &npenalties4);
{
struct xaddr addr;
struct penalty find, *penalty;
- time_t now;
+ double now;
int bits, max_sources, overflow_mode;
char addr_s[NI_MAXHOST];
struct penalties_by_addr *by_addr;
return 1;
}
}
- now = monotime();
+ now = monotime_double();
expire_penalties(now);
by_addr = addr.af == AF_INET ?
&penalties_by_addr4 : &penalties_by_addr6;
{
struct xaddr masked;
struct penalty *penalty = NULL, *existing = NULL;
- time_t now;
- int bits, penalty_secs, max_sources = 0, overflow_mode;
+ double now;
+ int bits, max_sources = 0, overflow_mode;
+ double penalty_secs;
char addrnetmask[NI_MAXHOST + 4];
const char *reason = NULL, *t;
size_t *npenaltiesp = NULL;
default:
fatal_f("internal error: unknown penalty %d", penalty_type);
}
+
+ if (penalty_secs <= 0)
+ return;
+
bits = addr->af == AF_INET ? ipv4_masklen : ipv6_masklen;
if (srclimit_mask_addr(addr, bits, &masked) != 0)
return;
addr_masklen_ntop(addr, bits, addrnetmask, sizeof(addrnetmask));
- now = monotime();
+ now = monotime_double();
expire_penalties(now);
by_expiry = addr->af == AF_INET ?
&penalties_by_expiry4 : &penalties_by_expiry6;
fatal_f("internal error: %s penalty tables corrupt", t);
do_log2_f(penalty->active ?
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE,
- "%s: new %s %s penalty of %d seconds for %s", t,
+ "%s: new %s %s penalty of %f seconds for %s", t,
addrnetmask, penalty->active ? "active" : "deferred",
penalty_secs, reason);
if (++(*npenaltiesp) > (size_t)max_sources)
existing->expiry = now + penalty_cfg.penalty_max;
if (existing->expiry - now > penalty_cfg.penalty_min &&
!existing->active) {
- logit_f("%s: activating %s penalty of %lld seconds for %s",
- addrnetmask, t, (long long)(existing->expiry - now),
- reason);
+ logit_f("%s: activating %s penalty of %.3f seconds for %s",
+ addrnetmask, t, existing->expiry - now, reason);
existing->active = 1;
}
existing->reason = penalty->reason;
struct penalty *p = NULL;
int bits;
char s[NI_MAXHOST + 4];
- time_t now;
+ double now;
- now = monotime();
+ now = monotime_double();
logit("%zu active %s penalties", npenalties, t);
RB_FOREACH(p, penalties_by_expiry, by_expiry) {
bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen;
if (p->expiry < now)
logit("client %s %s (expired)", s, p->reason);
else {
- logit("client %s %s (%llu secs left)", s, p->reason,
- (long long)(p->expiry - now));
+ logit("client %s %s (%.3f secs left)", s, p->reason,
+ p->expiry - now);
}
}
}