#!/bin/sh /etc/rc.common . /lib/functions/network.sh START=90 STOP=10 USE_PROCD=1 PROG=/usr/bin/owsd UPROXYD="/sbin/uproxyd" CONFIGFILE="/etc/config/owsd" JSONFILE="/tmp/owsd/owsd.json" DHCP_DOMAINS="" USERS="" OWLNUM=0 owsd_acl() { local section=$1 local username=$2 local user="" acl_add_user() { local user=$1 if [ "$user" == "$username" ]; then json_add_string "" $section fi } config_get user $section user if [ -n "$user" ]; then config_list_foreach "$section" "user" acl_add_user else for usr in $USERS; do acl_add_user $usr done fi OWLNUM=$((OWLNUM+1)) } append_users() { local section=$1 config_get username $section username USERS="$USERS $username" } rpcd_acl() { local section=$1 local owl="" local _i=1 config_get username $section username json_select $username uci -q delete rpcd.$section.owsd_listen while json_get_var owl $_i; do uci -q add_list rpcd.$section.owsd_listen="$owl" _i=$((_i+1)) done [ $((OWLNUM+1)) -eq $_i ] && uci -q delete rpcd.$section.owsd_listen json_select .. } handle_owsd_acl() { [ -d /tmp/owsd ] || mkdir /tmp/owsd config_load rpcd config_foreach append_users "login" config_load owsd json_init for USR in $USERS; do json_add_array "$USR" OWLNUM=0 config_foreach owsd_acl "owsd-listen" "$USR" json_close_array done json_dump > /tmp/owsd/owsd_acl json_load "$(cat /tmp/owsd/owsd_acl)" config_load rpcd config_foreach rpcd_acl "login" uci commit rpcd /etc/init.d/rpcd reload } load_dhcp_domains() { append_domain() { local domain=$1 DHCP_DOMAINS="$DHCP_DOMAINS $domain" } dhcp_domain_section() { local section=$1 local ip config_get ip "$section" ip [ -z "$ip" ] && config_list_foreach "$section" "name" append_domain } config_load dhcp # note: do not overload a config while parsing it config_foreach dhcp_domain_section "domain" } validate_owsd_ubusproxy() { uci_validate_section "owsd" "ubusproxy" "ubusproxy" \ 'enable:bool:1' \ 'peer:list(string)' \ 'object:list(string)' \ 'prefix:string' \ 'max_reconnect_time:string' \ 'client_backoff_timeout:string' \ 'reconnect_timeout:string' \ 'peer_key:file' \ 'peer_cert:file' \ 'peer_ca:file' \ } validate_owsd_global() { uci_validate_section "owsd" "owsd" "global" \ 'enable:bool:1' \ 'sock:string' \ 'redirect:string' \ 'www:string' \ 'www_maxage:integer' \ } append_str() { json_add_string "" "$1" } append_origin_parts() { local proto host port proto="$1" host="$2" port="$3" if [ "${proto}" = "https" -a "${port}" -eq 443 -o "${proto}" = "http" -a "${port}" -eq 80 ]; then append_str "${proto}://${host}" else append_str "${proto}://${host}:${port}" fi } validate_owsd_iface() { uci_validate_section "owsd" "owsd-listen" "$1" \ 'port:port' \ 'interface:network' \ 'origin:list(string)' \ 'whitelist_interface_as_origin:bool:1' \ 'whitelist_dhcp_domains:bool:0' \ 'whitelist_all_origins:bool:0' \ 'ipv6:bool:1' \ 'ipv6only:bool:0' \ 'linklocal:bool:0' \ 'cert:file' \ 'key:file' \ 'ca:file' \ 'restrict_to_user:list(string)' \ 'ubusx_acl:list(string)' \ && [ -n "${port}" ] } parse_owsd_iface() { local port interface whitelist_interface_as_origin whitelist_dhcp_domains whitelist_all_origins ipv6 ipv6only linklocal local cert key ca local restrict_to_user local ubusx_acl validate_owsd_iface "$1" || { echo "Validation failed" return 1 } # utility function new_listen_socket() { json_add_int "port" ${port} [ -n "${cert}" ] && json_add_string "cert" "${cert}" [ -n "${key}" ] && json_add_string "key" "${key}" [ -n "${ca}" ] && json_add_string "ca" "${ca}" [ -n "${restrict_to_user}" ] && { json_add_array "restrict_to_user" config_list_foreach "$1" "restrict_to_user" append_str json_close_array } [ -n "$2" ] && json_add_string "interface" "$2" [ -n "${ubusx_acl}" ] && json_add_string "ubusx_acl" "$ubusx_acl" } origin_whitelist_all() { [ "$1" = "*" ] && echo "true" } append_whitelists() { config_list_foreach "$1" "origin" append_str # uncomment code below when implementing one vhost per origin fix [ -n "$2" ] && whitelist_all_origins=1 if [ "$whitelist_all_origins" -eq 1 ]; then whitelist_dhcp_domains=1 whitelist_interface_as_origin=1 fi if [ "$whitelist_dhcp_domains" -eq 1 ]; then for domain in $DHCP_DOMAINS; do append_origin_parts "${http}" "${domain}" "${port}" done fi if [ -n "${interface}" -a -n "${addr}" -a "${whitelist_interface_as_origin}" -eq 1 ]; then append_origin_parts "${http}" "${addr}" "${port}" fi } local http="http${cert:+s}" local ip4addrs ip6addrs linklocaladdrs # bind to some network if [ -n "${interface}" ]; then # 1 listen-socket (vhost) for each IP address on that network's iface whitelist=$(config_list_foreach "$1" "origin" origin_whitelist_all) # ipv4 addresses if [ "${ipv6only}" -eq 0 ]; then network_get_ipaddrs ip4addrs "${interface}"; fi json_add_array "$1" for addr in ${ip4addrs}; do json_add_object "${1}" new_listen_socket "$1" "${addr}" [ -n "$whitelist" -o "$whitelist_all_origins" -eq 1 ] && json_add_boolean "origin_check" false json_add_array "origin" append_whitelists "$1" "$whitelist" json_close_array json_close_object done # ipv6 addresses if [ "${ipv6}" -eq 1 ]; then network_get_ipaddrs6 ip6addrs "${interface}" if [ "${linklocal}" -eq 1 ]; then network_get_device device "${interface}" [ -n "${device}" ] && linklocaladdrs=$(ifconfig $device | grep inet6 | grep Scope:Link | awk '{print$3}' | cut -d'/' -f1) ip6addrs="${ip6addrs} ${linklocaladdrs}" fi fi for addr in ${ip6addrs}; do json_add_object "${1}6" new_listen_socket "$1" "${addr}" addr="\\[${addr}]" [ -n "$whitelist" ] && json_add_boolean "origin_check" false json_add_array "origin" append_whitelists "$1" "$whitelist" json_close_array json_add_boolean "ipv6" 1 json_close_object done json_close_array else new_listen_socket "$1" if [ "${ipv6}" -eq 1 ]; then json_add_boolean "ipv6only" 1; fi if [ "${ipv6}" -eq 1 -a "${ipv6only}" -eq 1 ]; then json_add_boolean "ipv6only" 1; fi append_whitelists "$1" fi } parser_timeout() { local flag data local ret=0 #data format is digital with time unit #10s-10 seconds 10m-10 minutes 10h-10 hours 10d-10 days if [ -n "$1" ]; then flag=$(echo "$1"| tr -d '0-9' | tr 'A-Z' 'a-z') data=$(echo "$1"| tr -cd '0-9') case $flag in m) ret=$((data*1000*60)) ;; h) ret=$((data*1000*60*60)) ;; d) ret=$((data*1000*60*60*24)) ;; *) # assume seconds if no format given ret=$((data*1000)) ;; esac echo "$ret" else echo "0" fi } start_service() { # update rpcd config according to owsd acl handle_owsd_acl # preload dhcp domains list, in case any interface config requires it load_dhcp_domains config_load owsd # note: do not overload a config while parsing it config_get_bool owsd_enable global enable 1 [ $owsd_enable -eq 1 ] || return 0 procd_open_instance procd_set_param command $PROG local sock www redirect www_maxage local enable peer_cert peer_key peer_ca validate_owsd_global || { echo "Global validation failed" return 1 } json_init json_add_object "global" [ -n "${sock}" ] && json_add_string "socket" "$sock" [ -n "${www}" ] && json_add_string "www" "$www" [ -n "${redirect}" ] && json_add_string "redirect" "$redirect" [ -n "${www_maxage}" ] && json_add_int "www_maxage" "$www_maxage" json_close_object validate_owsd_ubusproxy && { if [ "${enable}" -eq 1 ]; then json_add_object "ubusproxy" [ -n "${peer_cert}" ] && json_add_string "peer_cert" "${peer_cert}" [ -n "${peer_key}" ] && json_add_string "peer_key" "${peer_key}" [ -n "${peer_ca}" ] && json_add_string "peer_ca" "${peer_ca}" append_peer () { [ -n "$1" ] && json_add_string "peer" "$1" } append_object () { [ -n "$1" ] && json_add_string "object" "$1" } json_add_array "peer" config_list_foreach "ubusproxy" "peer" append_peer json_close_array json_add_array "object" config_list_foreach "ubusproxy" "object" append_object json_close_array [ -n "${reconnect_timeout}" ] && json_add_int "reconnect_timeout" $(parser_timeout $reconnect_timeout) [ "${prefix}" == "mac" ] && json_add_string "prefix" "mac" json_close_object fi } json_add_object "owsd-listen" config_foreach parse_owsd_iface "owsd-listen" json_close_object [ ! -d "/tmp/owsd" ] && mkdir /tmp/owsd json_dump > "$JSONFILE" procd_append_param command -f "$JSONFILE" # procd_set_param stderr 1 procd_set_param respawn procd_close_instance if [ "${enable}" -eq 1 ]; then # Start uproxyd procd_open_instance procd_set_param command $UPROXYD config_get ctimeout ubusproxy client_backoff_timeout config_get reconn ubusproxy max_reconnect_time [ -n "${reconn}" ] && procd_append_param command -r "${reconn}" [ -n "${ctimeout}" ] && ctimeout=$(parser_timeout $ctimeout) [ -n "${ctimeout}" ] && procd_append_param command -t "${ctimeout}" procd_set_param respawn procd_close_instance fi } reload_service() { stop start } service_triggers() { procd_add_reload_trigger owsd }