uhttpd.init 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #!/bin/sh /etc/rc.common
  2. # Copyright (C) 2010 Jo-Philipp Wich
  3. START=50
  4. USE_PROCD=1
  5. UHTTPD_BIN="/usr/sbin/uhttpd"
  6. PX5G_BIN="/usr/sbin/px5g"
  7. OPENSSL_BIN="/usr/bin/openssl"
  8. append_arg() {
  9. local cfg="$1"
  10. local var="$2"
  11. local opt="$3"
  12. local def="$4"
  13. local val
  14. config_get val "$cfg" "$var"
  15. [ -n "$val" -o -n "$def" ] && procd_append_param command "$opt" "${val:-$def}"
  16. }
  17. append_bool() {
  18. local cfg="$1"
  19. local var="$2"
  20. local opt="$3"
  21. local def="$4"
  22. local val
  23. config_get_bool val "$cfg" "$var" "$def"
  24. [ "$val" = 1 ] && procd_append_param command "$opt"
  25. }
  26. generate_keys() {
  27. local cfg="$1"
  28. local key="$2"
  29. local crt="$3"
  30. local days bits country state location organization commonname
  31. config_get days "$cfg" days
  32. config_get bits "$cfg" bits
  33. config_get country "$cfg" country
  34. config_get state "$cfg" state
  35. config_get location "$cfg" location
  36. config_get organization "$cfg" organization
  37. config_get commonname "$cfg" commonname
  38. config_get key_type "$cfg" key_type
  39. config_get ec_curve "$cfg" ec_curve
  40. # Prefer px5g for certificate generation (existence evaluated last)
  41. local GENKEY_CMD=""
  42. local KEY_OPTS="rsa:${bits:-2048}"
  43. local UNIQUEID=$(dd if=/dev/urandom bs=1 count=4 | hexdump -e '1/1 "%02x"')
  44. [ "$key_type" = "ec" ] && KEY_OPTS="ec -pkeyopt ec_paramgen_curve:${ec_curve:-P-256}"
  45. [ -x "$OPENSSL_BIN" ] && GENKEY_CMD="$OPENSSL_BIN req -x509 -sha256 -outform der -nodes"
  46. [ -x "$PX5G_BIN" ] && GENKEY_CMD="$PX5G_BIN selfsigned -der"
  47. [ -n "$GENKEY_CMD" ] && {
  48. $GENKEY_CMD \
  49. -days ${days:-730} -newkey ${KEY_OPTS} -keyout "${UHTTPD_KEY}.new" -out "${UHTTPD_CERT}.new" \
  50. -subj /C="${country:-ZZ}"/ST="${state:-Somewhere}"/L="${location:-Unknown}"/O="${organization:-OpenWrt$UNIQUEID}"/CN="${commonname:-OpenWrt}"
  51. sync
  52. mv "${UHTTPD_KEY}.new" "${UHTTPD_KEY}"
  53. mv "${UHTTPD_CERT}.new" "${UHTTPD_CERT}"
  54. }
  55. }
  56. create_httpauth() {
  57. local cfg="$1"
  58. local prefix username password
  59. config_get prefix "$cfg" prefix
  60. config_get username "$cfg" username
  61. config_get password "$cfg" password
  62. if [ -z "$prefix" ] || [ -z "$username" ] || [ -z "$password" ]; then
  63. return
  64. fi
  65. echo "${prefix}:${username}:${password}" >>$httpdconf
  66. haveauth=1
  67. }
  68. append_lua_prefix() {
  69. local v="$1"
  70. local prefix="${v%%=*}"
  71. local handler="${v#*=}"
  72. if [ "$prefix" != "$handler" ] && [ -n "$prefix" ] && [ -f "$handler" ]; then
  73. procd_append_param command -l "$prefix" -L "$handler"
  74. else
  75. echo "Skipping invalid Lua prefix \"$v\"" >&2
  76. fi
  77. }
  78. append_ucode_prefix() {
  79. local v="$1"
  80. local prefix="${v%%=*}"
  81. local handler="${v#*=}"
  82. if [ "$prefix" != "$handler" ] && [ -n "$prefix" ] && [ -f "$handler" ]; then
  83. procd_append_param command -o "$prefix" -O "$handler"
  84. else
  85. echo "Skipping invalid ucode prefix \"$v\"" >&2
  86. fi
  87. }
  88. start_instance()
  89. {
  90. UHTTPD_CERT=""
  91. UHTTPD_KEY=""
  92. local cfg="$1"
  93. local realm="$(uci_get system.@system[0].hostname)"
  94. local listen http https interpreter indexes path handler httpdconf haveauth
  95. local enabled
  96. config_get_bool enabled "$cfg" 'enabled' 1
  97. [ $enabled -gt 0 ] || return
  98. procd_open_instance
  99. procd_set_param respawn
  100. procd_set_param stderr 1
  101. procd_set_param command "$UHTTPD_BIN" -f
  102. config_get config "$cfg" config
  103. if [ -z "$config" ]; then
  104. mkdir -p /var/etc/uhttpd
  105. httpdconf="/var/etc/uhttpd/httpd.${cfg}.conf"
  106. rm -f ${httpdconf}
  107. config_list_foreach "$cfg" httpauth create_httpauth
  108. if [ "$haveauth" = "1" ]; then
  109. procd_append_param command -c ${httpdconf}
  110. [ -r /etc/httpd.conf ] && cat /etc/httpd.conf >>/var/etc/uhttpd/httpd.${cfg}.conf
  111. fi
  112. fi
  113. append_arg "$cfg" home "-h"
  114. append_arg "$cfg" realm "-r" "${realm:-OpenWrt}"
  115. append_arg "$cfg" config "-c"
  116. append_arg "$cfg" cgi_prefix "-x"
  117. [ -f /usr/lib/uhttpd_lua.so ] && {
  118. local len
  119. config_get len "$cfg" lua_prefix_LENGTH
  120. if [ -n "$len" ]; then
  121. config_list_foreach "$cfg" lua_prefix append_lua_prefix
  122. else
  123. config_get prefix "$cfg" lua_prefix
  124. config_get handler "$cfg" lua_handler
  125. append_lua_prefix "$prefix=$handler"
  126. fi
  127. }
  128. [ -f /usr/lib/uhttpd_ubus.so ] && {
  129. append_arg "$cfg" ubus_prefix "-u"
  130. append_arg "$cfg" ubus_socket "-U"
  131. append_bool "$cfg" ubus_cors "-X" 0
  132. }
  133. [ -f /usr/lib/uhttpd_ucode.so ] && {
  134. config_list_foreach "$cfg" ucode_prefix append_ucode_prefix
  135. }
  136. append_arg "$cfg" script_timeout "-t"
  137. append_arg "$cfg" network_timeout "-T"
  138. append_arg "$cfg" http_keepalive "-k"
  139. append_arg "$cfg" tcp_keepalive "-A"
  140. append_arg "$cfg" error_page "-E"
  141. append_arg "$cfg" max_requests "-n" 3
  142. append_arg "$cfg" max_connections "-N"
  143. append_bool "$cfg" no_ubusauth "-a" 0
  144. append_bool "$cfg" no_symlinks "-S" 0
  145. append_bool "$cfg" no_dirlists "-D" 0
  146. append_bool "$cfg" rfc1918_filter "-R" 0
  147. config_get alias_list "$cfg" alias
  148. for alias in $alias_list; do
  149. procd_append_param command -y "$alias"
  150. done
  151. config_get http "$cfg" listen_http
  152. for listen in $http; do
  153. procd_append_param command -p "$listen"
  154. done
  155. config_get interpreter "$cfg" interpreter
  156. for path in $interpreter; do
  157. procd_append_param command -i "$path"
  158. done
  159. config_get indexes "$cfg" index_page
  160. for path in $indexes; do
  161. procd_append_param command -I "$path"
  162. done
  163. config_get https "$cfg" listen_https
  164. config_get UHTTPD_KEY "$cfg" key /etc/uhttpd.key
  165. config_get UHTTPD_CERT "$cfg" cert /etc/uhttpd.crt
  166. [ -f /lib/libustream-ssl.so ] && [ -n "$https" ] && {
  167. [ -s "$UHTTPD_CERT" -a -s "$UHTTPD_KEY" ] || {
  168. config_foreach generate_keys cert
  169. }
  170. [ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] && {
  171. append_arg "$cfg" cert "-C"
  172. append_arg "$cfg" key "-K"
  173. for listen in $https; do
  174. procd_append_param command -s "$listen"
  175. done
  176. }
  177. append_bool "$cfg" redirect_https "-q" 0
  178. }
  179. config_get json_script "$cfg" json_script
  180. for file in $json_script; do
  181. [ -s "$file" ] && procd_append_param command -H "$file"
  182. done
  183. procd_close_instance
  184. }
  185. uhttpd_interfaces()
  186. {
  187. local cfg="$1"
  188. local http https listen ips
  189. config_get http "$cfg" listen_http
  190. config_get https "$cfg" listen_https
  191. for listen in $http $https; do
  192. case "$listen" in
  193. "" |\
  194. "0.0.0.0:"* |\
  195. "[::]:"* )
  196. continue
  197. ;;
  198. *.*.*.*:*)
  199. ips="$ips ${listen%%:*}
  200. "
  201. ;;
  202. \[*\]:* )
  203. listen="${listen:1}"
  204. ips="$ips ${listen%%]:*}
  205. "
  206. ;;
  207. esac
  208. done
  209. ips="$( echo "$ips" | sort -u )"
  210. echo "$ips"
  211. }
  212. resolve_iface()
  213. {
  214. local cfg="$1"
  215. local ipaddr ipaddrs testip="$2"
  216. config_get ipaddrs "$cfg" ipaddr
  217. for ipaddr in $ipaddrs; do
  218. [ "$ipaddr" = "$testip" ] && echo "$cfg"
  219. done
  220. }
  221. get_interface_by_ip()
  222. {
  223. config_load network
  224. config_foreach resolve_iface interface "$@"
  225. }
  226. service_triggers()
  227. {
  228. local iface ifaces all=0
  229. procd_add_reload_trigger "uhttpd"
  230. procd_add_raw_trigger acme.renew 5000 /etc/init.d/uhttpd reload
  231. config_load uhttpd
  232. ips="$(config_foreach uhttpd_interfaces uhttpd)"
  233. [ -z "$ips" ] && return 0
  234. for ip in $ips; do
  235. iface="$(get_interface_by_ip $ip)"
  236. [ -z "$iface" ] && all=1
  237. ifaces="$ifaces $iface"
  238. done
  239. if [ "$all" = "1" ]; then
  240. procd_add_raw_trigger "interface.*.up" 1000 /etc/init.d/uhttpd start
  241. else
  242. for iface in $ifaces; do
  243. procd_add_raw_trigger "interface.$iface.up" 1000 /etc/init.d/uhttpd start
  244. done
  245. fi
  246. }
  247. start_service() {
  248. config_load uhttpd
  249. config_foreach start_instance uhttpd
  250. }