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 2005 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 int 187 loaddirect_map(mapname, localmap, defopts, stack, stkptr) 188 char *mapname, *localmap, *defopts; 189 char **stack, ***stkptr; 190 { 191 struct __nsw_lookup *curr_ns = NULL; 192 int ns_err = __NSW_SUCCESS; 193 struct ns_info *nsp; 194 195 if (*mapname == '/') /* must be a file */ 196 return (loaddirect_files(mapname, localmap, defopts, 197 stack, stkptr)); 198 199 while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 200 ns_err = nsp->ns_loaddirect(mapname, localmap, defopts, stack, 201 stkptr); 202 if (ns_err == __NSW_SUCCESS) 203 return (__NSW_SUCCESS); 204 } 205 206 return (__NSW_UNAVAIL); 207 } 208 209 int 210 gethostkeys(mapname, list, error, cache_time) 211 char *mapname; 212 struct dir_entry **list; 213 int *error; 214 int *cache_time; 215 { 216 char *buffer, **p; 217 int bufferlen = 1000; 218 struct dir_entry *last = NULL; 219 struct hostent ent; 220 221 #ifdef lint 222 mapname = mapname; 223 #endif 224 225 *cache_time = RDDIR_CACHE_TIME * 2; 226 *error = 0; 227 if (trace > 1) 228 trace_prt(1, "gethostkeys called\n"); 229 230 if (sethostent(1)) { 231 syslog(LOG_ERR, "gethostkeys: sethostent failed"); 232 *error = EIO; 233 return (__NSW_UNAVAIL); 234 } 235 236 buffer = (char *)malloc(bufferlen); 237 if (buffer == NULL) { 238 syslog(LOG_ERR, "gethostkeys: malloc of buffer failed"); 239 *error = ENOMEM; 240 return (__NSW_UNAVAIL); 241 } 242 243 while (gethostent_r(&ent, buffer, bufferlen, error)) { 244 /* 245 * add canonical name 246 */ 247 if (add_dir_entry(ent.h_name, list, &last)) { 248 *error = ENOMEM; 249 goto done; 250 } 251 if (ent.h_aliases == NULL) 252 goto done; /* no aliases */ 253 for (p = ent.h_aliases; *p != 0; p++) { 254 if (strcmp(*p, ent.h_name) != 0) { 255 /* 256 * add alias only if different 257 * from canonical name 258 */ 259 if (add_dir_entry(*p, list, &last)) { 260 *error = ENOMEM; 261 goto done; 262 } 263 } 264 } 265 assert(last != NULL); 266 } 267 done: if (*list != NULL) { 268 /* 269 * list of entries found 270 */ 271 *error = 0; 272 } 273 endhostent(); 274 275 return (__NSW_SUCCESS); 276 } 277 278 /* 279 * enumerate all entries in the map in the various name services. 280 */ 281 int 282 getmapkeys(mapname, list, error, cache_time, stack, stkptr, uid) 283 char *mapname; 284 struct dir_entry **list; 285 int *error; 286 int *cache_time; 287 char **stack, ***stkptr; 288 uid_t uid; 289 290 { 291 struct __nsw_lookup *curr_ns = NULL; 292 int ns_err = __NSW_SUCCESS; 293 int success = 0; 294 struct ns_info *nsp; 295 296 if (*mapname == '/') /* must be a file */ 297 return (getmapkeys_files(mapname, list, error, cache_time, 298 stack, stkptr)); 299 if (strcmp(mapname, "-hosts") == 0) { 300 return (gethostkeys(mapname, list, error, cache_time)); 301 } 302 303 while ((nsp = get_next_ns(&curr_ns, ns_err)) != NULL) { 304 ns_err = nsp->ns_getmapkeys(mapname, list, error, 305 cache_time, stack, stkptr); 306 if (*error == 0) { 307 /* 308 * return success if listing was successful 309 * for at least one name service 310 */ 311 success++; 312 } 313 314 /* 315 * XXX force next name service 316 */ 317 if (ns_err != __NSW_UNAVAIL) 318 ns_err = __NSW_NOTFOUND; 319 } 320 if (success) { 321 /* 322 * if succeeded at least once, return error=0 323 */ 324 *error = 0; 325 }; 326 327 return (success ? __NSW_SUCCESS : __NSW_NOTFOUND); 328 } 329