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 */ 21*7257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23*7257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24cb5caa98Sdjl * Use is subject to license terms. 25*7257d1b4Sraf */ 26*7257d1b4Sraf 27*7257d1b4Sraf /* 287c478bd9Sstevel@tonic-gate * nis/getservent.c -- "nis" backend for nsswitch "services" database 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include "nis_common.h" 347c478bd9Sstevel@tonic-gate #include <stdio.h> 35cb5caa98Sdjl #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <signal.h> 387c478bd9Sstevel@tonic-gate #include <malloc.h> 397c478bd9Sstevel@tonic-gate #include <netdb.h> 407c478bd9Sstevel@tonic-gate #include <synch.h> 41cb5caa98Sdjl #include <ctype.h> 427c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 437c478bd9Sstevel@tonic-gate #include <thread.h> 447c478bd9Sstevel@tonic-gate #include <sys/types.h> 457c478bd9Sstevel@tonic-gate #include <netinet/in.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static int 487c478bd9Sstevel@tonic-gate check_name(args) 497c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 507c478bd9Sstevel@tonic-gate { 517c478bd9Sstevel@tonic-gate struct servent *serv = (struct servent *)args->returnval; 527c478bd9Sstevel@tonic-gate const char *name = args->key.serv.serv.name; 537c478bd9Sstevel@tonic-gate const char *proto = args->key.serv.proto; 547c478bd9Sstevel@tonic-gate char **aliasp; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate if (proto != 0 && strcmp(serv->s_proto, proto) != 0) { 577c478bd9Sstevel@tonic-gate return (0); 587c478bd9Sstevel@tonic-gate } 597c478bd9Sstevel@tonic-gate if (strcmp(serv->s_name, name) == 0) { 607c478bd9Sstevel@tonic-gate return (1); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate for (aliasp = serv->s_aliases; *aliasp != 0; aliasp++) { 637c478bd9Sstevel@tonic-gate if (strcmp(*aliasp, name) == 0) { 647c478bd9Sstevel@tonic-gate return (1); 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate } 677c478bd9Sstevel@tonic-gate return (0); 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate 70cb5caa98Sdjl static int 71cb5caa98Sdjl check_name2(nss_XbyY_args_t *argp) 72cb5caa98Sdjl { 73cb5caa98Sdjl const char *limit, *linep, *keyp; 74cb5caa98Sdjl int name_match = 0; 75cb5caa98Sdjl 76cb5caa98Sdjl linep = (const char *)argp->buf.buffer; 77cb5caa98Sdjl limit = linep + strlen(argp->buf.buffer); 78cb5caa98Sdjl keyp = argp->key.serv.serv.name; 79cb5caa98Sdjl 80cb5caa98Sdjl /* compare name */ 81cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 82cb5caa98Sdjl keyp++; 83cb5caa98Sdjl linep++; 84cb5caa98Sdjl } 85cb5caa98Sdjl if (*keyp == '\0' && linep < limit && isspace(*linep)) { 86cb5caa98Sdjl if (argp->key.serv.proto == NULL) 87cb5caa98Sdjl return (1); 88cb5caa98Sdjl else 89cb5caa98Sdjl name_match = 1; 90cb5caa98Sdjl } 91cb5caa98Sdjl 92cb5caa98Sdjl /* skip remainder of the name, if any */ 93cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 94cb5caa98Sdjl linep++; 95cb5caa98Sdjl /* skip the delimiting spaces */ 96cb5caa98Sdjl while (linep < limit && isspace(*linep)) 97cb5caa98Sdjl linep++; 98cb5caa98Sdjl /* skip port number */ 99cb5caa98Sdjl while (linep < limit && !isspace(*linep) && *linep != '/') 100cb5caa98Sdjl linep++; 101cb5caa98Sdjl if (linep == limit || *linep != '/') 102cb5caa98Sdjl return (0); 103cb5caa98Sdjl 104cb5caa98Sdjl linep++; 105cb5caa98Sdjl if ((keyp = argp->key.serv.proto) == NULL) { 106cb5caa98Sdjl /* skip protocol */ 107cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 108cb5caa98Sdjl linep++; 109cb5caa98Sdjl } else { 110cb5caa98Sdjl /* compare protocol */ 111cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 112cb5caa98Sdjl *keyp == *linep) { 113cb5caa98Sdjl keyp++; 114cb5caa98Sdjl linep++; 115cb5caa98Sdjl } 116cb5caa98Sdjl /* no protocol match */ 117cb5caa98Sdjl if (*keyp || (linep < limit && !isspace(*linep))) 118cb5caa98Sdjl return (0); 119cb5caa98Sdjl /* protocol and name match, return */ 120cb5caa98Sdjl if (name_match) 121cb5caa98Sdjl return (1); 122cb5caa98Sdjl /* protocol match but name yet to be matched, so continue */ 123cb5caa98Sdjl } 124cb5caa98Sdjl 125cb5caa98Sdjl /* compare with the aliases */ 126cb5caa98Sdjl while (linep < limit) { 127cb5caa98Sdjl /* skip the delimiting spaces */ 128cb5caa98Sdjl while (linep < limit && isspace(*linep)) 129cb5caa98Sdjl linep++; 130cb5caa98Sdjl 131cb5caa98Sdjl /* compare with the alias name */ 132cb5caa98Sdjl keyp = argp->key.serv.serv.name; 133cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 134cb5caa98Sdjl *keyp == *linep) { 135cb5caa98Sdjl keyp++; 136cb5caa98Sdjl linep++; 137cb5caa98Sdjl } 138cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 139cb5caa98Sdjl return (1); 140cb5caa98Sdjl 141cb5caa98Sdjl /* skip remainder of the alias name, if any */ 142cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 143cb5caa98Sdjl linep++; 144cb5caa98Sdjl } 145cb5caa98Sdjl return (0); 146cb5caa98Sdjl } 147cb5caa98Sdjl 1487c478bd9Sstevel@tonic-gate static mutex_t no_byname_lock = DEFAULTMUTEX; 1497c478bd9Sstevel@tonic-gate static int no_byname_map = 0; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate static nss_status_t 1527c478bd9Sstevel@tonic-gate getbyname(be, a) 1537c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 1547c478bd9Sstevel@tonic-gate void *a; 1557c478bd9Sstevel@tonic-gate { 1567c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1577c478bd9Sstevel@tonic-gate const char *name = argp->key.serv.serv.name; 1587c478bd9Sstevel@tonic-gate const char *proto = argp->key.serv.proto; 1597c478bd9Sstevel@tonic-gate int no_map; 1607c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask; 1617c478bd9Sstevel@tonic-gate 162cb5caa98Sdjl (void) sigfillset(&newmask); 163*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 164*7257d1b4Sraf (void) mutex_lock(&no_byname_lock); 1657c478bd9Sstevel@tonic-gate no_map = no_byname_map; 166*7257d1b4Sraf (void) mutex_unlock(&no_byname_lock); 167*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (no_map == 0) { 1707c478bd9Sstevel@tonic-gate int yp_status; 1717c478bd9Sstevel@tonic-gate nss_status_t res; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate if (proto == 0) { 1747c478bd9Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, 1757c478bd9Sstevel@tonic-gate "services.byservicename", name, &yp_status); 1767c478bd9Sstevel@tonic-gate } else { 177cb5caa98Sdjl int len = strlen(name) + strlen(proto) + 3; 178cb5caa98Sdjl char *key = malloc(len); 1797c478bd9Sstevel@tonic-gate 180cb5caa98Sdjl if (key == NULL) { 1817c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 1827c478bd9Sstevel@tonic-gate } 183cb5caa98Sdjl (void) snprintf(key, len, "%s/%s", name, proto); 1847c478bd9Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, 1857c478bd9Sstevel@tonic-gate "services.byservicename", key, &yp_status); 1867c478bd9Sstevel@tonic-gate free(key); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (yp_status == YPERR_MAP) { 190cb5caa98Sdjl (void) sigfillset(&newmask); 191*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask); 192*7257d1b4Sraf (void) mutex_lock(&no_byname_lock); 1937c478bd9Sstevel@tonic-gate no_byname_map = 1; 194*7257d1b4Sraf (void) mutex_unlock(&no_byname_lock); 195*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, 196cb5caa98Sdjl (sigset_t *)NULL); 1977c478bd9Sstevel@tonic-gate } else /* if (res == NSS_SUCCESS) <==== */ { 1987c478bd9Sstevel@tonic-gate return (res); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 202cb5caa98Sdjl /* 203cb5caa98Sdjl * use check_anme to compare service name if nss1 or nss2 and 204cb5caa98Sdjl * request is not from nscd; otherwise use check_name2 205cb5caa98Sdjl */ 206cb5caa98Sdjl if (argp->buf.result != NULL) 2077c478bd9Sstevel@tonic-gate return (_nss_nis_XY_all(be, argp, 1, name, check_name)); 208cb5caa98Sdjl else 209cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, name, check_name2)); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static int 2137c478bd9Sstevel@tonic-gate check_port(args) 2147c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 2157c478bd9Sstevel@tonic-gate { 2167c478bd9Sstevel@tonic-gate struct servent *serv = (struct servent *)args->returnval; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * We only resorted to _nss_nis_XY_all because proto == 0, so just... 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate return (serv->s_port == args->key.serv.serv.port); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 224cb5caa98Sdjl static int 225cb5caa98Sdjl check_port2(nss_XbyY_args_t *argp) 226cb5caa98Sdjl { 227cb5caa98Sdjl const char *limit, *linep, *keyp, *numstart; 228cb5caa98Sdjl int numlen, s_port; 229cb5caa98Sdjl char numbuf[12], *numend; 230cb5caa98Sdjl 231cb5caa98Sdjl linep = (const char *)argp->buf.buffer; 232cb5caa98Sdjl limit = linep + strlen(argp->buf.buffer); 233cb5caa98Sdjl 234cb5caa98Sdjl /* skip name */ 235cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 236cb5caa98Sdjl linep++; 237cb5caa98Sdjl /* skip the delimiting spaces */ 238cb5caa98Sdjl while (linep < limit && isspace(*linep)) 239cb5caa98Sdjl linep++; 240cb5caa98Sdjl 241cb5caa98Sdjl /* compare port num */ 242cb5caa98Sdjl numstart = linep; 243cb5caa98Sdjl while (linep < limit && !isspace(*linep) && *linep != '/') 244cb5caa98Sdjl linep++; 245cb5caa98Sdjl if (linep == limit || *linep != '/') 246cb5caa98Sdjl return (0); 247cb5caa98Sdjl numlen = linep - numstart; 248cb5caa98Sdjl if (numlen == 0 || numlen >= sizeof (numbuf)) 249cb5caa98Sdjl return (0); 250cb5caa98Sdjl (void) memcpy(numbuf, numstart, numlen); 251cb5caa98Sdjl numbuf[numlen] = '\0'; 252cb5caa98Sdjl s_port = htons((int)strtol(numbuf, &numend, 10)); 253cb5caa98Sdjl if (*numend != '\0') 254cb5caa98Sdjl return (0); 255cb5caa98Sdjl if (s_port == argp->key.serv.serv.port) { 256cb5caa98Sdjl if ((keyp = argp->key.serv.proto) == NULL) 257cb5caa98Sdjl return (1); 258cb5caa98Sdjl } else 259cb5caa98Sdjl return (0); 260cb5caa98Sdjl 261cb5caa98Sdjl /* compare protocol */ 262cb5caa98Sdjl linep++; 263cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) { 264cb5caa98Sdjl keyp++; 265cb5caa98Sdjl linep++; 266cb5caa98Sdjl } 267cb5caa98Sdjl return (*keyp == '\0' && (linep == limit || isspace(*linep))); 268cb5caa98Sdjl } 269cb5caa98Sdjl 270cb5caa98Sdjl 2717c478bd9Sstevel@tonic-gate static nss_status_t 2727c478bd9Sstevel@tonic-gate getbyport(be, a) 2737c478bd9Sstevel@tonic-gate nis_backend_ptr_t be; 2747c478bd9Sstevel@tonic-gate void *a; 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2777c478bd9Sstevel@tonic-gate int port = ntohs(argp->key.serv.serv.port); 2787c478bd9Sstevel@tonic-gate const char *proto = argp->key.serv.proto; 2797c478bd9Sstevel@tonic-gate char *key; 2807c478bd9Sstevel@tonic-gate nss_status_t res; 281cb5caa98Sdjl int len; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if (proto == 0) { 2847c478bd9Sstevel@tonic-gate char portstr[12]; 2857c478bd9Sstevel@tonic-gate 286cb5caa98Sdjl (void) snprintf(portstr, 12, "%d", port); 287cb5caa98Sdjl /* 288cb5caa98Sdjl * use check_port to compare service port if nss1 or 289cb5caa98Sdjl * nss2 and request is not from nscd; otherwise use 290cb5caa98Sdjl * check_port2 291cb5caa98Sdjl */ 292cb5caa98Sdjl if (argp->buf.result != NULL) 293cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, portstr, 294cb5caa98Sdjl check_port)); 295cb5caa98Sdjl else 296cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, portstr, 297cb5caa98Sdjl check_port2)); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 300cb5caa98Sdjl len = strlen(proto) + 14; 301cb5caa98Sdjl if ((key = malloc(len)) == 0) { 3027c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 3037c478bd9Sstevel@tonic-gate } 304cb5caa98Sdjl (void) snprintf(key, len, "%d/%s", port, proto); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, "services.byname", key, 0); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate free(key); 3097c478bd9Sstevel@tonic-gate return (res); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate static nis_backend_op_t serv_ops[] = { 3137c478bd9Sstevel@tonic-gate _nss_nis_destr, 3147c478bd9Sstevel@tonic-gate _nss_nis_endent, 3157c478bd9Sstevel@tonic-gate _nss_nis_setent, 3167c478bd9Sstevel@tonic-gate _nss_nis_getent_netdb, 3177c478bd9Sstevel@tonic-gate getbyname, 3187c478bd9Sstevel@tonic-gate getbyport 3197c478bd9Sstevel@tonic-gate }; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3227c478bd9Sstevel@tonic-gate nss_backend_t * 3237c478bd9Sstevel@tonic-gate _nss_nis_services_constr(dummy1, dummy2, dummy3) 3247c478bd9Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3257c478bd9Sstevel@tonic-gate { 3267c478bd9Sstevel@tonic-gate return (_nss_nis_constr(serv_ops, 3277c478bd9Sstevel@tonic-gate sizeof (serv_ops) / sizeof (serv_ops[0]), 3287c478bd9Sstevel@tonic-gate "services.byname")); 3297c478bd9Sstevel@tonic-gate } 330