資訊人筆記

Work hard, Have fun, Make history!

使用者工具

網站工具


course:nctu-高等unix程式設計:chapter4

System Data Files and Information

0x00 Outline

  • Overview
  • Password
  • Group
  • Accounting
  • System Identification
  • Time and Data Resiurce

0x01 Overview

  • Linux 中有很多 data file,許多系統相關的設定檔會放在 /etc 底下
  • Password file : /etc/passwd
  • Group file : /etc/group
  • 這些設定檔一般為 ASCII text file,可以透過 standard I/O 存取
  • id command will return user identity

0x02 Password

passwd file

Description struct password member
User name char *pw_name
Encrypted password char *pw_passwd
Numerical user id uid_t pw_uid
Nunerical group id gid_t pw_gid
Comment field char *pw_gecos
Initial working dir char *pw_dir
Initial shell char *pw_shell
User access class char *pw_class
Next time to change password time_t pw_change
Account expiration time time_t pw_expire
  • passwd 檔案裡以 : 隔開每個欄位
  • 欄位可以是空的
  • 許多系統上的 service 都有自己的 uid 和 gid
  • shell 是 user login 時的第一支 process
    • 可以用 /dev/null/bin/false/sbin/nologin 等方式拒絕 user 登入系統
    • user可選用的合法 shell 列再 /etc/shells
  • finger command is a user information lookup program
    • 從 password database 讀取 user 資料

Function to Retrieve Password Information

include <pwd.h>
 
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
 
struct passwd {
    char   *pw_name;       /* username */
    char   *pw_passwd;     /* user password */
    uid_t   pw_uid;        /* user ID */
    gid_t   pw_gid;        /* group ID */
    char   *pw_gecos;      /* user information */
    char   *pw_dir;        /* home directory */
    char   *pw_shell;      /* shell program */
};
  • 根據 uid 或 username 取得特定使用者的 password information
#include <sys/types.h>
#include <pwd.h>
 
struct passwd *getpwent(void);
void setpwent(void);
void endpwent(void);
  • getpwent() function 取得 passwd database 的 next entry
  • setpwent() function 將指標重新指向 passwd database 的開頭 entry
  • endpwent() function 用來關閉 passwd database

User and Shadow Passwords

  • 以往加密過的密碼是存放在 /etc/passwd
  • 目前的 UNIX 作業系統則將加密密碼儲存在其他檔案,只允許 administrator 讀取
    • Freebsd: /etc/master.passwd
    • Linux: /etc/shadow
  • 只有少數程式會需要存取加密的密碼,像是 login(1)、passwd(1)

Linux's Shadow Structure

#include <shadow.h>
 
struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
 
struct spwd {
    char *sp_namp;     /* Login name */
    char *sp_pwdp;     /* Encrypted password */
    long  sp_lstchg;   /* Date of last change
                          (measured in days since
                          1970-01-01 00:00:00 +0000 (UTC)) */
    long  sp_min;      /* Min # of days between changes */
    long  sp_max;      /* Max # of days between changes */
    long  sp_warn;     /* # of days before password expires
                          to warn user to change it */
    long  sp_inact;    /* # of days after password expires
                          until account is disabled */
    long  sp_expire;   /* Date when account expires
                          (measured in days since
                          1970-01-01 00:00:00 +0000 (UTC)) */
    unsigned long sp_flag;  /* Reserved */
};

More on User Passwords

  • 密碼被保存時是加密的,see crypt(3)
  • 保存在 master.passwd 或 shadow 中時,密碼欄位是以 Algorithm id + Salt + Encrypted 紀錄,三者以 $ 連接
    • 加密演算法常見的為 DES
    • Algorithm id 部分是指使用的 hash 演算法
      • md5 : 1
      • sha256 : 5
      • sha512 : 6
  • Salt 的目的是增加安全性,讓同樣的密碼因為不同 salt 可以 hash 出不同結果
#include <unistd.h>
 
char *crypt(const char *key, const char *salt);
  • crypt 是一個加密函式
  • 會取 key 中的前八個字元,每個字元低位的 7bit,形成 56 bits 的 key,超過八個字元後的 key 無意義
  • salt 會在 [a-zA-Z0-9./]中取兩位,共 64*64=4096 種組合
  • 使用此函式時,編譯要加上 -lcrypt 參數

0x03 Group

group file

Description struct group member
Group name char *gr_name
Encrypted password char *gr_passwd
Nunerical group id gid_t gr_gid v
Array of pointers to individual user names

};
</code>

  • 根據 gid 或 group name 取得特定使用者的 group information
#include <sys/types.h>
#include <grp.h>
 
struct group *getpwent(void);
void setgrent(void);
void endgrent(void);
  • getgrent() function 取得 group database 的 next entry
  • setgrent() function 將指標重新指向 group database 的開頭 entry
  • endgrent() function 用來關閉 group database

Supplement Group IDs

  • newgroup(1) change to a new group,this will create a new shell execution envirement with modified real gid and egid
  • /etc/passwd 中記錄著每個 user 的 default gid
  • user 除了 default 之外也可以同時屬於多個 group
  • permission check 時會包含 user 所屬的所有群組
  • user 除了 default group 之外可加入的額外群組限制在 NGROUPS_MAX, 一般是 16

Group setup function

#include <unistd.h>
#include <grp.h>
 
int getgroups(int gidsetsize, gid_t grouplist[]);
int initgroups(const char *user, gid_t group);
int setgroups(size_t size, const gid_t *list);
  • initgroups(3) setup gid and supplement group IDs for a user based on /etc/group
  • setgroups(2) setup supplement group IDs, usually called by initgroups(3)

Other Data Files

Description Data file Header Structure Lookup function
password /etc/passwd <pwd.h> passwd getpwnam, getpwuid
groups /etc/groups <grp.h> group getgrnam, getgrgid
shadow /etc/shadow <shadow.h> shwd getspnam
hosts /etc/hosts <netdb.h> hostent gethostbyname, gethostbyaddr
networks /etc/networks <netdb.h> netent getnetbyname, getnetbyaddr
protocols /etc/protocols <netdb.h> protornt getprotobynabe, getprotobynumber
services /etc/services <netdb.h> servent getservbyname, getservbyport

0x04 Accounting

  • utmp: 紀錄目前登入的 user
  • wtmp: 紀錄過往的登入、登出、system up/down/reboot 活動
  • last、w、who command
struct utmp {
char ut_line[8]; /* tty line: "ttyh0", "ttyd0", "ttyp0", ... */
char ut_user[8]; /* login name */
long ut_time; /* seconds since Epoch */
};

0x05 System Identification

The uname function

#include <sys/utsname.h>
 
int uname(struct utsname *name);
 
struct utsname {
char sysname[]; /* name of the operating system */
char nodename[]; /* name of this node */
char release[]; /* current release of operating system */
char version[]; /* current version of this release */
char machine[]; /* name of hardware type */
};
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/utsname.h>
 
int main(void) {
 
   struct utsname buffer;
 
   errno = 0;
   if (uname(&buffer) != 0) {
      perror("uname");
      exit(EXIT_FAILURE);
   }
 
   printf("system name = %s\n", buffer.sysname);
   printf("node name   = %s\n", buffer.nodename);
   printf("release     = %s\n", buffer.release);
   printf("version     = %s\n", buffer.version);
   printf("machine     = %s\n", buffer.machine);
 
   #ifdef _GNU_SOURCE
      printf("domain name = %s\n", buffer.domainname);
   #endif
 
   return EXIT_SUCCESS;
}

The uname command

  • System
  • Node
  • Release
  • Version
  • Machine
  • Processor
  • Hardware platform
  • Operating system
$ uname -a
Linux ubuntu-vm 3.16.0-62-generic #83~14.04.1-Ubuntu SMP
Fri Feb 26 22:52:39 UTC 2016 x86_64 x86_64 x86_64
GNU/Linux

0x06 Time and Data Routines

tm structure

#include <time.h>
#include <sys/time.h>
 
time_t time(time_t *t);
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
 
struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};
 
struct timezone {
    int tz_minuteswest;     /* minutes west of Greenwich */
    int tz_dsttime;         /* type of DST correction */
};
  • time(2):取得 1970-01-01 00:00:00 +0000 (UTC) 至今經過的時間,單位為 second
  • gettimeofday(2): 取得 1970-01-01 00:00:00 +0000 (UTC) 至今經過的時間,單位為 milliseconds
#include <time.h>
 
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
 
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
 
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
 
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
 
time_t mktime(struct tm *tm);
 
struct tm {
    int tm_sec;         /* seconds */
    int tm_min;         /* minutes */
    int tm_hour;        /* hours */
    int tm_mday;        /* day of the month */
    int tm_mon;         /* month */
    int tm_year;        /* year */
    int tm_wday;        /* day of the week */
    int tm_yday;        /* day in the year */
    int tm_isdst;       /* daylight saving time */
};
  • ctime(), gmtime() and localtime() functions 將參數時間從 time_t (from 1970) 格式轉為 struct tm (human readable)
  • asctime() and mktime()function 將參數時間從 struct tm 轉換回 time_t
  • ctime(t) is equivalent to asctime(localtime(t))
#include <time.h>
 
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);

Time Zone

  • TZ 環境變數
  • tzset(3)

0x07參考資料

course/nctu-高等unix程式設計/chapter4.txt · 上一次變更: 127.0.0.1