UNIX高级环境编程 设置用户ID

来源:互联网 发布:电视剧知行天下 编辑:程序博客网 时间:2024/05/03 03:53

看UNIX相关的书时经常能遇到这几个概念,但一直没有好好去理清这几个概念,以致对这几个概念一直一知半解。今天好好区分了一下这几个概念并总结如下。说白了这几个UID引出都是为了系统的权限管理。

 

    下面分别用RUID, EUID,SUID来表示实际用户ID,有效用户ID,设置用户ID。另外用户ID是个整型数,为了说明方便真接使用了用户名来代表不同的UID。先解释一下这几个ID的作用:

RUID, 用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个UNIX系统后就唯一确定了他的RUID.

EUID, 用于系统决定用户对系统资源的访问权限,通常情况下等于RUID。

SUID,用于对外权限的开放。跟RUID及EUID是用一个用户绑定不同,它是跟文件而不是跟用户绑定。

 

    说明SUID的时候很多书都简略的提了一下passwd这个程序,下面就拿这个例子来分析。我们知道linux系统的密码都存在了/etc/shadow这个文件里。这个文件是如此的重要,在做任何修改之前最好先备份一下。查看/etc/shadow文件的属性如下:

 

[root@localhost ~]# ll /etc/shadow

-r-------- 1 root root 1144 Jul 20 22:33 /etc/shadow

 

从上可以看出/etc/shadow文件是一个属于root用户及root组的文件,并且只有EUID为root的用户具有读的权限,其它所有EUID都没有任何权限。当你在steve用户(EUID此时也为steve)的shell下试图用vim打开这个文件时会提示权限不允许。至于连root用户也只有读的权限我猜是为了不鼓励root用户使用vim类的编辑器去直接修改它,而要采用passwd命令来修改这个文件。如果你非要直接修改它,那么你可以使用chmod命令修改为属性为root可写,然后就可以修改了。

 

    用过UNIX系统的人都知道,任何一个用户都可以使用passwd这个命令来得新设定自己的密码。但从上面已经知道,非root用记是无法读这个文件的,那么普通用户是如何做到修改这个文件的呢?我们知道passwd这个命令实际执行的程序是/usr/bin/passwd, 查看这个文件属性如下:

 

-r-s--x--x 1 root root 21944 Feb 12  2006 /usr/bin/passwd;

 

对应文件存取标志的s位就是通常说的SUID位,另外可以看到所有用户都有执行的这个程序权力。当steve用户执行passwd命令的时候。Shell会fork出一个子进程,此时进程的EUID还是steve,然后exec程序/usr/bin/passwd。exec会根据/usr/bin/passwd的SUID位会把进程的EUID设成root,   此时这个进程都获得了root权限, 得到了读写/etc/shadow文件的权限, 从而steve用户可完成密码的修改。 exec退出后会恢复steve用户的EUID为steve.这样就不会使steve用户一直拥有root权限。

 

我们可以测试一下,用root用户把/usr/bin/passwd的SUID位去掉,如下:

[root@localhost ~]# ll /usr/bin/passwd 

-r-s--x--x 1 root root 21944 Feb 12  2006 /usr/bin/passwd

[root@localhost ~]# chmod u-s /usr/bin/passwd

[root@localhost ~]# ll /usr/bin/passwd       

-r-x--x--x 1 root root 21944 Feb 12  2006 /usr/bin/passwd

 

然后steve用户用命令passwd去更新密码会提示如下错误:

[steve@localhost ~]$ passwd

Changing password for user steve.

Changing password for steve

(current) UNIX password:

passwd: Authentication token manipulation error

[steve@localhost ~]$

这就是因为/usr/bin/passwd程序的SUID去掉后,steve用户虽然可以执行该程序,但因为/usr/bin/passwd/的SUID没有设置,这样exec后进程的EUID仍为steve的原因。

 

    也许有人会发现root用户却仍可以使用该用命修改密码,那是因为root用户本身的EUID时就是root (也有可能只要发现是RUID是root就不检查EUID了,直接可读写,root就是老大嘛), 可以读取密码文件。

 

另外也许有人会发现普通的文件文件普通的文本文件会也可以设置SUID位, 但这是没有意义的,因为文件文件没有地方执行seteuid()的系统调用来改变当用用户的EUID。

 

最后,这里的对用户ID的规则同样也适用了组ID。

转自;http://blog.csdn.net/guosha/article/details/2679334




于这个知识点,让我一段时间都觉得很难了解!经过了几章的学习,有点慢慢了解这个怎么一回事情。

每一个进程其实对应了6个以上的ID,它们分别是
实际用户ID,实际组ID
有效用户ID,有效组ID,附加组ID
保存设置用户ID,保存设置组ID


        实际用户ID,就是当前执行这个进程的ID,比如我现在是andrew用户,那么我执行main程序,那么这个main的实际用户ID就是andrew,实际组ID其实和实际用户ID类似。
        有效用户ID,这个就是比较关键的一个ID,这个ID应该是unix一直在使用的一个ID,因为即使你只是一个很简单的访问文件,那也是要通过这个有效用户ID的,因为每一个文件都有一定的访问权限,而一个进程或者一个程序去访问它,os本身就是根据你的有效用户ID了给与一定量的权限.
那么有效用户ID与实际用户ID有什么区别呢??
        这两个ID在一般情况下是相同的,比如当前用户是andrew,那么它的实际用户ID是andrew,而有效用户ID也是andrew。可是在不一般的情况下那么这两个ID就可能不一样了,那么什么样的情况下是不一样的呢?那就是当一个用户要进行一个合理的特权的时候就需要啦,那么到底是怎么样的情况呢?


每一个进程其实对应了6个以上的ID,它们分别是
实际用户ID,实际组ID
有效用户ID,有效组ID,附加组ID
保存设置用户ID,保存设置组ID


        实际用户ID,就是当前执行这个进程的ID,比如我现在是andrew用户,那么我执行main程序,那么这个main的实际用户ID就是andrew,实际组ID其实和实际用户ID类似。
        有效用户ID,这个就是比较关键的一个ID,这个ID应该是unix一直在使用的一个ID,因为即使你只是一个很简单的访问文件,那也是要通过这个有效用户ID的,因为每一个文件都有一定的访问权限,而一个进程或者一个程序去访问它,os本身就是根据你的有效用户ID了给与一定量的权限.
那么有效用户ID与实际用户ID有什么区别呢??
        这两个ID在一般情况下是相同的,比如当前用户是andrew,那么它的实际用户ID是andrew,而有效用户ID也是andrew。可是在不一般的情况下那么这两个ID就可能不一样了,那么什么样的情况下是不一样的呢?那就是当一个用户要进行一个合理的特权的时候就需要啦,那么到底是怎么样的情况呢?

        比如我们在linux系统中的passwd这个命令或者这个passwd这个程序,一个用户对自己进行修改密码是一种很正常的事情,可是保存密码的文件/etc/passwd却是root用户可写的这样的权利,那么也就是用如果你要修改密码,必须通过root用户帮你修改,这样出现的问题可不是一点点...

[plain] view plaincopyprint?
  1. <span style="font-size:13px;">-rw-r--r-- 1 root root 1762 2011-11-04 18:16 /etc/passwd</span>  
       这个事情的处理是这样的,让用户去运行passwd这个程序的时候,os给与root用户的权利,然后用户就可以修改自己的密码。具体的讲就是让用户去运行passwd这个程序的时候,unix将它的有效用户ID变成了拥有passwd的用户的ID,也就是root,所以就可以修改这个/etc/passwd这个文件。

<注 passwd命令是/usr/bin/passwd,passwd这个文件是/etc/passwd>

      保存设置用户ID,这个ID是前段时间让我一直不明白的ID,那是相当的郁闷,不过经过最近的学习发现了这个ID的用处。这个ID是用来保存有效ID的副本,让我们运行程序的过程其实就是os调用exec系列函数来调用我们程序的main函数,exec函数是kernel唯一执行程序的方法,或者那么讲不管什么用户程序的运行,其实也就是os的exec的调用过程。而exec在调用过程中会将这个程序的有效用户ID拷贝给保存用户ID。至于有什么用,下面再提出。


2.文件的设置用户ID位

       这个东西应该是上面的关键所在,每一个文件都有一个文件模式字(st_mode),这个字可以通过看stat函数去函数,而这个模式字包含了很多文件的属性,包括文件的类型,以及文件的访问权限的,当然设置用户ID位也在其中。通过设置这个位,就能当执行这个文件的时候,进程的有效ID设置为该文件本身的用户。不知道你明白与否,不过我那个时候却没有明白,不过现在却明白了,这里的文件我可以把他认为是一些可运行的文件,或者就是可执行文件,而当运行这个文件的时候,进程会改变其有效用户ID,变成这些文件本身的ID。还是举那个passwd这个例子,它的属性是

[plain] view plaincopyprint?
  1. -rw<span style="color:#ff0000;">s</span>r-xr-x 1 root root 37140 2011-02-15 06:11 /usr/bin/passwd   
看到s了没有,这就是设置了设置用户ID位的标志,而他的own是root,也只有root能有权利去写/etc/passwd的文件,可以当我们改变我们的密码的时候我们也改变了这个文件,现在你能感觉到什么了不??

下面举一个实际的例子看看:

[cpp] view plaincopyprint?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/stat.h>  
  4. #include <unistd.h>  
  5.   
  6. int main()  
  7. {  
  8.     printf("real user ID = %d\n",getuid());  
  9.     printf("effect user ID = %d\n",geteuid());  
  10.   
  11.     return 0;  
  12. }  
  13.   
  14. andrew$./main  
  15. real user ID = 1000  
  16. effect user ID = 1000  
  17.   
  18. andrew$su  
  19. root#chown root main  
  20. root#chmod u+s main  
  21. root#ls -l | grep main  
  22. -rwsr-xr-x  1 root   andrew  9809 2011-11-19 10:32 main  
  23. root#exit  
  24. andrew$exit  
  25. andrew$./main  
  26. real user ID = 1000  
  27. effect user ID = 0  
就像你看见的,有效用户ID变化了,真的变了,真的很神奇把,哈哈如果你还想知道其他的话,你可以试试看access这个函数,这个函数可以得知一个进程真的的能力,而不受设置用户ID的影响的,所以它能让你见到一个进程本身没有访问那个文件的能力,可是他在具体的运行的过程却可以打开这个文件。

3.还有一些什么呢?

关于这个我还想讨论一些东西,首先就是setuid(uid)这个函数,这个函数在不同的用户之下有这不一样的效果:
在root用户下,可以是实际用户ID,有效用户ID,保存设置用户ID都设置为uid
在普通用户下的话,如果uid是实际用户ID或者保存设置用户ID的话,那么则会将有效用户ID设置为uid,
如果不符合上面的那么就返回-1
还有关于kernel关于这3个用户的维护过程:
1.实际用户ID,这个ID可以认为是用户也不会改变的,除了root用户下的setuid这个函数可以改变,因为通常我们在login以后我们的用户就已经决定下来啦,那么也就是说实际用户ID是不变的。
2.有效用户ID,这个ID通常情况下是不改变的,但是当执行文件被设置了设置用户ID位,那么exec会将这个进程的有效用户ID修改成这个可执行文件的本来的用户,就像我们前面所说的那样的。

3.保存设置用户ID,这个准确的说可以认为是有效用户ID的备份,不管什么时候,只要运行了exec以后都会对有效用户ID进行拷贝的。

转自:http://blog.csdn.net/ccjjnn19890720/article/details/6990656



0 0
原创粉丝点击