summaryrefslogtreecommitdiff
path: root/usr/src/lib/nsswitch/files/common/getpwnam.c
diff options
context:
space:
mode:
authorBaban Kenkre <Baban.Kenkre@Sun.COM>2008-11-07 12:09:53 -0800
committerBaban Kenkre <Baban.Kenkre@Sun.COM>2008-11-07 12:09:53 -0800
commit2b4a78020b9c38d1b95e2f3fefa6d6e4be382d1f (patch)
treeb9f0bc817d950cefb1af4653dad8de547a17e061 /usr/src/lib/nsswitch/files/common/getpwnam.c
parent0a2b1d27cac02f57e17b310f8baeb1dda082c83a (diff)
downloadillumos-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.c100
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[] = {