xref: /openbsd/usr.sbin/ypldap/yp.c (revision 73492e0c)
1 /*	$OpenBSD: yp.c,v 1.22 2023/07/18 13:06:33 claudio Exp $ */
2 /*
3  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/socket.h>
21 #include <sys/select.h>
22 #include <sys/tree.h>
23 #include <sys/stat.h>
24 
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 
28 #include <errno.h>
29 #include <event.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <limits.h>
37 
38 #include <rpc/rpc.h>
39 #include <rpc/xdr.h>
40 #include <rpc/pmap_clnt.h>
41 #include <rpc/pmap_prot.h>
42 #include <rpc/pmap_rmt.h>
43 #include <rpcsvc/yp.h>
44 #include <rpcsvc/ypclnt.h>
45 
46 #include "ypldap.h"
47 #include "log.h"
48 
49 #define BINDINGDIR		"/var/yp/binding"
50 
51 void	yp_dispatch(struct svc_req *, SVCXPRT *);
52 void	yp_disable_events(void);
53 void	yp_fd_event(int, short, void *);
54 int	yp_check(struct svc_req *);
55 int	yp_valid_domain(char *, struct ypresp_val *);
56 void	yp_make_val(struct ypresp_val *, char *, int);
57 void	yp_make_keyval(struct ypresp_key_val *, char *, char *);
58 int	yp_write_binding(int, int);
59 
60 static struct env	*env;
61 
62 struct yp_event {
63 	TAILQ_ENTRY(yp_event)	 ye_entry;
64 	struct event		 ye_event;
65 };
66 
67 struct yp_data {
68 	SVCXPRT			*yp_trans_udp;
69 	SVCXPRT			*yp_trans_tcp;
70 	TAILQ_HEAD(, yp_event)	 yd_events;
71 };
72 
73 void
yp_disable_events(void)74 yp_disable_events(void)
75 {
76 	struct yp_event	*ye;
77 
78 	while ((ye = TAILQ_FIRST(&env->sc_yp->yd_events)) != NULL) {
79 		TAILQ_REMOVE(&env->sc_yp->yd_events, ye, ye_entry);
80 		event_del(&ye->ye_event);
81 		free(ye);
82 	}
83 }
84 
85 void
yp_enable_events(void)86 yp_enable_events(void)
87 {
88 	int		 i;
89 	extern fd_set	*__svc_fdset;
90 	extern int	 __svc_fdsetsize;
91 	struct yp_event	*ye;
92 
93 	for (i = 0; i < __svc_fdsetsize; i++) {
94 		if (FD_ISSET(i, __svc_fdset)) {
95 			if ((ye = calloc(1, sizeof(*ye))) == NULL)
96 				fatal(NULL);
97 			event_set(&ye->ye_event, i, EV_READ, yp_fd_event, NULL);
98 			event_add(&ye->ye_event, NULL);
99 			TAILQ_INSERT_TAIL(&env->sc_yp->yd_events, ye, ye_entry);
100 		}
101 	}
102 }
103 
104 void
yp_fd_event(int fd,short event,void * p)105 yp_fd_event(int fd, short event, void *p)
106 {
107 	svc_getreq_common(fd);
108 	yp_disable_events();
109 	yp_enable_events();
110 }
111 
112 void
yp_init(struct env * x_env)113 yp_init(struct env *x_env)
114 {
115 	struct sockaddr_in	 addr;
116 	struct yp_data		*yp;
117 	int			 s, udpport, tcpport;
118 
119 	if ((yp = calloc(1, sizeof(*yp))) == NULL)
120 		fatal(NULL);
121 	TAILQ_INIT(&yp->yd_events);
122 
123 	env = x_env;
124 	env->sc_yp = yp;
125 
126 	switch (env->sc_bind_mode) {
127 	case BIND_MODE_LOCAL:
128 		addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
129 		addr.sin_len = sizeof(struct sockaddr_in);
130 		addr.sin_family = AF_INET;
131 
132 		s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
133 		if (s == -1)
134 			fatal("cannot create udp socket");
135 		addr.sin_port = 0;
136 		if (bindresvport(s, &addr))
137 			fatal("cannot bind udp socket");
138 		if ((yp->yp_trans_udp = svcudp_create(s)) == NULL)
139 			fatal("cannot create udp service");
140 		udpport = ntohs(addr.sin_port);
141 
142 		s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
143 		if (s == -1)
144 			fatal("cannot create tcp socket");
145 		addr.sin_port = 0;
146 		if (bindresvport(s, &addr))
147 			fatal("cannot bind tcp socket");
148 		if ((yp->yp_trans_tcp = svctcp_create(s, 0, 0)) == NULL)
149 			fatal("cannot create tcp service");
150 		tcpport = ntohs(addr.sin_port);
151 
152 		/* protocol 0 means don't register with portmap */
153 		if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS,
154 		    yp_dispatch, 0)) {
155 			fatal("unable to register (YPPROG, YPVERS, udp)");
156 		}
157 		if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS,
158 		    yp_dispatch, 0)) {
159 			fatal("unable to register (YPPROG, YPVERS, tcp)");
160 		}
161 
162 		if (yp_write_binding(udpport, tcpport))
163 			fatal("cannot write yp binding file");
164 
165 		break;
166 
167 	case BIND_MODE_PORTMAP:
168 		(void)pmap_unset(YPPROG, YPVERS);
169 
170 		if ((yp->yp_trans_udp = svcudp_create(RPC_ANYSOCK)) == NULL)
171 			fatal("cannot create udp service");
172 		if ((yp->yp_trans_tcp = svctcp_create(RPC_ANYSOCK, 0, 0)) ==
173 		    NULL)
174 			fatal("cannot create tcp service");
175 
176 		if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS,
177 		    yp_dispatch, IPPROTO_UDP)) {
178 			fatal("unable to register (YPPROG, YPVERS, udp)");
179 		}
180 		if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS,
181 		    yp_dispatch, IPPROTO_TCP)) {
182 			fatal("unable to register (YPPROG, YPVERS, tcp)");
183 		}
184 		break;
185 	}
186 }
187 
188 int
yp_write_binding(int udpport,int tcpport)189 yp_write_binding(int udpport, int tcpport)
190 {
191 	char path[PATH_MAX];
192 	struct ypbind_resp ybr;
193 	struct iovec iov[3];
194 	struct in_addr bindaddr;
195 	u_short ypbind, ypserv_tcp, ypserv_udp;
196 	ssize_t total;
197 	int fd;
198 
199 	snprintf(path, sizeof path, "%s/%s.%ld", BINDINGDIR, env->sc_domainname,
200 	    YPVERS);
201 	fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644);
202 	if (fd == -1) {
203 		(void)mkdir(BINDINGDIR, 0755);
204 		fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC,
205 		    0644);
206 		if (fd == -1)
207 			return -1;
208 	}
209 
210 	if (fchmod(fd, 0644) == -1)
211 		return -1;
212 
213 	iov[0].iov_base = (caddr_t)&ypbind;
214 	iov[0].iov_len = sizeof ypbind;
215 	iov[1].iov_base = (caddr_t)&ybr;
216 	iov[1].iov_len = sizeof ybr;
217 	iov[2].iov_base = (caddr_t)&ypserv_tcp;
218 	iov[2].iov_len = sizeof ypserv_tcp;
219 
220 	bindaddr.s_addr = htonl(INADDR_LOOPBACK);
221 	ypserv_tcp = htons(tcpport);
222 	ypserv_udp = htons(udpport);
223 	ypbind = 0;
224 	memset(&ybr, 0, sizeof ybr);
225 	ybr.ypbind_status = YPBIND_SUCC_VAL;
226 	memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
227 	    &bindaddr,
228 	    sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr));
229 	memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
230 	    &ypserv_udp,
231 	    sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port));
232 
233 	total = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
234 	if (writev(fd, iov, sizeof(iov)/sizeof(iov[0])) !=
235 	    total) {
236 		close(fd);
237 		unlink(path);
238 		return -1;
239 	}
240 
241 	return 0;
242 }
243 
244 /*
245  * lots of inspiration from ypserv by Mats O Jansson
246  */
247 void
yp_dispatch(struct svc_req * req,SVCXPRT * trans)248 yp_dispatch(struct svc_req *req, SVCXPRT *trans)
249 {
250 	xdrproc_t		 xdr_argument;
251 	xdrproc_t		 xdr_result;
252 	char			*result;
253 	char			*(*cb)(char *, struct svc_req *);
254         union {
255 		domainname	 ypproc_domain_2_arg;
256 		domainname	 ypproc_domain_nonack_2_arg;
257 		ypreq_key	 ypproc_match_2_arg;
258 		ypreq_nokey	 ypproc_first_2_arg;
259 		ypreq_key	 ypproc_next_2_arg;
260 		ypreq_xfr	 ypproc_xfr_2_arg;
261 		ypreq_nokey	 ypproc_all_2_arg;
262 		ypreq_nokey	 ypproc_master_2_arg;
263 		ypreq_nokey	 ypproc_order_2_arg;
264 		domainname	 ypproc_maplist_2_arg;
265 	} argument;
266 
267 	xdr_argument = (xdrproc_t) xdr_void;
268 	xdr_result = (xdrproc_t) xdr_void;
269 	cb = NULL;
270 	switch (req->rq_proc) {
271 	case YPPROC_NULL:
272 		xdr_argument = (xdrproc_t) xdr_void;
273 		xdr_result = (xdrproc_t) xdr_void;
274 		if (yp_check(req) == -1)
275 			return;
276 		result = NULL;
277 		if (!svc_sendreply(trans, (xdrproc_t) xdr_void,
278 		    (void *)&result))
279 			svcerr_systemerr(trans);
280 		return;
281 	case YPPROC_DOMAIN:
282 		xdr_argument = (xdrproc_t) xdr_domainname;
283 		xdr_result = (xdrproc_t) xdr_bool;
284 		if (yp_check(req) == -1)
285 			return;
286 		cb = (void *)ypproc_domain_2_svc;
287 		break;
288 	case YPPROC_DOMAIN_NONACK:
289 		xdr_argument = (xdrproc_t) xdr_domainname;
290 		xdr_result = (xdrproc_t) xdr_bool;
291 		if (yp_check(req) == -1)
292 			return;
293 		cb = (void *)ypproc_domain_nonack_2_svc;
294 		break;
295 	case YPPROC_MATCH:
296 		xdr_argument = (xdrproc_t) xdr_ypreq_key;
297 		xdr_result = (xdrproc_t) xdr_ypresp_val;
298 		if (yp_check(req) == -1)
299 			return;
300 		cb = (void *)ypproc_match_2_svc;
301 		break;
302 	case YPPROC_FIRST:
303 		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
304 		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
305 		if (yp_check(req) == -1)
306 			return;
307 		cb = (void *)ypproc_first_2_svc;
308 		break;
309 	case YPPROC_NEXT:
310 		xdr_argument = (xdrproc_t) xdr_ypreq_key;
311 		xdr_result = (xdrproc_t) xdr_ypresp_key_val;
312 		if (yp_check(req) == -1)
313 			return;
314 		cb = (void *)ypproc_next_2_svc;
315 		break;
316 	case YPPROC_XFR:
317 		if (yp_check(req) == -1)
318 			return;
319 		svcerr_noproc(trans);
320 		return;
321 	case YPPROC_CLEAR:
322 		log_debug("ypproc_clear");
323 		if (yp_check(req) == -1)
324 			return;
325 		svcerr_noproc(trans);
326 		return;
327 	case YPPROC_ALL:
328 		log_debug("ypproc_all");
329 		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
330 		xdr_result = (xdrproc_t) xdr_ypresp_all;
331 		if (yp_check(req) == -1)
332 			return;
333 		cb = (void *)ypproc_all_2_svc;
334 		break;
335 	case YPPROC_MASTER:
336 		xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
337 		xdr_result = (xdrproc_t) xdr_ypresp_master;
338 		if (yp_check(req) == -1)
339 			return;
340 		cb = (void *)ypproc_master_2_svc;
341 		break;
342 	case YPPROC_ORDER:
343 		log_debug("ypproc_order");
344 		if (yp_check(req) == -1)
345 			return;
346 		svcerr_noproc(trans);
347 		return;
348 	case YPPROC_MAPLIST:
349 		xdr_argument = (xdrproc_t) xdr_domainname;
350 		xdr_result = (xdrproc_t) xdr_ypresp_maplist;
351 		if (yp_check(req) == -1)
352 			return;
353 		cb = (void *)ypproc_maplist_2_svc;
354 		break;
355 	default:
356 		svcerr_noproc(trans);
357 		return;
358 	}
359 	(void)memset(&argument, 0, sizeof(argument));
360 
361 	if (!svc_getargs(trans, xdr_argument, (caddr_t)&argument)) {
362 		svcerr_decode(trans);
363 		return;
364 	}
365 	result = (*cb)((char *)&argument, req);
366 	if (result != NULL && !svc_sendreply(trans, xdr_result, result))
367 		svcerr_systemerr(trans);
368 	if (!svc_freeargs(trans, xdr_argument, (caddr_t)&argument)) {
369 		/*
370 		 * ypserv does it too.
371 		 */
372 		fatal("unable to free arguments");
373 	}
374 }
375 
376 int
yp_check(struct svc_req * req)377 yp_check(struct svc_req *req)
378 {
379 #ifdef notyet
380 	struct sockaddr_in	*caller;
381 
382 	caller = svc_getcaller(req->rq_xprt);
383 	/*
384 	 * We might want to know who we allow here.
385 	 */
386 #endif
387 	return (0);
388 }
389 
390 int
yp_valid_domain(char * domain,struct ypresp_val * res)391 yp_valid_domain(char *domain, struct ypresp_val *res)
392 {
393 	if (domain == NULL) {
394 		log_debug("NULL domain !");
395 		return (-1);
396 	}
397 	if (strcmp(domain, env->sc_domainname) != 0) {
398 		res->stat = YP_NODOM;
399 		return (-1);
400 	}
401 	return (0);
402 }
403 
404 bool_t *
ypproc_domain_2_svc(domainname * arg,struct svc_req * req)405 ypproc_domain_2_svc(domainname *arg, struct svc_req *req)
406 {
407 	static bool_t	res;
408 
409 	res = (bool_t)1;
410 	if (strcmp(*arg, env->sc_domainname) != 0)
411 		res = (bool_t)0;
412 	return (&res);
413 }
414 
415 bool_t *
ypproc_domain_nonack_2_svc(domainname * arg,struct svc_req * req)416 ypproc_domain_nonack_2_svc(domainname *arg, struct svc_req *req)
417 {
418 	static bool_t	res;
419 
420 	if (strcmp(*arg, env->sc_domainname) != 0)
421 		return NULL;
422 	res = (bool_t)1;
423 	return (&res);
424 }
425 
426 ypresp_val *
ypproc_match_2_svc(ypreq_key * arg,struct svc_req * req)427 ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req)
428 {
429 	struct userent		 ukey;
430 	struct userent		*ue;
431 	struct groupent		 gkey;
432 	struct groupent		*ge;
433 	static struct ypresp_val res;
434 	const char		*estr;
435 	char			*bp, *cp;
436 	char			 key[YPMAXRECORD+1];
437 
438 	log_debug("matching '%.*s' in map %s", arg->key.keydat_len,
439 	   arg->key.keydat_val, arg->map);
440 
441 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
442 		return (&res);
443 
444 	if (env->sc_user_names == NULL) {
445 		/*
446 		 * tree not ready.
447 		 */
448 		return (NULL);
449 	}
450 
451 	if (arg->key.keydat_len > YPMAXRECORD) {
452 		log_debug("argument too long");
453 		return (NULL);
454 	}
455 	memset(key, 0, sizeof(key));
456 	(void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len);
457 
458 	if (strcmp(arg->map, "passwd.byname") == 0 ||
459 	    strcmp(arg->map, "master.passwd.byname") == 0) {
460 		ukey.ue_line = key;
461 		if ((ue = RB_FIND(user_name_tree, env->sc_user_names,
462 		    &ukey)) == NULL) {
463 			res.stat = YP_NOKEY;
464 			return (&res);
465 		}
466 
467 		yp_make_val(&res, ue->ue_line, 1);
468 		return (&res);
469 	} else if (strcmp(arg->map, "passwd.byuid") == 0 ||
470 		   strcmp(arg->map, "master.passwd.byuid") == 0) {
471 		ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr);
472 		if (estr) {
473 			res.stat = YP_BADARGS;
474 			return (&res);
475 		}
476 
477 		if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
478 		    &ukey)) == NULL) {
479 			res.stat = YP_NOKEY;
480 			return (&res);
481 		}
482 
483 		yp_make_val(&res, ue->ue_line, 1);
484 		return (&res);
485 	} else if (strcmp(arg->map, "group.bygid") == 0) {
486 		gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr);
487 		if (estr) {
488 			res.stat = YP_BADARGS;
489 			return (&res);
490 		}
491 		if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids,
492 		    &gkey)) == NULL) {
493 			res.stat = YP_NOKEY;
494 			return (&res);
495 		}
496 
497 		yp_make_val(&res, ge->ge_line, 1);
498 		return (&res);
499 	} else if (strcmp(arg->map, "group.byname") == 0) {
500 		gkey.ge_line = key;
501 		if ((ge = RB_FIND(group_name_tree, env->sc_group_names,
502 		    &gkey)) == NULL) {
503 			res.stat = YP_NOKEY;
504 			return (&res);
505 		}
506 
507 		yp_make_val(&res, ge->ge_line, 1);
508 		return (&res);
509 	} else if (strcmp(arg->map, "netid.byname") == 0) {
510 		bp = cp = key;
511 
512 		if (strncmp(bp, "unix.", strlen("unix.")) != 0) {
513 			res.stat = YP_BADARGS;
514 			return (&res);
515 		}
516 
517 		bp += strlen("unix.");
518 
519 		if (*bp == '\0') {
520 			res.stat = YP_BADARGS;
521 			return (&res);
522 		}
523 
524 		if (!(cp = strsep(&bp, "@"))) {
525 			res.stat = YP_BADARGS;
526 			return (&res);
527 		}
528 
529 		if (strcmp(bp, arg->domain) != 0) {
530 			res.stat = YP_BADARGS;
531 			return (&res);
532 		}
533 
534 		ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr);
535 		if (estr) {
536 			res.stat = YP_BADARGS;
537 			return (&res);
538 		}
539 
540 		if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
541 		    &ukey)) == NULL) {
542 			res.stat = YP_NOKEY;
543 			return (&res);
544 		}
545 
546 		yp_make_val(&res, ue->ue_netid_line, 0);
547 		return (&res);
548 
549 	} else {
550 		log_debug("unknown map %s", arg->map);
551 		res.stat = YP_NOMAP;
552 		return (&res);
553 	}
554 }
555 
556 ypresp_key_val *
ypproc_first_2_svc(ypreq_nokey * arg,struct svc_req * req)557 ypproc_first_2_svc(ypreq_nokey *arg, struct svc_req *req)
558 {
559 	static struct ypresp_key_val	res;
560 
561 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
562 		return (&res);
563 
564 	if (strcmp(arg->map, "passwd.byname") == 0 ||
565 	    strcmp(arg->map, "master.passwd.byname") == 0) {
566 		if (env->sc_user_lines == NULL)
567 			return (NULL);
568 
569 		yp_make_keyval(&res, env->sc_user_lines, env->sc_user_lines);
570 	} else if (strcmp(arg->map, "group.byname") == 0) {
571 		if (env->sc_group_lines == NULL)
572 			return (NULL);
573 
574 		yp_make_keyval(&res, env->sc_group_lines, env->sc_group_lines);
575 	} else {
576 		log_debug("unknown map %s", arg->map);
577 		res.stat = YP_NOMAP;
578 	}
579 
580 	return (&res);
581 }
582 
583 ypresp_key_val *
ypproc_next_2_svc(ypreq_key * arg,struct svc_req * req)584 ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
585 {
586 	struct userent			 ukey;
587 	struct userent			*ue;
588 	struct groupent			 gkey;
589 	struct groupent			*ge;
590 	char				*line;
591 	static struct ypresp_key_val	 res;
592 	char				 key[YPMAXRECORD+1];
593 
594 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
595 		return (&res);
596 
597 	if (strcmp(arg->map, "passwd.byname") == 0 ||
598 	    strcmp(arg->map, "master.passwd.byname") == 0) {
599 		memset(key, 0, sizeof(key));
600 		(void)strncpy(key, arg->key.keydat_val,
601 		    arg->key.keydat_len);
602 		ukey.ue_line = key;
603 		if ((ue = RB_NFIND(user_name_tree, env->sc_user_names,
604 		    &ukey)) == NULL) {
605 			res.stat = YP_NOKEY;
606 			return (&res);
607 		}
608 		line = ue->ue_line + (strlen(ue->ue_line) + 1);
609 		line = line + (strlen(line) + 1);
610 		yp_make_keyval(&res, line, line);
611 		return (&res);
612 
613 
614 	} else if (strcmp(arg->map, "group.byname") == 0) {
615 		memset(key, 0, sizeof(key));
616 		(void)strncpy(key, arg->key.keydat_val,
617 		    arg->key.keydat_len);
618 
619 		gkey.ge_line = key;
620 		if ((ge = RB_NFIND(group_name_tree, env->sc_group_names,
621 		    &gkey)) == NULL) {
622 			res.stat = YP_NOKEY;
623 			return (&res);
624 		}
625 
626 		line = ge->ge_line + (strlen(ge->ge_line) + 1);
627 		line = line + (strlen(line) + 1);
628 		yp_make_keyval(&res, line, line);
629 		return (&res);
630 	} else {
631 		log_debug("unknown map %s", arg->map);
632 		res.stat = YP_NOMAP;
633 		return (&res);
634 	}
635 }
636 
637 ypresp_all *
ypproc_all_2_svc(ypreq_nokey * arg,struct svc_req * req)638 ypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req)
639 {
640 	static struct ypresp_all	res;
641 
642 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
643 		return (&res);
644 
645 	svcerr_auth(req->rq_xprt, AUTH_FAILED);
646 	return (NULL);
647 }
648 
649 ypresp_master *
ypproc_master_2_svc(ypreq_nokey * arg,struct svc_req * req)650 ypproc_master_2_svc(ypreq_nokey *arg, struct svc_req *req)
651 {
652 	static struct ypresp_master	 res;
653 	static char master[YPMAXPEER + 1];
654 
655 	memset(&res, 0, sizeof(res));
656 	if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
657 		return (&res);
658 	if (gethostname(master, sizeof(master)) == 0) {
659 		res.peer = (peername)master;
660 		res.stat = YP_TRUE;
661 	} else
662 		res.stat = YP_NOKEY;
663 	return (&res);
664 }
665 
666 ypresp_maplist *
ypproc_maplist_2_svc(domainname * arg,struct svc_req * req)667 ypproc_maplist_2_svc(domainname *arg, struct svc_req *req)
668 {
669 	size_t			 i;
670 	static struct {
671 		char		*name;
672 		int		 cond;
673 	}			 mapnames[] = {
674 		{ "passwd.byname",		YPMAP_PASSWD_BYNAME },
675 		{ "passwd.byuid",		YPMAP_PASSWD_BYUID },
676 		{ "master.passwd.byname",	YPMAP_MASTER_PASSWD_BYNAME },
677 		{ "master.passwd.byuid",	YPMAP_MASTER_PASSWD_BYUID },
678 		{ "group.byname",		YPMAP_GROUP_BYNAME },
679 		{ "group.bygid",		YPMAP_GROUP_BYGID },
680 		{ "netid.byname",		YPMAP_NETID_BYNAME },
681 	};
682 	static ypresp_maplist	 res;
683 	static struct ypmaplist	 maps[sizeof(mapnames) / sizeof(mapnames[0])];
684 
685 	if (yp_valid_domain(*arg, (struct ypresp_val *)&res) == -1)
686 		return (&res);
687 
688 	res.stat = YP_TRUE;
689 	res.maps = NULL;
690 	for (i = 0; i < sizeof(mapnames) / sizeof(mapnames[0]); i++) {
691 		if (!(env->sc_flags & mapnames[i].cond))
692 			continue;
693 		maps[i].map = mapnames[i].name;
694 		maps[i].next = res.maps;
695 		res.maps = &maps[i];
696 	}
697 
698 	return (&res);
699 }
700 
701 void
yp_make_val(struct ypresp_val * res,char * line,int replacecolon)702 yp_make_val(struct ypresp_val *res, char *line, int replacecolon)
703 {
704 	static char		 buf[LINE_WIDTH];
705 
706 	memset(buf, 0, sizeof(buf));
707 
708 	if (replacecolon)
709 		line[strlen(line)] = ':';
710 	(void)strlcpy(buf, line, sizeof(buf));
711 	if (replacecolon)
712 		line[strcspn(line, ":")] = '\0';
713 	log_debug("sending out %s", buf);
714 
715 	res->stat = YP_TRUE;
716 	res->val.valdat_len = strlen(buf);
717 	res->val.valdat_val = buf;
718 }
719 
720 void
yp_make_keyval(struct ypresp_key_val * res,char * key,char * line)721 yp_make_keyval(struct ypresp_key_val *res, char *key, char *line)
722 {
723 	static char	keybuf[YPMAXRECORD+1];
724 	static char	buf[LINE_WIDTH];
725 
726 	memset(keybuf, 0, sizeof(keybuf));
727 	memset(buf, 0, sizeof(buf));
728 
729 	(void)strlcpy(keybuf, key, sizeof(keybuf));
730 	res->key.keydat_len = strlen(keybuf);
731 	res->key.keydat_val = keybuf;
732 
733 	if (*line == '\0') {
734 		res->stat = YP_NOMORE;
735 		return;
736 	}
737 	res->stat = YP_TRUE;
738 	line[strlen(line)] = ':';
739 	(void)strlcpy(buf, line, sizeof(buf));
740 	line[strcspn(line, ":")] = '\0';
741 	log_debug("sending out %s => %s", keybuf, buf);
742 
743 	res->val.valdat_len = strlen(buf);
744 	res->val.valdat_val = buf;
745 }
746