口令文件
在<pwd.h>
中定义了passwd
结构体。以下就是Linux下的该结构体:
struct passwd{
char *pw_name; /* username */
char *pw_passwd /*user password */
uid_t pw_uid /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
POSIX.1定义了两个获取口令文件项的函数。
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
两个函数返回值: 若成功,返回指针;若出错,返回NULL。
下面三个函数用于查看整个口令文件。
#include <pwd.h>
struct passwd *getpwent(void);
返回值: 若成功,返回指针;若出错或到达文件末尾,返回NULL。
void setpwent(void);
void endpwent(void);
getpwent
函数用于返回口令文件中下一个记录项;
setpwent
函数用来将getpwent
函数的读写地址指向密码文件开头;
endpwent
函数用于关闭使用getpwent
函数查看完的口令文件。
测试示例:
#include <stdio.h>
#include <pwd.h>
#include <stddef.h>
#include <string.h>
/* this is implementation of getpwnam function. */
struct passwd *getpwnam(const char *name)
{
struct passwd *ptr;
setpwent();
while((ptr = getpwent()) != NULL)
if(strcmp(name, ptr->pw_name) == 0)
break;
endpwent();
return ptr;
}
int main()
{
struct passwd *user;
user = getpwnam("dunk");
printf("name = \"%s\" , password = \"%s\", user id = %d, group id = %d\n",
user->pw_name, user->pw_passwd, user->pw_uid, user->pw_gid);
return 0;
}
结果如下:
阴影口令
将系统加密口令存放在被称之为阴影口令文件的文件中,与访问口令文件的一组函数相类似,有另一组函数可用于访问阴影口令文件。
#include <shadow.h>
struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
两个函数返回值:若成功,返回指针;若出错,返回NULL。
void setpent(void);
void endspent(void);
spwd
结构体说明:
struct spwd{
char *sp_name; /* Login name */
char *sp_pwdp; /* Encrypted password */
long sp_lstchg; /* Date of last change (measured in days since 1970-01-01 00:00:00 +0000 (UTC)) */
long sp_min; /* Min # of days between changes */
long sp_max; /* Max # of days between changes */
long sp_warn; /* # of days before password expires to warn user to change it */
long sp_inact; /* # of days after password expires until account is disabled */
long sp_expire; /* Date when account expires (measured in days since 1970-01-01 00:00:00 +0000 (UTC)) */
unsigned long sp_flag; /* Reserved */
};
组文件
UNIX组文件包含了如下结构体中的字段。这个结构体定义在<grp.h>
中。
struct group{
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointers to names of group members */
};
下面两个函数是用来查看组名和组ID的。
#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
这两个函数返回值:若成功,返回指针;若出错,返回NULL。
用来查看整个组文件的需要用到如下三个函数。
#include <grp.h>
struct group *getgrent(void);
返回值:若成功,返回指针;若出错或到达文件末尾,返回NULL。
void setgrent(void);
void endgrent(void);
setgrent
函数打开组文件并反绕它;
getgrent
函数从组文件中读下一个记录,如若该文件尚未打开,则先打开它;
endgrent
函数关闭组文件。
附属组ID
一个用户参与多个项目,因此用户就必须同时属于多个组,此类情况是很常有的。为了获取和设置附属组ID,提供了以下三个函数。
#include <unistd.h>
int getgroups(int gidsetsize, gid_t grouplist[]);
返回值:若成功,返回附属组ID数量;若出错,返回-1。
#include <grp.h> /* on Linux */
#include <unistd.h> /* on FreeBSD, Mac OS X, and Solaris*/
int setgroups(int ngroups, const gid_t grouplist[]);
#include <grp.h> /* on Linux and Solaris */
#include <unistd.h> /* on FreeBSD and Mac OS X */
int initgroups(const char *username, gid_t basegid);
两个函数返回值:若成功,返回0;若出错,返回-1。
getgroups
将进程所属用户的各附属组ID填写到数组grouplist
中,填写入该数组的附属组ID数最多为gidsetsize
个。
setgroups
可由超级用户调用以便为调用进程设置附属组ID表。
initgroups
函数调用setgroups
,initgroups
读整个组文件,然后对username
确定其组的成员关系。然后,它调用setgroups
,以便为该用户初始化附属组ID表。因为initgroups
要调用setgroups
,所以只有超级用户才能调用initgroups
。除了在组文件中找到username
是其成员的所有组,initgroups
也在附属组ID表中包括了basegid
。basegid
是username
在口令文件中的组ID。只有少数几个程序可以调用initgroups
。