diff --git a/hostmngr/files/scripts/hosts_acl.sh b/hostmngr/files/scripts/hosts_acl.sh index 0696b2e66..b2a9aeeb9 100755 --- a/hostmngr/files/scripts/hosts_acl.sh +++ b/hostmngr/files/scripts/hosts_acl.sh @@ -5,6 +5,9 @@ day="" next_days="" prev_days="" +schedule_added="" + +ACCESS_RULE="" IP_RULE="" IP_RULE1="" @@ -108,70 +111,77 @@ ip_rule_east_zone() { fi } -process_ac_schedule() { - local acs_id="$1" - local is_enabled - local access_control - local start_time="" - local mac="" +add_access_rule() { + local rule="$1" + echo "iptables -w -A hosts_forward ${rule}" >> $ACL_FILE + echo "ip6tables -w -A hosts_forward ${rule}" >> $ACL_FILE +} - handle_day_list() { - local value=$1 +handle_day_list() { + local value=$1 - val=$(echo $value | cut -c 1-3) - next_day_val=$(get_next_day $val) - prev_day_val=$(get_previous_day $val) - if [ -z $day ]; then - day="$val" - next_days="$next_day_val" - prev_days="$prev_day_val" - else - day="$day,$val" - next_days="$next_days,$next_day_val" - prev_days="$prev_days,$prev_day_val" - fi - } + val=$(echo $value | cut -c 1-3) + next_day_val=$(get_next_day $val) + prev_day_val=$(get_previous_day $val) + if [ -z $day ]; then + day="$val" + next_days="$next_day_val" + prev_days="$prev_day_val" + else + day="$day,$val" + next_days="$next_days,$next_day_val" + prev_days="$prev_days,$prev_day_val" + fi +} - config_list_foreach "$acs_id" "day" handle_day_list - config_get is_enabled "$acs_id" "enable" 1 - config_get access_control "$acs_id" "dm_parent" +handle_schedule() { + local schd_section="$1" + local ac_section="$2" + local acs_id + local start_time + local duration - if [ "$is_enabled" == "0" ] || [ -z "$access_control" ]; then - return + IP_RULE="$ACCESS_RULE" + IP_RULE1="" + day="" + next_days="" + prev_days="" + + config_get acs_id "$schd_section" "dm_parent" + + if [ "$acs_id" != "$ac_section" ]; then + return # schedule not for this access control section fi - IP_RULE="" - IP_RULE1="" - - config_get is_enabled "$access_control" "enable" 1 + local is_enabled + config_get is_enabled "$schd_section" "enable" 0 if [ "$is_enabled" == "0" ]; then return fi - mac=$(uci -q get hosts.$access_control.macaddr) - access_policy=$(uci -q get hosts.$access_control.access_policy) + local all_days="Monday Tuesday Wednesday Thursday Friday Saturday Sunday" + local day_config + config_get day_config "$schd_section" "day" "$all_days" - config_get start_time "$acs_id" "start_time" - config_get duration "$acs_id" "duration" + IFS=" " + for d in $day_config; do + handle_day_list $d + done - if [ -z "$mac" ] && [ -z "$start_time" ] && [ -z "$duration" ] && [ -z "$day" ] && [ -z "$access_policy" ]; then - return - fi - if [ -n "$mac" ]; then - IP_RULE="$IP_RULE -m mac --mac-source $mac" - fi + config_get start_time "$schd_section" "start_time" "00:00" + config_get duration "$schd_section" "duration" zone=$(date +%z | cut -c 1) local_start_time=$start_time - if [ -n "$duration" ]; then - hh=$(echo $local_start_time | awk -F: '{ print $1 }') - mm=$(echo $local_start_time | awk -F: '{ print $2 }') - hh_s=`expr $hh \* 3600` - mm_s=`expr $mm \* 60` - ss=$(( hh_s + mm_s )) - local_start_hh=$hh + hh=$(echo $local_start_time | awk -F: '{ print $1 }') + mm=$(echo $local_start_time | awk -F: '{ print $2 }') + hh_s=`expr $hh \* 3600` + mm_s=`expr $mm \* 60` + ss=$(( hh_s + mm_s )) + local_start_hh=$hh + if [ -n "$duration" ]; then stop_ss=$(( ss + duration )) hh=$(( stop_ss / 3600 )) rem_ss=$(( stop_ss % 3600 )) @@ -179,6 +189,10 @@ process_ac_schedule() { ss=$(( rem_ss % 60 )) local_stop_time="$hh:$mm:$ss" local_stop_hh=$hh + else + # if duartion is not specified, then apply rule to end of the day + local_stop_time="23:59:59" + local_stop_hh="23" fi utc_start_time=$(date -u -d @$(date "+%s" -d "$local_start_time") +%H:%M) @@ -191,43 +205,91 @@ process_ac_schedule() { ip_rule_east_zone $utc_start_hh $utc_stop_hh $local_start_hh $local_stop_hh $utc_start_time $utc_stop_time fi - if [ "$access_policy" == "Deny" ]; then - IP_RULE="$IP_RULE -j DROP" - if [ -n "$IP_RULE1" ]; then - IP_RULE1="$IP_RULE1 -j DROP" - fi - else - IP_RULE="$IP_RULE -j ACCEPT" - if [ -n "$IP_RULE1" ]; then - IP_RULE1="$IP_RULE1 -j ACCEPT" - fi - fi - - iptables -w -A hosts_forward ${IP_RULE} - ip6tables -w -A hosts_forward ${IP_RULE} + IP_RULE="$IP_RULE -j ACCEPT" if [ -n "$IP_RULE1" ]; then - iptables -w -A hosts_forward ${IP_RULE1} - ip6tables -w -A hosts_forward ${IP_RULE1} + IP_RULE1="$IP_RULE1 -j ACCEPT" fi - day="" - next_days="" - prev_days="" + add_access_rule "$IP_RULE" + if [ -n "$IP_RULE1" ]; then + add_access_rule "$IP_RULE1" + fi + + # for access rules to be effective for a schedule, need to add DROP rule + # to block the access outside the defined schedule + if [ "$schedule_added" == "0" ]; then + schedule_added="1" + fi } -iptables -w -F hosts_forward -ip6tables -w -F hosts_forward +handle_access_control() { + local ac_section="$1" + local is_enabled + + # default value of Hosts.AccessControl.{i}.Enable is false, + # so, if not defined in uci as 1, assume 0 + config_get is_enabled "$ac_section" "enable" 0 + if [ "$is_enabled" == "0" ]; then + return + fi + + local mac_addr + config_get mac_addr "$ac_section" "macaddr" + if [ -z "$mac_addr" ]; then + return + else + ACCESS_RULE="-m mac --mac-source $mac_addr" + fi + + local access_policy + config_get access_policy "$ac_section" "access_policy" + if [ -z "$access_policy" ]; then + return # since system default is allow so no need to do anything + fi + + # As per Data Model, if access policy is deny, then schedule is to be ignored + # and no access is to be provided for the device + if [ "$access_policy" == "Deny" ]; then + ACCESS_RULE="$ACCESS_RULE -j DROP" + add_access_rule "$ACCESS_RULE" + return # no need to parse schedule + fi + + schedule_added="0" + # check if schedule is defined for this access_control instance + # and if yes, create rule accordingly + config_foreach handle_schedule ac_schedule "$ac_section" + + # for access rule to work, need to have default drop rule as last rule + if [ "$schedule_added" == "1" ]; then + IP_RULE="$ACCESS_RULE -j DROP" + add_access_rule "$IP_RULE" + fi +} + +ACL_FILE="/tmp/hosts_access_control/access_control.rules" + +rm -f $ACL_FILE + +mkdir -p /tmp/hosts_access_control/ +touch $ACL_FILE + +echo "iptables -w -F hosts_forward" >> $ACL_FILE +echo "ip6tables -w -F hosts_forward" >> $ACL_FILE hosts_forward=$(iptables -t filter --list | grep hosts_forward) if [ -z "$hosts_forward" ]; then - iptables -w -t filter -N hosts_forward + echo "iptables -w -t filter -N hosts_forward" >> $ACL_FILE ret=$? - [ $ret -eq 0 ] && iptables -w -t filter -I FORWARD -j hosts_forward - ip6tables -w -t filter -N hosts_forward + [ $ret -eq 0 ] && echo "iptables -w -t filter -I FORWARD -j hosts_forward" >> $ACL_FILE + echo "ip6tables -w -t filter -N hosts_forward" >> $ACL_FILE ret=$? - [ $ret -eq 0 ] && ip6tables -w -t filter -I FORWARD -j hosts_forward + [ $ret -eq 0 ] && echo "ip6tables -w -t filter -I FORWARD -j hosts_forward" >> $ACL_FILE fi # Load /etc/config/hosts UCI file config_load hosts -config_foreach process_ac_schedule ac_schedule +config_foreach handle_access_control access_control + +# apply the rules +sh $ACL_FILE