sync with OpenBSD -current

This commit is contained in:
purplerain 2024-10-14 16:24:39 +00:00
parent f261735ef2
commit 6f79ebd4c9
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
40 changed files with 1378 additions and 597 deletions

View file

@ -1,5 +1,6 @@
/* $OpenBSD: cp.c,v 1.10 2021/11/28 19:28:41 deraadt Exp $ */ /* $OpenBSD: cp.c,v 1.11 2024/10/14 08:26:48 jsg Exp $ */
/* $NetBSD: cp.c,v 1.14 1995/09/07 06:14:51 jtc Exp $ */ /* $NetBSD: cp.c,v 1.14 1995/09/07 06:14:51 jtc Exp $ */
/* $NetBSD: utils.c,v 1.6 1997/02/26 14:40:51 cgd Exp $ */
/* /*
* Copyright (c) 1988, 1993, 1994 * Copyright (c) 1988, 1993, 1994
@ -385,54 +386,6 @@ copy(char *argv[], enum op type, int fts_options)
return (rval); return (rval);
} }
/* $OpenBSD: cp.c,v 1.10 2021/11/28 19:28:41 deraadt Exp $ */
/* $NetBSD: utils.c,v 1.6 1997/02/26 14:40:51 cgd Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#define _MAXBSIZE (64 * 1024) #define _MAXBSIZE (64 * 1024)
static int static int

View file

@ -2536,6 +2536,7 @@
./usr/libexec/ssh-pkcs11-helper ./usr/libexec/ssh-pkcs11-helper
./usr/libexec/ssh-sk-helper ./usr/libexec/ssh-sk-helper
./usr/libexec/sshd-session ./usr/libexec/sshd-session
./usr/libexec/sshd-auth
./usr/libexec/tradcpp ./usr/libexec/tradcpp
./usr/libexec/vi.recover ./usr/libexec/vi.recover
./usr/local ./usr/local
@ -2985,6 +2986,8 @@
./usr/share/relink/usr/lib/libcrypto.so.55.0.a ./usr/share/relink/usr/lib/libcrypto.so.55.0.a
./usr/share/relink/usr/libexec ./usr/share/relink/usr/libexec
./usr/share/relink/usr/libexec/ld.so.a ./usr/share/relink/usr/libexec/ld.so.a
./usr/share/relink/usr/libexec/sshd-auth
./usr/share/relink/usr/libexec/sshd-auth/sshd-auth.tar
./usr/share/relink/usr/libexec/sshd-session ./usr/share/relink/usr/libexec/sshd-session
./usr/share/relink/usr/libexec/sshd-session/sshd-session.tar ./usr/share/relink/usr/libexec/sshd-session/sshd-session.tar
./usr/share/relink/usr/sbin ./usr/share/relink/usr/sbin

4
etc/rc
View file

@ -1,4 +1,4 @@
# $OpenBSD: rc,v 1.576 2024/06/03 10:06:35 florian Exp $ # $OpenBSD: rc,v 1.577 2024/10/14 02:46:50 deraadt Exp $
# System startup script run by init on autoboot or after single-user. # System startup script run by init on autoboot or after single-user.
# Output and error are redirected to console by init, and the console is the # Output and error are redirected to console by init, and the console is the
@ -242,7 +242,7 @@ reorder_libs() {
done done
for _bin in $_relink/usr/sbin/sshd $_relink/usr/libexec/sshd-session \ for _bin in $_relink/usr/sbin/sshd $_relink/usr/libexec/sshd-session \
$_relink/usr/bin/ssh-agent ; do $_relink/usr/bin/sshd-auth $_relink/usr/bin/ssh-agent ; do
_tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) && _tmpdir=$(mktemp -dq $_relink/_rebuild.XXXXXXXXXXXX) &&
( (
set -o errexit set -o errexit

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ec_asn1.c,v 1.68 2024/10/11 18:58:04 tb Exp $ */ /* $OpenBSD: ec_asn1.c,v 1.71 2024/10/14 12:50:18 tb Exp $ */
/* /*
* Written by Nils Larsch for the OpenSSL project. * Written by Nils Larsch for the OpenSSL project.
*/ */
@ -601,15 +601,41 @@ ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
return ret; return ret;
} }
static int
ec_asn1_encode_field_element(const EC_GROUP *group, const BIGNUM *bn,
ASN1_OCTET_STRING *os)
{
unsigned char *buf;
int len;
int ret = 0;
/* Zero-pad field element per SEC 1, section 2.3.5. */
len = (EC_GROUP_get_degree(group) + 7) / 8;
/* One extra byte for historic NUL termination of ASN1_STRINGs. */
if ((buf = calloc(1, len + 1)) == NULL)
goto err;
if (BN_bn2binpad(bn, buf, len) != len)
goto err;
ASN1_STRING_set0(os, buf, len);
buf = NULL;
len = 0;
ret = 1;
err:
freezero(buf, len);
return ret;
}
static int static int
ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
{ {
BIGNUM *a = NULL, *b = NULL; BIGNUM *a = NULL, *b = NULL;
unsigned char *buffer_1 = NULL, *buffer_2 = NULL, *a_buf = NULL, int ret = 0;
*b_buf = NULL;
size_t len_1, len_2;
unsigned char char_zero = 0;
int ok = 0;
if (!group || !curve || !curve->a || !curve->b) if (!group || !curve || !curve->a || !curve->b)
return 0; return 0;
@ -619,64 +645,30 @@ ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
goto err; goto err;
} }
/* get a and b */
if (!EC_GROUP_get_curve(group, NULL, a, b, NULL)) { if (!EC_GROUP_get_curve(group, NULL, a, b, NULL)) {
ECerror(ERR_R_EC_LIB); ECerror(ERR_R_EC_LIB);
goto err; goto err;
} }
len_1 = (size_t) BN_num_bytes(a);
len_2 = (size_t) BN_num_bytes(b);
if (len_1 == 0) { if (!ec_asn1_encode_field_element(group, a, curve->a)) {
/* len_1 == 0 => a == 0 */ ECerror(ERR_R_EC_LIB);
a_buf = &char_zero; goto err;
len_1 = 1;
} else {
if ((buffer_1 = malloc(len_1)) == NULL) {
ECerror(ERR_R_MALLOC_FAILURE);
goto err;
}
if ((len_1 = BN_bn2bin(a, buffer_1)) == 0) {
ECerror(ERR_R_BN_LIB);
goto err;
}
a_buf = buffer_1;
} }
if (!ec_asn1_encode_field_element(group, b, curve->b)) {
if (len_2 == 0) { ECerror(ERR_R_EC_LIB);
/* len_2 == 0 => b == 0 */
b_buf = &char_zero;
len_2 = 1;
} else {
if ((buffer_2 = malloc(len_2)) == NULL) {
ECerror(ERR_R_MALLOC_FAILURE);
goto err;
}
if ((len_2 = BN_bn2bin(b, buffer_2)) == 0) {
ECerror(ERR_R_BN_LIB);
goto err;
}
b_buf = buffer_2;
}
/* set a and b */
if (!ASN1_STRING_set(curve->a, a_buf, len_1) ||
!ASN1_STRING_set(curve->b, b_buf, len_2)) {
ECerror(ERR_R_ASN1_LIB);
goto err; goto err;
} }
ASN1_BIT_STRING_free(curve->seed); ASN1_BIT_STRING_free(curve->seed);
curve->seed = NULL; curve->seed = NULL;
/* set the seed (optional) */
if (group->seed != NULL) { if (group->seed != NULL) {
if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
ECerror(ERR_R_MALLOC_FAILURE); ECerror(ERR_R_MALLOC_FAILURE);
goto err; goto err;
} }
if (!ASN1_BIT_STRING_set(curve->seed, group->seed, if (!ASN1_BIT_STRING_set(curve->seed,
(int) group->seed_len)) { group->seed, group->seed_len)) {
ECerror(ERR_R_ASN1_LIB); ECerror(ERR_R_ASN1_LIB);
goto err; goto err;
} }
@ -686,15 +678,13 @@ ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
} }
} }
ok = 1; ret = 1;
err: err:
free(buffer_1);
free(buffer_2);
BN_free(a); BN_free(a);
BN_free(b); BN_free(b);
return (ok); return ret;
} }
static ECPARAMETERS * static ECPARAMETERS *

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: SSL_alert_type_string.3,v 1.6 2024/10/09 08:22:28 tb Exp $ .\" $OpenBSD: SSL_alert_type_string.3,v 1.7 2024/10/13 08:25:09 jsg Exp $
.\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100 .\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100
.\" .\"
.\" This file was written by Lutz Jaenicke <jaenicke@openssl.org>. .\" This file was written by Lutz Jaenicke <jaenicke@openssl.org>.
@ -48,7 +48,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: October 9 2024 $ .Dd $Mdocdate: October 13 2024 $
.Dt SSL_ALERT_TYPE_STRING 3 .Dt SSL_ALERT_TYPE_STRING 3
.Os .Os
.Sh NAME .Sh NAME
@ -233,7 +233,7 @@ This message is always a warning.
Sent by the server to indicate that it does not recognize a PSK identity or an Sent by the server to indicate that it does not recognize a PSK identity or an
SRP identity. SRP identity.
.It \(dqCQ\(dq/\(dqcertificate required\(dq .It \(dqCQ\(dq/\(dqcertificate required\(dq
Sent by servers when a client certificate is desired byt none was provided Sent by servers when a client certificate is desired but none was provided
by the client. by the client.
.It \(dqAP\(dq/\(dqno application protocol\(dq .It \(dqAP\(dq/\(dqno application protocol\(dq
Sent by servers when a client ALPN extension advertises only protocols that Sent by servers when a client ALPN extension advertises only protocols that

View file

@ -1,6 +1,7 @@
/* $OpenBSD: ec_asn1_test.c,v 1.3 2024/10/12 16:15:28 tb Exp $ */ /* $OpenBSD: ec_asn1_test.c,v 1.4 2024/10/14 13:16:06 tb Exp $ */
/* /*
* Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -62,6 +63,38 @@ const uint8_t ec_secp256r1_pkparameters_parameters[] = {
0x01, 0x01, 0x01, 0x01,
}; };
const uint8_t ec_secp256k1_pkparameters_parameters[] = {
0x30, 0x81, 0xe0, 0x02, 0x01, 0x01, 0x30, 0x2c,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xfc, 0x2f, 0x30, 0x44, 0x04, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, 0x66,
0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62,
0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc,
0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81,
0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 0xda,
0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb,
0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4,
0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0,
0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,
0x02, 0x01, 0x01,
};
static void static void
hexdump(const unsigned char *buf, size_t len) hexdump(const unsigned char *buf, size_t len)
{ {
@ -94,7 +127,7 @@ compare_data(const char *label, const unsigned char *d1, size_t d1_len,
} }
static int static int
ec_group_pkparameters_test(const char *label, int asn1_flag, ec_group_pkparameters_test(const char *label, int nid, int asn1_flag,
const uint8_t *test_data, size_t test_data_len) const uint8_t *test_data, size_t test_data_len)
{ {
EC_GROUP *group_a = NULL, *group_b = NULL; EC_GROUP *group_a = NULL, *group_b = NULL;
@ -107,7 +140,7 @@ ec_group_pkparameters_test(const char *label, int asn1_flag,
/* /*
* Test i2d_ECPKParameters/d2i_ECPKParameters. * Test i2d_ECPKParameters/d2i_ECPKParameters.
*/ */
if ((group_a = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) if ((group_a = EC_GROUP_new_by_curve_name(nid)) == NULL)
errx(1, "failed to create EC_GROUP"); errx(1, "failed to create EC_GROUP");
EC_GROUP_set_asn1_flag(group_a, asn1_flag); EC_GROUP_set_asn1_flag(group_a, asn1_flag);
@ -182,7 +215,8 @@ static int
ec_group_pkparameters_named_curve_test(void) ec_group_pkparameters_named_curve_test(void)
{ {
return ec_group_pkparameters_test("ECPKPARAMETERS named curve", return ec_group_pkparameters_test("ECPKPARAMETERS named curve",
OPENSSL_EC_NAMED_CURVE, ec_secp256r1_pkparameters_named_curve, NID_X9_62_prime256v1, OPENSSL_EC_NAMED_CURVE,
ec_secp256r1_pkparameters_named_curve,
sizeof(ec_secp256r1_pkparameters_named_curve)); sizeof(ec_secp256r1_pkparameters_named_curve));
} }
@ -190,10 +224,20 @@ static int
ec_group_pkparameters_parameters_test(void) ec_group_pkparameters_parameters_test(void)
{ {
return ec_group_pkparameters_test("ECPKPARAMETERS parameters", return ec_group_pkparameters_test("ECPKPARAMETERS parameters",
OPENSSL_EC_EXPLICIT_CURVE, ec_secp256r1_pkparameters_parameters, NID_X9_62_prime256v1, OPENSSL_EC_EXPLICIT_CURVE,
ec_secp256r1_pkparameters_parameters,
sizeof(ec_secp256r1_pkparameters_parameters)); sizeof(ec_secp256r1_pkparameters_parameters));
} }
static int
ec_group_pkparameters_correct_padding_test(void)
{
return ec_group_pkparameters_test("ECPKPARAMETERS parameters",
NID_secp256k1, OPENSSL_EC_EXPLICIT_CURVE,
ec_secp256k1_pkparameters_parameters,
sizeof(ec_secp256k1_pkparameters_parameters));
}
static int static int
ec_group_roundtrip_curve(const EC_GROUP *group, const char *descr, int nid) ec_group_roundtrip_curve(const EC_GROUP *group, const char *descr, int nid)
{ {
@ -302,6 +346,7 @@ main(int argc, char **argv)
failed |= ec_group_pkparameters_named_curve_test(); failed |= ec_group_pkparameters_named_curve_test();
failed |= ec_group_pkparameters_parameters_test(); failed |= ec_group_pkparameters_parameters_test();
failed |= ec_group_pkparameters_correct_padding_test();
failed |= ec_group_roundtrip_builtin_curves(); failed |= ec_group_roundtrip_builtin_curves();
return (failed); return (failed);

View file

@ -1,4 +1,4 @@
# $OpenBSD: test-exec.sh,v 1.119 2024/06/20 08:18:34 dtucker Exp $ # $OpenBSD: test-exec.sh,v 1.120 2024/10/14 03:02:08 djm Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
#SUDO=sudo #SUDO=sudo
@ -53,6 +53,7 @@ SSHKEYSCAN=ssh-keyscan
SFTP=sftp SFTP=sftp
SFTPSERVER=/usr/libexec/sftp-server SFTPSERVER=/usr/libexec/sftp-server
SSHD_SESSION=/usr/libexec/sshd-session SSHD_SESSION=/usr/libexec/sshd-session
SSHD_AUTH=/usr/libexec/sshd-auth
SCP=scp SCP=scp
# Interop testing # Interop testing
@ -77,6 +78,9 @@ fi
if [ "x$TEST_SSH_SSHD_SESSION" != "x" ]; then if [ "x$TEST_SSH_SSHD_SESSION" != "x" ]; then
SSHD_SESSION="${TEST_SSH_SSHD_SESSION}" SSHD_SESSION="${TEST_SSH_SSHD_SESSION}"
fi fi
if [ "x$TEST_SSH_SSHD_AUTH" != "x" ]; then
SSHD_AUTH="${TEST_SSH_SSHD_AUTH}"
fi
if [ "x$TEST_SSH_SSHD" != "x" ]; then if [ "x$TEST_SSH_SSHD" != "x" ]; then
SSHD="${TEST_SSH_SSHD}" SSHD="${TEST_SSH_SSHD}"
fi fi
@ -426,6 +430,7 @@ cat << EOF > $OBJ/sshd_config
AcceptEnv _XXX_TEST AcceptEnv _XXX_TEST
Subsystem sftp $SFTPSERVER Subsystem sftp $SFTPSERVER
SshdSessionPath $SSHD_SESSION SshdSessionPath $SSHD_SESSION
SshdAuthPath $SSHD_AUTH
PerSourcePenalties no PerSourcePenalties no
EOF EOF

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: ddb.4,v 1.108 2024/09/05 08:52:27 bluhm Exp $ .\" $OpenBSD: ddb.4,v 1.109 2024/10/14 07:05:23 jmc Exp $
.\" $NetBSD: ddb.4,v 1.5 1994/11/30 16:22:09 jtc Exp $ .\" $NetBSD: ddb.4,v 1.5 1994/11/30 16:22:09 jtc Exp $
.\" .\"
.\" Mach Operating System .\" Mach Operating System
@ -25,7 +25,7 @@
.\" any improvements or extensions that they make and grant Carnegie Mellon .\" any improvements or extensions that they make and grant Carnegie Mellon
.\" the rights to redistribute these changes. .\" the rights to redistribute these changes.
.\" .\"
.Dd $Mdocdate: September 5 2024 $ .Dd $Mdocdate: October 14 2024 $
.Dt DDB 4 .Dt DDB 4
.Os .Os
.Sh NAME .Sh NAME
@ -1168,14 +1168,6 @@ Register names can be found with the
.Ic show registers .Ic show registers
command. command.
.Pp .Pp
Some variable names are suffixed with numbers, and some may have a modifier
following a colon immediately after the variable name.
For example, register variables can have the
.Ql :u
modifier to indicate a
user register (e.g.,
.Ql $eax:u ) .
.Pp
Built-in debugger variables currently supported are: Built-in debugger variables currently supported are:
.Bl -tag -width 10n -compact -offset indent .Bl -tag -width 10n -compact -offset indent
.It Va $radix .It Va $radix
@ -1277,16 +1269,13 @@ command.
The last address explicitly specified. The last address explicitly specified.
.It Li $ Ns Ar variable .It Li $ Ns Ar variable
The value of a register or variable. The value of a register or variable.
The name may be followed by a
.Ql \&:
and modifiers as described above with
.Ar identifier .
.It Ar expr Li # Ar expr .It Ar expr Li # Ar expr
A binary operator which rounds up the left hand side to the next A binary operator which rounds up the left hand side to the next
multiple of right hand side. multiple of right hand side.
.It Li * Ns Ar expr .It Li * Ns Ar expr
Indirection. Indirection.
It may be followed by a ':' and modifiers as described above. It may be followed by a ':' as described above with
.Ar identifier .
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr ctfstrip 1 , .Xr ctfstrip 1 ,

View file

@ -1,4 +1,4 @@
/* $OpenBSD: acpi_machdep.c,v 1.111 2024/09/01 03:08:56 jsg Exp $ */ /* $OpenBSD: acpi_machdep.c,v 1.112 2024/10/14 11:49:34 jan Exp $ */
/* /*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* *
@ -366,10 +366,10 @@ acpi_attach_machdep(struct acpi_softc *sc)
/* Unmap, will be remapped in acpi_sleep_cpu */ /* Unmap, will be remapped in acpi_sleep_cpu */
pmap_kremove(ACPI_TRAMPOLINE, PAGE_SIZE); pmap_kremove(ACPI_TRAMPOLINE, PAGE_SIZE);
pmap_kremove(ACPI_TRAMP_DATA, PAGE_SIZE); pmap_kremove(ACPI_TRAMP_DATA, PAGE_SIZE);
#endif /* SMALL_KERNEL */ #endif /* ! SMALL_KERNEL */
} }
#ifndef SMALL_KERNEL #if defined(SUSPEND) && !defined(SMALL_KERNEL)
/* /*
* This function may not have local variables due to a bug between * This function may not have local variables due to a bug between
* acpi_savecpu() and the resume path. * acpi_savecpu() and the resume path.
@ -562,7 +562,7 @@ resume_mp(void)
} }
#endif /* MULTIPROCESSOR */ #endif /* MULTIPROCESSOR */
#endif /* ! SMALL_KERNEL */ #endif /* defined(SUSPEND) && !defined(SMALL_KERNEL) */
bus_dma_tag_t bus_dma_tag_t
acpi_iommu_device_map(struct aml_node *node, bus_dma_tag_t dmat) acpi_iommu_device_map(struct aml_node *node, bus_dma_tag_t dmat)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: process_machdep.c,v 1.8 2023/06/10 19:30:48 kettenis Exp $ */ /* $OpenBSD: process_machdep.c,v 1.9 2024/10/14 12:02:16 jsg Exp $ */
/* /*
* Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
* *
@ -48,6 +48,7 @@
#include <machine/fpu.h> #include <machine/fpu.h>
#include <machine/pcb.h> #include <machine/pcb.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <machine/vmparam.h>
#include <arm64/armreg.h> #include <arm64/armreg.h>

View file

@ -1,4 +1,4 @@
/* $OpenBSD: intr.h,v 1.22 2023/09/12 08:29:28 jmatthew Exp $ */ /* $OpenBSD: intr.h,v 1.23 2024/10/14 10:08:13 jsg Exp $ */
/* /*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@ -79,7 +79,6 @@
#define IST_EDGE_BOTH 6 #define IST_EDGE_BOTH 6
#ifndef _LOCORE #ifndef _LOCORE
#include <sys/device.h>
#include <sys/queue.h> #include <sys/queue.h>
int splraise(int); int splraise(int);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pte.h,v 1.9 2024/09/29 12:22:57 jsg Exp $ */ /* $OpenBSD: pte.h,v 1.10 2024/10/14 12:02:16 jsg Exp $ */
/* /*
* Copyright (c) 2014 Dale Rahn <drahn@dalerahn.com> * Copyright (c) 2014 Dale Rahn <drahn@dalerahn.com>
* *
@ -17,8 +17,6 @@
#ifndef _ARM_PTE_H_ #ifndef _ARM_PTE_H_
#define _ARM_PTE_H_ #define _ARM_PTE_H_
#include "arm64/vmparam.h"
/* level X descriptor */ /* level X descriptor */
#define Lx_TYPE_MASK (0x00000003) /* mask of type bits */ #define Lx_TYPE_MASK (0x00000003) /* mask of type bits */
#define Lx_TYPE_S (0x00000001) #define Lx_TYPE_S (0x00000001)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: intr.h,v 1.14 2020/07/17 08:07:34 patrick Exp $ */ /* $OpenBSD: intr.h,v 1.15 2024/10/14 10:08:13 jsg Exp $ */
/* $NetBSD: intr.h,v 1.12 2003/06/16 20:00:59 thorpej Exp $ */ /* $NetBSD: intr.h,v 1.12 2003/06/16 20:00:59 thorpej Exp $ */
/* /*
@ -78,7 +78,6 @@
#define IST_EDGE_BOTH 6 #define IST_EDGE_BOTH 6
#ifndef _LOCORE #ifndef _LOCORE
#include <sys/device.h>
#include <sys/queue.h> #include <sys/queue.h>
struct cpu_info; struct cpu_info;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: midivar.h,v 1.14 2023/09/26 19:55:24 mvs Exp $ */ /* $OpenBSD: midivar.h,v 1.15 2024/10/14 00:47:36 jsg Exp $ */
/* /*
* Copyright (c) 2003, 2004 Alexandre Ratchov * Copyright (c) 2003, 2004 Alexandre Ratchov
@ -22,7 +22,6 @@
#include <dev/midi_if.h> #include <dev/midi_if.h>
#include <sys/device.h> #include <sys/device.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/proc.h>
#include <sys/timeout.h> #include <sys/timeout.h>
#define MIDI_RATE 3125 /* midi uart baud rate in bytes/second */ #define MIDI_RATE 3125 /* midi uart baud rate in bytes/second */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_wg.h,v 1.5 2023/06/01 18:57:53 kn Exp $ */ /* $OpenBSD: if_wg.h,v 1.6 2024/10/13 00:53:21 jsg Exp $ */
/* /*
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
@ -20,9 +20,6 @@
#ifndef __IF_WG_H__ #ifndef __IF_WG_H__
#define __IF_WG_H__ #define __IF_WG_H__
#include <sys/limits.h>
#include <sys/errno.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ip_mroute.h,v 1.31 2022/05/05 13:57:40 claudio Exp $ */ /* $OpenBSD: ip_mroute.h,v 1.32 2024/10/13 02:27:44 jsg Exp $ */
/* $NetBSD: ip_mroute.h,v 1.23 2004/04/21 17:49:46 itojun Exp $ */ /* $NetBSD: ip_mroute.h,v 1.23 2004/04/21 17:49:46 itojun Exp $ */
#ifndef _NETINET_IP_MROUTE_H_ #ifndef _NETINET_IP_MROUTE_H_
@ -18,8 +18,6 @@
* advanced API support, bandwidth metering and signaling. * advanced API support, bandwidth metering and signaling.
*/ */
#include <sys/timeout.h>
/* /*
* Multicast Routing set/getsockopt commands. * Multicast Routing set/getsockopt commands.
*/ */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: dirhash.h,v 1.8 2022/01/11 03:13:59 jsg Exp $ */ /* $OpenBSD: dirhash.h,v 1.9 2024/10/14 02:20:01 jsg Exp $ */
/* /*
* Copyright (c) 2001 Ian Dowse. All rights reserved. * Copyright (c) 2001 Ian Dowse. All rights reserved.
* *
@ -29,7 +29,7 @@
#ifndef _UFS_UFS_DIRHASH_H_ #ifndef _UFS_UFS_DIRHASH_H_
#define _UFS_UFS_DIRHASH_H_ #define _UFS_UFS_DIRHASH_H_
#include <sys/mutex.h> #include <sys/rwlock.h>
/* /*
* For fast operations on large directories, we maintain a hash * For fast operations on large directories, we maintain a hash

View file

@ -1,4 +1,4 @@
/* $OpenBSD: socket.c,v 1.33 2022/12/26 19:16:02 jmc Exp $ */ /* $OpenBSD: socket.c,v 1.34 2024/10/13 03:35:59 jsg Exp $ */
/* /*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -31,6 +31,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <err.h> #include <err.h>
#include <stdio.h>
#include "extern.h" #include "extern.h"

View file

@ -1,8 +1,8 @@
# $OpenBSD: Makefile,v 1.18 2024/05/17 00:30:23 djm Exp $ # $OpenBSD: Makefile,v 1.19 2024/10/14 01:57:50 djm Exp $
.include <bsd.own.mk> .include <bsd.own.mk>
SUBDIR= ssh sshd sshd-session \ SUBDIR= ssh sshd sshd-session sshd-auth \
ssh-add ssh-keygen ssh-agent scp sftp-server \ ssh-add ssh-keygen ssh-agent scp sftp-server \
ssh-keysign ssh-keyscan sftp ssh-pkcs11-helper ssh-sk-helper ssh-keysign ssh-keyscan sftp ssh-pkcs11-helper ssh-sk-helper

View file

@ -1,4 +1,4 @@
# $OpenBSD: Makefile.inc,v 1.96 2024/09/09 02:39:57 djm Exp $ # $OpenBSD: Makefile.inc,v 1.97 2024/10/14 01:57:50 djm Exp $
.include <bsd.own.mk> .include <bsd.own.mk>
@ -29,9 +29,9 @@ CDIAGFLAGS+= -Wold-style-definition
CDIAGFLAGS+= -Werror CDIAGFLAGS+= -Werror
.endif .endif
#CDIAGFLAGS+= -fno-common CDIAGFLAGS+= -fno-common
#DEBUG=-g DEBUG=-g
#INSTALL_STRIP= INSTALL_STRIP=
WARNINGS=yes WARNINGS=yes

View file

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.439 2024/07/25 22:40:08 djm Exp $ */ /* $OpenBSD: channels.c,v 1.440 2024/10/13 22:20:06 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -5219,3 +5219,22 @@ x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id,
fatal_fr(r, "send x11-req"); fatal_fr(r, "send x11-req");
free(new_data); free(new_data);
} }
/*
* Returns whether an x11 channel was used recently (less than a second ago)
*/
int
x11_channel_used_recently(struct ssh *ssh) {
u_int i;
Channel *c;
time_t lastused = 0;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c == NULL || c->ctype == NULL || c->lastused == 0 ||
strcmp(c->ctype, "x11-connection") != 0)
continue;
lastused = c->lastused;
}
return lastused != 0 && monotime() > lastused + 1;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.157 2024/07/25 22:40:08 djm Exp $ */ /* $OpenBSD: channels.h,v 1.158 2024/10/13 22:20:06 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -379,6 +379,7 @@ int x11_connect_display(struct ssh *);
int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
void x11_request_forwarding_with_spoofing(struct ssh *, int, void x11_request_forwarding_with_spoofing(struct ssh *, int,
const char *, const char *, const char *, int); const char *, const char *, const char *, int);
int x11_channel_used_recently(struct ssh *ssh);
/* channel close */ /* channel close */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.408 2024/07/01 04:31:17 djm Exp $ */ /* $OpenBSD: clientloop.c,v 1.409 2024/10/13 22:20:06 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -650,9 +650,10 @@ obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout,
if (just_started) if (just_started)
return 1; return 1;
/* Don't arm output fd for poll until the timing interval has elapsed */ /* Don't arm output fd for poll until the timing interval has elapsed... */
if (timespeccmp(&now, &next_interval, <)) if (timespeccmp(&now, &next_interval, <))
return 0; /* ...unless there's x11 communicattion happening */
return x11_channel_used_recently(ssh);
/* Calculate number of intervals missed since the last check */ /* Calculate number of intervals missed since the last check */
n = (now.tv_sec - next_interval.tv_sec) * 1000LL * 1000 * 1000; n = (now.tv_sec - next_interval.tv_sec) * 1000LL * 1000 * 1000;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: log.c,v 1.62 2024/06/27 22:36:44 djm Exp $ */ /* $OpenBSD: log.c,v 1.63 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -418,9 +418,9 @@ sshlogv(const char *file, const char *func, int line, int showfunc,
if (nlog_verbose == 0 && level > log_level) if (nlog_verbose == 0 && level > log_level)
return; return;
snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)", snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (bin=%s, pid=%ld)",
(cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line, (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line,
(long)getpid()); argv0 == NULL ? "UNKNOWN" : argv0, (long)getpid());
for (i = 0; i < nlog_verbose; i++) { for (i = 0; i < nlog_verbose; i++) {
if (match_pattern_list(tag, log_verbose[i], 0) == 1) { if (match_pattern_list(tag, log_verbose[i], 0) == 1) {
forced = 1; forced = 1;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.245 2024/09/22 12:56:21 jsg Exp $ */ /* $OpenBSD: monitor.c,v 1.246 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -90,7 +90,9 @@ static Gssctxt *gsscontext = NULL;
/* Imports */ /* Imports */
extern ServerOptions options; extern ServerOptions options;
extern u_int utmp_len; extern u_int utmp_len;
extern struct sshbuf *cfg;
extern struct sshbuf *loginmsg; extern struct sshbuf *loginmsg;
extern struct include_list includes;
extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
/* State exported from the child */ /* State exported from the child */
@ -111,6 +113,7 @@ int mm_answer_keyverify(struct ssh *, int, struct sshbuf *);
int mm_answer_pty(struct ssh *, int, struct sshbuf *); int mm_answer_pty(struct ssh *, int, struct sshbuf *);
int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *); int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *);
int mm_answer_term(struct ssh *, int, struct sshbuf *); int mm_answer_term(struct ssh *, int, struct sshbuf *);
int mm_answer_state(struct ssh *, int, struct sshbuf *);
#ifdef GSSAPI #ifdef GSSAPI
int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *);
@ -155,6 +158,7 @@ static int monitor_read(struct ssh *, struct monitor *, struct mon_table *,
static int monitor_read_log(struct monitor *); static int monitor_read_log(struct monitor *);
struct mon_table mon_dispatch_proto20[] = { struct mon_table mon_dispatch_proto20[] = {
{MONITOR_REQ_STATE, MON_ONCE, mm_answer_state},
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
{MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
#endif #endif
@ -177,6 +181,7 @@ struct mon_table mon_dispatch_proto20[] = {
}; };
struct mon_table mon_dispatch_postauth20[] = { struct mon_table mon_dispatch_postauth20[] = {
{MONITOR_REQ_STATE, MON_ONCE, mm_answer_state},
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
{MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
#endif #endif
@ -236,7 +241,8 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
ssh->authctxt = authctxt; ssh->authctxt = authctxt;
mon_dispatch = mon_dispatch_proto20; mon_dispatch = mon_dispatch_proto20;
/* Permit requests for moduli and signatures */ /* Permit requests for state, moduli and signatures */
monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
@ -339,6 +345,7 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor)
mon_dispatch = mon_dispatch_postauth20; mon_dispatch = mon_dispatch_postauth20;
/* Permit requests for moduli and signatures */ /* Permit requests for moduli and signatures */
monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
@ -396,7 +403,8 @@ monitor_read_log(struct monitor *pmonitor)
/* Log it */ /* Log it */
if (log_level_name(level) == NULL) if (log_level_name(level) == NULL)
fatal_f("invalid log level %u (corrupted message?)", level); fatal_f("invalid log level %u (corrupted message?)", level);
sshlogdirect(level, forced, "%s [preauth]", msg); sshlogdirect(level, forced, "%s [%s]", msg,
mon_dispatch == mon_dispatch_postauth20 ? "postauth" : "preauth");
sshbuf_free(logmsg); sshbuf_free(logmsg);
free(msg); free(msg);
@ -502,6 +510,82 @@ monitor_reset_key_state(void)
hostbased_chost = NULL; hostbased_chost = NULL;
} }
int
mm_answer_state(struct ssh *ssh, int sock, struct sshbuf *m)
{
struct sshbuf *inc = NULL, *hostkeys = NULL;
struct sshbuf *opts = NULL, *confdata = NULL;
struct include_item *item = NULL;
int postauth;
int r;
sshbuf_reset(m);
debug_f("config len %zu", sshbuf_len(cfg));
if ((m = sshbuf_new()) == NULL ||
(inc = sshbuf_new()) == NULL ||
(opts = sshbuf_new()) == NULL ||
(confdata = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed");
/* XXX unneccessary? */
/* pack includes into a string */
TAILQ_FOREACH(item, &includes, entry) {
if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 ||
(r = sshbuf_put_cstring(inc, item->filename)) != 0 ||
(r = sshbuf_put_stringb(inc, item->contents)) != 0)
fatal_fr(r, "compose includes");
}
hostkeys = pack_hostkeys();
/*
* Protocol from monitor to unpriv privsep process:
* string configuration
* uint64 timing_secret XXX move delays to monitor and remove
* string host_keys[] {
* string public_key
* string certificate
* }
* string server_banner
* string client_banner
* string included_files[] {
* string selector
* string filename
* string contents
* }
* string configuration_data (postauth)
* string keystate (postauth)
* string authenticated_user (postauth)
* string session_info (postauth)
* string authopts (postauth)
*/
if ((r = sshbuf_put_stringb(m, cfg)) != 0 ||
(r = sshbuf_put_u64(m, options.timing_secret)) != 0 ||
(r = sshbuf_put_stringb(m, hostkeys)) != 0 ||
(r = sshbuf_put_stringb(m, ssh->kex->server_version)) != 0 ||
(r = sshbuf_put_stringb(m, ssh->kex->client_version)) != 0 ||
(r = sshbuf_put_stringb(m, inc)) != 0)
fatal_fr(r, "compose config");
postauth = (authctxt && authctxt->pw && authctxt->authenticated);
if (postauth) {
/* XXX shouldn't be reachable */
fatal_f("internal error: called in postauth");
}
sshbuf_free(inc);
sshbuf_free(opts);
sshbuf_free(confdata);
mm_request_send(sock, MONITOR_ANS_STATE, m);
debug3_f("done");
return (0);
}
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
int int
mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m) mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
@ -547,24 +631,27 @@ int
mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
{ {
extern int auth_sock; /* XXX move to state struct? */ extern int auth_sock; /* XXX move to state struct? */
struct sshkey *key; struct sshkey *pubkey, *key;
struct sshbuf *sigbuf = NULL; struct sshbuf *sigbuf = NULL;
u_char *p = NULL, *signature = NULL; u_char *p = NULL, *signature = NULL;
char *alg = NULL; char *alg = NULL;
size_t datlen, siglen, alglen; size_t datlen, siglen;
int r, is_proof = 0; int r, is_proof = 0, keyid;
u_int keyid, compat; u_int compat;
const char proof_req[] = "hostkeys-prove-00@openssh.com"; const char proof_req[] = "hostkeys-prove-00@openssh.com";
debug3_f("entering"); debug3_f("entering");
if ((r = sshbuf_get_u32(m, &keyid)) != 0 || if ((r = sshkey_froms(m, &pubkey)) != 0 ||
(r = sshbuf_get_string(m, &p, &datlen)) != 0 || (r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
(r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 || (r = sshbuf_get_cstring(m, &alg, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &compat)) != 0) (r = sshbuf_get_u32(m, &compat)) != 0)
fatal_fr(r, "parse"); fatal_fr(r, "parse");
if (keyid > INT_MAX)
fatal_f("invalid key ID"); if ((keyid = get_hostkey_index(pubkey, 1, ssh)) == -1)
fatal_f("unknown hostkey");
debug_f("hostkey %s index %d", sshkey_ssh_name(pubkey), keyid);
sshkey_free(pubkey);
/* /*
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),

View file

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.h,v 1.24 2024/05/17 00:30:24 djm Exp $ */ /* $OpenBSD: monitor.h,v 1.25 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -56,6 +56,7 @@ enum monitor_reqtype {
MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
MONITOR_REQ_TERM = 50, MONITOR_REQ_TERM = 50,
MONITOR_REQ_STATE = 51, MONITOR_ANS_STATE = 52
}; };
struct ssh; struct ssh;
@ -89,4 +90,6 @@ void mm_get_keystate(struct ssh *, struct monitor *);
/* XXX: should be returned via a monitor call rather than config_fd */ /* XXX: should be returned via a monitor call rather than config_fd */
void mm_encode_server_options(struct sshbuf *); void mm_encode_server_options(struct sshbuf *);
struct sshbuf *pack_hostkeys(void);
#endif /* _MONITOR_H_ */ #endif /* _MONITOR_H_ */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.136 2024/06/19 23:24:47 djm Exp $ */ /* $OpenBSD: monitor_wrap.c,v 1.137 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -107,16 +107,6 @@ mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx)
sshbuf_free(log_msg); sshbuf_free(log_msg);
} }
int
mm_is_monitor(void)
{
/*
* m_pid is only set in the privileged part, and
* points to the unprivileged child.
*/
return (pmonitor && pmonitor->m_pid > 0);
}
static void static void
mm_reap(void) mm_reap(void)
{ {
@ -260,15 +250,13 @@ mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *hostkey_alg, const u_char *data, size_t datalen, const char *hostkey_alg,
const char *sk_provider, const char *sk_pin, u_int compat) const char *sk_provider, const char *sk_pin, u_int compat)
{ {
struct kex *kex = *pmonitor->m_pkex;
struct sshbuf *m; struct sshbuf *m;
u_int ndx = kex->host_key_index(key, 0, ssh);
int r; int r;
debug3_f("entering"); debug3_f("entering");
if ((m = sshbuf_new()) == NULL) if ((m = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed"); fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u32(m, ndx)) != 0 || if ((r = sshkey_puts(key, m)) != 0 ||
(r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 ||
(r = sshbuf_put_cstring(m, hostkey_alg)) != 0 || (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
(r = sshbuf_put_u32(m, compat)) != 0) (r = sshbuf_put_u32(m, compat)) != 0)
@ -281,6 +269,7 @@ mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
if ((r = sshbuf_get_string(m, sigp, lenp)) != 0) if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
fatal_fr(r, "parse"); fatal_fr(r, "parse");
sshbuf_free(m); sshbuf_free(m);
debug3_f("%s signature len=%zu", hostkey_alg, *lenp);
return (0); return (0);
} }
@ -686,6 +675,72 @@ mm_terminate(void)
sshbuf_free(m); sshbuf_free(m);
} }
/* Request state information */
void
mm_get_state(struct ssh *ssh, struct include_list *includes,
struct sshbuf *conf, struct sshbuf **confdatap,
uint64_t *timing_secretp,
struct sshbuf **hostkeysp, struct sshbuf **keystatep,
u_char **pw_namep,
struct sshbuf **authinfop, struct sshbuf **auth_optsp)
{
struct sshbuf *m, *inc;
u_char *cp;
size_t len;
int r;
struct include_item *item;
debug3_f("entering");
if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_STATE, m);
debug3_f("waiting for MONITOR_ANS_STATE");
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_STATE, m);
if ((r = sshbuf_get_string(m, &cp, &len)) != 0 ||
(r = sshbuf_get_u64(m, timing_secretp)) != 0 ||
(r = sshbuf_froms(m, hostkeysp)) != 0 ||
(r = sshbuf_get_stringb(m, ssh->kex->server_version)) != 0 ||
(r = sshbuf_get_stringb(m, ssh->kex->client_version)) != 0 ||
(r = sshbuf_get_stringb(m, inc)) != 0)
fatal_fr(r, "parse config");
/* postauth */
if (confdatap) {
if ((r = sshbuf_froms(m, confdatap)) != 0 ||
(r = sshbuf_froms(m, keystatep)) != 0 ||
(r = sshbuf_get_string(m, pw_namep, NULL)) != 0 ||
(r = sshbuf_froms(m, authinfop)) != 0 ||
(r = sshbuf_froms(m, auth_optsp)) != 0)
fatal_fr(r, "parse config postauth");
}
if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
fatal_fr(r, "sshbuf_put");
while (sshbuf_len(inc) != 0) {
item = xcalloc(1, sizeof(*item));
if ((item->contents = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed");
if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 ||
(r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 ||
(r = sshbuf_get_stringb(inc, item->contents)) != 0)
fatal_fr(r, "parse includes");
TAILQ_INSERT_TAIL(includes, item, entry);
}
free(cp);
sshbuf_free(m);
sshbuf_free(inc);
debug3_f("done");
}
static void static void
mm_chall_setup(char **name, char **infotxt, u_int *numprompts, mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
char ***prompts, u_int **echo_on) char ***prompts, u_int **echo_on)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.h,v 1.51 2024/05/17 06:42:04 jsg Exp $ */ /* $OpenBSD: monitor_wrap.h,v 1.52 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -75,6 +75,12 @@ void mm_session_pty_cleanup2(struct Session *);
void mm_send_keystate(struct ssh *, struct monitor*); void mm_send_keystate(struct ssh *, struct monitor*);
/* state */
struct include_list;
void mm_get_state(struct ssh *, struct include_list *, struct sshbuf *,
struct sshbuf **, uint64_t *, struct sshbuf **, struct sshbuf **,
u_char **, struct sshbuf **, struct sshbuf **);
/* bsdauth */ /* bsdauth */
int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_bsdauth_respond(void *, u_int, char **); int mm_bsdauth_respond(void *, u_int, char **);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pathnames.h,v 1.32 2024/05/17 00:30:24 djm Exp $ */ /* $OpenBSD: pathnames.h,v 1.33 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -41,6 +41,7 @@
/* Binary paths for the sshd components */ /* Binary paths for the sshd components */
#define _PATH_SSHD_SESSION "/usr/libexec/sshd-session" #define _PATH_SSHD_SESSION "/usr/libexec/sshd-session"
#define _PATH_SSHD_AUTH "/usr/libexec/sshd-auth"
/* /*
* The process id of the daemon listening for connections is saved here to * The process id of the daemon listening for connections is saved here to

View file

@ -1,71 +0,0 @@
/* $OpenBSD: sandbox-pledge.c,v 1.2 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2015 Theo de Raadt <deraadt@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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include "log.h"
#include "ssh-sandbox.h"
#include "xmalloc.h"
struct ssh_sandbox {
pid_t child_pid;
};
struct ssh_sandbox *
ssh_sandbox_init(void)
{
struct ssh_sandbox *box;
debug3_f("preparing pledge sandbox");
box = xcalloc(1, sizeof(*box));
box->child_pid = 0;
return box;
}
void
ssh_sandbox_child(struct ssh_sandbox *box)
{
if (pledge("stdio", NULL) == -1)
fatal_f("pledge()");
}
void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
debug3_f("finished");
}
void
ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
{
box->child_pid = child_pid;
/* Nothing to do here */
}

View file

@ -1,86 +0,0 @@
/* $OpenBSD: sandbox-rlimit.c,v 1.5 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2011 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "log.h"
#include "ssh-sandbox.h"
#include "xmalloc.h"
/* Minimal sandbox that sets zero nfiles, nprocs and filesize rlimits */
struct ssh_sandbox {
pid_t child_pid;
};
struct ssh_sandbox *
ssh_sandbox_init(void)
{
struct ssh_sandbox *box;
/*
* Strictly, we don't need to maintain any state here but we need
* to return non-NULL to satisfy the API.
*/
debug3_f("preparing rlimit sandbox");
box = xcalloc(1, sizeof(*box));
box->child_pid = 0;
return box;
}
void
ssh_sandbox_child(struct ssh_sandbox *box)
{
struct rlimit rl_zero;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
strerror(errno));
if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
fatal_f("setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
strerror(errno));
if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
strerror(errno));
}
void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
debug3_f("finished");
}
void
ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
{
box->child_pid = child_pid;
/* Nothing to do here */
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.c,v 1.419 2024/09/25 01:24:04 djm Exp $ */ /* $OpenBSD: servconf.c,v 1.420 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -191,6 +191,7 @@ initialize_server_options(ServerOptions *options)
options->num_channel_timeouts = 0; options->num_channel_timeouts = 0;
options->unused_connection_timeout = -1; options->unused_connection_timeout = -1;
options->sshd_session_path = NULL; options->sshd_session_path = NULL;
options->sshd_auth_path = NULL;
options->refuse_connection = -1; options->refuse_connection = -1;
} }
@ -461,6 +462,8 @@ fill_default_server_options(ServerOptions *options)
options->unused_connection_timeout = 0; options->unused_connection_timeout = 0;
if (options->sshd_session_path == NULL) if (options->sshd_session_path == NULL)
options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION); options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION);
if (options->sshd_auth_path == NULL)
options->sshd_auth_path = xstrdup(_PATH_SSHD_AUTH);
if (options->refuse_connection == -1) if (options->refuse_connection == -1)
options->refuse_connection = 0; options->refuse_connection = 0;
@ -542,7 +545,7 @@ typedef enum {
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout,
sSshdSessionPath, sRefuseConnection, sSshdSessionPath, sSshdAuthPath, sRefuseConnection,
sDeprecated, sIgnore, sUnsupported sDeprecated, sIgnore, sUnsupported
} ServerOpCodes; } ServerOpCodes;
@ -692,6 +695,7 @@ static struct {
{ "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "channeltimeout", sChannelTimeout, SSHCFG_ALL },
{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
{ "sshdauthpath", sSshdAuthPath, SSHCFG_GLOBAL },
{ "refuseconnection", sRefuseConnection, SSHCFG_ALL }, { "refuseconnection", sRefuseConnection, SSHCFG_ALL },
{ NULL, sBadOption, 0 } { NULL, sBadOption, 0 }
}; };
@ -2623,6 +2627,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
charptr = &options->sshd_session_path; charptr = &options->sshd_session_path;
goto parse_filename; goto parse_filename;
case sSshdAuthPath:
charptr = &options->sshd_auth_path;
goto parse_filename;
case sRefuseConnection: case sRefuseConnection:
intptr = &options->refuse_connection; intptr = &options->refuse_connection;
multistate_ptr = multistate_flag; multistate_ptr = multistate_flag;
@ -3198,6 +3206,7 @@ dump_config(ServerOptions *o)
dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
dump_cfg_string(sRDomain, o->routing_domain); dump_cfg_string(sRDomain, o->routing_domain);
dump_cfg_string(sSshdSessionPath, o->sshd_session_path); dump_cfg_string(sSshdSessionPath, o->sshd_session_path);
dump_cfg_string(sSshdAuthPath, o->sshd_auth_path);
dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt); dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt);
/* string arguments requiring a lookup */ /* string arguments requiring a lookup */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.168 2024/09/15 01:18:26 djm Exp $ */ /* $OpenBSD: servconf.h,v 1.169 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -246,6 +246,7 @@ typedef struct {
int unused_connection_timeout; int unused_connection_timeout;
char *sshd_session_path; char *sshd_session_path;
char *sshd_auth_path;
int refuse_connection; int refuse_connection;
} ServerOptions; } ServerOptions;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.338 2024/05/17 00:30:24 djm Exp $ */ /* $OpenBSD: session.c,v 1.339 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -1224,8 +1224,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
/* remove hostkey from the child's memory */ /* remove keys from memory */
destroy_sensitive_data();
ssh_packet_clear_keys(ssh); ssh_packet_clear_keys(ssh);
/* Force a password change */ /* Force a password change */
@ -1827,10 +1826,6 @@ session_signal_req(struct ssh *ssh, Session *s)
signame, s->forced ? "forced-command" : "subsystem"); signame, s->forced ? "forced-command" : "subsystem");
goto out; goto out;
} }
if (mm_is_monitor()) {
error_f("session signalling requires privilege separation");
goto out;
}
debug_f("signal %s, killpg(%ld, %d)", signame, (long)s->pid, sig); debug_f("signal %s, killpg(%ld, %d)", signame, (long)s->pid, sig);
temporarily_use_uid(s->pw); temporarily_use_uid(s->pw);

View file

@ -1,23 +0,0 @@
/* $OpenBSD: ssh-sandbox.h,v 1.1 2011/06/23 09:34:13 djm Exp $ */
/*
* Copyright (c) 2011 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct ssh_sandbox;
struct ssh_sandbox *ssh_sandbox_init(void);
void ssh_sandbox_child(struct ssh_sandbox *);
void ssh_sandbox_parent_finish(struct ssh_sandbox *);
void ssh_sandbox_parent_preauth(struct ssh_sandbox *, pid_t);

836
usr.bin/ssh/sshd-auth.c Normal file
View file

@ -0,0 +1,836 @@
/* $OpenBSD: sshd-auth.c,v 1.1 2024/10/14 01:57:50 djm Exp $ */
/*
* SSH2 implementation:
* Privilege Separation:
*
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/tree.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <limits.h>
#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#include <openssl/evp.h>
#endif
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "sshpty.h"
#include "packet.h"
#include "log.h"
#include "sshbuf.h"
#include "misc.h"
#include "match.h"
#include "servconf.h"
#include "uidswap.h"
#include "compat.h"
#include "cipher.h"
#include "digest.h"
#include "sshkey.h"
#include "kex.h"
#include "authfile.h"
#include "pathnames.h"
#include "atomicio.h"
#include "canohost.h"
#include "hostfile.h"
#include "auth.h"
#include "authfd.h"
#include "msg.h"
#include "dispatch.h"
#include "channels.h"
#include "session.h"
#include "monitor.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "auth-options.h"
#include "version.h"
#include "ssherr.h"
#include "sk-api.h"
#include "srclimit.h"
#include "dh.h"
/* Privsep fds */
#define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1)
#define PRIVSEP_LOG_FD (STDERR_FILENO + 2)
#define PRIVSEP_MIN_FREE_FD (STDERR_FILENO + 3)
extern char *__progname;
/* Server configuration options. */
ServerOptions options;
/* Name of the server configuration file. */
char *config_file_name = _PATH_SERVER_CONFIG_FILE;
/*
* Debug mode flag. This can be set on the command line. If debug
* mode is enabled, extra debugging output will be sent to the system
* log, the daemon will not go to background, and will exit after processing
* the first connection.
*/
int debug_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
static int inetd_flag = 0;
/* Saved arguments to main(). */
static char **saved_argv;
/* Daemon's agent connection */
int auth_sock = -1;
static int have_agent = 0;
u_int num_hostkeys;
struct sshkey **host_pubkeys; /* all public host keys */
struct sshkey **host_certificates; /* all public host certificates */
/* record remote hostname or ip */
u_int utmp_len = HOST_NAME_MAX+1;
/* variables used for privilege separation */
struct monitor *pmonitor = NULL;
int privsep_is_preauth = 1;
/* global connection state and authentication contexts */
Authctxt *the_authctxt = NULL;
struct ssh *the_active_state;
/* global key/cert auth options. XXX move to permanent ssh->authctxt? */
struct sshauthopt *auth_opts = NULL;
/* sshd_config buffer */
struct sshbuf *cfg;
/* Included files from the configuration file */
struct include_list includes = TAILQ_HEAD_INITIALIZER(includes);
/* message to be displayed after login */
struct sshbuf *loginmsg;
/* Prototypes for various functions defined later in this file. */
static void do_ssh2_kex(struct ssh *);
/* XXX stub */
int
mm_is_monitor(void)
{
return 0;
}
static void
privsep_child_demote(void)
{
gid_t gidset[1];
struct passwd *pw;
/* Demote the child */
if (getuid() == 0 || geteuid() == 0) {
if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
fatal("Privilege separation user %s does not exist",
SSH_PRIVSEP_USER);
pw = pwcopy(pw); /* Ensure mutable */
endpwent();
freezero(pw->pw_passwd, strlen(pw->pw_passwd));
/* Change our root directory */
if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
strerror(errno));
if (chdir("/") == -1)
fatal("chdir(\"/\"): %s", strerror(errno));
/*
* Drop our privileges
* NB. Can't use setusercontext() after chroot.
*/
debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,
(u_int)pw->pw_gid);
gidset[0] = pw->pw_gid;
if (setgroups(1, gidset) == -1)
fatal("setgroups: %.100s", strerror(errno));
permanently_set_uid(pw);
}
/* sandbox ourselves */
if (pledge("stdio", NULL) == -1)
fatal_f("pledge()");
}
static void
append_hostkey_type(struct sshbuf *b, const char *s)
{
int r;
if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
debug3_f("%s key not permitted by HostkeyAlgorithms", s);
return;
}
if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
fatal_fr(r, "sshbuf_putf");
}
static char *
list_hostkey_types(void)
{
struct sshbuf *b;
struct sshkey *key;
char *ret;
u_int i;
if ((b = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed");
for (i = 0; i < options.num_host_key_files; i++) {
key = host_pubkeys[i];
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA:
/* for RSA we also support SHA2 signatures */
append_hostkey_type(b, "rsa-sha2-512");
append_hostkey_type(b, "rsa-sha2-256");
/* FALLTHROUGH */
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
case KEY_ECDSA_SK:
case KEY_ED25519_SK:
case KEY_XMSS:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
/* If the private key has a cert peer, then list that too */
key = host_certificates[i];
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA_CERT:
/* for RSA we also support SHA2 signatures */
append_hostkey_type(b,
"rsa-sha2-512-cert-v01@openssh.com");
append_hostkey_type(b,
"rsa-sha2-256-cert-v01@openssh.com");
/* FALLTHROUGH */
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_ED25519_SK_CERT:
case KEY_XMSS_CERT:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
}
if ((ret = sshbuf_dup_string(b)) == NULL)
fatal_f("sshbuf_dup_string failed");
sshbuf_free(b);
debug_f("%s", ret);
return ret;
}
struct sshkey *
get_hostkey_public_by_type(int type, int nid, struct ssh *ssh)
{
u_int i;
struct sshkey *key;
for (i = 0; i < options.num_host_key_files; i++) {
switch (type) {
case KEY_RSA_CERT:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_ED25519_SK_CERT:
case KEY_XMSS_CERT:
key = host_certificates[i];
break;
default:
key = host_pubkeys[i];
break;
}
if (key == NULL || key->type != type)
continue;
switch (type) {
case KEY_ECDSA:
case KEY_ECDSA_SK:
case KEY_ECDSA_CERT:
case KEY_ECDSA_SK_CERT:
if (key->ecdsa_nid != nid)
continue;
/* FALLTHROUGH */
default:
return key;
}
}
return NULL;
}
/* XXX remove */
struct sshkey *
get_hostkey_private_by_type(int type, int nid, struct ssh *ssh)
{
return NULL;
}
/* XXX remove */
struct sshkey *
get_hostkey_by_index(int ind)
{
return NULL;
}
struct sshkey *
get_hostkey_public_by_index(int ind, struct ssh *ssh)
{
if (ind < 0 || (u_int)ind >= options.num_host_key_files)
return (NULL);
return host_pubkeys[ind];
}
int
get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh)
{
u_int i;
for (i = 0; i < options.num_host_key_files; i++) {
if (sshkey_is_cert(key)) {
if (key == host_certificates[i] ||
(compare && host_certificates[i] &&
sshkey_equal(key, host_certificates[i])))
return (i);
} else {
if (key == host_pubkeys[i] ||
(compare && host_pubkeys[i] &&
sshkey_equal(key, host_pubkeys[i])))
return (i);
}
}
return (-1);
}
static void
usage(void)
{
fprintf(stderr, "%s, %s\n", SSH_VERSION, SSH_OPENSSL_VERSION);
fprintf(stderr,
"usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n"
" [-E log_file] [-f config_file] [-g login_grace_time]\n"
" [-h host_key_file] [-o option] [-p port] [-u len]\n"
);
exit(1);
}
static void
parse_hostkeys(struct sshbuf *hostkeys)
{
int r;
u_int num_keys = 0;
struct sshkey *k;
const u_char *cp;
size_t len;
while (sshbuf_len(hostkeys) != 0) {
if (num_keys > 2048)
fatal_f("too many hostkeys");
host_pubkeys = xrecallocarray(host_pubkeys,
num_keys, num_keys + 1, sizeof(*host_pubkeys));
host_certificates = xrecallocarray(host_certificates,
num_keys, num_keys + 1, sizeof(*host_certificates));
/* public key */
k = NULL;
if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0)
fatal_fr(r, "extract pubkey");
if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0)
fatal_fr(r, "parse pubkey");
host_pubkeys[num_keys] = k;
if (k)
debug2_f("key %u: %s", num_keys, sshkey_ssh_name(k));
/* certificate */
k = NULL;
if ((r = sshbuf_get_string_direct(hostkeys, &cp, &len)) != 0)
fatal_fr(r, "extract pubkey");
if (len != 0 && (r = sshkey_from_blob(cp, len, &k)) != 0)
fatal_fr(r, "parse pubkey");
host_certificates[num_keys] = k;
if (k)
debug2_f("cert %u: %s", num_keys, sshkey_ssh_name(k));
num_keys++;
}
num_hostkeys = num_keys;
}
static void
recv_privsep_state(struct ssh *ssh, struct sshbuf *conf,
uint64_t *timing_secretp)
{
struct sshbuf *hostkeys;
debug3_f("begin");
mm_get_state(ssh, &includes, conf, NULL, timing_secretp,
&hostkeys, NULL, NULL, NULL, NULL);
parse_hostkeys(hostkeys);
sshbuf_free(hostkeys);
debug3_f("done");
}
/*
* Main program for the daemon.
*/
int
main(int ac, char **av)
{
struct ssh *ssh = NULL;
extern char *optarg;
extern int optind;
int r, opt, have_key = 0;
int sock_in = -1, sock_out = -1, rexeced_flag = 0;
char *line, *logfile = NULL;
u_int i;
mode_t new_umask;
Authctxt *authctxt;
struct connection_info *connection_info = NULL;
sigset_t sigmask;
uint64_t timing_secret = 0;
closefrom(PRIVSEP_MIN_FREE_FD);
sigemptyset(&sigmask);
sigprocmask(SIG_SETMASK, &sigmask, NULL);
/* Save argv. */
saved_argv = av;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
/* Initialize configuration options to their default values. */
initialize_server_options(&options);
/* Parse command-line arguments. */
while ((opt = getopt(ac, av,
"C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) {
switch (opt) {
case '4':
options.address_family = AF_INET;
break;
case '6':
options.address_family = AF_INET6;
break;
case 'f':
config_file_name = optarg;
break;
case 'c':
servconf_add_hostcert("[command-line]", 0,
&options, optarg);
break;
case 'd':
if (debug_flag == 0) {
debug_flag = 1;
options.log_level = SYSLOG_LEVEL_DEBUG1;
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
options.log_level++;
break;
case 'D':
/* ignore */
break;
case 'E':
logfile = optarg;
/* FALLTHROUGH */
case 'e':
/* ignore */
break;
case 'i':
inetd_flag = 1;
break;
case 'r':
/* ignore */
break;
case 'R':
rexeced_flag = 1;
break;
case 'Q':
/* ignored */
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
break;
case 'b':
/* protocol 1, ignored */
break;
case 'p':
options.ports_from_cmdline = 1;
if (options.num_ports >= MAX_PORTS) {
fprintf(stderr, "too many ports.\n");
exit(1);
}
options.ports[options.num_ports++] = a2port(optarg);
if (options.ports[options.num_ports-1] <= 0) {
fprintf(stderr, "Bad port number.\n");
exit(1);
}
break;
case 'g':
if ((options.login_grace_time = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid login grace time.\n");
exit(1);
}
break;
case 'k':
/* protocol 1, ignored */
break;
case 'h':
servconf_add_hostkey("[command-line]", 0,
&options, optarg, 1);
break;
case 't':
case 'T':
case 'G':
fatal("test/dump modes not supported");
break;
case 'C':
connection_info = server_get_connection_info(ssh, 0, 0);
if (parse_server_match_testspec(connection_info,
optarg) == -1)
exit(1);
break;
case 'u':
utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL);
if (utmp_len > HOST_NAME_MAX+1) {
fprintf(stderr, "Invalid utmp length.\n");
exit(1);
}
break;
case 'o':
line = xstrdup(optarg);
if (process_server_config_line(&options, line,
"command-line", 0, NULL, NULL, &includes) != 0)
exit(1);
free(line);
break;
case 'V':
fprintf(stderr, "%s, %s\n",
SSH_VERSION, SSH_OPENSSL_VERSION);
exit(0);
default:
usage();
break;
}
}
if (!rexeced_flag)
fatal("sshd-auth should not be executed directly");
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
#endif
/* If requested, redirect the logs to the specified logfile. */
if (logfile != NULL) {
char *cp, pid_s[32];
snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid());
cp = percent_expand(logfile,
"p", pid_s,
"P", "sshd-auth",
(char *)NULL);
log_redirect_stderr_to(cp);
free(cp);
}
log_init(__progname,
options.log_level == SYSLOG_LEVEL_NOT_SET ?
SYSLOG_LEVEL_INFO : options.log_level,
options.log_facility == SYSLOG_FACILITY_NOT_SET ?
SYSLOG_FACILITY_AUTH : options.log_facility, 1);
/* XXX can't use monitor_init(); it makes fds */
pmonitor = xcalloc(1, sizeof(*pmonitor));
pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
pmonitor->m_log_sendfd = PRIVSEP_LOG_FD;
set_log_handler(mm_log_handler, pmonitor);
/* Check that there are no remaining arguments. */
if (optind < ac) {
fprintf(stderr, "Extra argument %s.\n", av[optind]);
exit(1);
}
debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION);
/* Connection passed by stdin/out */
if (inetd_flag) {
/*
* NB. must be different fd numbers for the !socket case,
* as packet_connection_is_on_socket() depends on this.
*/
sock_in = dup(STDIN_FILENO);
sock_out = dup(STDOUT_FILENO);
} else {
/* rexec case; accept()ed socket in ancestor listener */
sock_in = sock_out = dup(STDIN_FILENO);
}
if (stdfd_devnull(1, 1, 0) == -1)
error("stdfd_devnull failed");
debug("network sockets: %d, %d", sock_in, sock_out);
/*
* Register our connection. This turns encryption off because we do
* not have a key.
*/
if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL)
fatal("Unable to create connection");
the_active_state = ssh;
ssh_packet_set_server(ssh);
pmonitor->m_pkex = &ssh->kex;
/* Fetch our configuration */
if ((cfg = sshbuf_new()) == NULL)
fatal("sshbuf_new config buf failed");
setproctitle("%s", "[session-auth early]");
recv_privsep_state(ssh, cfg, &timing_secret);
parse_server_config(&options, "rexec", cfg, &includes, NULL, 1);
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
options.timing_secret = timing_secret; /* XXX eliminate from unpriv */
#ifdef WITH_OPENSSL
if (options.moduli_file != NULL)
dh_set_moduli_file(options.moduli_file);
#endif
if (options.host_key_agent) {
if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
setenv(SSH_AUTHSOCKET_ENV_NAME,
options.host_key_agent, 1);
if ((r = ssh_get_authentication_socket(NULL)) == 0)
have_agent = 1;
else
error_r(r, "Could not connect to agent \"%s\"",
options.host_key_agent);
}
if (options.num_host_key_files != num_hostkeys) {
fatal("internal error: hostkeys confused (config %u recvd %u)",
options.num_host_key_files, num_hostkeys);
}
for (i = 0; i < options.num_host_key_files; i++) {
if (host_pubkeys[i] != NULL) {
have_key = 1;
break;
}
}
if (!have_key)
fatal("internal error: recieved no hostkeys");
/* Ensure that umask disallows at least group and world write */
new_umask = umask(0077) | 0022;
(void) umask(new_umask);
/* Initialize the log (it is reinitialized below in case we forked). */
log_init(__progname, options.log_level, options.log_facility, 1);
set_log_handler(mm_log_handler, pmonitor);
for (i = 0; i < options.num_log_verbose; i++)
log_verbose_add(options.log_verbose[i]);
/*
* Chdir to the root directory so that the current disk can be
* unmounted if desired.
*/
if (chdir("/") == -1)
error("chdir(\"/\"): %s", strerror(errno));
/* This is the child authenticating a new connection. */
setproctitle("%s", "[session-auth]");
/* Executed child processes don't need these. */
fcntl(sock_out, F_SETFD, FD_CLOEXEC);
fcntl(sock_in, F_SETFD, FD_CLOEXEC);
ssh_signal(SIGPIPE, SIG_IGN);
ssh_signal(SIGALRM, SIG_DFL);
ssh_signal(SIGHUP, SIG_DFL);
ssh_signal(SIGTERM, SIG_DFL);
ssh_signal(SIGQUIT, SIG_DFL);
ssh_signal(SIGCHLD, SIG_DFL);
/* Prepare the channels layer */
channel_init_channels(ssh);
channel_set_af(ssh, options.address_family);
server_process_channel_timeouts(ssh);
server_process_permitopen(ssh);
ssh_packet_set_nonblocking(ssh);
/* allocate authentication context */
authctxt = xcalloc(1, sizeof(*authctxt));
ssh->authctxt = authctxt;
/* XXX global for cleanup, access from other modules */
the_authctxt = authctxt;
/* Set default key authentication options */
if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL)
fatal("allocation failed");
/* prepare buffer to collect messages to display to user after login */
if ((loginmsg = sshbuf_new()) == NULL)
fatal("sshbuf_new loginmsg failed");
auth_debug_reset();
/* Enable challenge-response authentication for privilege separation */
privsep_challenge_enable();
#ifdef GSSAPI
/* Cache supported mechanism OIDs for later use */
ssh_gssapi_prepare_supported_oids();
#endif
privsep_child_demote();
/* perform the key exchange */
/* authenticate user and start session */
do_ssh2_kex(ssh);
do_authentication2(ssh);
/*
* The unprivileged child now transfers the current keystate and exits.
*/
mm_send_keystate(ssh, pmonitor);
ssh_packet_clear_keys(ssh);
exit(0);
}
int
sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
struct sshkey *pubkey, u_char **signature, size_t *slenp,
const u_char *data, size_t dlen, const char *alg)
{
if (privkey) {
if (mm_sshkey_sign(ssh, privkey, signature, slenp,
data, dlen, alg, options.sk_provider, NULL,
ssh->compat) < 0)
fatal_f("privkey sign failed");
} else {
if (mm_sshkey_sign(ssh, pubkey, signature, slenp,
data, dlen, alg, options.sk_provider, NULL,
ssh->compat) < 0)
fatal_f("pubkey sign failed");
}
return 0;
}
/* SSH2 key exchange */
static void
do_ssh2_kex(struct ssh *ssh)
{
char *hkalgs = NULL, *myproposal[PROPOSAL_MAX];
const char *compression = NULL;
struct kex *kex;
int r;
if (options.rekey_limit || options.rekey_interval)
ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
options.rekey_interval);
if (options.compression == COMP_NONE)
compression = "none";
hkalgs = list_hostkey_types();
kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms,
options.ciphers, options.macs, compression, hkalgs);
free(hkalgs);
/* start key exchange */
if ((r = kex_setup(ssh, myproposal)) != 0)
fatal_r(r, "kex_setup");
kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
kex = ssh->kex;
#ifdef WITH_OPENSSL
kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
#endif
kex->kex[KEX_C25519_SHA256] = kex_gen_server;
kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
kex->sign = sshd_hostkey_sign;
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done);
kex_proposal_free_entries(myproposal);
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_cstring(ssh, "markus")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal_fr(r, "send test");
#endif
debug("KEX done");
}
/* server specific fatal cleanup */
void
cleanup_exit(int i)
{
_exit(i);
}

View file

@ -0,0 +1,71 @@
# $OpenBSD: Makefile,v 1.1 2024/10/14 01:57:50 djm Exp $
.PATH: ${.CURDIR}/..
SRCS= sshd-auth.c auth2-methods.c \
auth-rhosts.c auth-passwd.c sshpty.c sshlogin.c servconf.c \
serverloop.c auth.c auth2.c auth-options.c session.c auth2-chall.c \
groupaccess.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c \
auth2-none.c auth2-passwd.c auth2-pubkey.c auth2-pubkeyfile.c \
monitor_wrap.c \
sftp-server.c sftp-common.c sftp-realpath.c
SRCS+= authfd.c compat.c dns.c fatal.c hostfile.c readpass.c utf8.c uidswap.c
SRCS+= ${SRCS_BASE} ${SRCS_KEX} ${SRCS_KEXS} ${SRCS_KEY} ${SRCS_KEYP} \
${SRCS_KRL} ${SRCS_PROT} ${SRCS_PKT} ${SRCS_UTL} ${SRCS_PKCS11} \
${SRCS_SK_CLIENT}
PROG= sshd-auth
BINDIR= /usr/libexec
BINMODE=511
NOMAN= 1
.include <bsd.own.mk> # for KERBEROS and AFS
KERBEROS5=no
.if (${KERBEROS5:L} == "yes")
CFLAGS+=-DKRB5 -I${DESTDIR}/usr/include/kerberosV -DGSSAPI
SRCS+= auth-krb5.c auth2-gss.c gss-serv.c gss-serv-krb5.c
.endif
.include <bsd.prog.mk>
.if (${KERBEROS5:L} == "yes")
LDADD+= -lgssapi -lkrb5 -lasn1
LDADD+= -lwind -lroken -lcom_err -lpthread -lheimbase -lkafs
DPADD+= ${LIBGSSAPI} ${LIBKRB5}
.endif
.if (${OPENSSL:L} == "yes")
LDADD+= -lcrypto
DPADD+= ${LIBCRYPTO}
.endif
LDADD+= -lutil
DPADD+= ${LIBUTIL}
.if (${ZLIB:L} == "yes")
LDADD+= -lz
DPADD+= ${LIBZ}
.endif
# The random relink kit, used on OpenBSD by /etc/rc
CLEANFILES+= ${PROG}.tar install.sh
install.sh: Makefile
echo "set -o errexit" > $@
echo "${CC} ${LDFLAGS} ${LDSTATIC} -o ${PROG}" \
"\`echo " ${OBJS} "| tr ' ' '\\\n' | sort -R\`" ${LDADD} >> $@
echo "./${PROG} -V # test it works" >> $@
echo "install -c -s -o root -g bin -m ${BINMODE} ${PROG} " \
"${BINDIR}/${PROG}" >> $@
${PROG}.tar: ${OBJS} install.sh
tar cf $@ ${OBJS} install.sh
afterinstall: ${PROG}.tar
install -d -o root -g wheel -m 755 \
${DESTDIR}/usr/share/relink/${BINDIR}/${PROG}
install -o ${BINOWN} -g ${BINGRP} -m 640 \
${PROG}.tar ${DESTDIR}/usr/share/relink/${BINDIR}/${PROG}/${PROG}.tar

View file

@ -1,4 +1,4 @@
/* $OpenBSD: sshd-session.c,v 1.9 2024/09/09 02:39:57 djm Exp $ */ /* $OpenBSD: sshd-session.c,v 1.10 2024/10/14 01:57:50 djm Exp $ */
/* /*
* SSH2 implementation: * SSH2 implementation:
* Privilege Separation: * Privilege Separation:
@ -86,7 +86,6 @@
#include "ssh-gss.h" #include "ssh-gss.h"
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "ssh-sandbox.h"
#include "auth-options.h" #include "auth-options.h"
#include "version.h" #include "version.h"
#include "ssherr.h" #include "ssherr.h"
@ -100,6 +99,11 @@
#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3)
#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4)
/* Privsep fds */
#define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1)
#define PRIVSEP_LOG_FD (STDERR_FILENO + 2)
#define PRIVSEP_MIN_FREE_FD (STDERR_FILENO + 3)
extern char *__progname; extern char *__progname;
/* Server configuration options. */ /* Server configuration options. */
@ -172,7 +176,17 @@ struct sshbuf *loginmsg;
/* Prototypes for various functions defined later in this file. */ /* Prototypes for various functions defined later in this file. */
void destroy_sensitive_data(void); void destroy_sensitive_data(void);
void demote_sensitive_data(void); void demote_sensitive_data(void);
static void do_ssh2_kex(struct ssh *);
/* XXX reduce to stub once postauth split */
int
mm_is_monitor(void)
{
/*
* m_pid is only set in the privileged part, and
* points to the unprivileged child.
*/
return (pmonitor && pmonitor->m_pid > 0);
}
/* /*
* Signal handler for the alarm after the login grace period has expired. * Signal handler for the alarm after the login grace period has expired.
@ -239,50 +253,41 @@ demote_sensitive_data(void)
} }
} }
static void struct sshbuf *
privsep_preauth_child(void) pack_hostkeys(void)
{ {
gid_t gidset[1]; struct sshbuf *keybuf = NULL, *hostkeys = NULL;
struct passwd *pw; int r;
u_int i;
/* Enable challenge-response authentication for privilege separation */ if ((hostkeys = sshbuf_new()) == NULL)
privsep_challenge_enable(); fatal_f("sshbuf_new failed");
#ifdef GSSAPI /* pack hostkeys into a string. Empty key slots get empty strings */
/* Cache supported mechanism OIDs for later use */ for (i = 0; i < options.num_host_key_files; i++) {
ssh_gssapi_prepare_supported_oids(); /* public key */
#endif if (sensitive_data.host_pubkeys[i] != NULL) {
if ((r = sshkey_puts(sensitive_data.host_pubkeys[i],
/* Demote the private keys to public keys. */ hostkeys)) != 0)
demote_sensitive_data(); fatal_fr(r, "compose hostkey public");
} else {
/* Demote the child */ if ((r = sshbuf_put_string(hostkeys, NULL, 0)) != 0)
if (getuid() == 0 || geteuid() == 0) { fatal_fr(r, "compose hostkey empty public");
if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) }
fatal("Privilege separation user %s does not exist", /* cert */
SSH_PRIVSEP_USER); if (sensitive_data.host_certificates[i] != NULL) {
pw = pwcopy(pw); /* Ensure mutable */ if ((r = sshkey_puts(
endpwent(); sensitive_data.host_certificates[i],
freezero(pw->pw_passwd, strlen(pw->pw_passwd)); hostkeys)) != 0)
fatal_fr(r, "compose host cert");
/* Change our root directory */ } else {
if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) if ((r = sshbuf_put_string(hostkeys, NULL, 0)) != 0)
fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, fatal_fr(r, "compose host cert empty");
strerror(errno)); }
if (chdir("/") == -1)
fatal("chdir(\"/\"): %s", strerror(errno));
/*
* Drop our privileges
* NB. Can't use setusercontext() after chroot.
*/
debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,
(u_int)pw->pw_gid);
gidset[0] = pw->pw_gid;
if (setgroups(1, gidset) == -1)
fatal("setgroups: %.100s", strerror(errno));
permanently_set_uid(pw);
} }
sshbuf_free(keybuf);
return hostkeys;
} }
static int static int
@ -290,20 +295,16 @@ privsep_preauth(struct ssh *ssh)
{ {
int status, r; int status, r;
pid_t pid; pid_t pid;
struct ssh_sandbox *box = NULL;
/* Set up unprivileged child process to deal with network data */ /* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init(); pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */ /* Store a pointer to the kex for later rekeying */
pmonitor->m_pkex = &ssh->kex; pmonitor->m_pkex = &ssh->kex;
box = ssh_sandbox_init(); if ((pid = fork()) == -1)
pid = fork();
if (pid == -1) {
fatal("fork of unprivileged child failed"); fatal("fork of unprivileged child failed");
} else if (pid != 0) { else if (pid != 0) {
debug2("Network child is on pid %ld", (long)pid); debug2("Network child is on pid %ld", (long)pid);
pmonitor->m_pid = pid; pmonitor->m_pid = pid;
if (have_agent) { if (have_agent) {
r = ssh_get_authentication_socket(&auth_sock); r = ssh_get_authentication_socket(&auth_sock);
@ -312,8 +313,6 @@ privsep_preauth(struct ssh *ssh)
have_agent = 0; have_agent = 0;
} }
} }
if (box != NULL)
ssh_sandbox_parent_preauth(box, pid);
monitor_child_preauth(ssh, pmonitor); monitor_child_preauth(ssh, pmonitor);
/* Wait for the child's exit status */ /* Wait for the child's exit status */
@ -332,23 +331,46 @@ privsep_preauth(struct ssh *ssh)
} else if (WIFSIGNALED(status)) } else if (WIFSIGNALED(status))
fatal_f("preauth child terminated by signal %d", fatal_f("preauth child terminated by signal %d",
WTERMSIG(status)); WTERMSIG(status));
if (box != NULL)
ssh_sandbox_parent_finish(box);
return 1; return 1;
} else { } else {
/* child */ /* child */
close(pmonitor->m_sendfd); close(pmonitor->m_sendfd);
close(pmonitor->m_log_recvfd); close(pmonitor->m_log_recvfd);
/* Arrange for logging to be sent to the monitor */ /*
set_log_handler(mm_log_handler, pmonitor); * Arrange unpriv-preauth child process fds:
* 0, 1 network socket
* 2 optional stderr
* 3 reserved
* 4 monitor message socket
* 5 monitor logging socket
*
* We know that the monitor sockets will have fds > 4 because
* of the reserved fds in main()
*/
privsep_preauth_child(); if (ssh_packet_get_connection_in(ssh) != STDIN_FILENO &&
setproctitle("%s", "[net]"); dup2(ssh_packet_get_connection_in(ssh), STDIN_FILENO) == -1)
if (box != NULL) fatal("dup2 stdin failed: %s", strerror(errno));
ssh_sandbox_child(box); if (ssh_packet_get_connection_out(ssh) != STDOUT_FILENO &&
dup2(ssh_packet_get_connection_out(ssh),
STDOUT_FILENO) == -1)
fatal("dup2 stdout failed: %s", strerror(errno));
/* leave stderr as-is */
log_redirect_stderr_to(NULL); /* dup can clobber log fd */
if (pmonitor->m_recvfd != PRIVSEP_MONITOR_FD &&
dup2(pmonitor->m_recvfd, PRIVSEP_MONITOR_FD) == -1)
fatal("dup2 monitor fd: %s", strerror(errno));
if (pmonitor->m_log_sendfd != PRIVSEP_LOG_FD &&
dup2(pmonitor->m_log_sendfd, PRIVSEP_LOG_FD) == -1)
fatal("dup2 log fd: %s", strerror(errno));
closefrom(PRIVSEP_MIN_FREE_FD);
return 0; saved_argv[0] = options.sshd_auth_path;
execv(options.sshd_auth_path, saved_argv);
fatal_f("exec of %s failed: %s",
options.sshd_auth_path, strerror(errno));
} }
} }
@ -392,79 +414,6 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
ssh_packet_set_authenticated(ssh); ssh_packet_set_authenticated(ssh);
} }
static void
append_hostkey_type(struct sshbuf *b, const char *s)
{
int r;
if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
debug3_f("%s key not permitted by HostkeyAlgorithms", s);
return;
}
if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
fatal_fr(r, "sshbuf_putf");
}
static char *
list_hostkey_types(void)
{
struct sshbuf *b;
struct sshkey *key;
char *ret;
u_int i;
if ((b = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed");
for (i = 0; i < options.num_host_key_files; i++) {
key = sensitive_data.host_keys[i];
if (key == NULL)
key = sensitive_data.host_pubkeys[i];
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA:
/* for RSA we also support SHA2 signatures */
append_hostkey_type(b, "rsa-sha2-512");
append_hostkey_type(b, "rsa-sha2-256");
/* FALLTHROUGH */
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
case KEY_ECDSA_SK:
case KEY_ED25519_SK:
case KEY_XMSS:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
/* If the private key has a cert peer, then list that too */
key = sensitive_data.host_certificates[i];
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA_CERT:
/* for RSA we also support SHA2 signatures */
append_hostkey_type(b,
"rsa-sha2-512-cert-v01@openssh.com");
append_hostkey_type(b,
"rsa-sha2-256-cert-v01@openssh.com");
/* FALLTHROUGH */
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_ED25519_SK_CERT:
case KEY_XMSS_CERT:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
}
if ((ret = sshbuf_dup_string(b)) == NULL)
fatal_f("sshbuf_dup_string failed");
sshbuf_free(b);
debug_f("%s", ret);
return ret;
}
static struct sshkey * static struct sshkey *
get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
{ {
@ -801,7 +750,7 @@ main(int ac, char **av)
struct ssh *ssh = NULL; struct ssh *ssh = NULL;
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
int r, opt, on = 1, remote_port; int devnull, r, opt, on = 1, remote_port;
int sock_in = -1, sock_out = -1, rexeced_flag = 0, have_key = 0; int sock_in = -1, sock_out = -1, rexeced_flag = 0, have_key = 0;
const char *remote_ip, *rdomain; const char *remote_ip, *rdomain;
char *line, *laddr, *logfile = NULL; char *line, *laddr, *logfile = NULL;
@ -950,6 +899,14 @@ main(int ac, char **av)
closefrom(REEXEC_MIN_FREE_FD); closefrom(REEXEC_MIN_FREE_FD);
/* Reserve fds we'll need later for reexec things */
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
fatal("open %s: %s", _PATH_DEVNULL, strerror(errno));
while (devnull < PRIVSEP_MIN_FREE_FD) {
if ((devnull = dup(devnull)) == -1)
fatal("dup %s: %s", _PATH_DEVNULL, strerror(errno));
}
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
#endif #endif
@ -985,15 +942,21 @@ main(int ac, char **av)
fatal("sshbuf_new config buf failed"); fatal("sshbuf_new config buf failed");
setproctitle("%s", "[rexeced]"); setproctitle("%s", "[rexeced]");
recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg, &timing_secret); recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg, &timing_secret);
close(REEXEC_CONFIG_PASS_FD); /* close the fd, but keep the slot reserved */
if (dup2(devnull, REEXEC_CONFIG_PASS_FD) == -1)
fatal("dup2 devnull->config fd: %s", strerror(errno));
parse_server_config(&options, "rexec", cfg, &includes, NULL, 1); parse_server_config(&options, "rexec", cfg, &includes, NULL, 1);
/* Fill in default values for those options not explicitly set. */ /* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options); fill_default_server_options(&options);
options.timing_secret = timing_secret; options.timing_secret = timing_secret;
if (!debug_flag) { if (!debug_flag && !inetd_flag) {
startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); if ((startup_pipe = dup(REEXEC_STARTUP_PIPE_FD)) == -1)
close(REEXEC_STARTUP_PIPE_FD); fatal("internal error: no startup pipe");
/* close the fd, but keep the slot reserved */
if (dup2(devnull, REEXEC_STARTUP_PIPE_FD) == -1)
fatal("dup2 devnull->startup fd: %s", strerror(errno));
/* /*
* Signal parent that this child is at a point where * Signal parent that this child is at a point where
* they can go away if they have a SIGHUP pending. * they can go away if they have a SIGHUP pending.
@ -1210,22 +1173,11 @@ main(int ac, char **av)
fatal("sshbuf_new loginmsg failed"); fatal("sshbuf_new loginmsg failed");
auth_debug_reset(); auth_debug_reset();
if (privsep_preauth(ssh) == 1) if (privsep_preauth(ssh) != 1)
goto authenticated; fatal("privsep_preauth failed");
/* perform the key exchange */ /* Now user is authenticated */
/* authenticate user and start session */
do_ssh2_kex(ssh);
do_authentication2(ssh);
/*
* The unprivileged child now transfers the current keystate and exits.
*/
mm_send_keystate(ssh, pmonitor);
ssh_packet_clear_keys(ssh);
exit(0);
authenticated:
/* /*
* Cancel the alarm we set to limit the time taken for * Cancel the alarm we set to limit the time taken for
* authentication. * authentication.
@ -1294,66 +1246,6 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
return 0; return 0;
} }
/* SSH2 key exchange */
static void
do_ssh2_kex(struct ssh *ssh)
{
char *hkalgs = NULL, *myproposal[PROPOSAL_MAX];
const char *compression = NULL;
struct kex *kex;
int r;
if (options.rekey_limit || options.rekey_interval)
ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
options.rekey_interval);
if (options.compression == COMP_NONE)
compression = "none";
hkalgs = list_hostkey_types();
kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms,
options.ciphers, options.macs, compression, hkalgs);
free(hkalgs);
/* start key exchange */
if ((r = kex_setup(ssh, myproposal)) != 0)
fatal_r(r, "kex_setup");
kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
kex = ssh->kex;
#ifdef WITH_OPENSSL
kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
#endif
kex->kex[KEX_C25519_SHA256] = kex_gen_server;
kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
kex->sign = sshd_hostkey_sign;
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done);
kex_proposal_free_entries(myproposal);
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_cstring(ssh, "markus")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal_fr(r, "send test");
#endif
debug("KEX done");
}
/* server specific fatal cleanup */ /* server specific fatal cleanup */
void void
cleanup_exit(int i) cleanup_exit(int i)

View file

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.3 2024/05/17 14:42:00 naddy Exp $ # $OpenBSD: Makefile,v 1.4 2024/10/14 01:57:50 djm Exp $
.PATH: ${.CURDIR}/.. .PATH: ${.CURDIR}/..
@ -8,7 +8,7 @@ SRCS= sshd-session.c auth2-methods.c \
groupaccess.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c \ groupaccess.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c \
auth2-none.c auth2-passwd.c auth2-pubkey.c auth2-pubkeyfile.c \ auth2-none.c auth2-passwd.c auth2-pubkey.c auth2-pubkeyfile.c \
monitor.c monitor_wrap.c \ monitor.c monitor_wrap.c \
sftp-server.c sftp-common.c sftp-realpath.c sandbox-pledge.c srclimit.c sftp-server.c sftp-common.c sftp-realpath.c srclimit.c
SRCS+= authfd.c compat.c dns.c fatal.c hostfile.c readpass.c utf8.c uidswap.c SRCS+= authfd.c compat.c dns.c fatal.c hostfile.c readpass.c utf8.c uidswap.c
SRCS+= ${SRCS_BASE} ${SRCS_KEX} ${SRCS_KEXS} ${SRCS_KEY} ${SRCS_KEYP} \ SRCS+= ${SRCS_BASE} ${SRCS_KEX} ${SRCS_KEXS} ${SRCS_KEY} ${SRCS_KEYP} \
${SRCS_KRL} ${SRCS_PROT} ${SRCS_PKT} ${SRCS_UTL} ${SRCS_PKCS11} \ ${SRCS_KRL} ${SRCS_PROT} ${SRCS_PKT} ${SRCS_UTL} ${SRCS_PKCS11} \

View file

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.612 2024/09/15 01:11:26 djm Exp $ */ /* $OpenBSD: sshd.c,v 1.613 2024/10/14 01:57:50 djm Exp $ */
/* /*
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved.
@ -1573,6 +1573,13 @@ main(int ac, char **av)
fatal("%s does not exist or is not executable", rexec_argv[0]); fatal("%s does not exist or is not executable", rexec_argv[0]);
debug3("using %s for re-exec", rexec_argv[0]); debug3("using %s for re-exec", rexec_argv[0]);
/* Ensure that the privsep binary exists now too. */
if (stat(options.sshd_auth_path, &sb) != 0 ||
!(sb.st_mode & (S_IXOTH|S_IXUSR))) {
fatal("%s does not exist or is not executable",
options.sshd_auth_path);
}
listener_proctitle = prepare_proctitle(ac, av); listener_proctitle = prepare_proctitle(ac, av);
/* Ensure that umask disallows at least group and world write */ /* Ensure that umask disallows at least group and world write */