The Linux Programming Interface
Users And Groups
(01)用户和组
Every user has a unique login name and an associated numeric user identifier (UID). Users can belong to one or more groups. Each group also has a unique name and a group identifier(GID).
(02) /etc/passwd文件
放有用户名,登录ID等信息。
(03) 密码文件 /etc/shadow
The shadow password file, /etc/shadow, was devised as a method of preventing such attacks.
(04) /etc/group
组函数文件夹
(05)获取用户和组信息
#include <pwd.h>
struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
Given a login name in name, the getpwnam() function returns a pointer to a structure of the following type, containing the corresponding information from the password record:
struct passwd {
char *pw_name; /* Login name (username) */
char *pw_passwd; /* Encrypted password */
uid_t pw_uid; /* User ID */
gid_t pw_gid; /* Group ID */
char *pw_gecos; /* Comment (user information) */
char *pw_dir; /* Initial working (home) directory */
char *pw_shell; /* Login shell */
};
(06) getpwnam, getpwuid, getgrnam, getgrgid举例
通过uid 得到name, 通过name 得到uid,还有组。
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include "ugid_functions.h" /* Declares functions defined here */
/* Return name corresponding to 'uid', or NULL on error */
char * userNameFromId(uid_t uid) {
struct passwd *pwd;
pwd = getpwuid(uid);
return (pwd == NULL) ? NULL : pwd->pw_name;
}
/* Return UID corresponding to 'name', or -1 on error */
uid_t userIdFromName(const char *name) {
struct passwd *pwd;
uid_t u;
char *endptr;
if (name == NULL || *name == '\0')
return -1;
u = strtol(name, &endptr, 10)
if (*endptr == '\0')
return u;
pwd = getpwnam(name);
if (pwd == NULL)
return -1;
return pwd->pw_uid;
}
/* Return name corresponding to 'gid', or NULL on error */
char *groupNameFromId(git_t gid) {
struct group *grp;
grp = getgrpid(gid);
return (grp == NULL) ? NULL : grp->gr_name;
}
/* Return GID corresponding to 'name', or -1 on error */
gid_t groupIdFromName(const char *name) {
struct group *grp;
gid_t g;
char *endptr;
if (name == NULL || *name == '\0')
return -1;
g = strtol(name, &endptr, 10)
if (*endptr == '\0')
return g;
grp = getgrnam(name);
if (grp == NULL)
return -1;
return grp->gr_gid;
}
(07)得到所有的信息
#include <pwd.h>
#include <stdio.h>
int main() {
struct passwd *pwd;
while ((pwd = getpwent()) != NULL)
printf("%-8s %5ld\n", pwd->pw_name, (long) pwd->pw_uid);
return 0;
}
输出:
wang@wang:~/Documents/tlpi-dist/users_groups$ ./getall
root 0
daemon 1
bin 2
sys 3
sync 4
games 5
man 6
lp 7
mail 8
news 9
uucp 10
proxy 13
www-data 33
backup 34
list 38
irc 39
gnats 41
nobody 65534
systemd-timesync 100
systemd-network 101
systemd-resolve 102
systemd-bus-proxy 103
syslog 104
_apt 105
messagebus 106
uuidd 107
lightdm 108
whoopsie 109
avahi-autoipd 110
avahi 111
dnsmasq 112
colord 113
speech-dispatcher 114
hplip 115
kernoops 116
pulse 117
rtkit 118
saned 119
usbmux 120
wang 1000
(08) 组
The getgrent(), setgrent(), and endgrent() functions perform analogous tasks fro the group file.
(09)验证登录,结果是没有权限。
#define _BSD_SOURCE /* Get getpass() declaration from <unisstd.h> */
#include <limits.h>
#include <pwd.h>
#include <shadow.h>
#include "tlpi_hdr.h"
#define _XOPEN_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
int main(int argc, char *argv[]) {
char *username, *password, *encrypted, *p;
struct passwd *pwd;
struct spwd *spwd;
Boolean authOk;
size_t len;
long lnmax;
lnmax = sysconf(_SC_LOGIN_NAME_MAX);
if (lnmax == -1)
lnmax = 256;
username = malloc(lnmax);
if (username == NULL)
errExit("malloc");
printf("Username: ");
fflush(stdout);
if (fgets(username, lnmax, stdin) == NULL)
exit(EXIT_FAILURE);
len = strlen(username);
if (username[len - 1] == '\n')
username[len - 1] = '\0';
pwd = getpwnam(username);
if (pwd == NULL)
fatal("couldn't get password record");
spwd = getspnam(username);
if (pwd == NULL)
fatal("couldn't get password record");
spwd = getspnam(username);
if (spwd == NULL && errno == EACCES)
fatal("no permission to read shadow password file");
/* If there is a shadow password record, use the shadow password */
if (spwd != NULL)
pwd->pw_passwd = spwd->sp_pwdp;
password = getpass("Password: ");
/* Encrypt password and erase cleartext version immediately */
encrypted = crypt(password, pwd->pw_passwd);
for (p = password; *p != '\0';)
*p++ = '\0';
if (encrypted == NULL)
errExit("crypt");
authOk = strcmp(encrypted, pwd->pw_passwd) == 0;
if (!authOk) {
printf("Incorrect password\n");
exit(EXIT_FAILURE);
}
printf("Successfully authenticated: UID=%ld\n", (long) pwd->pw_uid);
/* Now do authenticated work ... */
exit(EXIT_SUCCESS);
}
有些悲催的输出:
wang@wang:~/Documents/tlpi-dist/lib$ ./check_password
Username: wang
ERROR: no permission to read shadow password file
(10)总结
Each user has a unique login name and an associated numeric user ID. Users can belong to one or more groups, each of which also has a unique name and an associated numeric numeric identifier. The primary purpose of these identifiers is to establish ownership of various system resources (e.g., files) and permissions for accessing them.
A user's name and ID are defined in the /etc/passwd file, which also contains others information about the user. A user's group membership are defined by fields in the /etc/passwd/ and /etc/group files. A furher file, /etc/shadow, which can be read only by privileged processes, is used to separate the sensitive password information from the publicly available user information in /etc/passwd. Various library functions are provided for retrieving information from each of these files.
The crypt() function encrypts a passwd in the same manner as the standard login program, which is useful for program that need to authenticate users.
(11)习题