Unix系统正常允许需要使用大量和系统相关的数据文件;
有些数据文件是ASCII文件,有些是二进制文件;
但是为了方便接口来处理,所以提供一系列访问的接口。
6.1 口令文件
口令文件存储于/ect/passwd下面,每一行是一个记录按照:进行分隔:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/cache/rpcbind:/sbin/nologin
rtkit:x:499:497:RealtimeKit:/proc:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
saslauth:x:498:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/cache/rpcbind:/sbin/nologin
rtkit:x:499:497:RealtimeKit:/proc:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
saslauth:x:498:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
learn:x:501:501::/home/learn:/bin/bash
之前提到过每个字段含义。可以看到密码都是使用x表示。
如果不希望用户登录的话,那么提供一个不存在的shell比如/sbin/noshell或者是/sbin/nologin.
所涉及到的结构和接口包括:
#include <pwd.h>
struct passwd{
char *pw_name; /* user name */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user id */
gid_t pw_gid; /* group id */
char *pw_gecos; /* real name */
char *pw_dir; /* home directory*/
char *pw_shell; /* shell program */
};
//按照uid和passwd来进行查找
//内部实现可以理解为使用下列例程来完成:
struct passwd *getpwuid(uid_t uid);
struct passwd* getpwnam(const char* name);
//得到下一个entry.如果没有打开文件会自动打开
//不是线程安全的
struct passwd* getpwent(void);
//从头开始entry
void setpwent(void);
//关闭entry访问接口
void endpwent(void);
/* ***************************************** */
#include <pwd.h>
#include <stdio.h>
int main(){
setpwent();
struct passwd* pw=getpwent();
while(pw)
{
printf("%s:%s:%d:%d:%s:%s:%s ", pw->pw_name,pw->pw_passwd,pw->pw_uid,pw->pw_gid, pw->pw_gecos,pw->pw_dir,pw->pw_shell);
pw=getpwent();
}
endpwent();
return 0;
}
char *pw_name; /* user name */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user id */
gid_t pw_gid; /* group id */
char *pw_gecos; /* real name */
char *pw_dir; /* home directory*/
char *pw_shell; /* shell program */
};
//按照uid和passwd来进行查找
//内部实现可以理解为使用下列例程来完成:
struct passwd *getpwuid(uid_t uid);
struct passwd* getpwnam(const char* name);
//得到下一个entry.如果没有打开文件会自动打开
//不是线程安全的
struct passwd* getpwent(void);
//从头开始entry
void setpwent(void);
//关闭entry访问接口
void endpwent(void);
/* ***************************************** */
#include <pwd.h>
#include <stdio.h>
int main(){
setpwent();
struct passwd* pw=getpwent();
while(pw)
{
printf("%s:%s:%d:%d:%s:%s:%s ", pw->pw_name,pw->pw_passwd,pw->pw_uid,pw->pw_gid, pw->pw_gecos,pw->pw_dir,pw->pw_shell);
pw=getpwent();
}
endpwent();
return 0;
}
6.2 阴影口令
虽然密码是进行单向加密算法加密的,但是如果攻击者进行密码碰撞检测的话,并且配合 工程学的知识来破解的话,相对来说比较容易破解。
所以之后Unix系统将单向加密值放在/etc/shadow 文件下面,这个文件只有root可以阅读。格式和/etc/passwd一样:
root:$6$8zho7JZQasbuGH0z$YMeUA6c7yPvYrdVsp.aIU5y/L1lOM5ky.7e9IVD1P1diBvB2Q3mI.dgc2/uYtZmEmITVct5e74AGgZsSam3641:16891:0:99999:7:::
learn:$6$8ZSt4SDN$qtorosRh0GUbVmnNzBN2bNjl4OKTMPXcsH79UbacajyI//b8YfsuhRlbiB8UMD6phxDnR1zJ0.OGsSZUP.9ay0:16898:0:99999:7:::
所涉及到的结构和接口包括:
#include <shadow.h>
struct spwd {
char *sp_namp; /* user login name */
char *sp_pwdp; /* encrypted password */
long int sp_lstchg; /* last password change */
long int sp_min; /* days until change allowed. */
long int sp_max; /* days before change required */
long int sp_warn; /* days warning for expiration */
long int sp_inact; /* days before account inactive */
long int sp_expire; /* date when account expires */
unsigned long int sp_flag; /* reserved for future use */
};
//使用name查找,底层还是调用下面这几个函数
struct spwd* getspnam(const char* name);
struct spwd* getspent();
void setspent();
vodi endspent();
char *sp_namp; /* user login name */
char *sp_pwdp; /* encrypted password */
long int sp_lstchg; /* last password change */
long int sp_min; /* days until change allowed. */
long int sp_max; /* days before change required */
long int sp_warn; /* days warning for expiration */
long int sp_inact; /* days before account inactive */
long int sp_expire; /* date when account expires */
unsigned long int sp_flag; /* reserved for future use */
};
//使用name查找,底层还是调用下面这几个函数
struct spwd* getspnam(const char* name);
struct spwd* getspent();
void setspent();
vodi endspent();
6.3 组文件
格式和/etc/passwd一样,最后一个字段按照,分开:
root]#cat /etc/group
root:x:0:
bin:x:1:bin,daemon
daemon:x:2:bin,daemon
sys:x:3:bin,adm
adm:x:4:adm,daemon
tty:x:5:
disk:x:6:
lp:x:7:daemon
mem:x:8:
kmem:x:9:
wheel:x:10:
mail:x:12:mail,postfix
uucp:x:14:
man:x:15:
games:x:20:
gopher:x:30:
video:x:39:
dip:x:40:
ftp:x:50:
lock:x:54:
audio:x:63:
nobody:x:99:
fuse:x:493:
sshd:x:74:
tcpdump:x:72:
slocate:x:21:
learn:x:501:
bin:x:1:bin,daemon
daemon:x:2:bin,daemon
sys:x:3:bin,adm
adm:x:4:adm,daemon
tty:x:5:
disk:x:6:
lp:x:7:daemon
mem:x:8:
kmem:x:9:
wheel:x:10:
mail:x:12:mail,postfix
uucp:x:14:
man:x:15:
games:x:20:
gopher:x:30:
video:x:39:
dip:x:40:
ftp:x:50:
lock:x:54:
audio:x:63:
nobody:x:99:
fuse:x:493:
sshd:x:74:
tcpdump:x:72:
slocate:x:21:
learn:x:501:
结构和接口有下面这些:
#include <grp.h>
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
//按照gid和group name来检索
struct group* getgrgid(gid_t gid);
struct group* getgrnam(const char* name);
//遍历接口
struct group* getgrent();
void setgrent();
void endgrent();
/**********************************************************/
#include <grp.h>
#include <stdio.h>
int main()
{
setgrent();
struct group *gp=getgrent();
while(gp){
printf("%s:%s:%d:",gp->gr_name,gp->gr_passwd,gp->gr_gid);
if(*(gp->gr_mem)){
while(*(gp->gr_mem+1)){
printf("%s,",*(gp->gr_mem));
gp->gr_mem++;
}
printf("%s",*(gp->gr_mem));
}
printf(" ");
gp=getgrent();
}
endgrent();
return 0;
}
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
//按照gid和group name来检索
struct group* getgrgid(gid_t gid);
struct group* getgrnam(const char* name);
//遍历接口
struct group* getgrent();
void setgrent();
void endgrent();
/**********************************************************/
#include <grp.h>
#include <stdio.h>
int main()
{
setgrent();
struct group *gp=getgrent();
while(gp){
printf("%s:%s:%d:",gp->gr_name,gp->gr_passwd,gp->gr_gid);
if(*(gp->gr_mem)){
while(*(gp->gr_mem+1)){
printf("%s,",*(gp->gr_mem));
gp->gr_mem++;
}
printf("%s",*(gp->gr_mem));
}
printf(" ");
gp=getgrent();
}
endgrent();
return 0;
}