-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathsd-openssh
More file actions
187 lines (162 loc) · 7.36 KB
/
sd-openssh
File metadata and controls
187 lines (162 loc) · 7.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/bin/bash
build() {
if ! pacman -Qi openssh >/dev/null 2>&1; then
error "Package openssh not installed"
return 1
fi
declare -F add_busybox >/dev/null || . /usr/lib/initcpio/functions.d/systemd-extras
add_busybox || return $?
local keydir="${SD_OPENSSH_KEYDIR:-/etc/ssh}"
if [[ ! -d "$keydir" ]]; then
error "Host key directory '$keydir' does not exist (or not a directory)"
exit 1
fi
local key_type host_key openssh_opts
local -a load_credential_stmts
for key_type in ed25519 rsa ecdsa; do
host_key="ssh_host_${key_type}_key"
if [[ -r "${keydir}/${host_key}.enc" ]]; then
load_credential_stmts+=( "LoadCredentialEncrypted=${host_key}" )
openssh_opts+=" -h \${CREDENTIALS_DIRECTORY}/${host_key}"
add_file "${keydir}/${host_key}.enc" "/etc/credstore.encrypted/${host_key}"
fi
done
if [[ "${#load_credential_stmts[@]}" == "0" ]]; then
for key_type in ed25519 rsa ecdsa; do
host_key="ssh_host_${key_type}_key"
if [[ -r "${keydir}/${host_key}" ]]; then
load_credential_stmts+=( "LoadCredential=${host_key}" )
openssh_opts+=" -h \${CREDENTIALS_DIRECTORY}/${host_key}"
add_file "${keydir}/${host_key}" "/etc/credstore/${host_key}"
fi
done
if [[ -z "$SD_OPENSSH_KEYDIR" && "${#load_credential_stmts[@]}" != "0" ]]; then
warning "Reusing the SSH host keys from the regular operating environment poses a security risk."
warning "See https://github.com/wolegis/mkinitcpio-systemd-extras/wiki/OpenSSH-SSH-server for details."
fi
fi
if [[ "${#load_credential_stmts[@]}" == "0" ]]; then
error "Missing SSH host keys"
return 1
fi
add_binary sshd
add_binary /usr/lib/ssh/sshd-session
add_binary /usr/lib/ssh/sshd-auth
if [[ -n "$SD_OPENSSH_CONFIG" ]]; then
if [[ ! -r "$SD_OPENSSH_CONFIG" ]]; then
error "OpenSSH configuration $SD_OPENSSH_CONFIG does not exist (or not readable)"
return 1
fi
local -r usepam_substitution='s/^([[:blank:]]*)UsePAM .*/\1UsePAM no/'
add_dir /etc/ssh
sed -E -e "$usepam_substitution" <"$SD_OPENSSH_CONFIG" >"$BUILDROOT/etc/ssh/sshd_config"
chmod 600 "$BUILDROOT/etc/ssh/sshd_config"
if [[ -d "${SD_OPENSSH_CONFIG}.d" ]]; then
add_dir /etc/ssh/sshd_config.d
local config_file
while read -r config_file; do
sed -E -e "$usepam_substitution" <"$config_file" >"$BUILDROOT/etc/ssh/sshd_config.d/${config_file##*/}"
chmod 600 "$BUILDROOT/etc/ssh/sshd_config.d/${config_file##*/}"
done < <(find "${SD_OPENSSH_CONFIG}.d" -mindepth 1 -maxdepth 1 -type f)
fi
else
local default_config=(
"PasswordAuthentication no"
"KbdInteractiveAuthentication no"
"UsePAM no"
"PrintMotd no"
"AuthorizedKeysFile .ssh/authorized_keys"
)
add_dir /etc/ssh
printf "%s\n" "${default_config[@]}" > "$BUILDROOT/etc/ssh/sshd_config"
fi
grep '^nobody:' /etc/passwd >>"$BUILDROOT/etc/passwd"
grep '^nobody:' /etc/shadow >>"$BUILDROOT/etc/shadow"
grep '^nobody:' /etc/group >>"$BUILDROOT/etc/group"
grep '^nobody:' /etc/gshadow >>"$BUILDROOT/etc/gshadow"
add_dir /usr/share/empty.sshd 711
local socket_unit=(
"[Unit]"
"Description=OpenSSH server socket"
"Documentation=https://man.archlinux.org/man/sshd.8"
"Requires=systemd-networkd.service"
"After=systemd-networkd.service"
"DefaultDependencies=no"
""
"[Socket]"
"ListenStream=%i"
"Accept=true"
"KeepAlive=true"
"IPTOS=low-delay"
""
"[Install]"
"WantedBy=sysinit.target"
)
printf "%s\n" "${socket_unit[@]}" > "$BUILDROOT/usr/lib/systemd/system/sshd@.socket"
local service_unit=(
"[Unit]"
"Description=OpenSSH server (socket activated)"
"Documentation=https://man.archlinux.org/man/sshd.8"
"DefaultDependencies=no"
"CollectMode=inactive-or-failed"
""
"[Service]"
"Type=exec"
"StandardInput=socket"
"StandardOutput=socket"
"ExecStart=/usr/bin/sshd -i${SD_OPENSSH_COMMAND:+ -o ForceCommand='${SD_OPENSSH_COMMAND}'}${openssh_opts}"
"${load_credential_stmts[@]}"
)
printf "%s\n" "${service_unit[@]}" > "$BUILDROOT/usr/lib/systemd/system/sshd@.service"
# enable openssh listening on TCP port $SD_OPENSSH_PORT (if set to legal port number)
SD_OPENSSH_PORT="${SD_OPENSSH_PORT:-22}"
if (( SD_OPENSSH_PORT < 1 || SD_OPENSSH_PORT > 65535 )); then
error "Illegal value SD_OPENSSH_PORT=$SD_OPENSSH_PORT"
return 1
fi
add_symlink "/etc/systemd/system/sysinit.target.wants/sshd@$SD_OPENSSH_PORT.socket" /usr/lib/systemd/system/sshd@.socket
SD_OPENSSH_AUTHORIZED_KEYS="${SD_OPENSSH_AUTHORIZED_KEYS:-/root/.ssh/authorized_keys}"
if [[ -r "$SD_OPENSSH_AUTHORIZED_KEYS" ]]; then
add_file "$SD_OPENSSH_AUTHORIZED_KEYS" /root/.ssh/authorized_keys 600
chmod 700 "$BUILDROOT/root/.ssh"
else
error "Keys file '$SD_OPENSSH_AUTHORIZED_KEYS' does not exist (or not readable)"
return 1
fi
}
help() {
cat <<__EOF_HELP__
This hook enables OpenSSH server during initramfs phase. It is only applicable
for a systemd based intramfs phase, i.e. hook 'systemd' must be given in the
HOOKS array in mkinitcpio.conf.
See https://github.com/wolegis/mkinitcpio-systemd-extras/wiki/OpenSSH-server
for details.
The hook copies all required files and binaries to the initramfs image and
enables listening TCP port 22 (or some other).
Host keys are copied from \$SD_OPENSSH_KEYDIR (default /etc/ssh). Host keys
encrypted with systemd-creds (recognized by the suffix '.enc') are preferred.
By default OpenSSH presents the busybox shell after successful login. This
behavior can be overruled in two ways:
SD_OPENSSH_COMMAND defines a shell command. The string is appended to 'sh -c',
i.e. it may contain blanks, quotes and all kinds of special characters that are
interpreted by the shell. Example: To allow to unlock LUKS encrypted volumes
from remote (but nothing else, especially no shell access) set:
SD_OPENSSH_COMMAND="systemd-tty-ask-password-agent --query --watch"
Use option 'command=...' for the entry in /root/.ssh/authorized_keys that
contains the public key used to establish the SSH session. In the likely case
that this option is only desired for the 'authorized_keys' in the initramfs you
can set SD_OPENSSH_AUTHORIZED_KEYS to specify a special version of this file
to be copied into the initramfs.
Example: To allow to unlock LUKS encrypted volumes from remote specify:
command="systemd-tty-ask-password-agent --query" ssh-ed25519 AAAAC3N....
SD_OPENSSH_COMMAND takes precedence.
Set SD_OPENSSH_PORT to specify a port other than 22.
Set SD_OPENSSH_CONFIG to specify a configuration file to be used by the OpenSSH
server during initramfs phase. If present directory \$SD_OPENSSH_CONFIG.d is
automatically taken into account. If not specified a minimal default
configuration is used.
Set SD_OPENSSH_AUTHORIZED_KEYS to specify a keys file other than
/root/.ssh/authorized_keys.
If required the above mentioned variables must be set in /etc/mkinitcpio.conf.
__EOF_HELP__
}