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