对于linux运维人员来说,大部分人应该都知道/etc/passwd和/etc/shadow两个文件,分别存储的是linux用户的用户名以及密码等数据。实际,大部分情况下/etc/shadow才是存放密码的文件,而不是/etc/passwd。
先看下/etc/passwd文件的格式,以下截图为/etc/passwd部分内容:
再看下/etc/shadow文件内容,以下截图为/etc/shadow部分内容:
重点看maun:后面的三个$内容,即$1$DW$VL**
这三个$分别对应的是:加密算法、salt内容、加密后的密码。
目前支持的加密算法有三种:分别是MD5、SHA256和SHA512,分别对应的是1、5和6
注:实际这里不应该叫加密算法,因为MD5只是一种编码格式。但shadow源码里的函数命名就是encrypt(加密),所以这里就认为它是加密算法吧。
本文将通过修改用户密码来阐述linux的密码管理。
Linux的密码管理源码是shadow,git地址是:https://github.com/shadow-maint/shadow
Clone下来,main函数在src/passwd.c,从main函数入手:
Passwd数据结构定义在glibc的pwd/pwd.h文件中,数据结构如下:
接下来看下new_password函数。
我们看下/etc/login.defs的内容,部分内容截图如下: 因此,def_find函数根据ENCRYPT_METHOD查找对应的值就是MD5,因此使用MD5进行密码的加密。
注意:开发测试机上的ENCRYPT_METHOD配置都是MD5,但线上环境配置的都是SHA512
确定加密算法之后,接下来就是生成salt了,健壮的加密算法一般都会加盐。
主要看gensalt函数,上面获取method的已经在上面分析过。
目前有了明文密码和salt之后,接下来就是进行加密。
调用crypt函数,crypt函数在glibc代码里定义
从上面的调用可以知道,传给crypt函数的两个参数值分别是:pass,$1$**$*
因此,crypt函数匹配到第一个if语句为真,即MD5加密方式,继续调用__md5_crypt(key,salt)函数。
__md5_crypt_r函数就是将pass和salt进行一系列的转换后,输出加密串,而不是简单地返回hash值。
生成加密串后,将加密串赋给字符数组crypt_passwd 得到加密串之后,就更新/etc/shadow文件,过程结束。