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
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
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"
# 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"
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 | \
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"
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
}
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"
}
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
# * /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
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
}
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"