]> git.99rst.org Git - openwrt-packages.git/commitdiff
nut: add more common validators and add more validation
authorDaniel F. Dickinson <redacted>
Mon, 6 Jul 2026 23:00:39 +0000 (19:00 -0400)
committerJosef Schlehofer <redacted>
Wed, 15 Jul 2026 07:34:39 +0000 (09:34 +0200)
Factor out some common validation code into some validator functions,
and add more UCI config validation.

Signed-off-by: Daniel F. Dickinson <redacted>
net/nut/files/nut-cgi.init
net/nut/files/nut-common.sh.functions
net/nut/files/nut-monitor-config.sh.functions
net/nut/files/nut-monitor.init
net/nut/files/nut-server-config.sh.functions
net/nut/files/nut-server.init

index 9c95923582fbebb6762ee238eedbc28227fd366f..c44c7773afe0b01cc87e5c507d6cf56ba3f3c434 100644 (file)
@@ -170,12 +170,10 @@ validate_host() {
                        fi
                        ;;
                hostname)
-                       case "$hostname" in
-                       "" | *[!a-zA-Z0-9.:-\[\]-]*)
+                       if ! check_safe_hostname_or_ip "$hostname"; then
                                log_validation_error "$var" "$ups"
                                return 1
-                               ;;
-                       esac
+                       fi
                        ;;
                displayname)
                        # We accept a minimally useful set of characters for a display name
@@ -191,24 +189,9 @@ validate_host() {
                        esac
                        ;;
                port)
-                       # We don't log missing port log, as port is optional (NUT defaults
-                       # to using 3493 when it is not present)
-                       if [ -n "$port" ]; then
-                               case "$port" in
-                               0*)
-                                       log_validation_error "$var" "$ups"
-                                       return 1
-                                       ;;
-                               *[!0-9]*)
-                                       log_validation_error "$var" "$ups"
-                                       return 1
-                                       ;;
-                               esac
-                               # Catches illegal port numbers, including negative port numbers
-                               if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
-                                       log_error "Port set, but not between 1-65535 for '$ups'" nut-cgi nut-cgi
-                                       return 1
-                               fi
+                       if ! check_port "$port"; then
+                               log_validation_error "$var" "$ups"
+                               return 1
                        fi
                        ;;
                esac
index c077c27f5b0ca6451e4fbccb2b594ad1827e360b..368ef9b0aa7723bfa10f15a60308b8c42347d548 100644 (file)
@@ -68,6 +68,18 @@ check_valid_user_group_name() {
        return 0
 }
 
+# Just a check for safe/allowed characters, not a full validation
+check_safe_hostname_or_ip() {
+       local hostname="$1"
+
+       case "$hostname" in
+       "" | *[!a-zA-Z0-9.:-\[\]-]*)
+               return 1
+               ;;
+       esac
+       return 0
+}
+
 # shellcheck disable=SC2329,SC2317
 check_valid_hex_number() {
        local number="$1"
@@ -113,6 +125,58 @@ check_valid_hex_number() {
        # catch-all have a return) and shellcheck will complain if we do.
 }
 
+# also passes on an empty value
+check_signed_int() {
+       local number="$1"
+
+       # a minus sign with no number is invalid
+       if [ "$number" = "-" ]; then
+               return 1
+       fi
+
+       case "${number#[-]}" in
+       *[!0123456789]*)
+               return 1
+               ;;
+       *)
+               return 0
+               ;;
+       esac
+}
+
+# also passes on an empty value
+check_unsigned_int() {
+       local number="$1"
+
+       case "$number" in
+       *[!0123456789]*)
+               return 1
+               ;;
+       *)
+               return 0
+               ;;
+       esac
+}
+
+# check for valid port, if present
+# also passes on an empty value
+check_port() {
+       local port="$1"
+
+       if [ -n "$port" ]; then
+               case "$port" in
+               *[!0-9]*)
+                       return 1
+                       ;;
+               esac
+               # Catches port numbers outside valid range (1-65535)
+               if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
+                       return 1
+               fi
+       fi
+       return 0
+}
+
 # Wrap logging, in case we decide to update the logging, everywhere
 log_msg() {
        local reason="$1"
index 865e46689623c734aab6b5e7c120bcd5d1e3e358..35f305b21a6af64c411c1ac3315a6afc5a2bcf4e 100644 (file)
@@ -137,22 +137,15 @@ nut_upsmon_conf() {
                OVERDURATION | \
                OBLBDURATION)
                        config_get val "$cfg" "$uci_option"
-                       case "${val#[-]}" in
-                       *[!0123456789]*)
+                       if ! check_signed_int "$val"; then
                                log_error "upsmon section '$cfg' bad value for '$uci_option'" nut-monitor-config.sh nut-monitor-config
                                return 1
-                               ;;
-                       '')
-                               # Ignore options with no configuration
-                               :
-                               ;;
-                       *)
+                       elif [ -n "$val" ]; then # Ignore options with no configuration
                                if ! printf "%s %s\n" "$nut_option" "$val" >>"$config_file"; then
                                        log_error "upsmon section '$cfg' failed to write '$nut_option'" nut-monitor-config.sh nut-monitor-config
                                        return 1
                                fi
-                               ;;
-                       esac
+                       fi
                        ;;
                # integer: negative values not allowed
                DEADTIME | \
@@ -165,22 +158,15 @@ nut_upsmon_conf() {
                POLLFREQALERT | \
                RBWARNTIME)
                        config_get val "$cfg" "$uci_option"
-                       case "$val" in
-                       *[!0123456789]*)
+                       if ! check_unsigned_int "$val"; then
                                log_error "upsmon section '$cfg' bad value for '$uci_option'" nut-monitor-config.sh nut-monitor-config
                                return 1
-                               ;;
-                       '')
-                               # Ignore options with no configuration
-                               :
-                               ;;
-                       *)
+                       elif [ -n "$val" ]; then # Ignore options with no configuration
                                if ! printf "%s %s\n" "$nut_option" "$val" >>"$config_file"; then
                                        log_error "upsmon section '$cfg' failed to write '$nut_option'" nut-monitor-config.sh nut-monitor-config
                                        return 1
                                fi
-                               ;;
-                       esac
+                       fi
                        ;;
                SHUTDOWNCMD)
                        upsmon_conf_get_write "$cfg" "$config_file" "$uci_option" "$nut_option"
@@ -258,12 +244,48 @@ nut_upsmon_add() {
        local type
 
        config_get upsname "$cfg" upsname "$cfg"
+       if ! check_safe_uci_name "$upsname"; then
+               log_error "upsmon section '$cfg' has invalid upsname" nut-monitor-config.sh nut-monitor-config
+               upsmon_conf_fail="true"
+               # we do not error exit so as not abort processing of other sections on the config_foreach
+               return 0
+       fi
        config_get hostname "$cfg" hostname localhost
+       if ! check_safe_hostname_or_ip "$hostname"; then
+               log_error "upsmon section '$cfg' has invalid hostname" nut-monitor-config.sh nut-monitor-config
+               upsmon_conf_fail="true"
+               # we do not error exit so as not abort processing of other sections on the config_foreach
+               return 0
+       fi
        config_get port "$cfg" port
+       if ! check_port "$port"; then
+               log_error "upsmon section '$cfg' has invalid port" nut-monitor-config.sh nut-monitor-config
+               upsmon_conf_fail="true"
+               # we do not error exit so as not abort processing of other sections on the config_foreach
+               return 0
+       fi
        config_get powervalue "$cfg" powervalue 1
+       if ! check_unsigned_int "$powervalue" || [ -z "$powervalue" ]; then
+               log_error "upsmon section '$cfg' has invalid powervalue" nut-monitor-config.sh nut-monitor-config
+               upsmon_conf_fail="true"
+               # we do not error exit so as not abort processing of other sections on the config_foreach
+               return 0
+       fi
        config_get username "$cfg" username
        config_get password "$cfg" password
        config_get type "$cfg" type secondary
+       case "$type" in
+       primary | secondary)
+               # primary or secondary are the only allowed values
+               :
+               ;;
+       *)
+               log_error "upsmon section '$cfg' has invalid user/ups type" nut-monitor-config.sh nut-monitor-config
+               upsmon_conf_fail="true"
+               # we do not error exit so as not abort processing of other sections on the config_foreach
+               return 0
+               ;;
+       esac
 
        system="$upsname@$hostname"
        if [ -n "$port" ]; then
index 7fa9dccbf1366183c86bf3d8b27998c191616ce0..959448b8ccdb0b19b4e3156426601236b2630506 100644 (file)
@@ -201,6 +201,8 @@ stop_service() {
 }
 
 service_triggers() {
+       local val interface_reload_delay
+
        # No config, or error loading config is fatal
        config_load nut_monitor || {
                log_config_load_error "nut_monitor" "nut-monitor" "nut-monitor"
@@ -208,6 +210,10 @@ service_triggers() {
        }
 
        config_get interface_reload_delay upsmon interface_reload_delay $DEFAULT_PROCD_INTERFACE_RELOAD_DELAY
+       if ! check_unsigned_int "$interface_reload_delay" || [ -z "$interface_reload_delay" ]; then
+               log_msg "interface_reload_delay must be an unsigned integer" nut-monitor nut-monitor warn
+               interface_reload_delay="$DEFAULT_PROCD_INTERFACE_RELOAD_DELAY"
+       fi
 
        # We do not pass a variadic instance name as the nut-monitor initscript does
        # not need an additional instance name argument, only the initscript name
index f5533b15b4c4830f5397f47baccd2b8d1340cd8e..f688e2e2fafbbc4adda8541d81ac73af9a8ba0e6 100644 (file)
@@ -11,7 +11,7 @@
 # * /lib/functions.sh has been sourced
 # * /lib/functions/nut/nut-service.sh has been sourced
 
-# * /lib/functions/nut/nut-common.sh must be source and find_statepath executed
+# * /lib/functions/nut/nut-common.sh must be sourced and find_statepath executed
 #   before build_config is called
 
 # Ensure find_statepath from nut-service.sh is executed
@@ -158,7 +158,7 @@ build_server_config() {
                        return 1
                fi
        else
-               # Otherwise if nut-server is already configured, make sure both
+               # Otherwise if nut-monitor is already configured, make sure both
                # nut-server (this service) and nut-monitor are started
                if grep -q '^MODE=netclient' "$NUT_CONF"; then
                        # In modern OpenWrt 'sed -i' modifies the specified files, without backup
index e317e46a3b6a0205e763ded664c9ca6e90953196..1354e90abd2434078a7f8d495dffb3d5b45c6cf9 100644 (file)
@@ -556,6 +556,10 @@ service_triggers() {
        }
 
        config_get interface_reload_delay upsd interface_reload_delay $DEFAULT_PROCD_INTERFACE_RELOAD_DELAY
+       if ! check_unsigned_int "$interface_reload_delay" || [ -z "$interface_reload_delay" ]; then
+               log_msg "interface_reload_delay must be an unsigned integer" nut-server nut-server warn
+               interface_reload_delay="$DEFAULT_PROCD_INTERFACE_RELOAD_DELAY"
+       fi
 
        interface_triggers "add_trigger" "upsd" "$interface_reload_delay" "nut-server" "upsd"
        procd_add_reload_trigger "nut_server"
git clone https://git.99rst.org/PROJECT