506f7dac654572b6cfc6e6a7f8bf607f1e09e423
[openwrt/openwrt.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 append_ports()
64 {
65 local ipaddrs="$1"
66 local port="$2"
67
68 [ -z "$ipaddrs" ] && {
69 procd_append_param command -p "$port"
70 return
71 }
72
73 for addr in $ipaddrs; do
74 procd_append_param command -p "$addr:$port"
75 done
76 }
77
78 validate_section_dropbear()
79 {
80 uci_load_validate dropbear dropbear "$1" "$2" \
81 'PasswordAuth:bool:1' \
82 'enable:bool:1' \
83 'Interface:string' \
84 'GatewayPorts:bool:0' \
85 'RootPasswordAuth:bool:1' \
86 'RootLogin:bool:1' \
87 'rsakeyfile:file' \
88 'keyfile:list(file)' \
89 'BannerFile:file' \
90 'Port:list(port):22' \
91 'SSHKeepAlive:uinteger:300' \
92 'IdleTimeout:uinteger:0' \
93 'MaxAuthTries:uinteger:3' \
94 'RecvWindowSize:uinteger:0' \
95 'mdns:bool:1'
96 }
97
98 dropbear_instance()
99 {
100 local ipaddrs
101
102 [ "$2" = 0 ] || {
103 echo "validation failed"
104 return 1
105 }
106
107 [ -n "${Interface}" ] && {
108 [ -n "${BOOT}" ] && return 0
109
110 network_get_ipaddrs_all ipaddrs "${Interface}" || {
111 echo "interface ${Interface} has no physdev or physdev has no suitable ip"
112 return 1
113 }
114 }
115
116 [ "${enable}" = "0" ] && return 1
117 PIDCOUNT="$(( ${PIDCOUNT} + 1))"
118 local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid"
119
120 procd_open_instance
121 procd_set_param command "$PROG" -F -P "$pid_file"
122 [ "${PasswordAuth}" -eq 0 ] && procd_append_param command -s
123 [ "${GatewayPorts}" -eq 1 ] && procd_append_param command -a
124 [ "${RootPasswordAuth}" -eq 0 ] && procd_append_param command -g
125 [ "${RootLogin}" -eq 0 ] && procd_append_param command -w
126 if [ -n "${rsakeyfile}" ]; then
127 logger -t ${NAME} -p daemon.warn \
128 "option 'rsakeyfile' is considered to be deprecated and" \
129 "will be removed in future releases, use 'keyfile' instead"
130 hk_config 'rsakeyfile' "${rsakeyfile}"
131 fi
132 config_list_foreach "$1" "keyfile" hk_config__keyfile
133 [ -n "${BannerFile}" ] && procd_append_param command -b "${BannerFile}"
134 append_ports "${ipaddrs}" "${Port}"
135 [ "${IdleTimeout}" -ne 0 ] && procd_append_param command -I "${IdleTimeout}"
136 [ "${SSHKeepAlive}" -ne 0 ] && procd_append_param command -K "${SSHKeepAlive}"
137 [ "${MaxAuthTries}" -ne 0 ] && procd_append_param command -T "${MaxAuthTries}"
138 [ "${RecvWindowSize}" -gt 0 -a "${RecvWindowSize}" -le 1048576 ] && \
139 procd_append_param command -W "${RecvWindowSize}"
140 [ "${mdns}" -ne 0 ] && procd_add_mdns "ssh" "tcp" "$Port" "daemon=dropbear"
141 procd_set_param respawn
142 procd_close_instance
143 }
144
145 keygen()
146 {
147 for keytype in rsa; do
148 # check for keys
149 key=dropbear/dropbear_${keytype}_host_key
150 [ -f /tmp/$key -o -s /etc/$key ] || {
151 # generate missing keys
152 mkdir -p /tmp/dropbear
153 [ -x /usr/bin/dropbearkey ] && {
154 /usr/bin/dropbearkey -t $keytype -f /tmp/$key 2>&- >&- && exec /etc/rc.common "$initscript" start
155 } &
156 exit 0
157 }
158 done
159
160 lock /tmp/.switch2jffs
161 mkdir -p /etc/dropbear
162 mv /tmp/dropbear/dropbear_* /etc/dropbear/
163 lock -u /tmp/.switch2jffs
164 chown root /etc/dropbear
165 chmod 0700 /etc/dropbear
166 }
167
168 load_interfaces()
169 {
170 config_get interface "$1" Interface
171 config_get enable "$1" enable 1
172
173 [ "${enable}" = "1" ] && interfaces=" ${interface} ${interfaces}"
174 }
175
176 boot()
177 {
178 BOOT=1
179 start "$@"
180 }
181
182 start_service()
183 {
184 [ -s /etc/dropbear/dropbear_rsa_host_key ] || keygen
185
186 . /lib/functions.sh
187 . /lib/functions/network.sh
188
189 config_load "${NAME}"
190 config_foreach validate_section_dropbear dropbear dropbear_instance
191 }
192
193 service_triggers()
194 {
195 local interfaces
196
197 procd_add_config_trigger "config.change" "dropbear" /etc/init.d/dropbear reload
198
199 config_load "${NAME}"
200 config_foreach load_interfaces dropbear
201
202 [ -n "${interfaces}" ] && {
203 for n in $interfaces ; do
204 procd_add_interface_trigger "interface.*" $n /etc/init.d/dropbear reload
205 done
206 }
207
208 procd_add_validation validate_section_dropbear
209 }
210
211 shutdown() {
212 # close all open connections
213 killall dropbear
214 }
215
216 killclients()
217 {
218 local ignore=''
219 local server
220 local pid
221
222 # if this script is run from inside a client session, then ignore that session
223 pid="$$"
224 while [ "${pid}" -ne 0 ]
225 do
226 # get parent process id
227 pid=`cut -d ' ' -f 4 "/proc/${pid}/stat"`
228 [ "${pid}" -eq 0 ] && break
229
230 # check if client connection
231 grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" && {
232 append ignore "${pid}"
233 break
234 }
235 done
236
237 # get all server pids that should be ignored
238 for server in `cat /var/run/${NAME}.*.pid`
239 do
240 append ignore "${server}"
241 done
242
243 # get all running pids and kill client connections
244 local skip
245 for pid in `pidof "${NAME}"`
246 do
247 # check if correct program, otherwise process next pid
248 grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" || {
249 continue
250 }
251
252 # check if pid should be ignored (servers, ourself)
253 skip=0
254 for server in ${ignore}
255 do
256 if [ "${pid}" = "${server}" ]
257 then
258 skip=1
259 break
260 fi
261 done
262 [ "${skip}" -ne 0 ] && continue
263
264 # kill process
265 echo "${initscript}: Killing ${pid}..."
266 kill -KILL ${pid}
267 done
268 }