mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2025-12-10 07:44:50 +01:00
usermngr: added password expiry extension
This commit is contained in:
parent
02ee448479
commit
95778a4262
3 changed files with 97 additions and 10 deletions
|
|
@ -6,15 +6,15 @@ config USERMNGR_SECURITY_HARDENING
|
||||||
help
|
help
|
||||||
Enable this option to use PAM based faillock, passwdqc, faildelay for security hardening.
|
Enable this option to use PAM based faillock, passwdqc, faildelay for security hardening.
|
||||||
|
|
||||||
config USERMNGR_ENABLE_AUTH_VENDOR_EXT
|
config USERMNGR_ENABLE_VENDOR_EXT
|
||||||
depends on USERMNGR_SECURITY_HARDENING
|
depends on USERMNGR_SECURITY_HARDENING
|
||||||
bool "Exposes vendor datamodel extensions for AuthenticationPolicy"
|
bool "Expose vendor datamodel extensions."
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Enable this option to expose TR181 vendor extensions for AuthenticationPolicy.
|
Enable this option to expose TR181 vendor extensions.
|
||||||
|
|
||||||
config USERMNGR_VENDOR_PREFIX
|
config USERMNGR_VENDOR_PREFIX
|
||||||
depends on USERMNGR_ENABLE_AUTH_VENDOR_EXT
|
depends on USERMNGR_ENABLE_VENDOR_EXT
|
||||||
string "Package specific datamodel Vendor Prefix for TR181 extensions"
|
string "Package specific datamodel Vendor Prefix for TR181 extensions"
|
||||||
default ""
|
default ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=usermngr
|
PKG_NAME:=usermngr
|
||||||
PKG_VERSION:=1.4.5
|
PKG_VERSION:=1.4.6
|
||||||
|
|
||||||
LOCAL_DEV:=0
|
LOCAL_DEV:=0
|
||||||
ifneq ($(LOCAL_DEV),1)
|
ifneq ($(LOCAL_DEV),1)
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/usermngr.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/usermngr.git
|
||||||
PKG_SOURCE_VERSION:=1082342fda754d7219dbca7dec22d34ad4ff7f8e
|
PKG_SOURCE_VERSION:=416c49b53ed2fbbc983f404c65b8a8ce722152bd
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
endif
|
endif
|
||||||
|
|
@ -36,6 +36,7 @@ define Package/usermngr
|
||||||
DEPENDS+=+@USERMNGR_SECURITY_HARDENING:BUSYBOX_CONFIG_PAM
|
DEPENDS+=+@USERMNGR_SECURITY_HARDENING:BUSYBOX_CONFIG_PAM
|
||||||
DEPENDS+=+USERMNGR_SECURITY_HARDENING:linux-pam
|
DEPENDS+=+USERMNGR_SECURITY_HARDENING:linux-pam
|
||||||
DEPENDS+=+USERMNGR_SECURITY_HARDENING:passwdqc
|
DEPENDS+=+USERMNGR_SECURITY_HARDENING:passwdqc
|
||||||
|
DEPENDS+=+USERMNGR_ENABLE_VENDOR_EXT:shadow-chage
|
||||||
TITLE:=Package to add Device.Users. datamodel support
|
TITLE:=Package to add Device.Users. datamodel support
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
@ -57,8 +58,8 @@ ifeq ($(CONFIG_USERMNGR_SECURITY_HARDENING),y)
|
||||||
MAKE_FLAGS += USERMNGR_SECURITY_HARDENING=y
|
MAKE_FLAGS += USERMNGR_SECURITY_HARDENING=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USERMNGR_ENABLE_AUTH_VENDOR_EXT),y)
|
ifeq ($(CONFIG_USERMNGR_ENABLE_VENDOR_EXT),y)
|
||||||
MAKE_FLAGS += USERMNGR_ENABLE_AUTH_VENDOR_EXT=y
|
MAKE_FLAGS += USERMNGR_ENABLE_VENDOR_EXT=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USERMNGR_VENDOR_PREFIX),"")
|
ifeq ($(CONFIG_USERMNGR_VENDOR_PREFIX),"")
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,18 @@ REQUIRED_MODULES="
|
||||||
/usr/lib/security/pam_passwdqc.so
|
/usr/lib/security/pam_passwdqc.so
|
||||||
"
|
"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$*" | logger -t user.init -p info
|
||||||
|
}
|
||||||
|
|
||||||
|
log_err() {
|
||||||
|
echo "$*" | logger -t user.init -p err
|
||||||
|
}
|
||||||
|
|
||||||
check_required_modules() {
|
check_required_modules() {
|
||||||
for mod in $REQUIRED_MODULES; do
|
for mod in $REQUIRED_MODULES; do
|
||||||
if [ ! -f "$mod" ]; then
|
if [ ! -f "$mod" ]; then
|
||||||
logger -p err -t usermngr "ERROR: Cannot setup security policy, missing PAM module: $mod"
|
log_err "ERROR: Cannot setup security policy, missing PAM module: $mod"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
@ -41,7 +49,7 @@ compare_and_replace() {
|
||||||
|
|
||||||
if [ ! -f "$dst" ] || ! cmp -s "$src" "$dst"; then
|
if [ ! -f "$dst" ] || ! cmp -s "$src" "$dst"; then
|
||||||
cp "$src" "$dst"
|
cp "$src" "$dst"
|
||||||
logger -t pam_policy_setup "Updated $dst"
|
log "Updated $dst"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,9 +173,87 @@ update_account() {
|
||||||
compare_and_replace "$tmp_file" "$pam_file"
|
compare_and_replace "$tmp_file" "$pam_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_password_expiry() {
|
||||||
|
local user password_expiry shadow_entry lastchg_days lastchg_epoch expiry_epoch expiry_days max_days current_max_days
|
||||||
|
user="$1"
|
||||||
|
|
||||||
|
# Fetch expiry (in yyyy-mm-dd format) from UCI
|
||||||
|
config_get password_expiry "$user" password_expiry
|
||||||
|
|
||||||
|
# Get /etc/shadow entry for the user
|
||||||
|
shadow_entry="$(grep "^${user}:" /etc/shadow 2>/dev/null)"
|
||||||
|
if [ -z "$shadow_entry" ]; then
|
||||||
|
log_err "No shadow entry found for $user, skipping"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
current_max_days="$(echo "$shadow_entry" | cut -d: -f5)"
|
||||||
|
|
||||||
|
# Handle infinite lifetime (no expiry set)
|
||||||
|
if [ -z "$password_expiry" ]; then
|
||||||
|
if [ "$current_max_days" = "-1" ] || [ -z "$current_max_days" ]; then
|
||||||
|
log "Password for $user already set to never expire, no action needed"
|
||||||
|
else
|
||||||
|
chage -M -1 "$user"
|
||||||
|
log "Set password expiry for $user to never expire (previous max_days=$current_max_days)"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# option value is of the form 9999-12-31T23:59:59Z, so extract date
|
||||||
|
# because shadow/chage only allow us to specify expiry date
|
||||||
|
password_expiry="$(echo "$password_expiry" | cut -d 'T' -f 1)"
|
||||||
|
|
||||||
|
# Validate date format (yyyy-mm-dd)
|
||||||
|
if ! echo "$password_expiry" | grep -Eq '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'; then
|
||||||
|
log_err "Invalid password_expiry format for $user: '$password_expiry' (expected yyyy-mm-dd)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert expiry date to epoch seconds
|
||||||
|
expiry_epoch="$(date -d "$password_expiry" +%s 2>/dev/null)"
|
||||||
|
if [ -z "$expiry_epoch" ]; then
|
||||||
|
log_err "Failed to parse expiry date '$password_expiry' for $user"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract 'lastchg' field (3rd colon-separated field)
|
||||||
|
lastchg_days="$(echo "$shadow_entry" | cut -d: -f3)"
|
||||||
|
if [ -z "$lastchg_days" ] || [ "$lastchg_days" = "0" ]; then
|
||||||
|
log_err "No valid last password change date for $user, skipping"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert lastchg_days to epoch seconds
|
||||||
|
lastchg_epoch=$(( lastchg_days * 86400 ))
|
||||||
|
|
||||||
|
# Compute difference in days between expiry and last change
|
||||||
|
expiry_days=$(( (expiry_epoch - lastchg_epoch) / 86400 ))
|
||||||
|
# round up to full day, because of this expiry_days can never be 0, but I think that is a non-issue
|
||||||
|
expiry_days=$(( expiry_days + 1 ))
|
||||||
|
|
||||||
|
if [ "$expiry_days" -lt 0 ]; then
|
||||||
|
log_err "Expiry date for $user ($password_expiry) is before last password change, skipping"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
max_days="$expiry_days"
|
||||||
|
|
||||||
|
# Apply update if changed
|
||||||
|
if [ "$current_max_days" != "$max_days" ]; then
|
||||||
|
chage -M "$max_days" "$user"
|
||||||
|
log "Updated max_days for $user to $max_days (expiry=$password_expiry, lastchg_days=$lastchg_days)"
|
||||||
|
else
|
||||||
|
log "max_days for $user already set to $max_days (expiry=$password_expiry), no change"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
handle_security_policy() {
|
handle_security_policy() {
|
||||||
local auth_enabled enabled
|
local auth_enabled enabled
|
||||||
|
|
||||||
|
config_load users
|
||||||
|
config_foreach update_password_expiry user
|
||||||
|
|
||||||
# Read UCI values
|
# Read UCI values
|
||||||
auth_enabled="$(uci -q get users.users.auth_policy_enable || echo 0)"
|
auth_enabled="$(uci -q get users.users.auth_policy_enable || echo 0)"
|
||||||
enabled="$(uci -q get users.authentication_policy.enabled || echo 0)"
|
enabled="$(uci -q get users.authentication_policy.enabled || echo 0)"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue