【Linux系统编程】| 【06】用户和组、密码文件
上述7个区段2、密码文件/etc/shadow3、组文件/etc/group4、获取用户和组的信息从密码文件获取记录从组文件获取记录扫描密码文件和组文件中的所有记录从shadow密码文件中获取记录读取用户密码5、密码加密和用户认证密码验证...
·
1、密码文件/etc/passwd
上述7个区段
【登录名】:登录系统的用户名;
【密码】:包含加密处理的密码,长度为13,使用x代替,实际密码存储再shadow中;
【用户ID】:用户的数值型ID,root为0;
【组ID】:用户属组中首选属组的数值型ID;
【注释】:存放关于用户的描述性文字;
【主目录】:用户登录后的初始路径;
2、密码文件/etc/shadow
该文件包括加密处理的密码;
3、组文件/etc/group
该文件下一条记录的各个字段:
- 【组名】:与密码文件中的登录名类似;
- 【密码】:组密码,该密码经由加密处理;
- 【组ID】:该组的数值型ID;
- 【用户列表】:属于该组的用户名列表;
4、获取用户和组的信息
从密码文件获取记录
#include <pwd.h>
struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
struct passwd{
char *pw_name; // 登录名
char *pw_passwd; // 密码
uid_t pw_uid; // 用户ID
gid_t pw_gid; // 组ID
char *pw_gecos; // 用户信息
char *pw_dir; // 工作目录
char *pw_shell; // 登录shell
};
/**
上述两个函数返回一致,只是通过查询的方式不同;
*/
从组文件获取记录
#include <grp.h>
struct group *getgrnam(const char *name);
struct group *getrgid(git_t gid);
struct group {
char *gr_name; // 组名
char *gr_passwd; // 密码
gid_t gr_gid; // 组ID
char **gr_mem;
};
/**
上述函数分别通过组名和组ID来查找属主信息;
*/
扫描密码文件和组文件中的所有记录
#include<pwd.h>
struct passwd *getpwent(void);
/**
@func: 从密码文件中逐条返回记录,调用会自动打开密码文件;
*/
void setpwent(void);
/**
@func: 重返文件起始处;
*/
void endpwent(void);
/**
@func: 密码文件处理完,使用该函数进行关闭;
*/
从shadow密码文件中获取记录
#include<shadow.h>
struct spwd *getspnam(const char* name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
struct spwd {
char *sp_namp; // 用户名
char *sp_pwdp; // 密码
long sp_lstchg;
long sp_min;
long sp_max;
long sp_warn;
long sp_inact;
long sp_expire;
unsigned long sp_flag;
};
读取用户密码
#include <unistd.h>
char *getpass(const char *prompt);
/**
@func: 屏蔽回显功能,读取用户密码;
return: 返回密码;
*/
5、密码加密和用户认证
由于安全方面的原因,UNIX系统采用单向加密算法对密码进行加密,故加密形式将无法还原出原始密码;
因此,验证候选密码的唯一方法是使用同一算法对其进行加密,并将加密结果与存储于/etc/shadow中的密码进行匹配;
加密算法封装于crypt()函数之中;
#include <unistd.h>
char *crypt(const char *key, const char *salt);
/**
@func: 接收一个最长可达8字符的密码,并对其加密;
@param salt: 指向一个两字符的字符串,用来扰动DES算法;
return: 指向长度未13个字符的字符串,该字符串为静态分配而成,即经过加密处理的密码;
*/
【注意】: 在编译程序时,指定-lcrypt选项,链接该库;
密码验证
#define _BSD_SOURCE
#define _XOPEN_SOURCE
#include <unistd.h>
#include <limits.h>
#include <pwd.h>
#include <shadow.h>
#include "../Jxiepc/tlpi_hdr.h"
int main() {
char *username, *passwd, *encrypted, *p;
struct passwd *pwd;
struct spwd *spwd;
bool authOk;
size_t len;
long lnmax;
/* 获取主机上用户名字符串的最大长度 */
lnmax = sysconf(_SC_LOGIN_NAME_MAX);
if(lnmax == -1) lnmax = 256;
/* 给用户名分配内存 */
username = (char*)malloc(lnmax);
if(username == NULL) errExit("malloc");
/* 获取用户输入用户名 */
printf("username:");
fflush(stdout);
if(fgets(username, lnmax, stdin) == NULL)
exit(EXIT_FAILURE);
/* 记录实际用户名长度 */
len = strlen(username);
if(username[len - 1] == '\n')
username[len-1] = '\0';
/* 从密码文件中获取记录 */
pwd = getpwnam(username);
if(pwd == NULL)
fatal("couldn't get password record");
printf("%s\n", pwd->pw_passwd);
/* 从组文件中获取记录 */
spwd = getspnam(username);
if(spwd == NULL && errno == EACCES)
fatal("no permission to read shadow password file");
if(spwd != NULL)
pwd->pw_passwd = spwd->sp_pwdp;
printf("%s\n", spwd->sp_pwdp);
/* 从用户输入中获取 */
passwd = getpass("Password: ");
/* 密码加密验证 */
encrypted = crypt(passwd, pwd->pw_passwd);
printf("%s\n", encrypted);
for(p = passwd; *p != '\0';)
*p++ = '\0';
if(encrypted == NULL)
errExit("crypt");
authOk = strcmp(encrypted, pwd->pw_passwd) == 0;
if(!authOk){
printf("Incorrect password\n");
exit(EXIT_FAILURE);
}
printf("UID=%ld\n", (long )pwd->pw_uid);
return 0;
}
更多推荐
已为社区贡献3条内容
所有评论(0)