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 #include "nis_common.h"
327c478bd9Sstevel@tonic-gate #include <stdio.h>
33cb5caa98Sdjl #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <signal.h>
367c478bd9Sstevel@tonic-gate #include <malloc.h>
377c478bd9Sstevel@tonic-gate #include <netdb.h>
387c478bd9Sstevel@tonic-gate #include <synch.h>
39cb5caa98Sdjl #include <ctype.h>
407c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
417c478bd9Sstevel@tonic-gate #include <thread.h>
427c478bd9Sstevel@tonic-gate #include <sys/types.h>
437c478bd9Sstevel@tonic-gate #include <netinet/in.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate static int
check_name(args)467c478bd9Sstevel@tonic-gate check_name(args)
477c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args;
487c478bd9Sstevel@tonic-gate {
49cb5caa98Sdjl struct servent *serv = (struct servent *)args->returnval;
507c478bd9Sstevel@tonic-gate const char *name = args->key.serv.serv.name;
517c478bd9Sstevel@tonic-gate const char *proto = args->key.serv.proto;
527c478bd9Sstevel@tonic-gate char **aliasp;
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate if (proto != 0 && strcmp(serv->s_proto, proto) != 0) {
557c478bd9Sstevel@tonic-gate return (0);
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate if (strcmp(serv->s_name, name) == 0) {
587c478bd9Sstevel@tonic-gate return (1);
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate for (aliasp = serv->s_aliases; *aliasp != 0; aliasp++) {
617c478bd9Sstevel@tonic-gate if (strcmp(*aliasp, name) == 0) {
627c478bd9Sstevel@tonic-gate return (1);
637c478bd9Sstevel@tonic-gate }
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate return (0);
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate
68cb5caa98Sdjl static int
check_name2(nss_XbyY_args_t * argp)69cb5caa98Sdjl check_name2(nss_XbyY_args_t *argp)
70cb5caa98Sdjl {
71cb5caa98Sdjl const char *limit, *linep, *keyp;
72cb5caa98Sdjl int name_match = 0;
73cb5caa98Sdjl
74cb5caa98Sdjl linep = (const char *)argp->buf.buffer;
75cb5caa98Sdjl limit = linep + strlen(argp->buf.buffer);
76cb5caa98Sdjl keyp = argp->key.serv.serv.name;
77cb5caa98Sdjl
78cb5caa98Sdjl /* compare name */
79cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
80cb5caa98Sdjl keyp++;
81cb5caa98Sdjl linep++;
82cb5caa98Sdjl }
83cb5caa98Sdjl if (*keyp == '\0' && linep < limit && isspace(*linep)) {
84cb5caa98Sdjl if (argp->key.serv.proto == NULL)
85cb5caa98Sdjl return (1);
86cb5caa98Sdjl else
87cb5caa98Sdjl name_match = 1;
88cb5caa98Sdjl }
89cb5caa98Sdjl
90cb5caa98Sdjl /* skip remainder of the name, if any */
91cb5caa98Sdjl while (linep < limit && !isspace(*linep))
92cb5caa98Sdjl linep++;
93cb5caa98Sdjl /* skip the delimiting spaces */
94cb5caa98Sdjl while (linep < limit && isspace(*linep))
95cb5caa98Sdjl linep++;
96cb5caa98Sdjl /* skip port number */
97cb5caa98Sdjl while (linep < limit && !isspace(*linep) && *linep != '/')
98cb5caa98Sdjl linep++;
99cb5caa98Sdjl if (linep == limit || *linep != '/')
100cb5caa98Sdjl return (0);
101cb5caa98Sdjl
102cb5caa98Sdjl linep++;
103cb5caa98Sdjl if ((keyp = argp->key.serv.proto) == NULL) {
104cb5caa98Sdjl /* skip protocol */
105cb5caa98Sdjl while (linep < limit && !isspace(*linep))
106cb5caa98Sdjl linep++;
107cb5caa98Sdjl } else {
108cb5caa98Sdjl /* compare protocol */
109cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) &&
110*7257d1b4Sraf *keyp == *linep) {
111cb5caa98Sdjl keyp++;
112cb5caa98Sdjl linep++;
113cb5caa98Sdjl }
114cb5caa98Sdjl /* no protocol match */
115cb5caa98Sdjl if (*keyp || (linep < limit && !isspace(*linep)))
116cb5caa98Sdjl return (0);
117cb5caa98Sdjl /* protocol and name match, return */
118cb5caa98Sdjl if (name_match)
119cb5caa98Sdjl return (1);
120cb5caa98Sdjl /* protocol match but name yet to be matched, so continue */
121cb5caa98Sdjl }
122cb5caa98Sdjl
123cb5caa98Sdjl /* compare with the aliases */
124cb5caa98Sdjl while (linep < limit) {
125cb5caa98Sdjl /* skip the delimiting spaces */
126cb5caa98Sdjl while (linep < limit && isspace(*linep))
127cb5caa98Sdjl linep++;
128cb5caa98Sdjl
129cb5caa98Sdjl /* compare with the alias name */
130cb5caa98Sdjl keyp = argp->key.serv.serv.name;
131cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) &&
132*7257d1b4Sraf *keyp == *linep) {
133cb5caa98Sdjl keyp++;
134cb5caa98Sdjl linep++;
135cb5caa98Sdjl }
136cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep)))
137cb5caa98Sdjl return (1);
138cb5caa98Sdjl
139cb5caa98Sdjl /* skip remainder of the alias name, if any */
140cb5caa98Sdjl while (linep < limit && !isspace(*linep))
141cb5caa98Sdjl linep++;
142cb5caa98Sdjl }
143cb5caa98Sdjl return (0);
144cb5caa98Sdjl }
145cb5caa98Sdjl
1467c478bd9Sstevel@tonic-gate static mutex_t no_byname_lock = DEFAULTMUTEX;
1477c478bd9Sstevel@tonic-gate static int no_byname_map = 0;
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate static nss_status_t
getbyname(be,a)1507c478bd9Sstevel@tonic-gate getbyname(be, a)
1517c478bd9Sstevel@tonic-gate nis_backend_ptr_t be;
1527c478bd9Sstevel@tonic-gate void *a;
1537c478bd9Sstevel@tonic-gate {
154cb5caa98Sdjl nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
1557c478bd9Sstevel@tonic-gate const char *name = argp->key.serv.serv.name;
1567c478bd9Sstevel@tonic-gate const char *proto = argp->key.serv.proto;
1577c478bd9Sstevel@tonic-gate int no_map;
1587c478bd9Sstevel@tonic-gate sigset_t oldmask, newmask;
1597c478bd9Sstevel@tonic-gate
160cb5caa98Sdjl (void) sigfillset(&newmask);
161*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
162*7257d1b4Sraf (void) mutex_lock(&no_byname_lock);
1637c478bd9Sstevel@tonic-gate no_map = no_byname_map;
164*7257d1b4Sraf (void) mutex_unlock(&no_byname_lock);
165*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate if (no_map == 0) {
1687c478bd9Sstevel@tonic-gate int yp_status;
1697c478bd9Sstevel@tonic-gate nss_status_t res;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate if (proto == 0) {
1727c478bd9Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1,
1737c478bd9Sstevel@tonic-gate "services.byservicename", name, &yp_status);
1747c478bd9Sstevel@tonic-gate } else {
175cb5caa98Sdjl int len = strlen(name) + strlen(proto) + 3;
176cb5caa98Sdjl char *key = malloc(len);
1777c478bd9Sstevel@tonic-gate
178cb5caa98Sdjl if (key == NULL) {
1797c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
1807c478bd9Sstevel@tonic-gate }
181cb5caa98Sdjl (void) snprintf(key, len, "%s/%s", name, proto);
1827c478bd9Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1,
1837c478bd9Sstevel@tonic-gate "services.byservicename", key, &yp_status);
1847c478bd9Sstevel@tonic-gate free(key);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate if (yp_status == YPERR_MAP) {
188cb5caa98Sdjl (void) sigfillset(&newmask);
189*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
190*7257d1b4Sraf (void) mutex_lock(&no_byname_lock);
1917c478bd9Sstevel@tonic-gate no_byname_map = 1;
192*7257d1b4Sraf (void) mutex_unlock(&no_byname_lock);
193*7257d1b4Sraf (void) thr_sigsetmask(SIG_SETMASK, &oldmask,
194cb5caa98Sdjl (sigset_t *)NULL);
1957c478bd9Sstevel@tonic-gate } else /* if (res == NSS_SUCCESS) <==== */ {
1967c478bd9Sstevel@tonic-gate return (res);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
200cb5caa98Sdjl /*
201cb5caa98Sdjl * use check_anme to compare service name if nss1 or nss2 and
202cb5caa98Sdjl * request is not from nscd; otherwise use check_name2
203cb5caa98Sdjl */
204cb5caa98Sdjl if (argp->buf.result != NULL)
205cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, name, check_name));
206cb5caa98Sdjl else
207cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, name, check_name2));
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate static int
check_port(args)2117c478bd9Sstevel@tonic-gate check_port(args)
2127c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args;
2137c478bd9Sstevel@tonic-gate {
214cb5caa98Sdjl struct servent *serv = (struct servent *)args->returnval;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate * We only resorted to _nss_nis_XY_all because proto == 0, so just...
2187c478bd9Sstevel@tonic-gate */
2197c478bd9Sstevel@tonic-gate return (serv->s_port == args->key.serv.serv.port);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate
222cb5caa98Sdjl static int
check_port2(nss_XbyY_args_t * argp)223cb5caa98Sdjl check_port2(nss_XbyY_args_t *argp)
224cb5caa98Sdjl {
225cb5caa98Sdjl const char *limit, *linep, *keyp, *numstart;
226cb5caa98Sdjl int numlen, s_port;
227cb5caa98Sdjl char numbuf[12], *numend;
228cb5caa98Sdjl
229cb5caa98Sdjl linep = (const char *)argp->buf.buffer;
230cb5caa98Sdjl limit = linep + strlen(argp->buf.buffer);
231cb5caa98Sdjl
232cb5caa98Sdjl /* skip name */
233cb5caa98Sdjl while (linep < limit && !isspace(*linep))
234cb5caa98Sdjl linep++;
235cb5caa98Sdjl /* skip the delimiting spaces */
236cb5caa98Sdjl while (linep < limit && isspace(*linep))
237cb5caa98Sdjl linep++;
238cb5caa98Sdjl
239cb5caa98Sdjl /* compare port num */
240cb5caa98Sdjl numstart = linep;
241cb5caa98Sdjl while (linep < limit && !isspace(*linep) && *linep != '/')
242cb5caa98Sdjl linep++;
243cb5caa98Sdjl if (linep == limit || *linep != '/')
244cb5caa98Sdjl return (0);
245cb5caa98Sdjl numlen = linep - numstart;
246cb5caa98Sdjl if (numlen == 0 || numlen >= sizeof (numbuf))
247cb5caa98Sdjl return (0);
248cb5caa98Sdjl (void) memcpy(numbuf, numstart, numlen);
249cb5caa98Sdjl numbuf[numlen] = '\0';
250cb5caa98Sdjl s_port = htons((int)strtol(numbuf, &numend, 10));
251cb5caa98Sdjl if (*numend != '\0')
252cb5caa98Sdjl return (0);
253cb5caa98Sdjl if (s_port == argp->key.serv.serv.port) {
254cb5caa98Sdjl if ((keyp = argp->key.serv.proto) == NULL)
255cb5caa98Sdjl return (1);
256cb5caa98Sdjl } else
257cb5caa98Sdjl return (0);
258cb5caa98Sdjl
259cb5caa98Sdjl /* compare protocol */
260cb5caa98Sdjl linep++;
261cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
262cb5caa98Sdjl keyp++;
263cb5caa98Sdjl linep++;
264cb5caa98Sdjl }
265cb5caa98Sdjl return (*keyp == '\0' && (linep == limit || isspace(*linep)));
266cb5caa98Sdjl }
267cb5caa98Sdjl
268cb5caa98Sdjl
2697c478bd9Sstevel@tonic-gate static nss_status_t
getbyport(be,a)2707c478bd9Sstevel@tonic-gate getbyport(be, a)
2717c478bd9Sstevel@tonic-gate nis_backend_ptr_t be;
2727c478bd9Sstevel@tonic-gate void *a;
2737c478bd9Sstevel@tonic-gate {
274cb5caa98Sdjl nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2757c478bd9Sstevel@tonic-gate int port = ntohs(argp->key.serv.serv.port);
2767c478bd9Sstevel@tonic-gate const char *proto = argp->key.serv.proto;
2777c478bd9Sstevel@tonic-gate char *key;
2787c478bd9Sstevel@tonic-gate nss_status_t res;
279cb5caa98Sdjl int len;
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate if (proto == 0) {
2827c478bd9Sstevel@tonic-gate char portstr[12];
2837c478bd9Sstevel@tonic-gate
284cb5caa98Sdjl (void) snprintf(portstr, 12, "%d", port);
285cb5caa98Sdjl /*
286cb5caa98Sdjl * use check_port to compare service port if nss1 or
287cb5caa98Sdjl * nss2 and request is not from nscd; otherwise use
288cb5caa98Sdjl * check_port2
289cb5caa98Sdjl */
290cb5caa98Sdjl if (argp->buf.result != NULL)
291cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, portstr,
292cb5caa98Sdjl check_port));
293cb5caa98Sdjl else
294cb5caa98Sdjl return (_nss_nis_XY_all(be, argp, 1, portstr,
295cb5caa98Sdjl check_port2));
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
298cb5caa98Sdjl len = strlen(proto) + 14;
299cb5caa98Sdjl if ((key = malloc(len)) == 0) {
3007c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
3017c478bd9Sstevel@tonic-gate }
302cb5caa98Sdjl (void) snprintf(key, len, "%d/%s", port, proto);
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate res = _nss_nis_lookup(be, argp, 1, "services.byname", key, 0);
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate free(key);
3077c478bd9Sstevel@tonic-gate return (res);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate static nis_backend_op_t serv_ops[] = {
3117c478bd9Sstevel@tonic-gate _nss_nis_destr,
3127c478bd9Sstevel@tonic-gate _nss_nis_endent,
3137c478bd9Sstevel@tonic-gate _nss_nis_setent,
3147c478bd9Sstevel@tonic-gate _nss_nis_getent_netdb,
3157c478bd9Sstevel@tonic-gate getbyname,
3167c478bd9Sstevel@tonic-gate getbyport
3177c478bd9Sstevel@tonic-gate };
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3207c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_nis_services_constr(dummy1,dummy2,dummy3)3217c478bd9Sstevel@tonic-gate _nss_nis_services_constr(dummy1, dummy2, dummy3)
3227c478bd9Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3;
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate return (_nss_nis_constr(serv_ops,
3257c478bd9Sstevel@tonic-gate sizeof (serv_ops) / sizeof (serv_ops[0]),
3267c478bd9Sstevel@tonic-gate "services.byname"));
3277c478bd9Sstevel@tonic-gate }
328