/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * ns_nis.c * * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "automount.h" #define KEY 0 #define CONTENTS 1 static int replace_undscr_by_dot(char *); static int nis_err(int); static char nis_mydomain[YPMAXDOMAIN]; struct dir_cbdata { struct dir_entry **list; struct dir_entry *last; int error; }; static int readdir_callback(int, char *, int, const char *, int, struct dir_cbdata *); void init_nis(char **stack, char ***stkptr) { #ifdef lint stack = stack; stkptr = stkptr; #endif /* lint */ (void) sysinfo(SI_SRPC_DOMAIN, nis_mydomain, sizeof (nis_mydomain)); (void) __nis_reset_state(); /* XXX temporary hack for csh bug */ } /*ARGSUSED*/ int getmapent_nis(key, map, ml, stack, stkptr, iswildcard, isrestricted) char *key, *map; struct mapline *ml; char **stack; char ***stkptr; bool_t *iswildcard; bool_t isrestricted; { char *nisline = NULL; char *my_map = NULL; char *lp, *lq; int nislen, len; int nserr; if (iswildcard) *iswildcard = FALSE; nserr = yp_match(nis_mydomain, map, key, strlen(key), &nisline, &nislen); if (nserr == YPERR_MAP) { my_map = strdup(map); if (my_map == NULL) { syslog(LOG_ERR, "getmapent_nis: memory alloc failed: %m"); return (__NSW_UNAVAIL); } if (replace_undscr_by_dot(my_map)) nserr = yp_match(nis_mydomain, my_map, key, strlen(key), &nisline, &nislen); } if (nserr) { if (nserr == YPERR_KEY) { /* * Try the default entry "*" */ if (my_map == NULL) nserr = yp_match(nis_mydomain, map, "*", 1, &nisline, &nislen); else nserr = yp_match(nis_mydomain, my_map, "*", 1, &nisline, &nislen); if (!nserr && iswildcard) *iswildcard = TRUE; } else { if (verbose) syslog(LOG_ERR, "%s: %s", map, yperr_string(nserr)); nserr = 1; } } if (my_map != NULL) free(my_map); nserr = nis_err(nserr); if (nserr) goto done; /* * at this point we are sure that yp_match succeeded * so massage the entry by * 1. ignoring # and beyond * 2. trim the trailing whitespace */ if (lp = strchr(nisline, '#')) *lp = '\0'; len = strlen(nisline); if (len == 0) { nserr = __NSW_NOTFOUND; goto done; } lp = &nisline[len - 1]; while (lp > nisline && isspace(*lp)) *lp-- = '\0'; if (lp == nisline) { nserr = __NSW_NOTFOUND; goto done; } (void) strcpy(ml->linebuf, nisline); lp = ml->linebuf; lq = ml->lineqbuf; unquote(lp, lq); /* now we have the correct line */ nserr = __NSW_SUCCESS; done: if (nisline) free((char *)nisline); return (nserr); } int loadmaster_nis(mapname, defopts, stack, stkptr) char *mapname, *defopts; char **stack; char ***stkptr; { int first, err; char *key, *nkey, *val; int kl, nkl, vl; char dir[256], map[256], qbuff[256]; char *pmap, *opts, *my_mapname; int count = 0; first = 1; key = NULL; kl = 0; nkey = NULL; nkl = 0; val = NULL; vl = 0; /* * need a private copy of mapname, because we may change * the underscores by dots. We however do not want the * orignal to be changed, as we may want to use the * original name in some other name service */ my_mapname = strdup(mapname); if (my_mapname == NULL) { syslog(LOG_ERR, "loadmaster_yp: memory alloc failed: %m"); /* not the name svc's fault but ... */ return (__NSW_UNAVAIL); } for (;;) { if (first) { first = 0; err = yp_first(nis_mydomain, my_mapname, &nkey, &nkl, &val, &vl); if ((err == YPERR_MAP) && (replace_undscr_by_dot(my_mapname))) err = yp_first(nis_mydomain, my_mapname, &nkey, &nkl, &val, &vl); if ((err == YPERR_DOMAIN) || (err == YPERR_YPBIND)) { syslog(LOG_ERR, "can't read nis map %s: %s - retrying", my_mapname, yperr_string(err)); while ((err == YPERR_DOMAIN) || (err == YPERR_YPBIND)) { (void) sleep(20); err = yp_first(nis_mydomain, my_mapname, &nkey, &nkl, &val, &vl); } syslog(LOG_ERR, "nis map %s: read OK.", my_mapname); } } else { err = yp_next(nis_mydomain, my_mapname, key, kl, &nkey, &nkl, &val, &vl); } if (err) { if (err != YPERR_NOMORE && err != YPERR_MAP) if (verbose) syslog(LOG_ERR, "%s: %s", my_mapname, yperr_string(err)); break; } if (key) free(key); key = nkey; kl = nkl; if (kl >= 256 || vl >= 256) break; if (kl < 2 || vl < 1) break; if (isspace(*key) || *key == '#') break; (void) strncpy(dir, key, kl); dir[kl] = '\0'; if (macro_expand("", dir, qbuff, sizeof (dir))) { syslog(LOG_ERR, "%s in NIS map %s: entry too long (max %d chars)", dir, my_mapname, sizeof (dir) - 1); break; } (void) strncpy(map, val, vl); map[vl] = '\0'; if (macro_expand(dir, map, qbuff, sizeof (map))) { syslog(LOG_ERR, "%s in NIS map %s: entry too long (max %d chars)", map, my_mapname, sizeof (map) - 1); break; } pmap = map; while (*pmap && isspace(*pmap)) pmap++; /* skip blanks in front of map */ opts = pmap; while (*opts && !isspace(*opts)) opts++; if (*opts) { *opts++ = '\0'; while (*opts && isspace(*opts)) opts++; if (*opts == '-') opts++; else opts = defopts; } free(val); /* * Check for no embedded blanks. */ if (strcspn(opts, " ") == strlen(opts)) { dirinit(dir, pmap, opts, 0, stack, stkptr); count++; } else { pr_msg("Warning: invalid entry for %s in NIS map %s ignored.\n", dir, mapname); } } if (my_mapname) free(my_mapname); /* * In the context of a master map, if no entry is * found, it is like NOTFOUND */ if (count > 0 && err == YPERR_NOMORE) return (__NSW_SUCCESS); else { if (err) return (nis_err(err)); else /* * This case will happen if map is empty * or none of the entries is valid */ return (__NSW_NOTFOUND); } } int loaddirect_nis(nismap, localmap, opts, stack, stkptr) char *nismap, *localmap, *opts; char **stack; char ***stkptr; { int first, err, count; char *key, *nkey, *val, *my_nismap; int kl, nkl, vl; char dir[100]; first = 1; key = NULL; kl = 0; nkey = NULL; nkl = 0; val = NULL; vl = 0; count = 0; my_nismap = NULL; my_nismap = strdup(nismap); if (my_nismap == NULL) { syslog(LOG_ERR, "loadmaster_yp: memory alloc failed: %m"); return (__NSW_UNAVAIL); } for (;;) { if (first) { first = 0; err = yp_first(nis_mydomain, my_nismap, &nkey, &nkl, &val, &vl); if ((err == YPERR_MAP) && (replace_undscr_by_dot(my_nismap))) err = yp_first(nis_mydomain, my_nismap, &nkey, &nkl, &val, &vl); if ((err == YPERR_DOMAIN) || (err == YPERR_YPBIND)) { syslog(LOG_ERR, "can't read nis map %s: %s - retrying", my_nismap, yperr_string(err)); while ((err == YPERR_DOMAIN) || (err == YPERR_YPBIND)) { (void) sleep(20); err = yp_first(nis_mydomain, my_nismap, &nkey, &nkl, &val, &vl); } syslog(LOG_ERR, "nis map %s: read OK.", my_nismap); } } else { err = yp_next(nis_mydomain, my_nismap, key, kl, &nkey, &nkl, &val, &vl); } if (err) { if (err != YPERR_NOMORE && err != YPERR_MAP) syslog(LOG_ERR, "%s: %s", my_nismap, yperr_string(err)); break; } if (key) free(key); key = nkey; kl = nkl; if (kl < 2 || kl >= 100) continue; if (isspace(*key) || *key == '#') continue; (void) strncpy(dir, key, kl); dir[kl] = '\0'; dirinit(dir, localmap, opts, 1, stack, stkptr); count++; free(val); } if (my_nismap) free(my_nismap); if (count > 0 && err == YPERR_NOMORE) return (__NSW_SUCCESS); else return (nis_err(err)); } static int replace_undscr_by_dot(map) char *map; { int ret_val = 0; while (*map) { if (*map == '_') { ret_val = 1; *map = '.'; } map++; } return (ret_val); } static int nis_err(err) int err; { switch (err) { case 0: return (__NSW_SUCCESS); case YPERR_KEY: return (__NSW_NOTFOUND); case YPERR_MAP: return (__NSW_UNAVAIL); default: return (__NSW_UNAVAIL); } } int getmapkeys_nis(nsmap, list, error, cache_time, stack, stkptr) char *nsmap; struct dir_entry **list; int *error; int *cache_time; char **stack; char ***stkptr; { int nserr; struct dir_cbdata readdir_cbdata; struct ypall_callback cback; char *my_map = NULL; char *key = NULL, *val = NULL; int nkl, vl; #ifdef lint stack = stack; stkptr = stkptr; #endif /* lint */ *cache_time = RDDIR_CACHE_TIME; /* * XXX Hack to determine if we need to replace '_' with '.' * Have to use yp_first() since yp_all() simply fails if * the map is not present */ my_map = strdup(nsmap); if (my_map == NULL) { syslog(LOG_ERR, "getmapkeys_nis: memory alloc failed: %m"); *error = ENOMEM; return (__NSW_UNAVAIL); } nserr = yp_first(nis_mydomain, my_map, &key, &nkl, &val, &vl); if (nserr == YPERR_MAP) { if (replace_undscr_by_dot(my_map)) { nserr = yp_first(nis_mydomain, my_map, &key, &nkl, &val, &vl); } if (nserr == YPERR_MAP) { /* * map not found */ *error = 0; /* return an empty list */ if (verbose) { syslog(LOG_ERR, "%s: %s", nsmap, yperr_string(nserr)); } free(my_map); return (nis_err(nserr)); } if (key) free(key); if (val) free(val); } readdir_cbdata.list = list; readdir_cbdata.last = NULL; readdir_cbdata.error = 0; cback.foreach = readdir_callback; cback.data = (char *)&readdir_cbdata; /* * after all this song and dance we finally * ask for the list of entries */ nserr = yp_all(nis_mydomain, my_map, &cback); free(my_map); *error = readdir_cbdata.error; if (nserr) { if (verbose) syslog(LOG_ERR, "%s: %s", nsmap, yperr_string(nserr)); nserr = 1; if (*error == 0) *error = ENOENT; return (nis_err(nserr)); } return (__NSW_SUCCESS); } static int readdir_callback(instatus, inkey, inkeylen, inval, invallen, indata) int instatus; char *inkey; int inkeylen; const char *inval; int invallen; struct dir_cbdata *indata; { struct dir_entry **list = indata->list; struct dir_entry *last = indata->last; char key[MAXPATHLEN]; #ifdef lint inval = inval; invallen = invallen; #endif if (instatus != YP_TRUE) return (0); /* next entry. yp_all may decide otherwise... */ if (inkeylen == 0 || isspace(*inkey) || *inkey == '#') return (0); /* * yp_all allocates inkey with two extra bytes which contain * NEWLINE and null but these two bytes are not reflected in * inkeylen. */ strncpy(key, inkey, inkeylen); key[inkeylen] = '\0'; /* * Wildcard entry should be ignored - following entries should continue * to be read to corroborate with the way we search for entries in yp, * i.e., first for an exact key match and then a wildcard, if there's * no exact key match. */ if (key[0] == '*' && key[1] == '\0') return (0); if (add_dir_entry(key, list, &last)) { indata->error = ENOMEM; return (1); /* get no more entries */ } indata->last = last; indata->error = 0; return (0); }