File jeos-firstboot-1.5.3.obscpio of Package jeos-firstboot
07070100000000000081A400000000000000000000000166FC020700000421000000000000000000000000000000000000001D00000000jeos-firstboot-1.5.3/LICENSECopyright (c) 2015-2022 SUSE LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
07070100000001000081A400000000000000000000000166FC0207000010F1000000000000000000000000000000000000001F00000000jeos-firstboot-1.5.3/README.md# jeos-firstboot
## Description
jeos-firstboot allows initial configuration and adjustments of a Linux system using text based dialogs.
It is a lightweight and customisable firstboot wizard that allows to set basic system settings during and after the first boot of an image. Including showing the license and prompt for language, keyboard, timezone, root passsword and network configuration..
This is mainly developed for openSUSE and SUSE Linux Enterprise Server JeOS images. For more information visit the [JeOS wiki](https://en.opensuse.org/Portal:JeOS).
## Installation
The RPM package is developed in openSUSE OBS [devel package](https://build.opensuse.org/package/show/devel:openSUSE:Factory/jeos-firstboot)
You can also get binaries RPM for openSUSE flavours at [package download](https://software.opensuse.org/package/jeos-firstboot)
<!-- USAGE EXAMPLES -->
## Usage
jeos-firstboot is used as two systemd services [jeos-firstboot.service](https://github.com/openSUSE/jeos-firstboot/blob/master/files/usr/lib/systemd/system/jeos-firstboot.service) and [jeos-firstboot-snapshot](https://github.com/openSUSE/jeos-firstboot/blob/master/files/usr/lib/systemd/system/jeos-firstboot-snapshot.service), for using it you need to copy the appropriate service files and enable it.
You can check the example in the RPM package for installation.
The service is controlled by a file, so after installing it you should be sure that your system is configured appropriately
```sh
# Enable jeos-firstboot
mkdir -p /var/lib/YaST2
touch /var/lib/YaST2/reconfig_system
systemctl mask systemd-firstboot.service
systemctl enable jeos-firstboot.service
```
Beside the service that runs on firstboot there is also a tool to change configuration in a running system, this will also be installed and available as `jeos-config`
jeos-config usage:
```
Usage: jeos-config [OPTION...] [CONFIG_NAME]
Configure system settings using an interactive dialog
-h shows this usage help
locale Show configuration for locale
keytable Show configuration for keyboard
timezone Show configuration for timezone
password Show configuration for password
network Show configuration for network
raspberrywifi Show configuration for raspberrywifi
```
Additional modules (like raspberrywifi) are shown if present.
If no parameter is given it shows a dialog for selection.
## Writing modules
jeos-firstboot can be extended using modules written in bash placed in `/usr/share/jeos-firstboot/modules/` or `/etc/jeos-firstboot/modules/`. Modules in `/etc/jeos-firstboot/modules/` will be preferred. If a link to `/dev/null` is encountered, the module is skipped.
The basename of the module file is its name. It is used as prefix of properties and hooks. It is also used as argument to jeos-config when calling the module directly.
### Properties
```sh
# Shown in jeos-config for module selection
yourmodule_title="Title of your module"
# Shown in jeos-config --help
yourmodule_description="Show an awesome dialog with a nice button"
# Priority of the module. Modules with higher priority are run later in jeos-firstboot and shown below in jeos-config.
# The default is 50.
yourmodule_priority=50
```
### Hooks
```sh
# Runs if called by jeos-firstboot, currently after systemd-firstboot is called
# (that should probably be changed)
yourmodule_systemd_firstboot() { }
# Runs if called by jeos-firstboot, after all systemd_firstboot hooks.
yourmodule_post() { }
# Runs if called by jeos-config
yourmodule_jeos_config() { }
# Runs at the end of jeos-firstboot just before exiting.
yourmodule_cleanup() { }
```
<!-- CONTRIBUTING -->
## Contributing
Any contributions you make are greatly appreciated.
Feel free to create any [Issues](https://github.com/openSUSE/jeos-firstboot/issues) and send pull requests to this repository.
<!-- LICENSE -->
## License
Distributed under the MIT License. See [LICENSE](https://github.com/openSUSE/jeos-firstboot/blob/master/LICENSE) for more information.
## Credentials
jeos-firstboot supports [systemd credentials](https://systemd.io/CREDENTIALS/)
to pre-configure systems. The wizard does not prompt for settings
defined by credentials.
* firstboot.keymap
* firstboot.license-agreed
* firstboot.locale
* firstboot.timezone
* passwd.plaintext-password.root
07070100000002000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000001B00000000jeos-firstboot-1.5.3/files07070100000003000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000001F00000000jeos-firstboot-1.5.3/files/usr07070100000004000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000002300000000jeos-firstboot-1.5.3/files/usr/lib07070100000005000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000002B00000000jeos-firstboot-1.5.3/files/usr/lib/systemd07070100000006000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000003200000000jeos-firstboot-1.5.3/files/usr/lib/systemd/system07070100000007000081A400000000000000000000000166FC02070000042A000000000000000000000000000000000000005200000000jeos-firstboot-1.5.3/files/usr/lib/systemd/system/jeos-firstboot-snapshot.service# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
[Unit]
Description=SUSE JeOS First Boot Wizard - create system snapshot
# Same as YaST2-Firstboot.service here
After=apparmor.service local-fs.target plymouth-start.service YaST2-Second-Stage.service
Conflicts=plymouth-start.service
Before=getty@tty1.service serial-getty@ttyS0.service serial-getty@ttyS1.service serial-getty@ttyS2.service
Before=display-manager.service
ConditionPathExists=/var/lib/YaST2/reconfig_system
# The configuration is already done - so this doesn't make much sense
#OnFailure=poweroff.target
# jeos-firstboot-snapshot starts after jeos-firstboot, time got synced
# and dbus became available
Wants=time-sync.target
Requires=jeos-firstboot.service dbus.service
After=jeos-firstboot.service time-sync.target
[Service]
Type=oneshot
RemainAfterExit=yes
# In Pre - if creation fails, don't do the configuration again
ExecStartPre=/usr/bin/rm -f /var/lib/YaST2/reconfig_system
ExecStart=/usr/sbin/jeos-firstboot-snapshot
[Install]
WantedBy=default.target
07070100000008000081A400000000000000000000000166FC0207000005CB000000000000000000000000000000000000004900000000jeos-firstboot-1.5.3/files/usr/lib/systemd/system/jeos-firstboot.service# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
[Unit]
Description=SUSE JeOS First Boot Wizard
# Same as YaST2-Firstboot.service here
After=apparmor.service local-fs.target plymouth-start.service YaST2-Second-Stage.service
Conflicts=plymouth-start.service
Before=getty@tty1.service serial-getty@hvc0.service serial-getty@ttyS0.service serial-getty@ttyS1.service serial-getty@ttyS2.service serial-getty@ttyAMA0.service
Before=display-manager.service
ConditionPathExists=/var/lib/YaST2/reconfig_system
OnFailure=poweroff.target
# jeos-firstboot starts before wicked and login though.
# It writes wicked configuration manually
Before=wicked.service systemd-user-sessions.service
# For NM it uses nmcli, so NM needs to be running
After=NetworkManager.service
# If cloud-init is used on the system, wait until it's done to be able
# to check whether it performed any configuration.
After=cloud-init-local.service
# jeos-firstboot-snapshot.service deletes the flag file, but starts after us
Wants=jeos-firstboot-snapshot.service
[Service]
Type=oneshot
Environment=TERM=linux
RemainAfterExit=yes
ExecStartPre=/bin/sh -c "/usr/bin/plymouth quit 2>/dev/null || :"
ExecStart=/usr/sbin/jeos-firstboot
StandardOutput=tty
StandardInput=tty
#StandardError=tty
# enable accessing global keyring to get data from eg. initrd
KeyringMode=shared
ImportCredential=passwd.plaintext-password.root
ImportCredential=firstboot.*
[Install]
WantedBy=default.target
07070100000009000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000002400000000jeos-firstboot-1.5.3/files/usr/sbin0707010000000A000081ED00000000000000000000000166FC020700000AB9000000000000000000000000000000000000003000000000jeos-firstboot-1.5.3/files/usr/sbin/jeos-config#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
jeos_prefix="$(realpath "$(dirname "${BASH_SOURCE[0]}")/../")"
# shellcheck source-path=SCRIPTDIR/../
. "${jeos_prefix}/share/jeos-firstboot/jeos-firstboot-functions"
# shellcheck source-path=SCRIPTDIR/../
. "${jeos_prefix}/share/jeos-firstboot/jeos-firstboot-dialogs"
# for testing we may run as non root
if [ -w /run ]; then
export TMPDIR=/run
# debugging
if [ -n "$FIRSTBOOT_DEBUG" ]; then
set -x
exec 2>/var/log/firstboot-debug
fi
else
dry=1
fi
if [ -n "$dry" ]; then
run() {
echo "$@"
}
else
run() {
"$@"
}
fi
cleanup() {
#call_module_hook cleanup
echo
}
trap cleanup EXIT
init_modules
# Get a list of all config modules
config_modules=()
for module in "${modules[@]}"; do
if module_has_hook "$module" "jeos_config"; then
config_modules+=("${module}")
fi
done
select_config()
{
local modules_order=("locale" $"Locale" "keytable" $"Keyboard Layout" "timezone" $"Timezone" "password" $"Password")
for module in "${config_modules[@]}"; do
modules_order+=("$module" "$(module_get_prop "${module}" "title" "${module}")")
done
d_with_result --no-tags --menu $"Select configuration module" 0 0 "$(menuheight ${#modules_order[@]})" "${modules_order[@]}" || exit 0
}
usage()
{
cat <<EOF
Usage: jeos-config [OPTION...] [CONFIG_NAME]
Configure system settings using an interactive dialog
-h shows this usage help
locale Show configuration for locale
keytable Show configuration for keyboard
timezone Show configuration for timezone
password Show configuration for password
EOF
for module in "${config_modules[@]}"; do
local fallbackdescription="$(printf $"Show configuration for %s" "${module}")"
printf "\t%-8s\t%s\n" "${module}" "$(module_get_prop "$module" "description" "$fallbackdescription")"
done
}
while getopts ":h" opt; do
case ${opt} in
h)
usage
exit 0
;;
\?)
echo "Invalid Option: -$OPTARG" 1>&2
usage
exit 1
;;
esac
done
if [ ${OPTIND} -gt $# ]; then
select_config
subcommand=${result}
else
subcommand=${!OPTIND}; shift
fi
case "$subcommand" in
locale)
list=() # Set by findlocales
if ! findlocales; then
d --msgbox $"No locales found" 0 0
elif [ "${#list[@]}" -eq 2 ]; then # Only a single entry
d --msgbox $"Locale set to ${list[0]}, no more locales available" 5 50
else
dialog_locale
apply_locale
fi
;;
keytable)
dialog_keytable
JEOS_LOCALE="$(get_current_locale)"
apply_locale_and_keytable
;;
timezone)
dialog_timezone
timedatectl set-timezone "$JEOS_TIMEZONE"
;;
password)
dialog_password
apply_password
;;
*)
call_module "$subcommand" "jeos_config" || echo "Unknown option '$subcommand'"
esac
0707010000000B000081ED00000000000000000000000166FC020700001DED000000000000000000000000000000000000003300000000jeos-firstboot-1.5.3/files/usr/sbin/jeos-firstboot#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
set -e
jeos_prefix="$(realpath "$(dirname "${BASH_SOURCE[0]}")/../")"
TEXTDOMAIN='jeos-firstboot'
# shellcheck source-path=SCRIPTDIR/../
. "${jeos_prefix}/share/jeos-firstboot/jeos-firstboot-functions"
# shellcheck source-path=SCRIPTDIR/../
. "${jeos_prefix}/share/jeos-firstboot/jeos-firstboot-dialogs"
# shellcheck source-path=SCRIPTDIR/../
. "${jeos_prefix}/share/jeos-firstboot/welcome-screen"
# Read the optional configuration file
# shellcheck source-path=SCRIPTDIR/../
[ -f "${jeos_prefix}/share/defaults/jeos-firstboot.conf" ] && . "${jeos_prefix}/share/defaults/jeos-firstboot.conf"
# shellcheck source=/dev/null
[ -f /etc/jeos-firstboot.conf ] && . /etc/jeos-firstboot.conf
# for testing we may run as non root
if [ -w /run ]; then
export TMPDIR=/run
# debugging
if [ -n "$FIRSTBOOT_DEBUG" ]; then
set -x
exec 2>/var/log/firstboot-debug
fi
else
dry=1
fi
if [ -e /run/cloud-init/enabled ] && ! grep -qw none /run/cloud-init/cloud-id; then
echo $"System configured with cloud-init, skipping jeos-firstboot"
exit 0
fi
if [ -n "$dry" ]; then
run() {
echo "$@"
}
else
run() {
"$@"
}
fi
cleanup() {
call_module_hook cleanup
# reenable systemd and kernel logs
# Try the race-free DBus method first
if ! run dbus-send --system --print-reply --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager.SetShowStatus string: &>/dev/null; then
# Fall back to using signals
run kill -s SIGRTMAX-10 1
fi
run setterm -msg on 2>/dev/null || true
echo
}
trap cleanup EXIT
# avoid kernel messages spamming our console
run setterm -msg off 2>/dev/null || true
# Avoid systemd messages spamming our console
# Try the race-free DBus method first
if ! run dbus-send --system --print-reply --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager.SetShowStatus string:off &>/dev/null; then
# Fall back to using signals
run kill -s SIGRTMAX-9 1
# sleep to avoid systemd bug, bsc#1119382
sleep 1
fi
init_modules
systemd_firstboot_args=()
# If the configuration is not loaded and we are in the first terminal
# instance, make sure that the variables are declared.
JEOS_LOCALE=${JEOS_LOCALE-}
JEOS_KEYTABLE=${JEOS_KEYTABLE-}
# If there is only a single locale on the system, don't use its
# default timezone but UTC instead.
use_utc_as_default_tz=0
if [ -z "$JEOS_LOCALE" ] && ! get_credential JEOS_LOCALE firstboot.locale; then
welcome_screen_with_console_switch
dialog_locale
# Same check as inside dialog_locale
if [ "${#list[@]}" -eq 2 ]; then
use_utc_as_default_tz=1
fi
fi
# Activate the locale selected
apply_locale
# also add to systemd-firstboot parameters
systemd_firstboot_args+=("--locale=$JEOS_LOCALE")
if [ -z "$JEOS_KEYTABLE" ] && ! get_credential JEOS_KEYTABLE firstboot.keymap; then
welcome_screen_with_console_switch
dialog_keytable
fi
# langset.sh needs locale to set keytable
apply_locale_and_keytable
# apply_locale(_and_keytable) also sets the TZ, override it here
if [ "$use_utc_as_default_tz" -eq "1" ]; then
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/UTC /etc/localtime
fi
[ -n "$JEOS_LOCALE" ] && language="${JEOS_LOCALE%%_*}" || language="en"
force_english_license=0
export LANG="$JEOS_LOCALE"
kmscon_available() {
# kmscon itself is installed
kmscon --help >/dev/null 2>&1 || return 1
# At least one monospace font is available
[ -n "$(fc-match "monospace" 2>/dev/null)" ] || return 1
return 0
}
fbiterm_available() {
# fbiterm itself is installed
fbiterm --help >/dev/null 2>&1 || return 1
# fbiterm comes with its own fallback font
return 0
}
if [[ "$(resolve_tty "$(tty)")" =~ /dev/tty[0-9]+ ]]; then
# Those languages can't be displayed in the console
declare -A start_kmscon
start_kmscon["cs"]=1
start_kmscon["ja"]=1
start_kmscon["zh"]=1
start_kmscon["ko"]=1
# Relay those settings to the nested instance
export JEOS_LOCALE JEOS_KEYTABLE
if [ -n "$JEOS_LOCALE" -a -n "${start_kmscon[${language}]+_}" ]; then
if kmscon_available; then
ret_file="$(mktemp)"
kmscon --silent --font-size 10 --palette vga --no-reset-env -l -- /bin/sh -c "$0; echo \$? > $ret_file; kill \$PPID"
exit $(cat "$ret_file"; rm -f "$ret_file")
elif fbiterm_available; then
exec fbiterm -- "$0"
else
# No kmscon or fbiterm, fall back to english
export LANG="en_US.UTF-8"
force_english_license=1
fi
fi
fi
if [ -z "$JEOS_EULA_ALREADY_AGREED" ] && ! get_credential JEOS_EULA_ALREADY_AGREED firstboot.license-agreed; then
welcome_screen_with_console_switch
# Find the location of the EULA
# An EULA in /etc takes precedence
EULA_FILE=/etc/YaST2/licenses/base/license.txt
[ -e "${EULA_FILE}" ] || EULA_FILE=/usr/share/licenses/product/base/license.txt
# Failsafe: If no license found, quit.
if ! [ -e "$EULA_FILE" ]; then
d --msgbox $"No license found - cannot continue" 6 40
exit 1
fi
if [ "$force_english_license" = "0" ]; then
for i in "${EULA_FILE%.txt}.${JEOS_LOCALE}.txt" \
"${EULA_FILE%.txt}.${JEOS_LOCALE%%.UTF-8}.txt" \
"${EULA_FILE%.txt}.${language}.txt"; do
if [ -e "$i" ]; then
EULA_FILE="$i"
break
fi
done
fi
while true; do
d --exit-label $"Continue" --textbox "$EULA_FILE" $dh_text 85
[ -e "${EULA_FILE%/*}/no-acceptance-needed" ] && break
d_styled --yesno $"Do you agree with the terms of the license?" 0 0 && break
d_styled --msgbox $"Can not continue without agreement" 6 40 || :
done
fi
if [ -z "$JEOS_TIMEZONE" ] && ! get_credential JEOS_TIMEZONE firstboot.timezone; then
welcome_screen_with_console_switch
dialog_timezone
fi
systemd_firstboot_args+=("--timezone=$JEOS_TIMEZONE")
# systemd-firstboot does not set the timezone if it exists, langset.sh created it
run rm -f /etc/localtime
run systemd-firstboot "${systemd_firstboot_args[@]}"
if [ -z "$JEOS_PASSWORD_ALREADY_SET" ] && ! get_credential password passwd.plaintext-password.root; then
welcome_screen_with_console_switch
dialog_password
fi
# Only show the registration prompt on commercial distros and if it's not
# globally disabled. Can't use /etc/products.d/ for that, even TW has a register target.
if [ -z "${CPE_NAME##cpe:*o:suse:*}" ] && [ -z "${JEOS_HIDE_SUSECONNECT}" ]; then
if [ -x /usr/bin/SUSEConnect ] && [ -x /usr/sbin/transactional-update ]; then
welcome_screen_with_console_switch
d --msgbox $"Please register this image using your existing SUSE entitlement.
As \"root\" use the following command:
transactional-update register -e company@example.com -r YOUR_CODE
to register the instance with SCC
Without registration this instance does not have access to updates and
security fixes." 0 0 || true
elif [ -x /usr/bin/SUSEConnect ]; then
welcome_screen_with_console_switch
d --msgbox $"Please register this image using your existing SUSE entitlement.
As \"root\" use the following command:
SUSEConnect -e company@example.com -r YOUR_CODE
to register the instance with SCC
Without registration this instance does not have access to updates and
security fixes." 0 0 || true
fi
fi
call_module_hook systemd_firstboot
d --infobox $"Applying firstboot settings ..." 3 40 || true
apply_password
# Look for EFI dir to see if the machine is booted in UEFI mode
EFI_SYSTAB="/sys/firmware/efi/systab"
# modprobe and efivars are not available everywhere, just ignore those cases
run modprobe efivars &>/dev/null || true
if ! [ -f "$EFI_SYSTAB" ]; then
if [ -f /etc/sysconfig/bootloader ]; then
run sed -i -e "s/LOADER_TYPE=.*/LOADER_TYPE=grub2/g" /etc/sysconfig/bootloader
fi
fi
call_module_hook post
0707010000000C000081ED00000000000000000000000166FC020700000212000000000000000000000000000000000000003C00000000jeos-firstboot-1.5.3/files/usr/sbin/jeos-firstboot-snapshot#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
set -euo pipefail
if ! mountpoint -q /.snapshots &>/dev/null; then
echo "Snapshots not enabled, skipping"
exit 0
fi
if mountpoint -q /etc; then
echo "/etc is not part of the snapshot, skipping"
exit 0
fi
if [ ! -e /.snapshots/2 ]; then
snapper -v create -d "After jeos-firstboot configuration" --userdata "important=yes"
fi
if [ -x /usr/lib/snapper/plugins/grub ]; then
/usr/lib/snapper/plugins/grub --refresh
fi
exit 0
0707010000000D000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000002500000000jeos-firstboot-1.5.3/files/usr/share0707010000000E000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000002E00000000jeos-firstboot-1.5.3/files/usr/share/defaults0707010000000F000081A400000000000000000000000166FC02070000058A000000000000000000000000000000000000004200000000jeos-firstboot-1.5.3/files/usr/share/defaults/jeos-firstboot.conf# Example configuration file for jeos-firstboot
# Valid system locale that will be used in JeOS. If empty/unset, a
# dialog box will ask for the system locale.
# JEOS_LOCALE='en_US'
# Keyboard layout used in the system and during jeos-firstboot.
# If empty/unset, a dialog box will ask for the keyboard layout.
# JEOS_KEYTABLE='en'
# Local timezone of the system.
# If empty/unset, a dialog box will ask for the local timezone.
# JEOS_TIMEZONE='UTC'
# If set to a nonempty value, the dialog box for setting the
# initial password for the root user will be skipped. In this case is
# expected that the root password was set by other means.
# JEOS_PASSWORD_ALREADY_SET='yes'
# If set to a nonempty value, the dialog box for accepting the EULA
# will be skipped. Use this option only when building images (ISO /
# PXE / OEM) that are part of another product and than can be used
# when this license was already accepted by other means.
# JEOS_EULA_ALREADY_AGREED='yes'
# If set to a nonempty value, the dialog box for showing the
# SUSEConnect help will not be displayed. By default this dialog is
# present when SUSEConnect is installed on SLE systems.
# JEOS_HIDE_SUSECONNECT='yes'
# If enabled, jeos-firstboot shows a welcome screen on all consoles and
# continues on the console where Ok was pressed. When disabled, only the
# active console (last "console=" on the kernel cmdline) is used.
JEOS_ASK_CONSOLE=1
07070100000010000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000003400000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot07070100000011000081A400000000000000000000000166FC020700000976000000000000000000000000000000000000004B00000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/jeos-firstboot-dialogs# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
menulist()
{
list=()
local line
while read line; do
list+=("$line" '')
done < <("$@"||true)
[ -n "$list" ]
}
dialog_locale()
{
default="en_US"
[ -f /etc/locale.conf ] && locale_lang="$(awk -F= '$1 == "LANG" { split($2,fs,"."); print fs[1]; exit }' /etc/locale.conf)"
[ -n "$locale_lang" ] && default="$locale_lang"
list=() # Set by findlocales
newlocale="$default"
if ! findlocales; then
d --msgbox $"No locales found" 0 0
elif [ "${#list[@]}" -eq 2 ]; then # Only a single entry
newlocale="${list[0]}"
else
d --default-item "$default" --menu $"Select system locale" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"
newlocale="${result}"
fi
JEOS_LOCALE="${newlocale}.UTF-8"
}
dialog_keytable()
{
default="us"
[ -f /etc/vconsole.conf ] && vconsole_keymap="$(awk -F= '$1 == "KEYMAP" { split($2,fs,"."); print fs[1]; exit }' /etc/vconsole.conf)"
[ -n "$vconsole_keymap" ] && default="$vconsole_keymap"
if findkeymaps \
&& d --default-item "$default" --menu $"Select keyboard layout" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"; then
if [ -n "$result" ]; then
JEOS_KEYTABLE="$result"
fi
else
d --msgbox $"Error setting keyboard" 5 26
fi
}
dialog_timezone()
{
default="$(readlink -f /etc/localtime)"
default="${default##/usr/share/zoneinfo/}"
# timedatectl doesn't work as dbus is not up yet
# menulist timedatectl --no-pager list-timezones
if menulist awk \
'BEGIN{print "UTC"; sort="sort"}/^#/{next;}{print $3|sort}END{close(sort)}' \
/usr/share/zoneinfo/zone.tab \
&& d --default-item "$default" --menu $"Select time zone" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"; then
if [ -n "$result" ]; then
JEOS_TIMEZONE="$result"
fi
else
d --msgbox $"Error setting timezone" 5 26
fi
}
dialog_password()
{
while true; do
d --insecure --passwordbox $"Enter root password" 0 0
password="$result"
d --insecure --passwordbox $"Confirm root password" 0 0
if [ "$password" != "$result" ]; then
d --msgbox $"Entered passwords don't match" 5 40
continue
fi
if [ -z "$password" ]; then
warn $"Warning: No root password set.
You cannot log in that way. A debug shell will be started on tty9 just this time. Use it to e.g. import your ssh key." || true
run systemctl start debug-shell.service
fi
break
done
}
# vim: syntax=sh
07070100000012000081A400000000000000000000000166FC020700001502000000000000000000000000000000000000004D00000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/jeos-firstboot-functions# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
if [ -e /etc/os-release ]; then
. /etc/os-release
else
. /usr/lib/os-release
fi
stty_size() {
set -- $(stty size); LINES=$1; COLUMNS=$2
# stty size can return zero when not ready or
# its a serial console
if [ "$COLUMNS" = "0" -o "$LINES" = "0" ]; then
LINES=24
COLUMNS=80
fi
let dh_menu=LINES-15
let dh_text=LINES-5
}
stty_size
# Make sure globs and regex are consistent everywhere.
LC_COLLATE=C.UTF-8
result=
list=
password=''
modules=()
_find_modules() {
local f
for f in /etc/jeos-firstboot/modules/* "${jeos_prefix?}/share/jeos-firstboot/modules"/*; do
if [ -L "$f" ] || [ -f "$f" ]; then
echo "${f##*/}" "$f"
fi
done
}
# Echos the value of the module variable or a fallback if unset.
# Usage: module_get_prop modulename varname defaultvalue
module_get_prop() {
local module="$1"
local varname="$2"
local default="${3-}"
local fullname="${module}_${varname}"
echo -n "${!fullname-"${default}"}"
}
init_modules() {
[ -z "$modules" ] || return 0
local module f _prio
local unordered_modules=()
while read -r module f; do
if [ -L "$f" ] && [ "$(readlink "$f")" = "/dev/null" ]; then
continue
fi
# shellcheck source=/dev/null
source "$f" || continue
unordered_modules+=("${module}")
done < <(_find_modules|sort -k 1,1 -u)
# Sort modules by priority
while read -r _prio module; do
modules+=("${module}")
done < <(for module in "${unordered_modules[@]}"; do
module_get_prop "$module" "priority" 50; echo " $module"
done | sort -n)
}
module_has_hook() {
local module="$1"
local module_func="$2"
module_function="${module}_${module_func}"
[ "$(type -t -- "${module_function}")" = "function" ]
}
call_module() {
local module="$1"
local module_func="$2"
module_function="${module}_${module_func}"
[ "$(type -t -- "${module_function}")" = "function" ] || return 1
"${module_function}" && true # To not trigger errexit
ret=$?
[ $ret -eq 0 ] || return $ret
}
call_module_hook() {
local hook="$1"
for module in "${modules[@]}"; do
call_module "${module}" "${hook}" || continue
done
return 0
}
# Run dialog with jeos-firstboot style options applied
d_styled() {
dialog --backtitle "$PRETTY_NAME" "$@"
}
# Run d_styled and save the output into $result
d_with_result() {
local retval=0
local stdoutfd
# Bash makes it a bit annoying to read the output of a different FD into a variable, it
# only supports reading stdout by itself. So redirect 3 to stdout and 1 to the real stdout.
exec {stdoutfd}>&1
result="$(d_styled --output-fd 3 "$@" 3>&1 1>&${stdoutfd})" || retval=$?
# Word splitting makes it necessary to use eval here.
eval "exec ${stdoutfd}>&-"
return "$retval"
}
# Run d_with_result but exit if cancelled (ESC or Cancel/No button pressed)
d_with_exit_on_fail() {
while true
do
retval=0
d_with_result "$@" || retval=$?
case $retval in
0)
return 0
;;
1|255)
d_styled --yesno $"Do you really want to quit?" 0 0 && exit 1
continue
;;
esac
done
}
# Run d_with_exit_on_fail, just with the previous unclear name for backwards compat
d() {
d_with_exit_on_fail "$@"
}
warn(){
d --title $"Warning" --msgbox "$1" 0 0
}
# Given the number of total item pairs, outputs the number of items to display at once
menuheight() {
local height=$(($1 / 2))
[ "$height" -le "$dh_menu" ] || height="$dh_menu"
echo $height
}
# localectl --no-pager list-keymaps does not list aliases (symlinks), but those are used
# by YaST/langset.sh, so we need to show them.
findkeymaps()
{
list=()
local line
while read line; do
list+=("${line%.map.gz}" '')
done < <(find /usr/share/kbd/keymaps -name '*.map.gz' -printf "%f\n" | sort -u)
[ -n "$list" ]
}
findlocales()
{
list=()
local l locale
# List only locales which are both in live-langset-data and glibc-locale(-base)
for l in /usr/share/langset/*; do
locale="${l#/usr/share/langset/}"
[ -d "/usr/lib/locale/${locale}.utf8" ] || continue
list+=("${locale}" '')
done
[ -n "$list" ]
}
get_current_locale()
{
cur_locale=$(awk -F= '$1 == "LANG" { print $2; exit }' /etc/locale.conf)
[ -z "$cur_locale" ] && cur_locale="en_US"
echo "${cur_locale}"
}
apply_locale()
{
if [ ! -z "$JEOS_LOCALE" ]; then
run langset.sh "$JEOS_LOCALE" || warn $"Setting the locale failed"
fi
}
apply_locale_and_keytable()
{
if [ ! -z "$JEOS_LOCALE" -a ! -z "$JEOS_KEYTABLE" ]; then
# Activate the selected keyboard layout
run langset.sh "$JEOS_LOCALE" "$JEOS_KEYTABLE" || warn $"Setting the keyboard layout failed"
fi
}
apply_password()
{
# FIXME: systemd-firstboot doesn't set password if shadow present
if [ -n "$password" ]; then
run echo "root:$password" | run /usr/sbin/chpasswd
fi
}
# Resolves /dev/console and /dev/tty0
resolve_tty() {
local tty="$1"
if [ "$tty" = "/dev/console" ]; then
tty=$(awk '{printf "/dev/%s", $NF}' /sys/class/tty/console/active)
fi
if [ "$tty" = "/dev/tty0" ]; then
printf "/dev/%s" "$(cat /sys/class/tty/tty0/active)"
else
echo -n "$tty"
fi
}
# get systemd credential
# https://systemd.io/CREDENTIALS/
get_credential()
{
local var="${1:?}"
local name="${2:?}"
[ -n "$CREDENTIALS_DIRECTORY" ] || return 1
[ -e "$CREDENTIALS_DIRECTORY/$name" ] || return 1
read -r "$var" < "$CREDENTIALS_DIRECTORY/$name" || [ -n "${!var}" ]
}
# vim: syntax=sh
07070100000013000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000003C00000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules07070100000014000081A400000000000000000000000166FC020700000292000000000000000000000000000000000000004400000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/network# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
# Returns the basename of the target of network.service,
# e.g. "wicked" or "NetworkManager"
current_network_service()
{
systemctl show -P Id network.service | cut -d. -f1
}
network_service="$(current_network_service)"
if [ -e "${jeos_prefix?}/share/jeos-firstboot/modules/network-modules/${network_service}" ]; then
# shellcheck source=SCRIPTDIR/network-modules/NetworkManager
. "${jeos_prefix?}/share/jeos-firstboot/modules/network-modules/${network_service}"
else
echo "No network configuration module for ${network_service} found" >&2
fi
07070100000015000041ED00000000000000000000000266FC020700000000000000000000000000000000000000000000004C00000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/network-modules07070100000016000081A400000000000000000000000166FC02070000030F000000000000000000000000000000000000005B00000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/network-modules/NetworkManager# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
network_jeos_config()
{
nmtui
}
network_systemd_firstboot()
{
if [ "$(nmcli networking connectivity)" = "none" ]; then
welcome_screen_with_console_switch
# Note: Dialog also flushes the input queue here. Without that,
# nmtui would react to what is typed before it shows up.
if d_styled --yesno $"No active network connection detected.\nDo you want to configure network connections?" 0 0; then
# nmtui (resp. libslang used by newt) uses /dev/tty,
# so setsid is required to set it to the current one.
setsid -wc nmtui
# setsid steals our tty connection, reopen it
if [ "$console" != "$(tty)" ]; then
exec 0<>"$console" 1>&0
fi
fi
fi
}
07070100000017000081A400000000000000000000000166FC0207000005DC000000000000000000000000000000000000005300000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/network-modules/wicked# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
do_wicked_autoconfig()
{
d --infobox $"Collecting network info ..." 3 33
shopt -s nullglob
for net_path in /sys/class/net/*; do
[ -d "$net_path" ] || continue # skip bonding_masters file
net_device=${net_path##*/}
[ "$net_device" = "lo" ] && continue
# Only devices having ID_NET_NAME.* attrs
# Ignore errors if udev not available
udevadm info -q property -p "$net_path" 2>/dev/null | grep -qs ID_NET_NAME || continue
# But don't touch WLAN interfaces
udevadm info -q property -p "$net_path" | grep -qs "DEVTYPE=wlan" && continue
unset IPADDR
eval $(wicked test dhcp4 "$net_device" 2>/dev/null | grep -E "^IPADDR=")
ip link set down "$net_device" # set link down after probe once done
# Create a configuration file for each interface that provides
# an IPADDR
if [ -n "$IPADDR" ]; then
printf "STARTMODE=auto\nBOOTPROTO=dhcp\n" \
> "/etc/sysconfig/network/ifcfg-$net_device"
fi
done
run sed -i -E 's/^DHCLIENT(6?)_SET_HOSTNAME=.*$/DHCLIENT\1_SET_HOSTNAME=yes/' /etc/sysconfig/network/dhcp
}
network_jeos_config()
{
if ! d_styled --yesno $"This will create a new network configuration from scratch,
all connections will be lost.\nDo you want to continue?" 7 50; then
return
fi
do_wicked_autoconfig
d --infobox $"Restarting network ..." 3 26 || true
systemctl restart network
}
network_systemd_firstboot()
{
do_wicked_autoconfig
}
07070100000018000081A400000000000000000000000166FC020700001397000000000000000000000000000000000000004000000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/otp# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# shellcheck shell=bash
otp_title=$"TOTP for Cockpit Login"
otp_description=$"Set up TOTP for cockpit user authentication"
otp_priority=70
_otp_do_config_for_user()
{
local user="$1"
# Generate secret in base32 (most common format).
# 20 bytes (-> 160 bits) result in 32 base32 characters (5 bits each) and
# 40 hex digits (4 bits each), so no padding is necessary.
local totp_secret
if ! totp_secret="$(dd if=/dev/urandom bs=1 count=20 status=none | base32)"; then
d_styled --title "$otp_title" --msgbox $"Failed to generate TOTP secret" 6 45 || :
return 1
fi
# oath-toolkit prefers to work with the hex format.
local totp_secret_hex
totp_secret_hex="$(base32 -d <<<"$totp_secret" | hexdump -ve '1/1 "%.2x"')"
local url="otpauth://totp/${user}?secret=${totp_secret}&issuer=$(uname -n)"
local msg="$(
printf $"Configuring time-based one-time password (TOTP) authentication for the user '%s'.\n\n" "$user"
printf $"Enroll with your desired TOTP application by scanning the QR code or entering the secret manually, then enter the generated 6 digit code below to confirm successful enrollment. "
printf $"Once confirmed, the Cockpit Web UI will ask for an OTP value on each login.\n\n"
printf $"TOTP Secret: %s" "${totp_secret}"
)"
local qrcode="$(qrencode -t UTF8i -m 1 <<<"$url")"
local msg_with_qr="$(printf "%s\n\n%s" "${msg}" "${qrcode}")"
while true; do
# If the screen is to small to fit the text and QR code at once,
# show only the text but add a button to show the QR code.
if [ "$LINES" -ge 37 ] && [ "$COLUMNS" -ge 24 ]; then
d_with_result --title "$otp_title" \
--cancel-label $"Skip" \
--no-nl-expand --no-collapse \
--mixedform "${msg_with_qr}" 37 60 1 \
$"OTP value:" 1 0 "" 1 15 45 0 0
else
d_with_result --title "$otp_title" \
--cancel-label $"Skip" \
--no-nl-expand --no-collapse \
--extra-button --extra-label $"QR Code" \
--mixedform "${msg}" 17 60 1 \
$"OTP value:" 1 0 "" 1 15 45 0 0
fi
local ret=$?
if [ "$ret" -eq 1 ]; then
# Skip button pressed
return 0
elif [ "$ret" -eq 3 ]; then
# QR code button pressed
d_styled --title "$otp_title" --no-nl-expand --no-collapse --msgbox "${qrcode}" 23 50 || :
continue
elif [ "$ret" -eq 255 ]; then
# ESC
if d_styled --yesno $"Do you really want to quit?" 0 0; then
exit 1
fi
continue
fi
readarray -t input <<<"$result"
if ! echo "${totp_secret_hex}" | oathtool --totp -d 6 -w 3 - "${input[0]}" >/dev/null; then
d_styled --title "$otp_title" --msgbox $"TOTP did not match" 6 45 || :
continue
fi
# Replace or create token in ~/.pam_oath.
# Use su to run as the target user (not root) if necessary.
local run_as_user=("su" "$user" "-c")
if [ "$(whoami)" = "${user}" ]; then
run_as_user=("sh" "-e" "-c")
fi
# Iterate all lines, find the matching entry to modify or append a new one.
# FIXME: Use file used by the PAM configuration?
if "${run_as_user[@]}" "set -e; umask 077; touch ~/.pam_oath_usersfile; awk -i inplace -f - ~/.pam_oath_usersfile" <<EOF; then
\$2 == "${user}" { \$1 = "HOTP/T30/6"; \$4="${totp_secret_hex}"; replaced=1 }
1 { print }
ENDFILE { if (!replaced) { print "HOTP/T30/6 ${user} - ${totp_secret_hex}" } }
EOF
break
fi
d_styled --title "$otp_title" --msgbox $"Failed to configure pam_oath" 6 45 || :
continue
done
}
# There might be multiple user accounts, ask if necessary.
# Accepts an option --msg-if-no-users to show a dialog if no users found.
_otp_do_config()
{
# If not root, only allow configuration for the calling user
if [ "$(id -u)" != "0" ]; then
_otp_do_config_for_user "$(whoami)"
return
fi
# Otherwise allow configuring it for all users
local users
# Technically this should read login.defs for the UID range but that's not trivial.
readarray -t users < <(getent passwd | awk -F: '$3 >= 1000 && $3 <= 60000 { print $1; print $5; }')
if [ "${#users[@]}" -eq 0 ]; then
# No user to configure found
if [ "${1-}" = "--msg-if-no-users" ]; then
d_styled --title "$otp_title" --msgbox $"No users for TOTP configuration found" 6 45 || :
fi
return 0
elif [ "${#users[@]}" -eq 2 ]; then
_otp_do_config_for_user "${users[0]}"
else
while true; do
d_with_result --title "$otp_title" \
--cancel-label $"Skip" \
--menu $"Select user to configure" 0 0 "$(menuheight ${#users[@]})" "${users[@]}"
local ret=$?
if [ "$ret" -eq 1 ]; then
# Skip button pressed
return 0
elif [ "$ret" -eq 255 ]; then
# ESC
if d_styled --yesno $"Do you really want to quit?" 0 0; then
exit 1
fi
continue
fi
_otp_do_config_for_user "$result"
done
fi
}
# Only show the configuration if necessary packages are installed.
if command -v oathtool >/dev/null && command -v qrencode >/dev/null; then
otp_systemd_firstboot()
{
_otp_do_config
}
otp_jeos_config()
{
_otp_do_config --msg-if-no-users
}
fi
07070100000019000081A400000000000000000000000166FC020700000F76000000000000000000000000000000000000004A00000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/raspberrywifi# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
config_wireless=false
# Raspberry pi Wi-fi functions
raspberrywifi_get_wlan_devices()
{
list=()
local line
while read line; do
list+=("${line}" '')
done < <(ls -d /sys/class/net/*/wireless | awk -F'/' '{ print $5 }')
[ -n "$list" ]
}
raspberrywifi_get_wlan_networks()
{
list=()
local line
while read line; do
if [ -n "${line}" ]; then
list+=("SSID=${line}" "${line}")
fi
done < <(ip link set "$wlan_device" up && iwlist "$wlan_device" scan|grep ESSID|cut -d':' -f2|cut -d'"' -f2|sort -u)
list+=("manual" "Enter SSID manually")
[ -n "${list[*]}" ]
}
raspberrywifi_wlan_error()
{
dialog --backtitle "$PRETTY_NAME" --title $"Error" --yesno $"$1\n\nDo you want to retry?" 0 0
}
is_raspberry()
{
grep -q Raspberry /proc/device-tree/model 2> /dev/null
}
# This function is called as part of jeos-config module hook implementation
# and also used to run the config dialogs for the module itself for
# jeos-firstboot modules extension.
raspberrywifi_jeos_config()
{
while true
do
if ! raspberrywifi_get_wlan_devices; then
if raspberrywifi_wlan_error $"Error listing wlan devices"; then
continue
fi
break
fi
if [ "${#list[@]}" -eq "2" ]; then
wlan_device="${list[0]}"
else
d --menu $"Select wireless card to configure" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"
wlan_device="${result}"
fi
if raspberrywifi_get_wlan_networks; then
d --no-tags --menu $"Select wireless network to connect" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"
wlan_network="$result"
else
if raspberrywifi_wlan_error $"Error listing wireless networks"; then
continue
fi
break
fi
if [ "$wlan_network" == "manual" ]; then
d --inputbox $"SSID of hidden network" 0 0
wlan_network="$result"
else
wlan_network="$(cut -d "=" -f2- <<< "$wlan_network")"
fi
list=($"WPA-PSK" '' $"WPA-EAP" '' $"Open" '')
d --menu $"Select authentication mode" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"
wlan_auth_mode="$result"
wlan_auth_mode_conf=
if [ "$wlan_auth_mode" = "WPA-EAP" ]; then
wlan_auth_mode_conf=eap
d --inputbox $"Username" 0 0
wlan_username="$result"
fi
if [ "$wlan_auth_mode" = "WPA-PSK" ]; then
wlan_auth_mode_conf=psk
fi
if [ "$wlan_auth_mode" = "Open" ]; then
wlan_auth_mode_conf=open
fi
if [ "$wlan_auth_mode" != "Open" ]; then
wlan_password=
d --insecure --passwordbox $"Network password" 0 0
wlan_password="$result"
fi
config_file=$(mktemp -qt 'firstboot-XXXXXX')
cat << EOF > "$config_file"
BOOTPROTO='dhcp'
STARTMODE='auto'
WIRELESS_AP_SCANMODE='1'
WIRELESS_AUTH_MODE='$wlan_auth_mode_conf'
WIRELESS_ESSID='$wlan_network'
WIRELESS_MODE='Managed'
EOF
if [ "$wlan_auth_mode" = "WPA-PSK" ]; then
echo "WIRELESS_WPA_PSK='$wlan_password'" >> "$config_file"
fi
if [ "$wlan_auth_mode" = "WPA-EAP" ]; then
echo "WIRELESS_WPA_IDENTITY='$wlan_username'" >> "$config_file"
echo "WIRELESS_WPA_PASSWORD='$wlan_password'" >> "$config_file"
echo "WIRELESS_EAP_AUTH='mschapv2'" >> "$config_file"
fi
run mv -f "$config_file" /etc/sysconfig/network/ifcfg-"$wlan_device"
d --infobox $"Connecting to wireless network ..." 3 38 || true
run ifdown "$wlan_device" &>/dev/null || true
if ! run ifup "$wlan_device" &>/dev/null; then
if dialog --backtitle "$PRETTY_NAME" --yesno $"Connection failed, do you wish to retry?" 0 0; then
continue
fi
fi
return 0
done
}
# This is called by jeos-firstboot for user
# interaction and access to the global systemd_firstboot_args array
raspberrywifi_systemd_firstboot()
{
if is_raspberry && stat -t /sys/class/net/*/wireless &> /dev/null; then
if dialog --backtitle "$PRETTY_NAME" --yesno $"Configure wireless network?" 0 0; then
config_wireless=true
fi
fi
[ "$config_wireless" = "true" ] || return 0
raspberrywifi_jeos_config
}
# vim: syntax=sh
0707010000001A000081A400000000000000000000000166FC02070000028B000000000000000000000000000000000000004700000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/ssh_enroll# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# shellcheck shell=bash
# Only show the configuration if the package is installed
if command -v ssh-pairing >/dev/null; then
ssh_enroll_jeos_config()
{
DIALOGOPTS="--backtitle \"$PRETTY_NAME\"" ssh-pairing || :
}
ssh_enroll_systemd_firstboot()
{
if d_styled --title $"SSH Key Enrollment" --yesno $"Do you want to enroll keys for SSH access?" 0 0; then
while ! DIALOGOPTS="--backtitle \"$PRETTY_NAME\"" ssh-pairing; do
if ! d_styled --title $"SSH Key Enrollment" --yesno $"No keys enrolled. Try again?" 0 0; then
return 0
fi
done
fi
}
fi
0707010000001B000081A400000000000000000000000166FC020700000CDC000000000000000000000000000000000000004800000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/status_mail# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# shellcheck shell=bash
# This also gets the password as value, so make sure not to leak that in the process list
status_mail_set_config_option()
{
key="$1"
value="$2"
# Create the config file in /etc if necessary
[ -e /etc/default/systemd-status-mail ] || touch /etc/default/systemd-status-mail
# Ensure the permissions are correct
chown systemd-status-mail:systemd-journal /etc/default/systemd-status-mail
chmod 600 /etc/default/systemd-status-mail
# Escape string for the file itself
value="${value@Q}"
# awk only supports " quoting, so \ and " need to be escaped
# Escape backslash for awk
value="${value//\\/\\\\}"
# Escape double quotes for awk
value="${value//\"/\\\"}"
# Replace existing assignment(s) or append at the end
awk -i inplace -F= -f - /etc/default/systemd-status-mail <<EOF
\$1 == "${key}" { \$0="${key}=${value}"; replaced=1 }
1 { print }
ENDFILE { if (!replaced) { print "${key}=${value}" } }
EOF
}
status_mail_do_config()
{
if [ -e /usr/etc/default/systemd-status-mail ]; then
. /usr/etc/default/systemd-status-mail
fi
if [ -e /etc/default/systemd-status-mail ]; then
. /etc/default/systemd-status-mail
fi
# Add a (fake) placeholder to demonstrate the smtps:// syntax
if [ -z "${RELAYHOST}" ]; then
RELAYHOST="smtps://server:port"
fi
# If a password is set, don't pass it to dialog as default value
# to not leak it to ps
pw_placeholder="${MAILX_AUTH_PASSWORD}"
if [ -n "${pw_placeholder}" ]; then
pw_placeholder="^^^"
fi
d --title $"E-Mail Notifications" \
--insecure \
--mixedform $"If desired, enter a mail address to receive system status notifications:" 8 0 10 \
$"Destination" 1 0 "$ADDRESS" 1 18 35 0 0 \
$"Sender address" 2 0 "$FROM" 2 18 35 0 0 \
$"SMTP configuration (optional):" 4 0 "" 4 35 0 0 2 \
$"Server" 5 0 "$RELAYHOST" 5 18 35 0 0 \
$"Authentication (if needed):" 6 0 "" 6 35 0 0 2 \
$"Username" 7 0 "$MAILX_AUTH_USER" 7 18 35 0 0 \
$"Password" 8 0 "$pw_placeholder" 8 18 35 0 1 \
$"Additional mailx options (if needed):" 9 0 "" 6 35 0 0 2 \
$"" 10 0 "$MAILX_OPTIONS" 10 0 52 0 0
readarray -t input <<<"$result"
# Undo the placeholder
if [ "${input[3]}" = "smtps://server:port" ]; then
input[3]=
fi
if [ "${input[0]}" != "${ADDRESS}" ]; then
status_mail_set_config_option ADDRESS "${input[0]}"
fi
if [ "${input[1]}" != "${FROM}" ]; then
status_mail_set_config_option FROM "${input[1]}"
fi
if [ "${input[2]}" != "${RELAYHOST}" ]; then
status_mail_set_config_option RELAYHOST "${input[2]}"
fi
if [ "${input[3]}" != "${MAILX_AUTH_USER}" ]; then
status_mail_set_config_option MAILX_AUTH_USER "${input[3]}"
fi
if [ "${input[4]}" != "${pw_placeholder}" ] && [ "${input[4]}" != "${MAILX_AUTH_PASSWORD}" ]; then
status_mail_set_config_option MAILX_AUTH_PASSWORD "${input[4]}"
fi
if [ "${input[5]}" != "${MAILX_OPTIONS}" ]; then
status_mail_set_config_option MAILX_OPTIONS "${input[5]}"
fi
# The config file impacts the generator, run it again.
systemctl daemon-reload
return 0
}
# Only show the configuration if the package is installed
if [ -e /usr/lib/systemd/system/systemd-status-mail@.service ]; then
status_mail_jeos_config()
{
status_mail_do_config
}
fi
0707010000001C000081A400000000000000000000000166FC020700000B04000000000000000000000000000000000000004100000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/modules/user# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# shellcheck shell=bash
user_title=$"User Creation"
user_description=$"Create an unprivileged user account"
user_priority=60
user_do_config()
{
local username=""
local fullname=""
local errmsg
# Loop until cancelled or successfully completed.
while true; do
local msg="$(
echo $"If desired, create an additional user account."
echo $"This is necessary for password-based SSH login and the Cockpit Web UI."
)"
d_with_result --title $"User Creation" \
--insecure \
--cancel-label $"Skip" \
--mixedform "${msg}" 9 0 5 \
$"Username" 1 0 "$username" 1 18 35 0 0 \
$"Full name" 2 0 "$fullname" 2 18 35 0 0 \
$"Password" 4 0 "" 4 18 35 0 1 \
$"Password (again)" 5 0 "" 5 18 35 0 1
local ret=$?
if [ "$ret" -eq 1 ]; then
# Skip button pressed
return 0
elif [ "$ret" -eq 255 ]; then
# ESC
if d_styled --yesno $"Do you really want to quit?" 0 0; then
exit 1
fi
continue
fi
readarray -t input <<<"$result"
# Collect input
username="${input[0]}"
fullname="${input[1]}"
# Make sure not to pass those as parameters to processes!
local password="${input[2]}"
local password_repeat="${input[3]}"
# Input handling and validation
if ! [[ "$username" =~ ^[a-z][-_a-z0-9]*$ ]]; then
d_styled --title $"User Creation" --msgbox $"Invalid username.\nMake sure it starts with a
lowercase letter and only contains -, _, digits and lowercase letters." 8 45
continue
fi
if [ -z "$password" ]; then
d_styled --title $"User Creation" --msgbox $"You have to enter a password" 8 45
continue
fi
if [ "$password" != "$password_repeat" ]; then
d_styled --title $"User Creation" --msgbox $"Passwords do not match." 8 45
continue
fi
# Password strength check
errmsg="$(printf "%s" "$password" | cracklib-check 2>&1)"
# For some reason cracklib-check includes the password in the message.
# https://github.com/cracklib/cracklib/pull/78 improves this, but it's too new.
errmsg="${errmsg/*: /}"
if [ "$errmsg" != "OK" ]; then
d_styled --title $"User Creation" --msgbox "$(printf $"cracklib-check failed: %s" "$errmsg")" 8 45
continue
fi
errmsg="$(useradd "$username" -c "$fullname" 2>&1)"
if [ "$?" -ne 0 ]; then
d_styled --title $"User Creation" --msgbox "$(printf $"useradd failed: %s" "$errmsg")" 8 45
continue
fi
# Set the requested password
if ! printf "%s:%s" "$username" "$password" | chpasswd; then
d_styled --title $"User Creation" --msgbox "$(printf $"chpasswd failed, leaving account locked: %s" "$errmsg")" 8 45
# Nothing we can do here, admin can fix this locally as root
fi
break
done
return 0
}
user_systemd_firstboot()
{
user_do_config
}
user_jeos_config()
{
user_do_config
}
0707010000001D000081A400000000000000000000000166FC020700001061000000000000000000000000000000000000004300000000jeos-firstboot-1.5.3/files/usr/share/jeos-firstboot/welcome-screen# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2015-2022 SUSE LLC
# shellcheck shell=bash
# Function to allow showing dialogs (or other stuff) on all consoles.
# At its core, it works by spawning processes with the given command on each
# console and waits for them to finish. If any exits with an exit status other
# than 254, the others are killed and the status returned.
#
# The inner workings are a bit complex, mostly to workaround bash not being
# able to wait for any process to exit, returning pid + status. It can either
# wait for multiple processes (PIDs) to exit or return the exit status of any
# process, but not the corresponding PID. There is no way to deal with
# background processes which exit before "wait" was called. In the case that
# there is no background process anymore, "wait" simply returns 0.
# As a workaround, the spawned background processes stay alive until killed
# explicitly and report their exit status and console through a FIFO.
# Directory the fifo for IPC is stored in. Managed by on_all_consoles.
fifodir=
# Console of the successful console_subproc
console=
# Internal helper used by on_all_consoles.
# This function is called for each console and basically runs "$@" on the
# console given in $1 and writes its exit status into the fifo.
# Bash doesn't forward signals to its child processes, instead that needs
# to be done explicitly. This is necessary for "dialog" to restore the tty.
# Note: When passing a function as parameter, make sure to not spawn
# subprocesses, i.e. use exec when possible.
console_subproc() {
local console="$1"
shift
"$@" <>"$console" >&0 &
pid=$!
trap 'set +e; kill $pid; wait $pid; dialog --clear <>"$console" >&0; exit 0' SIGTERM
ret=0
wait $pid || ret=$?
# Undo the trap to not kill the already dead process and also
# avoid waiting for the current process (sleep 1) before handling it.
trap - SIGTERM
echo "$ret $console" > "${fifodir}/fifo"
# Stay around until explicitly killed.
while :; do sleep 1; done
}
on_all_consoles() {
# Needed to tell apart errors and escape
export DIALOG_ERROR=254
# The linux fbcon uses this, most serial consoles should be fine too
export TERM=linux
# Create a FIFO for communicating the status
fifodir="$(mktemp -d)"
mkfifo "${fifodir}/fifo"
# For every active console, create a background process
local pids=()
local currenttty="$(resolve_tty "$(tty)")"
for console in $(cat /sys/class/tty/console/active); do
console="/dev/${console}"
[ -r "$console" ] || continue
# Skip consoles which aren't ready, e.g. return EIO.
# For those, dialog would switch to /dev/tty as fallback.
stty size <>"$console" &>/dev/null || continue
# Skip current tty
[ "$(resolve_tty "$console")" = "$currenttty" ] && continue
console_subproc "$console" "$@" &
pids+=($!)
done
# Also for the current tty
console_subproc "$currenttty" "$@" &
pids+=($!)
# Wait for either all processes to fail or one to succeed
local finished=0
while read status console < "${fifodir}/fifo"; do
((finished++)) || :
[ "$finished" -eq ${#pids[@]} ] && break
[ "$status" -eq 254 ] || break
done
# All done, kill remaining processes
kill "${pids[@]}" || :
wait "${pids[@]}" 2>/dev/null || :
rm -r "$fifodir"
fifodir=
return "$status"
}
# If JEOS_ASK_CONSOLE is not 0, show the "welcome" screen and switch to the
# console where it was acked on.
welcome_screen_with_console_switch() {
[ "${JEOS_ASK_CONSOLE-0}" -eq "0" ] && return 0
# Only ask once
[ "${JEOS_CONSOLE_ASKED-0}" -eq "1" ] && return 0
export JEOS_CONSOLE_ASKED=1
while true; do
ret=0
on_all_consoles dialog --backtitle "$PRETTY_NAME" --title $"JeOS Firstboot" --ok-label $"Start" --msgbox $"Welcome to $PRETTY_NAME"'!\nThe initial configuration takes just a few steps.' 0 0 || ret=$?
if [ "$ret" -eq 0 ]; then
break;
elif [ "$ret" -eq 254 ]; then
# Error? Just continue and fail later
return;
else
if on_all_consoles dialog --backtitle "$PRETTY_NAME" --yesno $"Do you really want to quit?" 0 0; then
exit 1
fi
fi
done
# Move stdio to the console
if [ "$console" != "$(tty)" ]; then
exec 0<>"$console" 1>&0
stty_size
fi
}
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!110 blocks