summaryrefslogtreecommitdiff
path: root/usr/src/lib/nsswitch/files/common
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
parent0a2b1d27cac02f57e17b310f8baeb1dda082c83a (diff)
downloadillumos-joyent-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')
-rw-r--r--usr/src/lib/nsswitch/files/common/files_common.c50
-rw-r--r--usr/src/lib/nsswitch/files/common/files_common.h8
-rw-r--r--usr/src/lib/nsswitch/files/common/getgrent.c95
-rw-r--r--usr/src/lib/nsswitch/files/common/getpwnam.c100
4 files changed, 208 insertions, 45 deletions
diff --git a/usr/src/lib/nsswitch/files/common/files_common.c b/usr/src/lib/nsswitch/files/common/files_common.c
index 74d47f7c8c..4b7b6753c1 100644
--- a/usr/src/lib/nsswitch/files/common/files_common.c
+++ b/usr/src/lib/nsswitch/files/common/files_common.c
@@ -25,8 +25,6 @@
* Common code and structures used by name-service-switch "files" backends.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* An implementation that used mmap() sensibly would be a wonderful thing,
* but this here is just yer standard fgets() thang.
@@ -299,9 +297,27 @@ _nss_files_XY_all(be, args, netdb, filter, check)
if (check != NULL && (*check)(args, instr, linelen) == 0)
continue;
- func = args->str2ent;
- parsestat = (*func)(instr, linelen, args->buf.result,
- args->buf.buffer, args->buf.buflen);
+ parsestat = NSS_STR_PARSE_SUCCESS;
+ if (be->filename != NULL) {
+ /*
+ * Special case for passwd and group wherein we
+ * replace uids/gids > MAXUID by ID_NOBODY
+ * because files backend does not support
+ * ephemeral ids.
+ */
+ if (strcmp(be->filename, PF_PATH) == 0)
+ parsestat = validate_passwd_ids(instr,
+ &linelen, be->minbuf, 2);
+ else if (strcmp(be->filename, GF_PATH) == 0)
+ parsestat = validate_group_ids(instr,
+ &linelen, be->minbuf, 2, check);
+ }
+
+ if (parsestat == NSS_STR_PARSE_SUCCESS) {
+ func = args->str2ent;
+ parsestat = (*func)(instr, linelen, args->buf.result,
+ args->buf.buffer, args->buf.buflen);
+ }
if (parsestat == NSS_STR_PARSE_SUCCESS) {
args->returnval = (args->buf.result != NULL)?
@@ -366,7 +382,7 @@ _nss_files_XY_hash(files_backend_ptr_t be, nss_XbyY_args_t *args,
int netdb, files_hash_t *fhp, int hashop, files_XY_check_func check)
{
/* LINTED E_FUNC_VAR_UNUSED */
- int fd, retries, ht;
+ int fd, retries, ht, stat;
/* LINTED E_FUNC_VAR_UNUSED */
uint_t hash, line, f;
/* LINTED E_FUNC_VAR_UNUSED */
@@ -412,6 +428,28 @@ retry:
if ((*check)(args, fhp->fh_line[line].l_start,
fhp->fh_line[line].l_len) == 0)
continue;
+
+ if (be->filename != NULL) {
+ stat = NSS_STR_PARSE_SUCCESS;
+ if (strcmp(be->filename, PF_PATH) == 0)
+ stat = validate_passwd_ids(
+ fhp->fh_line[line].l_start,
+ &fhp->fh_line[line].l_len,
+ fhp->fh_line[line].l_len + 1,
+ 1);
+ else if (strcmp(be->filename, GF_PATH) == 0)
+ stat = validate_group_ids(
+ fhp->fh_line[line].l_start,
+ &fhp->fh_line[line].l_len,
+ fhp->fh_line[line].l_len + 1,
+ 1, check);
+ if (stat != NSS_STR_PARSE_SUCCESS) {
+ if (stat == NSS_STR_PARSE_ERANGE)
+ args->erange = 1;
+ continue;
+ }
+ }
+
if ((*args->str2ent)(fhp->fh_line[line].l_start,
fhp->fh_line[line].l_len, args->buf.result,
args->buf.buffer, args->buf.buflen) ==
diff --git a/usr/src/lib/nsswitch/files/common/files_common.h b/usr/src/lib/nsswitch/files/common/files_common.h
index b526833022..2138d7180e 100644
--- a/usr/src/lib/nsswitch/files/common/files_common.h
+++ b/usr/src/lib/nsswitch/files/common/files_common.h
@@ -31,8 +31,6 @@
#ifndef _FILES_COMMON_H
#define _FILES_COMMON_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <nss_common.h>
#include <nss_dbdefs.h>
#include <stdio.h>
@@ -136,6 +134,12 @@ extern nss_status_t _nss_files_XY_hash();
int _nss_files_check_name_aliases(nss_XbyY_args_t *, const char *, int);
int _nss_files_check_name_colon(nss_XbyY_args_t *, const char *, int);
+/* passwd and group validation functions */
+extern int validate_group_ids(char *line, int *linelenp, int buflen,
+ int extra_chars, files_XY_check_func check);
+extern int validate_passwd_ids(char *line, int *linelenp, int buflen,
+ int extra_chars);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/nsswitch/files/common/getgrent.c b/usr/src/lib/nsswitch/files/common/getgrent.c
index 6f45136f16..455e070da4 100644
--- a/usr/src/lib/nsswitch/files/common/getgrent.c
+++ b/usr/src/lib/nsswitch/files/common/getgrent.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/getgrent.c -- "files" backend for nsswitch "group" database
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <grp.h>
#include <unistd.h> /* for GF_PATH */
#include <stdlib.h> /* for GF_PATH */
@@ -69,16 +67,16 @@ hash_grgid(nss_XbyY_args_t *argp, int keyhash, const char *line,
if (keyhash)
return ((uint_t)argp->key.gid);
- /* skip groupname */
- while (linep < limit && *linep++ != ':');
- /* skip password */
- while (linep < limit && *linep++ != ':');
+ while (linep < limit && *linep++ != ':') /* skip groupname */
+ continue;
+ while (linep < limit && *linep++ != ':') /* skip password */
+ continue;
if (linep == limit)
return (GID_NOBODY);
/* gid */
end = linep;
- id = (uint_t)strtol(linep, (char **)&end, 10);
+ id = (uint_t)strtoul(linep, (char **)&end, 10);
/* empty gid */
if (linep == end)
return (GID_NOBODY);
@@ -127,7 +125,7 @@ static int
check_grgid(nss_XbyY_args_t *argp, const char *line, int linelen)
{
const char *linep, *limit, *end;
- gid_t gr_gid;
+ ulong_t gr_gid;
linep = line;
limit = line + linelen;
@@ -136,22 +134,22 @@ check_grgid(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 groupname */
+ continue;
+ while (linep < limit && *linep++ != ':') /* skip password */
+ continue;
if (linep == limit)
return (0);
- /* uid */
+ /* gid */
end = linep;
- gr_gid = (gid_t)strtol(linep, (char **)&end, 10);
+ gr_gid = strtoul(linep, (char **)&end, 10);
- /* empty gid is not valid */
- if (linep == end)
+ /* check if gid is empty or overflows */
+ if (linep == end || gr_gid > UINT32_MAX)
return (0);
- return (gr_gid == argp->key.gid);
+ return ((gid_t)gr_gid == argp->key.gid);
}
static nss_status_t
@@ -159,7 +157,66 @@ getbygid(be, a)
files_backend_ptr_t be;
void *a;
{
- return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_grgid));
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+
+ if (argp->key.gid > MAXUID)
+ return (NSS_NOTFOUND);
+ return (_nss_files_XY_hash(be, argp, 0, &hashinfo, 1, check_grgid));
+}
+
+/*
+ * Validates group entry replacing gid > MAXUID by GID_NOBODY.
+ */
+int
+validate_group_ids(char *line, int *linelenp, int buflen, int extra_chars,
+ files_XY_check_func check)
+{
+ char *linep, *limit, *gidp;
+ ulong_t gid;
+ int oldgidlen, idlen;
+ int linelen = *linelenp, newlinelen;
+
+ /*
+ * getbygid() rejects searching by ephemeral gid therefore
+ * no need to validate because the matched entry won't have
+ * an ephemeral gid.
+ */
+ if (check != NULL && check == check_grgid)
+ return (NSS_STR_PARSE_SUCCESS);
+
+ /* +/- entries valid for compat source only */
+ if (linelen == 0 || *line == '+' || *line == '-')
+ return (NSS_STR_PARSE_SUCCESS);
+
+ linep = line;
+ limit = line + linelen;
+
+ while (linep < limit && *linep++ != ':') /* skip groupname */
+ continue;
+ while (linep < limit && *linep++ != ':') /* skip password */
+ continue;
+ if (linep == limit)
+ return (NSS_STR_PARSE_PARSE);
+
+ gidp = linep;
+ gid = strtoul(gidp, (char **)&linep, 10); /* grab gid */
+ oldgidlen = linep - gidp;
+ if (linep >= limit || oldgidlen == 0)
+ return (NSS_STR_PARSE_PARSE);
+
+ if (gid <= MAXUID)
+ return (NSS_STR_PARSE_SUCCESS);
+
+ idlen = snprintf(NULL, 0, "%u", GID_NOBODY);
+ newlinelen = linelen + idlen - oldgidlen;
+ if (newlinelen + extra_chars > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+
+ (void) bcopy(linep, gidp + idlen, limit - linep + extra_chars);
+ (void) snprintf(gidp, idlen + 1, "%u", GID_NOBODY);
+ *(gidp + idlen) = ':';
+ *linelenp = newlinelen;
+ return (NSS_STR_PARSE_SUCCESS);
}
static nss_status_t
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[] = {