From 2d779f05ef5a96063b9545faad4b44e44cb258cb Mon Sep 17 00:00:00 2001 From: wpaul Date: Thu, 10 Apr 1997 14:12:51 +0000 Subject: Add a sanity test to ypproc_xfr_2_svc(): check that the map and domain in the transfer request actually exist. Technically ypxfr can do this too, but why waste the cycles getting ypxfr off the ground for a transfer we already know is going to fail. Also apply stricter access control rules; ypproc_xfr_2_svc() is in a different class than the normal map access procedures procedures. --- usr.sbin/ypserv/yp_server.c | 56 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-) (limited to 'usr.sbin/ypserv') diff --git a/usr.sbin/ypserv/yp_server.c b/usr.sbin/ypserv/yp_server.c index e60251f..ce86a15 100644 --- a/usr.sbin/ypserv/yp_server.c +++ b/usr.sbin/ypserv/yp_server.c @@ -45,7 +45,7 @@ #include #ifndef lint -static const char rcsid[] = "$Id$"; +static const char rcsid[] = "$Id: yp_server.c,v 1.5 1997/03/15 06:06:06 wpaul Exp wpaul $"; #endif /* not lint */ int forked = 0; @@ -305,25 +305,65 @@ ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) { static ypresp_xfr result; struct sockaddr_in *rqhost; + ypresp_master *mres; + ypreq_nokey mreq; result.transid = argp->transid; rqhost = svc_getcaller(rqstp->rq_xprt); + /* + * The FreeBSD ypxfr(8) program will not talk to a ypserv(8) + * or rpc.ypxfrd(8) unless it's using a reserved port, but we + * may as well check that the process calling this procedure + * is also using one. + * + * yp_access() may also do a reserved port test, but only + * if the YP_SECURE flag is set in the map. For this procedure, + * the check should be unconditional. + */ + if (ntohs(rqhost->sin_port) >= IPPORT_RESERVED) { + yp_error("ypxfr request from non-reserved port (%s:%d) -- \ +rejecting", inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); + YPXFR_RETURN(YPXFR_REFUSED) + } + #ifdef DB_CACHE if (yp_access(argp->map_parms.map, argp->map_parms.domain, (struct svc_req *)rqstp)) { #else if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { #endif - YPXFR_RETURN(YPXFR_REFUSED); + YPXFR_RETURN(YPXFR_REFUSED) } + if (argp->map_parms.domain == NULL) { - YPXFR_RETURN(YPXFR_BADARGS); + YPXFR_RETURN(YPXFR_BADARGS) } if (yp_validdomain(argp->map_parms.domain)) { - YPXFR_RETURN(YPXFR_NODOM); + YPXFR_RETURN(YPXFR_NODOM) + } + + /* + * Determine the master host ourselves. The caller may + * be up to no good. This has the side effect of verifying + * that the requested map and domain actually exist. + */ + + mreq.domain = argp->map_parms.domain; + mreq.map = argp->map_parms.map; + + mres = ypproc_master_2_svc(&mreq, rqstp); + + if (mres->stat != YP_TRUE) { + yp_error("couldn't find master for map %s@%s", + argp->map_parms.map, + argp->map_parms.domain); + yp_error("host at %s (%s) may be pulling my leg", + argp->map_parms.peer, + inet_ntoa(rqhost->sin_addr)); + YPXFR_RETURN(YPXFR_REFUSED) } switch(fork()) { @@ -342,7 +382,7 @@ ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) if (strcmp(yp_dir, _PATH_YP)) { execl(ypxfr_command, "ypxfr", "-d", argp->map_parms.domain, - "-h", argp->map_parms.peer, + "-h", mres->peer, "-p", yp_dir, "-C", t, g, inet_ntoa(rqhost->sin_addr), p, argp->map_parms.map, @@ -350,7 +390,7 @@ ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) } else { execl(ypxfr_command, "ypxfr", "-d", argp->map_parms.domain, - "-h", argp->map_parms.peer, + "-h", mres->peer, "-C", t, g, inet_ntoa(rqhost->sin_addr), p, argp->map_parms.map, @@ -358,12 +398,12 @@ ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) } forked++; yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); - YPXFR_RETURN(YPXFR_XFRERR); + YPXFR_RETURN(YPXFR_XFRERR) break; } case -1: yp_error("ypxfr fork(): %s", strerror(errno)); - YPXFR_RETURN(YPXFR_XFRERR); + YPXFR_RETURN(YPXFR_XFRERR) break; default: result.xfrstat = YPXFR_SUCC; -- cgit v1.1