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