• 系统数据文件和信息


    口令文件

      UNIX口令文件包含了如下图所示的个字段,这些字段包含在<pwd.h>中定义的passwd结构中。

      口令文件是/etc/passwd,而且是一个ASCII文件。每一行包含如下图所示的各字段,用冒号分隔,一般结构是

    LOGNAME:PASSWORD:UID:GID:USERINFO:HOME:SHELL 

      关于这些登录项,注意下面各点:

    1. 通常有一个用户名为root的登录项,其用户ID是0(超级用户)。
    2. 加密口令字段包含了一个占位符。较早期的系统版本中,该字段存放加密口令字,将加密口令字存放在一个人人可读的文件是一个安全性漏洞。所以将加密口令字存放在另一个文件中。 
    3. 口令文件项中的某些字段可能为空。如果加密口令字段为空,这通常意味着该用户没有口令(不推荐这样做)。aquid登录项有一空白字段:注释字段。空白注释字段不产生任何影响。 
    4. shell字段包含了一个可执行程序名,被用作该用户的登陆shell。若该字段为空,则取系统默认值,通常是/bin/sh。注意,squid登录项的该字段为/dev/null。显然,这是一个设备,不是可执行文件,此时目的是,阻止任何人以用户squid的名义登陆到该系统。 
    5. 为了阻止一个特定用户登陆系统,除了使用/dev/null外,还有若干种替代方法,常见一种方法是:将/bin/false用作登陆shell。他简单的以不成功(非0)状态终止,该shell将这种终止状态判断为假。另一种常见方法是:用/bin/true禁止一个账户,他所做的一切是以成功(0)状态终止。某些系统提供nologin命令,他打印可定制的出错信息,然后以非零状态终止。 
    6. 使用nobody用户名的一个目的是,使任何人都可以登录至系统,但其用户ID和组ID不提供任何特权。该用户ID和组ID只能访问人人皆可读、写的文件。 

      提供finger(l)命令的某些支持注释字段中的附加信息。如:

    #include <pwd.h>
    struct passwd *getpuid(uid_t uid);//给出用户id获取口令文件项
    struct passwd *getpwnam(const char *name);//给出用户名获取口令文件项
    //返回值:若成功,返回指针;若出错,返回NULL

      这两个函数都返回一个指向passwd结构的指针。该结构已由这两个函数在执行时填入信息。passwd结构通常是函数内部的静态变量,只要调用任一相关函数,其内容就会被重写

      调用getpwent时,他返回口令文件的下一个记录项。每次调用此函数都重写passw结构。 函数setpwent反绕它所使用的文件,endpwent则关闭这些文件。在使用getpwent查看完口令文件后,一定要调用endpwent关闭这些文件。

    #include <pwd.h>
    
    struct passwd *getpwent(void);
    //返回值:若成功,返回指针;若出错或者到达文件尾端,返回NULL
    
    void setpwent(void);
    void endpwent(void);

    demo

    #include <pwd.h>
    #include <stddef.h>
    #include <string.h>
    
    struct passwd *getpwnam(const char *name)
    {
        struct passwd *ptr;
        setpwent();
        while ((ptr = getpwent()) != NULL)
        {
            if (strcmp(name,ptr->pw_name) == 0) 
                breakl;
        }   
        endpwent();
        return ptr;
    }

     阴影口令  

      加密口令是经过单项加密算法处理过的用户口令副本。因为此算法是单向的,所以不能从加密口令猜测到原来的口令。为了不让人获得原始资料(加密口令),现在,某些系统将加密口令存放在另一个阴影口令(shadow password)文件中。该用户至少包含用户名和加密口令。与该口令相关的其他信息也可以存放在该文件中。

      只有用户登录名和加密口令这两个字段是必须的,阴影口令文件不应是一般用户可以读取的。 有一组函数可以访问阴影口令文件。

    #include <shadow.h>
    
    struct spwd *getspnam(const char *name);
    struct spwd *getspent(void);
    //两个函数返回值:若成功,返回指针;若出错,返回NULL
    
    void setspent(void);
    void endspent(void);

     组文件

      字段gr_mem是一个指针数组,其中每个指针指向一个属于该组的用户名。该数组以null指针结尾。 可以用下面函数查看组名或数值组ID。

    #include <grp.h>
    struct group *getgrpid(gid_t gid);
    struct group *getgrnam(const char *name);
    //返回值:若成功,返回指针;出错,返回NULL

      这两个函数也返回一个静态变量的指针,在每次调用时都重写该静态变量。 若要搜索整个组文件,则使用另外几个函数。

    #include <grp.h>
    struct group *getgrent(void);
    //返回值:若成功,返回指针;;若出错或者到达文件尾端,返回NULL
    void setgrent(void);
    void endgrent(void);

    附属组

      在UNIX系统中,对组的使用已经做了更改。在V7中,每个用户任何时候都只属于一个组。当用户登录时,系统就按口令文件记录项中的数值组ID,付给他实际组ID。可以在任何时候执行newgrp(l)以更改组ID。如果newgrp执行成功,则实际组ID更改为新的组ID,将用于后续的文件访问权限检查。执行不带任何参数的newgrp,则可返回到原来的组。

      在使用附属组时,我们不仅可以属于口令文件记录项中组ID所对应的的组,也可属于多至16个另外的组。文件访问权限检查相应的被修改为:不仅将进程的有效组ID与文件的组ID进行比较,而且也将所有附属组ID与文件的组ID进行比较。

      使用附属组ID的有点事不必显式的经常更改组。一个组用户会参与多个项目,因此也就要同时属于多个组。

      为了获取和设置组ID,提供如下函数

    #include <unistd.h>
    int getgroups(int gidsize, gid_t grouplist[]);
    //返回值:若成功,返回附属组ID数量;若出错,返回-1
    
    #include <grp.h>
    int setgroups(int ngroups, const gid_t grouplist[]);
    
    #include <grp.h>
    int initgroups(const char *username, gid_t basegid);
    //两个函数返回值:若成功,返回0;出错,返回-1

    其它数据文件

      UNIX还有很多其他文件,如记录各网络所提供服务的数据文件(/etc/services),有一个记录协议信息的数据文件(/etc/networks)。
      一般情况下,对于每个数据文件至少有3个函数。

    1. get函数:读下一个记录,如果需要,还会打开该文件。这种函数通常返回指向一个结构的指针,如果要保存其内容,则需复制它。
    2. set函数:打开相应数据文件,然后反绕该文件。如果希望在相应文件起始处开始处理,则调用此函数。
    3. end函数:关闭相应数据文件。在结束了对相应数据文件的读、写操作后,总应调用此函数关闭所有相关文件。

    如下为访问系统数据文件的一些例程: 

    登陆账户记录

    /*
    大多数UNUX系统都提供下列两个数据文件:utmp文件记录当前登陆到系统的各个用户:wtmp文件跟踪各个登陆和注销事件。
    每次写入这两个文件的是包含下列结构的一个二进制记录:
    */
    struct utmp
    {
        char ut_line[8];/* tty line: "ttyh0","ttyd0", "ttyp0,..." */
        char ut_name[8]; /*login name*/
        long it_time;    /*seconds since Epoch*/
    };

      登录时,login程序填写此类型结构,然后将其写入到utmp文件中,同时也将其添写到wtmp文件中。注销时,init进程将utmp文件中相应记录擦除,并将一个新纪录添写到wtmp文件中。在wtmp文件的注销记录中,ut_name字段清除为0.在系统再启动时,以及更改系统时间和日期的前后,都在wtmp文件中追加特殊的记录项。who(l)程序读取utmp文件,并以可读格式打印其内容。后来的UNIX版本提供last(l)命令,它读wtmp文件并打印所选择的记录。

    系统标识

    #include <sys/utsname.h>
    int uname(struct utsname *name);//返回与主机和操作系统有关的信息
    //返回值:若成功,返回非负值;若出错,返回-1
    
    struct ustname
    {
        char sysname[]; //操作系统名称
        char nodename[]; //节点名
        char release[]; //当前发行的操作系统
        char version[]; //系统版本
        char machine[]; //硬件类型名
    };
    //每个字符串都以null字节结尾。utsname结构中的信息通常用uname(l)命令打印
    
    /*
    namelen参数指定name缓冲区长度,如若提供足够的空间,则通过name返回的字符串以null字节结尾。如若没有提供足够的空间,则没有说明通过name返回的字符串是否以null结尾。 
    如果宿主主机连接到TCP/IP网络中,则此主机名通常是该主机的完整域名。 
    hostname(l)命令可用来获取和设置主机名。
    */
    #include <unistd.h>
    int gethostname(char *name, int namelen);
    //返回值:若成功,返回0;若出错,返回-1
  • 相关阅读:
    使用命令xrandr设置当前系统的显示分辨率及显示的旋转脚本
    CODEFORCE 246 Div.2 B题
    Android数据的四种存储方式之SQLite数据库
    C语言默认參数值的实现
    Android开发环境搭建
    也谈OpenFlow, SDN, NFV
    解决设置redmineblacklog的按钮无效问题
    长方体的研究
    表面张力与浮力
    表面张力与浮力
  • 原文地址:https://www.cnblogs.com/tianzeng/p/11050560.html
Copyright © 2020-2023  润新知