目录
passwd shadow文件介绍
shadow文件格式
生成密码方式
1. openssl生成
2. chpasswd
3. crypt函数
4. passwd
5. python crypt库
在unix早些时候是没有/etc/shadow这个文件的。用户的所有信息都只是保存在/etc/passwd文件中,加密后的用户密码保存在了passwd文件的第二个字段中。那么为什么要产生shadow文件呢? 我们看一下文件的权限,
-rw-r--r-- 1 root root 2313 12月 4 14:03 /etc/passwd
-rw-r----- 1 root shadow 1356 12月 5 15:59 /etc/shadow
可以看出,passwd对每个用户都是可读的,那么这不就把用户密码暴露给任何人了么?虽然是加过密的,但是这样也存在安全性问题,于是产生了shadow文件, 将用户的密码加密后存入shadow文件, 而passwd文件仅存放用户名等其他标识, 并对shadow文件的权限进行限制, 只有root用户可读可写.
当普通用户调用/usr/bin/passwd命令修改自己的密码,因为passwd对任何用户都是可执行的,会变身为root,所以此时用户拿着root的权限去读写shadow文件,当命令执行完成后变身结束,便失去root权限。可以看出经过对shadow文件的分离,既保证了普通用户对自己密码的修改,也保证了普通用户看不到加密后的密码串提升了安全性。
它的文件格式与/etc/passwd类似,由若干个字段组成,字段之间用“:”隔开
登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志
ice:$6$5NAhdLZN$PSiSm7IMPVsB6kCoFFVcI5JSPYqzM.c139wesTl/YGl6Z0MqTaTVmbTbWlJQkX11Uvr.sKTT46uO9QYDun87..:18000:0:99999:7:::
1) “登录名”是与/etc/passwd文件中的登录名相一致的用户账号
2) “口令”字段存放的是加密后的用户口令字,如果为空,则对应用户没有口令,登录时不需要口令;
星号代表帐号被锁定,将无法登录;双叹号表示这个密码已经过期了, 如果是$x$xxxxxxxx$的形式,则代表密码正常。
$6$开头的,表明是用SHA-512加密的,密文长度86,示例中‘5NAhdLZN’为salt值,是一个随机字符串,供加密使用
$1$ 表明是用MD5加密的,密文长度22个字符
$2$ 是用Blowfish加密的,
$5$ 是用 SHA-256加密的,密文长度43
3) “最后一次修改时间”表示的是从1970-1-1,到今天修改口令时的天数。
4) “最小时间间隔”指的是两次修改口令之间所需的最小天数。
5) “最大时间间隔”指的是口令保持有效的最大天数。
6) “警告时间”字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
7) “不活动时间”表示的是用户没有登录活动但账号仍能保持有效的最大天数。
8) “失效时间”字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号
1:MD5加密,密文长度22
5:SHA-256加密,密文长度43
6:SHA-512加密,密文长度86
4.手动生成password字串(测试于centos6.5)
方法一:dovecot包中提供dovecotadm命令。
介绍几种通过编程自动修改linux用户密码的方式。
openssl passwd -1 -salt "abcdefgh" "123456" // 指定随机字符串为‘abcdefgh’, 密码为'123456', 注意,-1是数字1, 同样的可以使用-6
$1$abcdefgh$KJHEbEnUJaxWv269o9nH60
将生成的秘钥替换掉shadow相应的行即可
echo ice:123456 | chpasswd //将用户ice的密码修改为‘123456’
chpasswd将直接修改shadow文件
int create_user_password(char *user, char *plain_text)
{
struct spwd *shd = NULL;
char * pwd = NULL;
char salt[64] = {0};
int i=0,j=0;
char rand_str[12] = {0};
if (geteuid() != 0)
{
return -1;
}
shd= getspnam(user);
if(shd != NULL)
{
while(1){
salt[i] = shd->sp_pwdp[i];
if(salt[i] == '$'){
j++;
if(j == 3){
break;
}
}
i++;
}
pwd = (char *)crypt((const char *)plain_text, (const char *)salt);
printf("pwd:%s\n",pwd);
return 0;
}
return -1;
}
其中, plain_text代表密码明文, salt格式: $1$xxxxxxxx$
通过crypt方式,同样需要人为的使用生成的字符串替换shadow中的行.
通过passwd命令来修改密码(该命令需要输入两次密码), 但是如果希望通过编程的方式,来自动化的输入密码,则还需要借助交互工具库expect.
__import__("crypt").crypt("password","$1$abcdefg$")