我们是怎么改密码的?
一个文件的信息可以用函数 stat(char *fname,struct stat * buf)取得,然后存放在stat结构里面。
struct stat 结构的成员变量有很多,只看三个
st_mode 文件类型和许可权限
st_uid 文件所有者的用户ID
st_gid 文件所属组的ID
可以用ls -l 列出文件的信息,看看存放用户密码的文件/etc/passwd
ls -l /etc/passwd
-rw-r--r-- 1 root root 1722 Jul 11 21:51 /etc/passwd
root root 表示该文件的所有者为超级用户root,并且包含在root组中。
-rw-r--r-- 就是st_mode,它包含16为,其中四位用作文件类型,9为用作许可权限,剩下三位用作文件的特殊属性。
从文件的许可权限可以看出,普通用户没有修改这个文件的权限,只有root用户(文件所有者)才能修改它,我们普通用户运行passwd命令怎么能够修改这个文件而修改自己的密码呢?
再看passwd命令文件的信息
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 41284 Jun 24 2011 /usr/bin/passwd
显示该文件的所有者为root,包含在root组中。并且其他用户有执行权限。普通用户能用passwd命令修改自己的密码,说明取得了root用户的权限。这是怎么做到滴?解决的办法,不是给所有用户修改这个文件的权限,而是给passwd命令一个特殊的权限。
怎么给它一个特殊的权限? 在他的特殊属性中包含set-user-ID位(当passwd命令文件信息中用户执行位为s时,说明它包含了set-user-ID位),SUID位告诉内核,当其他用户运行这个程序的时候认为是由文件所有者在运行这个程序,在这里就是root,而root有修改/etc/passwd的权限。
是否能修改其他用户的密码? 答案是否定的,passwd命令知道是谁在运行程序。他用系统调用getuid来得到用户ID,passwd命令可以修改/etc/passwd这个文件,但是 他只会修改该用户ID所对应的密码。
关于那么多ID
>实际用户ID和实际用户组ID
>有效用户ID 和有效用户组ID
>保存的设置用户ID和保存的设置用户组ID
实际用户ID和实际用户组ID 标识我们究竟是谁,谁在登陆并执行我们。
有效用户ID 和有效用户组ID 决定我们访问文件的权限。
保存的设置用户ID和保存的设置用户组ID在执行一个程序时包含有效用户ID 和有效用户组ID的副本(由exec函数保存)
通常,有效用户ID 等于实际用户ID,有效组ID等于实际组ID。
当执行一个程序文件时,进程的有效用户ID等于实际用户ID(程序的执行者),有效组ID通常等于实际用户组ID,但是可以在文件模式字(st_mode)设置一个特殊标志(即包含set-user-ID),其含义是“当执行此文件时,将进程的有效ID设置为文件所有者的用户ID”(即拥有程序文件所有者访问文件的权限)。有效ID组类同。
例如,若程序文件所有者是超级用户,而且设置了该文件的set-user-ID位,然后当该程序文件由一个进程执行时,该进程具有超级用户特权,不管执行此文件的进程的实际用户ID是什么,都进行这种处理。(这就是改密码程序)
执行exec函数前后实际用户ID和实际用户ID组保持不变,而有效ID是否改变取决于所执行程序文件的set-user-ID位和set-group-ID位是否设置。如果程序文件的set-user-ID位已设置,则有效用户ID为程序文件的所有者ID,否则有效用户ID不变。对组ID的处理方式相同。
可以用setuid函数设置实际用户ID和有效用户ID,setgid 类同。
int setuid(uid_t uid)
int setgid(uid_t uid)
>进程ID 进程的标识符
>进程组ID 进程组的标识符
GET-ID 傻傻分不清楚
pid_t getpid(void) 返回调用进程的进程ID
pid_t getppid(void) 返回调用进程的父进程ID
pid_t getpgid(pidt_t pid) 返回进程组ID
uid_t getuid(void) 返回调用进程的实际用户ID
uid_t geteuid(void) 返回调用进程的有效用户ID
uid_t getgid(void) 返回调用进程的实际组ID
uid_t getegid(void) 返回调用进程的有效组ID
int setpgid(pid_t pid,pid_t pgid) 设置进程的进程组ID(只能为自己和直接子进程设置组ID)
int setgid(uid_t uid)
如上图