xref: /freebsd/usr.sbin/ypldap/yp.c (revision db891e2149ca3fd06924447609926d6815174da3)
19e7c127fSCraig Rodrigues /*	$OpenBSD: yp.c,v 1.14 2015/02/11 01:26:00 pelikan Exp $ */
29e7c127fSCraig Rodrigues /*	$FreeBSD$ */
39e7c127fSCraig Rodrigues /*
49e7c127fSCraig Rodrigues  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
59e7c127fSCraig Rodrigues  *
69e7c127fSCraig Rodrigues  * Permission to use, copy, modify, and distribute this software for any
79e7c127fSCraig Rodrigues  * purpose with or without fee is hereby granted, provided that the above
89e7c127fSCraig Rodrigues  * copyright notice and this permission notice appear in all copies.
99e7c127fSCraig Rodrigues  *
109e7c127fSCraig Rodrigues  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
119e7c127fSCraig Rodrigues  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
129e7c127fSCraig Rodrigues  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
139e7c127fSCraig Rodrigues  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
149e7c127fSCraig Rodrigues  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
159e7c127fSCraig Rodrigues  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
169e7c127fSCraig Rodrigues  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
179e7c127fSCraig Rodrigues  */
189e7c127fSCraig Rodrigues 
199e7c127fSCraig Rodrigues #include <sys/types.h>
2066b5c05dSCraig Rodrigues #include <sys/param.h>
219e7c127fSCraig Rodrigues #include <sys/queue.h>
229e7c127fSCraig Rodrigues #include <sys/socket.h>
239e7c127fSCraig Rodrigues #include <sys/select.h>
249e7c127fSCraig Rodrigues #include <sys/tree.h>
259e7c127fSCraig Rodrigues 
269e7c127fSCraig Rodrigues #include <netinet/in.h>
279e7c127fSCraig Rodrigues #include <arpa/inet.h>
289e7c127fSCraig Rodrigues 
299e7c127fSCraig Rodrigues #include <errno.h>
309e7c127fSCraig Rodrigues #include <event.h>
319e7c127fSCraig Rodrigues #include <fcntl.h>
329e7c127fSCraig Rodrigues #include <unistd.h>
339e7c127fSCraig Rodrigues #include <pwd.h>
349e7c127fSCraig Rodrigues #include <stdio.h>
359e7c127fSCraig Rodrigues #include <stdlib.h>
369e7c127fSCraig Rodrigues #include <string.h>
379e7c127fSCraig Rodrigues #include <limits.h>
389e7c127fSCraig Rodrigues 
399e7c127fSCraig Rodrigues #include <rpc/rpc.h>
409e7c127fSCraig Rodrigues #include <rpc/xdr.h>
419e7c127fSCraig Rodrigues #include <rpc/pmap_clnt.h>
429e7c127fSCraig Rodrigues #include <rpc/pmap_prot.h>
439e7c127fSCraig Rodrigues #include <rpc/pmap_rmt.h>
449e7c127fSCraig Rodrigues #include <rpcsvc/yp.h>
459e7c127fSCraig Rodrigues #include <rpcsvc/ypclnt.h>
469e7c127fSCraig Rodrigues 
479e7c127fSCraig Rodrigues #include "ypldap.h"
489e7c127fSCraig Rodrigues 
499e7c127fSCraig Rodrigues void	yp_dispatch(struct svc_req *, SVCXPRT *);
509e7c127fSCraig Rodrigues void	yp_disable_events(void);
519e7c127fSCraig Rodrigues void	yp_fd_event(int, short, void *);
529e7c127fSCraig Rodrigues int	yp_check(struct svc_req *);
539e7c127fSCraig Rodrigues int	yp_valid_domain(char *, struct ypresp_val *);
549e7c127fSCraig Rodrigues void	yp_make_val(struct ypresp_val *, char *, int);
559e7c127fSCraig Rodrigues void	yp_make_keyval(struct ypresp_key_val *, char *, char *);
569e7c127fSCraig Rodrigues 
579e7c127fSCraig Rodrigues static struct env	*env;
589e7c127fSCraig Rodrigues 
599e7c127fSCraig Rodrigues struct yp_event {
609e7c127fSCraig Rodrigues 	TAILQ_ENTRY(yp_event)	 ye_entry;
619e7c127fSCraig Rodrigues 	struct event		 ye_event;
629e7c127fSCraig Rodrigues };
639e7c127fSCraig Rodrigues 
649e7c127fSCraig Rodrigues struct yp_data {
659e7c127fSCraig Rodrigues 	SVCXPRT			*yp_trans_udp;
669e7c127fSCraig Rodrigues 	SVCXPRT			*yp_trans_tcp;
679e7c127fSCraig Rodrigues 	TAILQ_HEAD(, yp_event)	 yd_events;
689e7c127fSCraig Rodrigues };
699e7c127fSCraig Rodrigues 
709e7c127fSCraig Rodrigues void
719e7c127fSCraig Rodrigues yp_disable_events(void)
729e7c127fSCraig Rodrigues {
739e7c127fSCraig Rodrigues 	struct yp_event	*ye;
749e7c127fSCraig Rodrigues 
759e7c127fSCraig Rodrigues 	while ((ye = TAILQ_FIRST(&env->sc_yp->yd_events)) != NULL) {
769e7c127fSCraig Rodrigues 		TAILQ_REMOVE(&env->sc_yp->yd_events, ye, ye_entry);
779e7c127fSCraig Rodrigues 		event_del(&ye->ye_event);
789e7c127fSCraig Rodrigues 		free(ye);
799e7c127fSCraig Rodrigues 	}
809e7c127fSCraig Rodrigues }
819e7c127fSCraig Rodrigues 
829e7c127fSCraig Rodrigues void
839e7c127fSCraig Rodrigues yp_enable_events(void)
849e7c127fSCraig Rodrigues {
859e7c127fSCraig Rodrigues 	int i;
869e7c127fSCraig Rodrigues 	struct yp_event	*ye;
879e7c127fSCraig Rodrigues 
88*db891e21SMarcelo Araujo 	for (i = 0; i < getdtablesize(); i++) {
899e7c127fSCraig Rodrigues 		if ((ye = calloc(1, sizeof(*ye))) == NULL)
909e7c127fSCraig Rodrigues 			fatal(NULL);
919e7c127fSCraig Rodrigues 		event_set(&ye->ye_event, i, EV_READ, yp_fd_event, NULL);
929e7c127fSCraig Rodrigues 		event_add(&ye->ye_event, NULL);
939e7c127fSCraig Rodrigues 		TAILQ_INSERT_TAIL(&env->sc_yp->yd_events, ye, ye_entry);
949e7c127fSCraig Rodrigues 	}
959e7c127fSCraig Rodrigues }
969e7c127fSCraig Rodrigues 
979e7c127fSCraig Rodrigues void
989e7c127fSCraig Rodrigues yp_fd_event(int fd, short event, void *p)
999e7c127fSCraig Rodrigues {
1009e7c127fSCraig Rodrigues 	svc_getreq_common(fd);
1019e7c127fSCraig Rodrigues 	yp_disable_events();
1029e7c127fSCraig Rodrigues 	yp_enable_events();
1039e7c127fSCraig Rodrigues }
1049e7c127fSCraig Rodrigues 
1059e7c127fSCraig Rodrigues void
1069e7c127fSCraig Rodrigues yp_init(struct env *x_env)
1079e7c127fSCraig Rodrigues {
1089e7c127fSCraig Rodrigues 	struct yp_data	*yp;
1099e7c127fSCraig Rodrigues 
1109e7c127fSCraig Rodrigues 	if ((yp = calloc(1, sizeof(*yp))) == NULL)
1119e7c127fSCraig Rodrigues 		fatal(NULL);
1129e7c127fSCraig Rodrigues 	TAILQ_INIT(&yp->yd_events);
1139e7c127fSCraig Rodrigues 
1149e7c127fSCraig Rodrigues 	env = x_env;
1159e7c127fSCraig Rodrigues 	env->sc_yp = yp;
1169e7c127fSCraig Rodrigues 
1179e7c127fSCraig Rodrigues 	(void)pmap_unset(YPPROG, YPVERS);
1189e7c127fSCraig Rodrigues 
1199e7c127fSCraig Rodrigues 	if ((yp->yp_trans_udp = svcudp_create(RPC_ANYSOCK)) == NULL)
1209e7c127fSCraig Rodrigues 		fatal("cannot create udp service");
1219e7c127fSCraig Rodrigues 	if ((yp->yp_trans_tcp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL)
1229e7c127fSCraig Rodrigues 		fatal("cannot create tcp service");
1239e7c127fSCraig Rodrigues 
1249e7c127fSCraig Rodrigues 	if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS,
1259e7c127fSCraig Rodrigues 	    yp_dispatch, IPPROTO_UDP)) {
1269e7c127fSCraig Rodrigues 		fatal("unable to register (YPPROG, YPVERS, udp)");
1279e7c127fSCraig Rodrigues 	}
1289e7c127fSCraig Rodrigues 	if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS,
1299e7c127fSCraig Rodrigues 	    yp_dispatch, IPPROTO_TCP)) {
1309e7c127fSCraig Rodrigues 		fatal("unable to register (YPPROG, YPVERS, tcp)");
1319e7c127fSCraig Rodrigues 	}
1329e7c127fSCraig Rodrigues }
1339e7c127fSCraig Rodrigues 
1349e7c127fSCraig Rodrigues /*
1359e7c127fSCraig Rodrigues  * lots of inspiration from ypserv by Mats O Jansson
1369e7c127fSCraig Rodrigues  */
1379e7c127fSCraig Rodrigues void
1389e7c127fSCraig Rodrigues yp_dispatch(struct svc_req *req, SVCXPRT *trans)
1399e7c127fSCraig Rodrigues {
1409e7c127fSCraig Rodrigues 	xdrproc_t		 xdr_argument;
1419e7c127fSCraig Rodrigues 	xdrproc_t		 xdr_result;
1429e7c127fSCraig Rodrigues 	char			*result;
1439e7c127fSCraig Rodrigues 	char			*(*cb)(char *, struct svc_req *);
1449e7c127fSCraig Rodrigues         union {
1459e7c127fSCraig Rodrigues 		domainname	 ypproc_domain_2_arg;
1469e7c127fSCraig Rodrigues 		domainname	 ypproc_domain_nonack_2_arg;
1479e7c127fSCraig Rodrigues 		ypreq_key	 ypproc_match_2_arg;
1489e7c127fSCraig Rodrigues 		ypreq_nokey	 ypproc_first_2_arg;
1499e7c127fSCraig Rodrigues 		ypreq_key	 ypproc_next_2_arg;
1509e7c127fSCraig Rodrigues 		ypreq_xfr	 ypproc_xfr_2_arg;
1519e7c127fSCraig Rodrigues 		ypreq_nokey	 ypproc_all_2_arg;
1529e7c127fSCraig Rodrigues 		ypreq_nokey	 ypproc_master_2_arg;
1539e7c127fSCraig Rodrigues 		ypreq_nokey	 ypproc_order_2_arg;
1549e7c127fSCraig Rodrigues 		domainname	 ypproc_maplist_2_arg;
1559e7c127fSCraig Rodrigues 	} argument;
1569e7c127fSCraig Rodrigues 
1579e7c127fSCraig Rodrigues 	xdr_argument = (xdrproc_t) xdr_void;
1589e7c127fSCraig Rodrigues 	xdr_result = (xdrproc_t) xdr_void;
1599e7c127fSCraig Rodrigues 	cb = NULL;
1609e7c127fSCraig Rodrigues 	switch (req->rq_proc) {
1619e7c127fSCraig Rodrigues 	case YPPROC_NULL:
1629e7c127fSCraig Rodrigues 		xdr_argument = (xdrproc_t) xdr_void;
1639e7c127fSCraig Rodrigues 		xdr_result = (xdrproc_t) xdr_void;
1649e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
1659e7c127fSCraig Rodrigues 			return;
1669e7c127fSCraig Rodrigues 		result = NULL;
1679e7c127fSCraig Rodrigues 		if (!svc_sendreply(trans, (xdrproc_t) xdr_void,
1689e7c127fSCraig Rodrigues 		    (void *)&result))
1699e7c127fSCraig Rodrigues 			svcerr_systemerr(trans);
1709e7c127fSCraig Rodrigues 		return;
1719e7c127fSCraig Rodrigues 	case YPPROC_DOMAIN:
1729e7c127fSCraig Rodrigues 		xdr_argument = (xdrproc_t) xdr_domainname;
1739e7c127fSCraig Rodrigues 		xdr_result = (xdrproc_t) xdr_bool;
1749e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
1759e7c127fSCraig Rodrigues 			return;
1769e7c127fSCraig Rodrigues 		cb = (void *)ypproc_domain_2_svc;
1779e7c127fSCraig Rodrigues 		break;
1789e7c127fSCraig Rodrigues 	case YPPROC_DOMAIN_NONACK:
1799e7c127fSCraig Rodrigues 		xdr_argument = (xdrproc_t) xdr_domainname;
1809e7c127fSCraig Rodrigues 		xdr_result = (xdrproc_t) xdr_bool;
1819e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
1829e7c127fSCraig Rodrigues 			return;
1839e7c127fSCraig Rodrigues 		cb = (void *)ypproc_domain_nonack_2_svc;
1849e7c127fSCraig Rodrigues 		break;
1859e7c127fSCraig Rodrigues 	case YPPROC_MATCH:
1869e7c127fSCraig Rodrigues 		xdr_argument = (xdrproc_t) xdr_ypreq_key;
1879e7c127fSCraig Rodrigues 		xdr_result = (xdrproc_t) xdr_ypresp_val;
1889e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
1899e7c127fSCraig Rodrigues 			return;
1909e7c127fSCraig Rodrigues 		cb = (void *)ypproc_match_2_svc;
1919e7c127fSCraig Rodrigues 		break;
1929e7c127fSCraig Rodrigues 	case YPPROC_FIRST:
1939e7c127fSCraig Rodrigues 		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
1949e7c127fSCraig Rodrigues 		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
1959e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
1969e7c127fSCraig Rodrigues 			return;
1979e7c127fSCraig Rodrigues 		cb = (void *)ypproc_first_2_svc;
1989e7c127fSCraig Rodrigues 		break;
1999e7c127fSCraig Rodrigues 	case YPPROC_NEXT:
2009e7c127fSCraig Rodrigues 		xdr_argument = (xdrproc_t) xdr_ypreq_key;
2019e7c127fSCraig Rodrigues 		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
2029e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2039e7c127fSCraig Rodrigues 			return;
2049e7c127fSCraig Rodrigues 		cb = (void *)ypproc_next_2_svc;
2059e7c127fSCraig Rodrigues 		break;
2069e7c127fSCraig Rodrigues 	case YPPROC_XFR:
2079e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2089e7c127fSCraig Rodrigues 			return;
2099e7c127fSCraig Rodrigues 		svcerr_noproc(trans);
2109e7c127fSCraig Rodrigues 		return;
2119e7c127fSCraig Rodrigues 	case YPPROC_CLEAR:
2129e7c127fSCraig Rodrigues 		log_debug("ypproc_clear");
2139e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2149e7c127fSCraig Rodrigues 			return;
2159e7c127fSCraig Rodrigues 		svcerr_noproc(trans);
2169e7c127fSCraig Rodrigues 		return;
2179e7c127fSCraig Rodrigues 	case YPPROC_ALL:
2189e7c127fSCraig Rodrigues 		log_debug("ypproc_all");
2199e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2209e7c127fSCraig Rodrigues 			return;
2219e7c127fSCraig Rodrigues 		cb = (void *)ypproc_all_2_svc;
2229e7c127fSCraig Rodrigues 		break;
2239e7c127fSCraig Rodrigues 	case YPPROC_MASTER:
2249e7c127fSCraig Rodrigues 		log_debug("ypproc_master");
2259e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2269e7c127fSCraig Rodrigues 			return;
2279e7c127fSCraig Rodrigues 		cb = (void *)ypproc_master_2_svc;
2289e7c127fSCraig Rodrigues 		break;
2299e7c127fSCraig Rodrigues 	case YPPROC_ORDER:
2309e7c127fSCraig Rodrigues 		log_debug("ypproc_order");
2319e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2329e7c127fSCraig Rodrigues 			return;
2339e7c127fSCraig Rodrigues 		svcerr_noproc(trans);
2349e7c127fSCraig Rodrigues 		return;
2359e7c127fSCraig Rodrigues 	case YPPROC_MAPLIST:
2369e7c127fSCraig Rodrigues 		log_debug("ypproc_maplist");
2379e7c127fSCraig Rodrigues 		if (yp_check(req) == -1)
2389e7c127fSCraig Rodrigues 			return;
2399e7c127fSCraig Rodrigues 		cb = (void *)ypproc_maplist_2_svc;
2409e7c127fSCraig Rodrigues 		break;
2419e7c127fSCraig Rodrigues 	default:
2429e7c127fSCraig Rodrigues 		svcerr_noproc(trans);
2439e7c127fSCraig Rodrigues 		return;
2449e7c127fSCraig Rodrigues 	}
2459e7c127fSCraig Rodrigues 	(void)memset(&argument, 0, sizeof(argument));
2469e7c127fSCraig Rodrigues 
2479e7c127fSCraig Rodrigues 	if (!svc_getargs(trans, xdr_argument, (caddr_t)&argument)) {
2489e7c127fSCraig Rodrigues 		svcerr_decode(trans);
2499e7c127fSCraig Rodrigues 		return;
2509e7c127fSCraig Rodrigues 	}
2519e7c127fSCraig Rodrigues 	result = (*cb)((char *)&argument, req);
2529e7c127fSCraig Rodrigues 	if (result != NULL && !svc_sendreply(trans, xdr_result, result))
2539e7c127fSCraig Rodrigues 		svcerr_systemerr(trans);
2549e7c127fSCraig Rodrigues 	if (!svc_freeargs(trans, xdr_argument, (caddr_t)&argument)) {
2559e7c127fSCraig Rodrigues 		/*
2569e7c127fSCraig Rodrigues 		 * ypserv does it too.
2579e7c127fSCraig Rodrigues 		 */
2589e7c127fSCraig Rodrigues 		fatal("unable to free arguments");
2599e7c127fSCraig Rodrigues 	}
2609e7c127fSCraig Rodrigues }
2619e7c127fSCraig Rodrigues 
2629e7c127fSCraig Rodrigues int
2639e7c127fSCraig Rodrigues yp_check(struct svc_req *req)
2649e7c127fSCraig Rodrigues {
2659e7c127fSCraig Rodrigues 	struct sockaddr_in	*caller;
2669e7c127fSCraig Rodrigues 
2679e7c127fSCraig Rodrigues 	caller = svc_getcaller(req->rq_xprt);
2689e7c127fSCraig Rodrigues 	/*
2699e7c127fSCraig Rodrigues 	 * We might want to know who we allow here.
2709e7c127fSCraig Rodrigues 	 */
2719e7c127fSCraig Rodrigues 	return (0);
2729e7c127fSCraig Rodrigues }
2739e7c127fSCraig Rodrigues 
2749e7c127fSCraig Rodrigues int
2759e7c127fSCraig Rodrigues yp_valid_domain(char *domain, struct ypresp_val *res)
2769e7c127fSCraig Rodrigues {
2779e7c127fSCraig Rodrigues 	if (domain == NULL) {
2789e7c127fSCraig Rodrigues 		log_debug("NULL domain !");
2799e7c127fSCraig Rodrigues 		return (-1);
2809e7c127fSCraig Rodrigues 	}
2819e7c127fSCraig Rodrigues 	if (strcmp(domain, env->sc_domainname) != 0) {
2829e7c127fSCraig Rodrigues 		res->stat = YP_NODOM;
2839e7c127fSCraig Rodrigues 		return (-1);
2849e7c127fSCraig Rodrigues 	}
2859e7c127fSCraig Rodrigues 	return (0);
2869e7c127fSCraig Rodrigues }
2879e7c127fSCraig Rodrigues 
2889e7c127fSCraig Rodrigues bool_t *
2899e7c127fSCraig Rodrigues ypproc_domain_2_svc(domainname *arg, struct svc_req *req)
2909e7c127fSCraig Rodrigues {
2919e7c127fSCraig Rodrigues 	static bool_t	res;
2929e7c127fSCraig Rodrigues 
2939e7c127fSCraig Rodrigues 	res = (bool_t)1;
2949e7c127fSCraig Rodrigues 	if (strcmp(*arg, env->sc_domainname) != 0)
2959e7c127fSCraig Rodrigues 		res = (bool_t)0;
2969e7c127fSCraig Rodrigues 	return (&res);
2979e7c127fSCraig Rodrigues }
2989e7c127fSCraig Rodrigues 
2999e7c127fSCraig Rodrigues bool_t *
3009e7c127fSCraig Rodrigues ypproc_domain_nonack_2_svc(domainname *arg, struct svc_req *req)
3019e7c127fSCraig Rodrigues {
3029e7c127fSCraig Rodrigues 	static bool_t	res;
3039e7c127fSCraig Rodrigues 
3049e7c127fSCraig Rodrigues 	if (strcmp(*arg, env->sc_domainname) != 0)
3059e7c127fSCraig Rodrigues 		return NULL;
3069e7c127fSCraig Rodrigues 	res = (bool_t)1;
3079e7c127fSCraig Rodrigues 	return (&res);
3089e7c127fSCraig Rodrigues }
3099e7c127fSCraig Rodrigues 
3109e7c127fSCraig Rodrigues ypresp_val *
3119e7c127fSCraig Rodrigues ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req)
3129e7c127fSCraig Rodrigues {
3139e7c127fSCraig Rodrigues 	struct userent		 ukey;
3149e7c127fSCraig Rodrigues 	struct userent		*ue;
3159e7c127fSCraig Rodrigues 	struct groupent		 gkey;
3169e7c127fSCraig Rodrigues 	struct groupent		*ge;
3179e7c127fSCraig Rodrigues 	static struct ypresp_val res;
3189e7c127fSCraig Rodrigues 	const char		*estr;
3199e7c127fSCraig Rodrigues 	char			*bp, *cp;
3209e7c127fSCraig Rodrigues 	char			 key[YPMAXRECORD+1];
3219e7c127fSCraig Rodrigues 
3229e7c127fSCraig Rodrigues 	log_debug("matching '%.*s' in map %s", arg->key.keydat_len,
3239e7c127fSCraig Rodrigues 	   arg->key.keydat_val, arg->map);
3249e7c127fSCraig Rodrigues 
3259e7c127fSCraig Rodrigues 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
3269e7c127fSCraig Rodrigues 		return (&res);
3279e7c127fSCraig Rodrigues 
3289e7c127fSCraig Rodrigues 	if (env->sc_user_names == NULL) {
3299e7c127fSCraig Rodrigues 		/*
3309e7c127fSCraig Rodrigues 		 * tree not ready.
3319e7c127fSCraig Rodrigues 		 */
3329e7c127fSCraig Rodrigues 		return (NULL);
3339e7c127fSCraig Rodrigues 	}
3349e7c127fSCraig Rodrigues 
3359e7c127fSCraig Rodrigues 	if (arg->key.keydat_len > YPMAXRECORD) {
3369e7c127fSCraig Rodrigues 		log_debug("argument too long");
3379e7c127fSCraig Rodrigues 		return (NULL);
3389e7c127fSCraig Rodrigues 	}
3399e7c127fSCraig Rodrigues 	bzero(key, sizeof(key));
3409e7c127fSCraig Rodrigues 	(void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len);
3419e7c127fSCraig Rodrigues 
3429e7c127fSCraig Rodrigues 	if (strcmp(arg->map, "passwd.byname") == 0 ||
3439e7c127fSCraig Rodrigues 	    strcmp(arg->map, "master.passwd.byname") == 0) {
3449e7c127fSCraig Rodrigues 		ukey.ue_line = key;
3459e7c127fSCraig Rodrigues 		if ((ue = RB_FIND(user_name_tree, env->sc_user_names,
3469e7c127fSCraig Rodrigues 		    &ukey)) == NULL) {
3479e7c127fSCraig Rodrigues 			res.stat = YP_NOKEY;
3489e7c127fSCraig Rodrigues 			return (&res);
3499e7c127fSCraig Rodrigues 		}
3509e7c127fSCraig Rodrigues 
3519e7c127fSCraig Rodrigues 		yp_make_val(&res, ue->ue_line, 1);
3529e7c127fSCraig Rodrigues 		return (&res);
3539e7c127fSCraig Rodrigues 	} else if (strcmp(arg->map, "passwd.byuid") == 0 ||
3549e7c127fSCraig Rodrigues 		   strcmp(arg->map, "master.passwd.byuid") == 0) {
3559e7c127fSCraig Rodrigues 		ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr);
3569e7c127fSCraig Rodrigues 		if (estr) {
3579e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
3589e7c127fSCraig Rodrigues 			return (&res);
3599e7c127fSCraig Rodrigues 		}
3609e7c127fSCraig Rodrigues 
3619e7c127fSCraig Rodrigues 		if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
3629e7c127fSCraig Rodrigues 		    &ukey)) == NULL) {
3639e7c127fSCraig Rodrigues 			res.stat = YP_NOKEY;
3649e7c127fSCraig Rodrigues 			return (&res);
3659e7c127fSCraig Rodrigues 		}
3669e7c127fSCraig Rodrigues 
3679e7c127fSCraig Rodrigues 		yp_make_val(&res, ue->ue_line, 1);
3689e7c127fSCraig Rodrigues 		return (&res);
3699e7c127fSCraig Rodrigues 	} else if (strcmp(arg->map, "group.bygid") == 0) {
3709e7c127fSCraig Rodrigues 		gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr);
3719e7c127fSCraig Rodrigues 		if (estr) {
3729e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
3739e7c127fSCraig Rodrigues 			return (&res);
3749e7c127fSCraig Rodrigues 		}
3759e7c127fSCraig Rodrigues 		if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids,
3769e7c127fSCraig Rodrigues 		    &gkey)) == NULL) {
3779e7c127fSCraig Rodrigues 			res.stat = YP_NOKEY;
3789e7c127fSCraig Rodrigues 			return (&res);
3799e7c127fSCraig Rodrigues 		}
3809e7c127fSCraig Rodrigues 
3819e7c127fSCraig Rodrigues 		yp_make_val(&res, ge->ge_line, 1);
3829e7c127fSCraig Rodrigues 		return (&res);
3839e7c127fSCraig Rodrigues 	} else if (strcmp(arg->map, "group.byname") == 0) {
3849e7c127fSCraig Rodrigues 		gkey.ge_line = key;
3859e7c127fSCraig Rodrigues 		if ((ge = RB_FIND(group_name_tree, env->sc_group_names,
3869e7c127fSCraig Rodrigues 		    &gkey)) == NULL) {
3879e7c127fSCraig Rodrigues 			res.stat = YP_NOKEY;
3889e7c127fSCraig Rodrigues 			return (&res);
3899e7c127fSCraig Rodrigues 		}
3909e7c127fSCraig Rodrigues 
3919e7c127fSCraig Rodrigues 		yp_make_val(&res, ge->ge_line, 1);
3929e7c127fSCraig Rodrigues 		return (&res);
3939e7c127fSCraig Rodrigues 	} else if (strcmp(arg->map, "netid.byname") == 0) {
3949e7c127fSCraig Rodrigues 		bp = cp = key;
3959e7c127fSCraig Rodrigues 
3969e7c127fSCraig Rodrigues 		if (strncmp(bp, "unix.", strlen("unix.")) != 0) {
3979e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
3989e7c127fSCraig Rodrigues 			return (&res);
3999e7c127fSCraig Rodrigues 		}
4009e7c127fSCraig Rodrigues 
4019e7c127fSCraig Rodrigues 		bp += strlen("unix.");
4029e7c127fSCraig Rodrigues 
4039e7c127fSCraig Rodrigues 		if (*bp == '\0') {
4049e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
4059e7c127fSCraig Rodrigues 			return (&res);
4069e7c127fSCraig Rodrigues 		}
4079e7c127fSCraig Rodrigues 
4089e7c127fSCraig Rodrigues 		if (!(cp = strsep(&bp, "@"))) {
4099e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
4109e7c127fSCraig Rodrigues 			return (&res);
4119e7c127fSCraig Rodrigues 		}
4129e7c127fSCraig Rodrigues 
4139e7c127fSCraig Rodrigues 		if (strcmp(bp, arg->domain) != 0) {
4149e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
4159e7c127fSCraig Rodrigues 			return (&res);
4169e7c127fSCraig Rodrigues 		}
4179e7c127fSCraig Rodrigues 
4189e7c127fSCraig Rodrigues 		ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr);
4199e7c127fSCraig Rodrigues 		if (estr) {
4209e7c127fSCraig Rodrigues 			res.stat = YP_BADARGS;
4219e7c127fSCraig Rodrigues 			return (&res);
4229e7c127fSCraig Rodrigues 		}
4239e7c127fSCraig Rodrigues 
4249e7c127fSCraig Rodrigues 		if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
4259e7c127fSCraig Rodrigues 		    &ukey)) == NULL) {
4269e7c127fSCraig Rodrigues 			res.stat = YP_NOKEY;
4279e7c127fSCraig Rodrigues 			return (&res);
4289e7c127fSCraig Rodrigues 		}
4299e7c127fSCraig Rodrigues 
4309e7c127fSCraig Rodrigues 		yp_make_val(&res, ue->ue_netid_line, 0);
4319e7c127fSCraig Rodrigues 		return (&res);
4329e7c127fSCraig Rodrigues 
4339e7c127fSCraig Rodrigues 	} else {
4349e7c127fSCraig Rodrigues 		log_debug("unknown map %s", arg->map);
4359e7c127fSCraig Rodrigues 		res.stat = YP_NOMAP;
4369e7c127fSCraig Rodrigues 		return (&res);
4379e7c127fSCraig Rodrigues 	}
4389e7c127fSCraig Rodrigues }
4399e7c127fSCraig Rodrigues 
4409e7c127fSCraig Rodrigues ypresp_key_val *
4419e7c127fSCraig Rodrigues ypproc_first_2_svc(ypreq_nokey *arg, struct svc_req *req)
4429e7c127fSCraig Rodrigues {
4439e7c127fSCraig Rodrigues 	static struct ypresp_key_val	res;
4449e7c127fSCraig Rodrigues 
4459e7c127fSCraig Rodrigues 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
4469e7c127fSCraig Rodrigues 		return (&res);
4479e7c127fSCraig Rodrigues 
4489e7c127fSCraig Rodrigues 	if (strcmp(arg->map, "passwd.byname") == 0 ||
4499e7c127fSCraig Rodrigues 	    strcmp(arg->map, "master.passwd.byname") == 0) {
4509e7c127fSCraig Rodrigues 		if (env->sc_user_lines == NULL)
4519e7c127fSCraig Rodrigues 			return (NULL);
4529e7c127fSCraig Rodrigues 
4539e7c127fSCraig Rodrigues 		yp_make_keyval(&res, env->sc_user_lines, env->sc_user_lines);
4549e7c127fSCraig Rodrigues 	} else if (strcmp(arg->map, "group.byname") == 0) {
4559e7c127fSCraig Rodrigues 		if (env->sc_group_lines == NULL)
4569e7c127fSCraig Rodrigues 			return (NULL);
4579e7c127fSCraig Rodrigues 
4589e7c127fSCraig Rodrigues 		yp_make_keyval(&res, env->sc_group_lines, env->sc_group_lines);
4599e7c127fSCraig Rodrigues 	} else {
4609e7c127fSCraig Rodrigues 		log_debug("unknown map %s", arg->map);
4619e7c127fSCraig Rodrigues 		res.stat = YP_NOMAP;
4629e7c127fSCraig Rodrigues 	}
4639e7c127fSCraig Rodrigues 
4649e7c127fSCraig Rodrigues 	return (&res);
4659e7c127fSCraig Rodrigues }
4669e7c127fSCraig Rodrigues 
4679e7c127fSCraig Rodrigues ypresp_key_val *
4689e7c127fSCraig Rodrigues ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
4699e7c127fSCraig Rodrigues {
4709e7c127fSCraig Rodrigues 	struct userent			 ukey;
4719e7c127fSCraig Rodrigues 	struct userent			*ue;
4729e7c127fSCraig Rodrigues 	struct groupent			 gkey;
4739e7c127fSCraig Rodrigues 	struct groupent			*ge;
4749e7c127fSCraig Rodrigues 	char				*line;
4759e7c127fSCraig Rodrigues 	static struct ypresp_key_val	 res;
4769e7c127fSCraig Rodrigues 	char				 key[YPMAXRECORD+1];
4779e7c127fSCraig Rodrigues 
4789e7c127fSCraig Rodrigues 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
4799e7c127fSCraig Rodrigues 		return (&res);
4809e7c127fSCraig Rodrigues 
4819e7c127fSCraig Rodrigues 	if (strcmp(arg->map, "passwd.byname") == 0 ||
4829e7c127fSCraig Rodrigues 	    strcmp(arg->map, "master.passwd.byname") == 0) {
4839e7c127fSCraig Rodrigues 		bzero(key, sizeof(key));
4849e7c127fSCraig Rodrigues 		(void)strncpy(key, arg->key.keydat_val,
4859e7c127fSCraig Rodrigues 		    arg->key.keydat_len);
4869e7c127fSCraig Rodrigues 		ukey.ue_line = key;
4879e7c127fSCraig Rodrigues 		if ((ue = RB_FIND(user_name_tree, env->sc_user_names,
4889e7c127fSCraig Rodrigues 		    &ukey)) == NULL) {
4899e7c127fSCraig Rodrigues 			/*
4909e7c127fSCraig Rodrigues 			 * canacar's trick:
4919e7c127fSCraig Rodrigues 			 * the user might have been deleted in between calls
4929e7c127fSCraig Rodrigues 			 * to next since the tree may be modified by a reload.
4939e7c127fSCraig Rodrigues 			 * next should still return the next user in
4949e7c127fSCraig Rodrigues 			 * lexicographical order, hence insert the search key
4959e7c127fSCraig Rodrigues 			 * and look up the next field, then remove it again.
4969e7c127fSCraig Rodrigues 			 */
4979e7c127fSCraig Rodrigues 			RB_INSERT(user_name_tree, env->sc_user_names, &ukey);
4989e7c127fSCraig Rodrigues 			if ((ue = RB_NEXT(user_name_tree, &env->sc_user_names,
4999e7c127fSCraig Rodrigues 			    &ukey)) == NULL) {
5009e7c127fSCraig Rodrigues 				RB_REMOVE(user_name_tree, env->sc_user_names,
5019e7c127fSCraig Rodrigues 				    &ukey);
5029e7c127fSCraig Rodrigues 				res.stat = YP_NOKEY;
5039e7c127fSCraig Rodrigues 				return (&res);
5049e7c127fSCraig Rodrigues 			}
5059e7c127fSCraig Rodrigues 			RB_REMOVE(user_name_tree, env->sc_user_names, &ukey);
5069e7c127fSCraig Rodrigues 		}
5079e7c127fSCraig Rodrigues 		line = ue->ue_line + (strlen(ue->ue_line) + 1);
5089e7c127fSCraig Rodrigues 		line = line + (strlen(line) + 1);
5099e7c127fSCraig Rodrigues 		yp_make_keyval(&res, line, line);
5109e7c127fSCraig Rodrigues 		return (&res);
5119e7c127fSCraig Rodrigues 
5129e7c127fSCraig Rodrigues 
5139e7c127fSCraig Rodrigues 	} else if (strcmp(arg->map, "group.byname") == 0) {
5149e7c127fSCraig Rodrigues 		bzero(key, sizeof(key));
5159e7c127fSCraig Rodrigues 		(void)strncpy(key, arg->key.keydat_val,
5169e7c127fSCraig Rodrigues 		    arg->key.keydat_len);
5179e7c127fSCraig Rodrigues 
5189e7c127fSCraig Rodrigues 		gkey.ge_line = key;
5199e7c127fSCraig Rodrigues 		if ((ge = RB_FIND(group_name_tree, env->sc_group_names,
5209e7c127fSCraig Rodrigues 		    &gkey)) == NULL) {
5219e7c127fSCraig Rodrigues 			/*
5229e7c127fSCraig Rodrigues 			 * canacar's trick reloaded.
5239e7c127fSCraig Rodrigues 			 */
5249e7c127fSCraig Rodrigues 			RB_INSERT(group_name_tree, env->sc_group_names, &gkey);
5259e7c127fSCraig Rodrigues 			if ((ge = RB_NEXT(group_name_tree, &env->sc_group_names,
5269e7c127fSCraig Rodrigues 			    &gkey)) == NULL) {
5279e7c127fSCraig Rodrigues 				RB_REMOVE(group_name_tree, env->sc_group_names,
5289e7c127fSCraig Rodrigues 				    &gkey);
5299e7c127fSCraig Rodrigues 				res.stat = YP_NOKEY;
5309e7c127fSCraig Rodrigues 				return (&res);
5319e7c127fSCraig Rodrigues 			}
5329e7c127fSCraig Rodrigues 			RB_REMOVE(group_name_tree, env->sc_group_names, &gkey);
5339e7c127fSCraig Rodrigues 		}
5349e7c127fSCraig Rodrigues 
5359e7c127fSCraig Rodrigues 		line = ge->ge_line + (strlen(ge->ge_line) + 1);
5369e7c127fSCraig Rodrigues 		line = line + (strlen(line) + 1);
5379e7c127fSCraig Rodrigues 		yp_make_keyval(&res, line, line);
5389e7c127fSCraig Rodrigues 		return (&res);
5399e7c127fSCraig Rodrigues 	} else {
5409e7c127fSCraig Rodrigues 		log_debug("unknown map %s", arg->map);
5419e7c127fSCraig Rodrigues 		res.stat = YP_NOMAP;
5429e7c127fSCraig Rodrigues 		return (&res);
5439e7c127fSCraig Rodrigues 	}
5449e7c127fSCraig Rodrigues }
5459e7c127fSCraig Rodrigues 
5469e7c127fSCraig Rodrigues ypresp_all *
5479e7c127fSCraig Rodrigues ypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req)
5489e7c127fSCraig Rodrigues {
5499e7c127fSCraig Rodrigues 	static struct ypresp_all	res;
5509e7c127fSCraig Rodrigues 
5519e7c127fSCraig Rodrigues 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
5529e7c127fSCraig Rodrigues 		return (&res);
5539e7c127fSCraig Rodrigues 
5549e7c127fSCraig Rodrigues 	svcerr_auth(req->rq_xprt, AUTH_FAILED);
5559e7c127fSCraig Rodrigues 	return (NULL);
5569e7c127fSCraig Rodrigues }
5579e7c127fSCraig Rodrigues 
5589e7c127fSCraig Rodrigues ypresp_master *
5599e7c127fSCraig Rodrigues ypproc_master_2_svc(ypreq_nokey *arg, struct svc_req *req)
5609e7c127fSCraig Rodrigues {
5619e7c127fSCraig Rodrigues 	static struct ypresp_master	 res;
5629e7c127fSCraig Rodrigues 
5639e7c127fSCraig Rodrigues 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
5649e7c127fSCraig Rodrigues 		return (&res);
5659e7c127fSCraig Rodrigues 
5669e7c127fSCraig Rodrigues 	res.stat = YP_YPERR;
5679e7c127fSCraig Rodrigues 	return (&res);
5689e7c127fSCraig Rodrigues }
5699e7c127fSCraig Rodrigues 
5709e7c127fSCraig Rodrigues ypresp_maplist *
5719e7c127fSCraig Rodrigues ypproc_maplist_2_svc(domainname *arg, struct svc_req *req)
5729e7c127fSCraig Rodrigues {
5739e7c127fSCraig Rodrigues 	size_t			 i;
5749e7c127fSCraig Rodrigues 	static struct {
5759e7c127fSCraig Rodrigues 		char		*name;
5769e7c127fSCraig Rodrigues 		int		 cond;
5779e7c127fSCraig Rodrigues 	}			 mapnames[] = {
5789e7c127fSCraig Rodrigues 		{ "passwd.byname",		YPMAP_PASSWD_BYNAME },
5799e7c127fSCraig Rodrigues 		{ "passwd.byuid",		YPMAP_PASSWD_BYUID },
5809e7c127fSCraig Rodrigues 		{ "master.passwd.byname",	YPMAP_MASTER_PASSWD_BYNAME },
5819e7c127fSCraig Rodrigues 		{ "master.passwd.byuid",	YPMAP_MASTER_PASSWD_BYUID },
5829e7c127fSCraig Rodrigues 		{ "group.byname",		YPMAP_GROUP_BYNAME },
5839e7c127fSCraig Rodrigues 		{ "group.bygid",		YPMAP_GROUP_BYGID },
5849e7c127fSCraig Rodrigues 		{ "netid.byname",		YPMAP_NETID_BYNAME },
5859e7c127fSCraig Rodrigues 	};
5869e7c127fSCraig Rodrigues 	static ypresp_maplist	 res;
5879e7c127fSCraig Rodrigues 	static struct ypmaplist	 maps[sizeof(mapnames) / sizeof(mapnames[0])];
5889e7c127fSCraig Rodrigues 
5899e7c127fSCraig Rodrigues 	if (yp_valid_domain(*arg, (struct ypresp_val *)&res) == -1)
5909e7c127fSCraig Rodrigues 		return (&res);
5919e7c127fSCraig Rodrigues 
5929e7c127fSCraig Rodrigues 	res.stat = YP_TRUE;
5939e7c127fSCraig Rodrigues 	res.maps = NULL;
5949e7c127fSCraig Rodrigues 	for (i = 0; i < sizeof(mapnames) / sizeof(mapnames[0]); i++) {
5959e7c127fSCraig Rodrigues 		if (!(env->sc_flags & mapnames[i].cond))
5969e7c127fSCraig Rodrigues 			continue;
5979e7c127fSCraig Rodrigues 		maps[i].map = mapnames[i].name;
5989e7c127fSCraig Rodrigues 		maps[i].next = res.maps;
5999e7c127fSCraig Rodrigues 		res.maps = &maps[i];
6009e7c127fSCraig Rodrigues 	}
6019e7c127fSCraig Rodrigues 
6029e7c127fSCraig Rodrigues 	return (&res);
6039e7c127fSCraig Rodrigues }
6049e7c127fSCraig Rodrigues 
6059e7c127fSCraig Rodrigues void
6069e7c127fSCraig Rodrigues yp_make_val(struct ypresp_val *res, char *line, int replacecolon)
6079e7c127fSCraig Rodrigues {
6089e7c127fSCraig Rodrigues 	static char		 buf[LINE_WIDTH];
6099e7c127fSCraig Rodrigues 
6109e7c127fSCraig Rodrigues 	bzero(buf, sizeof(buf));
6119e7c127fSCraig Rodrigues 
6129e7c127fSCraig Rodrigues 	if (replacecolon)
6139e7c127fSCraig Rodrigues 		line[strlen(line)] = ':';
6149e7c127fSCraig Rodrigues 	(void)strlcpy(buf, line, sizeof(buf));
6159e7c127fSCraig Rodrigues 	if (replacecolon)
6169e7c127fSCraig Rodrigues 		line[strcspn(line, ":")] = '\0';
6179e7c127fSCraig Rodrigues 	log_debug("sending out %s", buf);
6189e7c127fSCraig Rodrigues 
6199e7c127fSCraig Rodrigues 	res->stat = YP_TRUE;
6209e7c127fSCraig Rodrigues 	res->val.valdat_len = strlen(buf);
6219e7c127fSCraig Rodrigues 	res->val.valdat_val = buf;
6229e7c127fSCraig Rodrigues }
6239e7c127fSCraig Rodrigues 
6249e7c127fSCraig Rodrigues void
6259e7c127fSCraig Rodrigues yp_make_keyval(struct ypresp_key_val *res, char *key, char *line)
6269e7c127fSCraig Rodrigues {
6279e7c127fSCraig Rodrigues 	static char	keybuf[YPMAXRECORD+1];
6289e7c127fSCraig Rodrigues 	static char	buf[LINE_WIDTH];
6299e7c127fSCraig Rodrigues 
6309e7c127fSCraig Rodrigues 	bzero(keybuf, sizeof(keybuf));
6319e7c127fSCraig Rodrigues 	bzero(buf, sizeof(buf));
6329e7c127fSCraig Rodrigues 
6339e7c127fSCraig Rodrigues 	(void)strlcpy(keybuf, key, sizeof(keybuf));
6349e7c127fSCraig Rodrigues 	res->key.keydat_len = strlen(keybuf);
6359e7c127fSCraig Rodrigues 	res->key.keydat_val = keybuf;
6369e7c127fSCraig Rodrigues 
6379e7c127fSCraig Rodrigues 	if (*line == '\0') {
6389e7c127fSCraig Rodrigues 		res->stat = YP_NOMORE;
6399e7c127fSCraig Rodrigues 		return;
6409e7c127fSCraig Rodrigues 	}
6419e7c127fSCraig Rodrigues 	res->stat = YP_TRUE;
6429e7c127fSCraig Rodrigues 	line[strlen(line)] = ':';
6439e7c127fSCraig Rodrigues 	(void)strlcpy(buf, line, sizeof(buf));
6449e7c127fSCraig Rodrigues 	line[strcspn(line, ":")] = '\0';
6459e7c127fSCraig Rodrigues 	log_debug("sending out %s => %s", keybuf, buf);
6469e7c127fSCraig Rodrigues 
6479e7c127fSCraig Rodrigues 	res->val.valdat_len = strlen(buf);
6489e7c127fSCraig Rodrigues 	res->val.valdat_val = buf;
6499e7c127fSCraig Rodrigues }
650