diff options
author | djl <none@none> | 2006-09-29 06:00:17 -0700 |
---|---|---|
committer | djl <none@none> | 2006-09-29 06:00:17 -0700 |
commit | cb5caa98562cf06753163f558cbcfe30b8f4673a (patch) | |
tree | 7a24623821583899295e29553207e69701b471ff /usr/src/lib/nsswitch/compat/common/compat_common.c | |
parent | 350f572a3fa518fc3690d53066c2c54fd03b5a08 (diff) | |
download | illumos-joyent-cb5caa98562cf06753163f558cbcfe30b8f4673a.tar.gz |
PSARC 2005/133 Sparks: Name Service Switch 2
4406529 artificial limit of 10 threads per backend
4516075 LDAP connections could be reused more
4696964 LDAP naming services should support Kerberos authentication
4740951 Need host based authentication options in Native LDAP
4952533 Some backends of gethostby* do not set h_errno correctly
4979596 getXbyY calls should have better buffer mechanism
5028908 /usr/bin/logins accesses free memory deep in nss_getent_u().
5046881 nscd: old-data-ok parameter is not useful, should go away
6225323 NSS/nscd Enhancements (Sparks Project)
--HG--
rename : usr/src/cmd/nscd/attrstr.c => deleted_files/usr/src/cmd/nscd/attrstr.c
rename : usr/src/cmd/nscd/hash.c => deleted_files/usr/src/cmd/nscd/hash.c
rename : usr/src/cmd/nscd/nscd_parse.c => deleted_files/usr/src/cmd/nscd/nscd_parse.c
rename : usr/src/cmd/nscd/nscd.h => usr/src/cmd/nscd/cache.h
Diffstat (limited to 'usr/src/lib/nsswitch/compat/common/compat_common.c')
-rw-r--r-- | usr/src/lib/nsswitch/compat/common/compat_common.c | 352 |
1 files changed, 272 insertions, 80 deletions
diff --git a/usr/src/lib/nsswitch/compat/common/compat_common.c b/usr/src/lib/nsswitch/compat/common/compat_common.c index fe21797abf..330a4b7707 100644 --- a/usr/src/lib/nsswitch/compat/common/compat_common.c +++ b/usr/src/lib/nsswitch/compat/common/compat_common.c @@ -36,6 +36,11 @@ #include <ctype.h> #include <bsm/libbsm.h> #include <user_attr.h> +#include <pwd.h> +#include <shadow.h> +#include <grp.h> +#include <unistd.h> /* for GF_PATH */ +#include <dlfcn.h> #include "compat_common.h" /* @@ -44,6 +49,62 @@ extern int yp_get_default_domain(char **domain); +/* from libc */ +extern int str2passwd(const char *instr, int lenstr, void *ent, + char *buffer, int buflen); +extern int str2spwd(const char *instr, int lenstr, void *ent, + char *buffer, int buflen); +extern int str2group(const char *instr, int lenstr, void *ent, + char *buffer, int buflen); + +/* from libnsl */ +extern char *_strtok_escape(char *, char *, char **); + +/* + * str2auuser_s and str2userattr_s are very simple version + * of the str2auuser() and str2userattr() that can be found in + * libnsl. They only copy the user name into the userstr_t + * or au_user_str_t structure (so check on user name can be + * performed). + */ +static int +str2auuser_s( + const char *instr, + int lenstr, + void *ent, + char *buffer, + int buflen) +{ + char *last = NULL; + char *sep = KV_TOKEN_DELIMIT; + au_user_str_t *au_user = (au_user_str_t *)ent; + + if (lenstr >= buflen) + return (NSS_STR_PARSE_ERANGE); + (void) strncpy(buffer, instr, buflen); + au_user->au_name = _strtok_escape(buffer, sep, &last); + return (0); +} + +static int +str2userattr_s( + const char *instr, + int lenstr, + void *ent, + char *buffer, + int buflen) +{ + char *last = NULL; + char *sep = KV_TOKEN_DELIMIT; + userstr_t *user = (userstr_t *)ent; + + if (lenstr >= buflen) + return (NSS_STR_PARSE_ERANGE); + (void) strncpy(buffer, instr, buflen); + user->name = _strtok_escape(buffer, sep, &last); + return (0); +} + /* * Routines to manage list of "-" users for get{pw, sp, gr}ent(). Current * implementation is completely moronic; we use a linked list. But then @@ -58,7 +119,6 @@ struct setofstrings { * object rather than two. */ }; -typedef struct setofstrings *strset_t; static void strset_free(ssp) @@ -88,7 +148,7 @@ strset_add(ssp, nam) free(new); return (B_FALSE); } - strcpy(new->name, nam); + (void) strcpy(new->name, nam); new->next = *ssp; *ssp = new; return (B_TRUE); @@ -109,41 +169,6 @@ strset_in(ssp, nam) return (B_FALSE); } - -struct compat_backend { - compat_backend_op_t *ops; - int n_ops; - const char *filename; - FILE *f; - int minbuf; - char *buf; - int linelen; /* <== Explain use, lifetime */ - - nss_db_initf_t db_initf; - nss_db_root_t *db_rootp; /* Shared between instances */ - nss_getent_t db_context; /* Per-instance enumeration */ - - compat_get_name getnamef; - compat_merge_func mergef; - - /* We wouldn't need all this hokey state stuff if we */ - /* used another thread to implement a coroutine... */ - enum { - GETENT_FILE, - GETENT_NETGROUP, - GETENT_ATTRDB, - GETENT_ALL, - GETENT_DONE - } state; - strset_t minuses; - - int permit_netgroups; - const char *yp_domain; - nss_backend_t *getnetgrent_backend; - char *netgr_buffer; -}; - - /* * Lookup and enumeration routines for +@group and -@group. * @@ -171,15 +196,6 @@ netgr_in(compat_backend_ptr_t be, const char *group, const char *user) return (innetgr(group, 0, user, be->yp_domain)); } -static boolean_t -netgr_all_in(compat_backend_ptr_t be, const char *group) -{ - /* - * 4.x does this; ours not to reason why... - */ - return (netgr_in(be, group, "*")); -} - static void netgr_set(be, netgroup) compat_backend_ptr_t be; @@ -202,7 +218,7 @@ netgr_set(be, netgroup) args.netgroup = netgroup; args.iterator = 0; - nss_search(&netgr_db_root, _nss_initf_netgroup, + (void) nss_search(&netgr_db_root, _nss_initf_netgroup, NSS_DBOP_NETGROUP_SET, &args); be->getnetgrent_backend = args.iterator; } @@ -270,7 +286,7 @@ do_merge(be, args, instr, linelen) int overrides; const char *p; const char *end = instr + linelen; - nss_status_t res; + nss_status_t res = NSS_NOTFOUND; /* * Potential optimization: only perform the field-splitting nonsense @@ -292,7 +308,7 @@ do_merge(be, args, instr, linelen) overrides = -1; /* Indicates "you lose" */ break; } - memcpy(s, p, len); + (void) memcpy(s, p, len); s[len] = '\0'; fields[i] = s; overrides++; @@ -306,16 +322,29 @@ do_merge(be, args, instr, linelen) } } if (overrides == 1) { - /* No real overrides, return (*args) intact */ - res = NSS_SUCCESS; - } else if (overrides > 1) { + /* + * return result here if /etc file format is requested + */ + if (be->return_string_data != 1) { + /* No real overrides, return (*args) intact */ + res = NSS_SUCCESS; + } else { + free(fields[0]); + fields[0] = NULL; + } + } + + if (overrides > 1 || be->return_string_data == 1) { /* * The zero'th field is always nonempty (+/-...), but at least * one other field was also nonempty, i.e. wants to override */ switch ((*be->mergef)(be, args, (const char **)fields)) { case NSS_STR_PARSE_SUCCESS: - args->returnval = args->buf.result; + if (be->return_string_data != 1) + args->returnval = args->buf.result; + else + args->returnval = args->buf.buffer; args->erange = 0; res = NSS_SUCCESS; break; @@ -331,7 +360,7 @@ do_merge(be, args, instr, linelen) res = NSS_NOTFOUND; break; } - } else { + } else if (res != NSS_SUCCESS) { args->returnval = 0; args->erange = 0; res = NSS_UNAVAIL; /* ==> Right? */ @@ -383,7 +412,7 @@ _nss_compat_endent(be, dummy) void *dummy; { if (be->f != 0) { - fclose(be->f); + (void) fclose(be->f); be->f = 0; } if (be->buf != 0) { @@ -412,7 +441,7 @@ _nss_compat_destr(be, dummy) { if (be != 0) { if (be->f != 0) { - _nss_compat_endent(be, 0); + (void) _nss_compat_endent(be, 0); } nss_delete(be->db_rootp); nss_delete(&netgr_db_root); @@ -459,6 +488,7 @@ read_line(f, buffer, buflen) ; } } + /*NOTREACHED*/ } static int @@ -493,6 +523,10 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num) int (*func)(); const char *filter = argp->key.name; nss_status_t res; + union { + au_user_str_t au; + userstr_t user; + } workarea; #ifdef DEBUG (void) fprintf(stdout, "\n[compat_common.c: _attrdb_compat_XY_all]\n"); @@ -502,11 +536,33 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num) (be->buf = malloc(be->minbuf)) == 0) { return (NSS_UNAVAIL); } - if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) { - return (res); - } + if (check != NULL) + if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) + return (res); + res = NSS_NOTFOUND; + /* + * assume a NULL buf.result pointer is an indication + * that the lookup result should be returned in /etc + * file format + */ + if (argp->buf.result == NULL) { + be->return_string_data = 1; + + /* + * the code executed later needs the result struct + * as working area + */ + argp->buf.result = &workarea; + + if (strcmp(be->filename, USERATTR_FILENAME) == 0) + func = str2userattr_s; + else + func = str2auuser_s; + } else + func = argp->str2ent; + /*CONSTCOND*/ while (1) { int linelen; @@ -560,16 +616,36 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num) } } argp->returnval = 0; - func = argp->str2ent; parsestat = (*func)(instr, linelen, argp->buf.result, argp->buf.buffer, argp->buf.buflen); if (parsestat == NSS_STR_PARSE_SUCCESS) { - argp->returnval = argp->buf.result; + argp->returnval = argp->buf.result; if (check == 0 || (*check)(argp)) { + int len; + + if (be->return_string_data != 1) { + res = NSS_SUCCESS; + break; + } + + /* copy string data to result buffer */ + argp->buf.result = NULL; + argp->returnval = argp->buf.buffer; + if ((len = strlcpy(argp->buf.buffer, instr, + argp->buf.buflen)) >= + argp->buf.buflen) { + argp->returnval = NULL; + res = NSS_NOTFOUND; + argp->erange = 1; + break; + } + + argp->returnlen = len; res = NSS_SUCCESS; break; } } else if (parsestat == NSS_STR_PARSE_ERANGE) { + res = NSS_NOTFOUND; argp->erange = 1; break; } @@ -583,6 +659,14 @@ _attrdb_compat_XY_all(be, argp, netdb, check, op_num) } if (res != NSS_SUCCESS) { + /* + * tell the nss_search() and nss_getent() below + * if the result should be returned in the /etc + * file format + */ + if (be->return_string_data == 1) + argp->buf.result = NULL; + if ((op_num == NSS_DBOP_USERATTR_BYNAME) || (op_num == NSS_DBOP_AUDITUSER_BYNAME)) { res = nss_search(be->db_rootp, @@ -611,6 +695,13 @@ _nss_compat_XY_all(be, args, check, op_num) { nss_status_t res; int parsestat; + union { + struct passwd pwd; + struct spwd shdw; + struct group grp; + } workarea; + int (*str2ent_save)(); + if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { @@ -623,6 +714,30 @@ _nss_compat_XY_all(be, args, check, op_num) res = NSS_NOTFOUND; + /* + * assume a NULL buf.result pointer is an indication + * that the lookup result should be returned in /etc + * file format + */ + if (args->buf.result == NULL) { + + be->return_string_data = 1; + + /* + * the code executed later needs the result struct + * as working area + */ + args->buf.result = &workarea; + + str2ent_save = args->str2ent; + if (strcmp(be->filename, PASSWD) == 0) + args->str2ent = str2passwd; + else if (strcmp(be->filename, SHADOW) == 0) + args->str2ent = str2spwd; + else + args->str2ent = str2group; + } + /*CONSTCOND*/ while (1) { int linelen; @@ -648,13 +763,37 @@ _nss_compat_XY_all(be, args, check, op_num) if (parsestat == NSS_STR_PARSE_SUCCESS) { args->returnval = args->buf.result; if ((*check)(args) != 0) { - res = NSS_SUCCESS; - break; - } + int len; + if (be->return_string_data != 1) { + res = NSS_SUCCESS; + break; + } + + /* + * copy string data to + * result buffer + */ + args->buf.result = NULL; + args->str2ent = str2ent_save; + if ((len = strlcpy(args->buf.buffer, + instr, args->buf.buflen)) >= + args->buf.buflen) + parsestat = + NSS_STR_PARSE_ERANGE; + else { + args->returnval = + args->buf.buffer; + args->returnlen = len; + res = NSS_SUCCESS; + break; + } + } else + continue; + } /* ===> Check the Dani logic here... */ - } else if (parsestat == NSS_STR_PARSE_ERANGE) { + if (parsestat == NSS_STR_PARSE_ERANGE) { args->erange = 1; res = NSS_NOTFOUND; break; @@ -665,6 +804,7 @@ _nss_compat_XY_all(be, args, check, op_num) /* ==> ?? */ continue; } + /* * Process "+", "+name", "+@netgroup", "-name" or "-@netgroup" * @@ -701,15 +841,15 @@ _nss_compat_XY_all(be, args, check, op_num) continue; if (instr[0] == '+') { /* need to search for "+" entry */ - nss_search(be->db_rootp, be->db_initf, - op_num, args); + (void) nss_search(be->db_rootp, + be->db_initf, op_num, args); if (args->returnval == 0) continue; } } else { /* search then compare */ - nss_search(be->db_rootp, be->db_initf, op_num, - args); + (void) nss_search(be->db_rootp, + be->db_initf, op_num, args); if (args->returnval == 0) continue; if (!be->permit_netgroups || @@ -727,7 +867,8 @@ _nss_compat_XY_all(be, args, check, op_num) if (instr[0] == '-') continue; /* need to search for "+" entry */ - nss_search(be->db_rootp, be->db_initf, op_num, args); + (void) nss_search(be->db_rootp, be->db_initf, + op_num, args); if (args->returnval == 0) continue; } else { @@ -746,15 +887,15 @@ _nss_compat_XY_all(be, args, check, op_num) continue; if (instr[0] == '+') { /* need to search for "+" entry */ - nss_search(be->db_rootp, be->db_initf, - op_num, args); + (void) nss_search(be->db_rootp, + be->db_initf, op_num, args); if (args->returnval == 0) continue; } } else { /* search then compare */ - nss_search(be->db_rootp, be->db_initf, op_num, - args); + (void) nss_search(be->db_rootp, + be->db_initf, op_num, args); if (args->returnval == 0) continue; if (strcmp(instr + 1, (*be->getnamef)(args)) @@ -783,6 +924,10 @@ _nss_compat_XY_all(be, args, check, op_num) (void) _nss_compat_endent(be, 0); } + if (be->return_string_data == 1) { + args->str2ent = str2ent_save; + } + return (res); } @@ -794,6 +939,12 @@ _nss_compat_getent(be, a) nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; nss_status_t res; char *colon = 0; /* <=== need comment re lifetime */ + union { + struct passwd pwd; + struct spwd shdw; + struct group grp; + } workarea; + if (be->f == 0) { if ((res = _nss_compat_setent(be, 0)) != NSS_SUCCESS) { @@ -806,6 +957,21 @@ _nss_compat_getent(be, a) return (NSS_UNAVAIL); /* really panic, malloc failed */ } + /* + * assume a NULL buf.result pointer is an indication + * that the lookup result should be returned in /etc + * file format + */ + if (args->buf.result == NULL) { + be->return_string_data = 1; + + /* + * the code executed later needs the result struct + * as working area + */ + args->buf.result = &workarea; + } + /*CONSTCOND*/ while (1) { char *instr = be->buf; @@ -829,6 +995,7 @@ _nss_compat_getent(be, a) return (NSS_NOTFOUND); case GETENT_ATTRDB: + args->key.name = NULL; res = _attrdb_compat_XY_all(be, args, 1, (compat_XY_check_func)NULL, 0); return (res); @@ -845,11 +1012,12 @@ _nss_compat_getent(be, a) } if (instr[0] == '-') { if (instr[1] != '@') { - strset_add(&be->minuses, instr + 1); + (void) strset_add(&be->minuses, + instr + 1); } else if (be->permit_netgroups) { netgr_set(be, instr + 2); while (netgr_next_u(be, &name)) { - strset_add(&be->minuses, + (void) strset_add(&be->minuses, name); } netgr_end(be); @@ -869,8 +1037,30 @@ _nss_compat_getent(be, a) args->buf.buffer, args->buf.buflen); if (parsestat == NSS_STR_PARSE_SUCCESS) { - args->returnval = args->buf.result; - return (NSS_SUCCESS); + int len; + + if (be->return_string_data != 1) { + args->returnval = + args->buf.result; + return (NSS_SUCCESS); + } + + /* + * copy string data to + * result buffer + */ + args->buf.result = NULL; + args->returnval = + args->buf.buffer; + if ((len = strlcpy(args->buf.buffer, + instr, args->buf.buflen)) >= + args->buf.buflen) + parsestat = + NSS_STR_PARSE_ERANGE; + else { + args->returnlen = len; + return (NSS_SUCCESS); + } } /* ==> ?? Treat ERANGE differently ?? */ if (parsestat == NSS_STR_PARSE_ERANGE) { @@ -903,7 +1093,7 @@ _nss_compat_getent(be, a) case GETENT_ALL: linelen = be->linelen; args->returnval = 0; - nss_getent(be->db_rootp, be->db_initf, + (void) nss_getent(be->db_rootp, be->db_initf, &be->db_context, args); if (args->returnval == 0) { /* ==> ?? Treat ERANGE differently ?? */ @@ -947,7 +1137,7 @@ _nss_compat_getent(be, a) savename = args->key.name; args->key.name = name; args->returnval = 0; - nss_search(be->db_rootp, be->db_initf, + (void) nss_search(be->db_rootp, be->db_initf, NSS_DBOP_next_iter, args); args->key.name = savename; /* In case anyone cares */ } @@ -966,6 +1156,7 @@ _nss_compat_getent(be, a) } return (do_merge(be, args, instr, linelen)); } + /*NOTREACHED*/ } /* We don't use this directly; we just copy the bits when we want to */ @@ -1016,6 +1207,7 @@ _nss_compat_constr(ops, n_ops, filename, min_bufsize, rootp, initf, netgroups, be->yp_domain = 0; be->getnetgrent_backend = 0; be->netgr_buffer = 0; + be->return_string_data = 0; return ((nss_backend_t *)be); } |