sync with OpenBSD -current
This commit is contained in:
parent
2d0895064a
commit
0d235ae71d
70 changed files with 1715 additions and 502 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
51
regress/usr.bin/ssh/penalty.sh
Normal file
51
regress/usr.bin/ssh/penalty.sh
Normal 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"
|
||||
|
|
@ -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,33 +265,31 @@ export SSH_PKCS11_HELPER SSH_SK_HELPER
|
|||
|
||||
stop_sshd ()
|
||||
{
|
||||
if [ -f $PIDFILE ]; then
|
||||
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
|
||||
$SUDO kill $pid
|
||||
trace "wait for sshd to exit"
|
||||
i=0;
|
||||
while [ -f $PIDFILE -a $i -lt 5 ]; do
|
||||
i=`expr $i + 1`
|
||||
sleep $i
|
||||
done
|
||||
if test -f $PIDFILE; then
|
||||
if $SUDO kill -0 $pid; then
|
||||
echo "sshd didn't exit " \
|
||||
"port $PORT pid $pid"
|
||||
else
|
||||
echo "sshd died without cleanup"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
[ -f $PIDFILE ] || return
|
||||
pid=`$SUDO cat $PIDFILE`
|
||||
if [ "X$pid" = "X" ]; then
|
||||
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;
|
||||
while [ -f $PIDFILE -a $i -lt 5 ]; do
|
||||
i=`expr $i + 1`
|
||||
sleep $i
|
||||
done
|
||||
if test -f $PIDFILE; then
|
||||
if $SUDO kill -0 $pid; then
|
||||
echo "sshd didn't exit port $PORT pid $pid" 1>&2
|
||||
else
|
||||
echo "sshd died without cleanup" 1>&2
|
||||
fi
|
||||
exit 1
|
||||
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"
|
||||
}
|
||||
|
|
|
@ -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,7 +1469,10 @@ int cpu_suspended;
|
|||
void
|
||||
cpu_suspend_cycle(void)
|
||||
{
|
||||
cpu_idle_cycle_fcn();
|
||||
if (cpu_suspend_cycle_fcn)
|
||||
cpu_suspend_cycle_fcn();
|
||||
else
|
||||
cpu_idle_cycle_fcn();
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,7 +128,10 @@ x86_64_ipi_halt(struct cpu_info *ci)
|
|||
wbinvd();
|
||||
|
||||
for(;;) {
|
||||
__asm volatile("hlt");
|
||||
if (cpu_suspend_cycle_fcn)
|
||||
cpu_suspend_cycle_fcn();
|
||||
else
|
||||
__asm volatile("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
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,19 +1196,20 @@ 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);
|
||||
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);
|
||||
vmxnet3_rxfill(ring);
|
||||
mtx_leave(&ring->mtx);
|
||||
mtx_enter(&ring->mtx);
|
||||
if_rxr_put(&ring->rxr, done[i]);
|
||||
vmxnet3_rxfill(ring);
|
||||
mtx_leave(&ring->mtx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
11
sys/net/pf.c
11
sys/net/pf.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,10 +204,11 @@ 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_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
|
||||
#define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */
|
||||
#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 */
|
||||
|
||||
extern struct ipstat ipstat;
|
||||
extern int ip_defttl; /* default IP ttl */
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
dst6 = ifra->ifra_dstaddr;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
/* child has finished preliminaries */
|
||||
if (startup_flags[i]) {
|
||||
if (children[i].early && c == '\0') {
|
||||
/* child has finished preliminaries */
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -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, ¬after))
|
||||
goto out;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
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
|
||||
if (entp->data != NULL) {
|
||||
file = proc_parser_root_cert(entp, &cert);
|
||||
} else {
|
||||
file = parse_load_file(entp, &f, &flen);
|
||||
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));
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,8 +1695,8 @@ repo_move_valid(struct filepath_tree *tree)
|
|||
}
|
||||
|
||||
struct fts_state {
|
||||
enum { BASE_DIR, RSYNC_DIR, RRDP_DIR } type;
|
||||
struct repo *rp;
|
||||
enum { BASE_DIR, RSYNC_DIR, TA_DIR, RRDP_DIR } type;
|
||||
struct repo *rp;
|
||||
} fts_state;
|
||||
|
||||
static const struct rrdprepo *
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
purpose = CERT_PURPOSE_CA;
|
||||
/*
|
||||
* 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));
|
||||
|
|
|
@ -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,16 +139,21 @@ 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
|
||||
|
||||
read _LINE <SHA256.sig
|
||||
case ${_LINE} in
|
||||
*\ ${_KEY}) SIGNIFY_KEY=/etc/signify/${_KEY} ;;
|
||||
*\ ${_NEXTKEY}) SIGNIFY_KEY=/etc/signify/${_NEXTKEY} ;;
|
||||
*) err "invalid signing key" ;;
|
||||
esac
|
||||
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} ;;
|
||||
*\ ${_NEXTKEY}) SIGNIFY_KEY=/etc/signify/${_NEXTKEY} ;;
|
||||
*) err "invalid signing key" ;;
|
||||
esac
|
||||
|
||||
[[ -f ${SIGNIFY_KEY} ]] || err "cannot find ${SIGNIFY_KEY}"
|
||||
[[ -f ${SIGNIFY_KEY} ]] || err "cannot find ${SIGNIFY_KEY}"
|
||||
|
||||
unpriv -f SHA256 signify -Ve -p "${SIGNIFY_KEY}" -x SHA256.sig -m SHA256
|
||||
fi
|
||||
|
||||
unpriv -f SHA256 signify -Ve -p "${SIGNIFY_KEY}" -x SHA256.sig -m SHA256
|
||||
rm SHA256.sig
|
||||
|
||||
if cmp -s /var/db/installed.SHA256 SHA256 && ! $FORCE; then
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue