前言
同事在fedora22-PC版上,配置出了可用的password策略. 输入不合规的口令,会有警告或报错提示.
将同样的配置文件挪到fedora22-powerpc版上,passwd执行后,输入不合规的口令,可以完成口令修改。
我没有找到fedora22原版的passwd工程下载,用的是gnu-shadow-4.5中的passwd工程。
现在怀疑是配置文件条目不同引起的问题(gnu的代码写的刚刚的,也不敢怀疑:))
排错
gdb -tui –args ./passwd user_test
break new_password
run
new_password 中对PASS_ALWAYS_WARN配置项进行了检查
if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN")
&& (!obscure (orig, pass, pw) || reuse (pass, pw))) {
(void) puts (_("\nWarning: weak password (enter it again to use it anyway)."));
warned = true;
continue;
}
检查代码有与的关系, 如果PASS_ALWAYS_WARN 项的bool值不是yes, 后面的检查(obscure(), reuse())不会被执行了,导致口令检查策略失效.
obscure_msg 处判断了login.defs OBSCURE_CHECKS_ENAB yes
到了obscure_msg中, 就可以看到口令检查的全过程。
发现了login.defs 缺OBSCURE_CHECKS_ENAB配置项后,补全了先试了一下,口令检查策略文件已经生效了,就没有再继续观赏剩下的口令检查实现.
bool obscure (const char *old, const char *new, const struct passwd *pwdp)
{
const char *msg = obscure_msg (old, new, pwdp);
if (NULL != msg) {
printf (_("Bad password: %s. "), msg);
return false;
}
return true;
}
static /*@observer@*//*@null@*/const char *obscure_msg (
/*@notnull@*/const char *old,
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
{
size_t maxlen, oldlen, newlen;
char *new1, *old1;
const char *msg;
const char *result;
oldlen = strlen (old);
newlen = strlen (new);
if (newlen < (size_t) getdef_num ("PASS_MIN_LEN", 0)) {
return _("too short");
}
/*
* Remaining checks are optional.
*/
if (!getdef_bool ("OBSCURE_CHECKS_ENAB")) {
return NULL;
}
msg = password_check (old, new, pwdp);
if (NULL != msg) {
return msg;
}
result = getdef_str ("ENCRYPT_METHOD");
if (NULL == result) {
/* The traditional crypt() truncates passwords to 8 chars. It is
possible to circumvent the above checks by choosing an easy
8-char password and adding some random characters to it...
Example: "password$%^&*123". So check it again, this time
truncated to the maximum length. Idea from npasswd. --marekm */
if (getdef_bool ("MD5_CRYPT_ENAB")) {
return NULL;
}
} else {
if ( (strcmp (result, "MD5") == 0)
#ifdef USE_SHA_CRYPT
|| (strcmp (result, "SHA256") == 0)
|| (strcmp (result, "SHA512") == 0)
#endif
) {
return NULL;
}
}
maxlen = (size_t) getdef_num ("PASS_MAX_LEN", 8);
if ( (oldlen <= maxlen)
&& (newlen <= maxlen)) {
return NULL;
}
new1 = xstrdup (new);
old1 = xstrdup (old);
if (newlen > maxlen) {
new1[maxlen] = '\0';
}
if (oldlen > maxlen) {
old1[maxlen] = '\0';
}
msg = password_check (old1, new1, pwdp);
memzero (new1, newlen);
memzero (old1, oldlen);
free (new1);
free (old1);
return msg;
}
最后修正的配置文件
etc/login.defs
必须有的2项配置
PASS_ALWAYS_WARN yes
OBSCURE_CHECKS_ENAB yes
如果没有这2项,不继续向后检查口令是否符合策略要求了.
完整配置文件
#
# Please note that the parameters in this configuration file control the
# behavior of the tools from the shadow-utils component. None of these
# tools uses the PAM mechanism, and the utilities that use PAM (such as the
# passwd command) should therefore be configured elsewhere. Refer to
# /etc/pam.d/system-auth for more information.
#
# *REQUIRED*
# Directory where mailboxes reside, _or_ name of file, relative to the
# home directory. If you _do_ define both, MAIL_DIR takes precedence.
# QMAIL_DIR is for Qmail
#
#QMAIL_DIR Maildir
MAIL_DIR /var/spool/mail
#MAIL_FILE .mail
# Password aging controls:
#
# PASS_MAX_DAYS Maximum number of days a password may be used.
# PASS_MIN_DAYS Minimum number of days allowed between password changes.
# PASS_MIN_LEN Minimum acceptable password length.
# PASS_WARN_AGE Number of days warning given before a password expires.
#
PASS_MAX_DAYS 99999
PASS_MIN_DAYS 0
PASS_MIN_LEN 5
PASS_WARN_AGE 7
PASS_ALWAYS_WARN yes
OBSCURE_CHECKS_ENAB yes
#
# Min/max values for automatic uid selection in useradd
#
UID_MIN 1000
UID_MAX 60000
# System accounts
SYS_UID_MIN 201
SYS_UID_MAX 999
#
# Min/max values for automatic gid selection in groupadd
#
GID_MIN 1000
GID_MAX 60000
# System accounts
SYS_GID_MIN 201
SYS_GID_MAX 999
#
# If defined, this command is run when removing a user.
# It should remove any at/cron/print jobs etc. owned by
# the user to be removed (passed as the first argument).
#
#USERDEL_CMD /usr/sbin/userdel_local
#
# If useradd should create home directories for users by default
# On RH systems, we do. This option is overridden with the -m flag on
# useradd command line.
#
CREATE_HOME yes
# The permission mask is initialized to this value. If not specified,
# the permission mask will be initialized to 022.
UMASK 077
# This enables userdel to remove user groups if no members exist.
#
USERGROUPS_ENAB yes
# Use SHA512 to encrypt password.
ENCRYPT_METHOD MD5
MD5_CRYPT_ENAB yes
/etc/pam.d/system-auth
这个配置文件可能是 /etc/pam.d/system-auth-ac 的软连接
这配置文件没动,本身就是正确的. 加了口令校验配置项.
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 1000 quiet_success
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 1000 quiet
account required pam_permit.so
password requisite pam_cracklib.so retry=2 difok=10 minlen=6 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 enforce_for_root
#password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
-session optional pam_systemd.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
总结
开源软件是好,只要解决了编译问题,编译用-g选项不带-O2, 有个gdb, 有啥问题都可以单步明白。