diff options
author | Blake Setlow <csetlow@tower-research.com> | 2008-01-22 22:40:07 (GMT) |
---|---|---|
committer | Michael Stone <michael@laptop.org> | 2008-01-22 22:40:07 (GMT) |
commit | c8e10eb4ae55f5986344ddc8c230ee9f89fc429e (patch) | |
tree | a1682990624f5a537bcfaee29442f02130cbb63a | |
parent | 63865355abb28047bfb2eb152094b65f9c0a220c (diff) |
getpwuid_r and getpwnam_r prototypes.
-rw-r--r-- | nss-rainbow.c | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/nss-rainbow.c b/nss-rainbow.c index f898ecc..f0fc376 100644 --- a/nss-rainbow.c +++ b/nss-rainbow.c @@ -39,6 +39,22 @@ _nss_rainbow_setpwent(void) { g_done = false; } +int write_buf(char* home, char** buf, size_t * buflen) +{ + size_t homelen; + homelen = strnlen(home, *buflen); + if (homelen == *buflen) + { + errno = ERANGE; + return -1; + } + strncpy(*buf, home, homelen); + (*buf)[homelen] = '\0'; + *buflen -= homelen + 1; + *buf += homelen + 1; + return 0; +} + enum nss_status _nss_rainbow_getpwent_r(struct passwd *result, char* buf, size_t buflen, int *errnop) { /* I'm going to interpret the reentrancy requirement on this function to mean @@ -56,23 +72,15 @@ _nss_rainbow_getpwent_r(struct passwd *result, char* buf, size_t buflen, int *er getenv("USER"), out_error_unavail, "Unable to retrieve $USER."); - LET(size_t, homelen, buflen, - strnlen(home, buflen), - out_error_buffer, "$HOME too long."); - strncpy(buf, home, homelen); result->pw_dir = buf; - buf[homelen] = '\0'; - buf += homelen + 1; - buflen -= homelen + 1; + CHECK(int, -1, + write_buf(home, &buf, &buflen), + out_error_buffer, "Not enough buffer for $HOME."); - LET(size_t, userlen, buflen, - strnlen(user, buflen), - out_error_buffer, "$USER too long."); - strncpy(buf, user, userlen); result->pw_gecos = result->pw_name = result->pw_passwd = buf; - buf[userlen] = '\0'; - buf += userlen + 1; - buflen -= userlen + 1; + CHECK(int, -1, + write_buf(user, &buf, &buflen), + out_error_buffer, "Not enough buffer for $USER."); CHECK(bool, true, strlen(SHELL) > buflen, @@ -95,3 +103,61 @@ out_error_buffer: *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } + +enum nss_status _nss_rainbow_getpwbyuid_r(uid_t uid, struct passwd *result, char* buf, size_t buflen, int *errnop) { + if (uid < 10000) + return NSS_STATUS_NOTFOUND; + int homelen = snprintf(buf, buflen, "/home/olpc/isolation/1/%d", uid); + if ((homelen <= 0) || (((unsigned int) homelen) >= buflen)) { + PERROR("Insufficient HOMEBUFLEN for the home for user uid."); + goto out_error_buffer;} + buf[homelen] = '\0'; + struct stat statbuf; + CHECK(int, -1, + stat(buf, &statbuf), + out_error_errno, "Stat failed for homebuf."); + result->pw_uid = uid; + result->pw_gid = statbuf.st_gid; + result->pw_dir = buf; + buf += homelen + 1; + buflen -= homelen + 1; + homelen = snprintf(buf, buflen, "%d", uid); + if ((homelen <= 0) || (((unsigned int ) homelen ) >= buflen)) { + PERROR("Insufficient HOMEBUFLEN for user uid as a string."); + goto out_error_buffer; + } + result->pw_gecos = result->pw_name = result->pw_passwd = buf; + buf += homelen + 1; + buflen -= homelen + 1; + CHECK(bool, true, + strlen(SHELL) > buflen, + out_error_buffer, "Shell string constant too long."); + strcpy(buf, SHELL); + result->pw_shell = buf; + // DO NOT USE BUF UNLESS YOU INCREMENT IT NOW. + // YOU ARE DONE. + + return NSS_STATUS_SUCCESS; + +out_error_buffer: + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; +out_error_errno: + return NSS_STATUS_TRYAGAIN; +} +enum nss_status _nss_rainbow_getpwbynam_r(const char * name, struct passwd *result, char* buf, size_t buflen, int *errnop) { + const char * endptr = name + strlen(name); + char * endptrt = (char *) (uintptr_t) endptr; + long uid = strtol(name, &endptrt, 10); + if (endptr != endptrt) { + PERROR("Entire name is not an integer."); + goto out_error_badname; + } + + // YOU ARE DONE. + return _nss_rainbow_getpwbyuid_r((uid_t)uid, result, buf, buflen, errnop); + +out_error_badname: + *errnop = EINVAL; + return NSS_STATUS_NOTFOUND; +} |