|
所有的 linux 程序, 除了 init 外,都被其它的程序或用户启动.用户经常从 shell 中启动程序.通过检查环境变量和读取系统时钟,程序便可确定环境的大量信息.一个程序亦可找出正在使用它的使用者的信息.
当一个用户登录(log in)Linux系统时,他也就同时具有了用户名和密码.一旦这些信息被确认,用户将得到一个shell.用户也有他自己的特定标识--UID. 每一个在 Linux 上运行的程序代表有一个相应的用户,这个用户关联着一个UID.
你可以创建程序运行,就像有另外一个用户已经启动了它们.当一个程序有那个用户的 UID 权限设置,它就会像由这个可执行文件的拥有者启动运行一样.当执行了 su 命令, 程序运行就像它被超级用户启动,然后对访问的访问进行验证,验证通过后就改变到目标用户的UID(changes the UID to that of the target account,改变 UID 到目前帐户的那去),最后执行那个用户的登录shell.也程序运行得就像有另外一个用户启动了它,这常被系统管理员使用来执行维护任务.
UID 是用户身份表示的一把钥匙!
UID 有自己的类型 __uid_t ,这被定义在 sys/types.h 里. 这通常是一个小整数.有一些由系统预定义; 其它的当要建立新用户时被系统管理员创建.通常的,用户一般有大于 100 的 UID 值.
#ifndef __uid_t_defined
typedef __uid_t uid_t;
# define __uid_t_defined
#endif 在 bits/types.h 里:
# define __STD_TYPE typedef
#include <bits/typesizes.h> /* Defines __*_T_TYPE macros. */
__STD_TYPE __UID_T_TYPE __uid_t; /* Type of user identifications. */
在 bits/typesizes.h 里:
#define __UID_T_TYPE __U32_TYPE
再看 bits/types.h 里:
#define __S32_TYPE unsigned int
相关函数:
#include <sys/types.h>
#include <unistd.h>
uid_t getuid(void);
char *getlogin(void);
getuid() 函数返回程序所关联的 UID .这通常也是启动这个程序的用户的 UID .
getlogin 函数返回当前登录用户的用户名.
系统文件 /etc/passwd 包含一个处理用户帐户的数据库.它由行构成,每一行中代表一个用户信息: 用户名, 加密的密码, 用户的UID,组的GID,全名,家目录,默认shell.如下所示:beyes:x:500:500:beyes:/home/beyes:/bin/bash
如果写一个程序, 要确定那个启动了这个程序的用户的 UID, 你可以进一步查看密码文件以找出登录的用户名和全名.但一般不建议这么做,因为现代的类 UNIX 系统已经不使用(move away from)简单的密码文件以提升系统的安全性.许多系统,包括 Linux, 可以选择使用 "影子密码文件(shadow password files)" ,这个文件完全不包含任何有用的密码加密信息(这个文件通常为 /etc/shadow,这个文件普通用户不可读). 基于这样的原因, 就定义了一组函数以提供标准有效的用户信息编程接口:
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
密码数据库结构体 passwd 定义在 pwd.h 中,包含以下成员:
passwd Member Description
char *pw_name 用户的登录名
uid_t pw_uid UID 号
gid_t pw_gid GID 号
char *pw_dir 用户家目录
char *pw_shell 用户默认shell
对于用户的全名, 一些 UNIX 系统可能在域中使用不同的名字 : 在一些系统,它可能是 pw_gecos ,如在 Linux; 在其它的系统上,它可能会是 pw_comment . 这意味着,并不建议使用它.
getpwuid() 与 getpwnam() 两个函数都返回一个相应于用户的的指向 passwd 结构体的指针.
测试代码:
01 #include <sys/types.h>
02 #include <pwd.h>
03 #include <stdio.h>
04 #include <unistd.h>
05 #include <stdlib.h>
06
07
08 int main()
09 {
10 uid_t uid;
11 gid_t gid;
12 struct passwd *pw;
13
14 uid = getuid();
15 gid = getgid();
16
17 printf("User is %s\n", getlogin());
18
19 printf("User IDs: uid=%d, gid=%d\n", uid, gid);
20
21 pw = getpwuid(uid);
22
23 pw = getpwuid(uid);
24 printf("UID passwd entry:\n name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",
25 pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);
26
27
28 pw = getpwnam("root");
29 printf("root passwd entry:\n");
30
31 printf("name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",
32 pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);
33
34 exit(0);
35 }
运行输出:[root@localhost C]# ./user.exe
User is root
User IDs: uid=0, gid=0
UID passwd entry:
name=root, uid=0, gid=0, home=/root, shell=/bin/bash
root passwd entry:
name=root, uid=0, gid=0, home=/root, shell=/bin/bash 说明:
程序中,调用 getuid() 函数获得当前用户的 UID。这个 UID 被用在 getpwuid() 函数中获得详细的密码文件信息。
如果需要扫描所有的密码文件信息,你可以使用 getpwent() 函数,它能取得连续的文件条目:
#include <pwd.h>
#include <sys/types.h>
void endpwent(void);
struct passwd *getpwent(void);
void setpwent(void);
getpwent() 函数依次返回每一个用户信息条目。当所有都返回时,它返回一个空指针。一旦已经获得足够的条目信息,你可以使用 endpwent() 函数结束进程。setpwent() 函数使指针重置回到密码文件的开始位置处,这样就新的扫描就可以从下一次调用 getpwent() 开始。
用户和组的身份可以从其它的函数里获得,这些函数通常较少用到:
#include <sys/types.h>
#include <unistd.h>
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);
int setuid(uid_t uid);
int setgid(gid_t gid); 注意,这里只有超级用户才可以调用 setuid() 和 setgid() 函数 |
|