diff --git a/changelog/security/2024-01-05-openssh-update.md b/changelog/security/2024-01-05-openssh-update.md new file mode 100644 index 00000000000..698e8417c1e --- /dev/null +++ b/changelog/security/2024-01-05-openssh-update.md @@ -0,0 +1 @@ +- openssh ([CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795)) diff --git a/changelog/updates/2024-01-05-openssh-update.md b/changelog/updates/2024-01-05-openssh-update.md new file mode 100644 index 00000000000..206787df87b --- /dev/null +++ b/changelog/updates/2024-01-05-openssh-update.md @@ -0,0 +1 @@ +- openssh ([9.6p1](https://www.openssh.com/releasenotes.html#9.6p1)) diff --git a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/Manifest b/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/Manifest index 40dccfe452a..bbc5cf33ad5 100644 --- a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/Manifest +++ b/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/Manifest @@ -1,2 +1,2 @@ -DIST openssh-9.5p1.tar.gz 1843001 BLAKE2B 55dbb0a2792b0046c943a19ca0966660e6e378e77856e94823a1bbbafaa0da94357403765c4c028aebf6543049a0f9bbe0019629be3f92cdadfac1be56def796 SHA512 e183fdf7477fd986215b889eea4a945d71385e35305746ccb164e757ecc28166f429c70890a237d8ef4cdcae5132935ba2ecb3b2a658eb73a6afcf6f42277b9c -DIST openssh-9.5p1.tar.gz.asc 833 BLAKE2B abec3d14d9a880008db202be00ed446ccc0a98ce77c16a9e6d6492feac07c8f3284f9cd24f6ee1d904a55f9f23d5cce8a716916975c179a38ef6bde1d36e0acf SHA512 2b6de653420ba02eb99c7e6fba09af3bacfe9c701f3dfc3c94f41a3539c0414954fc5c64cce63c488c5ccd5d4ddb42d3f2184ff7f323342c885c47bf7d426ca1 +DIST openssh-9.6p1.tar.gz 1857862 BLAKE2B dd7f6747fe89f7b386be4faaf7fc43398a9bf439e45608ae61c2126cf8743c64ef7b5af45c75e9007b0bda525f8809261ca0f2fc47ce60177ba769a5324719dd SHA512 0ebf81e39914c3a90d7777a001ec7376a94b37e6024baf3e972c58f0982b7ddef942315f5e01d56c00ff95603b4a20ee561ab918ecc55511df007ac138160509 +DIST openssh-9.6p1.tar.gz.asc 833 BLAKE2B 9363d02f85457aa90069020827306a2f49d8406e32f5ee1d231844648dd2ffa02fa9b7325b8677a11e46a0ba0d9ffc86d9c989435d691a02f5354a956c49f9f9 SHA512 aec5a5bd6ce480a8e5b5879dc55f8186aec90fe61f085aa92ad7d07f324574aa781be09c83b7443a32848d091fd44fb12c1842d49cee77afc351e550ffcc096d diff --git a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/files/openssh-9.3_p1-GSSAPI-dns.patch b/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/files/openssh-9.3_p1-GSSAPI-dns.patch deleted file mode 100644 index cbc0ec2d9c2..00000000000 --- a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/files/openssh-9.3_p1-GSSAPI-dns.patch +++ /dev/null @@ -1,345 +0,0 @@ ---- a/auth.c -+++ b/auth.c -@@ -637,118 +637,6 @@ - return (&fake); - } - --/* -- * Returns the remote DNS hostname as a string. The returned string must not -- * be freed. NB. this will usually trigger a DNS query the first time it is -- * called. -- * This function does additional checks on the hostname to mitigate some -- * attacks on based on conflation of hostnames and IP addresses. -- */ -- --static char * --remote_hostname(struct ssh *ssh) --{ -- struct sockaddr_storage from; -- socklen_t fromlen; -- struct addrinfo hints, *ai, *aitop; -- char name[NI_MAXHOST], ntop2[NI_MAXHOST]; -- const char *ntop = ssh_remote_ipaddr(ssh); -- -- /* Get IP address of client. */ -- fromlen = sizeof(from); -- memset(&from, 0, sizeof(from)); -- if (getpeername(ssh_packet_get_connection_in(ssh), -- (struct sockaddr *)&from, &fromlen) == -1) { -- debug("getpeername failed: %.100s", strerror(errno)); -- return xstrdup(ntop); -- } -- -- ipv64_normalise_mapped(&from, &fromlen); -- if (from.ss_family == AF_INET6) -- fromlen = sizeof(struct sockaddr_in6); -- -- debug3("Trying to reverse map address %.100s.", ntop); -- /* Map the IP address to a host name. */ -- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), -- NULL, 0, NI_NAMEREQD) != 0) { -- /* Host name not found. Use ip address. */ -- return xstrdup(ntop); -- } -- -- /* -- * if reverse lookup result looks like a numeric hostname, -- * someone is trying to trick us by PTR record like following: -- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 -- */ -- memset(&hints, 0, sizeof(hints)); -- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ -- hints.ai_flags = AI_NUMERICHOST; -- if (getaddrinfo(name, NULL, &hints, &ai) == 0) { -- logit("Nasty PTR record \"%s\" is set up for %s, ignoring", -- name, ntop); -- freeaddrinfo(ai); -- return xstrdup(ntop); -- } -- -- /* Names are stored in lowercase. */ -- lowercase(name); -- -- /* -- * Map it back to an IP address and check that the given -- * address actually is an address of this host. This is -- * necessary because anyone with access to a name server can -- * define arbitrary names for an IP address. Mapping from -- * name to IP address can be trusted better (but can still be -- * fooled if the intruder has access to the name server of -- * the domain). -- */ -- memset(&hints, 0, sizeof(hints)); -- hints.ai_family = from.ss_family; -- hints.ai_socktype = SOCK_STREAM; -- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { -- logit("reverse mapping checking getaddrinfo for %.700s " -- "[%s] failed.", name, ntop); -- return xstrdup(ntop); -- } -- /* Look for the address from the list of addresses. */ -- for (ai = aitop; ai; ai = ai->ai_next) { -- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, -- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && -- (strcmp(ntop, ntop2) == 0)) -- break; -- } -- freeaddrinfo(aitop); -- /* If we reached the end of the list, the address was not there. */ -- if (ai == NULL) { -- /* Address not found for the host name. */ -- logit("Address %.100s maps to %.600s, but this does not " -- "map back to the address.", ntop, name); -- return xstrdup(ntop); -- } -- return xstrdup(name); --} -- --/* -- * Return the canonical name of the host in the other side of the current -- * connection. The host name is cached, so it is efficient to call this -- * several times. -- */ -- --const char * --auth_get_canonical_hostname(struct ssh *ssh, int use_dns) --{ -- static char *dnsname; -- -- if (!use_dns) -- return ssh_remote_ipaddr(ssh); -- else if (dnsname != NULL) -- return dnsname; -- else { -- dnsname = remote_hostname(ssh); -- return dnsname; -- } --} -- - /* These functions link key/cert options to the auth framework */ - - /* Log sshauthopt options locally and (optionally) for remote transmission */ ---- a/canohost.c -+++ b/canohost.c -@@ -205,3 +205,117 @@ - { - return get_sock_port(sock, 1); - } -+ -+/* -+ * Returns the remote DNS hostname as a string. The returned string must not -+ * be freed. NB. this will usually trigger a DNS query the first time it is -+ * called. -+ * This function does additional checks on the hostname to mitigate some -+ * attacks on legacy rhosts-style authentication. -+ * XXX is RhostsRSAAuthentication vulnerable to these? -+ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) -+ */ -+ -+static char * -+remote_hostname(struct ssh *ssh) -+{ -+ struct sockaddr_storage from; -+ socklen_t fromlen; -+ struct addrinfo hints, *ai, *aitop; -+ char name[NI_MAXHOST], ntop2[NI_MAXHOST]; -+ const char *ntop = ssh_remote_ipaddr(ssh); -+ -+ /* Get IP address of client. */ -+ fromlen = sizeof(from); -+ memset(&from, 0, sizeof(from)); -+ if (getpeername(ssh_packet_get_connection_in(ssh), -+ (struct sockaddr *)&from, &fromlen) == -1) { -+ debug("getpeername failed: %.100s", strerror(errno)); -+ return xstrdup(ntop); -+ } -+ -+ ipv64_normalise_mapped(&from, &fromlen); -+ if (from.ss_family == AF_INET6) -+ fromlen = sizeof(struct sockaddr_in6); -+ -+ debug3("Trying to reverse map address %.100s.", ntop); -+ /* Map the IP address to a host name. */ -+ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), -+ NULL, 0, NI_NAMEREQD) != 0) { -+ /* Host name not found. Use ip address. */ -+ return xstrdup(ntop); -+ } -+ -+ /* -+ * if reverse lookup result looks like a numeric hostname, -+ * someone is trying to trick us by PTR record like following: -+ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 -+ */ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/ -+ hints.ai_flags = AI_NUMERICHOST; -+ if (getaddrinfo(name, NULL, &hints, &ai) == 0) { -+ logit("Nasty PTR record \"%s\" is set up for %s, ignoring", -+ name, ntop); -+ freeaddrinfo(ai); -+ return xstrdup(ntop); -+ } -+ -+ /* Names are stored in lowercase. */ -+ lowercase(name); -+ -+ /* -+ * Map it back to an IP address and check that the given -+ * address actually is an address of this host. This is -+ * necessary because anyone with access to a name server can -+ * define arbitrary names for an IP address. Mapping from -+ * name to IP address can be trusted better (but can still be -+ * fooled if the intruder has access to the name server of -+ * the domain). -+ */ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = from.ss_family; -+ hints.ai_socktype = SOCK_STREAM; -+ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { -+ logit("reverse mapping checking getaddrinfo for %.700s " -+ "[%s] failed.", name, ntop); -+ return xstrdup(ntop); -+ } -+ /* Look for the address from the list of addresses. */ -+ for (ai = aitop; ai; ai = ai->ai_next) { -+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, -+ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && -+ (strcmp(ntop, ntop2) == 0)) -+ break; -+ } -+ freeaddrinfo(aitop); -+ /* If we reached the end of the list, the address was not there. */ -+ if (ai == NULL) { -+ /* Address not found for the host name. */ -+ logit("Address %.100s maps to %.600s, but this does not " -+ "map back to the address.", ntop, name); -+ return xstrdup(ntop); -+ } -+ return xstrdup(name); -+} -+ -+/* -+ * Return the canonical name of the host in the other side of the current -+ * connection. The host name is cached, so it is efficient to call this -+ * several times. -+ */ -+ -+const char * -+auth_get_canonical_hostname(struct ssh *ssh, int use_dns) -+{ -+ static char *dnsname; -+ -+ if (!use_dns) -+ return ssh_remote_ipaddr(ssh); -+ else if (dnsname != NULL) -+ return dnsname; -+ else { -+ dnsname = remote_hostname(ssh); -+ return dnsname; -+ } -+} ---- a/readconf.c -+++ b/readconf.c -@@ -160,6 +160,7 @@ - oClearAllForwardings, oNoHostAuthenticationForLocalhost, - oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, - oAddressFamily, oGssAuthentication, oGssDelegateCreds, -+ oGssTrustDns, - oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, - oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, - oHashKnownHosts, -@@ -207,9 +208,11 @@ - #if defined(GSSAPI) - { "gssapiauthentication", oGssAuthentication }, - { "gssapidelegatecredentials", oGssDelegateCreds }, -+ { "gssapitrustdns", oGssTrustDns }, - # else - { "gssapiauthentication", oUnsupported }, - { "gssapidelegatecredentials", oUnsupported }, -+ { "gssapitrustdns", oUnsupported }, - #endif - #ifdef ENABLE_PKCS11 - { "pkcs11provider", oPKCS11Provider }, -@@ -1125,6 +1128,10 @@ - intptr = &options->gss_deleg_creds; - goto parse_flag; - -+ case oGssTrustDns: -+ intptr = &options->gss_trust_dns; -+ goto parse_flag; -+ - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; -@@ -2341,6 +2348,7 @@ - options->pubkey_authentication = -1; - options->gss_authentication = -1; - options->gss_deleg_creds = -1; -+ options->gss_trust_dns = -1; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; -@@ -2501,6 +2509,8 @@ - options->gss_authentication = 0; - if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; -+ if (options->gss_trust_dns == -1) -+ options->gss_trust_dns = 0; - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) ---- a/readconf.h -+++ b/readconf.h -@@ -41,6 +41,7 @@ - int hostbased_authentication; /* ssh2's rhosts_rsa */ - int gss_authentication; /* Try GSS authentication */ - int gss_deleg_creds; /* Delegate GSS credentials */ -+ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ - int password_authentication; /* Try password - * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -843,6 +843,16 @@ - Forward (delegate) credentials to the server. - The default is - .Cm no . -+Note that this option applies to protocol version 2 connections using GSSAPI. -+.It Cm GSSAPITrustDns -+Set to -+.Dq yes to indicate that the DNS is trusted to securely canonicalize -+the name of the host being connected to. If -+.Dq no, the hostname entered on the -+command line will be passed untouched to the GSSAPI library. -+The default is -+.Dq no . -+This option only applies to protocol version 2 connections using GSSAPI. - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -764,6 +764,13 @@ - OM_uint32 min; - int r, ok = 0; - gss_OID mech = NULL; -+ const char *gss_host; -+ -+ if (options.gss_trust_dns) { -+ extern const char *auth_get_canonical_hostname(struct ssh *ssh, int use_dns); -+ gss_host = auth_get_canonical_hostname(ssh, 1); -+ } else -+ gss_host = authctxt->host; - - /* Try one GSSAPI method at a time, rather than sending them all at - * once. */ -@@ -778,7 +785,7 @@ - elements[authctxt->mech_tried]; - /* My DER encoding requires length<128 */ - if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, -- mech, authctxt->host)) { -+ mech, gss_host)) { - ok = 1; /* Mechanism works */ - } else { - authctxt->mech_tried++; diff --git a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/files/openssh-9.3_p1-openssl-ignore-status.patch b/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/files/openssh-9.3_p1-openssl-ignore-status.patch deleted file mode 100644 index fa33af39b6f..00000000000 --- a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/files/openssh-9.3_p1-openssl-ignore-status.patch +++ /dev/null @@ -1,17 +0,0 @@ -the last nibble of the openssl version represents the status. that is, -whether it is a beta or release. when it comes to version checks in -openssh, this component does not matter, so ignore it. - -https://bugzilla.mindrot.org/show_bug.cgi?id=2212 - ---- a/openbsd-compat/openssl-compat.c -+++ b/openbsd-compat/openssl-compat.c -@@ -58,7 +58,7 @@ ssh_compatible_openssl(long headerver, long libver) - * For versions >= 1.0.0, major,minor,status must match and library - * fix version must be equal to or newer than the header. - */ -- mask = 0xfff0000fL; /* major,minor,status */ -+ mask = 0xfff00000L; /* major,minor,status */ - hfix = (headerver & 0x000ff000) >> 12; - lfix = (libver & 0x000ff000) >> 12; - if ( (headerver & mask) == (libver & mask) && lfix >= hfix) diff --git a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/openssh-9.5_p1-r1.ebuild b/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/openssh-9.6_p1-r1.ebuild similarity index 90% rename from sdk_container/src/third_party/coreos-overlay/net-misc/openssh/openssh-9.5_p1-r1.ebuild rename to sdk_container/src/third_party/coreos-overlay/net-misc/openssh/openssh-9.6_p1-r1.ebuild index fddfbe6e64d..eb005b627f0 100644 --- a/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/openssh-9.5_p1-r1.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/net-misc/openssh/openssh-9.6_p1-r1.ebuild @@ -3,6 +3,7 @@ EAPI=8 +VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/openssh.org.asc inherit user-info flag-o-matic autotools pam systemd toolchain-funcs verify-sig # Make it more portable between straight releases @@ -13,13 +14,13 @@ DESCRIPTION="Port of OpenBSD's free SSH release" HOMEPAGE="https://www.openssh.com/" SRC_URI=" mirror://openbsd/OpenSSH/portable/${PARCH}.tar.gz - verify-sig? ( mirror://openbsd/OpenSSH/portable/${PARCH}.tar.gz.asc )" -VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/openssh.org.asc + verify-sig? ( mirror://openbsd/OpenSSH/portable/${PARCH}.tar.gz.asc ) +" S="${WORKDIR}/${PARCH}" LICENSE="BSD GPL-2" SLOT="0" -KEYWORDS="~alpha amd64 ~arm arm64 ~hppa ~ia64 ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~arm64-macos ~ppc-macos ~x64-macos ~x64-solaris" +KEYWORDS="~alpha amd64 arm arm64 hppa ~ia64 ~loong ~m68k ~mips ppc ppc64 ~riscv ~s390 sparc x86 ~amd64-linux ~x86-linux ~arm64-macos ~ppc-macos ~x64-macos ~x64-solaris" # Probably want to drop ssl defaulting to on in a future version. IUSE="abi_mips_n32 audit debug kerberos ldns libedit livecd pam +pie security-key selinux +ssl static test X xmss" @@ -56,12 +57,14 @@ RDEPEND=" pam? ( sys-libs/pam ) kerberos? ( virtual/krb5 ) " -DEPEND="${RDEPEND} +DEPEND=" + ${RDEPEND} virtual/os-headers kernel_linux? ( !prefix-guest? ( >=sys-kernel/linux-headers-5.1 ) ) static? ( ${LIB_DEPEND} ) " -RDEPEND="${RDEPEND} +RDEPEND=" + ${RDEPEND} !net-misc/openssh-contrib pam? ( >=sys-auth/pambase-20081028 ) !prefix? ( sys-apps/shadow ) @@ -81,8 +84,6 @@ BDEPEND=" " PATCHES=( - "${FILESDIR}/${PN}-9.3_p1-GSSAPI-dns.patch" #165444 integrated into gsskex - "${FILESDIR}/${PN}-9.3_p1-openssl-ignore-status.patch" "${FILESDIR}/${PN}-9.3_p1-disable-conch-interop-tests.patch" "${FILESDIR}/${PN}-9.3_p1-fix-putty-tests.patch" "${FILESDIR}/${PN}-9.3_p1-deny-shmget-shmat-shmdt-in-preauth-privsep-child.patch" @@ -134,11 +135,9 @@ src_prepare() { # don't break .ssh/authorized_keys2 for fun sed -i '/^AuthorizedKeysFile/s:^:#:' sshd_config || die - eapply -- "${PATCHES[@]}" + [[ -d ${WORKDIR}/patches ]] && PATCHES+=( "${WORKDIR}"/patches ) - [[ -d ${WORKDIR}/patches ]] && eapply "${WORKDIR}"/patches - - eapply_user #473004 + default # These tests are currently incompatible with PORTAGE_TMPDIR/sandbox sed -e '/\t\tpercent \\/ d' \ @@ -186,7 +185,25 @@ src_configure() { --datadir="${EPREFIX}"/usr/share/openssh --with-privsep-path="${EPREFIX}"/var/empty --with-privsep-user=sshd - --with-hardening + + # --with-hardening adds the following in addition to flags we + # already set in our toolchain: + # * -ftrapv (which is broken with GCC anyway), + # * -ftrivial-auto-var-init=zero (which is nice, but not the end of + # the world to not have) + # * -fzero-call-used-regs=used (history of miscompilations with + # Clang (bug #872548), ICEs on m68k (bug #920350, gcc PR113086, + # gcc PR104820, gcc PR104817, gcc PR110934)). + # + # Furthermore, OSSH_CHECK_CFLAG_COMPILE does not use AC_CACHE_CHECK, + # so we cannot just disable -fzero-call-used-regs=used. + # + # Therefore, just pass --without-hardening, given it doesn't negate + # our already hardened toolchain defaults, and avoids adding flags + # which are known-broken in both Clang and GCC and haven't been + # proven reliable. + --without-hardening + $(use_with audit audit linux) $(use_with kerberos kerberos5 "${EPREFIX}"/usr) $(use_with ldns) @@ -200,8 +217,7 @@ src_configure() { ) if use elibc_musl; then - # musl defines bogus values for UTMP_FILE and WTMP_FILE - # https://bugs.gentoo.org/753230 + # musl defines bogus values for UTMP_FILE and WTMP_FILE (bug #753230) myconf+=( --disable-utmp --disable-wtmp ) fi @@ -229,13 +245,9 @@ src_test() { } insert_include() { - local src_config="${1}" options="${2}" includedir="${3}" + local src_config=${1} options=${2} includedir=${3} local name copy regexp_options regexp lineno comment_options - if [[ ! "${includedir}" =~ ^/.* ]]; then - die "includir must be an absolute path (i.e, starting with /). Got: ${includedir}" - fi - name=${src_config##*/} copy="${T}/${name}" cp -a "${src_config}" "${copy}" || die @@ -255,7 +267,7 @@ insert_include() { head -n "${lineno}" "${copy}" || die cat <<-EOF || die # Make sure that all ${comment_options} options are below this Include! - Include "${EPREFIX}${includedir}/*.conf" + Include "${includedir}/*.conf" EOF tail -n "+${lineno}" "${copy}" || die @@ -277,8 +289,8 @@ tweak_ssh_configs() { dodir /etc/ssh/ssh_config.d /etc/ssh/sshd_config.d - insert_include "${ED}"/etc/ssh/ssh_config 'Host,Match' '/etc/ssh/ssh_config.d' - insert_include "${ED}"/etc/ssh/sshd_config 'Match' '/etc/ssh/sshd_config.d' + insert_include "${ED}"/etc/ssh/ssh_config 'Host,Match' "${EPREFIX}"/etc/ssh/ssh_config.d + insert_include "${ED}"/etc/ssh/sshd_config 'Match' "${EPREFIX}"/etc/ssh/sshd_config.d cat <<-EOF >> "${ED}"/etc/ssh/ssh_config.d/9999999gentoo.conf || die # Send locale environment variables (bug #367017)