diff --git a/build-aux/iso-grub-cfg.sh b/build-aux/iso-grub-cfg.sh index b2ba49bc..360c37e7 100755 --- a/build-aux/iso-grub-cfg.sh +++ b/build-aux/iso-grub-cfg.sh @@ -123,6 +123,7 @@ mkdir -p boot/grub/init echo "furthermore" > boot/grub/init/furthermore # TODO: Possibly use a 'try' feature to not warn in case it was already unset. echo "unset require dhclient" > boot/grub/init/network-no-dhclient +echo "require sshd optional" > boot/grub/init/local-sshd exec > boot/grub/grub.cfg @@ -191,6 +192,7 @@ fi set enable_src=true set enable_network_drivers= set enable_dhclient=true +set enable_sshd=false export version export machine @@ -202,6 +204,7 @@ export no_random_seed export enable_src export enable_network_drivers export enable_dhclient +export enable_sshd EOF if [ -n "$ports" ]; then @@ -297,6 +300,11 @@ cat << EOF module /boot/grub/init/network-no-dhclient --append-to /etc/init/network echo done fi + if \$enable_sshd; then + echo -n "Enabling sshd ... " + module /boot/grub/init/local-sshd --append-to /etc/init/local + echo done + fi if [ \$no_random_seed != --no-random-seed ]; then echo -n "Loading /boot/random.seed (256) ... " module /boot/random.seed --random-seed @@ -456,6 +464,18 @@ else } fi +if \$enable_sshd; then + menuentry "Disable SSH server" { + enable_sshd=false + configfile /boot/grub/advanced.cfg + } +else + menuentry "Enable SSH server" { + enable_sshd=true + configfile /boot/grub/advanced.cfg + } +fi + menuentry "Select binary packages..." { configfile /boot/grub/tix.cfg } diff --git a/build-aux/ports.conf b/build-aux/ports.conf index b2e29510..dba9895e 100644 --- a/build-aux/ports.conf +++ b/build-aux/ports.conf @@ -1,3 +1,3 @@ set_minimal="cut dash e2fsprogs grep grub mdocml sed xargs" -set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip libcurl libcurses libssl libstdc++ nano make patch pkg-config tar vim wget xz xorriso" +set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip libcurl libcurses libssl libstdc++ nano make patch pkg-config ssh tar vim wget xz xorriso" sets="basic minimal" diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h index ef482084..7615bd44 100644 --- a/libc/include/sys/cdefs.h +++ b/libc/include/sys/cdefs.h @@ -99,4 +99,37 @@ is updated to not rely on this macro. */ #undef __SORTIX_HAS_RESTARTABLE_SYSCALLS__ +/* TODO: Define when general user security is implemented. Remove when ssh is + updated to not rely on this macro. */ +#undef __SORTIX_HAS_UID_SECURITY__ + +/* TODO: Define when mmap MAP_SHARED works properly. Remove when ssh is updated + to not rely on this macro. */ +#undef __SORTIX_HAS_WORKING_MAP_SHARED__ + +/* TODO: Define when shared memory, file descriptor passing, and general user + security are implemented. Remove when ssh is updated to not rely on + this macro. */ +#undef __SORTIX_HAS_WORKING_PRIVSEP__ + +/* TODO: Define when initgroups(2) is implemented. Remove when ssh is updated to + not rely on this macro. */ +#undef __SORTIX_HAS_INITGROUPS__ + +/* TODO: Define when setgroups(2) is implemented. Remove when ssh is updated to + not rely on this macro. */ +#undef __SORTIX_HAS_SETGROUPS__ + +/* TODO: Define when getgroups(2) is implemented. Remove when ssh is updated to + not rely on this macro. */ +#undef __SORTIX_HAS_GETGROUPS__ + +/* TODO: Define when scanf is standards compliant. Remove when ssh is updated to + not rely on this macro. */ +#undef __SORTIX_HAS_WORKING_SCANF__ + +/* TODO: Define when getservbyname(3) is implemented and works. Remove when ssh + is updated to not rely on this macro. */ +#undef __SORTIX_HAS_GETSERVBYNAME__ + #endif diff --git a/share/man/man7/installation.7 b/share/man/man7/installation.7 index bf30b65c..5066ccc0 100644 --- a/share/man/man7/installation.7 +++ b/share/man/man7/installation.7 @@ -83,7 +83,8 @@ The release modification procedure lets you customize aspects such as the default bootloader menu option and timeout, the default hostname, the default keyboard layout, the default graphics resolution, adding files of your choice to the live environment, control which drivers are loaded by default, control which -live environment daemons are started by default, and so on. +live environment daemons are started by default, deploy ssh keys so secure shell +connections are trusted on the first connection, and so on. .Pp Warning: The live environment does not come with any random entropy and entropy gathering is not yet implemented. diff --git a/share/man/man7/release-iso-bootconfig.7 b/share/man/man7/release-iso-bootconfig.7 index 44363cf5..4f5e278c 100644 --- a/share/man/man7/release-iso-bootconfig.7 +++ b/share/man/man7/release-iso-bootconfig.7 @@ -276,6 +276,8 @@ Whether to load the source code initrd containing .Pa /src . (Default: .Sy true ) +.It Sy enable_sshd +TODO: Document this. .It Sy machine The machine type this release was built for. .It Sy menu_title diff --git a/share/man/man7/release-iso-modification.7 b/share/man/man7/release-iso-modification.7 index 3ed5a004..8614585d 100644 --- a/share/man/man7/release-iso-modification.7 +++ b/share/man/man7/release-iso-modification.7 @@ -17,7 +17,8 @@ The release modification procedure lets you customize aspects such as the default bootloader menu option and timeout, the default hostname, the default keyboard layout, the default graphics resolution, adding files of your choice to the live environment, control which drivers are loaded by default, control which -live environment daemons are started by default, and so on. +live environment daemons are started by default, deploy ssh keys so secure shell +connections are trusted on the first connection, and so on. .Ss Prerequisites .Bl -bullet -compact .It @@ -410,6 +411,105 @@ wants to manually configure network interfaces with tix-iso-bootconfig --disable-dhclient bootconfig tix-iso-add sortix.iso bootconfig .Ed +.Ss Enable SSH Server By Default +To customize a release so it starts the SSH server +.Xr sshd 8 +automatically using the SSH configuration found in the liveconfig directory: +.Bd -literal +tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig +tix-iso-add sortix.iso bootconfig +.Ed +.Ss SSH Into Live Environment +To customize the live environment of a release so you can ssh into its root +user, to have the the hostname +.Sy example.com , +to start a ssh server with the keys generated now, authorize the local user to +ssh into the live environment's root user, and register the sshd server's keys +by their hostnames and network addresses so the connection is trusted on the +first attempt (you can omit the network addresses if you don't know yet): +.Bd -literal +tix-iso-liveconfig \\ + --hostname=example.com \\ + --root-ssh-authorized-keys="$HOME/.ssh/id_rsa.pub" \\ + --sshd-keygen \\ + --sshd-key-known-hosts-file="$HOME/.ssh/known_hosts" \\ + --sshd-key-known-hosts-hosts="example.com example.com,192.0.2.1 192.0.2.1" \\ + liveconfig +tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig +tix-iso-add sortix.iso bootconfig +rm -f liveconfig/etc/ssh_host_*_key # When no longer useful. +rm -f bootconfig/boot/liveconfig.xz # When no longer useful. +rm -f sortix.iso # When no longer useful. +# And erase any media made from sortix.iso when no longer useful. +ssh root@example.org # When the system is running. +.Ed +This example generates sshd private keys (remember to delete them when no longer +needed, see the warnings in +.Xr tix-iso-liveconfig 8 ) +and shows them by running: +.Bd -literal +mkdir -p liveconfig/etc +for keytype in rsa dsa ecdsa ed25519; do + ssh-keygen -t $keytype -f liveconfig/etc/ssh_host_${keytype}_key" -N "" \\ + -C "root@$hostname" +done +for keytype in rsa dsa ecdsa ed25519; do + ssh-keygen -l -f liveconfig/etc/ssh_host_${keytype}_key +done +.Ed +It then constructs a +.Pa known_hosts +file for each network address and hashes it. +.Bd -literal +(for host in $network_addresses; do + for keytype in rsa dsa ecdsa ed25519; do + printf '%s ' "$host" && + sed -E 's/^([^ ]* [^ ]*).*/\1/' \\ + liveconfig/etc/ssh_host_${keytype}_key.pub + done +done) > known_hosts +ssh-keygen -H -f known_hosts +rm -f known_hosts.old +.Ed +.Xr ssh 1 +will trust the server by the network addresses on the first connection if you +append the contents of +.Pa known_hosts +to your +.Pa ~/.ssh/known_hosts . +.Pa liveconfig/root/.ssh/authorized_keys +file is made by appending the appropriate public keys previously made with +.Xr ssh-keygen 1 . +.Ss SSH Back From Live Environment +To customize the live environment of a release so its root user can ssh back to +your user, where the local hostname is +.Sy example.com +(the address to which the new installation will be connecting), by +generating a private key for the root user +(remember to delete it when no longer +needed, see the warnings in +.Xr tix-iso-liveconfig 8 ) +and adding its public key to your local +.Pa ~/.ssh/authorized_keys : +.Bd -literal +tix-iso-liveconfig --root-ssh-keygen liveconfig +ssh-keyscan -H example.com > liveconfig/root/.ssh/known_hosts +cat liveconfig/root/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys +tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig +tix-iso-add sortix.iso bootconfig +rm -f output-directory/root/.ssh/id_rsa # When no longer useful. +rm -f bootconfig/boot/liveconfig.xz # When no longer useful. +rm -f sortix.iso # When no longer useful. +# And erase any media made from sortix.iso when no longer useful. +.Ed +This example will generate a ssh key for the root user by running: +.Bd -literal +mkdir -p -m 700 liveconfig/root/.ssh +ssh-keygen -t rsa -f liveconfig/root/.ssh/id_rsa -N "" -C "root@$hostname" +.Ed +Consider omitting the +.Fl N +option and password protect the private key to protect it in the case of a leak. .Sh SEE ALSO .Xr xorriso 1 , .Xr development 7 , diff --git a/share/man/man7/upgrade.7 b/share/man/man7/upgrade.7 index f9181efd..43781ab7 100644 --- a/share/man/man7/upgrade.7 +++ b/share/man/man7/upgrade.7 @@ -30,7 +30,8 @@ The release modification procedure lets you customize aspects such as the default bootloader menu option and timeout, the default hostname, the default keyboard layout, the default graphics resolution, adding files of your choice to the live environment, control which drivers are loaded by default, control which -live environment daemons are started by default, and so on. +live environment daemons are started by default, deploy ssh keys so secure shell +connections are trusted on the first connection, and so on. .Pp Warning: The live environment does not come with any random entropy and entropy gathering is not yet implemented. diff --git a/sysinstall/sysinstall.c b/sysinstall/sysinstall.c index 8e226a87..381e7cfa 100644 --- a/sysinstall/sysinstall.c +++ b/sysinstall/sysinstall.c @@ -1023,6 +1023,54 @@ int main(void) textf("Group '%s' added to /etc/group.\n", "root"); break; } + // TODO: This should also be done in sysupgrade(8). + struct ssh_file + { + const char* path; + const char* pub; + }; + const struct ssh_file ssh_files[] = + { + {"/root/.ssh/authorized_keys", NULL}, + {"/root/.ssh/config", NULL}, + {"/root/.ssh/id_dsa", "/root/.ssh/id_dsa.pub"}, + {"/root/.ssh/id_rsa", "/root/.ssh/id_rsa.pub"}, + {"/root/.ssh/known_hosts", NULL}, + }; + size_t ssh_files_count = sizeof(ssh_files) / sizeof(ssh_files[0]); + for ( size_t i = 0; i < ssh_files_count; i++ ) + { + const struct ssh_file* file = &ssh_files[i]; + if ( access_or_die(file->path, F_OK) < 0 ) + continue; + text("\n"); + textf("Found %s\n", file->path); + if ( file->pub && !access_or_die(file->pub, F_OK) ) + textf("Found %s\n", file->pub); + while ( true ) + { + char question[256]; + snprintf(question, sizeof(question), + "Copy %s from installer environment?", file->path); + prompt(input, sizeof(input), question, "no"); + if ( strcasecmp(input, "no") == 0 ) + break; + if ( strcasecmp(input, "yes") != 0 ) + continue; + mkdir_or_chmod_or_die("root/.ssh", 0700); + // TODO: The right way to copy a file here? + textf("Copying %s -> %s\n", file->path, file->path + 1); + execute((const char*[]) + {"cp", file->path, file->path+ 1, NULL }, "f"); + if ( file->pub ) + { + textf("Copying %s -> %s\n", file->pub, file->pub + 1); + execute((const char*[]) + {"cp", file->pub, file->pub + 1, NULL }, "f"); + } + break; + } + } text("\n"); if ( mkdir("etc/init", 0755) < 0 ) @@ -1128,6 +1176,91 @@ int main(void) // TODO: Ask if networking should be disabled / enabled. + if ( !access_or_die("/tix/tixinfo/ssh", F_OK) ) + { + text("A ssh server has been installed. You have the option of starting " + "it on boot to allow remote login over a cryptographically secure " + "channel.\n\n"); + text("Warning: " BRAND_DISTRIBUTION_NAME " does not yet collect " + "entropy for secure random numbers. Unless you type '!' and " + "escape to a shell and put 256 bytes of actual randomness into " + "boot/random.seed, the first boot will use the randomness of this " + "installer environment to generate ssh keys. This initial " + "randomness may be as weak as the wall time when you booted the " + "installer, which is easily guessed by an attacker. The same " + "warning applies to outgoing secure connections as well.\n\n"); + while ( true ) + { + prompt(input, sizeof(input), + "Enable ssh server?", "no"); + if ( strcasecmp(input, "no") == 0 ) + break; + if ( strcasecmp(input, "yes") != 0 ) + continue; + if ( !install_configurationf("etc/init/local", "a", + "require sshd optional\n") ) + { + warn("etc/init/local"); + continue; + } + text("Added 'require sshd optional' to /etc/init/local\n"); + text("The ssh server will be started when the system boots.\n"); + break; + } + text("\n"); + } + + struct sshd_key_file + { + const char* pri; + const char* pub; + }; + const struct sshd_key_file sshd_key_files[] = + { + {"/etc/ssh_host_dsa_key", "/etc/ssh_host_dsa_key.pub"}, + {"/etc/ssh_host_ecdsa_key", "/etc/ssh_host_ecdsa_key.pub"}, + {"/etc/ssh_host_ed25519_key", "/etc/ssh_host_ed25519_key.pub"}, + {"/etc/ssh_host_rsa_key", "/etc/ssh_host_rsa_key.pub"}, + }; + size_t sshd_key_files_count + = sizeof(sshd_key_files) / sizeof(sshd_key_files[0]); + bool any_sshd_keys = false; + for ( size_t i = 0; i < sshd_key_files_count; i++ ) + { + if ( !access_or_die(sshd_key_files[i].pri, F_OK) ) + { + textf("Found %s\n", sshd_key_files[i].pri); + any_sshd_keys = true; + } + } + if ( any_sshd_keys ) + { + while ( true ) + { + prompt(input, sizeof(input), + "Copy sshd private keys from installer environment?", "no"); + if ( strcasecmp(input, "no") == 0 ) + break; + if ( strcasecmp(input, "yes") != 0 ) + continue; + for ( size_t i = 0; i < sshd_key_files_count; i++ ) + { + const struct sshd_key_file* file = &sshd_key_files[i]; + if ( access_or_die(file->pri, F_OK) < 0 ) + continue; + // TODO: The right way to copy a file here? + textf("Copying %s -> %s\n", file->pri, file->pri + 1); + execute((const char*[]) + {"cp", file->pri, file->pri + 1, NULL }, "f"); + textf("Copying %s -> %s\n", file->pub, file->pub + 1); + execute((const char*[]) + {"cp", file->pub, file->pub + 1, NULL }, "f"); + } + break; + } + text("\n"); + } + text("It's time to boot into the newly installed system.\n\n"); if ( strcasecmp(accept_grub, "no") == 0 ) diff --git a/tix/tix-iso-bootconfig b/tix/tix-iso-bootconfig index 8976b92a..e32aedb3 100755 --- a/tix/tix-iso-bootconfig +++ b/tix/tix-iso-bootconfig @@ -25,6 +25,7 @@ enable_append_title=true enable_dhclient= enable_network_drivers= enable_src= +enable_sshd= liveconfig= operand=1 random_seed=false @@ -55,10 +56,12 @@ for argument do --disable-dhclient) enable_dhclient=false ;; --disable-network-drivers) enable_network_drivers=false ;; --disable-src) enable_src=false ;; + --disable-sshd) enable_sshd=false ;; --enable-append-title) enable_append_title=true ;; --enable-dhclient) enable_dhclient=true ;; --enable-network-drivers) enable_network_drivers=true ;; --enable-src) enable_src=true ;; + --enable-sshd) enable_sshd=true ;; --liveconfig=*) liveconfig=$parameter ;; --liveconfig) previous_option=liveconfig ;; --random-seed) random_seed=true ;; @@ -141,6 +144,7 @@ mkdir -p -- "$directory/boot/grub" print_enable_default_bool "$enable_dhclient" dhclient dhclient print_enable_default "$enable_network_drivers" network_drivers network-drivers print_enable_default_bool "$enable_src" src src + print_enable_default_bool "$enable_sshd" sshd sshd if $enable_append_title; then printf "base_menu_title=\"\$base_menu_title - \"'%s'\n" \ "$(printf '%s\n' "$append_title" | sed "s/'/'\\\\''/g")" diff --git a/tix/tix-iso-bootconfig.8 b/tix/tix-iso-bootconfig.8 index 3158dd1a..c27de11a 100644 --- a/tix/tix-iso-bootconfig.8 +++ b/tix/tix-iso-bootconfig.8 @@ -12,10 +12,12 @@ .Op Fl \-disable-dhclient .Op Fl \-disable-network-drivers .Op Fl \-disable-src +.Op Fl \-disable-sshd .Op Fl \-enable-append-title .Op Fl \-enable-dhclient .Op Fl \-enable-network-drivers .Op Fl \-enable-src +.Op Fl \-enable-sshd .Op Fl \-liveconfig Ns = Ns Ar liveconfig-directory .Op Fl \-random-seed .Op Fl \-timeout Ns = Ns Ar boot-menu-timeout @@ -115,6 +117,14 @@ by setting .Sy enable_src GRUB variable to .Sy false . +.It Fl \-disable-sshd +Disable automatically starting the ssh server by setting the +.Sy enable_sshd +GRUB variable to +.Sy false , +selecting the the default behavior of not starting the +.Xr sshd 8 +daemon. .It Fl \-enable-append-title Enable appending " - " followed by the value set with .Fl \-append-title @@ -146,6 +156,14 @@ by setting .Sy enable_src GRUB variable to .Sy true . +.It Fl \-enable-sshd +Enable automatically starting the ssh server by setting the +.Sy enable_sshd +GRUB variable to +.Sy true , +causing the bootloader to load additional configuration that turns on the +.Xr sshd 8 +daemon on boot. .It Fl \-liveconfig Ns = Ns Ar liveconfig-directory Overlay the .Ar liveconfig-directory @@ -282,6 +300,14 @@ wants to manually configure network interfaces with tix-iso-bootconfig --disable-dhclient bootconfig tix-iso-add sortix.iso bootconfig .Ed +.Ss Enable SSH Server By Default +To customize a release so it starts the SSH server +.Xr sshd 8 +automatically using the SSH configuration found in the liveconfig directory: +.Bd -literal +tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig +tix-iso-add sortix.iso bootconfig +.Ed .Sh SEE ALSO .Xr xorriso 1 , .Xr kernel 7 , diff --git a/tix/tix-iso-liveconfig b/tix/tix-iso-liveconfig index fe902cf7..2ac589fb 100755 --- a/tix/tix-iso-liveconfig +++ b/tix/tix-iso-liveconfig @@ -22,6 +22,15 @@ directory= hostname= kblayout= operand=1 +root_ssh_authorized_keys= +root_ssh_config= +root_ssh_keygen=false +root_ssh_known_hosts= +ssh_config= +sshd_config= +sshd_keygen=false +sshd_key_known_hosts_file= +sshd_key_known_hosts_hosts= videomode= dashdash= @@ -45,6 +54,22 @@ for argument do --hostname) previous_option=hostname ;; --kblayout=*) kblayout=$parameter ;; --kblayout) previous_option=kblayout ;; + --root-ssh-authorized-keys=*) root_ssh_authorized_keys=$parameter ;; + --root-ssh-authorized-keys) previous_option=root_ssh_authorized_keys ;; + --root-ssh-config=*) root_ssh_config=$parameter ;; + --root-ssh-config) previous_option=root_ssh_config ;; + --root-ssh-keygen) root_ssh_keygen=true ;; + --root-ssh-known-hosts=*) root_ssh_known_hosts=$parameter ;; + --root-ssh-known-hosts) previous_option=root_ssh_known_hosts ;; + --ssh-config=*) ssh_config=$parameter ;; + --ssh-config) previous_option=ssh_config ;; + --sshd-config=*) sshd_config=$parameter ;; + --sshd-config) previous_option=sshd_config ;; + --sshd-keygen) sshd_keygen=true ;; + --sshd-key-known-hosts-file=*) sshd_key_known_hosts_file=$parameter ;; + --sshd-key-known-hosts-file) previous_option=sshd_key_known_hosts_file ;; + --sshd-key-known-hosts-hosts=*) sshd_key_known_hosts_hosts=$parameter ;; + --sshd-key-known-hosts-hosts) previous_option=sshd_key_known_hosts_hosts ;; --videomode=*) videomode=$parameter ;; --videomode) previous_option=videomode ;; -*) echo "$0: unrecognized option $argument" >&2 @@ -87,3 +112,72 @@ fi if [ -n "$videomode" ]; then printf "%s\n" "$videomode" > "$directory/etc/videomode" fi + +if [ -n "$ssh_config" ]; then + mkdir -p -- "$directory/etc" + cp -- "$ssh_config" "$directory/etc/ssh_config" +fi + +if [ -n "$sshd_config" ]; then + mkdir -p -- "$directory/etc" + cp -- "$sshd_config" "$directory/etc/sshd_config" +fi + +if $sshd_keygen; then + mkdir -p -- "$directory/etc" + for keytype in rsa dsa ecdsa ed25519; do + if [ ! -e "$directory/etc/ssh_host_${keytype}_key" ]; then + ssh-keygen -t $keytype -f "$directory/etc/ssh_host_${keytype}_key" -N "" \ + -C "root@$hostname" + fi + done + for keytype in rsa dsa ecdsa ed25519; do + ssh-keygen -l -f "$directory/etc/ssh_host_${keytype}_key" + done +fi + +if [ -n "$sshd_key_known_hosts_file" ]; then + known_hosts_tmp=$(mktemp) + for host in $sshd_key_known_hosts_hosts; do + for keytype in rsa dsa ecdsa ed25519; do + if [ ! -e "$directory/etc/ssh_host_${keytype}_key.pub" ]; then + continue + fi + (printf '%s ' "$host" && + sed -E 's/^([^ ]* [^ ]*).*/\1/' \ + "$directory/etc/ssh_host_${keytype}_key.pub") \ + >> "$known_hosts_tmp" + done + done + # TODO: ssh-keygen needs a standalone way to make such a hash. + ssh-keygen -H -f "$known_hosts_tmp" 1>/dev/null 2>/dev/null + cat -- "$known_hosts_tmp" >> "$sshd_key_known_hosts_file" + rm -f "$known_hosts_tmp" + rm -f "$known_hosts_tmp.old" +fi + +if [ -n "$root_ssh_authorized_keys" ]; then + mkdir -p -- "$directory/root" + mkdir -p -m 700 -- "$directory/root/.ssh" + cp -- "$root_ssh_authorized_keys" "$directory/root/.ssh/authorized_keys" +fi + +if [ -n "$root_ssh_config" ]; then + mkdir -p -- "$directory/root" + mkdir -p -m 700 -- "$directory/root/.ssh" + cp -- "$root_ssh_config" "$directory/root/.ssh/config" +fi + +if [ -n "$root_ssh_known_hosts" ]; then + mkdir -p -- "$directory/root" + mkdir -p -m 700 -- "$directory/root/.ssh" + cp -- "$root_ssh_known_hosts" "$directory/root/.ssh/known_hosts" +fi + +if $root_ssh_keygen; then + mkdir -p -- "$directory/root" + mkdir -p -m 700 -- "$directory/root/.ssh" + if [ ! -e "$directory/root/.ssh/id_rsa"]; then + ssh-keygen -t rsa -f "$directory/root/.ssh/id_rsa" -N "" -C "root@$hostname" + fi +fi diff --git a/tix/tix-iso-liveconfig.8 b/tix/tix-iso-liveconfig.8 index 3f233dfe..3d1bb5d6 100644 --- a/tix/tix-iso-liveconfig.8 +++ b/tix/tix-iso-liveconfig.8 @@ -8,6 +8,15 @@ .Nm .Op Fl \-hostname Ns = Ns Ar hostname .Op Fl \-kblayout Ns = Ns Ar kblayout +.Op Fl \-root-ssh-authorized-keys Ns = Ns Ar file +.Op Fl \-root-ssh-config Ns = Ns Ar file +.Op Fl \-root-ssh-keygen +.Op Fl \-root-ssh-known-hosts Ns = Ns Ar file +.Op Fl \-ssh-config Ns = Ns Ar file +.Op Fl \-sshd-config Ns = Ns Ar file +.Op Fl \-sshd-keygen +.Op Fl \-sshd-key-known-hosts-file Ns = Ns Ar file +.Op Fl \-sshd-key-known-hosts-hosts Ns = Ns Ar host-list .Op Fl \-videomode Ns = Ns Ar videomode .Ar output-directory .Sh DESCRIPTION @@ -57,6 +66,151 @@ to .Pa output-directory/etc/kblayout . (See .Xr kblayout 5 ) +.It Fl \-root-ssh-authorized-keys Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/root/.ssh/authorized_keys +so it becomes root's list of authorized ssh keys. +.It Fl \-root-ssh-config Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/root/.ssh/config +so it becomes root's +.Xr ssh_config 5 . +.It Fl \-root-ssh-keygen +Generate a ssh private and public key pair for rsa (see the warnings below) at +.Pa output-directory/root/.ssh/id_rsa +and +.Pa output-directory/root/.ssh/id_rsa.pub . +These keys are not regenerated if they already exist. +The comment in the key uses the +.Fl \-hostname +option if set, otherwise it defaults to +.Sy sortix . +The key is not password protected. +.Pp +The key is generated by running: +.Bd -literal +ssh-keygen \\ + -t rsa \\ + -f "$output_directory/root/.ssh/id_rsa" \\ + -N "" \\ + -C "root@$hostname" +.Ed +.Pp +Warning: The information in the generated +.Pa output-directory/root/.ssh/id_rsa +private key must be kept confidential and should be securely erased whereever it +goes whenever it is no longer useful in a particular place, otherwise +unauthorized may be able to impersonate this user. +These keys should be reissued whenever a root user of a new installation should +be considered distinct from other installations using the same keys. +The installer will offer to copy the keys to the newly installed system. +Once the +.Ar output-directory +is no longer useful, the +.Pa output-directory/root/.ssh/id_rsa +file inside it should be securely erased. +If a bootconfig has been made whose liveconfig contains thes private key, +.Pa bootconfig/boot/liveconfig.xz +should be securely erased when no longer useful. +If a release .iso has been made from +.Ar output-directory , +it should be securely erased when no longer useful. +If a release .iso has been burned to a physical media, it should be securely +erased when no longer useful. +.It Fl \-root-ssh-known-hosts Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/root/.ssh/known_hosts +so it becomes root's list of known ssh hosts and their public keys. +.It Fl \-ssh-config Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/etc/ssh_config +so it becomes the +.Xr ssh_config 5 +of the live environment. +.It Fl \-sshd-config Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/etc/sshd_config +so it becomes the +.Xr sshd_config 5 +of the live environment. +.It Fl \-sshd-keygen +Generate sshd private keys for rsa, dsa, ecdsa, and ed25519 (see the below +warnings), but don't overwrite any existing keys in the +.Ar output-directory +directory. +The comment in the key uses the +.Fl \-hostname +option if set, otherwise it defaults to +.Sy sortix . +Each key is generated by running: +.Bd -literal +ssh-keygen \\ + -t $keytype \\ + -f "$output_directory/etc/ssh_host_${keytype}_key" \\ + -N "" \\ + -C "root@$hostname" +.Ed +.Pp +The fingerprints of each key is printed afterwards by running: +.Bd -literal +.Li ssh-keygen -l -f "$output_directory/etc/ssh_host_${keytype}_key" +.Ed +.Pp +Warning: The information in the generated +.Pa output_directory/etc/ssh_host_*_key +files must be kept confidential and should be securely erased whereever it goes +whenever it is no longer useful in a particular place, otherwise unauthorized +people may be able to impersonate the ssh server. +These keys should not be recycled to image more than a single system. +The installer will offer to copy the keys to the newly installed system. +Once the +.Ar output-directory +is no longer useful, the +.Pa output_directory/etc/ssh_host_*_key +files inside it should be securely erased. +If a bootconfig has been made whose liveconfig contains these keys, +.Pa bootconfig/boot/liveconfig.xz +should be securely erased when no longer useful. +If a release .iso has been made from +.Ar output-directory , +it should be securely erased when no longer useful. +If a release .iso has been burned to a physical media, it should be securely +erased when no longer useful. +.It Fl \-sshd-key-known-hosts-file Ns = Ns Ar file +Append the ssh known_hosts entries to +.Ar file +for the +.Pa output_directory/etc/ssh_host_*_key.pub +.Xr sshd 8 +keys for each hostname provided in the +.Fl \-sshd-key-known-hosts-hosts +option. +For each hostname, for each public key, a line is written to the +.Ar file +consisting of the hostname followed by a space and then followed by the public +key. +The written entries are then hashed an attacker can't discover the hosts from +the known_hosts file, which is done by running +.Xr ssh-keygen 1 +with the +.Fl H +option on the produced file. +.It Fl \-sshd-key-known-hosts-hosts Ns = Ns Ar host-list +A space delimited list of hostnames, network addresses, and hostnames followed +by a comma and then the network address, which the sshd server will be +connectible by, used to generate the known_hosts entries in the +.Fl \-sshd-key-known-hosts-file +option. .It Fl \-videomode Ns = Ns Ar videomode Set the live environment's graphics resolution by writing .Ar videomode @@ -82,11 +236,55 @@ tix-iso-liveconfig \\ tix-iso-bootconfig --liveconfig=liveconfig bootconfig tix-iso-add sortix.iso bootconfig .Ed +.Ss SSH Into Live Environment +To customize the live environment of a release so you can ssh into its root +user, to have the the hostname +.Sy example.com , +to start a ssh server with the keys generated now, authorize the local user to +ssh into the live environment's root user, and register the sshd server's keys +by their hostnames and network addresses so the connection is trusted on the +first attempt (you can omit the network addresses if you don't know yet): +.Bd -literal +tix-iso-liveconfig \\ + --hostname=example.com \\ + --root-ssh-authorized-keys="$HOME/.ssh/id_rsa.pub" \\ + --sshd-keygen \\ + --sshd-key-known-hosts-file="$HOME/.ssh/known_hosts" \\ + --sshd-key-known-hosts-hosts="example.com example.com,192.0.2.1 192.0.2.1" \\ + liveconfig +tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig +tix-iso-add sortix.iso bootconfig +rm -f liveconfig/etc/ssh_host_*_key # When no longer useful. +rm -f bootconfig/boot/liveconfig.xz # When no longer useful. +rm -f sortix.iso # When no longer useful. +# And erase any media made from sortix.iso when no longer useful. +ssh root@example.org # When the system is running. +.Ed +.Ss SSH Back From Live Environment +To customize the live environment of a release so its root user can ssh back to +your user, where the local hostname is +.Sy example.com +(the address to which the new installation will be connecting): +.Bd -literal +tix-iso-liveconfig --root-ssh-keygen liveconfig +ssh-keyscan -H example.com > liveconfig/root/.ssh/known_hosts +cat liveconfig/root/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys +tix-iso-bootconfig --liveconfig=liveconfig --enable-sshd bootconfig +tix-iso-add sortix.iso bootconfig +rm -f output-directory/root/.ssh/id_rsa # When no longer useful. +rm -f bootconfig/boot/liveconfig.xz # When no longer useful. +rm -f sortix.iso # When no longer useful. +# And erase any media made from sortix.iso when no longer useful. +.Ed .Sh SEE ALSO +.Xr ssh-keygen 1 , .Xr xorriso 1 , .Xr hostname 5 , .Xr kblayout 5 , +.Xr ssh_config 5 , +.Xr sshd_config 5 , .Xr videomode 5 , .Xr release-iso-modification 7 , +.Xr sshd 8 , .Xr tix-iso-add 8 , .Xr tix-iso-bootconfig 8