10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * ns_generic.c 240Sstevel@tonic-gate * 25*249Sjwahlig * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 260Sstevel@tonic-gate * Use is subject to license terms. 270Sstevel@tonic-gate */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include <stdio.h> 320Sstevel@tonic-gate #include <syslog.h> 330Sstevel@tonic-gate #include <string.h> 340Sstevel@tonic-gate #include <stdlib.h> 350Sstevel@tonic-gate #include <nsswitch.h> 360Sstevel@tonic-gate #include <sys/param.h> 370Sstevel@tonic-gate #include <netdb.h> 380Sstevel@tonic-gate #include <errno.h> 390Sstevel@tonic-gate #include <assert.h> 400Sstevel@tonic-gate #include <rpc/rpc.h> 410Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 420Sstevel@tonic-gate #include "automount.h" 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * Each name service is represented by a ns_info structure. 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate struct ns_info { 480Sstevel@tonic-gate char *ns_name; /* service name */ 490Sstevel@tonic-gate void (*ns_init)(); /* initialization routine */ 500Sstevel@tonic-gate int (*ns_getmapent)(); /* get map entry given key */ 510Sstevel@tonic-gate int (*ns_loadmaster)(); /* load master map */ 520Sstevel@tonic-gate int (*ns_loaddirect)(); /* load direct map */ 530Sstevel@tonic-gate int (*ns_getmapkeys)(); /* readdir */ 540Sstevel@tonic-gate }; 550Sstevel@tonic-gate 560Sstevel@tonic-gate static struct ns_info ns_info[] = { 570Sstevel@tonic-gate 580Sstevel@tonic-gate "files", init_files, getmapent_files, 590Sstevel@tonic-gate loadmaster_files, loaddirect_files, 600Sstevel@tonic-gate getmapkeys_files, 610Sstevel@tonic-gate 620Sstevel@tonic-gate "ldap", init_ldap, getmapent_ldap, 630Sstevel@tonic-gate loadmaster_ldap, loaddirect_ldap, 640Sstevel@tonic-gate getmapkeys_ldap, 650Sstevel@tonic-gate 660Sstevel@tonic-gate "nisplus", init_nisplus, getmapent_nisplus, 670Sstevel@tonic-gate loadmaster_nisplus, loaddirect_nisplus, 680Sstevel@tonic-gate getmapkeys_nisplus, 690Sstevel@tonic-gate 700Sstevel@tonic-gate "nis", init_nis, getmapent_nis, 710Sstevel@tonic-gate loadmaster_nis, loaddirect_nis, 720Sstevel@tonic-gate getmapkeys_nis, 730Sstevel@tonic-gate 740Sstevel@tonic-gate NULL, NULL, NULL, NULL, NULL, NULL, NULL 750Sstevel@tonic-gate }; 760Sstevel@tonic-gate 770Sstevel@tonic-gate static struct ns_info *get_next_ns(struct __nsw_lookup **, int); 780Sstevel@tonic-gate 790Sstevel@tonic-gate void 800Sstevel@tonic-gate ns_setup(char **stack, char ***stkptr) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate struct ns_info *nsp; 830Sstevel@tonic-gate 840Sstevel@tonic-gate for (nsp = ns_info; nsp->ns_name; nsp++) { 850Sstevel@tonic-gate nsp->ns_init(stack, stkptr); 860Sstevel@tonic-gate } 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate static struct ns_info * 900Sstevel@tonic-gate get_next_ns(curr_ns, curr_nserr) 910Sstevel@tonic-gate struct __nsw_lookup **curr_ns; 920Sstevel@tonic-gate int curr_nserr; 930Sstevel@tonic-gate { 940Sstevel@tonic-gate static struct __nsw_switchconfig *conf = NULL; 950Sstevel@tonic-gate enum __nsw_parse_err pserr; 960Sstevel@tonic-gate struct __nsw_lookup *lkp; 970Sstevel@tonic-gate struct ns_info *nsp; 980Sstevel@tonic-gate 990Sstevel@tonic-gate if (conf == NULL) { 1000Sstevel@tonic-gate /* __nsw_getconfig() is protected by a lock */ 1010Sstevel@tonic-gate conf = __nsw_getconfig("automount", &pserr); 1020Sstevel@tonic-gate if (conf == NULL) { 1030Sstevel@tonic-gate return (NULL); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate if (*curr_ns == NULL) 1080Sstevel@tonic-gate /* first time */ 1090Sstevel@tonic-gate lkp = conf->lookups; 1100Sstevel@tonic-gate else { 1110Sstevel@tonic-gate lkp = *curr_ns; 1120Sstevel@tonic-gate /* __NSW_ACTION is MT-Safe */ 1130Sstevel@tonic-gate if (__NSW_ACTION(lkp, curr_nserr) == __NSW_RETURN) 1140Sstevel@tonic-gate return (NULL); 1150Sstevel@tonic-gate lkp = lkp->next; 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate for (; lkp; lkp = lkp->next) { 1190Sstevel@tonic-gate for (nsp = ns_info; nsp->ns_name; nsp++) { 1200Sstevel@tonic-gate if (strcmp(lkp->service_name, nsp->ns_name) == 0) { 1210Sstevel@tonic-gate *curr_ns = lkp; 1220Sstevel@tonic-gate return (nsp); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate /* 1260Sstevel@tonic-gate * Note: if we get here then we've found 1270Sstevel@tonic-gate * an unsupported name service. 1280Sstevel@tonic-gate */ 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate return (NULL); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate int 1350Sstevel@tonic-gate getmapent(key, mapname, ml, stack, stkptr, iswildcard, isrestricted) 1360Sstevel@tonic-gate char *key, *mapname; 1370Sstevel@tonic-gate struct mapline *ml; 1380Sstevel@tonic-gate char **stack, ***stkptr; 1390Sstevel@tonic-gate bool_t *iswildcard; 1400Sstevel@tonic-gate bool_t isrestricted; 1410Sstevel@tonic-gate { 1420Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 1430Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 1440Sstevel@tonic-gate struct ns_info *nsp; 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate if (strcmp(mapname, "-hosts") == 0) { 1470Sstevel@tonic-gate (void) strcpy(ml->linebuf, "-hosts"); 1480Sstevel@tonic-gate return (__NSW_SUCCESS); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 1520Sstevel@tonic-gate return (getmapent_files(key, mapname, ml, stack, stkptr, 1530Sstevel@tonic-gate iswildcard, isrestricted)); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 1560Sstevel@tonic-gate ns_err = nsp->ns_getmapent(key, mapname, ml, stack, stkptr, 1570Sstevel@tonic-gate iswildcard, isrestricted); 1580Sstevel@tonic-gate if (ns_err == __NSW_SUCCESS) 1590Sstevel@tonic-gate return (__NSW_SUCCESS); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate return (__NSW_UNAVAIL); 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate int 1660Sstevel@tonic-gate loadmaster_map(mapname, defopts, stack, stkptr) 1670Sstevel@tonic-gate char *mapname, *defopts; 1680Sstevel@tonic-gate char **stack, ***stkptr; 1690Sstevel@tonic-gate { 1700Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 1710Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 1720Sstevel@tonic-gate struct ns_info *nsp; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 1750Sstevel@tonic-gate return (loadmaster_files(mapname, defopts, stack, stkptr)); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 1780Sstevel@tonic-gate ns_err = nsp->ns_loadmaster(mapname, defopts, stack, stkptr); 1790Sstevel@tonic-gate if (ns_err == __NSW_SUCCESS) 1800Sstevel@tonic-gate return (__NSW_SUCCESS); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate return (__NSW_UNAVAIL); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 186*249Sjwahlig int 1870Sstevel@tonic-gate loaddirect_map(mapname, localmap, defopts, stack, stkptr) 1880Sstevel@tonic-gate char *mapname, *localmap, *defopts; 1890Sstevel@tonic-gate char **stack, ***stkptr; 1900Sstevel@tonic-gate { 1910Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 1920Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 1930Sstevel@tonic-gate struct ns_info *nsp; 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 1960Sstevel@tonic-gate return (loaddirect_files(mapname, localmap, defopts, 1970Sstevel@tonic-gate stack, stkptr)); 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 2000Sstevel@tonic-gate ns_err = nsp->ns_loaddirect(mapname, localmap, defopts, stack, 2010Sstevel@tonic-gate stkptr); 2020Sstevel@tonic-gate if (ns_err == __NSW_SUCCESS) 2030Sstevel@tonic-gate return (__NSW_SUCCESS); 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate return (__NSW_UNAVAIL); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate int 2100Sstevel@tonic-gate gethostkeys(mapname, list, error, cache_time) 2110Sstevel@tonic-gate char *mapname; 2120Sstevel@tonic-gate struct dir_entry **list; 2130Sstevel@tonic-gate int *error; 2140Sstevel@tonic-gate int *cache_time; 2150Sstevel@tonic-gate { 2160Sstevel@tonic-gate char *buffer, **p; 2170Sstevel@tonic-gate int bufferlen = 1000; 2180Sstevel@tonic-gate struct dir_entry *last = NULL; 2190Sstevel@tonic-gate struct hostent ent; 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate #ifdef lint 2220Sstevel@tonic-gate mapname = mapname; 2230Sstevel@tonic-gate #endif 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate *cache_time = RDDIR_CACHE_TIME * 2; 2260Sstevel@tonic-gate *error = 0; 2270Sstevel@tonic-gate if (trace > 1) 2280Sstevel@tonic-gate trace_prt(1, "gethostkeys called\n"); 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate if (sethostent(1)) { 2310Sstevel@tonic-gate syslog(LOG_ERR, "gethostkeys: sethostent failed"); 2320Sstevel@tonic-gate *error = EIO; 2330Sstevel@tonic-gate return (__NSW_UNAVAIL); 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate buffer = (char *)malloc(bufferlen); 2370Sstevel@tonic-gate if (buffer == NULL) { 2380Sstevel@tonic-gate syslog(LOG_ERR, "gethostkeys: malloc of buffer failed"); 2390Sstevel@tonic-gate *error = ENOMEM; 2400Sstevel@tonic-gate return (__NSW_UNAVAIL); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate while (gethostent_r(&ent, buffer, bufferlen, error)) { 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * add canonical name 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate if (add_dir_entry(ent.h_name, list, &last)) { 2480Sstevel@tonic-gate *error = ENOMEM; 2490Sstevel@tonic-gate goto done; 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate if (ent.h_aliases == NULL) 2520Sstevel@tonic-gate goto done; /* no aliases */ 2530Sstevel@tonic-gate for (p = ent.h_aliases; *p != 0; p++) { 2540Sstevel@tonic-gate if (strcmp(*p, ent.h_name) != 0) { 2550Sstevel@tonic-gate /* 2560Sstevel@tonic-gate * add alias only if different 2570Sstevel@tonic-gate * from canonical name 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate if (add_dir_entry(*p, list, &last)) { 2600Sstevel@tonic-gate *error = ENOMEM; 2610Sstevel@tonic-gate goto done; 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate assert(last != NULL); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate done: if (*list != NULL) { 2680Sstevel@tonic-gate /* 2690Sstevel@tonic-gate * list of entries found 2700Sstevel@tonic-gate */ 2710Sstevel@tonic-gate *error = 0; 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate endhostent(); 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate return (__NSW_SUCCESS); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate /* 2790Sstevel@tonic-gate * enumerate all entries in the map in the various name services. 2800Sstevel@tonic-gate */ 281*249Sjwahlig int 2820Sstevel@tonic-gate getmapkeys(mapname, list, error, cache_time, stack, stkptr, uid) 2830Sstevel@tonic-gate char *mapname; 2840Sstevel@tonic-gate struct dir_entry **list; 2850Sstevel@tonic-gate int *error; 2860Sstevel@tonic-gate int *cache_time; 2870Sstevel@tonic-gate char **stack, ***stkptr; 2880Sstevel@tonic-gate uid_t uid; 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate { 2910Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 2920Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 2930Sstevel@tonic-gate int success = 0; 2940Sstevel@tonic-gate struct ns_info *nsp; 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 2970Sstevel@tonic-gate return (getmapkeys_files(mapname, list, error, cache_time, 2980Sstevel@tonic-gate stack, stkptr)); 2990Sstevel@tonic-gate if (strcmp(mapname, "-hosts") == 0) { 3000Sstevel@tonic-gate return (gethostkeys(mapname, list, error, cache_time)); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 3040Sstevel@tonic-gate ns_err = nsp->ns_getmapkeys(mapname, list, error, 3050Sstevel@tonic-gate cache_time, stack, stkptr); 3060Sstevel@tonic-gate if (*error == 0) { 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * return success if listing was successful 3090Sstevel@tonic-gate * for at least one name service 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate success++; 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * XXX force next name service 3160Sstevel@tonic-gate */ 3170Sstevel@tonic-gate if (ns_err != __NSW_UNAVAIL) 3180Sstevel@tonic-gate ns_err = __NSW_NOTFOUND; 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate if (success) { 3210Sstevel@tonic-gate /* 3220Sstevel@tonic-gate * if succeeded at least once, return error=0 3230Sstevel@tonic-gate */ 3240Sstevel@tonic-gate *error = 0; 3250Sstevel@tonic-gate }; 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate return (success ? __NSW_SUCCESS : __NSW_NOTFOUND); 3280Sstevel@tonic-gate } 329