uhttpd.init 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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:-397} -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. -addext extendedKeyUsage=serverAuth -addext subjectAltName=DNS:"${commonname:-OpenWrt}"
  52. sync
  53. mv "${UHTTPD_KEY}.new" "${UHTTPD_KEY}"
  54. mv "${UHTTPD_CERT}.new" "${UHTTPD_CERT}"
  55. }
  56. }
  57. create_httpauth() {
  58. local cfg="$1"
  59. local prefix username password
  60. config_get prefix "$cfg" prefix
  61. config_get username "$cfg" username
  62. config_get password "$cfg" password
  63. if [ -z "$prefix" ] || [ -z "$username" ] || [ -z "$password" ]; then
  64. return
  65. fi
  66. echo "${prefix}:${username}:${password}" >>$httpdconf
  67. haveauth=1
  68. }
  69. append_lua_prefix() {
  70. local v="$1"
  71. local prefix="${v%%=*}"
  72. local handler="${v#*=}"
  73. if [ "$prefix" != "$handler" ] && [ -n "$prefix" ] && [ -f "$handler" ]; then
  74. procd_append_param command -l "$prefix" -L "$handler"
  75. else
  76. echo "Skipping invalid Lua prefix \"$v\"" >&2
  77. fi
  78. }
  79. append_ucode_prefix() {
  80. local v="$1"
  81. local prefix="${v%%=*}"
  82. local handler="${v#*=}"
  83. if [ "$prefix" != "$handler" ] && [ -n "$prefix" ] && [ -f "$handler" ]; then
  84. procd_append_param command -o "$prefix" -O "$handler"
  85. else
  86. echo "Skipping invalid ucode prefix \"$v\"" >&2
  87. fi
  88. }
  89. start_instance()
  90. {
  91. UHTTPD_CERT=""
  92. UHTTPD_KEY=""
  93. local cfg="$1"
  94. local realm="$(uci_get system.@system[0].hostname)"
  95. local listen http https interpreter indexes path handler httpdconf haveauth
  96. local enabled
  97. config_get_bool enabled "$cfg" 'enabled' 1
  98. [ $enabled -gt 0 ] || return
  99. procd_open_instance
  100. procd_set_param respawn
  101. procd_set_param stderr 1
  102. procd_set_param command "$UHTTPD_BIN" -f
  103. config_get config "$cfg" config
  104. if [ -z "$config" ]; then
  105. mkdir -p /var/etc/uhttpd
  106. httpdconf="/var/etc/uhttpd/httpd.${cfg}.conf"
  107. rm -f ${httpdconf}
  108. config_list_foreach "$cfg" httpauth create_httpauth
  109. if [ "$haveauth" = "1" ]; then
  110. procd_append_param command -c ${httpdconf}
  111. [ -r /etc/httpd.conf ] && cat /etc/httpd.conf >>/var/etc/uhttpd/httpd.${cfg}.conf
  112. fi
  113. fi
  114. append_arg "$cfg" home "-h"
  115. append_arg "$cfg" realm "-r" "${realm:-OpenWrt}"
  116. append_arg "$cfg" config "-c"
  117. append_arg "$cfg" cgi_prefix "-x"
  118. [ -f /usr/lib/uhttpd_lua.so ] && {
  119. local len
  120. config_get len "$cfg" lua_prefix_LENGTH
  121. if [ -n "$len" ]; then
  122. config_list_foreach "$cfg" lua_prefix append_lua_prefix
  123. else
  124. config_get prefix "$cfg" lua_prefix
  125. config_get handler "$cfg" lua_handler
  126. append_lua_prefix "$prefix=$handler"
  127. fi
  128. }
  129. [ -f /usr/lib/uhttpd_ubus.so ] && {
  130. append_arg "$cfg" ubus_prefix "-u"
  131. append_arg "$cfg" ubus_socket "-U"
  132. append_bool "$cfg" ubus_cors "-X" 0
  133. }
  134. [ -f /usr/lib/uhttpd_ucode.so ] && {
  135. config_list_foreach "$cfg" ucode_prefix append_ucode_prefix
  136. }
  137. append_arg "$cfg" script_timeout "-t"
  138. append_arg "$cfg" network_timeout "-T"
  139. append_arg "$cfg" http_keepalive "-k"
  140. append_arg "$cfg" tcp_keepalive "-A"
  141. append_arg "$cfg" error_page "-E"
  142. append_arg "$cfg" max_requests "-n" 3
  143. append_arg "$cfg" max_connections "-N"
  144. append_bool "$cfg" no_ubusauth "-a" 0
  145. append_bool "$cfg" no_symlinks "-S" 0
  146. append_bool "$cfg" no_dirlists "-D" 0
  147. append_bool "$cfg" rfc1918_filter "-R" 0
  148. config_get alias_list "$cfg" alias
  149. for alias in $alias_list; do
  150. procd_append_param command -y "$alias"
  151. done
  152. config_get http "$cfg" listen_http
  153. for listen in $http; do
  154. procd_append_param command -p "$listen"
  155. done
  156. config_get interpreter "$cfg" interpreter
  157. for path in $interpreter; do
  158. procd_append_param command -i "$path"
  159. done
  160. config_get indexes "$cfg" index_page
  161. for path in $indexes; do
  162. procd_append_param command -I "$path"
  163. done
  164. config_get https "$cfg" listen_https
  165. config_get UHTTPD_KEY "$cfg" key /etc/uhttpd.key
  166. config_get UHTTPD_CERT "$cfg" cert /etc/uhttpd.crt
  167. [ -f /lib/libustream-ssl.so ] && [ -n "$https" ] && {
  168. [ -s "$UHTTPD_CERT" -a -s "$UHTTPD_KEY" ] || {
  169. config_foreach generate_keys cert
  170. }
  171. [ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] && {
  172. append_arg "$cfg" cert "-C"
  173. append_arg "$cfg" key "-K"
  174. procd_append_param file "$UHTTPD_CERT"
  175. procd_append_param file "$UHTTPD_KEY"
  176. for listen in $https; do
  177. procd_append_param command -s "$listen"
  178. done
  179. }
  180. append_bool "$cfg" redirect_https "-q" 0
  181. }
  182. config_get json_script "$cfg" json_script
  183. for file in $json_script; do
  184. [ -s "$file" ] && procd_append_param command -H "$file"
  185. done
  186. procd_close_instance
  187. }
  188. uhttpd_interfaces()
  189. {
  190. local cfg="$1"
  191. local http https listen ips
  192. config_get http "$cfg" listen_http
  193. config_get https "$cfg" listen_https
  194. for listen in $http $https; do
  195. case "$listen" in
  196. "" |\
  197. "0.0.0.0:"* |\
  198. "[::]:"* )
  199. continue
  200. ;;
  201. *.*.*.*:*)
  202. ips="$ips ${listen%%:*}
  203. "
  204. ;;
  205. \[*\]:* )
  206. listen="${listen:1}"
  207. ips="$ips ${listen%%]:*}
  208. "
  209. ;;
  210. esac
  211. done
  212. ips="$( echo "$ips" | sort -u )"
  213. echo "$ips"
  214. }
  215. resolve_iface()
  216. {
  217. local cfg="$1"
  218. local ipaddr ipaddrs testip="$2"
  219. config_get ipaddrs "$cfg" ipaddr
  220. for ipaddr in $ipaddrs; do
  221. [ "$ipaddr" = "$testip" ] && echo "$cfg"
  222. done
  223. }
  224. get_interface_by_ip()
  225. {
  226. config_load network
  227. config_foreach resolve_iface interface "$@"
  228. }
  229. service_triggers()
  230. {
  231. local iface ifaces all=0
  232. procd_add_reload_trigger "uhttpd"
  233. procd_add_raw_trigger acme.renew 5000 /etc/init.d/uhttpd reload
  234. config_load uhttpd
  235. ips="$(config_foreach uhttpd_interfaces uhttpd)"
  236. [ -z "$ips" ] && return 0
  237. for ip in $ips; do
  238. iface="$(get_interface_by_ip $ip)"
  239. [ -z "$iface" ] && all=1
  240. ifaces="$ifaces $iface"
  241. done
  242. if [ "$all" = "1" ]; then
  243. procd_add_raw_trigger "interface.*.up" 1000 /etc/init.d/uhttpd start
  244. else
  245. for iface in $ifaces; do
  246. procd_add_raw_trigger "interface.$iface.up" 1000 /etc/init.d/uhttpd start
  247. done
  248. fi
  249. }
  250. start_service() {
  251. config_load uhttpd
  252. config_foreach start_instance uhttpd
  253. }