linux用户及密码的存储和校验方法
五个板栗
前言:
在linux中,用户和密码由/etc/passwd文件和/etc/shadow文件存储。
/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 *passwd = argv[2]; ret = user_auth(user, passwd); if (ret < 0) { printf("user auth failed, ret=%d\n", ret); return ret; } if (ret > 0) { printf("passwd not match, auth failed\n"); return ret; } printf("auth okay!\n"); return 0; }
编译该程序是指定链接库crypt
gcc auth.c -lcrypt
然后使用该程序验证我们添加的用户test,密码是test,正确的输入用户名和密码时输出结果如下:
└─$ sudo ./a.out test test auth okay!
如果故意输入错误密码,再次执行得到如下结果:
└─$ sudo ./a.out test hello passwd not match, auth failed
到此这篇关于linux用户及密码的存储和校验方法的文章就介绍到这了,更多相关linux存储和校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!