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