系統數據文件和信息

口令文件

  UNIX口令文件包含了以下圖所示的個字段,這些字段包含在<pwd.h>中定義的passwd結構中。node

  口令文件是/etc/passwd,並且是一個ASCII文件。每一行包含以下圖所示的各字段,用冒號分隔,通常結構是算法

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

  關於這些登陸項,注意下面各點: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)文件中。該用戶至少包含用戶名和加密口令。與該口令相關的其餘信息也能夠存放在該文件中。ui

  只有用戶登陸名和加密口令這兩個字段是必須的,陰影口令文件不該是通常用戶能夠讀取的。 有一組函數能夠訪問陰影口令文件。加密

#include <shadow.h>

struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
//兩個函數返回值:若成功,返回指針;若出錯,返回NULL

void setspent(void);
void endspent(void);

 組文件

  字段gr_mem是一個指針數組,其中每一個指針指向一個屬於該組的用戶名。該數組以null指針結尾。 能夠用下面函數查看組名或數值組ID。spa

#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
相關文章
相關標籤/搜索