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
|
||||
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
|
||||
bool "Exposes vendor datamodel extensions for AuthenticationPolicy"
|
||||
bool "Expose vendor datamodel extensions."
|
||||
default y
|
||||
help
|
||||
Enable this option to expose TR181 vendor extensions for AuthenticationPolicy.
|
||||
Enable this option to expose TR181 vendor extensions.
|
||||
|
||||
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"
|
||||
default ""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=usermngr
|
||||
PKG_VERSION:=1.4.5
|
||||
PKG_VERSION:=1.4.6
|
||||
|
||||
LOCAL_DEV:=0
|
||||
ifneq ($(LOCAL_DEV),1)
|
||||
PKG_SOURCE_PROTO:=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_MIRROR_HASH:=skip
|
||||
endif
|
||||
|
|
@ -36,6 +36,7 @@ define Package/usermngr
|
|||
DEPENDS+=+@USERMNGR_SECURITY_HARDENING:BUSYBOX_CONFIG_PAM
|
||||
DEPENDS+=+USERMNGR_SECURITY_HARDENING:linux-pam
|
||||
DEPENDS+=+USERMNGR_SECURITY_HARDENING:passwdqc
|
||||
DEPENDS+=+USERMNGR_ENABLE_VENDOR_EXT:shadow-chage
|
||||
TITLE:=Package to add Device.Users. datamodel support
|
||||
endef
|
||||
|
||||
|
|
@ -57,8 +58,8 @@ ifeq ($(CONFIG_USERMNGR_SECURITY_HARDENING),y)
|
|||
MAKE_FLAGS += USERMNGR_SECURITY_HARDENING=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USERMNGR_ENABLE_AUTH_VENDOR_EXT),y)
|
||||
MAKE_FLAGS += USERMNGR_ENABLE_AUTH_VENDOR_EXT=y
|
||||
ifeq ($(CONFIG_USERMNGR_ENABLE_VENDOR_EXT),y)
|
||||
MAKE_FLAGS += USERMNGR_ENABLE_VENDOR_EXT=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USERMNGR_VENDOR_PREFIX),"")
|
||||
|
|
|
|||
|
|
@ -16,10 +16,18 @@ REQUIRED_MODULES="
|
|||
/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() {
|
||||
for mod in $REQUIRED_MODULES; do
|
||||
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
|
||||
fi
|
||||
done
|
||||
|
|
@ -41,7 +49,7 @@ compare_and_replace() {
|
|||
|
||||
if [ ! -f "$dst" ] || ! cmp -s "$src" "$dst"; then
|
||||
cp "$src" "$dst"
|
||||
logger -t pam_policy_setup "Updated $dst"
|
||||
log "Updated $dst"
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -165,9 +173,87 @@ update_account() {
|
|||
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() {
|
||||
local auth_enabled enabled
|
||||
|
||||
config_load users
|
||||
config_foreach update_password_expiry user
|
||||
|
||||
# Read UCI values
|
||||
auth_enabled="$(uci -q get users.users.auth_policy_enable || echo 0)"
|
||||
enabled="$(uci -q get users.authentication_policy.enabled || echo 0)"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue