diff options
| author | Rich Felker <dalias@aerifal.cx> | 2011-02-12 00:22:29 -0500 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2011-02-12 00:22:29 -0500 | 
| commit | 0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 (patch) | |
| tree | 6eaef0d8a720fa3da580de87b647fff796fe80b3 /src/passwd | |
| download | musl-0b44a0315b47dd8eced9f3b7f31580cf14bbfc01.tar.gz | |
initial check-in, version 0.5.0v0.5.0
Diffstat (limited to 'src/passwd')
| -rw-r--r-- | src/passwd/getgr_r.c | 53 | ||||
| -rw-r--r-- | src/passwd/getgrent.c | 39 | ||||
| -rw-r--r-- | src/passwd/getgrent_a.c | 46 | ||||
| -rw-r--r-- | src/passwd/getpw_r.c | 46 | ||||
| -rw-r--r-- | src/passwd/getpwent.c | 39 | ||||
| -rw-r--r-- | src/passwd/getpwent_a.c | 37 | ||||
| -rw-r--r-- | src/passwd/getspent.c | 14 | ||||
| -rw-r--r-- | src/passwd/getspnam.c | 17 | ||||
| -rw-r--r-- | src/passwd/getspnam_r.c | 89 | ||||
| -rw-r--r-- | src/passwd/lckpwdf.c | 11 | ||||
| -rw-r--r-- | src/passwd/pwf.h | 13 | 
11 files changed, 404 insertions, 0 deletions
diff --git a/src/passwd/getgr_r.c b/src/passwd/getgr_r.c new file mode 100644 index 00000000..5b1333e3 --- /dev/null +++ b/src/passwd/getgr_r.c @@ -0,0 +1,53 @@ +#include "pwf.h" + +#define FIX(x) (gr->gr_##x = gr->gr_##x-line+buf) + +static int getgr_r(const char *name, gid_t gid, struct group *gr, char *buf, size_t size, struct group **res) +{ +	FILE *f; +	char *line = 0; +	size_t len = 0; +	char **mem = 0; +	size_t nmem = 0; +	int rv = 0; +	size_t i; + +	f = fopen("/etc/group", "rb"); +	if (!f) return errno; + +	*res = 0; +	while (__getgrent_a(f, gr, &line, &len, &mem, &nmem)) { +		if (name && !strcmp(name, gr->gr_name) +		|| !name && gr->gr_gid == gid) { +			if (size < len + nmem*sizeof(char *) + 32) { +				rv = ERANGE; +				break; +			} +			*res = gr; +			buf += (16-(uintptr_t)buf)%16; +			gr->gr_mem = (void *)buf; +			buf += nmem*sizeof(char *); +			memcpy(buf, line, len); +			FIX(name); +			FIX(passwd); +			for (i=0; mem[i]; i++) +				gr->gr_mem[i] = mem[i]-line+buf; +			gr->gr_mem[i] = 0; +			break; +		} +	} + 	free(mem); + 	free(line); +	fclose(f); +	return rv; +} + +int getgrnam_r(const char *name, struct group *gr, char *buf, size_t size, struct group **res) +{ +	return getgr_r(name, 0, gr, buf, size, res); +} + +int getgruid_r(gid_t gid, struct group *gr, char *buf, size_t size, struct group **res) +{ +	return getgr_r(0, gid, gr, buf, size, res); +} diff --git a/src/passwd/getgrent.c b/src/passwd/getgrent.c new file mode 100644 index 00000000..e9d25eba --- /dev/null +++ b/src/passwd/getgrent.c @@ -0,0 +1,39 @@ +#include "pwf.h" + +static FILE *f; + +void setgrent() +{ +	if (f) fclose(f); +	f = 0; +} + +weak_alias(setgrent, endgrent); + +struct group *getgrent() +{ +	static char *line, **mem; +	static struct group gr; +	size_t size=0, nmem=0; +	if (!f) f = fopen("/etc/group", "rb"); +	if (!f) return 0; +	return __getgrent_a(f, &gr, &line, &size, &mem, &nmem); +} + +struct group *getgrgid(gid_t gid) +{ +	struct group *gr; +	setgrent(); +	while ((gr=getgrent()) && gr->gr_gid != gid); +	endgrent(); +	return gr; +} + +struct group *getgrnam(const char *name) +{ +	struct group *gr; +	setgrent(); +	while ((gr=getgrent()) && strcmp(gr->gr_name, name)); +	endgrent(); +	return gr; +} diff --git a/src/passwd/getgrent_a.c b/src/passwd/getgrent_a.c new file mode 100644 index 00000000..ccb51d52 --- /dev/null +++ b/src/passwd/getgrent_a.c @@ -0,0 +1,46 @@ +#include "pwf.h" + +struct group *__getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem) +{ +	ssize_t l; +	char *s, *mems; +	size_t i; + +	for (;;) { +		if ((l=getline(line, size, f)) < 0) { +			free(*line); +			*line = 0; +			return 0; +		} +		line[0][l-1] = 0; + +		s = line[0]; +		gr->gr_name = s++; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; gr->gr_passwd = s; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; gr->gr_gid = atoi(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; mems = s; +		break; +	} + +	for (*nmem=!!*s; *s; s++) +		if (*s==',') ++*nmem; +	free(*mem); +	*mem = calloc(sizeof(char *), *nmem+1); +	if (!*mem) { +		free(*line); +		*line = 0; +		return 0; +	} +	mem[0][0] = mems; +	for (s=mems, i=0; *s; s++) +		if (*s==',') *s++ = 0, mem[0][++i] = s; +	mem[0][++i] = 0; +	gr->gr_mem = *mem; +	return gr; +} diff --git a/src/passwd/getpw_r.c b/src/passwd/getpw_r.c new file mode 100644 index 00000000..7b331e8a --- /dev/null +++ b/src/passwd/getpw_r.c @@ -0,0 +1,46 @@ +#include "pwf.h" + +#define FIX(x) (pw->pw_##x = pw->pw_##x-line+buf) + +static int getpw_r(const char *name, uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res) +{ +	FILE *f; +	char *line = 0; +	size_t len = 0; +	int rv = 0; + +	f = fopen("/etc/passwd", "rb"); +	if (!f) return errno; + +	*res = 0; +	while (__getpwent_a(f, pw, &line, &len)) { +		if (name && !strcmp(name, pw->pw_name) +		|| !name && pw->pw_uid == uid) { +			if (size < len) { +				rv = ERANGE; +				break; +			} +			*res = pw; +			memcpy(buf, line, len); +			FIX(name); +			FIX(passwd); +			FIX(gecos); +			FIX(dir); +			FIX(shell); +			break; +		} +	} + 	free(line); +	fclose(f); +	return rv; +} + +int getpwnam_r(const char *name, struct passwd *pw, char *buf, size_t size, struct passwd **res) +{ +	return getpw_r(name, 0, pw, buf, size, res); +} + +int getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res) +{ +	return getpw_r(0, uid, pw, buf, size, res); +} diff --git a/src/passwd/getpwent.c b/src/passwd/getpwent.c new file mode 100644 index 00000000..dabd411a --- /dev/null +++ b/src/passwd/getpwent.c @@ -0,0 +1,39 @@ +#include "pwf.h" + +static FILE *f; + +void setpwent() +{ +	if (f) fclose(f); +	f = 0; +} + +weak_alias(setpwent, endpwent); + +struct passwd *getpwent() +{ +	static char *line; +	static struct passwd pw; +	size_t size=0; +	if (!f) f = fopen("/etc/passwd", "rb"); +	if (!f) return 0; +	return __getpwent_a(f, &pw, &line, &size); +} + +struct passwd *getpwuid(uid_t uid) +{ +	struct passwd *pw; +	setpwent(); +	while ((pw=getpwent()) && pw->pw_uid != uid); +	endpwent(); +	return pw; +} + +struct passwd *getpwnam(const char *name) +{ +	struct passwd *pw; +	setpwent(); +	while ((pw=getpwent()) && strcmp(pw->pw_name, name)); +	endpwent(); +	return pw; +} diff --git a/src/passwd/getpwent_a.c b/src/passwd/getpwent_a.c new file mode 100644 index 00000000..aaf84edd --- /dev/null +++ b/src/passwd/getpwent_a.c @@ -0,0 +1,37 @@ +#include "pwf.h" + +struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size) +{ +	ssize_t l; +	char *s; +	for (;;) { +		if ((l=getline(line, size, f)) < 0) { +			free(*line); +			*line = 0; +			return 0; +		} +		line[0][l-1] = 0; + +		s = line[0]; +		pw->pw_name = s++; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; pw->pw_passwd = s; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; pw->pw_uid = atoi(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; pw->pw_gid = atoi(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; pw->pw_gecos = s; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; pw->pw_dir = s; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; pw->pw_shell = s; +		return pw; +	} +} diff --git a/src/passwd/getspent.c b/src/passwd/getspent.c new file mode 100644 index 00000000..8574a480 --- /dev/null +++ b/src/passwd/getspent.c @@ -0,0 +1,14 @@ +#include "pwf.h" + +void setspent() +{ +} + +void endspent() +{ +} + +struct spwd *getspent() +{ +	return 0; +} diff --git a/src/passwd/getspnam.c b/src/passwd/getspnam.c new file mode 100644 index 00000000..041f8965 --- /dev/null +++ b/src/passwd/getspnam.c @@ -0,0 +1,17 @@ +#include "pwf.h" + +#define LINE_LIM 256 + +struct spwd *getspnam(const char *name) +{ +	static struct spwd sp; +	static char *line; +	struct spwd *res; +	int e; + +	if (!line) line = malloc(LINE_LIM); +	if (!line) return 0; +	e = getspnam_r(name, &sp, line, LINE_LIM, &res); +	if (e) errno = e; +	return res; +} diff --git a/src/passwd/getspnam_r.c b/src/passwd/getspnam_r.c new file mode 100644 index 00000000..1dd39ce0 --- /dev/null +++ b/src/passwd/getspnam_r.c @@ -0,0 +1,89 @@ +#include <fcntl.h> +#include <unistd.h> +#include "pwf.h" + +/* This implementation support Openwall-style TCB passwords in place of + * traditional shadow, if the appropriate directories and files exist. + * Thus, it is careful to avoid following symlinks or blocking on fifos + * which a malicious user might create in place of his or her TCB shadow + * file. It also avoids any allocation to prevent memory-exhaustion + * attacks via huge TCB shadow files. */ + +int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct spwd **res) +{ +	char path[20+NAME_MAX]; +	FILE *f = 0; +	int rv = 0; +	int fd; +	size_t k, l = strlen(name); +	char *s; +	int skip = 0; + +	*res = 0; + +	/* Disallow potentially-malicious user names */ +	if (*name=='.' || strchr(name, '/') || !l) +		return EINVAL; + +	/* Buffer size must at least be able to hold name, plus some.. */ +	if (size < l+100) return ERANGE; + +	/* Protect against truncation */ +	if (snprintf(path, sizeof path, "/etc/tcb/%s/shadow", name) >= sizeof path) +		return EINVAL; + +	fd = open(path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK); +	if (fd >= 0) { +		f = fdopen(fd, "rb"); +		if (!f) { +			close(fd); +			return errno; +		} +	} else { +		f = fopen("/etc/shadow", "rb"); +		if (!f) return errno; +	} + +	while (fgets(buf, size, f) && (k=strlen(buf))>0) { +		if (skip || strncmp(name, buf, l)) { +			skip = buf[k-1] != '\n'; +			continue; +		} +		if (buf[k-1] != '\n') { +			rv = ERANGE; +			break; +		} +		buf[k-1] = 0; + +		s = buf; +		sp->sp_namp = s; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_pwdp = s; +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_lstchg = atol(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_min = atol(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_max = atol(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_warn = atol(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_inact = atol(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_expire = atol(s); +		if (!(s = strchr(s, ':'))) continue; + +		*s++ = 0; sp->sp_flag = atol(s); +		*res = sp; +		break; +	} +	fclose(f); +	return rv; +} diff --git a/src/passwd/lckpwdf.c b/src/passwd/lckpwdf.c new file mode 100644 index 00000000..2feda617 --- /dev/null +++ b/src/passwd/lckpwdf.c @@ -0,0 +1,11 @@ +#include <shadow.h> + +int lckpwdf() +{ +	return 0; +} + +int ulckpwdf() +{ +	return 0; +} diff --git a/src/passwd/pwf.h b/src/passwd/pwf.h new file mode 100644 index 00000000..0a76ef80 --- /dev/null +++ b/src/passwd/pwf.h @@ -0,0 +1,13 @@ +#include <pwd.h> +#include <grp.h> +#include <shadow.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <limits.h> +#include "libc.h" + +struct passwd *__getpwent_a(FILE *f, struct passwd *pw, char **line, size_t *size); +struct spwd *__getspent_a(FILE *f, struct spwd *sp, char **line, size_t *size); +struct group *__getgrent_a(FILE *f, struct group *gr, char **line, size_t *size, char ***mem, size_t *nmem);  | 
