!!!!!!!!!!!!
分类: LINUX
2009-09-28 09:14:32
2009.9
【摘要】
主要介绍用户权限有关的内容。
【关键词】
实际用户ID、有效用户ID。
一、问题的提出主要介绍用户权限有关的内容。
二、解决思路1.用户标识
1) 用户ID
口令文件登录项中的用户ID是个数值,它向系统标识各个不同的用户。系统管理员在确定一个用户的登录名的同时,确定其用户ID。用户不能更改其用户ID。通常每个用户有一个唯一的用户ID。用户ID为0的用户为根(root)或超级用户。在口令文件中,通常有一个登录项,其登录名为root,我们成这种用户的特权为超级用户特权。
2)组ID
口令文件登录项也包括用户的组ID,它是一个数值。组ID也是由系统管理员在指定用户登录名时分配的。一般来说,在口令文件中有多个记录项具有相同的组ID。组被用于将若干用户分到不同的项目组或部门中去。这种机制允许同组的各个成员之间共享资源。
3)附加组ID
除了在口令文件中对一个登录名指定一个组ID外,大多数还允许一个用户属于另外的组。它允许一个用户属于多至16个另外的组。
2.设置用户ID和设置组ID
与一个进程相关联的ID有6个,如下表:
实际用户ID 我们实际上是谁 实际组ID |
有效用户ID 用于文件访问权限检查 有效组ID 附加组ID |
保存的设置用户ID 有exec函数保存 保存的设置组ID |
实际用户ID和实际组ID标识我们究竟是谁。这两个字段在登录时取自口令文件中的登录项。通常,在一个登录会话间这些值并不改变,但是超级用户进程有方法改变它们。
有效用户ID,有效组ID以及附加组ID决定了我们的文件访问权限。
保存的设置用户ID和保存的设置组ID在执行一个程序时包含了有效用户ID和有效组ID的副本。
通常,有效用户ID等于实际用户ID,有效组ID等于实际组ID。
每个文件都有一个所有者和组所有者,所有者有stat结构中的st_uid成员表示,组所有者则由st_gid成员表示。
当执行一个程序文件时,进程的有效用户ID通常就是实际用户ID,有效组ID通常是实际组ID。但是可以在文件模式字(st_mode)中设置一个特殊标志,其含义是当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID(st_uid)。与此类似,在文件模式字中可以设置另一位,它使得将执行此文件的进程的有效组ID设置为文件的组所有者ID(st_gid)。在文件模式字中的这两位被成为设置用户ID位和设置组ID位。
例如,若文件所有者为超级用户,而且设置了该文件的设置文件ID位,然后当该程序由一个进程执行时,则该进程具有超级用户特权。不管执行此文件的进程的实际用户ID是什么,都进行这种处理。
设置用户ID位及设置组ID位都包含在st_mode值中。这两位可用常量S_ISUID和S_ISGID测试。
struct stat
{
mode_t st_mode ;
ino_t st_ino ;
dev_t st_dev ;
dev_t st_rdev ;
nlink_t st_nlink ;
uid_t st_uid;
gid_t st_gid;
off_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
blksize_t st_blksize;
blkcnt_t st_blocks;
}
3.文件的访问权限
文件方位权限如下:
常量 |
说明 |
对普通文件的影响 |
对目录的影响 |
S_ISUID |
设置用户ID |
执行时设置有效用户ID |
不使用 |
S_ISGID |
设置组ID |
若组执行位设置,则执行时设置有效族ID,否则使强制性记录锁起作用(若支持) |
将在目录中创建的新文件的组ID设置为目录的组ID |
S_ISVTX |
粘住位 |
在交换区保存程序正文(若支持) |
限制在目录中删除和更名名文件 |
S_IRUSR |
用户读 |
许可用户读文件 |
许可用户读目录项 |
S_IWUSR |
用户写 |
许可用户写文件 |
许可用户在目录中删除和创建文件 |
S_IXUSR |
用户执行 |
许可用户执行文件 |
许可用户在目录中搜索给定路径名 |
S_IRGRP |
组读 |
许可组读文件 |
许可组读目录项 |
S_IWGRP |
组写 |
许可组写文件 |
许可组在目录中删除或创建文件 |
S_IXGRP |
组执行 |
许可组执行文件 |
许可组在目录中搜索给定路径名 |
S_IROTH |
其它读 |
许可其它读文件 |
许可其它读目录 |
S_IWOTH |
其它写 |
许可其它写文件 |
许可其它在目录中删除或创建文件 |
S_IXOTH |
其它执行 |
许可其它执行文件 |
许可其它在目录中搜索给定路径名 |
进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试,而这种测试可能涉及文件的所有者、进程的有效ID(有效用户ID和有效组ID)以及进程的附加组ID(若支持的话)。两个所有者ID是文件的性质,而两个有效ID和附加组ID则是进程的性质。内核进行的测试是:
(1) 若进程的有效用户ID为0,则允许访问。这给予了超级用户对整个文件系统进行处理的最充分的自由。
(2) 若进程的有效用户ID等于文件的所有者 ID(也就是该进程拥有此文件),那么:若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。适当的访问权限位指的是,若进程为读而打开该文件,则用户读位应为1;若进程为写而打开该文件,则用户位应为1;若进程将执行该文件,则用户执行位应为1。
(3) 若进程的有效组ID或进程的附加组ID之一等于文件的组ID,那么:若组适当的访问权限位被设置,则允许访问,否则拒绝访问。
(4) 若其它用户适当的访问权限位被设置,则允许访问,否则拒绝访问。
4.更改用户ID和组ID
可以使用setuid函数设置实际用户ID和有效用户ID,可以用setgid函数设置实际组ID和有效组ID。
int setuid(uid_t uid);
int setgid(gid_t gid);
更改用户ID的规则如下:
(1) 若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID,以及保存的设置用户ID设置为uid。
(2) 若进程没有超级用户特权,但是uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid。不改变实际用户ID和保存的设置用户ID。
(3) 如果上面两个条件都不满足,则将errno设置为EPERM,并返回-1。
关于内核维护的三个用户ID,还要注意下列几点:
(1) 只有超级用户进程可以更改实际用户ID。通常,实际用户ID是在用户登录时,由login(1)程序设置的,而且永远不会改变它。因为login是一个超级用户进程,当它调用setuid时,会设置所有三个用户ID。
(2) 仅当对程序文件设置了设置用户ID位时,exec函数才会设置有效用户ID。如果设置用户ID位没有设置,则exec函数不会改变有效用户ID,而将其维持原先值。任何时候都可以调用setuid,将有效用户设置为实际用户ID或保存的设置用户ID。
(3) 保存的设置用户ID是由exec复制有效用户ID而得来的。如果设置了文件的设置用户ID位,则在exec根据文件的用户ID设置了进程的有效用户ID以后,就将这个副本保存起来。
改变三个用户ID的不同方法:
ID |
exec |
Setuid(uid) | ||
设置用户ID位关闭 |
设置用户ID位打开 |
超级用户 |
非特权用户 | |
实际用户ID 有效用户ID 保存的设置用户ID |
不变 不变 从有效用户ID复制 |
不变 设置为程序文件的用户ID 从有效用户ID复制 |
设为uid 设为uid 设为uid |
不变 设为uid 不变 |