hostmngr: update implementation

following cases/bugs are handled in this change:
1. Ignore schedule if access_policy is deny
2. For access policy allow, with schedule, deny for time outside
   the defined schedule.
3. Default value for days
4. Handle scenario when start time is not defined by initializing
   the start time to 00:00
5. Handle scenario when duration is not defined
This commit is contained in:
Rahul Thakur 2024-02-23 12:21:34 +05:30
parent ddfab6f729
commit 2f20ec448d

View file

@ -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