1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
7 * Reserved.  This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License').  You may not use this file
10 * except in compliance with the License.  Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*	$OpenBSD: ypserv_proc.c,v 1.14 1997/09/12 01:44:57 deraadt Exp $ */
25
26/*
27 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 *    notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 *    notice, this list of conditions and the following disclaimer in the
37 *    documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 *    must display the following acknowledgement:
40 *	This product includes software developed by Mats O Jansson
41 * 4. The name of the author may not be used to endorse or promote products
42 *    derived from this software without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
45 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
48 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57#include <sys/cdefs.h>
58#ifndef LINT
59__unused static char rcsid[] = "$OpenBSD: ypserv_proc.c,v 1.14 1997/09/12 01:44:57 deraadt Exp $";
60#endif
61
62#include <rpc/rpc.h>
63#include "yp.h"
64#include "ypv1.h"
65#include <rpcsvc/ypclnt.h>
66#include <sys/stat.h>
67#include <sys/socket.h>
68#include <sys/param.h>
69#include <netinet/in.h>
70#include <arpa/inet.h>
71#include "ypdb.h"
72#include <fcntl.h>
73#include <dirent.h>
74#include <stdio.h>
75#include <string.h>
76#include <unistd.h>
77#include <stdlib.h>
78#include "yplog.h"
79#include "ypdef.h"
80
81#ifdef DEBUG
82#define YPLOG yplog
83#else /* DEBUG */
84#define YPLOG if (!ok) yplog
85#endif /* DEBUG */
86
87extern ypresp_val ypdb_get_record();
88extern ypresp_key_val ypdb_get_first();
89extern ypresp_key_val ypdb_get_next();
90extern ypresp_order ypdb_get_order();
91extern ypresp_master ypdb_get_master();
92extern bool_t ypdb_xdr_get_all();
93extern void ypdb_close_all();
94extern int ypdb_secure();
95extern int yp_acl_check_host(struct in_addr *);
96
97static char *True = "true";
98static char *False = "FALSE";
99#define TORF(N) ((N) ? True : False)
100void *
101ypproc_null_2_svc(argp, rqstp)
102	void *argp;
103        struct svc_req *rqstp;
104{
105	static char *result;
106	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
107	int ok = yp_acl_check_host(&caller->sin_addr);
108
109	YPLOG("null_2: caller=[%s].%d, auth_ok=%s",
110	      inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok));
111
112	if (!ok) {
113		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
114		return(NULL);
115	}
116
117	result = NULL;
118
119	return ((void *)&result);
120}
121
122bool_t *
123ypproc_domain_2_svc(argp, rqstp)
124	domainname *argp;
125        struct svc_req *rqstp;
126{
127	static bool_t result; /* is domain_served? */
128	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
129	int ok = yp_acl_check_host(&caller->sin_addr);
130	static char domain_path[MAXPATHLEN];
131	struct stat finfo;
132
133	if (strchr(*argp, '/'))
134		goto bail;
135	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
136	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
137				    S_ISDIR(finfo.st_mode));
138
139	YPLOG("domain_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
140	      inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
141	      TORF(ok), *argp, TORF(result));
142
143	if (!ok) {
144bail:
145		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
146		return(NULL);
147	}
148
149	return (&result);
150}
151
152bool_t *
153ypproc_domain_nonack_2_svc(argp, rqstp)
154	domainname *argp;
155        struct svc_req *rqstp;
156{
157	static bool_t result; /* is domain served? */
158	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
159	int ok = yp_acl_check_host(&caller->sin_addr);
160	static char domain_path[MAXPATHLEN];
161	struct stat finfo;
162
163	if (strchr(*argp, '/'))
164		goto bail;
165	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
166	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
167				    S_ISDIR(finfo.st_mode));
168
169	YPLOG(
170	  "domain_nonack_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
171	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
172	  *argp, TORF(result));
173
174	if (!ok) {
175bail:
176		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
177		return(NULL);
178	}
179
180	if (!result) {
181		return(NULL); /* don't send nack */
182	}
183
184	return (&result);
185}
186
187ypresp_val *
188ypproc_match_2_svc(argp, rqstp)
189	ypreq_key *argp;
190        struct svc_req *rqstp;
191{
192	static ypresp_val res;
193	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
194	int ok = yp_acl_check_host(&caller->sin_addr);
195	int secure = ypdb_secure(argp->domain,argp->map);
196
197	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
198		goto bail;
199	YPLOG(
200	  "match_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
201	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
202	  TORF(ok), TORF(secure),
203	  argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val);
204
205	if (!ok) {
206bail:
207		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
208		return(NULL);
209	}
210
211	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
212		res.stat = YP_YPERR;
213	} else {
214		res = ypdb_get_record(argp->domain,argp->map,argp->key, FALSE);
215	}
216
217#ifdef DEBUG
218	yplog("  match2_status: %s", yperr_string(ypprot_err(res.stat)));
219#endif
220
221	return (&res);
222}
223
224ypresp_key_val *
225ypproc_first_2_svc(argp, rqstp)
226	ypreq_nokey *argp;
227        struct svc_req *rqstp;
228{
229	static ypresp_key_val res;
230	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
231	int ok = yp_acl_check_host(&caller->sin_addr);
232	int secure = ypdb_secure(argp->domain,argp->map);
233
234	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
235		goto bail;
236	YPLOG( "first_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
237	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
238	  TORF(ok), TORF(secure),
239	  argp->domain, argp->map);
240
241	if (!ok) {
242bail:
243		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
244		return(NULL);
245	}
246
247	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
248		res.stat = YP_YPERR;
249	} else {
250		res = ypdb_get_first(argp->domain,argp->map,FALSE);
251	}
252
253#ifdef DEBUG
254	yplog("  first2_status: %s", yperr_string(ypprot_err(res.stat)));
255#endif
256
257	return (&res);
258}
259
260ypresp_key_val *
261ypproc_next_2_svc(argp, rqstp)
262	ypreq_key *argp;
263        struct svc_req *rqstp;
264{
265	static ypresp_key_val res;
266	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
267	int ok = yp_acl_check_host(&caller->sin_addr);
268	int secure = ypdb_secure(argp->domain,argp->map);
269
270	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
271		goto bail;
272	YPLOG(
273	  "next_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
274	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
275	  TORF(ok), TORF(secure),
276	  argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val);
277
278	if (!ok) {
279bail:
280		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
281		return(NULL);
282	}
283
284	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
285		res.stat = YP_YPERR;
286	} else {
287		res = ypdb_get_next(argp->domain,argp->map,argp->key,FALSE);
288	}
289
290#ifdef DEBUG
291	yplog("  next2_status: %s", yperr_string(ypprot_err(res.stat)));
292#endif
293
294	return (&res);
295}
296
297ypresp_xfr *
298ypproc_xfr_2_svc(argp, rqstp)
299	ypreq_xfr *argp;
300        struct svc_req *rqstp;
301{
302	static ypresp_xfr res;
303	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
304	int ok = yp_acl_check_host(&caller->sin_addr);
305	pid_t	pid;
306	char	tid[11];
307	char	prog[11];
308	char	port[11];
309	char	ypxfr_proc[] = YPXFR_PROC;
310	char	*ipadd;
311
312	bzero((char *)&res, sizeof(res));
313
314	YPLOG("xfr_2: caller=[%s].%d, auth_ok=%s, domain=%s, tid=%d, prog=%d",
315	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
316	  argp->map_parms.domain, argp->transid, argp->prog);
317	YPLOG("       ipadd=%s, port=%d, map=%s", inet_ntoa(caller->sin_addr),
318	  argp->port, argp->map_parms.map);
319
320	if (strchr(argp->map_parms.domain, '/') ||
321	    strchr(argp->map_parms.map, '/') ||
322	    ntohs(caller->sin_port) >= IPPORT_RESERVED) {
323		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
324		return(NULL);
325	}
326
327	snprintf(tid, sizeof(tid), "%d",argp->transid);
328	snprintf(prog, sizeof(prog), "%d", argp->prog);
329	snprintf(port, sizeof(port), "%d", argp->port);
330	ipadd = inet_ntoa(caller->sin_addr);
331
332	pid = vfork();
333	if (pid == -1) {
334		svcerr_systemerr(rqstp->rq_xprt);
335		return(NULL);
336	}
337	if (pid == 0) {
338		execl(ypxfr_proc, "ypxfr", "-d", argp->map_parms.domain,
339		    "-C",tid, prog, ipadd, port, argp->map_parms.map, NULL);
340		_exit(1);
341	}
342
343	/*
344	 * XXX: fill in res
345	 */
346	return (&res);
347}
348
349void *
350ypproc_clear_2_svc(argp, rqstp)
351	void *argp;
352        struct svc_req *rqstp;
353{
354	static char *res;
355	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
356	int ok = yp_acl_check_host(&caller->sin_addr);
357
358	YPLOG( "clear_2: caller=[%s].%d, auth_ok=%s, opt=%s",
359	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
360#ifdef OPTDB
361		True
362#else
363		False
364#endif
365	);
366
367	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
368		ok = FALSE;
369
370	if (!ok) {
371		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
372		return(NULL);
373	}
374
375	res = NULL;
376
377#ifdef OPTDB
378        ypdb_close_all();
379#endif
380
381	return ((void *)&res);
382}
383
384ypresp_all *
385ypproc_all_2_svc(argp, rqstp)
386	ypreq_nokey *argp;
387        struct svc_req *rqstp;
388{
389	static ypresp_all res;
390	pid_t pid;
391	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
392	int ok = yp_acl_check_host(&caller->sin_addr);
393	int secure = ypdb_secure(argp->domain,argp->map);
394
395	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
396		goto bail;
397	YPLOG( "all_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
398	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
399	  TORF(ok), TORF(secure), argp->domain, argp->map);
400
401	if (!ok) {
402bail:
403		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
404		return(NULL);
405	}
406
407	bzero((char *)&res, sizeof(res));
408
409	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
410		res.ypresp_all_u.val.stat = YP_YPERR;
411		return(&res);
412	}
413
414	pid = fork();
415
416	if (pid) {
417
418		if (pid == -1) {
419			/* XXXCDC An error has occurred */
420		}
421
422		return(NULL); /* PARENT: continue */
423
424	}
425	/* CHILD: send result, then exit */
426
427	if (!svc_sendreply(rqstp->rq_xprt, (xdrproc_t)ypdb_xdr_get_all, (char *) argp)) {
428		svcerr_systemerr(rqstp->rq_xprt);
429	}
430
431	/* note: no need to free args, we are exiting */
432
433	exit(0);
434}
435
436ypresp_master *
437ypproc_master_2_svc(argp, rqstp)
438	ypreq_nokey *argp;
439        struct svc_req *rqstp;
440{
441	static ypresp_master res;
442	static peername nopeer = "";
443	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
444	int ok = yp_acl_check_host(&caller->sin_addr);
445	int secure = ypdb_secure(argp->domain,argp->map);
446
447	if (strchr(argp->domain, '/') || strchr(argp->map, '/'))
448		goto bail;
449	YPLOG( "master_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
450	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
451	  TORF(ok), TORF(secure), argp->domain, argp->map);
452
453	if (!ok) {
454bail:
455		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
456		return(NULL);
457	}
458
459	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
460		res.stat = YP_YPERR;
461	} else {
462		res = ypdb_get_master(argp->domain,argp->map);
463	}
464
465#ifdef DEBUG
466	yplog("  master2_status: %s", yperr_string(ypprot_err(res.stat)));
467#endif
468
469	/* This code was added because a yppoll <unknown-domain> */
470	/* from a sun crashed the server in xdr_string, trying   */
471	/* to access the peer through a NULL-pointer. yppoll in  */
472	/* this server start asking for order. If order is ok    */
473	/* then it will ask for master. SunOS 4 asks for both    */
474	/* always. I'm not sure this is the best place for the   */
475	/* fix, but for now it will do. xdr_peername or          */
476	/* xdr_string in ypserv_xdr.c may be a better place?     */
477
478	if (res.peer == NULL) {
479		res.peer = nopeer;
480	}
481
482	/* End of fix                                            */
483
484	return (&res);
485}
486
487
488ypresp_order *
489ypproc_order_2_svc(argp, rqstp)
490	ypreq_nokey *argp;
491        struct svc_req *rqstp;
492{
493	static ypresp_order res;
494	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
495	int ok = yp_acl_check_host(&caller->sin_addr);
496	int secure = ypdb_secure(argp->domain,argp->map);
497
498	if (strchr(argp->domain, '/'))
499		goto bail;
500	YPLOG( "order_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
501	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
502	  TORF(ok), TORF(secure), argp->domain, argp->map);
503
504	if (!ok) {
505bail:
506		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
507		return(NULL);
508	}
509
510	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
511		res.stat = YP_YPERR;
512	} else if (strchr(argp->map, '/')) {
513		res.stat = YP_NOMAP;
514	} else {
515		res = ypdb_get_order(argp->domain,argp->map);
516	}
517
518#ifdef DEBUG
519	yplog("  order2_status: %s", yperr_string(ypprot_err(res.stat)));
520#endif
521
522	return (&res);
523}
524
525
526ypresp_maplist *
527ypproc_maplist_2_svc(argp, rqstp)
528	domainname *argp;
529        struct svc_req *rqstp;
530{
531	static ypresp_maplist res;
532	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
533	int ok = yp_acl_check_host(&caller->sin_addr);
534	static char domain_path[MAXPATHLEN];
535	struct stat finfo;
536	DIR   *dirp = NULL;
537	struct dirent *dp;
538	char  *suffix;
539	ypstat status;
540	struct ypmaplist *m;
541	char  *map_name;
542
543	if (strchr(*argp, '/'))
544		goto bail;
545	YPLOG("maplist_2: caller=[%s].%d, auth_ok=%s, domain=%s",
546	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
547	  *argp);
548
549	if (!ok) {
550bail:
551		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
552		return(NULL);
553	}
554
555	bzero((char *)&res, sizeof(res));
556
557	snprintf(domain_path,MAXPATHLEN, "%s/%s",YP_DB_PATH,*argp);
558
559	status = YP_TRUE;
560
561	res.maps = NULL;
562
563	if (!((stat(domain_path, &finfo) == 0) &&
564		S_ISDIR(finfo.st_mode)))
565		status = YP_NODOM;
566
567	if (status >= 0) {
568	  if ((dirp = opendir(domain_path)) == NULL) {
569	    status = YP_NODOM;
570	  }
571	}
572
573	if (status >= 0) {
574	  for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
575	    if ((!strcmp(dp->d_name, ".")) ||
576		((!strcmp(dp->d_name, ".."))) ||
577		(dp->d_namlen < 4))
578	      continue;
579	    suffix = (char *) &dp->d_name[dp->d_namlen-3];
580	    if (strcmp(suffix,".db") == 0) {
581
582	      if ((m = (struct ypmaplist *)
583		   malloc((unsigned) sizeof(struct ypmaplist))) == NULL) {
584		status = YP_YPERR;
585		break;
586	      }
587
588	      if ((map_name = (char *)
589		   malloc((unsigned) dp->d_namlen - 2)) == NULL) {
590		status = YP_YPERR;
591		break;
592	      }
593
594	      m->next = res.maps;
595	      m->map = map_name;
596	      res.maps = m;
597	      strncpy(map_name, dp->d_name, dp->d_namlen - 3);
598	      m->map[dp->d_namlen - 3] = '\0';
599
600	    }
601	  }
602	}
603
604	if (dirp != NULL) {
605	  closedir(dirp);
606	}
607
608	res.stat = status;
609
610#ifdef DEBUG
611	yplog("  maplist_status: %s", yperr_string(ypprot_err(res.stat)));
612#endif
613
614	return (&res);
615}
616
617void *
618ypproc_null_1_svc(argp, rqstp)
619	void *argp;
620        struct svc_req *rqstp;
621{
622	static char *result;
623	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
624	int ok = yp_acl_check_host(&caller->sin_addr);
625
626	YPLOG("null_1: caller=[%s].%d, auth_ok=%s",
627	      inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok));
628
629	if (!ok) {
630		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
631		return(NULL);
632	}
633
634	result = NULL;
635
636	return ((void *)&result);
637}
638
639bool_t *
640ypproc_domain_1_svc(argp, rqstp)
641	domainname *argp;
642        struct svc_req *rqstp;
643{
644	static bool_t result; /* is domain_served? */
645	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
646	int ok = yp_acl_check_host(&caller->sin_addr);
647	static char domain_path[MAXPATHLEN];
648	struct stat finfo;
649
650	if (strchr(*argp, '/'))
651		goto bail;
652	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
653	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
654				    S_ISDIR(finfo.st_mode));
655
656	YPLOG("domain_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
657	      inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
658	      TORF(ok), *argp, TORF(result));
659
660	if (!ok) {
661bail:
662		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
663		return(NULL);
664	}
665
666	return (&result);
667}
668
669bool_t *
670ypproc_domain_nonack_1_svc(argp, rqstp)
671	domainname *argp;
672        struct svc_req *rqstp;
673{
674	static bool_t result; /* is domain served? */
675	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
676	int ok = yp_acl_check_host(&caller->sin_addr);
677	static char domain_path[MAXPATHLEN];
678	struct stat finfo;
679
680	if (strchr(*argp, '/'))
681		goto bail;
682	snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp);
683	result = (bool_t) ((stat(domain_path, &finfo) == 0) &&
684				    S_ISDIR(finfo.st_mode));
685
686	YPLOG(
687	  "domain_nonack_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s",
688	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok),
689	  *argp, TORF(result));
690
691	if (!ok) {
692bail:
693		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
694		return(NULL);
695	}
696
697	if (!result) {
698		return(NULL); /* don't send nack */
699	}
700
701	return (&result);
702}
703
704ypresponse *
705ypproc_match_1_svc(argp, rqstp)
706	yprequest *argp;
707        struct svc_req *rqstp;
708{
709	static ypresponse res;
710	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
711	int ok = yp_acl_check_host(&caller->sin_addr);
712	int secure;
713
714	if (strchr(argp->ypmatch_req_domain, '/') ||
715	    strchr(argp->ypmatch_req_map, '/'))
716		goto bail;
717	res.yp_resptype = YPMATCH_RESPTYPE;
718	res.ypmatch_resp_valptr = "";
719	res.ypmatch_resp_valsize = 0;
720
721	if (argp->yp_reqtype != YPMATCH_REQTYPE) {
722		res.ypmatch_resp_status = YP_BADARGS;
723		return(&res);
724	}
725
726	secure = ypdb_secure(argp->ypmatch_req_domain, argp->ypmatch_req_map);
727
728	YPLOG(
729	  "match_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
730	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
731	  TORF(ok), TORF(secure),
732	  argp->ypmatch_req_domain,  argp->ypmatch_req_map,
733	  argp->ypmatch_req_keysize, argp->ypmatch_req_keyptr);
734
735	if (!ok) {
736bail:
737		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
738		return(NULL);
739	}
740
741	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
742		res.ypmatch_resp_status = YP_YPERR;
743	} else {
744		res.ypmatch_resp_val =
745		      ypdb_get_record(argp->ypmatch_req_domain,
746				      argp->ypmatch_req_map,
747				      argp->ypmatch_req_keydat,
748				      FALSE);
749	}
750
751#ifdef DEBUG
752	yplog("  match1_status: %s",
753	      yperr_string(ypprot_err(res.ypmatch_resp_status)));
754#endif
755
756	return (&res);
757}
758
759ypresponse *
760ypproc_first_1_svc(argp, rqstp)
761	yprequest *argp;
762        struct svc_req *rqstp;
763{
764	static ypresponse res;
765	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
766	int ok = yp_acl_check_host(&caller->sin_addr);
767	int secure;
768
769	if (strchr(argp->ypfirst_req_domain, '/') ||
770	    strchr(argp->ypfirst_req_map, '/'))
771		goto bail;
772	res.yp_resptype = YPFIRST_RESPTYPE;
773	res.ypfirst_resp_valptr  = res.ypfirst_resp_keyptr  = "";
774	res.ypfirst_resp_valsize = res.ypfirst_resp_keysize = 0;
775
776	if (argp->yp_reqtype != YPREQ_NOKEY) {
777		res.ypfirst_resp_status = YP_BADARGS;
778		return(&res);
779	}
780
781	secure = ypdb_secure(argp->ypfirst_req_domain, argp->ypfirst_req_map);
782
783	YPLOG( "first_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
784	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
785	  TORF(ok), TORF(secure),
786	  argp->ypfirst_req_domain, argp->ypfirst_req_map);
787
788	if (!ok) {
789bail:
790		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
791		return(NULL);
792	}
793
794	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
795		res.ypfirst_resp_status = YP_YPERR;
796	} else {
797		res.ypfirst_resp_val =
798		      ypdb_get_first(argp->ypfirst_req_domain,
799				     argp->ypfirst_req_map,
800				     FALSE);
801	}
802
803#ifdef DEBUG
804	yplog("  first1_status: %s",
805	      yperr_string(ypprot_err(res.ypfirst_resp_status)));
806#endif
807
808	return (&res);
809}
810
811ypresponse *
812ypproc_next_1_svc(argp, rqstp)
813	yprequest *argp;
814        struct svc_req *rqstp;
815{
816	static ypresponse res;
817	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
818	int ok = yp_acl_check_host(&caller->sin_addr);
819	int secure;
820
821	if (strchr(argp->ypnext_req_domain, '/') ||
822	    strchr(argp->ypnext_req_map, '/'))
823		goto bail;
824	res.yp_resptype = YPNEXT_RESPTYPE;
825	res.ypnext_resp_valptr  = res.ypnext_resp_keyptr  = "";
826	res.ypnext_resp_valsize = res.ypnext_resp_keysize = 0;
827
828	if (argp->yp_reqtype != YPNEXT_REQTYPE) {
829		res.ypnext_resp_status = YP_BADARGS;
830		return(&res);
831	}
832
833	secure = ypdb_secure(argp->ypnext_req_domain, argp->ypnext_req_map);
834
835	YPLOG(
836	  "next_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s",
837	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
838	  TORF(ok), TORF(secure),
839	  argp->ypnext_req_domain,  argp->ypnext_req_map,
840	  argp->ypnext_req_keysize, argp->ypnext_req_keyptr);
841
842	if (!ok) {
843bail:
844		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
845		return(NULL);
846	}
847
848	if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
849		res.ypnext_resp_status = YP_YPERR;
850	} else {
851		res.ypnext_resp_val =
852		      ypdb_get_next(argp->ypnext_req_domain,
853				    argp->ypnext_req_map,
854				    argp->ypnext_req_keydat,
855				    FALSE);
856	}
857
858#ifdef DEBUG
859	yplog("  next1_status: %s",
860	      yperr_string(ypprot_err(res.ypnext_resp_status)));
861#endif
862
863	return (&res);
864}
865
866ypresponse *
867ypproc_poll_1_svc(argp, rqstp)
868	yprequest *argp;
869        struct svc_req *rqstp;
870{
871	static ypresponse res;
872	ypresp_order order;
873	ypresp_master master;
874	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
875	int ok = yp_acl_check_host(&caller->sin_addr);
876	int secure;
877
878	if (strchr(argp->yppoll_req_domain, '/') ||
879	    strchr(argp->yppoll_req_map, '/'))
880		goto bail;
881	res.yp_resptype = YPPOLL_RESPTYPE;
882	res.yppoll_resp_domain = argp->yppoll_req_domain;
883	res.yppoll_resp_map = argp->yppoll_req_map;
884	res.yppoll_resp_ordernum = 0;
885	res.yppoll_resp_owner = "";
886
887	if (argp->yp_reqtype != YPPOLL_REQTYPE) {
888		return(&res);
889	}
890
891	secure = ypdb_secure(argp->yppoll_req_domain, argp->yppoll_req_map);
892
893	YPLOG( "poll_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
894	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
895	  TORF(ok), TORF(secure),
896	  argp->yppoll_req_domain, argp->yppoll_req_map);
897
898	if (!ok) {
899bail:
900		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
901		return(NULL);
902	}
903
904	if (!(secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED))) {
905		order = ypdb_get_order(argp->yppoll_req_domain,
906				       argp->yppoll_req_map);
907		master = ypdb_get_master(argp->yppoll_req_domain,
908					 argp->yppoll_req_map);
909		res.yppoll_resp_ordernum = order.ordernum;
910		res.yppoll_resp_owner = master.peer;
911	}
912
913#ifdef DEBUG
914	yplog("  poll1_status: %s", "none");
915#endif
916	return (&res);
917}
918
919void *
920ypproc_push_1_svc(argp, rqstp)
921	yprequest *argp;
922        struct svc_req *rqstp;
923{
924	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
925	int ok = yp_acl_check_host(&caller->sin_addr);
926	int secure;
927	pid_t	pid;
928	char	yppush_proc[] = YPPUSH_PROC;
929
930	if (strchr(argp->yppush_req_domain, '/') ||
931	    strchr(argp->yppush_req_map, '/'))
932		goto bail;
933	if (argp->yp_reqtype != YPPUSH_REQTYPE) {
934		return(NULL);
935	}
936
937	secure = ypdb_secure(argp->yppush_req_domain, argp->yppush_req_map);
938
939	YPLOG( "push_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
940	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
941	  TORF(ok), TORF(secure),
942	  argp->yppush_req_domain, argp->yppush_req_map);
943
944	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
945		ok = FALSE;
946
947	if (!ok) {
948bail:
949		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
950		return(NULL);
951	}
952
953	pid = vfork();
954	if (pid == -1) {
955		svcerr_systemerr(rqstp->rq_xprt);
956		return(NULL);
957	}
958	if (pid == 0) {
959		execl(yppush_proc, "yppush", "-d", argp->yppush_req_domain,
960		      argp->yppush_req_map, NULL);
961		_exit(1);
962	}
963
964	return (NULL);
965}
966
967void *
968ypproc_pull_1_svc(argp, rqstp)
969	yprequest *argp;
970        struct svc_req *rqstp;
971{
972	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
973	int ok = yp_acl_check_host(&caller->sin_addr);
974	int secure;
975	pid_t	pid;
976	char	ypxfr_proc[] = YPXFR_PROC;
977
978	if (strchr(argp->yppull_req_domain, '/') ||
979	    strchr(argp->yppull_req_map, '/'))
980		goto bail;
981	if (argp->yp_reqtype != YPPULL_REQTYPE) {
982		return(NULL);
983	}
984
985	secure = ypdb_secure(argp->yppull_req_domain, argp->yppull_req_map);
986
987	YPLOG( "pull_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s",
988	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
989	  TORF(ok), TORF(secure),
990	  argp->yppull_req_domain, argp->yppull_req_map);
991
992	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
993		ok = FALSE;
994
995	if (!ok) {
996bail:
997		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
998		return(NULL);
999	}
1000
1001	pid = vfork();
1002	if (pid == -1) {
1003		svcerr_systemerr(rqstp->rq_xprt);
1004		return(NULL);
1005	}
1006	if (pid == 0) {
1007		execl(ypxfr_proc, "ypxfr", "-d", argp->yppull_req_domain,
1008		      argp->yppull_req_map, NULL);
1009		_exit(1);
1010	}
1011
1012	return (NULL);
1013}
1014
1015void *
1016ypproc_get_1_svc(argp, rqstp)
1017	yprequest *argp;
1018        struct svc_req *rqstp;
1019{
1020	struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt);
1021	int ok = yp_acl_check_host(&caller->sin_addr);
1022	int secure;
1023	pid_t	pid;
1024	char	ypxfr_proc[] = YPXFR_PROC;
1025
1026	if (strchr(argp->ypget_req_domain, '/') ||
1027	    strchr(argp->ypget_req_map, '/'))
1028		goto bail;
1029	if (argp->yp_reqtype != YPGET_REQTYPE) {
1030		return(NULL);
1031	}
1032
1033	secure = ypdb_secure(argp->ypget_req_domain, argp->ypget_req_map);
1034
1035	YPLOG( "get_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, owner=%s",
1036	  inet_ntoa(caller->sin_addr), ntohs(caller->sin_port),
1037	  TORF(ok), TORF(secure),
1038	  argp->ypget_req_domain, argp->ypget_req_map,
1039	  argp->ypget_req_owner);
1040
1041	if (ntohs(caller->sin_port) >= IPPORT_RESERVED)
1042		ok = FALSE;
1043
1044	if (!ok) {
1045bail:
1046		svcerr_auth(rqstp->rq_xprt, AUTH_FAILED);
1047		return(NULL);
1048	}
1049
1050	pid = vfork();
1051	if (pid == -1) {
1052		svcerr_systemerr(rqstp->rq_xprt);
1053		return(NULL);
1054	}
1055	if (pid == 0) {
1056		execl(ypxfr_proc, "ypxfr", "-d", argp->ypget_req_domain, "-h",
1057		      argp->ypget_req_owner, argp->yppush_req_map, NULL);
1058		_exit(1);
1059	}
1060
1061	return (NULL);
1062}
1063