diff --git a/packages/ns-don/files/don b/packages/ns-don/files/don index 000a7c085..285a70c19 100755 --- a/packages/ns-don/files/don +++ b/packages/ns-don/files/don @@ -17,6 +17,10 @@ rsa_key="$base_dir/rsa_key" ecdsa_key="$base_dir/ecdsa_key" socket="$base_dir/management" credentials="$base_dir/credentials" +session_start="$base_dir/session_start" +session_extended="$base_dir/session_extended" +cleanup_lock="$base_dir/.cleanup_lock" +crontab_file="/etc/crontabs/root" user="nethsupport" password="" ca=$(uci -q get don.config.ca) @@ -27,8 +31,48 @@ if [ "$2" == "-j" ]; then json_output=1 fi +function log_message +{ + # Log to /var/log/messages using logger (syslog) + logger -t "don" -p daemon.info "$1" +} + +function log_error +{ + # Log errors to syslog + logger -t "don" -p daemon.err "$1" +} + +function add_cron_expiration +{ + # Add cron job to check expiration every hour + if ! grep -q "/usr/sbin/don expire" "$crontab_file" 2>/dev/null; then + echo "0 * * * * sleep \$(( RANDOM % 60 )); /usr/sbin/don expire" >> "$crontab_file" + [ -x /etc/init.d/cron ] && /etc/init.d/cron restart + log_message "Expiration cron job added" + fi +} + +function remove_cron_expiration +{ + # Remove cron job for expiration checking + if [ -f "$crontab_file" ]; then + sed -i '\|/usr/sbin/don expire|d' "$crontab_file" + [ -x /etc/init.d/cron ] && /etc/init.d/cron restart + fi +} + function cleanup { + # Use lock file to prevent concurrent cleanup calls + if [ -f "$cleanup_lock" ]; then + # Another cleanup is already running, skip + return + fi + # Create lock to prevent concurrent executions + touch "$cleanup_lock" + # Remove expiration cron job + remove_cron_expiration # stop demons [ -f "$sshd_pid" ] && kill "$(cat $sshd_pid)" [ -f "$vpn_pid" ] && kill "$(cat $vpn_pid)" && sleep 3 && [ -f "$vpn_pid" ] && kill -9 "$(cat $vpn_pid)" @@ -40,19 +84,64 @@ function cleanup # destroy ubus sessions session=$(ubus call session list | jq -r '.ubus_rpc_session as $parent | .data.username | select(. == "nethsupport") | $parent') if [ "$session" != "" ]; then - ubus call session destroy '{"ubus_rpc_session": "'$session'"}' + ubus call session destroy '{"ubus_rpc_session": "'"$session"'"}' fi + log_message "Remote support session stopped" } -function show_credentials +function get_session_info { + local extra_status="$1" + # Both session_start and credentials must be present for a valid session + if [ ! -f "$session_start" ] || [ ! -f "$credentials" ]; then + if [ "$json_output" == 1 ]; then + echo "null" + fi + return 1 + fi + + # Read credentials file into array + mapfile -t creds < "$credentials" + local server_id="${creds[0]}" + local session_id="${creds[1]}" + + local session_start_time + session_start_time=$(cat "$session_start") + local session_expiry + + # Use extended expiry if available, otherwise use start + 24 hours + if [ -f "$session_extended" ]; then + local extension_duration + extension_duration=$(cat "$session_extended") + session_expiry=$((session_start_time + extension_duration)) + else + session_expiry=$((session_start_time + 86400)) + fi + + local current_time + current_time=$(date +%s) + local time_remaining=$((session_expiry - current_time)) + if [ "$json_output" == 1 ]; then - echo "{\"server_id\": \"$(sed -n '1{p;q}' $credentials)\", \"session_id\": \"$(sed -n '2{p;q}' $credentials)\"}" + local status_field="" + if [ "$extra_status" == "already_extended" ]; then + status_field=", \"status\": \"$extra_status\"" + fi + if [ "$time_remaining" -gt 0 ]; then + echo "{\"server_id\": \"$server_id\", \"session_id\": \"$session_id\", \"expires_in_seconds\": $time_remaining$status_field}" + else + echo "{\"server_id\": \"$server_id\", \"session_id\": \"$session_id\", \"status\": \"expired\"}" + fi else - echo -n "Server ID:" - echo -e "\t"$(sed -n '1{p;q}' $credentials) - echo -n "Session ID:" - echo -e "\t"$(sed -n '2{p;q}' $credentials) + local hours_remaining=$((time_remaining / 3600)) + local minutes_remaining=$(( (time_remaining % 3600) / 60 )) + echo "Server ID:$(printf '\t')$server_id" + echo "Session ID:$(printf '\t')$session_id" + if [ "$time_remaining" -gt 0 ]; then + echo "Session expires in: ${hours_remaining}h ${minutes_remaining}m" + else + echo "Session EXPIRED" + fi fi } @@ -67,11 +156,13 @@ start) system_id=$(uci -q get ns-plug.config.system_id) fi if [ -z "$system_id" ]; then + log_error "Remote support session failed: system_id not configured" exit 2 fi - cn=$(openssl x509 -noout -subject -in $ca | cut -d= -f 2- | sed 's/ = /=/g') + cn=$(openssl x509 -noout -subject -in "$ca" | cut -d= -f 2- | sed 's/ = /=/g') if [ -z "$cn" ]; then + log_error "Remote support session failed: invalid CA certificate" exit 3 fi @@ -162,38 +253,118 @@ AuthorizedKeysFile $auth_keys StrictModes no EOF - mkdir -m 0700 -p /var/empty - /usr/sbin/sshd -f $sshd_conf - cat $(uci -q get don.config.ssh_key) > $auth_keys + mkdir -p /var/empty + chmod 700 /var/empty + /usr/sbin/sshd -f "$sshd_conf" + cat "$(uci -q get don.config.ssh_key)" > "$auth_keys" # Enable UI access uci set rpcd.ns_don=login uci set rpcd.ns_don.username=$user - uci set rpcd.ns_don.password=$(echo $password | mkpasswd) + uci set rpcd.ns_don.password="$(echo "$password" | mkpasswd)" uci add_list rpcd.ns_don.read='*' uci add_list rpcd.ns_don.write='*' # commit rpcd changes uci commit rpcd - show_credentials + # Save session start time + date +%s > "$session_start" + # Mark as not extended initially + rm -f $session_extended + + # Add expiration cron job + add_cron_expiration + + log_message "Remote support session started" + + get_session_info ;; stop) cleanup ;; status) - if [ -f $credentials ]; then - show_credentials - exit 0 + if [ -f "$credentials" ]; then + get_session_info + exit $? else if [ "$json_output" == 1 ]; then echo null else echo "don is not running" fi - exit 1 + exit 1 + fi +;; +expire) + # Check if session has expired - requires both files to be present + if [ ! -f "$session_start" ] || [ ! -f "$credentials" ]; then + if [ "$json_output" == 1 ]; then + echo "{\"status\": \"no_session\"}" + else + echo "No session running" + fi + exit 0 fi + + session_start_time=$(cat "$session_start") + # Use extended expiry if available, otherwise use start + 24 hours + if [ -f "$session_extended" ]; then + extension_duration=$(cat "$session_extended") + session_expiry=$((session_start_time + extension_duration)) + else + session_expiry=$((session_start_time + 86400)) + fi + + current_time=$(date +%s) + time_remaining=$((session_expiry - current_time)) + + if [ $time_remaining -le 0 ]; then + # Session has expired - STOP IT NOW + if [ "$json_output" == 1 ]; then + echo "{\"status\": \"expired\", \"action\": \"stopping\"}" + else + echo "Session expired - stopping don service" + fi + log_error "Remote support session expired - auto-disabling" + cleanup + fi +;; +extend) + # Extend session by 7 days + if [ ! -f "$session_start" ] || [ ! -f "$credentials" ]; then + if [ "$json_output" == 1 ]; then + echo "{\"status\": \"no_session\"}" + else + echo "No session running" + fi + exit 0 + fi + + # Only extend once: if already extended, do nothing + if [ -f "$session_extended" ]; then + if [ "$json_output" != 1 ]; then + echo "Session already extended" + echo "" + fi + get_session_info "already_extended" + exit $? + fi + + # Extend: store 24h + 7 days as total duration relative to session_start + echo "$((86400 + 604800))" > "$session_extended" + + # Log the extension + log_message "Remote support session extended by 7 days" + + if [ "$json_output" != 1 ]; then + echo "Session extended by 7 days" + echo "" + fi + + # Show updated session info + get_session_info ;; *) - echo "Usage: $0 {start|stop|status} [-j]" + echo "Usage: $0 {start|stop|status|expire|extend} [-j]" exit 2 esac