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 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * getnetgrent.c 31 * 32 * - name-service switch frontend routines for the netgroup API. 33 * 34 * Policy decision: 35 * If netgroup A refers to netgroup B, both must occur in the same 36 * source (any other choice gives very confusing semantics). This 37 * assumption is deeply embedded in the code below and in the backends. 38 * 39 * innetgr() is implemented on top of something called __multi_innetgr(), 40 * which replaces each (char *) argument of innetgr() with a counted vector 41 * of (char *). The semantics are the same as an OR of the results of 42 * innetgr() operations on each possible 4-tuple picked from the arguments, 43 * but it's possible to implement some cases more efficiently. This is 44 * important for mountd, which used to read YP netgroup.byhost directly in 45 * order to determine efficiently whether a given host belonged to any one 46 * of a long list of netgroups. Wildcarded arguments are indicated by a 47 * count of zero. 48 */ 49 50 #include "synonyms.h" 51 #include <string.h> 52 #include <synch.h> 53 #include <nss_dbdefs.h> 54 #include <mtlib.h> 55 #include <libc.h> 56 57 static DEFINE_NSS_DB_ROOT(db_root); 58 59 void 60 _nss_initf_netgroup(p) 61 nss_db_params_t *p; 62 { 63 p->name = NSS_DBNAM_NETGROUP; 64 p->default_config = NSS_DEFCONF_NETGROUP; 65 } 66 67 /* 68 * The netgroup routines aren't quite like the majority of the switch clients. 69 * innetgr() more-or-less fits the getXXXbyYYY mould, but for the others: 70 * - setnetgrent("netgroup") is really a getXXXbyYYY routine, i.e. it 71 * searches the sources until it finds an entry with the given name. 72 * Rather than returning the (potentially large) entry, it simply 73 * initializes a cursor, and then... 74 * - getnetgrent(...) is repeatedly invoked by the user to extract the 75 * contents of the entry found by setnetgrent(). 76 * - endnetgrent() is almost like a real endXXXent routine. 77 * If we were certain that all the backends could provide netgroup information 78 * in a common form, we could make the setnetgrent() backend return the entire 79 * entry to the frontend, then implement getnetgrent() and endnetgrent() 80 * strictly in the frontend (aka here). But we're not certain, so we won't. 81 * 82 * NOTE: 83 * In the SunOS 4.x (YP) version of this code, innetgr() did not 84 * affect the state of {set,get,end}netgrent(). Somewhere out 85 * there probably lurks a program that depends on this behaviour, 86 * so this version (both frontend and backends) had better 87 * behave the same way. 88 */ 89 90 /* ===> ?? fix "__" name */ 91 int 92 __multi_innetgr(ngroup, pgroup, 93 nhost, phost, 94 nuser, puser, 95 ndomain, pdomain) 96 nss_innetgr_argc ngroup, nhost, nuser, ndomain; 97 nss_innetgr_argv pgroup, phost, puser, pdomain; 98 { 99 struct nss_innetgr_args ia; 100 101 if (ngroup == 0) { 102 return (0); /* One thing fewer to worry backends */ 103 } 104 105 ia.groups.argc = ngroup; 106 ia.groups.argv = pgroup; 107 ia.arg[NSS_NETGR_MACHINE].argc = nhost; 108 ia.arg[NSS_NETGR_MACHINE].argv = phost; 109 ia.arg[NSS_NETGR_USER].argc = nuser; 110 ia.arg[NSS_NETGR_USER].argv = puser; 111 ia.arg[NSS_NETGR_DOMAIN].argc = ndomain; 112 ia.arg[NSS_NETGR_DOMAIN].argv = pdomain; 113 ia.status = NSS_NETGR_NO; 114 115 (void) nss_search(&db_root, _nss_initf_netgroup, 116 NSS_DBOP_NETGROUP_IN, &ia); 117 return (ia.status == NSS_NETGR_FOUND); 118 } 119 120 int 121 innetgr(group, host, user, domain) 122 const char *group, *host, *user, *domain; 123 { 124 #define IA(charp) \ 125 (nss_innetgr_argc)((charp) != 0), (nss_innetgr_argv)(&(charp)) 126 127 return (__multi_innetgr(IA(group), IA(host), IA(user), IA(domain))); 128 } 129 130 /* 131 * Context for setnetgrent()/getnetgrent(). If the user is being sensible 132 * the requests will be serialized anyway, but let's play safe and 133 * serialize them ourselves (anything to prevent a coredump)... 134 * We can't use lmutex_lock() here because we don't know what the backends 135 * that we call may call in turn. They might call malloc()/free(). 136 * So we use the brute-force fork_lock_enter() instead. 137 */ 138 static nss_backend_t *getnetgrent_backend; 139 140 int 141 setnetgrent(const char *netgroup) 142 { 143 nss_backend_t *be; 144 145 if (netgroup == NULL) { 146 /* Prevent coredump, otherwise don't do anything profound */ 147 netgroup = ""; 148 } 149 150 (void) fork_lock_enter(NULL); 151 be = getnetgrent_backend; 152 if (be != NULL && NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 153 (void *)netgroup) != NSS_SUCCESS) { 154 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_DESTRUCTOR, 0); 155 be = NULL; 156 } 157 if (be == NULL) { 158 struct nss_setnetgrent_args args; 159 160 args.netgroup = netgroup; 161 args.iterator = 0; 162 (void) nss_search(&db_root, _nss_initf_netgroup, 163 NSS_DBOP_NETGROUP_SET, &args); 164 be = args.iterator; 165 } 166 getnetgrent_backend = be; 167 fork_lock_exit(); 168 return (0); 169 } 170 171 int 172 getnetgrent_r(machinep, namep, domainp, buffer, buflen) 173 char **machinep; 174 char **namep; 175 char **domainp; 176 char *buffer; 177 int buflen; 178 { 179 struct nss_getnetgrent_args args; 180 181 args.buffer = buffer; 182 args.buflen = buflen; 183 args.status = NSS_NETGR_NO; 184 185 (void) fork_lock_enter(NULL); 186 if (getnetgrent_backend != 0) { 187 (void) NSS_INVOKE_DBOP(getnetgrent_backend, 188 NSS_DBOP_GETENT, &args); 189 } 190 fork_lock_exit(); 191 192 if (args.status == NSS_NETGR_FOUND) { 193 *machinep = args.retp[NSS_NETGR_MACHINE]; 194 *namep = args.retp[NSS_NETGR_USER]; 195 *domainp = args.retp[NSS_NETGR_DOMAIN]; 196 return (1); 197 } else { 198 return (0); 199 } 200 } 201 202 static nss_XbyY_buf_t *buf; 203 204 int 205 getnetgrent(machinep, namep, domainp) 206 char **machinep; 207 char **namep; 208 char **domainp; 209 { 210 (void) NSS_XbyY_ALLOC(&buf, 0, NSS_BUFLEN_NETGROUP); 211 return (getnetgrent_r(machinep, namep, domainp, 212 buf->buffer, buf->buflen)); 213 } 214 215 int 216 endnetgrent() 217 { 218 (void) fork_lock_enter(NULL); 219 if (getnetgrent_backend != 0) { 220 (void) NSS_INVOKE_DBOP(getnetgrent_backend, 221 NSS_DBOP_DESTRUCTOR, 0); 222 getnetgrent_backend = 0; 223 } 224 fork_lock_exit(); 225 nss_delete(&db_root); /* === ? */ 226 NSS_XbyY_FREE(&buf); 227 return (0); 228 } 229