1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate /* 29*0Sstevel@tonic-gate * nis_common.c 30*0Sstevel@tonic-gate * 31*0Sstevel@tonic-gate * Common code and structures used by name-service-switch "nis" backends. 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include "nis_common.h" 37*0Sstevel@tonic-gate #include <string.h> 38*0Sstevel@tonic-gate #include <synch.h> 39*0Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 40*0Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 41*0Sstevel@tonic-gate #include <thread.h> 42*0Sstevel@tonic-gate #include <ctype.h> 43*0Sstevel@tonic-gate #include <stdlib.h> 44*0Sstevel@tonic-gate #include <signal.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #ifndef MT_UNSAFE_YP /* Is the libnsl YP client code MT-unsafe? */ 47*0Sstevel@tonic-gate #define MT_UNSAFE_YP 0 /* No, not any longer */ 48*0Sstevel@tonic-gate #endif 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate #if MT_UNSAFE_YP 51*0Sstevel@tonic-gate static mutex_t one_lane = DEFAULTMUTEX; 52*0Sstevel@tonic-gate #endif 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate /* <rpcsvc/ypclnt.h> uses (char *) where it should use (const char *) */ 55*0Sstevel@tonic-gate typedef char *grrr; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate /* 58*0Sstevel@tonic-gate * The YP client code thinks it's being helpful by appending '\n' and '\0' 59*0Sstevel@tonic-gate * to the values returned by yp_match() et al. In order to do this it 60*0Sstevel@tonic-gate * ends up doing more malloc()ing and data copying than would otherwise 61*0Sstevel@tonic-gate * be necessary. If we're interested in performance we should provide 62*0Sstevel@tonic-gate * alternative library interfaces that skip the helpfulness and instead 63*0Sstevel@tonic-gate * let the XDR routines dump the value directly into the buffer where 64*0Sstevel@tonic-gate * we really want it. For now, though, we just use the vanilla interface. 65*0Sstevel@tonic-gate */ 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate static nss_status_t 68*0Sstevel@tonic-gate switch_err(ypstatus, ismatch) 69*0Sstevel@tonic-gate int ypstatus; 70*0Sstevel@tonic-gate int ismatch; 71*0Sstevel@tonic-gate { 72*0Sstevel@tonic-gate switch (ypstatus) { 73*0Sstevel@tonic-gate case 0: 74*0Sstevel@tonic-gate return (NSS_SUCCESS); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate case YPERR_BADARGS: 77*0Sstevel@tonic-gate case YPERR_KEY: 78*0Sstevel@tonic-gate return (NSS_NOTFOUND); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate /* 81*0Sstevel@tonic-gate * When the YP server is running in DNS forwarding mode, 82*0Sstevel@tonic-gate * the forwarder will return YPERR_NOMORE to us if it 83*0Sstevel@tonic-gate * is unable to contact a server (i.e., it has timed out). 84*0Sstevel@tonic-gate * The NSS_NISSERVDNS_TRYAGAIN is returned for timeout errors. 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate case YPERR_NOMORE: 87*0Sstevel@tonic-gate if (ismatch) 88*0Sstevel@tonic-gate return (NSS_NISSERVDNS_TRYAGAIN); 89*0Sstevel@tonic-gate else 90*0Sstevel@tonic-gate return (NSS_NOTFOUND); 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate case YPERR_DOMAIN: 93*0Sstevel@tonic-gate case YPERR_YPSERV: 94*0Sstevel@tonic-gate case YPERR_BUSY: 95*0Sstevel@tonic-gate return (NSS_TRYAGAIN); 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate default: 98*0Sstevel@tonic-gate return (NSS_UNAVAIL); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /*ARGSUSED*/ 103*0Sstevel@tonic-gate nss_status_t 104*0Sstevel@tonic-gate _nss_nis_setent(be, dummy) 105*0Sstevel@tonic-gate nis_backend_ptr_t be; 106*0Sstevel@tonic-gate void *dummy; 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate if (be->enum_key != 0) { 109*0Sstevel@tonic-gate free(be->enum_key); 110*0Sstevel@tonic-gate be->enum_key = 0; 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate be->enum_keylen = 0; 113*0Sstevel@tonic-gate return (NSS_SUCCESS); 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate nss_status_t 117*0Sstevel@tonic-gate _nss_nis_endent(be, dummy) 118*0Sstevel@tonic-gate nis_backend_ptr_t be; 119*0Sstevel@tonic-gate void *dummy; 120*0Sstevel@tonic-gate { 121*0Sstevel@tonic-gate return (_nss_nis_setent(be, dummy)); 122*0Sstevel@tonic-gate /* Nothing else we can clean up, is there? */ 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate void 126*0Sstevel@tonic-gate massage_netdb(const char **valp, int *vallenp) 127*0Sstevel@tonic-gate { 128*0Sstevel@tonic-gate const char *first; 129*0Sstevel@tonic-gate const char *last; 130*0Sstevel@tonic-gate const char *val = *valp; 131*0Sstevel@tonic-gate int vallen = *vallenp; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate if ((last = memchr(val, '#', vallen)) == 0) { 134*0Sstevel@tonic-gate last = val + vallen; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate for (first = val; first < last && isspace(*first); first++) { 137*0Sstevel@tonic-gate ; 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate for (/* cstyle */; first < last && isspace(last[-1]); last--) { 140*0Sstevel@tonic-gate ; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * Don't check for an empty line because it shouldn't ever 144*0Sstevel@tonic-gate * have made it into the YP map. 145*0Sstevel@tonic-gate */ 146*0Sstevel@tonic-gate *valp = first; 147*0Sstevel@tonic-gate *vallenp = (int)(last - first); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate nss_status_t 151*0Sstevel@tonic-gate _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp) 152*0Sstevel@tonic-gate const char *domain; 153*0Sstevel@tonic-gate const char *map; 154*0Sstevel@tonic-gate const char *key; 155*0Sstevel@tonic-gate char **valp; 156*0Sstevel@tonic-gate int *vallenp; 157*0Sstevel@tonic-gate int *ypstatusp; 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate int ypstatus; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate #if MT_UNSAFE_YP 162*0Sstevel@tonic-gate sigset_t oldmask, newmask; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate sigfillset(&newmask); 165*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 166*0Sstevel@tonic-gate _mutex_lock(&one_lane); 167*0Sstevel@tonic-gate #endif 168*0Sstevel@tonic-gate ypstatus = __yp_match_cflookup((grrr)domain, (grrr)map, 169*0Sstevel@tonic-gate (grrr)key, (int)strlen(key), valp, vallenp, 0); 170*0Sstevel@tonic-gate #if MT_UNSAFE_YP 171*0Sstevel@tonic-gate _mutex_unlock(&one_lane); 172*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 173*0Sstevel@tonic-gate #endif 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate if (ypstatusp != 0) { 176*0Sstevel@tonic-gate *ypstatusp = ypstatus; 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate return (switch_err(ypstatus, 1)); 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate /* 182*0Sstevel@tonic-gate * XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct) 183*0Sstevel@tonic-gate * lookups when we need a reserved port. 184*0Sstevel@tonic-gate */ 185*0Sstevel@tonic-gate nss_status_t 186*0Sstevel@tonic-gate _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp) 187*0Sstevel@tonic-gate const char *domain; 188*0Sstevel@tonic-gate const char *map; 189*0Sstevel@tonic-gate const char *key; 190*0Sstevel@tonic-gate char **valp; 191*0Sstevel@tonic-gate int *vallenp; 192*0Sstevel@tonic-gate int *ypstatusp; 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate int ypstatus; 195*0Sstevel@tonic-gate extern int yp_match_rsvdport(); 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate #if MT_UNSAFE_YP 198*0Sstevel@tonic-gate sigset_t oldmask, newmask; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate sigfillset(&newmask); 201*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 202*0Sstevel@tonic-gate _mutex_lock(&one_lane); 203*0Sstevel@tonic-gate #endif 204*0Sstevel@tonic-gate ypstatus = __yp_match_rsvdport_cflookup((grrr)domain, (grrr)map, 205*0Sstevel@tonic-gate (grrr)key, strlen(key), valp, vallenp, 0); 206*0Sstevel@tonic-gate #if MT_UNSAFE_YP 207*0Sstevel@tonic-gate _mutex_unlock(&one_lane); 208*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 209*0Sstevel@tonic-gate #endif 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate if (ypstatusp != 0) { 212*0Sstevel@tonic-gate *ypstatusp = ypstatus; 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate return (switch_err(ypstatus, 1)); 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate nss_status_t 218*0Sstevel@tonic-gate _nss_nis_lookup(be, args, netdb, map, key, ypstatusp) 219*0Sstevel@tonic-gate nis_backend_ptr_t be; 220*0Sstevel@tonic-gate nss_XbyY_args_t *args; 221*0Sstevel@tonic-gate int netdb; 222*0Sstevel@tonic-gate const char *map; 223*0Sstevel@tonic-gate const char *key; 224*0Sstevel@tonic-gate int *ypstatusp; 225*0Sstevel@tonic-gate { 226*0Sstevel@tonic-gate nss_status_t res; 227*0Sstevel@tonic-gate int vallen; 228*0Sstevel@tonic-gate char *val; 229*0Sstevel@tonic-gate char *free_ptr; 230*0Sstevel@tonic-gate int parsestat; 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate if ((res = _nss_nis_ypmatch(be->domain, map, key, &val, &vallen, 233*0Sstevel@tonic-gate ypstatusp)) != NSS_SUCCESS) { 234*0Sstevel@tonic-gate return (res); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate free_ptr = val; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate if (netdb) { 240*0Sstevel@tonic-gate massage_netdb((const char **)&val, &vallen); 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate parsestat = (*args->str2ent)(val, vallen, 244*0Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 245*0Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 246*0Sstevel@tonic-gate args->returnval = args->buf.result; 247*0Sstevel@tonic-gate res = NSS_SUCCESS; 248*0Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 249*0Sstevel@tonic-gate args->erange = 1; 250*0Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 251*0Sstevel@tonic-gate res = NSS_NOTFOUND; 252*0Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate free(free_ptr); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate return (res); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate nss_status_t 260*0Sstevel@tonic-gate _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp) 261*0Sstevel@tonic-gate nis_backend_ptr_t be; 262*0Sstevel@tonic-gate nss_XbyY_args_t *args; 263*0Sstevel@tonic-gate int netdb; 264*0Sstevel@tonic-gate const char *map; 265*0Sstevel@tonic-gate const char *key; 266*0Sstevel@tonic-gate int *ypstatusp; 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate nss_status_t res; 269*0Sstevel@tonic-gate int vallen; 270*0Sstevel@tonic-gate char *val; 271*0Sstevel@tonic-gate char *free_ptr; 272*0Sstevel@tonic-gate int parsestat; 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate if ((res = _nss_nis_ypmatch_rsvdport(be->domain, map, key, &val, 275*0Sstevel@tonic-gate &vallen, ypstatusp)) != NSS_SUCCESS) { 276*0Sstevel@tonic-gate return (res); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate free_ptr = val; 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate if (netdb) { 282*0Sstevel@tonic-gate massage_netdb((const char **)&val, &vallen); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate parsestat = (*args->str2ent)(val, vallen, 286*0Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 287*0Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 288*0Sstevel@tonic-gate args->returnval = args->buf.result; 289*0Sstevel@tonic-gate res = NSS_SUCCESS; 290*0Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 291*0Sstevel@tonic-gate args->erange = 1; 292*0Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 293*0Sstevel@tonic-gate res = NSS_NOTFOUND; 294*0Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate free(free_ptr); 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate return (res); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate static nss_status_t 302*0Sstevel@tonic-gate do_getent(be, args, netdb) 303*0Sstevel@tonic-gate nis_backend_ptr_t be; 304*0Sstevel@tonic-gate nss_XbyY_args_t *args; 305*0Sstevel@tonic-gate int netdb; 306*0Sstevel@tonic-gate { 307*0Sstevel@tonic-gate nss_status_t res; 308*0Sstevel@tonic-gate int ypstatus; 309*0Sstevel@tonic-gate int outkeylen, outvallen; 310*0Sstevel@tonic-gate char *outkey, *outval; 311*0Sstevel@tonic-gate char *free_ptr; 312*0Sstevel@tonic-gate int parsestat; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate #if MT_UNSAFE_YP 315*0Sstevel@tonic-gate sigset_t oldmask, newmask; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate sigfillset(&newmask); 318*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 319*0Sstevel@tonic-gate _mutex_lock(&one_lane); 320*0Sstevel@tonic-gate #endif 321*0Sstevel@tonic-gate if (be->enum_key == 0) { 322*0Sstevel@tonic-gate ypstatus = __yp_first_cflookup((grrr)be->domain, 323*0Sstevel@tonic-gate (grrr)be->enum_map, &outkey, 324*0Sstevel@tonic-gate &outkeylen, &outval, 325*0Sstevel@tonic-gate &outvallen, 0); 326*0Sstevel@tonic-gate } else { 327*0Sstevel@tonic-gate ypstatus = __yp_next_cflookup((grrr)be->domain, 328*0Sstevel@tonic-gate (grrr)be->enum_map, be->enum_key, 329*0Sstevel@tonic-gate be->enum_keylen, &outkey, 330*0Sstevel@tonic-gate &outkeylen, &outval, 331*0Sstevel@tonic-gate &outvallen, 0); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate #if MT_UNSAFE_YP 334*0Sstevel@tonic-gate _mutex_unlock(&one_lane); 335*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 336*0Sstevel@tonic-gate #endif 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate if ((res = switch_err(ypstatus, 0)) != NSS_SUCCESS) { 339*0Sstevel@tonic-gate return (res); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate free_ptr = outval; 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate if (netdb) { 345*0Sstevel@tonic-gate massage_netdb((const char **)&outval, &outvallen); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate parsestat = (*args->str2ent)(outval, outvallen, 349*0Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 350*0Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 351*0Sstevel@tonic-gate args->returnval = args->buf.result; 352*0Sstevel@tonic-gate res = NSS_SUCCESS; 353*0Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 354*0Sstevel@tonic-gate args->erange = 1; 355*0Sstevel@tonic-gate /* We won't find this otherwise, anyway */ 356*0Sstevel@tonic-gate res = NSS_NOTFOUND; 357*0Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate free(free_ptr); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate if (be->enum_key != 0) { 362*0Sstevel@tonic-gate free(be->enum_key); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate be->enum_key = outkey; 365*0Sstevel@tonic-gate be->enum_keylen = outkeylen; 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate return (res); 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate nss_status_t 371*0Sstevel@tonic-gate _nss_nis_getent_rigid(be, args) 372*0Sstevel@tonic-gate nis_backend_ptr_t be; 373*0Sstevel@tonic-gate void *args; 374*0Sstevel@tonic-gate { 375*0Sstevel@tonic-gate return (do_getent(be, (nss_XbyY_args_t *)args, 0)); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate nss_status_t 379*0Sstevel@tonic-gate _nss_nis_getent_netdb(be, args) 380*0Sstevel@tonic-gate nis_backend_ptr_t be; 381*0Sstevel@tonic-gate void *args; 382*0Sstevel@tonic-gate { 383*0Sstevel@tonic-gate return (do_getent(be, (nss_XbyY_args_t *)args, 1)); 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate struct cb_data { 388*0Sstevel@tonic-gate void *args; 389*0Sstevel@tonic-gate const char *filter; 390*0Sstevel@tonic-gate nis_do_all_func_t func; 391*0Sstevel@tonic-gate nss_status_t result; 392*0Sstevel@tonic-gate }; 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate enum { ITER_NEXT = 0, ITER_STOP = 1 }; /* Should be in <rpcsvc/ypclnt.h> */ 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate /*ARGSUSED*/ 397*0Sstevel@tonic-gate static int 398*0Sstevel@tonic-gate do_cback(instatus, inkey, inkeylen, inval, invallen, indata) 399*0Sstevel@tonic-gate int instatus; 400*0Sstevel@tonic-gate const char *inkey; 401*0Sstevel@tonic-gate int inkeylen; 402*0Sstevel@tonic-gate const char *inval; 403*0Sstevel@tonic-gate int invallen; 404*0Sstevel@tonic-gate struct cb_data *indata; 405*0Sstevel@tonic-gate { 406*0Sstevel@tonic-gate nss_status_t res; 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate if (instatus != YP_TRUE) { 409*0Sstevel@tonic-gate return (ITER_NEXT); /* yp_all may decide otherwise... */ 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate if (indata->filter != 0 && strstr(inval, indata->filter) == 0) { 413*0Sstevel@tonic-gate /* 414*0Sstevel@tonic-gate * Optimization: if the entry doesn't contain the filter 415*0Sstevel@tonic-gate * string then it can't be the entry we want, so don't 416*0Sstevel@tonic-gate * bother looking more closely at it. 417*0Sstevel@tonic-gate */ 418*0Sstevel@tonic-gate return (ITER_NEXT); 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate res = (*indata->func)(inval, invallen, indata->args); 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate if (res == NSS_NOTFOUND) { 424*0Sstevel@tonic-gate return (ITER_NEXT); 425*0Sstevel@tonic-gate } else { 426*0Sstevel@tonic-gate indata->result = res; 427*0Sstevel@tonic-gate return (ITER_STOP); 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate nss_status_t 432*0Sstevel@tonic-gate _nss_nis_do_all(be, args, filter, func) 433*0Sstevel@tonic-gate nis_backend_ptr_t be; 434*0Sstevel@tonic-gate void *args; 435*0Sstevel@tonic-gate const char *filter; 436*0Sstevel@tonic-gate nis_do_all_func_t func; 437*0Sstevel@tonic-gate { 438*0Sstevel@tonic-gate int ypall_status; 439*0Sstevel@tonic-gate struct cb_data data; 440*0Sstevel@tonic-gate struct ypall_callback cback; 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate data.args = args; 443*0Sstevel@tonic-gate data.filter = filter; 444*0Sstevel@tonic-gate data.func = func; 445*0Sstevel@tonic-gate data.result = NSS_NOTFOUND; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate cback.foreach = do_cback; 448*0Sstevel@tonic-gate cback.data = (char *)&data; 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate #if MT_UNSAFE_YP 451*0Sstevel@tonic-gate sigset_t oldmask, newmask; 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate sigfillset(&newmask); 454*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 455*0Sstevel@tonic-gate _mutex_lock(&one_lane); 456*0Sstevel@tonic-gate #endif 457*0Sstevel@tonic-gate ypall_status = __yp_all_cflookup((grrr)be->domain, 458*0Sstevel@tonic-gate (grrr) be->enum_map, &cback, 0); 459*0Sstevel@tonic-gate #if MT_UNSAFE_YP 460*0Sstevel@tonic-gate _mutex_unlock(&one_lane); 461*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 462*0Sstevel@tonic-gate #endif 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate switch (ypall_status) { 465*0Sstevel@tonic-gate case 0: 466*0Sstevel@tonic-gate return (data.result); 467*0Sstevel@tonic-gate case YPERR_DOMAIN: 468*0Sstevel@tonic-gate case YPERR_YPSERV: 469*0Sstevel@tonic-gate case YPERR_BUSY: /* Probably never get this, but... */ 470*0Sstevel@tonic-gate return (NSS_TRYAGAIN); 471*0Sstevel@tonic-gate default: 472*0Sstevel@tonic-gate return (NSS_UNAVAIL); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate struct XbyY_data { 477*0Sstevel@tonic-gate nss_XbyY_args_t *args; 478*0Sstevel@tonic-gate nis_XY_check_func func; 479*0Sstevel@tonic-gate int netdb; 480*0Sstevel@tonic-gate }; 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate static nss_status_t 483*0Sstevel@tonic-gate XbyY_iterator(instr, instr_len, a) 484*0Sstevel@tonic-gate const char *instr; 485*0Sstevel@tonic-gate int instr_len; 486*0Sstevel@tonic-gate void *a; 487*0Sstevel@tonic-gate { 488*0Sstevel@tonic-gate struct XbyY_data *xydata = (struct XbyY_data *)a; 489*0Sstevel@tonic-gate nss_XbyY_args_t *args = xydata->args; 490*0Sstevel@tonic-gate nss_status_t res; 491*0Sstevel@tonic-gate int parsestat; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate if (xydata->netdb) { 494*0Sstevel@tonic-gate massage_netdb(&instr, &instr_len); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate parsestat = (*args->str2ent)(instr, instr_len, 498*0Sstevel@tonic-gate args->buf.result, args->buf.buffer, args->buf.buflen); 499*0Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) { 500*0Sstevel@tonic-gate args->returnval = args->buf.result; 501*0Sstevel@tonic-gate if ((*xydata->func)(args)) { 502*0Sstevel@tonic-gate res = NSS_SUCCESS; 503*0Sstevel@tonic-gate } else { 504*0Sstevel@tonic-gate res = NSS_NOTFOUND; 505*0Sstevel@tonic-gate args->returnval = 0; 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) { 508*0Sstevel@tonic-gate /* 509*0Sstevel@tonic-gate * If we got here because (*str2ent)() found that the buffer 510*0Sstevel@tonic-gate * wasn't big enough, maybe we should quit and return erange. 511*0Sstevel@tonic-gate * Instead we'll keep looking and eventually return "not 512*0Sstevel@tonic-gate * found" -- it's a bug, but not an earth-shattering one. 513*0Sstevel@tonic-gate */ 514*0Sstevel@tonic-gate args->erange = 1; /* <== Is this a good idea? */ 515*0Sstevel@tonic-gate res = NSS_NOTFOUND; 516*0Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */ 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate return (res); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate nss_status_t 522*0Sstevel@tonic-gate _nss_nis_XY_all(be, args, netdb, filter, func) 523*0Sstevel@tonic-gate nis_backend_ptr_t be; 524*0Sstevel@tonic-gate nss_XbyY_args_t *args; 525*0Sstevel@tonic-gate int netdb; 526*0Sstevel@tonic-gate const char *filter; 527*0Sstevel@tonic-gate nis_XY_check_func func; 528*0Sstevel@tonic-gate { 529*0Sstevel@tonic-gate struct XbyY_data data; 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate data.args = args; 532*0Sstevel@tonic-gate data.func = func; 533*0Sstevel@tonic-gate data.netdb = netdb; 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate return (_nss_nis_do_all(be, &data, filter, XbyY_iterator)); 536*0Sstevel@tonic-gate /* Now how many levels of callbacks was that? */ 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate /*ARGSUSED*/ 541*0Sstevel@tonic-gate nss_status_t 542*0Sstevel@tonic-gate _nss_nis_destr(be, dummy) 543*0Sstevel@tonic-gate nis_backend_ptr_t be; 544*0Sstevel@tonic-gate void *dummy; 545*0Sstevel@tonic-gate { 546*0Sstevel@tonic-gate if (be != 0) { 547*0Sstevel@tonic-gate /* === Should change to invoke ops[ENDENT] ? */ 548*0Sstevel@tonic-gate _nss_nis_endent(be, 0); 549*0Sstevel@tonic-gate free(be); 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate return (NSS_SUCCESS); /* In case anyone is dumb enough to check */ 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate /* We want to lock this even if the YP routines are MT-safe */ 555*0Sstevel@tonic-gate static mutex_t yp_domain_lock = DEFAULTMUTEX; 556*0Sstevel@tonic-gate static char *yp_domain; 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate const char * 559*0Sstevel@tonic-gate _nss_nis_domain() 560*0Sstevel@tonic-gate { 561*0Sstevel@tonic-gate char *domain; 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * This much locking is probably more "by the book" than necessary... 565*0Sstevel@tonic-gate */ 566*0Sstevel@tonic-gate sigset_t oldmask, newmask; 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate sigfillset(&newmask); 569*0Sstevel@tonic-gate (void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 570*0Sstevel@tonic-gate (void) _mutex_lock(&yp_domain_lock); 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate if ((domain = yp_domain) == 0) { 573*0Sstevel@tonic-gate #if MT_UNSAFE_YP 574*0Sstevel@tonic-gate _mutex_lock(&one_lane); 575*0Sstevel@tonic-gate #endif 576*0Sstevel@tonic-gate if (yp_get_default_domain(&yp_domain) == 0) { 577*0Sstevel@tonic-gate domain = yp_domain; 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate #if MT_UNSAFE_YP 580*0Sstevel@tonic-gate _mutex_unlock(&one_lane); 581*0Sstevel@tonic-gate #endif 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate _mutex_unlock(&yp_domain_lock); 585*0Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate return (domain); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate nss_backend_t * 591*0Sstevel@tonic-gate _nss_nis_constr(ops, n_ops, enum_map) 592*0Sstevel@tonic-gate nis_backend_op_t ops[]; 593*0Sstevel@tonic-gate int n_ops; 594*0Sstevel@tonic-gate const char *enum_map; 595*0Sstevel@tonic-gate { 596*0Sstevel@tonic-gate const char *domain; 597*0Sstevel@tonic-gate nis_backend_ptr_t be; 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate if ((domain = _nss_nis_domain()) == 0 || 600*0Sstevel@tonic-gate (be = (nis_backend_ptr_t)malloc(sizeof (*be))) == 0) { 601*0Sstevel@tonic-gate return (0); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate be->ops = ops; 604*0Sstevel@tonic-gate be->n_ops = n_ops; 605*0Sstevel@tonic-gate be->domain = domain; 606*0Sstevel@tonic-gate be->enum_map = enum_map; /* Don't strdup, assume valid forever */ 607*0Sstevel@tonic-gate be->enum_key = 0; 608*0Sstevel@tonic-gate be->enum_keylen = 0; 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate return ((nss_backend_t *)be); 611*0Sstevel@tonic-gate } 612