Upstream refresh for v1.5.0-rc1 : Upstream 19.07 : 4fb6b8c553f692eeb5bcb203e0f8ee8df0...
[librecmc/librecmc.git] / package / network / services / dropbear / files / dropbear.init
1 #!/bin/sh /etc/rc.common
2 # Copyright (C) 2006-2010 OpenWrt.org
3 # Copyright (C) 2006 Carlos Sobrinho
4
5 START=19
6 STOP=50
7
8 USE_PROCD=1
9 PROG=/usr/sbin/dropbear
10 NAME=dropbear
11 PIDCOUNT=0
12 EXTRA_COMMANDS="killclients"
13 EXTRA_HELP="    killclients Kill ${NAME} processes except servers and yourself"
14
15 _dropbearkey()
16 {
17         /usr/bin/dropbearkey "$@" 0<&- 1>&- 2>&-
18 }
19
20 # $1 - host key file name
21 hk_verify()
22 {
23         [ -f "$1" ] || return 1
24         [ -s "$1" ] || return 2
25         _dropbearkey -y -f "$1" || return 3
26         return 0
27 }
28
29 # $1 - hk_verify() return code
30 hk_errmsg()
31 {
32         case "$1" in
33         0) ;;
34         1) echo "file does not exist" ;;
35         2) echo "file has zero length" ;;
36         3) echo "file is not valid host key or not supported" ;;
37         *) echo "unknown error" ;;
38         esac
39 }
40
41 # $1 - config option
42 # $2 - host key file name
43 hk_config()
44 {
45         local x m
46         hk_verify "$2"; x=$?
47         case "$x" in
48         0)      procd_append_param command -r "$2"
49                 ;;
50         *)      m=$(hk_errmsg "$x")
51                 logger -t "${NAME}" -p daemon.warn \
52                   "option '$1', value '$2': $m, skipping"
53                 ;;
54         esac
55 }
56
57 # $1 - host key file name
58 hk_config__keyfile()
59 {
60         hk_config 'keyfile' "$1"
61 }
62
63 hk_generate_as_needed()
64 {
65         local kdir kgen ktype tdir kcount tfile
66         kdir='/etc/dropbear'
67
68         kgen=''
69         for ktype in ecdsa rsa; do
70                 hk_verify "${kdir}/dropbear_${ktype}_host_key" && continue
71
72                 kgen="${kgen} ${ktype}"
73         done
74
75         [ -z "${kgen}" ] && return
76
77         tdir=$(mktemp -d); chmod 0700 "${tdir}"
78
79         kcount=0
80         for ktype in ${kgen}; do
81                 tfile="${tdir}/dropbear_${ktype}_host_key"
82
83                 if ! _dropbearkey -t ${ktype} -f "${tfile}"; then
84                         # unsupported key type
85                         rm -f "${tfile}"
86                         continue
87                 fi
88
89                 kcount=$((kcount+1))
90         done
91
92         if [ ${kcount} -ne 0 ]; then
93                 mkdir -p "${kdir}"; chmod 0700 "${kdir}"; chown root "${kdir}"
94                 mv -f "${tdir}/"* "${kdir}/"
95         fi
96
97         rm -rf "${tdir}"
98 }
99
100 append_ports()
101 {
102         local ipaddrs="$1"
103         local port="$2"
104
105         [ -z "$ipaddrs" ] && {
106                 procd_append_param command -p "$port"
107                 return
108         }
109
110         for addr in $ipaddrs; do
111                 procd_append_param command -p "$addr:$port"
112         done
113 }
114
115 validate_section_dropbear()
116 {
117         uci_load_validate dropbear dropbear "$1" "$2" \
118                 'PasswordAuth:bool:1' \
119                 'enable:bool:1' \
120                 'Interface:string' \
121                 'GatewayPorts:bool:0' \
122                 'RootPasswordAuth:bool:1' \
123                 'RootLogin:bool:1' \
124                 'rsakeyfile:file' \
125                 'keyfile:list(file)' \
126                 'BannerFile:file' \
127                 'Port:port:22' \
128                 'SSHKeepAlive:uinteger:300' \
129                 'IdleTimeout:uinteger:0' \
130                 'MaxAuthTries:uinteger:3' \
131                 'RecvWindowSize:uinteger:0' \
132                 'mdns:bool:1'
133 }
134
135 dropbear_instance()
136 {
137         local ipaddrs
138
139         [ "$2" = 0 ] || {
140                 echo "validation failed"
141                 return 1
142         }
143
144         [ -n "${Interface}" ] && {
145                 [ -n "${BOOT}" ] && return 0
146
147                 network_get_ipaddrs_all ipaddrs "${Interface}" || {
148                         echo "interface ${Interface} has no physdev or physdev has no suitable ip"
149                         return 1
150                 }
151         }
152
153         [ "${enable}" = "0" ] && return 1
154         PIDCOUNT="$(( ${PIDCOUNT} + 1))"
155         local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid"
156
157         procd_open_instance
158         procd_set_param command "$PROG" -F -P "$pid_file"
159         [ "${PasswordAuth}" -eq 0 ] && procd_append_param command -s
160         [ "${GatewayPorts}" -eq 1 ] && procd_append_param command -a
161         [ "${RootPasswordAuth}" -eq 0 ] && procd_append_param command -g
162         [ "${RootLogin}" -eq 0 ] && procd_append_param command -w
163         if [ -n "${rsakeyfile}" ]; then
164                 logger -t ${NAME} -p daemon.warn \
165                         "option 'rsakeyfile' is considered to be deprecated and" \
166                         "will be removed in future releases, use 'keyfile' instead"
167                 hk_config 'rsakeyfile' "${rsakeyfile}"
168         fi
169         config_list_foreach "$1" "keyfile" hk_config__keyfile
170         [ -n "${BannerFile}" ] && procd_append_param command -b "${BannerFile}"
171         append_ports "${ipaddrs}" "${Port}"
172         [ "${IdleTimeout}" -ne 0 ] && procd_append_param command -I "${IdleTimeout}"
173         [ "${SSHKeepAlive}" -ne 0 ] && procd_append_param command -K "${SSHKeepAlive}"
174         [ "${MaxAuthTries}" -ne 0 ] && procd_append_param command -T "${MaxAuthTries}"
175         [ "${RecvWindowSize}" -gt 0 -a "${RecvWindowSize}" -le 1048576 ] && \
176                 procd_append_param command -W "${RecvWindowSize}"
177         [ "${mdns}" -ne 0 ] && procd_add_mdns "ssh" "tcp" "$Port" "daemon=dropbear"
178         procd_set_param respawn
179         procd_close_instance
180 }
181
182 load_interfaces()
183 {
184         config_get interface "$1" Interface
185         config_get enable "$1" enable 1
186
187         [ "${enable}" = "1" ] && interfaces=" ${interface} ${interfaces}"
188 }
189
190 boot()
191 {
192         BOOT=1
193         start "$@"
194 }
195
196 start_service()
197 {
198         hk_generate_as_needed
199
200         . /lib/functions.sh
201         . /lib/functions/network.sh
202
203         config_load "${NAME}"
204         config_foreach validate_section_dropbear dropbear dropbear_instance
205 }
206
207 service_triggers()
208 {
209         local interfaces
210
211         procd_add_config_trigger "config.change" "dropbear" /etc/init.d/dropbear reload
212
213         config_load "${NAME}"
214         config_foreach load_interfaces dropbear
215
216         [ -n "${interfaces}" ] && {
217                 for n in $interfaces ; do
218                         procd_add_interface_trigger "interface.*" $n /etc/init.d/dropbear reload
219                 done
220         }
221
222         procd_add_validation validate_section_dropbear
223 }
224
225 shutdown() {
226         # close all open connections
227         killall dropbear
228 }
229
230 killclients()
231 {
232         local ignore=''
233         local server
234         local pid
235
236         # if this script is run from inside a client session, then ignore that session
237         pid="$$"
238         while [ "${pid}" -ne 0 ]
239          do
240                 # get parent process id
241                 pid=`cut -d ' ' -f 4 "/proc/${pid}/stat"`
242                 [ "${pid}" -eq 0 ] && break
243
244                 # check if client connection
245                 grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" && {
246                         append ignore "${pid}"
247                         break
248                 }
249         done
250
251         # get all server pids that should be ignored
252         for server in `cat /var/run/${NAME}.*.pid`
253          do
254                 append ignore "${server}"
255         done
256
257         # get all running pids and kill client connections
258         local skip
259         for pid in `pidof "${NAME}"`
260          do
261                 # check if correct program, otherwise process next pid
262                 grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" || {
263                         continue
264                 }
265
266                 # check if pid should be ignored (servers, ourself)
267                 skip=0
268                 for server in ${ignore}
269                  do
270                         if [ "${pid}" = "${server}" ]
271                          then
272                                 skip=1
273                                 break
274                         fi
275                 done
276                 [ "${skip}" -ne 0 ] && continue
277
278                 # kill process
279                 echo "${initscript}: Killing ${pid}..."
280                 kill -KILL ${pid}
281         done
282 }