1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * ns_generic.c 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 26*0Sstevel@tonic-gate * Use is subject to license terms. 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include <stdio.h> 32*0Sstevel@tonic-gate #include <syslog.h> 33*0Sstevel@tonic-gate #include <string.h> 34*0Sstevel@tonic-gate #include <stdlib.h> 35*0Sstevel@tonic-gate #include <nsswitch.h> 36*0Sstevel@tonic-gate #include <sys/param.h> 37*0Sstevel@tonic-gate #include <netdb.h> 38*0Sstevel@tonic-gate #include <errno.h> 39*0Sstevel@tonic-gate #include <assert.h> 40*0Sstevel@tonic-gate #include <rpc/rpc.h> 41*0Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h> 42*0Sstevel@tonic-gate #include "automount.h" 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* 45*0Sstevel@tonic-gate * Each name service is represented by a ns_info structure. 46*0Sstevel@tonic-gate */ 47*0Sstevel@tonic-gate struct ns_info { 48*0Sstevel@tonic-gate char *ns_name; /* service name */ 49*0Sstevel@tonic-gate void (*ns_init)(); /* initialization routine */ 50*0Sstevel@tonic-gate int (*ns_getmapent)(); /* get map entry given key */ 51*0Sstevel@tonic-gate int (*ns_loadmaster)(); /* load master map */ 52*0Sstevel@tonic-gate int (*ns_loaddirect)(); /* load direct map */ 53*0Sstevel@tonic-gate int (*ns_getmapkeys)(); /* readdir */ 54*0Sstevel@tonic-gate }; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate static struct ns_info ns_info[] = { 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate "files", init_files, getmapent_files, 59*0Sstevel@tonic-gate loadmaster_files, loaddirect_files, 60*0Sstevel@tonic-gate getmapkeys_files, 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate "ldap", init_ldap, getmapent_ldap, 63*0Sstevel@tonic-gate loadmaster_ldap, loaddirect_ldap, 64*0Sstevel@tonic-gate getmapkeys_ldap, 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate "nisplus", init_nisplus, getmapent_nisplus, 67*0Sstevel@tonic-gate loadmaster_nisplus, loaddirect_nisplus, 68*0Sstevel@tonic-gate getmapkeys_nisplus, 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate "nis", init_nis, getmapent_nis, 71*0Sstevel@tonic-gate loadmaster_nis, loaddirect_nis, 72*0Sstevel@tonic-gate getmapkeys_nis, 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate NULL, NULL, NULL, NULL, NULL, NULL, NULL 75*0Sstevel@tonic-gate }; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate static struct ns_info *get_next_ns(struct __nsw_lookup **, int); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate void 80*0Sstevel@tonic-gate ns_setup(char **stack, char ***stkptr) 81*0Sstevel@tonic-gate { 82*0Sstevel@tonic-gate struct ns_info *nsp; 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate for (nsp = ns_info; nsp->ns_name; nsp++) { 85*0Sstevel@tonic-gate nsp->ns_init(stack, stkptr); 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate static struct ns_info * 90*0Sstevel@tonic-gate get_next_ns(curr_ns, curr_nserr) 91*0Sstevel@tonic-gate struct __nsw_lookup **curr_ns; 92*0Sstevel@tonic-gate int curr_nserr; 93*0Sstevel@tonic-gate { 94*0Sstevel@tonic-gate static struct __nsw_switchconfig *conf = NULL; 95*0Sstevel@tonic-gate enum __nsw_parse_err pserr; 96*0Sstevel@tonic-gate struct __nsw_lookup *lkp; 97*0Sstevel@tonic-gate struct ns_info *nsp; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate if (conf == NULL) { 100*0Sstevel@tonic-gate /* __nsw_getconfig() is protected by a lock */ 101*0Sstevel@tonic-gate conf = __nsw_getconfig("automount", &pserr); 102*0Sstevel@tonic-gate if (conf == NULL) { 103*0Sstevel@tonic-gate return (NULL); 104*0Sstevel@tonic-gate } 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate if (*curr_ns == NULL) 108*0Sstevel@tonic-gate /* first time */ 109*0Sstevel@tonic-gate lkp = conf->lookups; 110*0Sstevel@tonic-gate else { 111*0Sstevel@tonic-gate lkp = *curr_ns; 112*0Sstevel@tonic-gate /* __NSW_ACTION is MT-Safe */ 113*0Sstevel@tonic-gate if (__NSW_ACTION(lkp, curr_nserr) == __NSW_RETURN) 114*0Sstevel@tonic-gate return (NULL); 115*0Sstevel@tonic-gate lkp = lkp->next; 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate for (; lkp; lkp = lkp->next) { 119*0Sstevel@tonic-gate for (nsp = ns_info; nsp->ns_name; nsp++) { 120*0Sstevel@tonic-gate if (strcmp(lkp->service_name, nsp->ns_name) == 0) { 121*0Sstevel@tonic-gate *curr_ns = lkp; 122*0Sstevel@tonic-gate return (nsp); 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate /* 126*0Sstevel@tonic-gate * Note: if we get here then we've found 127*0Sstevel@tonic-gate * an unsupported name service. 128*0Sstevel@tonic-gate */ 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate return (NULL); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate int 135*0Sstevel@tonic-gate getmapent(key, mapname, ml, stack, stkptr, iswildcard, isrestricted) 136*0Sstevel@tonic-gate char *key, *mapname; 137*0Sstevel@tonic-gate struct mapline *ml; 138*0Sstevel@tonic-gate char **stack, ***stkptr; 139*0Sstevel@tonic-gate bool_t *iswildcard; 140*0Sstevel@tonic-gate bool_t isrestricted; 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 143*0Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 144*0Sstevel@tonic-gate struct ns_info *nsp; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate if (strcmp(mapname, "-hosts") == 0) { 147*0Sstevel@tonic-gate (void) strcpy(ml->linebuf, "-hosts"); 148*0Sstevel@tonic-gate return (__NSW_SUCCESS); 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 152*0Sstevel@tonic-gate return (getmapent_files(key, mapname, ml, stack, stkptr, 153*0Sstevel@tonic-gate iswildcard, isrestricted)); 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 156*0Sstevel@tonic-gate ns_err = nsp->ns_getmapent(key, mapname, ml, stack, stkptr, 157*0Sstevel@tonic-gate iswildcard, isrestricted); 158*0Sstevel@tonic-gate if (ns_err == __NSW_SUCCESS) 159*0Sstevel@tonic-gate return (__NSW_SUCCESS); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate return (__NSW_UNAVAIL); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate int 166*0Sstevel@tonic-gate loadmaster_map(mapname, defopts, stack, stkptr) 167*0Sstevel@tonic-gate char *mapname, *defopts; 168*0Sstevel@tonic-gate char **stack, ***stkptr; 169*0Sstevel@tonic-gate { 170*0Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 171*0Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 172*0Sstevel@tonic-gate struct ns_info *nsp; 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 175*0Sstevel@tonic-gate return (loadmaster_files(mapname, defopts, stack, stkptr)); 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 178*0Sstevel@tonic-gate ns_err = nsp->ns_loadmaster(mapname, defopts, stack, stkptr); 179*0Sstevel@tonic-gate if (ns_err == __NSW_SUCCESS) 180*0Sstevel@tonic-gate return (__NSW_SUCCESS); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate return (__NSW_UNAVAIL); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate loaddirect_map(mapname, localmap, defopts, stack, stkptr) 187*0Sstevel@tonic-gate char *mapname, *localmap, *defopts; 188*0Sstevel@tonic-gate char **stack, ***stkptr; 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 191*0Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 192*0Sstevel@tonic-gate struct ns_info *nsp; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 195*0Sstevel@tonic-gate return (loaddirect_files(mapname, localmap, defopts, 196*0Sstevel@tonic-gate stack, stkptr)); 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 199*0Sstevel@tonic-gate ns_err = nsp->ns_loaddirect(mapname, localmap, defopts, stack, 200*0Sstevel@tonic-gate stkptr); 201*0Sstevel@tonic-gate if (ns_err == __NSW_SUCCESS) 202*0Sstevel@tonic-gate return (__NSW_SUCCESS); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate return (__NSW_UNAVAIL); 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate int 209*0Sstevel@tonic-gate gethostkeys(mapname, list, error, cache_time) 210*0Sstevel@tonic-gate char *mapname; 211*0Sstevel@tonic-gate struct dir_entry **list; 212*0Sstevel@tonic-gate int *error; 213*0Sstevel@tonic-gate int *cache_time; 214*0Sstevel@tonic-gate { 215*0Sstevel@tonic-gate char *buffer, **p; 216*0Sstevel@tonic-gate int bufferlen = 1000; 217*0Sstevel@tonic-gate struct dir_entry *last = NULL; 218*0Sstevel@tonic-gate struct hostent ent; 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate #ifdef lint 221*0Sstevel@tonic-gate mapname = mapname; 222*0Sstevel@tonic-gate #endif 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate *cache_time = RDDIR_CACHE_TIME * 2; 225*0Sstevel@tonic-gate *error = 0; 226*0Sstevel@tonic-gate if (trace > 1) 227*0Sstevel@tonic-gate trace_prt(1, "gethostkeys called\n"); 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate if (sethostent(1)) { 230*0Sstevel@tonic-gate syslog(LOG_ERR, "gethostkeys: sethostent failed"); 231*0Sstevel@tonic-gate *error = EIO; 232*0Sstevel@tonic-gate return (__NSW_UNAVAIL); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate buffer = (char *)malloc(bufferlen); 236*0Sstevel@tonic-gate if (buffer == NULL) { 237*0Sstevel@tonic-gate syslog(LOG_ERR, "gethostkeys: malloc of buffer failed"); 238*0Sstevel@tonic-gate *error = ENOMEM; 239*0Sstevel@tonic-gate return (__NSW_UNAVAIL); 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate while (gethostent_r(&ent, buffer, bufferlen, error)) { 243*0Sstevel@tonic-gate /* 244*0Sstevel@tonic-gate * add canonical name 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate if (add_dir_entry(ent.h_name, list, &last)) { 247*0Sstevel@tonic-gate *error = ENOMEM; 248*0Sstevel@tonic-gate goto done; 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate if (ent.h_aliases == NULL) 251*0Sstevel@tonic-gate goto done; /* no aliases */ 252*0Sstevel@tonic-gate for (p = ent.h_aliases; *p != 0; p++) { 253*0Sstevel@tonic-gate if (strcmp(*p, ent.h_name) != 0) { 254*0Sstevel@tonic-gate /* 255*0Sstevel@tonic-gate * add alias only if different 256*0Sstevel@tonic-gate * from canonical name 257*0Sstevel@tonic-gate */ 258*0Sstevel@tonic-gate if (add_dir_entry(*p, list, &last)) { 259*0Sstevel@tonic-gate *error = ENOMEM; 260*0Sstevel@tonic-gate goto done; 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate assert(last != NULL); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate done: if (*list != NULL) { 267*0Sstevel@tonic-gate /* 268*0Sstevel@tonic-gate * list of entries found 269*0Sstevel@tonic-gate */ 270*0Sstevel@tonic-gate *error = 0; 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate endhostent(); 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate return (__NSW_SUCCESS); 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * enumerate all entries in the map in the various name services. 279*0Sstevel@tonic-gate */ 280*0Sstevel@tonic-gate getmapkeys(mapname, list, error, cache_time, stack, stkptr, uid) 281*0Sstevel@tonic-gate char *mapname; 282*0Sstevel@tonic-gate struct dir_entry **list; 283*0Sstevel@tonic-gate int *error; 284*0Sstevel@tonic-gate int *cache_time; 285*0Sstevel@tonic-gate char **stack, ***stkptr; 286*0Sstevel@tonic-gate uid_t uid; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate { 289*0Sstevel@tonic-gate struct __nsw_lookup *curr_ns = NULL; 290*0Sstevel@tonic-gate int ns_err = __NSW_SUCCESS; 291*0Sstevel@tonic-gate int success = 0; 292*0Sstevel@tonic-gate struct ns_info *nsp; 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate if (*mapname == '/') /* must be a file */ 295*0Sstevel@tonic-gate return (getmapkeys_files(mapname, list, error, cache_time, 296*0Sstevel@tonic-gate stack, stkptr)); 297*0Sstevel@tonic-gate if (strcmp(mapname, "-hosts") == 0) { 298*0Sstevel@tonic-gate return (gethostkeys(mapname, list, error, cache_time)); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 302*0Sstevel@tonic-gate ns_err = nsp->ns_getmapkeys(mapname, list, error, 303*0Sstevel@tonic-gate cache_time, stack, stkptr); 304*0Sstevel@tonic-gate if (*error == 0) { 305*0Sstevel@tonic-gate /* 306*0Sstevel@tonic-gate * return success if listing was successful 307*0Sstevel@tonic-gate * for at least one name service 308*0Sstevel@tonic-gate */ 309*0Sstevel@tonic-gate success++; 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate /* 313*0Sstevel@tonic-gate * XXX force next name service 314*0Sstevel@tonic-gate */ 315*0Sstevel@tonic-gate if (ns_err != __NSW_UNAVAIL) 316*0Sstevel@tonic-gate ns_err = __NSW_NOTFOUND; 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate if (success) { 319*0Sstevel@tonic-gate /* 320*0Sstevel@tonic-gate * if succeeded at least once, return error=0 321*0Sstevel@tonic-gate */ 322*0Sstevel@tonic-gate *error = 0; 323*0Sstevel@tonic-gate }; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate return (success ? __NSW_SUCCESS : __NSW_NOTFOUND); 326*0Sstevel@tonic-gate } 327