17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 212e145884Sraf 227c478bd9Sstevel@tonic-gate /* 23*7257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * getnetgrent.c 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * - name-service switch frontend routines for the netgroup API. 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * Policy decision: 357c478bd9Sstevel@tonic-gate * If netgroup A refers to netgroup B, both must occur in the same 367c478bd9Sstevel@tonic-gate * source (any other choice gives very confusing semantics). This 377c478bd9Sstevel@tonic-gate * assumption is deeply embedded in the code below and in the backends. 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * innetgr() is implemented on top of something called __multi_innetgr(), 407c478bd9Sstevel@tonic-gate * which replaces each (char *) argument of innetgr() with a counted vector 417c478bd9Sstevel@tonic-gate * of (char *). The semantics are the same as an OR of the results of 427c478bd9Sstevel@tonic-gate * innetgr() operations on each possible 4-tuple picked from the arguments, 437c478bd9Sstevel@tonic-gate * but it's possible to implement some cases more efficiently. This is 447c478bd9Sstevel@tonic-gate * important for mountd, which used to read YP netgroup.byhost directly in 457c478bd9Sstevel@tonic-gate * order to determine efficiently whether a given host belonged to any one 467c478bd9Sstevel@tonic-gate * of a long list of netgroups. Wildcarded arguments are indicated by a 477c478bd9Sstevel@tonic-gate * count of zero. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate 50*7257d1b4Sraf #include "lint.h" 517c478bd9Sstevel@tonic-gate #include <string.h> 527c478bd9Sstevel@tonic-gate #include <synch.h> 537c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 547c478bd9Sstevel@tonic-gate #include <mtlib.h> 557c478bd9Sstevel@tonic-gate #include <libc.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate void 607c478bd9Sstevel@tonic-gate _nss_initf_netgroup(p) 617c478bd9Sstevel@tonic-gate nss_db_params_t *p; 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_NETGROUP; 647c478bd9Sstevel@tonic-gate p->default_config = NSS_DEFCONF_NETGROUP; 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * The netgroup routines aren't quite like the majority of the switch clients. 697c478bd9Sstevel@tonic-gate * innetgr() more-or-less fits the getXXXbyYYY mould, but for the others: 707c478bd9Sstevel@tonic-gate * - setnetgrent("netgroup") is really a getXXXbyYYY routine, i.e. it 717c478bd9Sstevel@tonic-gate * searches the sources until it finds an entry with the given name. 727c478bd9Sstevel@tonic-gate * Rather than returning the (potentially large) entry, it simply 737c478bd9Sstevel@tonic-gate * initializes a cursor, and then... 747c478bd9Sstevel@tonic-gate * - getnetgrent(...) is repeatedly invoked by the user to extract the 757c478bd9Sstevel@tonic-gate * contents of the entry found by setnetgrent(). 767c478bd9Sstevel@tonic-gate * - endnetgrent() is almost like a real endXXXent routine. 77cb5caa98Sdjl * The behaviour in NSS was: 787c478bd9Sstevel@tonic-gate * If we were certain that all the backends could provide netgroup information 797c478bd9Sstevel@tonic-gate * in a common form, we could make the setnetgrent() backend return the entire 807c478bd9Sstevel@tonic-gate * entry to the frontend, then implement getnetgrent() and endnetgrent() 817c478bd9Sstevel@tonic-gate * strictly in the frontend (aka here). But we're not certain, so we won't. 82cb5caa98Sdjl * In NSS2: 83cb5caa98Sdjl * Since nscd returns the results, and it is nscd that accumulates 84cb5caa98Sdjl * the results, then we can return the entire result on the setnetgrent. 857c478bd9Sstevel@tonic-gate * 867c478bd9Sstevel@tonic-gate * NOTE: 877c478bd9Sstevel@tonic-gate * In the SunOS 4.x (YP) version of this code, innetgr() did not 887c478bd9Sstevel@tonic-gate * affect the state of {set,get,end}netgrent(). Somewhere out 897c478bd9Sstevel@tonic-gate * there probably lurks a program that depends on this behaviour, 907c478bd9Sstevel@tonic-gate * so this version (both frontend and backends) had better 917c478bd9Sstevel@tonic-gate * behave the same way. 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* ===> ?? fix "__" name */ 957c478bd9Sstevel@tonic-gate int 967c478bd9Sstevel@tonic-gate __multi_innetgr(ngroup, pgroup, 977c478bd9Sstevel@tonic-gate nhost, phost, 987c478bd9Sstevel@tonic-gate nuser, puser, 997c478bd9Sstevel@tonic-gate ndomain, pdomain) 1007c478bd9Sstevel@tonic-gate nss_innetgr_argc ngroup, nhost, nuser, ndomain; 1017c478bd9Sstevel@tonic-gate nss_innetgr_argv pgroup, phost, puser, pdomain; 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate struct nss_innetgr_args ia; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (ngroup == 0) { 1067c478bd9Sstevel@tonic-gate return (0); /* One thing fewer to worry backends */ 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate ia.groups.argc = ngroup; 1107c478bd9Sstevel@tonic-gate ia.groups.argv = pgroup; 1117c478bd9Sstevel@tonic-gate ia.arg[NSS_NETGR_MACHINE].argc = nhost; 1127c478bd9Sstevel@tonic-gate ia.arg[NSS_NETGR_MACHINE].argv = phost; 1137c478bd9Sstevel@tonic-gate ia.arg[NSS_NETGR_USER].argc = nuser; 1147c478bd9Sstevel@tonic-gate ia.arg[NSS_NETGR_USER].argv = puser; 1157c478bd9Sstevel@tonic-gate ia.arg[NSS_NETGR_DOMAIN].argc = ndomain; 1167c478bd9Sstevel@tonic-gate ia.arg[NSS_NETGR_DOMAIN].argv = pdomain; 1177c478bd9Sstevel@tonic-gate ia.status = NSS_NETGR_NO; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate (void) nss_search(&db_root, _nss_initf_netgroup, 1207c478bd9Sstevel@tonic-gate NSS_DBOP_NETGROUP_IN, &ia); 1217c478bd9Sstevel@tonic-gate return (ia.status == NSS_NETGR_FOUND); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate int 1257c478bd9Sstevel@tonic-gate innetgr(group, host, user, domain) 1267c478bd9Sstevel@tonic-gate const char *group, *host, *user, *domain; 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate #define IA(charp) \ 1297c478bd9Sstevel@tonic-gate (nss_innetgr_argc)((charp) != 0), (nss_innetgr_argv)(&(charp)) 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate return (__multi_innetgr(IA(group), IA(host), IA(user), IA(domain))); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate /* 1357c478bd9Sstevel@tonic-gate * Context for setnetgrent()/getnetgrent(). If the user is being sensible 1367c478bd9Sstevel@tonic-gate * the requests will be serialized anyway, but let's play safe and 1377c478bd9Sstevel@tonic-gate * serialize them ourselves (anything to prevent a coredump)... 1387c478bd9Sstevel@tonic-gate * We can't use lmutex_lock() here because we don't know what the backends 1397c478bd9Sstevel@tonic-gate * that we call may call in turn. They might call malloc()/free(). 14098c1a6b4Sraf * So we use the brute-force callout_lock_enter() instead. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate static nss_backend_t *getnetgrent_backend; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate int 1457c478bd9Sstevel@tonic-gate setnetgrent(const char *netgroup) 1467c478bd9Sstevel@tonic-gate { 1477c478bd9Sstevel@tonic-gate nss_backend_t *be; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if (netgroup == NULL) { 1507c478bd9Sstevel@tonic-gate /* Prevent coredump, otherwise don't do anything profound */ 1517c478bd9Sstevel@tonic-gate netgroup = ""; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 15498c1a6b4Sraf callout_lock_enter(); 1557c478bd9Sstevel@tonic-gate be = getnetgrent_backend; 1567c478bd9Sstevel@tonic-gate if (be != NULL && NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 1577c478bd9Sstevel@tonic-gate (void *)netgroup) != NSS_SUCCESS) { 1587c478bd9Sstevel@tonic-gate (void) NSS_INVOKE_DBOP(be, NSS_DBOP_DESTRUCTOR, 0); 1597c478bd9Sstevel@tonic-gate be = NULL; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate if (be == NULL) { 1627c478bd9Sstevel@tonic-gate struct nss_setnetgrent_args args; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate args.netgroup = netgroup; 1657c478bd9Sstevel@tonic-gate args.iterator = 0; 1667c478bd9Sstevel@tonic-gate (void) nss_search(&db_root, _nss_initf_netgroup, 1677c478bd9Sstevel@tonic-gate NSS_DBOP_NETGROUP_SET, &args); 1687c478bd9Sstevel@tonic-gate be = args.iterator; 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate getnetgrent_backend = be; 17198c1a6b4Sraf callout_lock_exit(); 1727c478bd9Sstevel@tonic-gate return (0); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate int 1767c478bd9Sstevel@tonic-gate getnetgrent_r(machinep, namep, domainp, buffer, buflen) 1777c478bd9Sstevel@tonic-gate char **machinep; 1787c478bd9Sstevel@tonic-gate char **namep; 1797c478bd9Sstevel@tonic-gate char **domainp; 1807c478bd9Sstevel@tonic-gate char *buffer; 1817c478bd9Sstevel@tonic-gate int buflen; 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate struct nss_getnetgrent_args args; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate args.buffer = buffer; 1867c478bd9Sstevel@tonic-gate args.buflen = buflen; 1877c478bd9Sstevel@tonic-gate args.status = NSS_NETGR_NO; 1887c478bd9Sstevel@tonic-gate 18998c1a6b4Sraf callout_lock_enter(); 1907c478bd9Sstevel@tonic-gate if (getnetgrent_backend != 0) { 1917c478bd9Sstevel@tonic-gate (void) NSS_INVOKE_DBOP(getnetgrent_backend, 1927c478bd9Sstevel@tonic-gate NSS_DBOP_GETENT, &args); 1937c478bd9Sstevel@tonic-gate } 19498c1a6b4Sraf callout_lock_exit(); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate if (args.status == NSS_NETGR_FOUND) { 1977c478bd9Sstevel@tonic-gate *machinep = args.retp[NSS_NETGR_MACHINE]; 1987c478bd9Sstevel@tonic-gate *namep = args.retp[NSS_NETGR_USER]; 1997c478bd9Sstevel@tonic-gate *domainp = args.retp[NSS_NETGR_DOMAIN]; 2007c478bd9Sstevel@tonic-gate return (1); 2017c478bd9Sstevel@tonic-gate } else { 2027c478bd9Sstevel@tonic-gate return (0); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate static nss_XbyY_buf_t *buf; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate int 2097c478bd9Sstevel@tonic-gate getnetgrent(machinep, namep, domainp) 2107c478bd9Sstevel@tonic-gate char **machinep; 2117c478bd9Sstevel@tonic-gate char **namep; 2127c478bd9Sstevel@tonic-gate char **domainp; 2137c478bd9Sstevel@tonic-gate { 2147c478bd9Sstevel@tonic-gate (void) NSS_XbyY_ALLOC(&buf, 0, NSS_BUFLEN_NETGROUP); 2157c478bd9Sstevel@tonic-gate return (getnetgrent_r(machinep, namep, domainp, 2167c478bd9Sstevel@tonic-gate buf->buffer, buf->buflen)); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate int 2207c478bd9Sstevel@tonic-gate endnetgrent() 2217c478bd9Sstevel@tonic-gate { 22298c1a6b4Sraf callout_lock_enter(); 2237c478bd9Sstevel@tonic-gate if (getnetgrent_backend != 0) { 2247c478bd9Sstevel@tonic-gate (void) NSS_INVOKE_DBOP(getnetgrent_backend, 2257c478bd9Sstevel@tonic-gate NSS_DBOP_DESTRUCTOR, 0); 2267c478bd9Sstevel@tonic-gate getnetgrent_backend = 0; 2277c478bd9Sstevel@tonic-gate } 22898c1a6b4Sraf callout_lock_exit(); 2297c478bd9Sstevel@tonic-gate nss_delete(&db_root); /* === ? */ 2307c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&buf); 2317c478bd9Sstevel@tonic-gate return (0); 2327c478bd9Sstevel@tonic-gate } 233