WEB开发网
开发学院操作系统Linux/Unix 密码维护:使用 chpasswd 和 pwgen 阅读

密码维护:使用 chpasswd 和 pwgen

 2010-06-18 00:00:00 来源:WEB开发网   
核心提示:在迁移用户时,应该提供初始密码,密码维护:使用 chpasswd 和 pwgen,然后,用户通常通过电子邮件或电话得知新密码,pwgen 生成的密码是不容易猜测的单词,因此确保新密码的安全性更好,如果启用了安全密码策略规则,当用户登录时

在迁移用户时,应该提供初始密码。然后,用户通常通过电子邮件或电话得知新密码。如果启用了安全密码策略规则,当用户登录时,会提示他们修改密码。还可以通过特殊请求要求用户在本地或远程重新设置账户密码。完成这些密码更改要花费不少时间,而且是重复性的。但是,通过使用 AIX 实用程序 chpasswd(Linux 系统也附带这个工具),可以简便地重复执行这些任务。

但是,选择良好的密码是另一个问题。把多个密码同时更改或重新设置为词典单词甚至用户名很容易,但这不是良好的密码策略。密码应该很容易记住,用户不需要把它写下来。一些人认为对于普通用户账户使用随机密码是良好的安全策略。我认为,只有在用户能够记住自己的密码的前提下,这才是好策略。如果用户把密码写在便条上,他们很可能把便条放在便于拿到的地方,比如贴在桌子下面或放在抽屉里面。潜在的入侵者很容易在这些地方找到用户的密码。

对于系统管理员或希望生成密码的用户来说,可以使用实用程序 pwgen 生成可发音和不可发音的密码。pwgen 可以生成一个或多个密码,可以指定不同的密码长度,可以指定必须包含大写字母或数字。

在本文中,我将演示 chpasswd 和 pwgen 的用法,以及如何以交互或批处理方式使用它们处理密码更改。我是在几年前把用户迁移到 LDAP 环境时首次接触到 chpasswd 的。现在,我经常使用它以非交互方式更改本地或远程账户密码。

使用 chpasswd

可以使用 chpasswd 方便地更改单个或多个账户密码。这意味着不需要像平时一样在命令行上重复输入密码。尽管可以以交互方式使用 chpasswd,但是我建议以非交互方式使用它。使用 chpasswd 是一种快速更改密码的方法。

使用 chpasswd 的格式是:

chpasswd -f <pwdadm flags> -c

其中:
-f 可以解析 pwdadm 标志
-c 清除密码标志

从标准输入读取以下格式的用户名和密码:

user_name:user_password 

假设我们希望创建三个用户账户,用户名分别是 alpha、bravo 和 charlie。

这些账户上还没有设置密码,可以通过查询 /etc/passwd 文件和执行 pwdadm 命令看出这一点:

# tail /etc/passwd 
alpha:*:209:1:alpha.apps:/home/alpha:/usr/bin/ksh 
bravo:*:210:1:bravo.suppt:/home/bravo:/usr/bin/ksh 
charlie:*:211:1:charlie.suppt:/home/charlie:/usr/bin/ksh 

注意,passwd 文件中的第二栏是 '*',这表明还没有设置密码。通过用 pwdadm 命令查询用户也可以确认这一情况:

 # pwdadm -q alpha 
alpha: 

因为没有设置密码,所以没有产生输出。如果有密码,'lastupdate' 字段的值应该是设置密码时的 UTC 时间戳。

我将演示使用 chpasswd 为这些用户设置初始密码的两种方法。在下面的示例中,在命令行上回显用户名 alpha 和密码 mypasswd,然后通过管道连接到 chpasswd:

echo "alpha:mypasswd" | chpasswd 

还可以把登录名和密码信息包含在一个字符串中,然后通过管道连接到 chpasswd,如下所示:

# detail="charlie:charpw" 
echo $detail | chpasswd 

现在,通过 pwdadm 查询用户 alpha,可以看到已经设置了标志值 ADMCHG,这是重新设置密码时 chpasswd 的默认设置:

# pwdadm -q alpha 
alpha: 
    lastupdate = 1265765265 
    flags = ADMCHG 

ADMCHG 表示当用户 alpha 下一次尝试用设置的初始密码 (mypasswd) 登录时,会强迫用户 alpha 更改密码。这也适用于设置了 ADMCHG 标志的其他账户。

还可以用保存在文件中的信息更改密码。例如,考虑 pass 文件中的以下内容:

# cat pass 
bravo:bravpass 
charlie:charpass 

在前面的 pass 文件中,用户 bravo 将把密码改为 bravpass,用户 charlie 将把密码改为 charpass。要想执行密码更改,只需对这个文件执行 cat 并通过管道连接到 chpasswd,如下所示:

# cat pass | chpasswd 

还可以把文件重定向到 chpasswd 进行处理。在这个示例中,通过指定 'c-' 选项(清除密码标志),指定用户 bravo 和 charlie 不必更改密码,如下所示:

# chpasswd -c < pass 

使用 pwdadm 查询用户 charlie,会产生以下输出:

# pwdadm -q charlie 
charlie: 
    lastupdate = 1265853052 

注意 chpasswd 命令中的清除标志选项;它清除字段中的所有标志值。

pwdadm 输出中的 lastupdate 值表示最近设置或更改密码的时间。以秒为单位的 UTC 时间戳需要转换为更有意义的日期时间戳。

下面两个命令都返回最近更新或初始设置密码的时间(如果有密码的话)。在这个示例中,查询用户 alpha 最近的密码更新:

# lssec -f /etc/security/passwd -s alpha -a lastupdate 
alpha lastupdate=1265940457 
 
# pwdadm -q alpha 
alpha: 
    lastupdate = 1265940457 
    flags = ADMCHG

可以使用 perl 或 gawk 把 UTC 转换为日期时间戳,下面两个示例产生相同的结果:

# perl -e 'use POSIX;print ctime(1265940457)' 
Thu Feb 11 20:07:37 2010 
 
 
# gawk 'BEGIN {print strftime("%c",1265940457)}' 
Thu Feb 11 20:07:37 GMT 2010

安装 pwgen

pwgen 源代码的当前版本是 2.0.6。二进制版本是 2.0.5。在这里,我将使用源代码。

下载源代码之后,解压并编译它:

# gunzip pwgen-2.06.tar.gz 
# tar -xvf pwgen-2.06.tar 
# cd pwgen-2.06 
#./configure 
# make 
# make install 

pwgen 二进制代码将安装在 /usr/local/bin 中。

使用 pwgen

pwgen 可以生成难以记住的随机密码或容易记住的密码。可以以交互方式使用它,也可以通过脚本以批模式使用它。

在默认情况下,pwgen 向标准输出发送许多密码。一般来说,我们不需要这种结果;但是,如果希望选择要手工输入的一次性密码,这种输出是有用的。在生成密码时,pwgen 在默认情况下尝试在密码中包含数字和大写字母。

格式是:

pwgen <options> <password_length> <number_of_passwords>

常用选项是:

-1每行输出一个密码
-c必须包含大写字母
-n必须包含数字
-s随机密码

以下命令输出一个 8 字符的密码:

# pwgen 8 1 
eej3eeZu 

以下命令输出三个 7 字符的密码并要求必须使用一个大写字母:

# pwgen -c 7 3
ohw4Aj7 Pei0obe gaw4De4 

以下命令输出 10 个 8 字符的密码并要求必须使用一个大写字母和数字:

# pwgen -c -n 8 10 
zum5Shei Choo6Eih Ub5uagei Ooxu6ohs Eix9xeip iV4yoeph Io3aeGhe taiTh6ia 
cuere1AW phai9Pai 

pwgen 会判断您是否通过 tty 执行它。如果不是,它在默认情况下(不传递选项)只生成一个密码。这便于脚本把值存储在变量中,如下所示:

# pass=$(pwgen) 
# echo $pass 
ohtherah 

如果愿意,可以使用反撇号进行命令替换。以下命令产生相同的结果:

        pass=`pwgen` 
        # echo $pass 
        oowahxei 

当然,可以包含任意数量的密码。在下面的示例中,生成三个密码:

# pass=$(pwgen -c -n 8 3) 
# echo $pass 
EluBie0z thohku0W Ail3fu3z 

下面的命令生成一个真正随机的 8 字符密码:

# pwgen -s 8 1 
9bTzZxt9 

在使用随机选项时(像前一个示例一样),应该注意一点:这些密码很难记住,如果把它们分配给用户,用户很可能会把它们写下来。根据我的经验,应该只对应用程序所有者账户使用随机生成的密码。

结合使用

既然我们已经看到了 chpasswd 和 pwgen 的效果,现在就开始为用户设置初始密码。这显然必须通过 清单 1 这样的脚本来完成。首先,获取需要设置密码的用户的列表;这个列表可以包含在一个文件中(但是这里把用户包含在字符串 $list 中,其中包含三个用户)。在循环处理每个用户时,使用以下命令为每个用户生成一个 8 字符的密码:

pwgen 8 1 

第一个检查确认 AIX 主机上是否存在这个用户账户。如果存在,就按照 chpasswd 所需的格式把用户名和生成的密码追加到 passfile 文件中。处理完所有用户之后,通过管道把这个文件连接到 chpasswd。如果用户在 /etc/passwd 中不存在,passfile 中就没有此用户的用户名/密码条目。

清单 1. setpass

#!/bin/sh 
# setpass 
 
passfile=/home/dxtans/passfile 
>$passfile 
 
list="alpha bravo charlie" 
 
for user in $list 
 do 
  if ! grep -w ^$user /etc/passwd > /dev/null 
  then 
  echo "user NOT present: $user" 
 else 
  echo "user present: $user" 
 pass=$(pwgen 8 1) 
 echo "$user:$pass">>$passfile 
 fi 
done 
cat $passfile | chpasswd 

运行脚本 setpass 之后,生成包含以下内容的 passfile 文件:

# cat passfile 
alpha:jiebuzio 
bravo:oegaeyay 
charlie:ooweipoa 

在下一个示例中(见 清单 2),创建用户 foxtrot 和初始密码并修改登录属性。create_user 脚本演示使用 pwgen 设置密码的一种方式。在这个示例中,密码设置为 8 个字符,包含至少一个大写字母和一个数字:

pwgen -c -n 8 1 

首先,创建用户 foxtrot 并把 su 设置为 false。然后,为这个用户账户设置密码,清除所有密码限制标志(这意味着用户 foxtrot 在登录时不会提示他更改密码)。然后设置 gecos 字段,把变量 $user 展开成 foxtrot,在展开的变量后面添加 "apps"。把 maxage 设置为 5,这意味着在前一次更改或设置密码 5 周之后,会迫使用户 foxtrot 更改密码。把 minage 设置为 1,这意味着在一周内用户 foxtrot 不能再次更改密码。最后,设置组成员,即主组为 staff(这是 AIX 的默认设置)。

清单 2. create_user

#!/bin/sh 
# create_user 
 
user="foxtrot" 
pass=$(pwgen -c -n 8 1) 
echo "the passwd for $user is: $pass" 
 
echo "creating user $user..creating password" 
mkuser su=false $user 
 if [ $? = 0 ] 
 then 
  echo "$user:$pass" | chpasswd -c 
 else 
  echo "error: unable to create user $user" 
  exit 1 
 fi 
echo "changing $user attributes..." 
 chuser gecos="${user}.apps" $user 
 chuser maxage=5 $user 
 chuser minage=1 $user 

执行脚本 create_user 时,输出是:

# create_user 
the passwd for foxtrot is: oiN2hi9r 
creating user foxtrot..creating password 
changing foxtrot attributes... 

通过使用 pwdadm 命令,可以看出密码标志已经清除了:

# pwdadm -q foxtrot 
foxtrot: 
    lastupdate = 1266174412 

应该经常更改根密码,这是一项审计要求。按我的观点,最好的方式是作为根用户通过 ssh 连接每个主机,然后更改密码。但是注意,我们绝不希望忘记这个密码。因此,最好先在本地用 pwgen 生成这个密码,在脚本中硬编码它,执行脚本并把密码保存在安全的物理位置(比如保险柜)之后从脚本中删除密码。不要忘了将新密码告诉其他系统管理员。

一种好做法是把要远程连接的所有主机包含在一个文件中。采用这种方法意味着其他脚本可以读取这个文件,不需要在脚本中手工输入它们。包含主机的典型文件可以采用以下格式:

# cat all_hosts 
host1 
host2 
host3 
host.. 

清单 3 展示了一种简便的方法。已经用 pwgen 生成了密码,密码是 'tu8ahLae'。对于要连接的每个主机(从 all_hosts 文件读取),使用 here document 方法。这意味着包含在单词 'mayday' 之间的所有命令在远程主机上被读取为标准输入。字符串 root:tu8ahLae 通过管道传递给 chpasswd,如下所示:

echo "root:tu8ahLae" | chpasswd 

清单 3. chpw_root

#!/bin/sh 
cat all_hosts | while read host 
do 
echo "[$host]″ 
 
ssh -T -t -l root $host<<'mayday' 
hostname 
 
echo "root:tu8ahLae" | chpasswd 
 if [ $? != 0 ] 
then 
echo " password of root change failed $host" 
 else 
echo " password of root change OK" 
fi 
mayday 
done 

chpw_root 脚本假设 ssh 密钥已经从远程主机交换到了驻留脚本的主机。

通知用户

清单 2 中的脚本创建一个用户并设置初始密码,但是将新密码通知给用户是个手工任务。这常常需要把身份验证信息复制并粘贴到电子邮件中,然后向用户发送电子邮件,或者通过电话通知他们。更自动化的方法是直接从脚本向用户发送电子邮件。为此,必须建立一个把用户与电子邮件地址关联起来的过程。可以考虑采用的一种方法是使用一个包含用户 ID 和相应电子邮件地址的文件。另一种方法是把用户的电子邮件地址放在 /etc/password 文件中的 gecos 字段中,采用 <first_name>.<last_name>@<domain> 形式。

dxtans:!:203:1:david.tansley@btinternet.com:/home/dxtans:/usr/bin/ksh 

但是,这种方法会增加输入量,尤其是在有许多 AIX 系统的情况下,所以应该只在管理少量系统的情况下考虑采用它。

另一种方法是使用全局的查找文件(我认为这种方法更方便,而且不需要管理 /etc/passwd 文件)。这个文件包含所有可登录用户及其电子邮件地址的列表,如下所示:

# cat email_lookup 
alpha  alpha.apps@mycompany.com 
bravo  bravo.suppt@mycompany.com 
charlie charlie.suppt@mycompany.com 

全局文件 email_lookup 包含所有用户名和电子邮件账户,可以把它传输到所有系统上。只更新一个全局文件方便得多,只需在添加或删除用户时更新它,然后再次通过 scp 把它传输到所有系统。如果在放置 email_lookup 文件的远程系统上没有某个用户,也没关系,因为既然这个用户不存在,在更改密码时就不会查找他。

清单 4 中的脚本使用前面的 email_lookup 文件寻找用户名和相应的电子邮件地址,然后通知用户账户的更改情况。它从前面生成的 passfile 文件读取用户名和密码,然后通过检查 /etc/passwd 确认这是有效的账户。如果一切正常,那么从 email_lookup 文件中提取出用户的电子邮件地址。脚本假设已经运行了 chpasswd,登录名和密码已经保存在 passfile 文件中了。理想情况下,脚本还应该包含 chpasswd 和 pwgen 例程,以便方便地更改密码。目前,清单 4 中的脚本说明在重新设置或更改密码之后如何自动地通过电子邮件通知用户。

清单 4. email_user

#!/bin/sh 
passfile=/home/dxtans/passfile 
email_lookup=/home/dxtans/email_lookup 
 
IFS=":" 
cat $passfile | while read user pass 
do 
  if grep -w ^$user /etc/passwd >/dev/null 
   then 
    echo "$user - found" 
    email_name=$(grep -w ^$user $email_lookup | awk '{print $2}') 
     if [ "$email_name" = "" ] 
      then 
      echo "lookup failed for this user:$user" 
     fi 
    mail -s "`hostname` account change" $email_name<<mayday 
your account: $user 
new password: $pass 
mayday 
 
  else 
    echo "$user - NOT found" 
fi 
 done 

结束语

系统管理员可以通过结合使用 chpasswd 和 pwgen 自动地设置用户密码。pwgen 生成的密码是不容易猜测的单词,因此确保新密码的安全性更好。我还推荐了两种通知用户密码更改的方法。

Tags:密码 维护 使用

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接