dropbear.init 5.8 KB

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