diff options
Diffstat (limited to 'meta-phosphor/recipes-extended')
9 files changed, 154 insertions, 11 deletions
diff --git a/meta-phosphor/recipes-extended/libpwquality/libpwquality/pwquality.conf b/meta-phosphor/recipes-extended/libpwquality/libpwquality/pwquality.conf new file mode 100644 index 0000000000..048c0fd7d5 --- /dev/null +++ b/meta-phosphor/recipes-extended/libpwquality/libpwquality/pwquality.conf @@ -0,0 +1,7 @@ +enforce_for_root +minlen=8 +difok=0 +lcredit=0 +ocredit=0 +dcredit=0 +ucredit=0 diff --git a/meta-phosphor/recipes-extended/libpwquality/libpwquality_%.bbappend b/meta-phosphor/recipes-extended/libpwquality/libpwquality_%.bbappend new file mode 100644 index 0000000000..5986567c95 --- /dev/null +++ b/meta-phosphor/recipes-extended/libpwquality/libpwquality_%.bbappend @@ -0,0 +1,12 @@ +EXTRA_OECONF:append = " --enable-python-bindings=no" +RDEPENDS:${PN}:remove:class-target = " ${PYTHON_PN}-core" + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += " \ + file://pwquality.conf \ + " + +do_install:append() { + install -d ${D}/etc/security + install -m 0644 ${WORKDIR}/pwquality.conf ${D}/etc/security +} diff --git a/meta-phosphor/recipes-extended/pam/libpam/convert-pam-configs.service b/meta-phosphor/recipes-extended/pam/libpam/convert-pam-configs.service new file mode 100644 index 0000000000..099a5c6e07 --- /dev/null +++ b/meta-phosphor/recipes-extended/pam/libpam/convert-pam-configs.service @@ -0,0 +1,10 @@ +[Unit] +Description=Convert PAM config files + +[Service] +RemainAfterExit=yes +Type=oneshot +ExecStart=/usr/bin/convert-pam-configs.sh + +[Install] +WantedBy=multi-user.target diff --git a/meta-phosphor/recipes-extended/pam/libpam/convert-pam-configs.sh b/meta-phosphor/recipes-extended/pam/libpam/convert-pam-configs.sh new file mode 100755 index 0000000000..27ec218682 --- /dev/null +++ b/meta-phosphor/recipes-extended/pam/libpam/convert-pam-configs.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# Convert OpenBMC linux-PAM config files + +# Location of config files this script modifies: +# PAM_CONF_DIR - path to the PAM config files +# SECURITY_CONF_DIR - path to the security config files +PAM_CONF_DIR=/etc/pam.d +SECURITY_CONF_DIR=/etc/security + +# Handle common-password: +# Change cracklib to pwquality and handle the minlen parameter +pam_cracklib=$(grep "^password.*pam_cracklib.so" ${PAM_CONF_DIR}/common-password) +if [ -n "${pam_cracklib}" ] +then + echo "Changing ${PAM_CONF_DIR}/common-password to use pam_pwquality.so (was pam_cracklib.so)" >&2 + minlen=$(echo "${pam_cracklib}" | sed -e "s/.*minlen=\([[:alnum:]]*\).*/\1/") + echo " Converting parameter minlen=${minlen} to ${SECURITY_CONF_DIR}/pwquality.conf minlen" >&2 + sed -i.bak -e "s/^minlen=.*/minlen=$minlen/" ${SECURITY_CONF_DIR}/pwquality.conf + pwquality='password [success=ok default=die] pam_pwquality.so debug' + sed -i.bak -e "s/^password.*pam_cracklib.so.*/$pwquality/" ${PAM_CONF_DIR}/common-password + echo "# This file was converted by $0" >>${PAM_CONF_DIR}/common-password +fi + +# Handle common-auth: +# Change tally2 to faillock and handle the deny & unlock_time parameters +pam_tally2=$(grep "^auth.*pam_tally2.so" ${PAM_CONF_DIR}/common-auth) +if [ -n "${pam_tally2}" ] +then + echo "Changing ${PAM_CONF_DIR}/common-auth to use pam_faillock.so (was pam_tally2.so)" >&2 + deny=$(echo "${pam_tally2}" | sed -e "s/.*deny=\([[:alnum:]]*\).*/\1/") + unlock_time=$(echo "${pam_tally2}" | sed -e "s/.*unlock_time=\([[:alnum:]]*\).*/\1/") + # Change faillock.conf parameters + echo " Converting parameter deny=${deny} to ${SECURITY_CONF_DIR}/faillock.conf deny" >&2 + echo " Converting parameter unlock_time=${unlock_time} to ${SECURITY_CONF_DIR}/faillock.conf unlock_time" >&2 + sed -i.bak \ + -e "s/^deny=.*/deny=$deny/" \ + -e "s/^unlock_time=.*/unlock_time=$unlock_time/" \ + ${SECURITY_CONF_DIR}/faillock.conf + # Change pam_tally2 to pam_faillock (changes the overall auth stack) + authfail='auth [default=die] pam_faillock.so authfail' + authsucc='auth sufficient pam_faillock.so authsucc' + sed -i.bak \ + -e "/^auth.*pam_tally2.so.*$/d" \ + -e "/^auth.*pam_deny.so/i $authfail\n$authsucc" \ + ${PAM_CONF_DIR}/common-auth + echo "# This file was converted by $0" >>${PAM_CONF_DIR}/common-auth +fi + diff --git a/meta-phosphor/recipes-extended/pam/libpam/faillock.conf b/meta-phosphor/recipes-extended/pam/libpam/faillock.conf new file mode 100644 index 0000000000..dba79c450a --- /dev/null +++ b/meta-phosphor/recipes-extended/pam/libpam/faillock.conf @@ -0,0 +1,2 @@ +deny=0 +unlock_time=0 diff --git a/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-account b/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-account index 82449cad03..9a739ecde2 100644 --- a/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-account +++ b/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-account @@ -18,7 +18,8 @@ account [success=2 new_authtok_reqd=done default=ignore] pam_unix.so -account [success=1 new_authtok_reqd=done default=ignore] pam_ldap.so ignore_unknown_user ignore_authinfo_unavail # here's the fallback if no module succeeds account requisite pam_deny.so -account required pam_tally2.so +# Announce if faillock is blocking access +account required pam_faillock.so # prime the stack with a positive return value if there isn't one already; # this avoids us returning an error just because nothing sets a success code # since the modules above will each just jump around diff --git a/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-auth b/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-auth index 8eef164d12..c051ab7e67 100644 --- a/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-auth +++ b/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-auth @@ -8,14 +8,19 @@ # traditional Unix authentication mechanisms. # here are the per-package modules (the "Primary" block) -auth [success=ok user_unknown=ignore default=2] pam_tally2.so deny=0 unlock_time=0 # Try for local user first, and then try for ldap auth [success=2 default=ignore] pam_unix.so quiet -auth [success=1 default=ignore] pam_ldap.so ignore_unknown_user ignore_authinfo_unavail -# here's the fallback if no module succeeds -auth requisite pam_deny.so +# Control gets here when no authentication module succeeds. Increment the +# failure tally and return failure status to PAM. +auth [default=die] pam_faillock.so authfail +# Control gets here when authentication succeeds. Check if the user is locked +# out due to consecutive authentication failures and return status accordingly. +auth sufficient pam_faillock.so authsucc +# If authsucc failed, deny access +auth requisite pam_deny.so # prime the stack with a positive return value if there isn't one already; # this avoids us returning an error just because nothing sets a success code # since the modules above will each just jump around -auth required pam_permit.so +auth required pam_permit.so # and here are more per-package modules (the "Additional" block) diff --git a/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-password b/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-password index ef706f3080..2fc4011b26 100644 --- a/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-password +++ b/meta-phosphor/recipes-extended/pam/libpam/pam.d/common-password @@ -10,13 +10,10 @@ # The "sha512" option enables salted SHA512 passwords. Without this option, # the default is Unix crypt. Prior releases used the option "md5". # -# The "obscure" option replaces the old `OBSCURE_CHECKS_ENAB' option in -# login.defs. -# # See the pam_unix manpage for other options. # here are the per-package modules (the "Primary" block) -password [success=ok default=die] pam_cracklib.so debug enforce_for_root reject_username minlen=8 difok=0 lcredit=0 ocredit=0 dcredit=0 ucredit=0 +password [success=ok default=die] pam_pwquality.so debug password [success=ok default=die] pam_ipmicheck.so spec_grp_name=ipmi use_authtok password [success=ok ignore=ignore default=die] pam_pwhistory.so debug enforce_for_root remember=0 use_authtok password [success=ok default=die] pam_unix.so sha512 use_authtok diff --git a/meta-phosphor/recipes-extended/pam/libpam_%.bbappend b/meta-phosphor/recipes-extended/pam/libpam_%.bbappend index 658dc0beec..d9ffdac9b0 100644 --- a/meta-phosphor/recipes-extended/pam/libpam_%.bbappend +++ b/meta-phosphor/recipes-extended/pam/libpam_%.bbappend @@ -4,19 +4,80 @@ SRC_URI += " file://pam.d/common-password \ file://pam.d/common-account \ file://pam.d/common-auth \ file://pam.d/common-session \ + file://faillock.conf \ + file://convert-pam-configs.service \ + file://convert-pam-configs.sh \ " +inherit systemd +SYSTEMD_SERVICE:${PN} += "convert-pam-configs.service" + +FILES:${PN} += "${bindir}/convert-pam-configs.sh \ + ${systemd_system_unitdir}/convert-pam-configs.service \ + " + do_install:append() { # The libpam recipe will always add a pam_systemd.so line to # common-session if systemd is enabled; however systemd only # builds pam_systemd.so if logind is enabled, and we disable # that package. So, remove the pam_systemd.so line here. sed -i '/pam_systemd.so/d' ${D}${sysconfdir}/pam.d/common-session + + install -d ${D}/etc/security + install -m 0644 ${WORKDIR}/faillock.conf ${D}/etc/security + + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/convert-pam-configs.sh ${D}${bindir} + + install -d ${D}${systemd_system_unitdir} + install -m 0644 ${WORKDIR}/convert-pam-configs.service ${D}${systemd_system_unitdir} } -RDEPENDS:${PN}-runtime += "${MLPREFIX}pam-plugin-cracklib-${libpam_suffix} \ - ${MLPREFIX}pam-plugin-tally2-${libpam_suffix} \ +RDEPENDS:${PN}-runtime += "libpwquality \ + ${MLPREFIX}pam-plugin-faillock-${libpam_suffix} \ ${MLPREFIX}pam-plugin-pwhistory-${libpam_suffix} \ ${MLPREFIX}pam-plugin-succeed-if-${libpam_suffix} \ ${MLPREFIX}pam-plugin-localuser-${libpam_suffix} \ " + +# +# Background: +# 1. Linux-PAM modules tally2 and cracklib were removed in libpam_1.5, +# which prompted OpenBMC to change to the faillock and pwquality modules. +# The PAM config files under /etc/pam.d were changed accordingly. +# 2. OpenBMC implementations store Redfish property values in PAM config files. +# For example, the D-Bus property maxLoginAttemptBeforeLockout is stored in +# /etc/pam.d/common-auth as the pam_tally2.so deny= parameter value. +# 3. The /etc directory is readonly and has a readwrite overlayfs. That +# means when a config file changes, an overlay file is created which hides +# the readonly version. +# +# Problem scenario: +# 1. Begin with a BMC that has a firmware image which has the old PAM +# modules and the old PAM config files which have modified parameters. +# For example, there is an overlay file for /etc/pam.d/common-auth. +# 2. Perform a firmware update to a firmware image which has the new PAM +# modules. The updated image will have not have the old PAM modules. +# It will have the new PAM config files in its readonly file system and +# the old PAM config files in its readwrite overlay. +# 3. Note that PAM authentication will always fail at this point because +# the old PAM config files in the overlay tell PAM to use the old PAM +# modules which are not present on the system. +# +# Two possible recoveries are: +# A. Factory reset the BMC. This will clear the readwrite overlay, +# allowing PAM to use the readonly version. +# B. Convert the old PAM config files to the new style. See below. +# +# Service: The convert-pam-configs.service updates the old-style PAM config +# files on the BMC: it changes uses of the old modules to the new modules +# and carries forward configuration parameters. A key point is that files +# are written to *only* as needed to convert uses of the old modules to the +# new modules. See the conversion tool for details. +# +# This service can be removed when the BMC no longer supports a direct +# firware update path from a version which has the old PAM configs to a +# version which has the new PAM configs. +# +# In case of downgrade, Factory reset is recommended. Current logic in existing +# images won't be able to take care of these settings during downgrade. |