sync with OpenBSD -current

This commit is contained in:
purplerain 2024-06-09 07:57:03 +00:00
parent 2d0895064a
commit 0d235ae71d
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
70 changed files with 1715 additions and 502 deletions

View file

@ -96,6 +96,10 @@ bool RetCleanPass::runOnMachineFunction(MachineFunction &MF) {
bool modified = false;
// If a setjmp-like function is called by this function, we should not clean
if (MF.exposesReturnsTwice())
return false;
for (auto &MBB : MF) {
std::vector<MachineInstr*> fixups;
bool foundcall = false;

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: X509_STORE_CTX_set_verify.3,v 1.7 2023/08/10 16:15:42 schwarze Exp $
.\" $OpenBSD: X509_STORE_CTX_set_verify.3,v 1.8 2024/06/07 05:51:39 tb Exp $
.\"
.\" Copyright (c) 2021, 2022 Ingo Schwarze <schwarze@openbsd.org>
.\" Copyright (c) 2023 Job Snijders <job@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: August 10 2023 $
.Dd $Mdocdate: June 7 2024 $
.Dt X509_STORE_CTX_SET_VERIFY 3
.Os
.Sh NAME
@ -142,6 +142,28 @@ function provided by the user should check whether a given certificate
was issued using the CA certificate
.Fa issuer ,
and must return 0 on failure and 1 on success.
The default implementation ignores the
.Fa ctx
argument and returns success if and only if
.Xr X509_check_issued 3
returns
.Dv X509_V_OK .
It is important to pay close attention to the order of the
.Fa issuer
and
.Fa subject
arguments.
In
.Xr X509_check_issued 3
the
.Fa issuer
precedes the
.Fa subject
while in
.Fn check_issued
the
.Fa subject
comes first.
.Sh RETURN VALUES
.Fn X509_STORE_CTX_verify_fn
is supposed to return 1 to indicate that the chain is valid
@ -221,3 +243,14 @@ and
.Fn X509_STORE_CTX_get_check_issued
first appeared in OpenSSL 1.1.0 and have been available since
.Ox 7.3 .
.Sh BUGS
The reversal of order of
.Fa subject
and
.Fa issuer
between
.Fn check_issued
and
.Xr X509_check_issued 3
is very confusing.
It has led to bugs and will cause many more.

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: X509_cmp.3,v 1.3 2021/07/02 10:50:39 schwarze Exp $
.\" $OpenBSD: X509_cmp.3,v 1.4 2024/06/07 14:00:09 job Exp $
.\" full merge up to: OpenSSL ea5d4b89 Jun 6 11:42:02 2019 +0800
.\"
.\" This file is a derived work.
@ -65,7 +65,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: July 2 2021 $
.Dd $Mdocdate: June 7 2024 $
.Dt X509_CMP 3
.Os
.Sh NAME
@ -123,8 +123,10 @@
.Fn X509_cmp
compares two X.509 certificates using
.Xr memcmp 3
on the SHA1 hashes of their canonical (DER) representations as generated with
on the hashes of their canonical (DER) representations as generated with
.Xr X509_digest 3 .
The digest function is implementation-specific: LibreSSL uses SHA-512, other
implementations use SHA-1.
.Pp
.Fn X509_NAME_cmp
compares two X.501
@ -172,8 +174,10 @@ structures using
.Fn X509_CRL_match
compares two certificate revocation lists using
.Xr memcmp 3
on the SHA1 hashes of their canonical (DER) representations as generated with
on the hashes of their canonical (DER) representations as generated with
.Xr X509_CRL_digest 3 .
The digest function is implementation-specific: LibreSSL uses SHA-512, other
implementations use SHA-1.
.Sh RETURN VALUES
All these functions return 0 to indicate a match or a non-zero value
to indicate a mismatch.

View file

@ -1,4 +1,4 @@
/* $OpenBSD: x509_verify.c,v 1.69 2024/04/08 23:46:21 beck Exp $ */
/* $OpenBSD: x509_verify.c,v 1.70 2024/06/07 06:21:40 tb Exp $ */
/*
* Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org>
*
@ -528,7 +528,7 @@ x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent,
return (ctx->xsc->check_issued(ctx->xsc, child, parent));
/* XXX key usage */
return X509_check_issued(child, parent) != X509_V_OK;
return X509_check_issued(parent, child) == X509_V_OK;
}
static int

View file

@ -1,4 +1,4 @@
# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org>
# Copyright (c) 2010-2024 Alexander Bluhm <bluhm@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above

View file

@ -1,7 +1,7 @@
#!/usr/bin/perl
# $OpenBSD: remote.pl,v 1.9 2017/12/18 17:01:27 bluhm Exp $
# $OpenBSD: remote.pl,v 1.10 2024/06/08 22:50:40 bluhm Exp $
# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
# Copyright (c) 2010-2024 Alexander Bluhm <bluhm@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@ -272,4 +272,5 @@ sub copy_prefix {
chomp;
print $dst "$prefix: $_\n" if length;
}
$src->clearerr();
}

View file

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.133 2024/01/11 04:50:28 djm Exp $
# $OpenBSD: Makefile,v 1.134 2024/06/06 19:49:25 djm Exp $
OPENSSL?= yes
@ -102,7 +102,8 @@ LTESTS= connect \
connection-timeout \
match-subsystem \
agent-pkcs11-restrict \
agent-pkcs11-cert
agent-pkcs11-cert \
penalty
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
INTEROP_TESTS+= dropbear-ciphers dropbear-kex

View file

@ -0,0 +1,51 @@
# $OpenBSD
# Placed in the Public Domain.
tid="penalties"
grep -vi PerSourcePenalties $OBJ/sshd_config > $OBJ/sshd_config.bak
cp $OBJ/authorized_keys_${USER} $OBJ/authorized_keys_${USER}.bak
conf() {
test -z "$PIDFILE" || stop_sshd
(cat $OBJ/sshd_config.bak ;
echo "PerSourcePenalties $@") > $OBJ/sshd_config
cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER}
start_sshd
}
conf "noauth:10s authfail:6s grace-exceeded:10s min:8s max:20s"
verbose "test connect"
${SSH} -F $OBJ/ssh_config somehost true || fatal "basic connect failed"
verbose "penalty for authentication failure"
# Fail authentication once
cat /dev/null > $OBJ/authorized_keys_${USER}
${SSH} -F $OBJ/ssh_config somehost true && fatal "noauth connect succeeded"
cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER}
# Should be below penalty threshold
${SSH} -F $OBJ/ssh_config somehost true || fatal "authfail not expired"
# Fail authentication again; penalty should activate
cat /dev/null > $OBJ/authorized_keys_${USER}
${SSH} -F $OBJ/ssh_config somehost true && fatal "noauth connect succeeded"
cp $OBJ/authorized_keys_${USER}.bak $OBJ/authorized_keys_${USER}
# These should be refused by the active penalty
${SSH} -F $OBJ/ssh_config somehost true && fail "authfail not rejected"
sleep 5
${SSH} -F $OBJ/ssh_config somehost true && fail "repeat authfail not rejected"
# Penalty should have expired, this should succeed.
sleep 8
${SSH} -F $OBJ/ssh_config somehost true || fail "authfail not expired"
verbose "penalty for no authentication"
${SSHKEYSCAN} -p $PORT 127.0.0.1 >/dev/null 2>&1 || fatal "keyscan failed"
# Repeat attempt should be penalised
${SSHKEYSCAN} -p $PORT 127.0.0.1 >/dev/null 2>&1 && fail "keyscan not rejected"

View file

@ -1,4 +1,4 @@
# $OpenBSD: test-exec.sh,v 1.111 2024/05/17 01:45:22 djm Exp $
# $OpenBSD: test-exec.sh,v 1.114 2024/06/06 19:48:40 djm Exp $
# Placed in the Public Domain.
#SUDO=sudo
@ -265,14 +265,15 @@ export SSH_PKCS11_HELPER SSH_SK_HELPER
stop_sshd ()
{
if [ -f $PIDFILE ]; then
[ -f $PIDFILE ] || return
pid=`$SUDO cat $PIDFILE`
if [ "X$pid" = "X" ]; then
echo no sshd running
else
if [ $pid -lt 2 ]; then
echo bad pid for sshd: $pid
else
echo "no sshd running" 1>&2
return
elif [ $pid -lt 2 ]; then
echo "bad pid for sshd: $pid" 1>&2
return
fi
$SUDO kill $pid
trace "wait for sshd to exit"
i=0;
@ -282,16 +283,13 @@ stop_sshd ()
done
if test -f $PIDFILE; then
if $SUDO kill -0 $pid; then
echo "sshd didn't exit " \
"port $PORT pid $pid"
echo "sshd didn't exit port $PORT pid $pid" 1>&2
else
echo "sshd died without cleanup"
echo "sshd died without cleanup" 1>&2
fi
exit 1
fi
fi
fi
fi
PIDFILE=""
}
# helper
@ -427,6 +425,7 @@ cat << EOF > $OBJ/sshd_config
AcceptEnv _XXX_TEST
Subsystem sftp $SFTPSERVER
SshdSessionPath $SSHD_SESSION
PerSourcePenalties no
EOF
# This may be necessary if /usr/src and/or /usr/obj are group-writable,
@ -689,6 +688,7 @@ start_sshd ()
i=`expr $i + 1`
sleep $i
done
ln -f -s ${logfile} $TEST_SSHD_LOGFILE
test -f $PIDFILE || fatal "no sshd running on port $PORT"
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: cpu.c,v 1.189 2024/05/29 12:21:33 kettenis Exp $ */
/* $OpenBSD: cpu.c,v 1.190 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
@ -1469,6 +1469,9 @@ int cpu_suspended;
void
cpu_suspend_cycle(void)
{
if (cpu_suspend_cycle_fcn)
cpu_suspend_cycle_fcn();
else
cpu_idle_cycle_fcn();
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: intr.c,v 1.58 2024/05/29 12:21:33 kettenis Exp $ */
/* $OpenBSD: intr.c,v 1.59 2024/06/07 06:26:23 jsg Exp $ */
/* $NetBSD: intr.c,v 1.3 2003/03/03 22:16:20 fvdl Exp $ */
/*
@ -559,8 +559,6 @@ intr_handler(struct intrframe *frame, struct intrhand *ih)
return rc;
}
#define CONCAT(x,y) __CONCAT(x,y)
/*
* Fake interrupt handler structures for the benefit of symmetry with
* other interrupt sources, and the benefit of intr_calculatemasks()

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ipifuncs.c,v 1.38 2023/10/30 12:50:59 mvs Exp $ */
/* $OpenBSD: ipifuncs.c,v 1.39 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: ipifuncs.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@ -128,6 +128,9 @@ x86_64_ipi_halt(struct cpu_info *ci)
wbinvd();
for(;;) {
if (cpu_suspend_cycle_fcn)
cpu_suspend_cycle_fcn();
else
__asm volatile("hlt");
}
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: machdep.c,v 1.293 2024/04/29 00:29:48 jsg Exp $ */
/* $OpenBSD: machdep.c,v 1.294 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@ -162,6 +162,7 @@ char machine[] = MACHINE;
*/
void cpu_idle_cycle_hlt(void);
void (*cpu_idle_cycle_fcn)(void) = &cpu_idle_cycle_hlt;
void (*cpu_suspend_cycle_fcn)(void);
/* the following is used externally for concurrent handlers */
int setperf_prio = 0;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: mpbios.c,v 1.31 2022/02/21 11:03:39 mpi Exp $ */
/* $OpenBSD: mpbios.c,v 1.32 2024/06/07 23:19:18 jsg Exp $ */
/* $NetBSD: mpbios.c,v 1.7 2003/05/15 16:32:50 fvdl Exp $ */
/*-
@ -856,14 +856,6 @@ mp_print_eisa_intr(int intr)
}
#endif
#define TAB_UNIT 4
#define TAB_ROUND(a) _TAB_ROUND(a, TAB_UNIT)
#define _TAB_ROUND(a,u) (((a) + (u - 1)) & ~(u - 1))
#define EXTEND_TAB(a,u) (!(_TAB_ROUND(a, u) == _TAB_ROUND((a + 1), u)))
void
mpbios_bus(const u_int8_t *ent, struct device *self)
{

View file

@ -1,4 +1,4 @@
# $OpenBSD: Makefile.amd64,v 1.136 2024/06/05 20:19:26 deraadt Exp $
# $OpenBSD: Makefile.amd64,v 1.137 2024/06/07 05:17:34 deraadt Exp $
# For instructions on building kernels consult the config(8) and options(4)
# manual pages.
@ -73,7 +73,7 @@ CMACHFLAGS+= -mno-retpoline -fcf-protection=none
.endif
.else
CMACHFLAGS+= -mretpoline-external-thunk -fcf-protection=branch
#CMACHFLAGS+= -fret-clean
CMACHFLAGS+= -fret-clean
.endif
.if ${COMPILER_VERSION:Mclang}
NO_INTEGR_AS= -no-integrated-as

View file

@ -1,4 +1,4 @@
/* $OpenBSD: cpu.h,v 1.171 2024/05/29 12:21:33 kettenis Exp $ */
/* $OpenBSD: cpu.h,v 1.172 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@ -420,6 +420,7 @@ void cpu_proc_fork(struct proc *, struct proc *);
int amd64_pa_used(paddr_t);
#define cpu_idle_enter() do { /* nothing */ } while (0)
extern void (*cpu_idle_cycle_fcn)(void);
extern void (*cpu_suspend_cycle_fcn)(void);
#define cpu_idle_cycle() (*cpu_idle_cycle_fcn)()
#define cpu_idle_leave() do { /* nothing */ } while (0)
extern void (*initclock_func)(void);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: i82489var.h,v 1.18 2018/10/04 05:00:40 guenther Exp $ */
/* $OpenBSD: i82489var.h,v 1.19 2024/06/09 03:12:59 jsg Exp $ */
/* $NetBSD: i82489var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
/*-
@ -87,21 +87,6 @@ extern void Xresume_lapic_ltimer(void);
extern void Xrecurse_lapic_ltimer(void);
#define LAPIC_TIMER_VECTOR 0xc0
/*
* 'pin numbers' for local APIC
*/
#define LAPIC_PIN_TIMER 0
#define LAPIC_PIN_PCINT 2
#define LAPIC_PIN_LVINT0 3
#define LAPIC_PIN_LVINT1 4
#define LAPIC_PIN_LVERR 5
extern void Xintr_lapic0(void);
extern void Xintr_lapic2(void);
extern void Xintr_lapic3(void);
extern void Xintr_lapic4(void);
extern void Xintr_lapic5(void);
/*
* Vector used for Xen HVM Event Channel Interrupts.
*/

View file

@ -1,4 +1,4 @@
/* $OpenBSD: db_trace.c,v 1.44 2023/04/26 16:53:58 claudio Exp $ */
/* $OpenBSD: db_trace.c,v 1.45 2024/06/07 10:14:29 jsg Exp $ */
/* $NetBSD: db_trace.c,v 1.18 1996/05/03 19:42:01 christos Exp $ */
/*
@ -68,12 +68,6 @@ struct db_variable *db_eregs = db_regs + nitems(db_regs);
*/
#define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
#define NONE 0
#define TRAP 1
#define SYSCALL 2
#define INTERRUPT 3
#define AST 4
int db_i386_numargs(struct callframe *);
/*

View file

@ -1,4 +1,4 @@
/* $OpenBSD: machdep.c,v 1.671 2024/05/26 13:37:32 kettenis Exp $ */
/* $OpenBSD: machdep.c,v 1.672 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@ -167,6 +167,7 @@ char machine[] = MACHINE;
void (*cpu_idle_leave_fcn)(void) = NULL;
void (*cpu_idle_cycle_fcn)(void) = NULL;
void (*cpu_idle_enter_fcn)(void) = NULL;
void (*cpu_suspend_cycle_fcn)(void);
struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL };

View file

@ -1,4 +1,4 @@
/* $OpenBSD: mpbios.c,v 1.46 2024/05/13 01:15:50 jsg Exp $ */
/* $OpenBSD: mpbios.c,v 1.47 2024/06/07 23:19:18 jsg Exp $ */
/* $NetBSD: mpbios.c,v 1.2 2002/10/01 12:56:57 fvdl Exp $ */
/*-
@ -925,14 +925,6 @@ mp_print_eisa_intr(int intr)
printf(" EISA irq %d", intr);
}
#define TAB_UNIT 4
#define TAB_ROUND(a) _TAB_ROUND(a, TAB_UNIT)
#define _TAB_ROUND(a,u) (((a) + (u - 1)) & ~(u - 1))
#define EXTEND_TAB(a,u) (!(_TAB_ROUND(a, u) == _TAB_ROUND((a + 1), u)))
void
mpbios_bus(const u_int8_t *ent, struct device *self)
{

View file

@ -1,4 +1,4 @@
/* $OpenBSD: cpu.h,v 1.189 2024/05/21 23:16:06 jsg Exp $ */
/* $OpenBSD: cpu.h,v 1.190 2024/06/07 16:53:35 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
@ -375,6 +375,7 @@ extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[];
extern void (*cpu_idle_enter_fcn)(void);
extern void (*cpu_idle_cycle_fcn)(void);
extern void (*cpu_idle_leave_fcn)(void);
extern void (*cpu_suspend_cycle_fcn)(void);
extern int cpuspeed;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: clock.c,v 1.69 2024/05/13 01:15:50 jsg Exp $ */
/* $OpenBSD: clock.c,v 1.70 2024/06/08 00:24:00 jsg Exp $ */
/* $NetBSD: clock.c,v 1.39 1996/05/12 23:11:54 mycroft Exp $ */
/*-
@ -138,9 +138,6 @@ static struct timecounter i8254_timecounter = {
struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
u_long rtclock_tval;
#define SECMIN ((unsigned)60) /* seconds per minute */
#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */
u_int
mc146818_read(void *sc, u_int reg)
{

View file

@ -1,4 +1,4 @@
/* $OpenBSD: acpicpu.c,v 1.92 2022/04/06 18:59:27 naddy Exp $ */
/* $OpenBSD: acpicpu.c,v 1.93 2024/06/07 16:53:35 kettenis Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
* Copyright (c) 2015 Philip Guenther <guenther@openbsd.org>
@ -172,6 +172,7 @@ void acpicpu_add_cstate(struct acpicpu_softc *_sc, int _state, int _method,
int _flags, int _latency, int _power, uint64_t _address);
void acpicpu_set_pdc(struct acpicpu_softc *);
void acpicpu_idle(void);
void acpicpu_suspend(void);
#if 0
void acpicpu_set_throttle(struct acpicpu_softc *, int);
@ -747,6 +748,7 @@ acpicpu_attach(struct device *parent, struct device *self, void *aux)
extern uint32_t acpi_force_bm;
cpu_idle_cycle_fcn = &acpicpu_idle;
cpu_suspend_cycle_fcn = &acpicpu_suspend;
/*
* C3 (and maybe C2?) needs BM_RLD to be set to
@ -1277,3 +1279,66 @@ acpicpu_idle(void)
sc->sc_prev_sleep = (sc->sc_prev_sleep + (sc->sc_prev_sleep >> 1)
+ itime) >> 1;
}
void
acpicpu_suspend(void)
{
extern int cpu_suspended;
struct cpu_info *ci = curcpu();
struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev;
struct acpi_cstate *best, *cx;
if (sc == NULL) {
__asm volatile("sti");
panic("null acpicpu");
}
/*
* Find the lowest usable state.
*/
best = cx = SLIST_FIRST(&sc->sc_cstates);
while ((cx->flags & CST_FLAG_SKIP)) {
if ((cx = SLIST_NEXT(cx, link)) == NULL)
break;
best = cx;
}
switch (best->method) {
default:
case CST_METH_HALT:
__asm volatile("sti; hlt");
break;
case CST_METH_IO_HALT:
inb((u_short)best->address);
__asm volatile("sti; hlt");
break;
case CST_METH_MWAIT:
{
unsigned int hints;
hints = (unsigned)best->address;
/* intel errata AAI65: cflush before monitor */
if (ci->ci_cflushsz != 0 &&
strcmp(cpu_vendor, "GenuineIntel") == 0) {
membar_sync();
clflush((unsigned long)&cpu_suspended);
membar_sync();
}
monitor(&cpu_suspended, 0, 0);
if (cpu_suspended || !CPU_IS_PRIMARY(ci))
mwait(0, hints);
break;
}
case CST_METH_GAS_IO:
inb((u_short)best->address);
/* something harmless to give system time to change state */
acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0);
break;
}
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: audio.c,v 1.206 2023/02/10 14:34:16 visa Exp $ */
/* $OpenBSD: audio.c,v 1.207 2024/06/07 08:48:10 jsg Exp $ */
/*
* Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
*
@ -48,8 +48,6 @@
#define DPRINTFN(n, ...) do {} while(0)
#endif
#define IPL_SOFTAUDIO IPL_SOFTNET
#define DEVNAME(sc) ((sc)->dev.dv_xname)
#define AUDIO_UNIT(n) (minor(n) & 0x0f)
#define AUDIO_DEV(n) (minor(n) & 0xf0)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ufshci.c,v 1.34 2024/06/05 04:58:05 mglocker Exp $ */
/* $OpenBSD: ufshci.c,v 1.35 2024/06/09 03:21:54 jsg Exp $ */
/*
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@ -89,8 +89,6 @@ int ufshci_utr_cmd_sync(struct ufshci_softc *,
struct ufshci_ccb *, struct scsi_xfer *,
uint32_t, uint16_t);
int ufshci_xfer_complete(struct ufshci_softc *);
int ufshci_powerdown(struct ufshci_softc *);
int ufshci_resume(struct ufshci_softc *);
/* SCSI */
int ufshci_ccb_alloc(struct ufshci_softc *, int);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fms.c,v 1.38 2024/05/24 06:02:53 jsg Exp $ */
/* $OpenBSD: fms.c,v 1.39 2024/06/09 05:18:12 jsg Exp $ */
/* $NetBSD: fms.c,v 1.5.4.1 2000/06/30 16:27:50 simonb Exp $ */
/*-
@ -118,9 +118,6 @@ int fms_read_codec(void *, u_int8_t, u_int16_t *);
int fms_write_codec(void *, u_int8_t, u_int16_t);
void fms_reset_codec(void *);
int fms_allocmem(struct fms_softc *, size_t, size_t,
struct fms_dma *);
int
fms_match(struct device *parent, void *match, void *aux)
{

View file

@ -31,7 +31,7 @@
*******************************************************************************/
/* $OpenBSD: if_em_hw.h,v 1.94 2024/05/13 01:15:51 jsg Exp $ */
/* $OpenBSD: if_em_hw.h,v 1.95 2024/06/09 05:18:12 jsg Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* if_em_hw.h
@ -408,8 +408,6 @@ struct em_host_mng_dhcp_cookie{
};
int32_t em_read_part_num(struct em_hw *hw, uint32_t *part_num);
int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer,
uint16_t length);
boolean_t em_check_mng_mode(struct em_hw *hw);
boolean_t em_enable_tx_pkt_filtering(struct em_hw *hw);
int32_t em_read_eeprom(struct em_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_vmx.c,v 1.86 2024/05/21 19:49:06 jan Exp $ */
/* $OpenBSD: if_vmx.c,v 1.87 2024/06/07 08:44:25 jan Exp $ */
/*
* Copyright (c) 2013 Tsubai Masanari
@ -114,6 +114,8 @@ struct vmxnet3_comp_ring {
};
u_int next;
u_int32_t gen;
struct mbuf *sendmp;
struct mbuf *lastmp;
};
struct vmxnet3_txqueue {
@ -160,6 +162,7 @@ struct vmxnet3_softc {
struct vmxnet3_queue *sc_q;
struct intrmap *sc_intrmap;
u_int sc_vrrs;
struct vmxnet3_driver_shared *sc_ds;
u_int8_t *sc_mcast;
struct vmxnet3_upt1_rss_conf *sc_rss;
@ -170,7 +173,7 @@ struct vmxnet3_softc {
#endif
};
#define JUMBO_LEN (1024 * 9)
#define JUMBO_LEN ((16 * 1024) - 1)
#define DMAADDR(map) ((map)->dm_segs[0].ds_addr)
#define READ_BAR0(sc, reg) bus_space_read_4((sc)->sc_iot0, (sc)->sc_ioh0, reg)
@ -273,15 +276,21 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux)
return;
}
/* Vmxnet3 Revision Report and Selection */
ver = READ_BAR1(sc, VMXNET3_BAR1_VRRS);
if ((ver & 0x1) == 0) {
if (ISSET(ver, 0x2)) {
sc->sc_vrrs = 2;
} else if (ISSET(ver, 0x1)) {
sc->sc_vrrs = 1;
} else {
printf(": unsupported hardware version 0x%x\n", ver);
return;
}
WRITE_BAR1(sc, VMXNET3_BAR1_VRRS, 1);
WRITE_BAR1(sc, VMXNET3_BAR1_VRRS, sc->sc_vrrs);
/* UPT Version Report and Selection */
ver = READ_BAR1(sc, VMXNET3_BAR1_UVRS);
if ((ver & 0x1) == 0) {
if (!ISSET(ver, 0x1)) {
printf(": incompatible UPT version 0x%x\n", ver);
return;
}
@ -410,6 +419,11 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux)
ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6;
if (sc->sc_vrrs == 2) {
ifp->if_xflags |= IFXF_LRO;
ifp->if_capabilities |= IFCAP_LRO;
}
#if NVLAN > 0
if (sc->sc_ds->upt_features & UPT1_F_VLAN)
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
@ -704,6 +718,10 @@ vmxnet3_rxfill(struct vmxnet3_rxring *ring)
uint32_t rgen;
uint32_t type = htole32(VMXNET3_BTYPE_HEAD << VMXNET3_RX_BTYPE_S);
/* Second ring just contains packet bodies. */
if (ring->rid == 1)
type = htole32(VMXNET3_BTYPE_BODY << VMXNET3_RX_BTYPE_S);
MUTEX_ASSERT_LOCKED(&ring->mtx);
slots = if_rxr_get(&ring->rxr, NRXDESC);
@ -781,17 +799,17 @@ vmxnet3_rxinit(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
VMX_DMA_LEN(&ring->dmamem));
bus_dmamap_sync(sc->sc_dmat, VMX_DMA_MAP(&ring->dmamem),
0, VMX_DMA_LEN(&ring->dmamem), BUS_DMASYNC_PREWRITE);
}
/* XXX only fill ring 0 */
ring = &rq->cmd_ring[0];
mtx_enter(&ring->mtx);
vmxnet3_rxfill(ring);
mtx_leave(&ring->mtx);
}
comp_ring = &rq->comp_ring;
comp_ring->next = 0;
comp_ring->gen = VMX_RXC_GEN;
comp_ring->sendmp = NULL;
comp_ring->lastmp = NULL;
memset(VMX_DMA_KVA(&comp_ring->dmamem), 0,
VMX_DMA_LEN(&comp_ring->dmamem));
@ -1074,9 +1092,9 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
struct mbuf_list ml = MBUF_LIST_INITIALIZER();
struct mbuf *m;
bus_dmamap_t map;
unsigned int idx, len;
unsigned int idx;
unsigned int next, rgen;
unsigned int done = 0;
unsigned int rid, done[2] = {0, 0};
next = comp_ring->next;
rgen = comp_ring->gen;
@ -1096,11 +1114,14 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
idx = letoh32((rxcd->rxc_word0 >> VMXNET3_RXC_IDX_S) &
VMXNET3_RXC_IDX_M);
if (letoh32((rxcd->rxc_word0 >> VMXNET3_RXC_QID_S) &
VMXNET3_RXC_QID_M) < sc->sc_nqueues)
ring = &rq->cmd_ring[0];
rid = 0;
else
ring = &rq->cmd_ring[1];
rid = 1;
ring = &rq->cmd_ring[rid];
m = ring->m[idx];
KASSERT(m != NULL);
@ -1111,31 +1132,62 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, map);
done++;
done[rid]++;
/*
* A receive descriptor of type 4 which is flaged as start of
* packet, contains the number of TCP segment of an LRO packet.
*/
if (letoh32((rxcd->rxc_word3 & VMXNET3_RXC_TYPE_M) >>
VMXNET3_RXC_TYPE_S) == 4 &&
ISSET(rxcd->rxc_word0, VMXNET3_RXC_SOP)) {
m->m_pkthdr.ph_mss = letoh32(rxcd->rxc_word1 &
VMXNET3_RXC_SEG_CNT_M);
}
m->m_len = letoh32((rxcd->rxc_word2 >> VMXNET3_RXC_LEN_S) &
VMXNET3_RXC_LEN_M);
if (comp_ring->sendmp == NULL) {
comp_ring->sendmp = comp_ring->lastmp = m;
comp_ring->sendmp->m_pkthdr.len = 0;
} else {
CLR(m->m_flags, M_PKTHDR);
comp_ring->lastmp->m_next = m;
comp_ring->lastmp = m;
}
comp_ring->sendmp->m_pkthdr.len += m->m_len;
if (!ISSET(rxcd->rxc_word0, VMXNET3_RXC_EOP))
continue;
/*
* End of Packet
*/
if (letoh32(rxcd->rxc_word2 & VMXNET3_RXC_ERROR)) {
ifp->if_ierrors++;
m_freem(m);
m_freem(comp_ring->sendmp);
comp_ring->sendmp = comp_ring->lastmp = NULL;
continue;
}
len = letoh32((rxcd->rxc_word2 >> VMXNET3_RXC_LEN_S) &
VMXNET3_RXC_LEN_M);
if (len < VMXNET3_MIN_MTU) {
m_freem(m);
if (comp_ring->sendmp->m_pkthdr.len < VMXNET3_MIN_MTU) {
m_freem(comp_ring->sendmp);
comp_ring->sendmp = comp_ring->lastmp = NULL;
continue;
}
m->m_pkthdr.len = m->m_len = len;
vmxnet3_rx_offload(rxcd, m);
if (((letoh32(rxcd->rxc_word0) >> VMXNET3_RXC_RSSTYPE_S) &
VMXNET3_RXC_RSSTYPE_M) != VMXNET3_RXC_RSSTYPE_NONE) {
m->m_pkthdr.ph_flowid = letoh32(rxcd->rxc_word1);
SET(m->m_pkthdr.csum_flags, M_FLOWID);
comp_ring->sendmp->m_pkthdr.ph_flowid =
letoh32(rxcd->rxc_word1);
SET(comp_ring->sendmp->m_pkthdr.csum_flags, M_FLOWID);
}
ml_enqueue(&ml, m);
vmxnet3_rx_offload(rxcd, comp_ring->sendmp);
ml_enqueue(&ml, comp_ring->sendmp);
comp_ring->sendmp = comp_ring->lastmp = NULL;
}
bus_dmamap_sync(sc->sc_dmat, VMX_DMA_MAP(&comp_ring->dmamem),
@ -1144,20 +1196,21 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
comp_ring->next = next;
comp_ring->gen = rgen;
if (done == 0)
return;
for (int i = 0; i < 2; i++) {
if (done[i] == 0)
continue;
ring = &rq->cmd_ring[0];
ring = &rq->cmd_ring[i];
if (ifiq_input(rq->ifiq, &ml))
if_rxr_livelocked(&ring->rxr);
/* XXX Should we (try to) allocate buffers for ring 2 too? */
mtx_enter(&ring->mtx);
if_rxr_put(&ring->rxr, done);
if_rxr_put(&ring->rxr, done[i]);
vmxnet3_rxfill(ring);
mtx_leave(&ring->mtx);
}
}
void
vmxnet3_iff(struct vmxnet3_softc *sc)
@ -1211,6 +1264,8 @@ vmxnet3_iff(struct vmxnet3_softc *sc)
void
vmxnet3_rx_offload(struct vmxnet3_rxcompdesc *rxcd, struct mbuf *m)
{
uint32_t pkts;
/*
* VLAN Offload
*/
@ -1243,6 +1298,45 @@ vmxnet3_rx_offload(struct vmxnet3_rxcompdesc *rxcd, struct mbuf *m)
else if (ISSET(rxcd->rxc_word3, VMXNET3_RXC_UDP))
SET(m->m_pkthdr.csum_flags, M_UDP_CSUM_IN_OK);
}
/*
* TCP Large Receive Offload
*/
pkts = m->m_pkthdr.ph_mss;
m->m_pkthdr.ph_mss = 0;
if (pkts > 1) {
struct ether_extracted ext;
uint32_t paylen;
ether_extract_headers(m, &ext);
paylen = ext.iplen;
if (ext.ip4 || ext.ip6)
paylen -= ext.iphlen;
if (ext.tcp) {
paylen -= ext.tcphlen;
tcpstat_inc(tcps_inhwlro);
tcpstat_add(tcps_inpktlro, pkts);
} else {
tcpstat_inc(tcps_inbadlro);
}
/*
* If we gonna forward this packet, we have to mark it as TSO,
* set a correct mss, and recalculate the TCP checksum.
*/
if (ext.tcp && paylen >= pkts) {
SET(m->m_pkthdr.csum_flags, M_TCP_TSO);
m->m_pkthdr.ph_mss = paylen / pkts;
}
if (ext.tcp &&
ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_IN_OK)) {
SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT);
}
}
}
void
@ -1309,6 +1403,13 @@ vmxnet3_init(struct vmxnet3_softc *sc)
return EIO;
}
/* TCP Large Receive Offload */
if (ISSET(ifp->if_xflags, IFXF_LRO))
SET(sc->sc_ds->upt_features, UPT1_F_LRO);
else
CLR(sc->sc_ds->upt_features, UPT1_F_LRO);
WRITE_CMD(sc, VMXNET3_CMD_SET_FEATURE);
/* Program promiscuous mode and multicast filters. */
vmxnet3_iff(sc);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_vmxreg.h,v 1.9 2020/07/07 01:36:49 dlg Exp $ */
/* $OpenBSD: if_vmxreg.h,v 1.10 2024/06/07 08:44:25 jan Exp $ */
/*
* Copyright (c) 2013 Tsubai Masanari
@ -76,6 +76,7 @@ enum UPT1_RxStats {
#define VMXNET3_CMD_RESET 0xcafe0002 /* reset device */
#define VMXNET3_CMD_SET_RXMODE 0xcafe0003 /* set interface flags */
#define VMXNET3_CMD_SET_FILTER 0xcafe0004 /* set address filter */
#define VMXNET3_CMD_SET_FEATURE 0xcafe0009 /* set features */
#define VMXNET3_CMD_GET_STATUS 0xf00d0000 /* get queue errors */
#define VMXNET3_CMD_GET_STATS 0xf00d0001
#define VMXNET3_CMD_GET_LINK 0xf00d0002 /* get link status */
@ -189,6 +190,7 @@ struct vmxnet3_rxcompdesc {
u_int32_t rxc_word1;
#define VMXNET3_RXC_RSSHASH_M 0xffffffff /* RSS hash value */
#define VMXNET3_RXC_RSSHASH_S 0
#define VMXNET3_RXC_SEG_CNT_M 0x000000ff /* No. of seg. in LRO pkt */
u_int32_t rxc_word2;
#define VMXNET3_RXC_LEN_M 0x00003fff
@ -210,6 +212,7 @@ struct vmxnet3_rxcompdesc {
#define VMXNET3_RXC_FRAGMENT 0x00400000 /* IP fragment */
#define VMXNET3_RXC_FCS 0x00800000 /* frame CRC correct */
#define VMXNET3_RXC_TYPE_M 0x7f000000
#define VMXNET3_RXC_TYPE_S 24
#define VMXNET3_RXC_GEN_M 0x00000001U
#define VMXNET3_RXC_GEN_S 31
} __packed;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: igc_api.h,v 1.2 2022/05/11 06:14:15 kevlo Exp $ */
/* $OpenBSD: igc_api.h,v 1.3 2024/06/09 05:18:12 jsg Exp $ */
/*-
* Copyright 2021 Intel Corp
* Copyright 2021 Rubicon Communications, LLC (Netgate)
@ -20,35 +20,17 @@ int igc_setup_init_funcs(struct igc_hw *, bool);
int igc_init_mac_params(struct igc_hw *);
int igc_init_nvm_params(struct igc_hw *);
int igc_init_phy_params(struct igc_hw *);
int igc_get_bus_info(struct igc_hw *);
void igc_clear_vfta(struct igc_hw *);
void igc_write_vfta(struct igc_hw *, uint32_t, uint32_t);
int igc_force_mac_fc(struct igc_hw *);
int igc_check_for_link(struct igc_hw *);
int igc_reset_hw(struct igc_hw *);
int igc_init_hw(struct igc_hw *);
int igc_setup_link(struct igc_hw *);
int igc_get_speed_and_duplex(struct igc_hw *, uint16_t *,
uint16_t *);
int igc_disable_pcie_master(struct igc_hw *);
void igc_config_collision_dist(struct igc_hw *);
int igc_rar_set(struct igc_hw *, uint8_t *, uint32_t);
uint32_t igc_hash_mc_addr(struct igc_hw *, uint8_t *);
void igc_update_mc_addr_list(struct igc_hw *, uint8_t *, uint32_t);
int igc_check_reset_block(struct igc_hw *);
int igc_get_cable_length(struct igc_hw *);
int igc_validate_mdi_setting(struct igc_hw *);
int igc_get_phy_info(struct igc_hw *);
int igc_phy_hw_reset(struct igc_hw *);
void igc_power_up_phy(struct igc_hw *);
void igc_power_down_phy(struct igc_hw *);
int igc_read_mac_addr(struct igc_hw *);
int igc_read_pba_string(struct igc_hw *, uint8_t *, uint32_t);
void igc_reload_nvm(struct igc_hw *);
int igc_validate_nvm_checksum(struct igc_hw *);
int igc_read_nvm(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
int igc_write_nvm(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
int igc_set_d3_lplu_state(struct igc_hw *, bool);
int igc_set_d0_lplu_state(struct igc_hw *, bool);
#endif /* _IGC_API_H_ */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: igc_mac.h,v 1.1 2021/10/31 14:52:57 patrick Exp $ */
/* $OpenBSD: igc_mac.h,v 1.2 2024/06/09 05:18:12 jsg Exp $ */
/*-
* Copyright 2021 Intel Corp
* Copyright 2021 Rubicon Communications, LLC (Netgate)
@ -12,34 +12,23 @@
void igc_init_mac_ops_generic(struct igc_hw *);
int igc_null_ops_generic(struct igc_hw *);
int igc_null_link_info(struct igc_hw *, uint16_t *, uint16_t *);
bool igc_null_mng_mode(struct igc_hw *);
void igc_null_update_mc(struct igc_hw *, uint8_t *h, uint32_t);
void igc_null_write_vfta(struct igc_hw *, uint32_t a, uint32_t);
int igc_check_for_copper_link_generic(struct igc_hw *);
int igc_config_fc_after_link_up_generic(struct igc_hw *);
int igc_disable_pcie_master_generic(struct igc_hw *);
int igc_force_mac_fc_generic(struct igc_hw *);
int igc_get_auto_rd_done_generic(struct igc_hw *);
int igc_get_bus_info_pcie_generic(struct igc_hw *);
void igc_set_lan_id_single_port(struct igc_hw *);
int igc_get_speed_and_duplex_copper_generic(struct igc_hw *, uint16_t *,
uint16_t *);
void igc_update_mc_addr_list_generic(struct igc_hw *, uint8_t *, uint32_t);
int igc_rar_set_generic(struct igc_hw *, uint8_t *, uint32_t);
int igc_set_fc_watermarks_generic(struct igc_hw *);
int igc_setup_link_generic(struct igc_hw *);
int igc_validate_mdi_setting_crossover_generic(struct igc_hw *);
int igc_hash_mc_addr_generic(struct igc_hw *, uint8_t *);
void igc_clear_hw_cntrs_base_generic(struct igc_hw *);
void igc_clear_vfta_generic(struct igc_hw *);
void igc_init_rx_addrs_generic(struct igc_hw *, uint16_t);
void igc_pcix_mmrbc_workaround_generic(struct igc_hw *);
void igc_put_hw_semaphore_generic(struct igc_hw *);
int igc_check_alt_mac_addr_generic(struct igc_hw *);
void igc_set_pcie_no_snoop_generic(struct igc_hw *, uint32_t);
void igc_write_vfta_generic(struct igc_hw *, uint32_t, uint32_t);
void igc_config_collision_dist_generic(struct igc_hw *);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: igc_nvm.h,v 1.1 2021/10/31 14:52:57 patrick Exp $ */
/* $OpenBSD: igc_nvm.h,v 1.2 2024/06/09 05:18:12 jsg Exp $ */
/*-
* Copyright 2021 Intel Corp
* Copyright 2021 Rubicon Communications, LLC (Netgate)
@ -13,17 +13,11 @@
void igc_init_nvm_ops_generic(struct igc_hw *);
int igc_null_read_nvm(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
void igc_null_nvm_generic(struct igc_hw *);
int igc_null_led_default(struct igc_hw *, uint16_t *);
int igc_null_write_nvm(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
int igc_poll_eerd_eewr_done(struct igc_hw *, int);
int igc_read_mac_addr_generic(struct igc_hw *);
int igc_read_pba_string_generic(struct igc_hw *, uint8_t *, uint32_t);
int igc_read_nvm_eerd(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
int igc_valid_led_default_generic(struct igc_hw *, uint16_t *);
int igc_validate_nvm_checksum_generic(struct igc_hw *);
int igc_write_nvm_spi(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
int igc_update_nvm_checksum_generic(struct igc_hw *);
void igc_release_nvm_generic(struct igc_hw *);
void igc_reload_nvm_generic(struct igc_hw *);
#endif /* _IGC_NVM_H_ */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: igc_phy.h,v 1.2 2022/05/11 06:14:15 kevlo Exp $ */
/* $OpenBSD: igc_phy.h,v 1.3 2024/06/09 05:18:12 jsg Exp $ */
/*-
* Copyright 2021 Intel Corp
* Copyright 2021 Rubicon Communications, LLC (Netgate)
@ -20,13 +20,8 @@ int igc_check_downshift_generic(struct igc_hw *);
int igc_check_reset_block_generic(struct igc_hw *);
int igc_get_phy_id(struct igc_hw *);
int igc_phy_hw_reset_generic(struct igc_hw *);
int igc_phy_reset_dsp_generic(struct igc_hw *);
int igc_set_d3_lplu_state_generic(struct igc_hw *, bool);
int igc_setup_copper_link_generic(struct igc_hw *);
int igc_phy_has_link_generic(struct igc_hw *, uint32_t, uint32_t, bool *);
int igc_determine_phy_address(struct igc_hw *);
int igc_enable_phy_wakeup_reg_access_bm(struct igc_hw *, uint16_t *);
int igc_disable_phy_wakeup_reg_access_bm(struct igc_hw *, uint16_t *);
void igc_power_up_phy_copper(struct igc_hw *);
void igc_power_down_phy_copper(struct igc_hw *);
int igc_read_phy_reg_mdic(struct igc_hw *, uint32_t offset, uint16_t *);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ixgbe.h,v 1.35 2024/04/12 19:27:43 jan Exp $ */
/* $OpenBSD: ixgbe.h,v 1.36 2024/06/09 05:18:12 jsg Exp $ */
/******************************************************************************
@ -268,10 +268,6 @@ int32_t ixgbe_init_hw(struct ixgbe_hw *hw);
enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw);
int32_t ixgbe_identify_phy(struct ixgbe_hw *hw);
void ixgbe_flap_tx_laser(struct ixgbe_hw *hw);
int32_t ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg_wait_to_complete);
int32_t ixgbe_setup_mac_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg_wait_to_complete);
int32_t ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up, bool link_up_wait_to_complete);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pf.c,v 1.1196 2024/05/14 08:26:13 jsg Exp $ */
/* $OpenBSD: pf.c,v 1.1197 2024/06/07 18:24:16 bluhm Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@ -7958,12 +7958,17 @@ done:
switch (pd.naf) {
case AF_INET:
if (pd.dir == PF_IN) {
if (ipforwarding == 0) {
int flags;
if (ip_forwarding == 0) {
ipstat_inc(ips_cantforward);
action = PF_DROP;
break;
}
ip_forward(pd.m, ifp, NULL, 1);
flags = IP_FORWARDING | IP_REDIRECT;
if (ip_directedbcast)
SET(flags, IP_ALLOWBROADCAST);
ip_forward(pd.m, ifp, NULL, flags);
} else
ip_output(pd.m, NULL, NULL, 0, NULL, NULL, 0);
break;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pipex.c,v 1.153 2024/01/23 17:57:21 mvs Exp $ */
/* $OpenBSD: pipex.c,v 1.154 2024/06/07 13:43:21 jsg Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@ -104,9 +104,6 @@ int pipex_prune = 1; /* [I] walk list every seconds */
struct mbuf_queue pipexoutq = MBUF_QUEUE_INITIALIZER(
IFQ_MAXLEN, IPL_SOFTNET);
/* borrow an mbuf pkthdr field */
#define ph_ppp_proto ether_vtag
#ifdef PIPEX_DEBUG
int pipex_debug = 0; /* [A] systcl net.inet.ip.pipex_debug */
#endif

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip_esp.c,v 1.195 2022/05/03 09:18:11 claudio Exp $ */
/* $OpenBSD: ip_esp.c,v 1.196 2024/06/07 13:15:25 jsg Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@ -334,8 +334,6 @@ esp_zeroize(struct tdb *tdbp)
return error;
}
#define MAXBUFSIZ (AH_ALEN_MAX > ESP_MAX_IVS ? AH_ALEN_MAX : ESP_MAX_IVS)
/*
* ESP input processing, called (eventually) through the protocol switch.
*/

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip_icmp.c,v 1.192 2023/09/16 09:33:27 mpi Exp $ */
/* $OpenBSD: ip_icmp.c,v 1.193 2024/06/07 18:24:16 bluhm Exp $ */
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
/*
@ -589,7 +589,7 @@ reflect:
struct sockaddr_in ssrc;
struct rtentry *newrt = NULL;
if (icmp_rediraccept == 0 || ipforwarding == 1)
if (icmp_rediraccept == 0 || ip_forwarding == 1)
goto freeit;
if (code > 3)
goto badcode;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip_input.c,v 1.394 2024/05/08 13:01:30 bluhm Exp $ */
/* $OpenBSD: ip_input.c,v 1.395 2024/06/07 18:24:16 bluhm Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@ -84,10 +84,10 @@
#endif
/* values controllable via sysctl */
int ipforwarding = 0;
int ip_forwarding = 0;
int ipmforwarding = 0;
int ipmultipath = 0;
int ipsendredirects = 1;
int ip_sendredirects = 1;
int ip_dosourceroute = 0;
int ip_defttl = IPDEFTTL;
int ip_mtudisc = 1;
@ -108,8 +108,8 @@ const struct sysctl_bounded_args ipctl_vars[] = {
#ifdef MROUTING
{ IPCTL_MRTPROTO, &ip_mrtproto, SYSCTL_INT_READONLY },
#endif
{ IPCTL_FORWARDING, &ipforwarding, 0, 2 },
{ IPCTL_SENDREDIRECTS, &ipsendredirects, 0, 1 },
{ IPCTL_FORWARDING, &ip_forwarding, 0, 2 },
{ IPCTL_SENDREDIRECTS, &ip_sendredirects, 0, 1 },
{ IPCTL_DEFTTL, &ip_defttl, 0, 255 },
{ IPCTL_DIRECTEDBCAST, &ip_directedbcast, 0, 1 },
{ IPCTL_IPPORT_FIRSTAUTO, &ipport_firstauto, 0, 65535 },
@ -137,8 +137,8 @@ static struct mbuf_queue ipsendraw_mq;
extern struct niqueue arpinq;
int ip_ours(struct mbuf **, int *, int, int);
int ip_dooptions(struct mbuf *, struct ifnet *);
int in_ouraddr(struct mbuf *, struct ifnet *, struct route *);
int ip_dooptions(struct mbuf *, struct ifnet *, int);
int in_ouraddr(struct mbuf *, struct ifnet *, struct route *, int);
int ip_fragcheck(struct mbuf **, int *);
struct mbuf * ip_reass(struct ipqent *, struct ipq *);
@ -431,7 +431,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
#if NPF > 0
struct in_addr odst;
#endif
int pfrdr = 0;
int flags = 0;
KASSERT(*offp == 0);
@ -461,9 +461,15 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
goto bad;
ip = mtod(m, struct ip *);
pfrdr = odst.s_addr != ip->ip_dst.s_addr;
if (odst.s_addr != ip->ip_dst.s_addr)
SET(flags, IP_REDIRECT);
#endif
if (ip_forwarding != 0)
SET(flags, IP_FORWARDING);
if (ip_directedbcast)
SET(flags, IP_ALLOWBROADCAST);
hlen = ip->ip_hl << 2;
/*
@ -472,7 +478,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
* error was detected (causing an icmp message
* to be sent and the original packet to be freed).
*/
if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp)) {
if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp, flags)) {
m = *mp = NULL;
goto bad;
}
@ -483,7 +489,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
goto out;
}
switch(in_ouraddr(m, ifp, &ro)) {
switch(in_ouraddr(m, ifp, &ro, flags)) {
case 2:
goto bad;
case 1:
@ -565,7 +571,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
/*
* Not for us; forward if possible and desirable.
*/
if (ipforwarding == 0) {
if (!ISSET(flags, IP_FORWARDING)) {
ipstat_inc(ips_cantforward);
goto bad;
}
@ -585,7 +591,7 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
}
#endif /* IPSEC */
ip_forward(m, ifp, &ro, pfrdr);
ip_forward(m, ifp, &ro, flags);
*mp = NULL;
rtfree(ro.ro_rt);
return IPPROTO_DONE;
@ -807,7 +813,7 @@ ip_deliver(struct mbuf **mp, int *offp, int nxt, int af, int shared)
#undef IPSTAT_INC
int
in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro)
in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro, int flags)
{
struct rtentry *rt;
struct ip *ip;
@ -837,7 +843,8 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro)
* if it is received on the interface with that address.
*/
if (ISSET(rt->rt_flags, RTF_BROADCAST) &&
(!ip_directedbcast || rt->rt_ifidx == ifp->if_index)) {
(!ISSET(flags, IP_ALLOWBROADCAST) ||
rt->rt_ifidx == ifp->if_index)) {
match = 1;
/* Make sure M_BCAST is set */
@ -876,7 +883,8 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro)
break;
}
}
} else if (ipforwarding == 0 && rt->rt_ifidx != ifp->if_index &&
} else if (!ISSET(flags, IP_FORWARDING) &&
rt->rt_ifidx != ifp->if_index &&
!((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) ||
(m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) {
/* received on wrong interface. */
@ -1150,7 +1158,7 @@ ip_flush(void)
* 0 if the packet should be processed further.
*/
int
ip_dooptions(struct mbuf *m, struct ifnet *ifp)
ip_dooptions(struct mbuf *m, struct ifnet *ifp, int flags)
{
struct ip *ip = mtod(m, struct ip *);
unsigned int rtableid = m->m_pkthdr.ph_rtableid;
@ -1371,8 +1379,8 @@ ip_dooptions(struct mbuf *m, struct ifnet *ifp)
}
}
KERNEL_UNLOCK();
if (forward && ipforwarding > 0) {
ip_forward(m, ifp, NULL, 1);
if (forward && ISSET(flags, IP_FORWARDING)) {
ip_forward(m, ifp, NULL, flags | IP_REDIRECT);
return (1);
}
return (0);
@ -1514,7 +1522,7 @@ const u_char inetctlerrmap[PRC_NCMDS] = {
* of codes and types.
*
* If not forwarding, just drop the packet. This could be confusing
* if ipforwarding was zero but some routing protocol was advancing
* if ip_forwarding was zero but some routing protocol was advancing
* us as a gateway to somewhere. However, we must let the routing
* protocol deal with that.
*
@ -1522,7 +1530,7 @@ const u_char inetctlerrmap[PRC_NCMDS] = {
* via a source route.
*/
void
ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt)
ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int flags)
{
struct mbuf mfake, *mcopy;
struct ip *ip = mtod(m, struct ip *);
@ -1588,7 +1596,7 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt)
if ((rt->rt_ifidx == ifp->if_index) &&
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
ipsendredirects && !srcrt &&
ip_sendredirects && !ISSET(flags, IP_REDIRECT) &&
!arpproxy(satosin(rt_key(rt))->sin_addr, m->m_pkthdr.ph_rtableid)) {
if ((ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_netmask) ==
ifatoia(rt->rt_ifa)->ia_net) {
@ -1602,9 +1610,7 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt)
}
}
error = ip_output(m, NULL, ro,
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
NULL, NULL, 0);
error = ip_output(m, NULL, ro, flags | IP_FORWARDING, NULL, NULL, 0);
rt = ro->ro_rt;
if (error)
ipstat_inc(ips_cantforward);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip_output.c,v 1.399 2024/05/16 13:01:04 bluhm Exp $ */
/* $OpenBSD: ip_output.c,v 1.400 2024/06/07 18:24:16 bluhm Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@ -428,7 +428,7 @@ sendit:
#endif
#ifdef IPSEC
if ((flags & IP_FORWARDING) && ipforwarding == 2 &&
if ((flags & IP_FORWARDING) && ip_forwarding == 2 &&
(!ipsec_in_use ||
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) == NULL)) {
error = EHOSTUNREACH;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip_var.h,v 1.117 2024/04/17 20:48:51 bluhm Exp $ */
/* $OpenBSD: ip_var.h,v 1.118 2024/06/07 18:24:16 bluhm Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@ -204,8 +204,9 @@ struct ipoffnxt {
};
/* flags passed to ip_output */
#define IP_FORWARDING 0x1 /* most of ip header exists */
#define IP_RAWOUTPUT 0x2 /* raw ip header exists */
#define IP_FORWARDING 0x0001 /* most of ip header exists */
#define IP_RAWOUTPUT 0x0002 /* raw ip header exists */
#define IP_REDIRECT 0x0004 /* redirected by pf or source route */
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
#define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */
@ -221,11 +222,12 @@ extern int ipport_firstauto; /* min port for port allocation */
extern int ipport_lastauto; /* max port for port allocation */
extern int ipport_hifirstauto; /* min dynamic/private port number */
extern int ipport_hilastauto; /* max dynamic/private port number */
extern int ipforwarding; /* enable IP forwarding */
extern int ip_forwarding; /* enable IP forwarding */
#ifdef MROUTING
extern int ipmforwarding; /* enable multicast forwarding */
#endif
extern int ipmultipath; /* enable multipath routing */
extern int ip_directedbcast; /* accept all broadcast packets */
extern unsigned int la_hold_total;
extern const struct pr_usrreqs rip_usrreqs;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_input.c,v 1.405 2024/04/17 20:48:51 bluhm Exp $ */
/* $OpenBSD: tcp_input.c,v 1.406 2024/06/07 08:02:17 jsg Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@ -106,11 +106,6 @@ int tcp_flush_queue(struct tcpcb *);
#ifdef INET6
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
/* for the packet header length in the mbuf */
#define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len)
#define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ip6_hdr))
#define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip))
#endif /* INET6 */
int tcprexmtthresh = 3;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: in6.c,v 1.266 2024/05/21 15:12:25 florian Exp $ */
/* $OpenBSD: in6.c,v 1.267 2024/06/07 09:48:19 florian Exp $ */
/* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */
/*
@ -549,7 +549,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
struct in6_ifaddr *ia6)
{
int error = 0, hostIsNew = 0, plen = -1;
struct sockaddr_in6 dst6;
struct sockaddr_in6 dst6, gw6;
struct in6_addrlifetime *lt;
struct in6_multi_mship *imm;
struct rtentry *rt;
@ -604,7 +604,13 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
}
if (ifra->ifra_flags & IN6_IFF_AUTOCONF) {
gw6 = ifra->ifra_dstaddr;
memset(&dst6, 0, sizeof(dst6));
} else {
dst6 = ifra->ifra_dstaddr;
memset(&gw6, 0, sizeof(gw6));
}
if (dst6.sin6_family == AF_INET6) {
error = in6_check_embed_scope(&dst6, ifp->if_index);
if (error)
@ -614,6 +620,11 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
(ifp->if_flags & IFF_LOOPBACK)) && plen != 128)
return (EINVAL);
}
if (gw6.sin6_family == AF_INET6) {
error = in6_check_embed_scope(&gw6, ifp->if_index);
if (error)
return error;
}
/* lifetime consistency check */
lt = &ifra->ifra_lifetime;
if (lt->ia6t_pltime > lt->ia6t_vltime)
@ -702,10 +713,10 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
}
if ((ifra->ifra_flags & IN6_IFF_AUTOCONF) &&
dst6.sin6_family == AF_INET6 &&
gw6.sin6_family == AF_INET6 &&
!IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia6->ia_gwaddr.sin6_addr)) {
/* Set or update announcing router */
ia6->ia_gwaddr = dst6;
ia6->ia_gwaddr = gw6;
}
/*

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip6_forward.c,v 1.117 2024/04/16 12:56:39 bluhm Exp $ */
/* $OpenBSD: ip6_forward.c,v 1.118 2024/06/07 18:24:16 bluhm Exp $ */
/* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */
/*
@ -75,7 +75,7 @@
* of codes and types.
*
* If not forwarding, just drop the packet. This could be confusing
* if ipforwarding was zero but some routing protocol was advancing
* if ip6_forwarding was zero but some routing protocol was advancing
* us as a gateway to somewhere. However, we must let the routing
* protocol deal with that.
*

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip6_mroute.c,v 1.141 2024/04/06 14:23:27 bluhm Exp $ */
/* $OpenBSD: ip6_mroute.c,v 1.142 2024/06/07 08:37:59 jsg Exp $ */
/* $NetBSD: ip6_mroute.c,v 1.59 2003/12/10 09:28:38 itojun Exp $ */
/* $KAME: ip6_mroute.c,v 1.45 2001/03/25 08:38:51 itojun Exp $ */
@ -135,34 +135,6 @@ int ip6_mrouter_ver = 0;
int ip6_mrtproto; /* for netstat only */
struct mrt6stat mrt6stat;
#define NO_RTE_FOUND 0x1
#define RTE_FOUND 0x2
/*
* Macros to compute elapsed time efficiently
* Borrowed from Van Jacobson's scheduling code
*/
#define TV_DELTA(a, b, delta) do { \
int xxs; \
\
delta = (a).tv_usec - (b).tv_usec; \
if ((xxs = (a).tv_sec - (b).tv_sec)) { \
switch (xxs) { \
case 2: \
delta += 1000000; \
/* FALLTHROUGH */ \
case 1: \
delta += 1000000; \
break; \
default: \
delta += (1000000 * xxs); \
} \
} \
} while (0)
#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
(a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
int get_sg6_cnt(struct sioc_sg_req6 *, unsigned int);
int get_mif6_cnt(struct sioc_mif_req6 *, unsigned int);
int ip6_mrouter_init(struct socket *, int, int);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ext2fs_vfsops.c,v 1.119 2024/05/12 09:19:54 jsg Exp $ */
/* $OpenBSD: ext2fs_vfsops.c,v 1.120 2024/06/07 09:26:37 jsg Exp $ */
/* $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */
/*
@ -101,10 +101,7 @@ ext2fs_init(struct vfsconf *vfsp)
/*
* Called by main() when ext2fs is going to be mounted as root.
*
* Name is updated by mount(8) after booting.
*/
#define ROOTNAME "root_device"
int
ext2fs_mountroot(void)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: uvm_addr.c,v 1.34 2024/05/13 01:15:53 jsg Exp $ */
/* $OpenBSD: uvm_addr.c,v 1.35 2024/06/07 06:04:43 jsg Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@ -24,8 +24,6 @@
#include <uvm/uvm_addr.h>
#include <sys/pool.h>
/* Max gap between hint allocations. */
#define UADDR_HINT_MAXGAP (4 * PAGE_SIZE)
/* Number of pivots in pivot allocator. */
#define NUM_PIVOTS 16
/*

View file

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.195 2024/05/17 06:11:17 deraadt Exp $ */
/* $OpenBSD: misc.c,v 1.196 2024/06/06 17:15:25 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
@ -2947,3 +2947,19 @@ lib_contains_symbol(const char *path, const char *s)
free(nl[0].n_name);
return ret;
}
int
signal_is_crash(int sig)
{
switch (sig) {
case SIGSEGV:
case SIGBUS:
case SIGTRAP:
case SIGSYS:
case SIGFPE:
case SIGILL:
case SIGABRT:
return 1;
}
return 0;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.108 2024/05/17 00:30:24 djm Exp $ */
/* $OpenBSD: misc.h,v 1.109 2024/06/06 17:15:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -250,6 +250,7 @@ void notify_complete(struct notifier_ctx *, const char *, ...)
typedef void (*sshsig_t)(int);
sshsig_t ssh_signal(int, sshsig_t);
int signal_is_crash(int);
/* On OpenBSD time_t is int64_t which is long long. */
#define SSH_TIME_T_MAX LLONG_MAX

View file

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.239 2024/05/17 06:42:04 jsg Exp $ */
/* $OpenBSD: monitor.c,v 1.240 2024/06/06 17:15:25 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -132,6 +132,7 @@ static char *auth_submethod = NULL;
static u_int session_id2_len = 0;
static u_char *session_id2 = NULL;
static pid_t monitor_child_pid;
int auth_attempted = 0;
struct mon_table {
enum monitor_reqtype type;
@ -248,6 +249,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
authenticated = (monitor_read(ssh, pmonitor,
mon_dispatch, &ent) == 1);
/* Record that auth was attempted to set exit status later */
if ((ent->flags & MON_AUTH) != 0)
auth_attempted = 1;
/* Special handling for multiple required authentications */
if (options.num_auth_methods != 0) {
if (authenticated &&
@ -290,6 +295,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
fatal_f("authentication method name unknown");
debug_f("user %s authenticated by privileged process", authctxt->user);
auth_attempted = 0;
ssh->authctxt = NULL;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.130 2024/05/17 00:30:24 djm Exp $ */
/* $OpenBSD: monitor_wrap.c,v 1.131 2024/06/06 17:15:25 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <errno.h>
#include <pwd.h>
@ -69,6 +70,7 @@
#include "session.h"
#include "servconf.h"
#include "monitor_wrap.h"
#include "srclimit.h"
#include "ssherr.h"
@ -133,6 +135,36 @@ mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
fatal_f("write: %s", strerror(errno));
}
static void
mm_reap(void)
{
int status = -1;
if (!mm_is_monitor())
return;
while (waitpid(pmonitor->m_pid, &status, 0) == -1) {
if (errno == EINTR)
continue;
pmonitor->m_pid = -1;
fatal_f("waitpid: %s", strerror(errno));
}
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) {
debug_f("preauth child exited with status %d",
WEXITSTATUS(status));
cleanup_exit(255);
}
} else if (WIFSIGNALED(status)) {
error_f("preauth child terminated by signal %d",
WTERMSIG(status));
cleanup_exit(signal_is_crash(WTERMSIG(status)) ?
EXIT_CHILD_CRASH : 255);
} else {
error_f("preauth child terminated abnormally");
cleanup_exit(EXIT_CHILD_CRASH);
}
}
void
mm_request_receive(int sock, struct sshbuf *m)
{
@ -145,6 +177,7 @@ mm_request_receive(int sock, struct sshbuf *m)
if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
if (errno == EPIPE) {
debug3_f("monitor fd closed");
mm_reap();
cleanup_exit(255);
}
fatal_f("read: %s", strerror(errno));

View file

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.c,v 1.407 2024/05/17 01:17:40 djm Exp $ */
/* $OpenBSD: servconf.c,v 1.409 2024/06/06 20:25:48 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -145,6 +145,16 @@ initialize_server_options(ServerOptions *options)
options->per_source_max_startups = -1;
options->per_source_masklen_ipv4 = -1;
options->per_source_masklen_ipv6 = -1;
options->per_source_penalty_exempt = NULL;
options->per_source_penalty.enabled = -1;
options->per_source_penalty.max_sources = -1;
options->per_source_penalty.overflow_mode = -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_max = -1;
options->per_source_penalty.penalty_min = -1;
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
@ -377,6 +387,24 @@ fill_default_server_options(ServerOptions *options)
options->per_source_masklen_ipv4 = 32;
if (options->per_source_masklen_ipv6 == -1)
options->per_source_masklen_ipv6 = 128;
if (options->per_source_penalty.enabled == -1)
options->per_source_penalty.enabled = 1;
if (options->per_source_penalty.max_sources == -1)
options->per_source_penalty.max_sources = 65536;
if (options->per_source_penalty.overflow_mode == -1)
options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
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 = 20;
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_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->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
@ -454,6 +482,7 @@ fill_default_server_options(ServerOptions *options)
CLEAR_ON_NONE(options->chroot_directory);
CLEAR_ON_NONE(options->routing_domain);
CLEAR_ON_NONE(options->host_key_agent);
CLEAR_ON_NONE(options->per_source_penalty_exempt);
for (i = 0; i < options->num_host_key_files; i++)
CLEAR_ON_NONE(options->host_key_files[i]);
@ -485,6 +514,7 @@ typedef enum {
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms,
sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize,
sPerSourcePenalties, sPerSourcePenaltyExemptList,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
sAcceptEnv, sSetEnv, sPermitTunnel,
@ -601,6 +631,8 @@ static struct {
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
{ "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL },
{ "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL },
{ "persourcepenalties", sPerSourcePenalties, SSHCFG_GLOBAL },
{ "persourcepenaltyexemptlist", sPerSourcePenaltyExemptList, SSHCFG_GLOBAL },
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
@ -1888,6 +1920,89 @@ process_server_config_line_depth(ServerOptions *options, char *line,
options->per_source_max_startups = value;
break;
case sPerSourcePenaltyExemptList:
charptr = &options->per_source_penalty_exempt;
arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (addr_match_list(NULL, arg) != 0) {
fatal("%s line %d: keyword %s "
"invalid address argument.",
filename, linenum, keyword);
}
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sPerSourcePenalties:
while ((arg = argv_next(&ac, &av)) != NULL) {
found = 1;
value = -1;
value2 = 0;
p = NULL;
/* Allow no/yes only in first position */
if (strcasecmp(arg, "no") == 0 ||
(value2 = (strcasecmp(arg, "yes") == 0))) {
if (ac > 0) {
fatal("%s line %d: keyword %s \"%s\" "
"argument must appear alone.",
filename, linenum, keyword, arg);
}
if (*activep &&
options->per_source_penalty.enabled == -1)
options->per_source_penalty.enabled = value2;
continue;
} else if (strncmp(arg, "crash:", 6) == 0) {
p = arg + 6;
intptr = &options->per_source_penalty.penalty_crash;
} else if (strncmp(arg, "authfail:", 9) == 0) {
p = arg + 9;
intptr = &options->per_source_penalty.penalty_authfail;
} else if (strncmp(arg, "noauth:", 7) == 0) {
p = arg + 7;
intptr = &options->per_source_penalty.penalty_noauth;
} else if (strncmp(arg, "grace-exceeded:", 15) == 0) {
p = arg + 15;
intptr = &options->per_source_penalty.penalty_grace;
} else if (strncmp(arg, "max:", 4) == 0) {
p = arg + 4;
intptr = &options->per_source_penalty.penalty_max;
} else if (strncmp(arg, "min:", 4) == 0) {
p = arg + 4;
intptr = &options->per_source_penalty.penalty_min;
} else if (strncmp(arg, "max-sources:", 12) == 0) {
intptr = &options->per_source_penalty.max_sources;
if ((errstr = atoi_err(arg+12, &value)) != NULL)
fatal("%s line %d: %s value %s.",
filename, linenum, keyword, errstr);
} else if (strcmp(arg, "overflow:deny-all") == 0) {
intptr = &options->per_source_penalty.overflow_mode;
value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL;
} else if (strcmp(arg, "overflow:permissive") == 0) {
intptr = &options->per_source_penalty.overflow_mode;
value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
} else {
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(p)) == -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 (!found) {
fatal("%s line %d: no %s specified",
filename, linenum, keyword);
}
break;
case sMaxAuthTries:
intptr = &options->max_authtries;
goto parse_int;
@ -3012,6 +3127,7 @@ dump_config(ServerOptions *o)
dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
dump_cfg_string(sRDomain, o->routing_domain);
dump_cfg_string(sSshdSessionPath, o->sshd_session_path);
dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
@ -3099,4 +3215,20 @@ dump_config(ServerOptions *o)
if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
printf(" verify-required");
printf("\n");
if (o->per_source_penalty.enabled) {
printf("persourcepenalties crash:%d authfail:%d noauth:%d "
"grace-exceeded:%d max:%d min:%d max-sources:%d "
"overflow:%s\n", o->per_source_penalty.penalty_crash,
o->per_source_penalty.penalty_authfail,
o->per_source_penalty.penalty_noauth,
o->per_source_penalty.penalty_grace,
o->per_source_penalty.penalty_max,
o->per_source_penalty.penalty_min,
o->per_source_penalty.max_sources,
o->per_source_penalty.overflow_mode ==
PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ?
"deny-all" : "permissive");
} else
printf("persourcepenalties no\n");
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.163 2024/05/23 23:47:16 jsg Exp $ */
/* $OpenBSD: servconf.h,v 1.164 2024/06/06 17:15:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -65,6 +65,20 @@ struct listenaddr {
struct addrinfo *addrs;
};
#define PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL 1
#define PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE 2
struct per_source_penalty {
int enabled;
int max_sources;
int overflow_mode;
int penalty_crash;
int penalty_grace;
int penalty_authfail;
int penalty_noauth;
int penalty_max;
int penalty_min;
};
typedef struct {
u_int num_ports;
u_int ports_from_cmdline;
@ -172,6 +186,8 @@ typedef struct {
int per_source_max_startups;
int per_source_masklen_ipv4;
int per_source_masklen_ipv6;
char *per_source_penalty_exempt;
struct per_source_penalty per_source_penalty;
int max_authtries;
int max_sessions;
char *banner; /* SSH-2 banner message */

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020 Darren Tucker <dtucker@openbsd.org>
* Copyright (c) 2024 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -16,11 +17,13 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/tree.h>
#include <limits.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "addr.h"
#include "canohost.h"
@ -28,17 +31,71 @@
#include "misc.h"
#include "srclimit.h"
#include "xmalloc.h"
#include "servconf.h"
#include "match.h"
static int max_children, max_persource, ipv4_masklen, ipv6_masklen;
static struct per_source_penalty penalty_cfg;
static char *penalty_exempt;
/* Per connection state, used to enforce unauthenticated connection limit. */
static struct child_info {
int id;
struct xaddr addr;
} *child;
} *children;
/*
* Penalised addresses, active entries here prohibit connections until expired.
* Entries become active when more than penalty_min seconds of penalty are
* outstanding.
*/
struct penalty {
struct xaddr addr;
time_t expiry;
int active;
const char *reason;
RB_ENTRY(penalty) by_addr;
RB_ENTRY(penalty) by_expiry;
};
static int penalty_addr_cmp(struct penalty *a, struct penalty *b);
static int penalty_expiry_cmp(struct penalty *a, struct penalty *b);
RB_HEAD(penalties_by_addr, penalty) penalties_by_addr;
RB_HEAD(penalties_by_expiry, penalty) penalties_by_expiry;
RB_GENERATE_STATIC(penalties_by_addr, penalty, by_addr, penalty_addr_cmp)
RB_GENERATE_STATIC(penalties_by_expiry, penalty, by_expiry, penalty_expiry_cmp)
static size_t npenalties;
static int
srclimit_mask_addr(const struct xaddr *addr, int bits, struct xaddr *masked)
{
struct xaddr xmask;
/* Mask address off address to desired size. */
if (addr_netmask(addr->af, bits, &xmask) != 0 ||
addr_and(masked, addr, &xmask) != 0) {
debug3_f("%s: invalid mask %d bits", __func__, bits);
return -1;
}
return 0;
}
static int
srclimit_peer_addr(int sock, struct xaddr *addr)
{
struct sockaddr_storage storage;
socklen_t addrlen = sizeof(storage);
struct sockaddr *sa = (struct sockaddr *)&storage;
if (getpeername(sock, sa, &addrlen) != 0)
return 1; /* not remote socket? */
if (addr_sa_to_xaddr(sa, addrlen, addr) != 0)
return 1; /* unknown address family? */
return 0;
}
void
srclimit_init(int max, int persource, int ipv4len, int ipv6len)
srclimit_init(int max, int persource, int ipv4len, int ipv6len,
struct per_source_penalty *penalty_conf, const char *penalty_exempt_conf)
{
int i;
@ -46,25 +103,27 @@ srclimit_init(int max, int persource, int ipv4len, int ipv6len)
ipv4_masklen = ipv4len;
ipv6_masklen = ipv6len;
max_persource = persource;
penalty_cfg = *penalty_conf;
penalty_exempt = penalty_exempt_conf == NULL ?
NULL : xstrdup(penalty_exempt_conf);
if (max_persource == INT_MAX) /* no limit */
return;
debug("%s: max connections %d, per source %d, masks %d,%d", __func__,
max, persource, ipv4len, ipv6len);
if (max <= 0)
fatal("%s: invalid number of sockets: %d", __func__, max);
child = xcalloc(max_children, sizeof(*child));
children = xcalloc(max_children, sizeof(*children));
for (i = 0; i < max_children; i++)
child[i].id = -1;
children[i].id = -1;
RB_INIT(&penalties_by_addr);
RB_INIT(&penalties_by_expiry);
}
/* returns 1 if connection allowed, 0 if not allowed. */
int
srclimit_check_allow(int sock, int id)
{
struct xaddr xa, xb, xmask;
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
struct sockaddr *sa = (struct sockaddr *)&addr;
struct xaddr xa, xb;
int i, bits, first_unused, count = 0;
char xas[NI_MAXHOST];
@ -72,26 +131,19 @@ srclimit_check_allow(int sock, int id)
return 1;
debug("%s: sock %d id %d limit %d", __func__, sock, id, max_persource);
if (getpeername(sock, sa, &addrlen) != 0)
return 1; /* not remote socket? */
if (addr_sa_to_xaddr(sa, addrlen, &xa) != 0)
return 1; /* unknown address family? */
/* Mask address off address to desired size. */
bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen;
if (addr_netmask(xa.af, bits, &xmask) != 0 ||
addr_and(&xb, &xa, &xmask) != 0) {
debug3("%s: invalid mask %d bits", __func__, bits);
if (srclimit_peer_addr(sock, &xa) != 0)
return 1;
bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen;
if (srclimit_mask_addr(&xa, bits, &xb) != 0)
return 1;
}
first_unused = max_children;
/* Count matching entries and find first unused one. */
for (i = 0; i < max_children; i++) {
if (child[i].id == -1) {
if (children[i].id == -1) {
if (i < first_unused)
first_unused = i;
} else if (addr_cmp(&child[i].addr, &xb) == 0) {
} else if (addr_cmp(&children[i].addr, &xb) == 0) {
count++;
}
}
@ -114,8 +166,8 @@ srclimit_check_allow(int sock, int id)
return 0;
/* Connection allowed, store masked address. */
child[first_unused].id = id;
memcpy(&child[first_unused].addr, &xb, sizeof(xb));
children[first_unused].id = id;
memcpy(&children[first_unused].addr, &xb, sizeof(xb));
return 1;
}
@ -130,9 +182,249 @@ srclimit_done(int id)
debug("%s: id %d", __func__, id);
/* Clear corresponding state entry. */
for (i = 0; i < max_children; i++) {
if (child[i].id == id) {
child[i].id = -1;
if (children[i].id == id) {
children[i].id = -1;
return;
}
}
}
static int
penalty_addr_cmp(struct penalty *a, struct penalty *b)
{
return addr_cmp(&a->addr, &b->addr);
/* Addresses must be unique in by_addr, so no need to tiebreak */
}
static int
penalty_expiry_cmp(struct penalty *a, struct penalty *b)
{
if (a->expiry != b->expiry)
return a->expiry < b->expiry ? -1 : 1;
/* Tiebreak on addresses */
return addr_cmp(&a->addr, &b->addr);
}
static void
expire_penalties(time_t now)
{
struct penalty *penalty, *tmp;
/* XXX avoid full scan of tree, e.g. min-heap */
RB_FOREACH_SAFE(penalty, penalties_by_expiry,
&penalties_by_expiry, tmp) {
if (penalty->expiry >= now)
break;
if (RB_REMOVE(penalties_by_expiry, &penalties_by_expiry,
penalty) != penalty ||
RB_REMOVE(penalties_by_addr, &penalties_by_addr,
penalty) != penalty)
fatal_f("internal error: penalty tables corrupt");
free(penalty);
if (npenalties-- == 0)
fatal_f("internal error: npenalties underflow");
}
}
static void
addr_masklen_ntop(struct xaddr *addr, int masklen, char *s, size_t slen)
{
size_t o;
if (addr_ntop(addr, s, slen) != 0) {
strlcpy(s, "UNKNOWN", slen);
return;
}
if ((o = strlen(s)) < slen)
snprintf(s + o, slen - o, "/%d", masklen);
}
int
srclimit_penalty_check_allow(int sock, const char **reason)
{
struct xaddr addr;
struct penalty find, *penalty;
time_t now;
int bits;
char addr_s[NI_MAXHOST];
if (!penalty_cfg.enabled)
return 1;
if (srclimit_peer_addr(sock, &addr) != 0)
return 1;
if (penalty_exempt != NULL) {
if (addr_ntop(&addr, addr_s, sizeof(addr_s)) != 0)
return 1; /* shouldn't happen */
if (addr_match_list(addr_s, penalty_exempt) == 1) {
return 1;
}
}
if (npenalties > (size_t)penalty_cfg.max_sources &&
penalty_cfg.overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) {
*reason = "too many penalised addresses";
return 0;
}
bits = addr.af == AF_INET ? ipv4_masklen : ipv6_masklen;
memset(&find, 0, sizeof(find));
if (srclimit_mask_addr(&addr, bits, &find.addr) != 0)
return 1;
now = monotime();
if ((penalty = RB_FIND(penalties_by_addr,
&penalties_by_addr, &find)) == NULL)
return 1; /* no penalty */
if (penalty->expiry < now) {
expire_penalties(now);
return 1; /* expired penalty */
}
if (!penalty->active)
return 1; /* Penalty hasn't hit activation threshold yet */
*reason = penalty->reason;
return 0;
}
static void
srclimit_remove_expired_penalties(void)
{
struct penalty *p = NULL;
int bits;
char s[NI_MAXHOST + 4];
/* Delete the soonest-to-expire penalties. */
while (npenalties > (size_t)penalty_cfg.max_sources) {
if ((p = RB_MIN(penalties_by_expiry,
&penalties_by_expiry)) == NULL)
break; /* shouldn't happen */
bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen;
addr_masklen_ntop(&p->addr, bits, s, sizeof(s));
debug3_f("overflow, remove %s", s);
if (RB_REMOVE(penalties_by_expiry,
&penalties_by_expiry, p) != p ||
RB_REMOVE(penalties_by_addr, &penalties_by_addr, p) != p)
fatal_f("internal error: penalty tables corrupt");
free(p);
npenalties--;
}
}
void
srclimit_penalise(struct xaddr *addr, int penalty_type)
{
struct xaddr masked;
struct penalty *penalty, *existing;
time_t now;
int bits, penalty_secs;
char addrnetmask[NI_MAXHOST + 4];
const char *reason = NULL;
if (!penalty_cfg.enabled)
return;
if (penalty_exempt != NULL) {
if (addr_ntop(addr, addrnetmask, sizeof(addrnetmask)) != 0)
return; /* shouldn't happen */
if (addr_match_list(addrnetmask, penalty_exempt) == 1) {
debug3_f("address %s is exempt", addrnetmask);
return;
}
}
switch (penalty_type) {
case SRCLIMIT_PENALTY_NONE:
return;
case SRCLIMIT_PENALTY_CRASH:
penalty_secs = penalty_cfg.penalty_crash;
reason = "penalty: caused crash";
break;
case SRCLIMIT_PENALTY_AUTHFAIL:
penalty_secs = penalty_cfg.penalty_authfail;
reason = "penalty: failed authentication";
break;
case SRCLIMIT_PENALTY_NOAUTH:
penalty_secs = penalty_cfg.penalty_noauth;
reason = "penalty: connections without attempting authentication";
break;
case SRCLIMIT_PENALTY_GRACE_EXCEEDED:
penalty_secs = penalty_cfg.penalty_crash;
reason = "penalty: exceeded LoginGraceTime";
break;
default:
fatal_f("internal error: unknown penalty %d", penalty_type);
}
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();
expire_penalties(now);
if (npenalties > (size_t)penalty_cfg.max_sources &&
penalty_cfg.overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) {
verbose_f("penalty table full, cannot penalise %s for %s",
addrnetmask, reason);
return;
}
penalty = xcalloc(1, sizeof(*penalty));
penalty->addr = masked;
penalty->expiry = now + penalty_secs;
penalty->reason = reason;
if ((existing = RB_INSERT(penalties_by_addr, &penalties_by_addr,
penalty)) == NULL) {
/* penalty didn't previously exist */
if (penalty_secs > penalty_cfg.penalty_min)
penalty->active = 1;
if (RB_INSERT(penalties_by_expiry, &penalties_by_expiry,
penalty) != NULL)
fatal_f("internal error: penalty tables corrupt");
verbose_f("%s: new %s penalty of %d seconds for %s",
addrnetmask, penalty->active ? "active" : "deferred",
penalty_secs, reason);
if (++npenalties > (size_t)penalty_cfg.max_sources)
srclimit_remove_expired_penalties(); /* permissive */
return;
}
debug_f("%s penalty for %s already exists, %lld seconds remaining",
existing->active ? "active" : "inactive",
addrnetmask, (long long)(existing->expiry - now));
/* Expiry information is about to change, remove from tree */
if (RB_REMOVE(penalties_by_expiry, &penalties_by_expiry,
existing) != existing)
fatal_f("internal error: penalty tables corrupt (remove)");
/* An entry already existed. Accumulate penalty up to maximum */
existing->expiry += penalty_secs;
if (existing->expiry - now > penalty_cfg.penalty_max)
existing->expiry = now + penalty_cfg.penalty_max;
if (existing->expiry - now > penalty_cfg.penalty_min &&
!existing->active) {
verbose_f("%s: activating penalty of %lld seconds for %s",
addrnetmask, (long long)(existing->expiry - now), reason);
existing->active = 1;
}
existing->reason = penalty->reason;
free(penalty);
/* Re-insert into expiry tree */
if (RB_INSERT(penalties_by_expiry, &penalties_by_expiry,
existing) != NULL)
fatal_f("internal error: penalty tables corrupt (insert)");
}
void
srclimit_penalty_info(void)
{
struct penalty *p = NULL;
int bits;
char s[NI_MAXHOST + 4];
time_t now;
now = monotime();
logit("%zu active penalties", npenalties);
RB_FOREACH(p, penalties_by_expiry, &penalties_by_expiry) {
bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen;
addr_masklen_ntop(&p->addr, bits, s, sizeof(s));
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));
}
}
}

View file

@ -13,6 +13,26 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void srclimit_init(int, int, int, int);
struct xaddr;
struct per_source_penalty;
void srclimit_init(int, int, int, int,
struct per_source_penalty *, const char *);
int srclimit_check_allow(int, int);
void srclimit_done(int);
#define SRCLIMIT_PENALTY_NONE 0
#define SRCLIMIT_PENALTY_CRASH 1
#define SRCLIMIT_PENALTY_AUTHFAIL 2
#define SRCLIMIT_PENALTY_GRACE_EXCEEDED 3
#define SRCLIMIT_PENALTY_NOAUTH 4
/* meaningful exit values, used by sshd listener for penalties */
#define EXIT_LOGIN_GRACE 3 /* login grace period exceeded */
#define EXIT_CHILD_CRASH 4 /* preauth child crashed */
#define EXIT_AUTH_ATTEMPTED 5 /* at least one auth attempt made */
void srclimit_penalise(struct xaddr *, int);
int srclimit_penalty_check_allow(int, const char **);
void srclimit_penalty_info(void);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: sshd-session.c,v 1.2 2024/05/17 02:39:11 jsg Exp $ */
/* $OpenBSD: sshd-session.c,v 1.3 2024/06/06 17:15:25 djm Exp $ */
/*
* SSH2 implementation:
* Privilege Separation:
@ -188,11 +188,7 @@ grace_alarm_handler(int sig)
ssh_signal(SIGTERM, SIG_IGN);
kill(0, SIGTERM);
}
/* Log error and exit. */
sigdie("Timeout before authentication for %s port %d",
ssh_remote_ipaddr(the_active_state),
ssh_remote_port(the_active_state));
_exit(EXIT_LOGIN_GRACE);
}
/* Destroy the host and server keys. They will no longer be needed. */
@ -1220,6 +1216,8 @@ main(int ac, char **av)
ssh_signal(SIGALRM, SIG_DFL);
authctxt->authenticated = 1;
if (startup_pipe != -1) {
/* signal listener that authentication completed successfully */
(void)atomicio(vwrite, startup_pipe, "\001", 1);
close(startup_pipe);
startup_pipe = -1;
}
@ -1338,6 +1336,8 @@ do_ssh2_kex(struct ssh *ssh)
void
cleanup_exit(int i)
{
extern int auth_attempted; /* monitor.c */
if (the_active_state != NULL && the_authctxt != NULL) {
do_cleanup(the_active_state, the_authctxt);
if (privsep_is_preauth &&
@ -1350,5 +1350,8 @@ cleanup_exit(int i)
}
}
}
/* Override default fatal exit value when auth was attempted */
if (i == 255 && auth_attempted)
_exit(EXIT_AUTH_ATTEMPTED);
_exit(i);
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.605 2024/06/01 07:03:37 djm Exp $ */
/* $OpenBSD: sshd.c,v 1.607 2024/06/06 19:50:01 djm Exp $ */
/*
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved.
@ -72,6 +72,7 @@
#include "version.h"
#include "ssherr.h"
#include "sk-api.h"
#include "addr.h"
#include "srclimit.h"
/* Re-exec fds */
@ -120,6 +121,8 @@ struct {
} sensitive_data;
/* This is set to true when a signal is received. */
static volatile sig_atomic_t received_siginfo = 0;
static volatile sig_atomic_t received_sigchld = 0;
static volatile sig_atomic_t received_sighup = 0;
static volatile sig_atomic_t received_sigterm = 0;
@ -127,8 +130,9 @@ static volatile sig_atomic_t received_sigterm = 0;
u_int utmp_len = HOST_NAME_MAX+1;
/*
* startup_pipes/flags are used for tracking children of the listening sshd
* process early in their lifespans. This tracking is needed for three things:
* The early_child/children array below is used for tracking children of the
* listening sshd process early in their lifespans, before they have
* completed authentication. This tracking is needed for four things:
*
* 1) Implementing the MaxStartups limit of concurrent unauthenticated
* connections.
@ -137,14 +141,31 @@ u_int utmp_len = HOST_NAME_MAX+1;
* after it restarts.
* 3) Ensuring that rexec'd sshd processes have received their initial state
* from the parent listen process before handling SIGHUP.
* 4) Tracking and logging unsuccessful exits from the preauth sshd monitor,
* including and especially those for LoginGraceTime timeouts.
*
* Child processes signal that they have completed closure of the listen_socks
* and (if applicable) received their rexec state by sending a char over their
* sock. Child processes signal that authentication has completed by closing
* the sock (or by exiting).
* sock.
*
* Child processes signal that authentication has completed by sending a
* second char over the socket before closing it, otherwise the listener will
* continue tracking the child (and using up a MaxStartups slot) until the
* preauth subprocess exits, whereupon the listener will log its exit status.
* preauth processes will exit with a status of EXIT_LOGIN_GRACE to indicate
* they did not authenticate before the LoginGraceTime alarm fired.
*/
static int *startup_pipes = NULL;
static int *startup_flags = NULL; /* Indicates child closed listener */
struct early_child {
int pipefd;
int early; /* Indicates child closed listener */
char *id; /* human readable connection identifier */
pid_t pid;
struct xaddr addr;
int have_addr;
int status, have_status;
};
static struct early_child *children;
static int children_active;
static int startup_pipe = -1; /* in child */
/* sshd_config buffer */
@ -171,15 +192,257 @@ close_listen_socks(void)
num_listen_socks = 0;
}
/* Allocate and initialise the children array */
static void
child_alloc(void)
{
int i;
children = xcalloc(options.max_startups, sizeof(*children));
for (i = 0; i < options.max_startups; i++) {
children[i].pipefd = -1;
children[i].pid = -1;
}
}
/* Register a new connection in the children array; child pid comes later */
static struct early_child *
child_register(int pipefd, int sockfd)
{
int i, lport, rport;
char *laddr = NULL, *raddr = NULL;
struct early_child *child = NULL;
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
struct sockaddr *sa = (struct sockaddr *)&addr;
for (i = 0; i < options.max_startups; i++) {
if (children[i].pipefd != -1 || children[i].pid > 0)
continue;
child = &(children[i]);
break;
}
if (child == NULL) {
fatal_f("error: accepted connection when all %d child "
" slots full", options.max_startups);
}
child->pipefd = pipefd;
child->early = 1;
/* record peer address, if available */
if (getpeername(sockfd, sa, &addrlen) == 0 &&
addr_sa_to_xaddr(sa, addrlen, &child->addr) == 0)
child->have_addr = 1;
/* format peer address string for logs */
if ((lport = get_local_port(sockfd)) == 0 ||
(rport = get_peer_port(sockfd)) == 0) {
/* Not a TCP socket */
raddr = get_peer_ipaddr(sockfd);
xasprintf(&child->id, "connection from %s", raddr);
} else {
laddr = get_local_ipaddr(sockfd);
raddr = get_peer_ipaddr(sockfd);
xasprintf(&child->id, "connection from %s to %s", laddr, raddr);
}
free(laddr);
free(raddr);
if (++children_active > options.max_startups)
fatal_f("internal error: more children than max_startups");
return child;
}
/*
* Finally free a child entry. Don't call this directly.
*/
static void
child_finish(struct early_child *child)
{
if (children_active == 0)
fatal_f("internal error: children_active underflow");
if (child->pipefd != -1)
close(child->pipefd);
free(child->id);
memset(child, '\0', sizeof(*child));
child->pipefd = -1;
child->pid = -1;
children_active--;
}
/*
* Close a child's pipe. This will not stop tracking the child immediately
* (it will still be tracked for waitpid()) unless force_final is set, or
* child has already exited.
*/
static void
child_close(struct early_child *child, int force_final, int quiet)
{
if (!quiet)
debug_f("enter%s", force_final ? " (forcing)" : "");
if (child->pipefd != -1) {
close(child->pipefd);
child->pipefd = -1;
}
if (child->pid == -1 || force_final)
child_finish(child);
}
/* Record a child exit. Safe to call from signal handlers */
static void
child_exit(pid_t pid, int status)
{
int i;
if (children == NULL || pid <= 0)
return;
for (i = 0; i < options.max_startups; i++) {
if (children[i].pid == pid) {
children[i].have_status = 1;
children[i].status = status;
break;
}
}
}
/*
* Reap a child entry that has exited, as previously flagged
* using child_exit().
* Handles logging of exit condition and will finalise the child if its pipe
* had already been closed.
*/
static void
child_reap(struct early_child *child)
{
LogLevel level = SYSLOG_LEVEL_DEBUG1;
int was_crash, penalty_type = SRCLIMIT_PENALTY_NONE;
/* Log exit information */
if (WIFSIGNALED(child->status)) {
/*
* Increase logging for signals potentially associated
* with serious conditions.
*/
if ((was_crash = signal_is_crash(WTERMSIG(child->status))))
level = SYSLOG_LEVEL_ERROR;
do_log2(level, "session process %ld for %s killed by "
"signal %d%s", (long)child->pid, child->id,
WTERMSIG(child->status), child->early ? " (early)" : "");
if (was_crash)
penalty_type = SRCLIMIT_PENALTY_CRASH;
} else if (!WIFEXITED(child->status)) {
penalty_type = SRCLIMIT_PENALTY_CRASH;
error("session process %ld for %s terminated abnormally, "
"status=0x%x%s", (long)child->pid, child->id, child->status,
child->early ? " (early)" : "");
} else {
/* Normal exit. We care about the status */
switch (WEXITSTATUS(child->status)) {
case 0:
debug3_f("preauth child %ld for %s completed "
"normally %s", (long)child->pid, child->id,
child->early ? " (early)" : "");
break;
case EXIT_LOGIN_GRACE:
penalty_type = SRCLIMIT_PENALTY_GRACE_EXCEEDED;
logit("Timeout before authentication for %s, "
"pid = %ld%s", child->id, (long)child->pid,
child->early ? " (early)" : "");
break;
case EXIT_CHILD_CRASH:
penalty_type = SRCLIMIT_PENALTY_CRASH;
logit("Session process %ld unpriv child crash for %s%s",
(long)child->pid, child->id,
child->early ? " (early)" : "");
break;
case EXIT_AUTH_ATTEMPTED:
penalty_type = SRCLIMIT_PENALTY_AUTHFAIL;
debug_f("preauth child %ld for %s exited "
"after unsuccessful auth attempt %s",
(long)child->pid, child->id,
child->early ? " (early)" : "");
break;
default:
penalty_type = SRCLIMIT_PENALTY_NOAUTH;
debug_f("preauth child %ld for %s exited "
"with status %d%s", (long)child->pid, child->id,
WEXITSTATUS(child->status),
child->early ? " (early)" : "");
break;
}
}
/*
* XXX would be nice to have more subtlety here.
* - Different penalties
* a) authentication failures without success (e.g. brute force)
* b) login grace exceeded (penalise DoS)
* c) monitor crash (penalise exploit attempt)
* d) unpriv preauth crash (penalise exploit attempt)
* - Unpriv auth exit status/WIFSIGNALLED is not available because
* the "mm_request_receive: monitor fd closed" fatal kills the
* monitor before waitpid() can occur. It would be good to use the
* unpriv exit status to detect crashes.
*
* For now, just penalise (a), (b) and (c), since that is what we have
* readily available. The authentication failures detection cannot
* discern between failed authentication and other connection problems
* until we have the unpriv exist status plumbed through (and the unpriv
* child modified to use a different exit status when auth has been
* attempted), but it's a start.
*/
if (child->have_addr)
srclimit_penalise(&child->addr, penalty_type);
child->pid = -1;
child->have_status = 0;
if (child->pipefd == -1)
child_finish(child);
}
/* Reap all children that have exited; called after SIGCHLD */
static void
child_reap_all_exited(void)
{
int i;
if (children == NULL)
return;
for (i = 0; i < options.max_startups; i++) {
if (!children[i].have_status)
continue;
child_reap(&(children[i]));
}
}
static void
close_startup_pipes(void)
{
int i;
if (startup_pipes)
for (i = 0; i < options.max_startups; i++)
if (startup_pipes[i] != -1)
close(startup_pipes[i]);
if (children == NULL)
return;
for (i = 0; i < options.max_startups; i++) {
if (children[i].pipefd != -1)
child_close(&(children[i]), 1, 1);
}
}
/* Called after SIGINFO */
static void
show_info(void)
{
int i;
/* XXX print listening sockets here too */
if (children == NULL)
return;
logit("%d active startups", children_active);
for (i = 0; i < options.max_startups; i++) {
if (children[i].pipefd == -1 && children[i].pid <= 0)
continue;
logit("child %d: fd=%d pid=%ld %s%s", i, children[i].pipefd,
(long)children[i].pid, children[i].id,
children[i].early ? " (early)" : "");
}
srclimit_penalty_info();
}
/*
@ -222,6 +485,12 @@ sigterm_handler(int sig)
received_sigterm = sig;
}
static void
siginfo_handler(int sig)
{
received_siginfo = 1;
}
/*
* SIGCHLD handler. This is called whenever a child dies. This will then
* reap any zombies left by exited children.
@ -233,9 +502,17 @@ main_sigchld_handler(int sig)
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid == -1 && errno == EINTR))
;
for (;;) {
if ((pid = waitpid(-1, &status, WNOHANG)) == 0)
break;
else if (pid == -1) {
if (errno == EINTR)
continue;
break;
}
child_exit(pid, status);
received_sigchld = 1;
}
errno = save_errno;
}
@ -268,7 +545,7 @@ should_drop_connection(int startups)
}
/*
* Check whether connection should be accepted by MaxStartups.
* Check whether connection should be accepted by MaxStartups or for penalty.
* Returns 0 if the connection is accepted. If the connection is refused,
* returns 1 and attempts to send notification to client.
* Logs when the MaxStartups condition is entered or exited, and periodically
@ -278,12 +555,17 @@ static int
drop_connection(int sock, int startups, int notify_pipe)
{
char *laddr, *raddr;
const char msg[] = "Exceeded MaxStartups\r\n";
const char *reason = NULL, msg[] = "Not allowed at this time\r\n";
static time_t last_drop, first_drop;
static u_int ndropped;
LogLevel drop_level = SYSLOG_LEVEL_VERBOSE;
time_t now;
if (!srclimit_penalty_check_allow(sock, &reason)) {
drop_level = SYSLOG_LEVEL_INFO;
goto handle;
}
now = monotime();
if (!should_drop_connection(startups) &&
srclimit_check_allow(sock, notify_pipe) == 1) {
@ -313,12 +595,16 @@ drop_connection(int sock, int startups, int notify_pipe)
}
last_drop = now;
ndropped++;
reason = "past Maxstartups";
handle:
laddr = get_local_ipaddr(sock);
raddr = get_peer_ipaddr(sock);
do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d "
"past MaxStartups", startups, raddr, get_peer_port(sock),
laddr, get_local_port(sock));
do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d %s",
startups,
raddr, get_peer_port(sock),
laddr, get_local_port(sock),
reason);
free(laddr);
free(raddr);
/* best-effort notification to client */
@ -521,8 +807,12 @@ server_listen(void)
u_int i;
/* Initialise per-source limit tracking. */
srclimit_init(options.max_startups, options.per_source_max_startups,
options.per_source_masklen_ipv4, options.per_source_masklen_ipv6);
srclimit_init(options.max_startups,
options.per_source_max_startups,
options.per_source_masklen_ipv4,
options.per_source_masklen_ipv6,
&options.per_source_penalty,
options.per_source_penalty_exempt);
for (i = 0; i < options.num_listen_addrs; i++) {
listen_on_addrs(&options.listen_addrs[i]);
@ -548,32 +838,30 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
int log_stderr)
{
struct pollfd *pfd = NULL;
int i, j, ret, npfd;
int ostartups = -1, startups = 0, listening = 0, lameduck = 0;
int i, ret, npfd;
int oactive = -1, listening = 0, lameduck = 0;
int startup_p[2] = { -1 , -1 }, *startup_pollfd;
char c = 0;
struct sockaddr_storage from;
struct early_child *child;
socklen_t fromlen;
pid_t pid;
sigset_t nsigset, osigset;
/* setup fd set for accept */
/* pipes connected to unauthenticated child sshd processes */
startup_pipes = xcalloc(options.max_startups, sizeof(int));
startup_flags = xcalloc(options.max_startups, sizeof(int));
child_alloc();
startup_pollfd = xcalloc(options.max_startups, sizeof(int));
for (i = 0; i < options.max_startups; i++)
startup_pipes[i] = -1;
/*
* Prepare signal mask that we use to block signals that might set
* received_sigterm or received_sighup, so that we are guaranteed
* received_sigterm/hup/chld/info, so that we are guaranteed
* to immediately wake up the ppoll if a signal is received after
* the flag is checked.
*/
sigemptyset(&nsigset);
sigaddset(&nsigset, SIGHUP);
sigaddset(&nsigset, SIGCHLD);
sigaddset(&nsigset, SIGINFO);
sigaddset(&nsigset, SIGTERM);
sigaddset(&nsigset, SIGQUIT);
@ -595,11 +883,19 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
unlink(options.pid_file);
exit(received_sigterm == SIGTERM ? 0 : 255);
}
if (ostartups != startups) {
if (received_sigchld) {
child_reap_all_exited();
received_sigchld = 0;
}
if (received_siginfo) {
show_info();
received_siginfo = 0;
}
if (oactive != children_active) {
setproctitle("%s [listener] %d of %d-%d startups",
listener_proctitle, startups,
listener_proctitle, children_active,
options.max_startups_begin, options.max_startups);
ostartups = startups;
oactive = children_active;
}
if (received_sighup) {
if (!lameduck) {
@ -620,8 +916,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
npfd = num_listen_socks;
for (i = 0; i < options.max_startups; i++) {
startup_pollfd[i] = -1;
if (startup_pipes[i] != -1) {
pfd[npfd].fd = startup_pipes[i];
if (children[i].pipefd != -1) {
pfd[npfd].fd = children[i].pipefd;
pfd[npfd].events = POLLIN;
startup_pollfd[i] = npfd++;
}
@ -639,34 +935,46 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
continue;
for (i = 0; i < options.max_startups; i++) {
if (startup_pipes[i] == -1 ||
if (children[i].pipefd == -1 ||
startup_pollfd[i] == -1 ||
!(pfd[startup_pollfd[i]].revents & (POLLIN|POLLHUP)))
continue;
switch (read(startup_pipes[i], &c, sizeof(c))) {
switch (read(children[i].pipefd, &c, sizeof(c))) {
case -1:
if (errno == EINTR || errno == EAGAIN)
continue;
if (errno != EPIPE) {
error_f("startup pipe %d (fd=%d): "
"read %s", i, startup_pipes[i],
"read %s", i, children[i].pipefd,
strerror(errno));
}
/* FALLTHROUGH */
case 0:
/* child exited or completed auth */
close(startup_pipes[i]);
srclimit_done(startup_pipes[i]);
startup_pipes[i] = -1;
startups--;
if (startup_flags[i])
/* child exited preauth */
if (children[i].early)
listening--;
srclimit_done(children[i].pipefd);
child_close(&(children[i]), 0, 0);
break;
case 1:
if (children[i].early && c == '\0') {
/* child has finished preliminaries */
if (startup_flags[i]) {
listening--;
startup_flags[i] = 0;
children[i].early = 0;
debug2_f("child %lu for %s received "
"config", (long)children[i].pid,
children[i].id);
} else if (!children[i].early && c == '\001') {
/* child has completed auth */
debug2_f("child %lu for %s auth done",
(long)children[i].pid,
children[i].id);
child_close(&(children[i]), 1, 0);
} else {
error_f("unexpected message 0x%02x "
"child %ld for %s in state %d",
(int)c, (long)children[i].pid,
children[i].id, children[i].early);
}
break;
}
@ -695,7 +1003,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
close(*newsock);
continue;
}
if (drop_connection(*newsock, startups, startup_p[0])) {
if (drop_connection(*newsock,
children_active, startup_p[0])) {
close(*newsock);
close(startup_p[0]);
close(startup_p[1]);
@ -712,14 +1021,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
continue;
}
for (j = 0; j < options.max_startups; j++)
if (startup_pipes[j] == -1) {
startup_pipes[j] = startup_p[0];
startups++;
startup_flags[j] = 1;
break;
}
/*
* Got connection. Fork a child to handle it, unless
* we are in debugging mode.
@ -737,7 +1038,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
close(startup_p[0]);
close(startup_p[1]);
startup_pipe = -1;
pid = getpid();
send_rexec_state(config_s[0], cfg);
close(config_s[0]);
free(pfd);
@ -750,7 +1050,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
* parent continues listening.
*/
listening++;
if ((pid = fork()) == 0) {
child = child_register(startup_p[0], *newsock);
if ((child->pid = fork()) == 0) {
/*
* Child. Close the listening and
* max_startup sockets. Start using
@ -774,10 +1075,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s,
}
/* Parent. Stay in the loop. */
if (pid == -1)
if (child->pid == -1)
error("fork: %.100s", strerror(errno));
else
debug("Forked child %ld.", (long)pid);
debug("Forked child %ld.", (long)child->pid);
close(startup_p[1]);
@ -1340,6 +1641,7 @@ main(int ac, char **av)
ssh_signal(SIGCHLD, main_sigchld_handler);
ssh_signal(SIGTERM, sigterm_handler);
ssh_signal(SIGQUIT, sigterm_handler);
ssh_signal(SIGINFO, siginfo_handler);
/*
* Write out the pid file after the sigterm handler
@ -1395,6 +1697,7 @@ main(int ac, char **av)
fatal("dup2 startup_p: %s", strerror(errno));
close(startup_pipe);
}
log_redirect_stderr_to(NULL);
closefrom(REEXEC_MIN_FREE_FD);
ssh_signal(SIGHUP, SIG_IGN); /* avoid reset to SIG_DFL */

View file

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd_config.5,v 1.355 2024/02/21 06:17:29 djm Exp $
.Dd $Mdocdate: February 21 2024 $
.\" $OpenBSD: sshd_config.5,v 1.358 2024/06/06 21:14:49 jmc Exp $
.Dd $Mdocdate: June 6 2024 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -1558,6 +1558,69 @@ Values for IPv4 and optionally IPv6 may be specified, separated by a colon.
The default is
.Cm 32:128 ,
which means each address is considered individually.
.It Cm PerSourcePenalties
Controls penalties for various conditions that may represent attacks on
.Xr sshd 8 .
If a penalty is enforced against a client then its source address and any
others in the
.Cm PerSourceNetBlockSize
will be refused connection for a period.
A penalty doesn't affect concurrent connections in progress, but multiple
penalties from the same source from concurrent connections will accumulate
up to a maximum.
Conversely, penalties are not applied until a minimum threshold time has been
accumulated.
Penalties are off by default but may be enabled using default settings using the
.Cm yes
keyword or by specifying one or more of the keywords below.
.Pp
Penalties are controlled using the following keywords, all of which accept
arguments, e.g.\&
.Qq crash:2m .
.Bl -tag -width Ds
.It Cm crash:duration
Specifies how long to refuse clients that cause a crash of
.Xr sshd 8 .
.It Cm authfail:duration
Specifies how long to refuse clients that disconnect after making one or more
unsuccessful authentication attempts.
.It Cm noauth:duration
Specifies how long to refuse clients that disconnect without attempting
authentication.
This timeout should be used cautiously otherwise it may penalise legitimate
scanning tools such as
.Xr ssh-keyscan 1 .
.It Cm grace-exceeded:duration
Specifies how long to refuse clients that fail to authenticate after
.Cm LoginGraceTime .
.It Cm max:duration
Specifies the maximum time a particular source address range will be refused
access for.
Repeated penalties will accumulate up to this maximum.
.It Cm min:duration
Specifies the minimum penalty that must accrue before enforcement begins.
.It Cm max-sources:number
Specifies the maximum number of penalise client address ranges to track.
.It Cm overflow:mode
Controls how the server behaves when
.Cm max-sources
is exceeded.
There are two operating modes:
.Cm deny-all ,
which denies all incoming connections other than those exempted via
.Cm PerSourcePenaltyExemptList
until a penalty expires, and
.Cm permissive ,
which allows new connections by removing existing penalties early.
.El
.It Cm PerSourcePenaltyExemptList
Specifies a comma-separated list of addresses to exempt from penalties.
This list may contain wildcards and CIDR address/masklen ranges.
Note that the mask length provided must be consistent with the address -
it is an error to specify a mask length that is too long for the address
or one with bits set in this host portion of the address.
For example, 192.0.2.0/33 and 192.0.2.0/8, respectively.
The default is not to exempt any addresses.
.It Cm PidFile
Specifies the file that contains the process ID of the
SSH daemon, or

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: dhcp6leasectl.8,v 1.1 2024/06/06 15:16:57 florian Exp $
.\" $OpenBSD: dhcp6leasectl.8,v 1.2 2024/06/07 17:38:22 jmc Exp $
.\"
.\" Copyright (c) 2021 Florian Obser <florian@openbsd.org>
.\" Copyright (c) 2016 Kenneth R Westerback <kwesterback@gmail.com>
@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: June 6 2024 $
.Dd $Mdocdate: June 7 2024 $
.Dt DHCP6LEASECTL 8
.Os
.Sh NAME
@ -52,9 +52,7 @@ to communicate with
Specify the maximum number of seconds to wait for
.Ar interface
to be configured.
The default is to wait 10 seconds unless
.Fl l
is specified.
The default is 10 seconds.
.El
.Sh FILES
.Bl -tag -width "/dev/dhcp6leased.sockXX" -compact

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: dhcpleasectl.8,v 1.5 2023/03/02 17:09:54 jmc Exp $
.\" $OpenBSD: dhcpleasectl.8,v 1.6 2024/06/07 17:38:22 jmc Exp $
.\"
.\" Copyright (c) 2021 Florian Obser <florian@openbsd.org>
.\" Copyright (c) 2016 Kenneth R Westerback <kwesterback@gmail.com>
@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: March 2 2023 $
.Dd $Mdocdate: June 7 2024 $
.Dt DHCPLEASECTL 8
.Os
.Sh NAME
@ -52,9 +52,7 @@ to communicate with
Specify the maximum number of seconds to wait for
.Ar interface
to be configured.
The default is to wait 10 seconds unless
.Fl l
is specified.
The default is 10 seconds.
.El
.Sh FILES
.Bl -tag -width "/dev/dhcpleased.sockXX" -compact

View file

@ -1,4 +1,4 @@
/* $OpenBSD: cert.c,v 1.140 2024/06/06 12:38:02 tb Exp $ */
/* $OpenBSD: cert.c,v 1.144 2024/06/08 13:33:49 tb Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Job Snijders <job@openbsd.org>
@ -744,6 +744,15 @@ cert_parse_ee_cert(const char *fn, int talid, X509 *x)
if (!cert_check_subject_and_issuer(fn, x))
goto out;
if (!x509_cache_extensions(x, fn))
goto out;
if ((cert->purpose = x509_get_purpose(x, fn)) != CERT_PURPOSE_EE) {
warnx("%s: expected EE cert, got %s", fn,
purpose2str(cert->purpose));
goto out;
}
if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE) {
warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature",
fn);
@ -827,11 +836,8 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
goto out;
}
/* Cache X509v3 extensions, see X509_check_ca(3). */
if (X509_check_purpose(x, -1, -1) <= 0) {
warnx("%s: could not cache X509v3 extensions", fn);
if (!x509_cache_extensions(x, fn))
goto out;
}
if (X509_get_version(x) != 2) {
warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
@ -957,11 +963,12 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
goto out;
if (!x509_get_notafter(x, fn, &cert->notafter))
goto out;
cert->purpose = x509_get_purpose(x, fn);
/* Validation on required fields. */
cert->purpose = x509_get_purpose(x, fn);
switch (cert->purpose) {
case CERT_PURPOSE_TA:
/* XXX - caller should indicate if it expects TA or CA cert */
case CERT_PURPOSE_CA:
if ((pkey = X509_get0_pubkey(x)) == NULL) {
warnx("%s: X509_get0_pubkey failed", fn);
@ -1015,6 +1022,9 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
goto out;
}
break;
case CERT_PURPOSE_EE:
warn("%s: unexpected EE cert", fn);
goto out;
default:
warnx("%s: x509_get_purpose failed in %s", fn, __func__);
goto out;
@ -1117,8 +1127,9 @@ ta_parse(const char *fn, struct cert *p, const unsigned char *pkey,
"trust anchor may not specify CRL resource", fn);
goto badcert;
}
if (p->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
warnx("%s: BGPsec cert cannot be a trust anchor", fn);
if (p->purpose != CERT_PURPOSE_TA) {
warnx("%s: expected trust anchor purpose, got %s", fn,
purpose2str(p->purpose));
goto badcert;
}
/*

View file

@ -1,4 +1,4 @@
/* $OpenBSD: cms.c,v 1.45 2024/05/24 12:57:20 tb Exp $ */
/* $OpenBSD: cms.c,v 1.46 2024/06/08 13:28:35 tb Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@ -324,11 +324,8 @@ cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char *der,
goto out;
}
/* Cache X509v3 extensions, see X509_check_ca(3). */
if (X509_check_purpose(*xp, -1, -1) <= 0) {
warnx("%s: could not cache X509v3 extensions", fn);
if (!x509_cache_extensions(*xp, fn))
goto out;
}
if (!x509_get_notafter(*xp, fn, &notafter))
goto out;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: extern.h,v 1.221 2024/06/04 04:17:18 tb Exp $ */
/* $OpenBSD: extern.h,v 1.224 2024/06/08 13:30:35 tb Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@ -107,8 +107,10 @@ struct cert_ip {
enum cert_purpose {
CERT_PURPOSE_INVALID,
CERT_PURPOSE_TA,
CERT_PURPOSE_CA,
CERT_PURPOSE_BGPSEC_ROUTER
CERT_PURPOSE_EE,
CERT_PURPOSE_BGPSEC_ROUTER,
};
/*
@ -901,6 +903,7 @@ struct ibuf *io_buf_recvfd(int, struct ibuf **);
/* X509 helpers. */
void x509_init_oid(void);
int x509_cache_extensions(X509 *, const char *);
int x509_get_aia(X509 *, const char *, char **);
int x509_get_aki(X509 *, const char *, char **);
int x509_get_sia(X509 *, const char *, char **);
@ -922,6 +925,7 @@ time_t x509_find_expires(time_t, struct auth *, struct crl_tree *);
/* printers */
char *nid2str(int);
const char *purpose2str(enum cert_purpose);
char *time2str(time_t);
void x509_print(const X509 *);
void tal_print(const struct tal *);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: filemode.c,v 1.43 2024/06/06 07:19:10 tb Exp $ */
/* $OpenBSD: filemode.c,v 1.45 2024/06/08 13:34:59 tb Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -157,7 +157,8 @@ parse_load_cert(char *uri)
if (cert == NULL)
goto done;
if (cert->purpose != CERT_PURPOSE_CA) {
warnx("AIA reference to bgpsec cert %s", uri);
warnx("AIA reference to %s in %s",
purpose2str(cert->purpose), uri);
goto done;
}
/* try to load the CRL of this cert */
@ -403,7 +404,7 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
cert = cert_parse_pre(file, buf, len);
if (cert == NULL)
break;
is_ta = X509_get_extension_flags(cert->x509) & EXFLAG_SS;
is_ta = (cert->purpose == CERT_PURPOSE_TA);
if (!is_ta)
cert = cert_parse(file, cert);
if (cert == NULL)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: main.c,v 1.258 2024/05/20 15:51:43 claudio Exp $ */
/* $OpenBSD: main.c,v 1.260 2024/06/08 13:31:38 tb Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -481,7 +481,7 @@ queue_add_from_tal(struct tal *tal)
/* steal the pkey from the tal structure */
data = tal->pkey;
tal->pkey = NULL;
entityq_add(NULL, nfile, RTYPE_CER, DIR_VALID, repo, data,
entityq_add(NULL, nfile, RTYPE_CER, DIR_UNKNOWN, repo, data,
tal->pkeysz, tal->id, tal->id, NULL);
}
@ -618,6 +618,7 @@ entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
}
cert = cert_read(b);
switch (cert->purpose) {
case CERT_PURPOSE_TA:
case CERT_PURPOSE_CA:
queue_add_from_cert(cert);
break;
@ -626,7 +627,7 @@ entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
repo_stat_inc(rp, talid, type, STYPE_BGPSEC);
break;
default:
errx(1, "unexpected cert purpose received");
errx(1, "unexpected %s", purpose2str(cert->purpose));
break;
}
cert_free(cert);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: parser.c,v 1.136 2024/05/20 15:51:43 claudio Exp $ */
/* $OpenBSD: parser.c,v 1.139 2024/06/07 13:24:35 tb Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -570,35 +570,101 @@ proc_parser_cert(char *file, const unsigned char *der, size_t len,
return cert;
}
/*
* Root certificates come from TALs (has a pkey and is self-signed).
* Parse the certificate, ensure that its public key matches the
* known public key from the TAL, and then validate the RPKI
* content.
*
* This returns a certificate (which must not be freed) or NULL on
* parse failure.
*/
static struct cert *
proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
unsigned char *pkey, size_t pkeysz, int talid)
static int
proc_parser_ta_cmp(const struct cert *cert1, const struct cert *cert2)
{
struct cert *cert;
/* Extract certificate data. */
cert = cert_parse_pre(file, der, len);
cert = ta_parse(file, cert, pkey, pkeysz);
if (cert == NULL)
return NULL;
cert->talid = talid;
if (cert1 == NULL)
return -1;
if (cert2 == NULL)
return 1;
/*
* Add valid roots to the RPKI auth tree.
* The standards don't specify tiebreakers. While RFC 6487 and other
* sources advise against backdating, it's explicitly allowed and some
* TAs do. Some TAs have also re-issued with new dates and old
* serialNumber.
* Our tiebreaker logic: a more recent notBefore is taken to mean a
* more recent issuance, and thus preferable. Given equal notBefore
* values, prefer the TA cert with the narrower validity window. This
* hopefully encourages TA operators to reduce egregiously long TA
* validity periods.
*/
auth_insert(file, &auths, cert, NULL);
return cert;
if (cert1->notbefore < cert2->notbefore)
return -1;
if (cert1->notbefore > cert2->notbefore)
return 1;
if (cert1->notafter > cert2->notafter)
return -1;
if (cert1->notafter < cert2->notafter)
return 1;
/*
* Both certs are valid from our perspective. If anything changed,
* prefer the freshly-fetched one. We rely on cert_parse_pre() having
* cached the extensions and thus libcrypto has already computed the
* certs' hashes (SHA-1 for OpenSSL, SHA-512 for LibreSSL). The below
* compares them.
*/
return X509_cmp(cert1->x509, cert2->x509) != 0;
}
/*
* Root certificates come from TALs. Inspect and validate both options and
* compare the two. The cert in out_cert must not be freed. Returns the file
* name of the chosen TA.
*/
static char *
proc_parser_root_cert(struct entity *entp, struct cert **out_cert)
{
struct cert *cert1 = NULL, *cert2 = NULL;
char *file1 = NULL, *file2 = NULL;
unsigned char *der = NULL, *pkey = entp->data;
size_t der_len = 0, pkeysz = entp->datasz;
int cmp;
*out_cert = NULL;
file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID);
der = load_file(file2, &der_len);
cert2 = cert_parse_pre(file2, der, der_len);
free(der);
cert2 = ta_parse(file2, cert2, pkey, pkeysz);
if (!noop) {
file1 = parse_filepath(entp->repoid, entp->path, entp->file,
DIR_TEMP);
der = load_file(file1, &der_len);
cert1 = cert_parse_pre(file1, der, der_len);
free(der);
cert1 = ta_parse(file1, cert1, pkey, pkeysz);
}
if ((cmp = proc_parser_ta_cmp(cert1, cert2)) > 0) {
cert_free(cert2);
free(file2);
cert1->talid = entp->talid;
auth_insert(file1, &auths, cert1, NULL);
*out_cert = cert1;
return file1;
} else {
if (cmp < 0 && cert1 != NULL && cert2 != NULL)
warnx("%s: cached TA is newer", entp->file);
cert_free(cert1);
free(file1);
if (cert2 != 0) {
cert2->talid = entp->talid;
auth_insert(file2, &auths, cert2, NULL);
}
*out_cert = cert2;
return file2;
}
}
/*
@ -784,14 +850,13 @@ parse_entity(struct entityq *q, struct msgbuf *msgq)
tal_free(tal);
break;
case RTYPE_CER:
if (entp->data != NULL) {
file = proc_parser_root_cert(entp, &cert);
} else {
file = parse_load_file(entp, &f, &flen);
io_str_buffer(b, file);
if (entp->data != NULL)
cert = proc_parser_root_cert(file,
f, flen, entp->data, entp->datasz,
entp->talid);
else
cert = proc_parser_cert(file, f, flen, entp);
}
io_str_buffer(b, file);
if (cert != NULL)
mtime = cert->notbefore;
io_simple_buffer(b, &mtime, sizeof(mtime));

View file

@ -1,4 +1,4 @@
/* $OpenBSD: print.c,v 1.54 2024/06/06 05:57:36 tb Exp $ */
/* $OpenBSD: print.c,v 1.55 2024/06/08 13:30:35 tb Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -65,6 +65,25 @@ nid2str(int nid)
return buf;
}
const char *
purpose2str(enum cert_purpose purpose)
{
switch (purpose) {
case CERT_PURPOSE_INVALID:
return "invalid cert";
case CERT_PURPOSE_TA:
return "TA cert";
case CERT_PURPOSE_CA:
return "CA cert";
case CERT_PURPOSE_EE:
return "EE cert";
case CERT_PURPOSE_BGPSEC_ROUTER:
return "BGPsec Router cert";
default:
return "unknown certificate purpose";
}
}
char *
time2str(time_t t)
{

View file

@ -1,4 +1,4 @@
/* $OpenBSD: repo.c,v 1.59 2024/05/30 12:33:15 claudio Exp $ */
/* $OpenBSD: repo.c,v 1.60 2024/06/07 08:22:53 claudio Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -78,7 +78,6 @@ struct tarepo {
SLIST_ENTRY(tarepo) entry;
char *descr;
char *basedir;
char *temp;
char **uri;
size_t urisz;
size_t uriidx;
@ -322,7 +321,7 @@ repo_done(const void *vp, int ok)
* If temp is set add Xs for mkostemp.
*/
static char *
ta_filename(const struct tarepo *tr, int temp)
ta_filename(const struct tarepo *tr)
{
const char *file;
char *nfile;
@ -331,8 +330,7 @@ ta_filename(const struct tarepo *tr, int temp)
file = strrchr(tr->uri[0], '/');
assert(file);
if (asprintf(&nfile, "%s%s%s", tr->basedir, file,
temp ? ".XXXXXXXX" : "") == -1)
if (asprintf(&nfile, "%s%s", tr->basedir, file) == -1)
err(1, NULL);
return nfile;
@ -367,18 +365,21 @@ ta_fetch(struct tarepo *tr)
*/
rsync_fetch(tr->id, tr->uri[tr->uriidx], tr->basedir, NULL);
} else {
char *temp;
int fd;
tr->temp = ta_filename(tr, 1);
fd = mkostemp(tr->temp, O_CLOEXEC);
temp = ta_filename(tr);
fd = open(temp,
O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1) {
warn("mkostemp: %s", tr->temp);
warn("open: %s", temp);
free(temp);
http_finish(tr->id, HTTP_FAILED, NULL);
return;
}
if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
warn("fchmod: %s", tr->temp);
free(temp);
http_fetch(tr->id, tr->uri[tr->uriidx], NULL, fd);
}
}
@ -392,12 +393,21 @@ ta_get(struct tal *tal)
if ((tr = calloc(1, sizeof(*tr))) == NULL)
err(1, NULL);
tr->id = ++repoid;
SLIST_INSERT_HEAD(&tarepos, tr, entry);
if ((tr->descr = strdup(tal->descr)) == NULL)
err(1, NULL);
tr->basedir = repo_dir(tal->descr, "ta", 0);
tr->basedir = repo_dir(tal->descr, ".ta", 0);
/* create base directory */
if (mkpath(tr->basedir) == -1) {
warn("mkpath %s", tr->basedir);
tr->state = REPO_FAILED;
repo_done(tr, 0);
return tr;
}
/* steal URI information from TAL */
tr->urisz = tal->urisz;
@ -430,7 +440,6 @@ ta_free(void)
SLIST_REMOVE_HEAD(&tarepos, entry);
free(tr->descr);
free(tr->basedir);
free(tr->temp);
free(tr->uri);
free(tr);
}
@ -1070,20 +1079,12 @@ http_finish(unsigned int id, enum http_result res, const char *last_mod)
/* Move downloaded TA file into place, or unlink on failure. */
if (res == HTTP_OK) {
char *file;
file = ta_filename(tr, 0);
if (rename(tr->temp, file) == -1)
warn("rename to %s", file);
free(file);
logx("ta/%s: loaded from network", tr->descr);
tr->state = REPO_DONE;
stats.http_repos++;
repo_done(tr, 1);
} else {
if (unlink(tr->temp) == -1 && errno != ENOENT)
warn("unlink %s", tr->temp);
remove_contents(tr->basedir);
tr->uriidx++;
warnx("ta/%s: load from network failed", tr->descr);
@ -1632,15 +1633,19 @@ repo_move_valid(struct filepath_tree *tree)
struct filepath *fp, *nfp;
size_t rsyncsz = strlen(".rsync/");
size_t rrdpsz = strlen(".rrdp/");
size_t tasz = strlen(".ta/");
char *fn, *base;
RB_FOREACH_SAFE(fp, filepath_tree, tree, nfp) {
if (strncmp(fp->file, ".rsync/", rsyncsz) != 0 &&
strncmp(fp->file, ".rrdp/", rrdpsz) != 0)
strncmp(fp->file, ".rrdp/", rrdpsz) != 0 &&
strncmp(fp->file, ".ta/", tasz) != 0)
continue; /* not a temporary file path */
if (strncmp(fp->file, ".rsync/", rsyncsz) == 0) {
fn = fp->file + rsyncsz;
} else if (strncmp(fp->file, ".ta/", tasz) == 0) {
fn = fp->file + 1; /* just skip the '.' */
} else {
base = strchr(fp->file + rrdpsz, '/');
assert(base != NULL);
@ -1690,7 +1695,7 @@ repo_move_valid(struct filepath_tree *tree)
}
struct fts_state {
enum { BASE_DIR, RSYNC_DIR, RRDP_DIR } type;
enum { BASE_DIR, RSYNC_DIR, TA_DIR, RRDP_DIR } type;
struct repo *rp;
} fts_state;
@ -1768,8 +1773,9 @@ repo_cleanup_entry(FTSENT *e, struct filepath_tree *tree, int cachefd)
unlink:
if (unlink(e->fts_accpath) == -1) {
warn("unlink %s", path);
} else if (fts_state.type == RSYNC_DIR) {
/* no need to keep rsync files */
} else if (fts_state.type == RSYNC_DIR ||
fts_state.type == TA_DIR) {
/* no need to keep rsync or ta files */
if (verbose > 1)
logx("deleted superfluous %s", path);
if (fts_state.rp != NULL)
@ -1792,9 +1798,11 @@ repo_cleanup_entry(FTSENT *e, struct filepath_tree *tree, int cachefd)
fts_state.rp = NULL;
}
if (e->fts_level == 1) {
/* rpki.example.org or .rrdp / .rsync */
/* rpki.example.org or .rrdp / .rsync / .ta */
if (strcmp(".rsync", e->fts_name) == 0)
fts_state.type = RSYNC_DIR;
else if (strcmp(".ta", e->fts_name) == 0)
fts_state.type = TA_DIR;
else if (strcmp(".rrdp", e->fts_name) == 0)
fts_state.type = RRDP_DIR;
else
@ -1805,6 +1813,8 @@ repo_cleanup_entry(FTSENT *e, struct filepath_tree *tree, int cachefd)
/* rpki.example.org/repository or .rrdp/hashdir */
if (fts_state.type == BASE_DIR)
fts_state.rp = repo_bypath(path);
if (fts_state.type == TA_DIR)
fts_state.rp = repo_bypath(path + 1);
/*
* special handling for rrdp directories,
* clear them if they are not used anymore but
@ -1826,7 +1836,8 @@ repo_cleanup_entry(FTSENT *e, struct filepath_tree *tree, int cachefd)
/* do not remove .rsync and .rrdp */
fts_state.rp = NULL;
if (fts_state.type == RRDP_DIR ||
fts_state.type == RSYNC_DIR)
fts_state.type == RSYNC_DIR ||
fts_state.type == TA_DIR)
break;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: x509.c,v 1.93 2024/06/04 14:17:24 tb Exp $ */
/* $OpenBSD: x509.c,v 1.97 2024/06/08 13:32:30 tb Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@ -132,6 +132,26 @@ x509_init_oid(void)
}
}
/*
* A number of critical OpenSSL API functions can't properly indicate failure
* and are unreliable if the extensions aren't already cached. An old trick is
* to cache the extensions using an error-checked call to X509_check_purpose()
* with a purpose of -1. This way functions such as X509_check_ca(), X509_cmp(),
* X509_get_key_usage(), X509_get_extended_key_usage() won't lie.
*
* Should be called right after deserialization and is essentially free to call
* multiple times.
*/
int
x509_cache_extensions(X509 *x509, const char *fn)
{
if (X509_check_purpose(x509, -1, 0) <= 0) {
warnx("%s: could not cache X509v3 extensions", fn);
return 0;
}
return 1;
}
/*
* Parse X509v3 authority key identifier (AKI), RFC 6487 sec. 4.8.3.
* Returns the AKI or NULL if it could not be parsed.
@ -246,18 +266,34 @@ x509_get_ski(X509 *x, const char *fn, char **ski)
}
/*
* Check the certificate's purpose: CA or BGPsec Router.
* Return a member of enum cert_purpose.
* Check the cert's purpose: the cA bit in basic constraints distinguishes
* between TA/CA and EE/BGPsec router. TAs are self-signed, CAs not self-issued,
* EEs have no extended key usage, BGPsec router have id-kp-bgpsec-router OID.
*/
enum cert_purpose
x509_get_purpose(X509 *x, const char *fn)
{
BASIC_CONSTRAINTS *bc = NULL;
EXTENDED_KEY_USAGE *eku = NULL;
int crit;
int crit, ext_flags, is_ca;
enum cert_purpose purpose = CERT_PURPOSE_INVALID;
if (X509_check_ca(x) == 1) {
if (!x509_cache_extensions(x, fn))
goto out;
ext_flags = X509_get_extension_flags(x);
/* This weird API can return 0, 1, 2, 4, 5 but can't error... */
if ((is_ca = X509_check_ca(x)) > 1) {
if (is_ca == 4)
warnx("%s: RFC 6487: sections 4.8.1 and 4.8.4: "
"no basic constraints, but keyCertSign set", fn);
else
warnx("%s: unexpected legacy certificate", fn);
goto out;
}
if (is_ca) {
bc = X509_get_ext_d2i(x, NID_basic_constraints, &crit, NULL);
if (bc == NULL) {
if (crit != -1)
@ -278,27 +314,50 @@ x509_get_purpose(X509 *x, const char *fn)
"Constraint must be absent", fn);
goto out;
}
/*
* EXFLAG_SI means that issuer and subject are identical.
* EXFLAG_SS is SI plus the AKI is absent or matches the SKI.
* Thus, exactly the trust anchors should have EXFLAG_SS set
* and we should never see EXFLAG_SI without EXFLAG_SS.
*/
if ((ext_flags & EXFLAG_SS) != 0)
purpose = CERT_PURPOSE_TA;
else if ((ext_flags & EXFLAG_SI) == 0)
purpose = CERT_PURPOSE_CA;
else
warnx("%s: RFC 6487, section 4.8.3: "
"self-issued cert with AKI-SKI mismatch", fn);
goto out;
}
if (X509_get_extension_flags(x) & EXFLAG_BCONS) {
if ((ext_flags & EXFLAG_BCONS) != 0) {
warnx("%s: Basic Constraints ext in non-CA cert", fn);
goto out;
}
/*
* EKU is only defined for BGPsec Router certs and must be absent from
* EE certs.
*/
eku = X509_get_ext_d2i(x, NID_ext_key_usage, &crit, NULL);
if (eku == NULL) {
if (crit != -1)
warnx("%s: error parsing EKU", fn);
else
warnx("%s: EKU: extension missing", fn);
purpose = CERT_PURPOSE_EE; /* EKU absent */
goto out;
}
if (crit != 0) {
warnx("%s: EKU: extension must not be marked critical", fn);
goto out;
}
/*
* XXX - this isn't quite correct: other EKU OIDs are allowed per
* RFC 8209, section 3.1.3.2, e.g., anyEKU could potentially help
* avoid tripping up validators that don't know about the BGPsec
* router purpose. Drop check or downgrade from error to warning?
*/
if (sk_ASN1_OBJECT_num(eku) != 1) {
warnx("%s: EKU: expected 1 purpose, have %d", fn,
sk_ASN1_OBJECT_num(eku));

View file

@ -1,6 +1,6 @@
#!/bin/ksh
#
# $OpenBSD: sysupgrade.sh,v 1.49 2023/10/12 12:31:15 kn Exp $
# $OpenBSD: sysupgrade.sh,v 1.50 2024/06/08 06:05:40 florian Exp $
#
# Copyright (c) 1997-2015 Todd Miller, Theo de Raadt, Ken Westerback
# Copyright (c) 2015 Robert Peichaer <rpe@openbsd.org>
@ -139,6 +139,9 @@ unpriv -f SHA256.sig ftp -N sysupgrade -Vmo SHA256.sig ${URL}SHA256.sig
_KEY=secbsd-${_KERNV[0]%.*}${_KERNV[0]#*.}-base.pub
_NEXTKEY=secbsd-${NEXT_VERSION%.*}${NEXT_VERSION#*.}-base.pub
if $SNAP; then
unpriv -f SHA256 signify -Ve -x SHA256.sig -m SHA256
else
read _LINE <SHA256.sig
case ${_LINE} in
*\ ${_KEY}) SIGNIFY_KEY=/etc/signify/${_KEY} ;;
@ -149,6 +152,8 @@ esac
[[ -f ${SIGNIFY_KEY} ]] || err "cannot find ${SIGNIFY_KEY}"
unpriv -f SHA256 signify -Ve -p "${SIGNIFY_KEY}" -x SHA256.sig -m SHA256
fi
rm SHA256.sig
if cmp -s /var/db/installed.SHA256 SHA256 && ! $FORCE; then