linux用户及密码的存储和校验

归志宁无五亩园,读书本意在元元。这篇文章主要讲述linux用户及密码的存储和校验相关的知识,希望能为你提供帮助。
在linux中,用户和密码由/etc/passwd文件和/etc/shadow文件存储。

【linux用户及密码的存储和校验】/etc/passwd文件
在passwd中,每一行代表一个用户记录,每条记录分为7个字段,字段间用:分割,以下是每个字段的描述。

用户名:用户绑定的名字
加密后的密码(可选)
用户id,用来标识用户
用户组id,表示用户所属组
用户描述信息
用户的家目录
用户命令解释器

如果第二项密码字段为一个小写的x,则表示用户的密码存储在/etc/shadow文件中,即在/etc/shadow文件中也有一行对应该用户记录的记录。
/etc/shadow文件
shadow是一个包含系统帐户密码信息和可选时间信息的文件。shadow文件每一行代表一条记录,每一条记录有9个字段,以下是每个字段的描述。
登录用户名:必须对应到/etc/passwd文件中的一条记录中的用户登录名
加密密码:加密后的密码字符串
最后一次密码修改日期
用户更改密码前必须等待的最小密码期限
用户必须更改密码的最大密码期限
密码过期警告时间
密码不活动期
用户到期时间
保留,用于将来扩展其他属性

测试用户
新建一个用户test,设置密码为test,然后查看其passwd记录以及shadow记录。
└─$ sudo adduser --home /home/test --shell /bin/bash test
Adding user `test ...
Adding new group `test (1001) ...
configuration error - unknown item NONEXISTENT (notify administrator)
configuration error - unknown item PREVENT_NO_AUTH (notify administrator)
Adding new user `test (1001) with group `test ...
configuration error - unknown item NONEXISTENT (notify administrator)
configuration error - unknown item PREVENT_NO_AUTH (notify administrator)
Creating home directory `/home/test ...
Copying files from `/etc/skel ...
New password:
Retype new password:
passwd: password updated successfully

Changing the user information for test
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] yes
└─$ cat /etc/passwd | grep test
test:x:1001:1001:,,,:/home/test:/bin/bash
└─$ sudo cat /etc/shadow | grep test
test:$y$j9T$1L/PH8ddqysyageBD6TnF1$MNm4An/z6LHdRq0JEOnFuviXBequ23gbIG8U1A/f4F.:19
112:0:99999:7:::

用户验证API
可使用crypt和shadow的api对用户和密码进行验证
#include < crypt.h>
#include < unistd.h>
char *crypt(const char *key, const char *salt);
/* General shadow password file API */
#include < shadow.h>
struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
struct spwd *fgetspent(FILE *stream);
struct spwd *sgetspent(const char *s);
int putspent(const struct spwd *p, FILE *stream);
int lckpwdf(void);
int ulckpwdf(void);

下面的代码实例让用户输入用户名和密码,通过crypt和shadow API进行检验用户输入的用户名和密码

是否匹配
#include < unistd.h>
#include < stdio.h>
#include < shadow.h>
#include < crypt.h>
#include < stdlib.h>
#include < errno.h>
#include < string.h>
/*
* user_auth - Authentication user name and password.
* @user: user name.
* @passwd: user password string.
*
* on success return 0, return errno on error.
*/
int user_auth(const char *user, const char *passwd)

struct spwd *user_spwd;
char *encrypted_pwd;
if (!user || !passwd)
return -EINVAL;
user_spwd = getspnam(user);
if (!user_spwd)
return -errno;
encrypted_pwd = crypt(passwd, user_spwd-> sp_pwdp);
if (!encrypted_pwd)
return -errno;
return abs(strcmp(encrypted_pwd, user_spwd-> sp_pwdp));

int main(int argc, char *argv[])

int ret;
char *user = argv[1];
char *

    推荐阅读