diff options
author | Baban Kenkre <Baban.Kenkre@Sun.COM> | 2008-11-07 12:09:53 -0800 |
---|---|---|
committer | Baban Kenkre <Baban.Kenkre@Sun.COM> | 2008-11-07 12:09:53 -0800 |
commit | 2b4a78020b9c38d1b95e2f3fefa6d6e4be382d1f (patch) | |
tree | b9f0bc817d950cefb1af4653dad8de547a17e061 /usr/src/lib/nsswitch/files/common/getpwnam.c | |
parent | 0a2b1d27cac02f57e17b310f8baeb1dda082c83a (diff) | |
download | illumos-gate-2b4a78020b9c38d1b95e2f3fefa6d6e4be382d1f.tar.gz |
PSARC/2008/441 Active Directory name service module (nss_ad)
6722476 name service switch module for AD (nss_ad) needed
Diffstat (limited to 'usr/src/lib/nsswitch/files/common/getpwnam.c')
-rw-r--r-- | usr/src/lib/nsswitch/files/common/getpwnam.c | 100 |
1 files changed, 82 insertions, 18 deletions
diff --git a/usr/src/lib/nsswitch/files/common/getpwnam.c b/usr/src/lib/nsswitch/files/common/getpwnam.c index 8faa2014eb..570eec84ad 100644 --- a/usr/src/lib/nsswitch/files/common/getpwnam.c +++ b/usr/src/lib/nsswitch/files/common/getpwnam.c @@ -19,14 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * files/getpwnam.c -- "files" backend for nsswitch "passwd" database */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <pwd.h> #include <shadow.h> #include <unistd.h> /* for PF_PATH */ @@ -70,16 +68,16 @@ hash_pwuid(nss_XbyY_args_t *argp, int keyhash, const char *line, if (keyhash) return ((uint_t)argp->key.uid); - /* skip username */ - while (linep < limit && *linep++ != ':'); - /* skip password */ - while (linep < limit && *linep++ != ':'); + while (linep < limit && *linep++ != ':') /* skip username */ + continue; + while (linep < limit && *linep++ != ':') /* skip password */ + continue; if (linep == limit) return (UID_NOBODY); /* uid */ end = linep; - id = (uint_t)strtol(linep, (char **)&end, 10); + id = (uint_t)strtoul(linep, (char **)&end, 10); /* empty uid */ if (linep == end) @@ -129,7 +127,7 @@ static int check_pwuid(nss_XbyY_args_t *argp, const char *line, int linelen) { const char *linep, *limit, *end; - uid_t pw_uid; + ulong_t pw_uid; linep = line; limit = line + linelen; @@ -138,22 +136,22 @@ check_pwuid(nss_XbyY_args_t *argp, const char *line, int linelen) if (linelen == 0 || *line == '+' || *line == '-') return (0); - /* skip username */ - while (linep < limit && *linep++ != ':'); - /* skip password */ - while (linep < limit && *linep++ != ':'); + while (linep < limit && *linep++ != ':') /* skip username */ + continue; + while (linep < limit && *linep++ != ':') /* skip password */ + continue; if (linep == limit) return (0); /* uid */ end = linep; - pw_uid = (uid_t)strtol(linep, (char **)&end, 10); + pw_uid = strtoul(linep, (char **)&end, 10); - /* empty uid is not valid */ - if (linep == end) + /* check if the uid is empty or overflows */ + if (linep == end || pw_uid > UINT32_MAX) return (0); - return (pw_uid == argp->key.uid); + return ((uid_t)pw_uid == argp->key.uid); } static nss_status_t @@ -161,7 +159,73 @@ getbyuid(be, a) files_backend_ptr_t be; void *a; { - return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_pwuid)); + nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; + + if (argp->key.uid > MAXUID) + return (NSS_NOTFOUND); + return (_nss_files_XY_hash(be, argp, 0, &hashinfo, 1, check_pwuid)); +} + +/* + * Validates passwd entry replacing uid/gid > MAXUID by ID_NOBODY. + */ +int +validate_passwd_ids(char *line, int *linelenp, int buflen, int extra_chars) +{ + char *linep, *limit, *uidp, *gidp; + uid_t uid; + gid_t gid; + ulong_t uidl, gidl; + int olduidlen, oldgidlen, idlen; + int linelen = *linelenp, newlinelen; + + /* + * +name entries in passwd(4) do not override uid and gid + * values. Therefore no need to validate the ids in these + * entries. + */ + if (linelen == 0 || *line == '+' || *line == '-') + return (NSS_STR_PARSE_SUCCESS); + + linep = line; + limit = line + linelen; + + while (linep < limit && *linep++ != ':') /* skip username */ + continue; + while (linep < limit && *linep++ != ':') /* skip password */ + continue; + if (linep == limit) + return (NSS_STR_PARSE_PARSE); + + uidp = linep; + uidl = strtoul(uidp, (char **)&linep, 10); /* grab uid */ + olduidlen = linep - uidp; + if (++linep >= limit || olduidlen == 0) + return (NSS_STR_PARSE_PARSE); + + gidp = linep; + gidl = strtoul(gidp, (char **)&linep, 10); /* grab gid */ + oldgidlen = linep - gidp; + if (linep >= limit || oldgidlen == 0) + return (NSS_STR_PARSE_PARSE); + + if (uidl <= MAXUID && gidl <= MAXUID) + return (NSS_STR_PARSE_SUCCESS); + uid = (uidl > MAXUID) ? UID_NOBODY : (uid_t)uidl; + gid = (gidl > MAXUID) ? GID_NOBODY : (gid_t)gidl; + + /* Check if we have enough space in the buffer */ + idlen = snprintf(NULL, 0, "%u:%u", uid, gid); + newlinelen = linelen + idlen - olduidlen - oldgidlen - 1; + if (newlinelen + extra_chars > buflen) + return (NSS_STR_PARSE_ERANGE); + + /* Replace ephemeral ids by ID_NOBODY */ + (void) bcopy(linep, uidp + idlen, limit - linep + extra_chars); + (void) snprintf(uidp, idlen + 1, "%u:%u", uid, gid); + *(uidp + idlen) = ':'; /* restore : that was overwritten by snprintf */ + *linelenp = newlinelen; + return (NSS_STR_PARSE_SUCCESS); } static files_backend_op_t passwd_ops[] = { |