10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2830Sdjl * Common Development and Distribution License (the "License"). 6*2830Sdjl * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2830Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*2830Sdjl * Use is subject to license terms. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * nis/getservent.c -- "nis" backend for nsswitch "services" database 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include "nis_common.h" 310Sstevel@tonic-gate #include <stdio.h> 32*2830Sdjl #include <stdlib.h> 330Sstevel@tonic-gate #include <string.h> 340Sstevel@tonic-gate #include <signal.h> 350Sstevel@tonic-gate #include <malloc.h> 360Sstevel@tonic-gate #include <netdb.h> 370Sstevel@tonic-gate #include <synch.h> 38*2830Sdjl #include <ctype.h> 390Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 400Sstevel@tonic-gate #include <thread.h> 410Sstevel@tonic-gate #include <sys/types.h> 420Sstevel@tonic-gate #include <netinet/in.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate static int 450Sstevel@tonic-gate check_name(args) 460Sstevel@tonic-gate nss_XbyY_args_t *args; 470Sstevel@tonic-gate { 48*2830Sdjl struct servent *serv = (struct servent *)args->returnval; 490Sstevel@tonic-gate const char *name = args->key.serv.serv.name; 500Sstevel@tonic-gate const char *proto = args->key.serv.proto; 510Sstevel@tonic-gate char **aliasp; 520Sstevel@tonic-gate 530Sstevel@tonic-gate if (proto != 0 && strcmp(serv->s_proto, proto) != 0) { 540Sstevel@tonic-gate return (0); 550Sstevel@tonic-gate } 560Sstevel@tonic-gate if (strcmp(serv->s_name, name) == 0) { 570Sstevel@tonic-gate return (1); 580Sstevel@tonic-gate } 590Sstevel@tonic-gate for (aliasp = serv->s_aliases; *aliasp != 0; aliasp++) { 600Sstevel@tonic-gate if (strcmp(*aliasp, name) == 0) { 610Sstevel@tonic-gate return (1); 620Sstevel@tonic-gate } 630Sstevel@tonic-gate } 640Sstevel@tonic-gate return (0); 650Sstevel@tonic-gate } 660Sstevel@tonic-gate 67*2830Sdjl static int 68*2830Sdjl check_name2(nss_XbyY_args_t *argp) 69*2830Sdjl { 70*2830Sdjl const char *limit, *linep, *keyp; 71*2830Sdjl int name_match = 0; 72*2830Sdjl 73*2830Sdjl linep = (const char *)argp->buf.buffer; 74*2830Sdjl limit = linep + strlen(argp->buf.buffer); 75*2830Sdjl keyp = argp->key.serv.serv.name; 76*2830Sdjl 77*2830Sdjl /* compare name */ 78*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 79*2830Sdjl keyp++; 80*2830Sdjl linep++; 81*2830Sdjl } 82*2830Sdjl if (*keyp == '\0' && linep < limit && isspace(*linep)) { 83*2830Sdjl if (argp->key.serv.proto == NULL) 84*2830Sdjl return (1); 85*2830Sdjl else 86*2830Sdjl name_match = 1; 87*2830Sdjl } 88*2830Sdjl 89*2830Sdjl /* skip remainder of the name, if any */ 90*2830Sdjl while (linep < limit && !isspace(*linep)) 91*2830Sdjl linep++; 92*2830Sdjl /* skip the delimiting spaces */ 93*2830Sdjl while (linep < limit && isspace(*linep)) 94*2830Sdjl linep++; 95*2830Sdjl /* skip port number */ 96*2830Sdjl while (linep < limit && !isspace(*linep) && *linep != '/') 97*2830Sdjl linep++; 98*2830Sdjl if (linep == limit || *linep != '/') 99*2830Sdjl return (0); 100*2830Sdjl 101*2830Sdjl linep++; 102*2830Sdjl if ((keyp = argp->key.serv.proto) == NULL) { 103*2830Sdjl /* skip protocol */ 104*2830Sdjl while (linep < limit && !isspace(*linep)) 105*2830Sdjl linep++; 106*2830Sdjl } else { 107*2830Sdjl /* compare protocol */ 108*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 109*2830Sdjl *keyp == *linep) { 110*2830Sdjl keyp++; 111*2830Sdjl linep++; 112*2830Sdjl } 113*2830Sdjl /* no protocol match */ 114*2830Sdjl if (*keyp || (linep < limit && !isspace(*linep))) 115*2830Sdjl return (0); 116*2830Sdjl /* protocol and name match, return */ 117*2830Sdjl if (name_match) 118*2830Sdjl return (1); 119*2830Sdjl /* protocol match but name yet to be matched, so continue */ 120*2830Sdjl } 121*2830Sdjl 122*2830Sdjl /* compare with the aliases */ 123*2830Sdjl while (linep < limit) { 124*2830Sdjl /* skip the delimiting spaces */ 125*2830Sdjl while (linep < limit && isspace(*linep)) 126*2830Sdjl linep++; 127*2830Sdjl 128*2830Sdjl /* compare with the alias name */ 129*2830Sdjl keyp = argp->key.serv.serv.name; 130*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 131*2830Sdjl *keyp == *linep) { 132*2830Sdjl keyp++; 133*2830Sdjl linep++; 134*2830Sdjl } 135*2830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 136*2830Sdjl return (1); 137*2830Sdjl 138*2830Sdjl /* skip remainder of the alias name, if any */ 139*2830Sdjl while (linep < limit && !isspace(*linep)) 140*2830Sdjl linep++; 141*2830Sdjl } 142*2830Sdjl return (0); 143*2830Sdjl } 144*2830Sdjl 1450Sstevel@tonic-gate static mutex_t no_byname_lock = DEFAULTMUTEX; 1460Sstevel@tonic-gate static int no_byname_map = 0; 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate static nss_status_t 1490Sstevel@tonic-gate getbyname(be, a) 1500Sstevel@tonic-gate nis_backend_ptr_t be; 1510Sstevel@tonic-gate void *a; 1520Sstevel@tonic-gate { 153*2830Sdjl nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1540Sstevel@tonic-gate const char *name = argp->key.serv.serv.name; 1550Sstevel@tonic-gate const char *proto = argp->key.serv.proto; 1560Sstevel@tonic-gate int no_map; 1570Sstevel@tonic-gate sigset_t oldmask, newmask; 1580Sstevel@tonic-gate 159*2830Sdjl (void) sigfillset(&newmask); 1600Sstevel@tonic-gate (void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 1610Sstevel@tonic-gate (void) _mutex_lock(&no_byname_lock); 1620Sstevel@tonic-gate no_map = no_byname_map; 1630Sstevel@tonic-gate (void) _mutex_unlock(&no_byname_lock); 1640Sstevel@tonic-gate (void) _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate if (no_map == 0) { 1670Sstevel@tonic-gate int yp_status; 1680Sstevel@tonic-gate nss_status_t res; 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate if (proto == 0) { 1710Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, 1720Sstevel@tonic-gate "services.byservicename", name, &yp_status); 1730Sstevel@tonic-gate } else { 174*2830Sdjl int len = strlen(name) + strlen(proto) + 3; 175*2830Sdjl char *key = malloc(len); 1760Sstevel@tonic-gate 177*2830Sdjl if (key == NULL) { 1780Sstevel@tonic-gate return (NSS_UNAVAIL); 1790Sstevel@tonic-gate } 180*2830Sdjl (void) snprintf(key, len, "%s/%s", name, proto); 1810Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, 1820Sstevel@tonic-gate "services.byservicename", key, &yp_status); 1830Sstevel@tonic-gate free(key); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate if (yp_status == YPERR_MAP) { 187*2830Sdjl (void) sigfillset(&newmask); 1880Sstevel@tonic-gate _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 1890Sstevel@tonic-gate _mutex_lock(&no_byname_lock); 1900Sstevel@tonic-gate no_byname_map = 1; 1910Sstevel@tonic-gate _mutex_unlock(&no_byname_lock); 192*2830Sdjl _thr_sigsetmask(SIG_SETMASK, &oldmask, 193*2830Sdjl (sigset_t *)NULL); 1940Sstevel@tonic-gate } else /* if (res == NSS_SUCCESS) <==== */ { 1950Sstevel@tonic-gate return (res); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate 199*2830Sdjl /* 200*2830Sdjl * use check_anme to compare service name if nss1 or nss2 and 201*2830Sdjl * request is not from nscd; otherwise use check_name2 202*2830Sdjl */ 203*2830Sdjl if (argp->buf.result != NULL) 204*2830Sdjl return (_nss_nis_XY_all(be, argp, 1, name, check_name)); 205*2830Sdjl else 206*2830Sdjl return (_nss_nis_XY_all(be, argp, 1, name, check_name2)); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate static int 2100Sstevel@tonic-gate check_port(args) 2110Sstevel@tonic-gate nss_XbyY_args_t *args; 2120Sstevel@tonic-gate { 213*2830Sdjl struct servent *serv = (struct servent *)args->returnval; 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* 2160Sstevel@tonic-gate * We only resorted to _nss_nis_XY_all because proto == 0, so just... 2170Sstevel@tonic-gate */ 2180Sstevel@tonic-gate return (serv->s_port == args->key.serv.serv.port); 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 221*2830Sdjl static int 222*2830Sdjl check_port2(nss_XbyY_args_t *argp) 223*2830Sdjl { 224*2830Sdjl const char *limit, *linep, *keyp, *numstart; 225*2830Sdjl int numlen, s_port; 226*2830Sdjl char numbuf[12], *numend; 227*2830Sdjl 228*2830Sdjl linep = (const char *)argp->buf.buffer; 229*2830Sdjl limit = linep + strlen(argp->buf.buffer); 230*2830Sdjl 231*2830Sdjl /* skip name */ 232*2830Sdjl while (linep < limit && !isspace(*linep)) 233*2830Sdjl linep++; 234*2830Sdjl /* skip the delimiting spaces */ 235*2830Sdjl while (linep < limit && isspace(*linep)) 236*2830Sdjl linep++; 237*2830Sdjl 238*2830Sdjl /* compare port num */ 239*2830Sdjl numstart = linep; 240*2830Sdjl while (linep < limit && !isspace(*linep) && *linep != '/') 241*2830Sdjl linep++; 242*2830Sdjl if (linep == limit || *linep != '/') 243*2830Sdjl return (0); 244*2830Sdjl numlen = linep - numstart; 245*2830Sdjl if (numlen == 0 || numlen >= sizeof (numbuf)) 246*2830Sdjl return (0); 247*2830Sdjl (void) memcpy(numbuf, numstart, numlen); 248*2830Sdjl numbuf[numlen] = '\0'; 249*2830Sdjl s_port = htons((int)strtol(numbuf, &numend, 10)); 250*2830Sdjl if (*numend != '\0') 251*2830Sdjl return (0); 252*2830Sdjl if (s_port == argp->key.serv.serv.port) { 253*2830Sdjl if ((keyp = argp->key.serv.proto) == NULL) 254*2830Sdjl return (1); 255*2830Sdjl } else 256*2830Sdjl return (0); 257*2830Sdjl 258*2830Sdjl /* compare protocol */ 259*2830Sdjl linep++; 260*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 261*2830Sdjl keyp++; 262*2830Sdjl linep++; 263*2830Sdjl } 264*2830Sdjl return (*keyp == '\0' && (linep == limit || isspace(*linep))); 265*2830Sdjl } 266*2830Sdjl 267*2830Sdjl 2680Sstevel@tonic-gate static nss_status_t 2690Sstevel@tonic-gate getbyport(be, a) 2700Sstevel@tonic-gate nis_backend_ptr_t be; 2710Sstevel@tonic-gate void *a; 2720Sstevel@tonic-gate { 273*2830Sdjl nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2740Sstevel@tonic-gate int port = ntohs(argp->key.serv.serv.port); 2750Sstevel@tonic-gate const char *proto = argp->key.serv.proto; 2760Sstevel@tonic-gate char *key; 2770Sstevel@tonic-gate nss_status_t res; 278*2830Sdjl int len; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (proto == 0) { 2810Sstevel@tonic-gate char portstr[12]; 2820Sstevel@tonic-gate 283*2830Sdjl (void) snprintf(portstr, 12, "%d", port); 284*2830Sdjl /* 285*2830Sdjl * use check_port to compare service port if nss1 or 286*2830Sdjl * nss2 and request is not from nscd; otherwise use 287*2830Sdjl * check_port2 288*2830Sdjl */ 289*2830Sdjl if (argp->buf.result != NULL) 290*2830Sdjl return (_nss_nis_XY_all(be, argp, 1, portstr, 291*2830Sdjl check_port)); 292*2830Sdjl else 293*2830Sdjl return (_nss_nis_XY_all(be, argp, 1, portstr, 294*2830Sdjl check_port2)); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 297*2830Sdjl len = strlen(proto) + 14; 298*2830Sdjl if ((key = malloc(len)) == 0) { 2990Sstevel@tonic-gate return (NSS_UNAVAIL); 3000Sstevel@tonic-gate } 301*2830Sdjl (void) snprintf(key, len, "%d/%s", port, proto); 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, "services.byname", key, 0); 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate free(key); 3060Sstevel@tonic-gate return (res); 3070Sstevel@tonic-gate } 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate static nis_backend_op_t serv_ops[] = { 3100Sstevel@tonic-gate _nss_nis_destr, 3110Sstevel@tonic-gate _nss_nis_endent, 3120Sstevel@tonic-gate _nss_nis_setent, 3130Sstevel@tonic-gate _nss_nis_getent_netdb, 3140Sstevel@tonic-gate getbyname, 3150Sstevel@tonic-gate getbyport 3160Sstevel@tonic-gate }; 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate /*ARGSUSED*/ 3190Sstevel@tonic-gate nss_backend_t * 3200Sstevel@tonic-gate _nss_nis_services_constr(dummy1, dummy2, dummy3) 3210Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3220Sstevel@tonic-gate { 3230Sstevel@tonic-gate return (_nss_nis_constr(serv_ops, 3240Sstevel@tonic-gate sizeof (serv_ops) / sizeof (serv_ops[0]), 3250Sstevel@tonic-gate "services.byname")); 3260Sstevel@tonic-gate } 327