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 | |
parent | 0a2b1d27cac02f57e17b310f8baeb1dda082c83a (diff) | |
download | illumos-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.c | 50 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/common/files_common.h | 8 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/common/getgrent.c | 95 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/common/getpwnam.c | 100 |
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[] = { |