From 460a7e676684674c409ae92a9d8247d790bf1c85 Mon Sep 17 00:00:00 2001 From: deraadt Date: Thu, 30 Jan 1997 07:47:28 +0000 Subject: [PATCH] if at first-request-for-a-domain we discover a file /etc/yp/$domainneme to exist, use it as a list of valid servers instead of doing broadcasts. However, do not change the semantics of -ypset or -ypsetme. Based on the reasoning provided in netbsd pr#1759, lukem@supp.cpr.itg.telecom.com.au --- usr.sbin/ypbind/ypbind.8 | 41 ++++++++---- usr.sbin/ypbind/ypbind.c | 139 ++++++++++++++++++++++++++++++++------- 2 files changed, 146 insertions(+), 34 deletions(-) diff --git a/usr.sbin/ypbind/ypbind.8 b/usr.sbin/ypbind/ypbind.8 index de5c35617dd..7fad0c1ae3b 100644 --- a/usr.sbin/ypbind/ypbind.8 +++ b/usr.sbin/ypbind/ypbind.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ypbind.8,v 1.5 1996/04/29 08:05:39 deraadt Exp $ +.\" $OpenBSD: ypbind.8,v 1.6 1997/01/30 07:47:28 deraadt Exp $ .\" $NetBSD: ypbind.8,v 1.2 1996/02/28 01:21:00 thorpej Exp $ .\" .\" Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -42,12 +42,12 @@ .Nm ypbind .Nd create and maintain a binding to a YP server .Sh SYNOPSIS -.Nm ypbind +.Nm .Op Fl ypset -.Nm ypbind +.Nm .Op Fl ypsetme .Sh DESCRIPTION -.Nm Ypbind +.Nm finds the server for a particular YP domain and stores information about it in a .Pa binding file. @@ -56,20 +56,32 @@ that particular domain and which port the server is using. This information is stored in the directory .Pa /var/yp/binding in a file named with the convention -.Pa domainname.version. +.Pa DOMAINNAME.version. (The YP system only supplies information on version 2.) .Pp When -.Nm ypbind -starts, it broadcasts looking for a process willing to serve maps for the +.Nm +starts the primary domain (or gets the first request for a new domain), +it checks if a file for the domain in question exists in the directory +.Pa /etc/yp/ +(ie. /etc/yp/DOMAINNAME). +If such a file exists, it will list the hosts which +.Nm +should restrict it's server search to. +Otherwise, +.Nm +assumes it will need to use broadcasts to find a valid server. +Using either of these techniques, +.Nm +will search for a server willing to serve maps for the client's domain. Once a binding is established, -.Nm ypbind +.Nm maintains this binding by periodically communicating with the server to which it is bound. If the binding is somehow lost, e.g by server reboot, -.Nm ypbind +.Nm marks the domain as unbound and attempts to re-establish the binding. When the binding is once again successful, -.Nm ypbind +.Nm marks the domain as bound and resumes its periodic check. .Pp The options are as follows: @@ -88,14 +100,19 @@ The and .Fl ypsetme options are dangerous and should be avoided. +For greatest security, the use of a server list in +.Pa /var/yp/DOMAINNAME +is recommended. .Pp If the directory .Pa /var/yp/binding exists, YP is started automatically at boot time by .Pa /etc/rc . .Sh FILES -.Pa /var/yp/binding/domainname.version +.Pa /var/yp/binding/DOMAINNAME.version - binding file for domainname +.Pa /etc/yp/DOMAINNNAME +- server list for this particular domain .Sh SEE ALSO .Xr domainname 1 , .Xr ypcat 1 , @@ -103,7 +120,7 @@ exists, YP is started automatically at boot time by .Xr yppoll 8 , .Xr ypset 8 , .Xr ypwhich 1 , -.Xr ypserv 8 +.Xr ypserv 8 , .Xr yp 8 .Sh AUTHOR Theo de Raadt diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c index 4ceaa900523..ce154b3cc73 100644 --- a/usr.sbin/ypbind/ypbind.c +++ b/usr.sbin/ypbind/ypbind.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ypbind.c,v 1.17 1997/01/30 06:03:08 deraadt Exp $ */ +/* $OpenBSD: ypbind.c,v 1.18 1997/01/30 07:47:29 deraadt Exp $ */ /* * Copyright (c) 1996 Theo de Raadt @@ -34,7 +34,7 @@ */ #ifndef LINT -static char rcsid[] = "$OpenBSD: ypbind.c,v 1.17 1997/01/30 06:03:08 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: ypbind.c,v 1.18 1997/01/30 07:47:29 deraadt Exp $"; #endif #include @@ -63,9 +63,11 @@ static char rcsid[] = "$OpenBSD: ypbind.c,v 1.17 1997/01/30 06:03:08 deraadt Exp #include #include #include +#include #include #include +#define SERVERSDIR "/etc/yp" #define BINDINGDIR "/var/yp/binding" #define YPBINDLOCK "/var/run/ypbind.lock" @@ -82,6 +84,8 @@ struct _dom_binding { int dom_lockfd; int dom_alive; int dom_xid; + char dom_servlist[MAXPATHLEN]; + FILE *dom_servlistfp; }; extern bool_t xdr_domainname(), xdr_ypbind_resp(); @@ -92,8 +96,10 @@ void rpc_received __P((char *dom, struct sockaddr_in *raddrp, int force)); void checkwork __P((void)); enum clnt_stat handle_replies __P((void)); enum clnt_stat handle_ping __P((void)); -int broadcast __P((struct _dom_binding *ypdb)); +int broadcast __P((struct _dom_binding *ypdb, char *, int)); +int direct __P((struct _dom_binding *ypdb, char *, int)); int ping __P((struct _dom_binding *ypdb)); +int pings __P((struct _dom_binding *ypdb)); char *domain; @@ -150,6 +156,9 @@ ypbindproc_domain_2x(transp, argp, clnt) char path[MAXPATHLEN]; time_t now; + if (strchr((char *)argp, '/') || strchr((char *)argp, '.')) + return NULL; + memset(&res, 0, sizeof res); res.ypbind_status = YPBIND_FAIL_VAL; @@ -164,9 +173,12 @@ ypbindproc_domain_2x(transp, argp, clnt) ypdb->dom_vers = YPVERS; ypdb->dom_alive = 0; ypdb->dom_lockfd = -1; - sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, - (int)ypdb->dom_vers); + sprintf(path, "%s/%s.%d", BINDINGDIR, + ypdb->dom_domain, (int)ypdb->dom_vers); unlink(path); + sprintf(ypdb->dom_servlist, "%s/%s", + SERVERSDIR, ypdb->dom_domain); + ypdb->dom_servlistfp = fopen(ypdb->dom_servlist, "r"); ypdb->dom_xid = unique_xid(ypdb); ypdb->dom_pnext = ypbindlist; ypbindlist = ypdb; @@ -483,6 +495,9 @@ main(argc, argv) rmtcr.xdr_results = xdr_bool; rmtcr.results_ptr = (caddr_t)&rmtcr_outval; + if (strchr(domain, '/') || strchr(domain, '.')) + errx(1, "bad domainname %s", domain); + /* build initial domain binding, make it "unsuccessful" */ ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); memset(ypbindlist, 0, sizeof *ypbindlist); @@ -490,8 +505,8 @@ main(argc, argv) ypbindlist->dom_vers = YPVERS; ypbindlist->dom_alive = 0; ypbindlist->dom_lockfd = -1; - sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain, - (int)ypbindlist->dom_vers); + sprintf(path, "%s/%s.%d", BINDINGDIR, + ypbindlist->dom_domain, (int)ypbindlist->dom_vers); (void)unlink(path); checkwork(); @@ -559,7 +574,7 @@ checkwork() if (ypdb->dom_alive == 1) ping(ypdb); else - broadcast(ypdb); + pings(ypdb); time(&t); ypdb->dom_check_t = t + 5; } @@ -626,19 +641,16 @@ ping(ypdb) } int -broadcast(ypdb) +pings(ypdb) struct _dom_binding *ypdb; { domainname dom = ypdb->dom_domain; struct rpc_msg msg; - char buf[1400], *inbuf = NULL; + struct sockaddr_in bindsin; + char buf[1400]; char path[MAXPATHLEN]; enum clnt_stat st; - int outlen, i, sock, len, inlen = 8192; - struct sockaddr_in bindsin; - struct ifconf ifc; - struct ifreq ifreq, *ifr; - struct in_addr in; + int outlen; AUTH *rpcua; XDR xdr; @@ -685,27 +697,49 @@ broadcast(ypdb) if (ypdb->dom_lockfd != -1) { close(ypdb->dom_lockfd); ypdb->dom_lockfd = -1; - sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, - (int)ypdb->dom_vers); + sprintf(path, "%s/%s.%d", BINDINGDIR, + ypdb->dom_domain, (int)ypdb->dom_vers); unlink(path); } - memset(&bindsin, 0, sizeof bindsin); - bindsin.sin_family = AF_INET; - bindsin.sin_len = sizeof(bindsin); - bindsin.sin_port = htons(PMAPPORT); - if (ypdb->dom_alive == 2) { /* * This resolves the following situation: * ypserver on other subnet was once bound, * but rebooted and is now using a different port */ + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bindsin.sin_port = htons(PMAPPORT); bindsin.sin_addr = ypdb->dom_server_addr.sin_addr; if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin, sizeof bindsin) < 0) perror("sendto"); } + if (ypdb->dom_servlistfp) + return direct(ypdb, buf, outlen); + return broadcast(ypdb, buf, outlen); +} + +int +broadcast(ypdb, buf, outlen) + struct _dom_binding *ypdb; + char *buf; + int outlen; +{ + char *inbuf = NULL; + int i, sock, len, inlen = 8192; + struct sockaddr_in bindsin; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + struct in_addr in; + + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bindsin.sin_port = htons(PMAPPORT); + /* find all networks and send the RPC packet out them all */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); @@ -774,6 +808,67 @@ broadcast(ypdb) return 0; } +int +direct(ypdb, buf, outlen) + struct _dom_binding *ypdb; + char *buf; + int outlen; +{ + char line[1024], *p; + struct hostent *hp; + struct sockaddr_in bindsin; + int i, c; + struct stat fst, st; + + if (fstat(fileno(ypdb->dom_servlistfp), &fst) != -1 && + stat(ypdb->dom_servlist, &st) != -1 && + (st.st_dev != fst.st_dev || st.st_ino != fst.st_ino)) { + FILE *fp; + + fp = fopen(ypdb->dom_servlist, "r"); + if (fp) { + fclose(ypdb->dom_servlistfp); + ypdb->dom_servlistfp = fp; + } + } + (void) rewind(ypdb->dom_servlistfp); + + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bindsin.sin_port = htons(PMAPPORT); + + while (fgets(line, sizeof(line), ypdb->dom_servlistfp) != NULL) { + /* skip lines that are too big */ + p = strchr(line, '\n'); + if (p == NULL) { + while ((c = getc(ypdb->dom_servlistfp)) != '\n' && c != EOF) + ; + continue; + } + *p = '\0'; + p = line; + while (isspace(*p)) + p++; + if (*p == '#') + continue; + hp = gethostbyname(p); + if (!hp) + continue; + /* step through all addresses in case first is unavailable */ + for (i = 0; hp->h_addr_list[i]; i++) { + memmove(&bindsin.sin_addr, hp->h_addr_list[0], + hp->h_length); + if (sendto(rpcsock, buf, outlen, 0, + (struct sockaddr *)&bindsin, sizeof bindsin) < 0) { + perror("sendto"); + continue; + } + } + } + return 0; +} + enum clnt_stat handle_replies() { -- 2.20.1