Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1743597
  • 博文数量: 1493
  • 博客积分: 38
  • 博客等级: 民兵
  • 技术积分: 5834
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-19 17:28
文章分类

全部博文(1493)

文章存档

2016年(11)

2015年(38)

2014年(137)

2013年(253)

2012年(1054)

2011年(1)

分类:

2012-07-17 08:33:46

  因为某种原因 感觉心里一直有想把Unix有关文件权限编程这部份弄懂的想法,  所以第三遍看Unix高级编程第四章, 以前都是一眼带过, 根本没看吃透, 再次看感觉懂了蛮多的, 写下了以后复习用!

一: 一个进程相关的ID主要有:

 实际用户ID  实际组ID : 标识空间我们是谁, 登录时取自口令文件登录项,登录会话期间一直不变,超级用户可改变
 有效用户ID  有效组ID : 决定了我们的文件访问权限,也就是用来测试本进程对某些文件的访问权限
 保存的设置用户ID,设置组ID: 执行一个程序时包含了有效用户ID 和有效组ID的副本

ps: 通常 有效用户ID等于实际用户ID,有效组ID等于实际组ID ,当执行一个文件时, 如果文件设置了设置用户ID位设置用户组ID位 即SUID  SGID 则情况不同


二: 进程每次打开一个文件时, 内核进行访问权限测试:

 涉及到用户所有者(st_uid st_gid), 进程有效ID(有效用户ID和有效组ID)以及附加组ID(若支持的话)
 所有者ID是文件的性质,
两个有效ID和附加组ID则是进程的性质

内核进行的测试步骤:
 1. 如果
进程的有效用户ID是0(超级用户), 则允许访问
 2. 若
进程有效用户ID等于文件所有者ID, 则根据文件所有者所设置的权限访问

点击(此处)折叠或打开

  1. -rwxr-xr-x 1 201 202 1891 7月 16 10:24 test.sh
   如上, 如果进程的有效用户ID 等于201, 则进程对文件的权限为 -rwxr-xr-x  紫色所表示的权限
 
 3.  如进程的有效组ID或进程的附加组ID之一等于文件的组ID(即文件的实际组ID) , 那么进程对文件的权限为文件所有组所设置的权限  .

    还是上面这个例子, 如果进程的有效组ID或附加组ID之一为202的话, 那么进程对文件的权限 为 -rwxr-xr-x 紫色所表示的权限

 4. 若其他用户适当权限被设置 则进程此文件的权限为文件的其他访问权限

   就是上面例子的最后三位权限了!

注意:
这四步是依次执行的, 如果不是超级用户, 但是进程拥有此文件( 也就是有效用户ID等于文件的实际用户ID) 那么就按文件所有者权限来确认进程对此文件的权限, 后面的步骤不再执行!

对于进程访问文件权限测试的总结
   从上面可以看出, 内核对进程文件的权限测试 主要是针对 进程的有效用户ID来进行测试的,  也就是说, 如果有效用户ID 等于文件所有者ID  那么我(打开文件的进程) 就是文件的所有者 拥有文件所有者所拥有的权限, 如果不是文件的所有者 就再测试进程有效组ID...

三:文件模式中的设置用户ID位和设置组ID位
  
   关于具体的描述网上很多文章都说了, 简单说下书上说的:
文件 设置用户ID位: 当执行此文件时, 将进程的有效用户ID设置成文件的所有者用户ID
        设置组ID位: 当执行此文件时, 将进程的有效组ID设置成文件的组所有者ID



  1. -rwsr-sr-x 1 200 201 1891 7月 16 10:24 test.sh
如上  -rwsr-sr-x 紫色表示文件设置了 设置用户ID位;  -rwsr-sr-x  紫色表示设置了 设置组ID位 , 如果这里的S位为大写, 表示执行位没有设置,连文件执行位都没设置, 那么设置了 设置用户或设置组ID位 也没有用。

最经常看到的例子:
 passwd程序就是一个设置用户ID程序, 允许任何用户修改其口令, 因为命令可以将新口令写入口令文件/etc/passwd, 但只有超级用户才有该文件的写权限, 所以设置了该passwd设置用户ID位, 当执行passwd时, 进程有效用户ID设置成程序passwd的所有者ID, 即root, 所以可以写入新命令到口令文件中了!


四: 新文件和新目录的所有权

 1. 新文件的用户ID设置成进程的有效用户ID
 2. 新文件的组ID两种情况:
    (1)  新文件的组ID是进程的有效组ID
    (2)  如果新文件的组ID所在目录的设置组ID位 设置了的话, 新文件的组ID将设为目录的组ID (这设置组ID位这里的作用与权限测试的时候有点类似)
 3. 其他:

 
(1). mkdir 函数自动的传递了目录的设置组ID位
 (2) access 函数是用实际用户ID和实际组ID来进行访问权限的测试的
如果你只想测试下实际用户所拥有的权限 ,就可以使用这个函数了。

五:编程应用

 1. 在执行exec前后 进程的实际用户ID和实际组ID不变, 而有效ID 取决于所执行的程序文件 是否设置了设置用户ID位设置组ID位, 如果设置了 设置用户ID位, 则有效用户ID变成程序文件所有者ID,否则有效用户ID不变, 对组ID处理方式与此相同,

 2.  保存的设置用户ID是由exec复制有效用户ID后得来的, 所有第一点里面介绍设置用户ID时说 是有效用户ID的副本!

 3
. 一般设计应用程序时, 总是试图使用最小特权模型, 依照模型, 程序应当只具有为完成任务所需的最小特权.

 4. 使用函数:


  1. #include ,unistd.h>

  2.     int setuid(uid_t uid); //设置实际用户ID和有效用户ID,如果进程为超级用户,则会设置实际、有效、保存的设置用户ID
  3.     int setgid(gid_t gid); //设置实际组ID和有效组ID
  4.     int setreuid(uid_t ruid, uid_t euid); //交换实际用户ID和有效用户ID
  5.     int setregid(gid_t rgid, gid_t egid);
  6.     int seteuid(uid_t uid); //更改有效用户ID
  7.     int setegid(gid_t gid);
注意:
   根据书上来看, 特权用户使用这几个函数的时候, 都是直接用参数的值来设置实际用户ID或者有效用户ID,这些值都可以是
任意的.
       例如:setreuid(ruid, euid), 如果是特权用户,则直接设置实际用户ID为ruid,有效用户ID为euid

  但非特权用户就不行了, 非特权用户
用setuid(), seteuid()则只能将有效有户ID设置为实际用户ID或保存的设置用户ID,如果不是这两个数,设置失败!

对编程应用方面的总结:
  非特权用户不能指定任意的有效用户ID, 结合其他几个函数来交换或设置有效用户ID, 与设置用户ID位 一起实现权限的控制

六: 以书上的例子结束
 
man程序文件的所有者及他属组通宵是为man自身保留的用户和组, man可能需要执行许多其他命令,以处理包含显示手册页的文件,为了防止被欺骗或重写错误文件, man在两种权限间切换: 运行man命令用户的权限, 拥有man可执行文件用户的权限

 1. man程序文件由名为man的用户所拥有, 设置用户ID位已设置, exec 此程序时 , 用户ID情况:

实际用户ID = 我们的用户ID
有效用户ID = man      //因为设置用户ID位,所有进程的有效用户ID成了文件的所有者ID
保存的设置用户ID = man  // 保存的设置用户ID,复制有效用户ID得来

 2.  程序访问需要的配置文件和手册页,这些文件由man用户拥有, 因为有效用户ID是man,所以可以访问

 3. man 代表我们运行任一命令前, 调用setuid(getuid()) , 我们不是超级用户, 所以仅仅改变有效用户ID, 用户ID情况变成:

实际用户ID = 我们的用户ID (未改变)
有效用户ID = 我们的用户ID
保存的设置用户ID = man

   现在man 以有效用户为我们的用户ID运行, 所以man 只能搜索我们通常可以访问的文件, 代表我们安全的执行一次过滤

4.  当过滤完成后 ,  再调用setuid(euid), {euid 由用户man调用geteuid()保存下来,  这里setuid的参数为设置用户ID 所以是许可的} ,现在用户ID情况:

实际用户ID = 我们的用户ID (未改变)
有效用户ID = man
保存的设置用户ID = man (未改变)

注意:  一个进程无法直接获取他的保存的设置用户ID, 但因为exec时设置用户ID是由复制有效ID获取的, 所以开始时应该用euid=geteuid()保存这个有效ID 即后面的设置用户ID, 供这里使用.

 
5. 因为有效用户是man, 所以现在可以对其他文件进行操作了

阅读(269) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~