From 0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 12 Feb 2011 00:22:29 -0500 Subject: initial check-in, version 0.5.0 --- src/passwd/getgr_r.c | 53 +++++++++++++++++++++++++++++ src/passwd/getgrent.c | 39 ++++++++++++++++++++++ src/passwd/getgrent_a.c | 46 +++++++++++++++++++++++++ src/passwd/getpw_r.c | 46 +++++++++++++++++++++++++ src/passwd/getpwent.c | 39 ++++++++++++++++++++++ src/passwd/getpwent_a.c | 37 ++++++++++++++++++++ src/passwd/getspent.c | 14 ++++++++ src/passwd/getspnam.c | 17 ++++++++++ src/passwd/getspnam_r.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ src/passwd/lckpwdf.c | 11 ++++++ src/passwd/pwf.h | 13 ++++++++ 11 files changed, 404 insertions(+) create mode 100644 src/passwd/getgr_r.c create mode 100644 src/passwd/getgrent.c create mode 100644 src/passwd/getgrent_a.c create mode 100644 src/passwd/getpw_r.c create mode 100644 src/passwd/getpwent.c create mode 100644 src/passwd/getpwent_a.c create mode 100644 src/passwd/getspent.c create mode 100644 src/passwd/getspnam.c create mode 100644 src/passwd/getspnam_r.c create mode 100644 src/passwd/lckpwdf.c create mode 100644 src/passwd/pwf.h (limited to 'src/passwd') 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 +#include +#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 + +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 +#include +#include +#include +#include +#include +#include +#include +#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); -- cgit v1.2.1