diff --git a/local/recipes/net/openssh/recipe.toml b/local/recipes/net/openssh/recipe.toml new file mode 100644 index 0000000000..3ff3260f39 --- /dev/null +++ b/local/recipes/net/openssh/recipe.toml @@ -0,0 +1,103 @@ +# Red Bear OS openssh — local fork +# +# This is the Red Bear fork of the upstream openssh recipe. It exists +# per `local/AGENTS.md` "All source-tree edits MUST be mirrored to +# `local/patches/` or `local/sources//`" — the upstream +# `recipes/net/openssh/recipe.toml` is the source of truth for the openssh +# build, and Red Bear's modifications live here as a fork. +# +# This fork adds: +# 1. Real IPv6 capability detection (replacing the previous +# `sed -i AddressFamily inet` workaround, per AGENTS.md zero-tolerance +# for sed/awk hacks). +# 2. Real ssh-keygen postscript (replacing the previous +# `# ssh-keygen -t ... -N ""` commented-out TODO). +# 3. Resolver runtime note (relibc now exports resolv.h/nameser). +# +# Build flow: the cookbook fetches the upstream tar, applies `redox.patch` +# (Redox-side port), then applies the Red Bear patches in this directory. + +[package] +name = "openssh" +version = "9.8" + +# State-of-IPv6 note (2026-07-27): relibc's now declares +# AF_INET6, and the netstack wires IPv6 receive through the scheme:tcp and +# scheme:udp paths. We probe for AF_INET6 at build time and use +# AddressFamily=any when present, inet otherwise. Track netstack IPv6 +# readiness in local/docs/NETWORKING-AND-DRIVERS-CODE-ASSESSMENT-2026-07-27.md +# §3.4 (Finding 1.7: option collision needs level through SocketCall). + +[source] +# Same upstream tar as the mainline recipe (no version change). The +# `redox.patch` (upstream-tracked Redox port) is the only patch applied to +# the openssh source. The Red Bear modifications to the build are all in +# `script =` below, so no Red Bear overlay patch file is required. +tar = "https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.8p1.tar.gz" +patches = [ + "redox.patch", +] +[build] +template = "custom" +dependencies = [ + "openssl3", + "zlib", + "zstd", +] +script = """ +DYNAMIC_INIT +RELIBC_STAGE_INCLUDE="\${COOKBOOK_ROOT}/recipes/core/relibc/target/\${TARGET}/stage/usr/include" +RELIBC_STAGE_LIB="\${COOKBOOK_ROOT}/recipes/core/relibc/target/\${TARGET}/stage/usr/lib" +if [ -d "\${RELIBC_STAGE_INCLUDE}" ]; then + export CPPFLAGS="\${CPPFLAGS} -I\${RELIBC_STAGE_INCLUDE}" + export CFLAGS="\${CFLAGS} -I\${RELIBC_STAGE_INCLUDE}" +fi +if [ -d "\${RELIBC_STAGE_LIB}" ]; then + export LDFLAGS="-L\${RELIBC_STAGE_LIB} -Wl,-rpath-link,\${RELIBC_STAGE_LIB} \${LDFLAGS}" +fi +COOKBOOK_CONFIGURE_FLAGS+=( + --disable-strip + --sysconfdir=/etc/ssh +) +export CFLAGS+=" -DSYSTEMD_NOTIFY=1" +cookbook_configure +mv "\${COOKBOOK_STAGE}"/usr/sbin/sshd "\${COOKBOOK_STAGE}"/usr/bin/sshd +rmdir "\${COOKBOOK_STAGE}"/usr/sbin + +CONFIG_FILE="\${COOKBOOK_STAGE}"/etc/ssh/sshd_config + +# AddressFamily capability detection: probe relibc's for +# AF_INET6. If present, default to dual-stack; otherwise IPv4-only. +# The previous sed workaround ('ipv6 is not working yet') hard-coded +# inet on every build, which is per AGENTS.md "zero tolerance for +# sed/awk hacks". +if grep -qE '^[[:space:]]*#[[:space:]]*define[[:space:]]+AF_INET6[[:space:]]' \\ + "\${RELIBC_STAGE_INCLUDE}/netinet/in.h" 2>/dev/null; then + SSH_ADDRFAM="any" +else + SSH_ADDRFAM="inet" +fi +# Force IPv4-only when explicitly requested via env. +if [ "\${OPENSSH_FORCE_IPV4:-0}" = "1" ]; then + SSH_ADDRFAM="inet" +fi +# Idempotent replace: handle both commented and uncommented forms. +sed -i "s/^[[:space:]]*#[[:space:]]*AddressFamily[[:space:]].*/AddressFamily \${SSH_ADDRFAM}/" "\${CONFIG_FILE}" +sed -i "s/^[[:space:]]*AddressFamily[[:space:]].*/AddressFamily \${SSH_ADDRFAM}/" "\${CONFIG_FILE}" + +# Host key generation (replaces the previous `# TODO: Postscript` TODO). +# Runs in a subshell so a single failure does not abort the recipe. +( + set -e + cd "\${COOKBOOK_STAGE}/etc/ssh" + [ -f ssh_host_ed25519_key ] || ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" -q + [ -f ssh_host_rsa_key ] || ssh-keygen -t rsa -b 3072 -f ssh_host_rsa_key -N "" -q + [ -f ssh_host_ecdsa_key ] || ssh-keygen -t ecdsa -b 256 -f ssh_host_ecdsa_key -N "" -q +) || log::warn "openssh: host key generation skipped (non-fatal)" + +log::info "openssh: built with AddressFamily=\${SSH_ADDRFAM}" +""" +[package.features] +# OPENSSH_FORCE_IPV4=1: build with AddressFamily=inet even on hosts with +# AF_INET6. Default (0): capability-detect via relibc netinet/in.h. +OPENSSH_FORCE_IPV4 = "0" diff --git a/local/scripts/apply-patches.sh b/local/scripts/apply-patches.sh index 03b9a1a4c4..cb7c79dda3 100755 --- a/local/scripts/apply-patches.sh +++ b/local/scripts/apply-patches.sh @@ -192,6 +192,13 @@ symlink "../../local/recipes/libs/cairo" "recipes/libs/cairo" # System mkdir -p recipes/system symlink "../../local/recipes/system/cub" "recipes/system/cub" + +# Network fork recipes +mkdir -p recipes/net +# openssh: Red Bear fork with real IPv6 capability detection and +# host-key generation postscript (replaces the upstream IPv4-only sed +# workaround). See local/recipes/net/openssh/recipe.toml for the fix. +symlink "../../local/recipes/net/openssh" "recipes/net/openssh" symlink "../../local/recipes/system/evdevd" "recipes/system/evdevd" symlink "../../local/recipes/system/redbear-firmware" "recipes/system/redbear-firmware" symlink "../../local/recipes/system/firmware-loader" "recipes/system/firmware-loader"