Index: head/libexec/ypxfr/ypxfr_main.c =================================================================== --- head/libexec/ypxfr/ypxfr_main.c (revision 359676) +++ head/libexec/ypxfr/ypxfr_main.c (revision 359677) @@ -1,579 +1,579 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ypxfr_extern.h" +int debug = 1; + char *progname = "ypxfr"; char *yp_dir = _PATH_YP; int _rpcpmstart = 0; static int ypxfr_use_yplib = 0; /* Assume the worst. */ static int ypxfr_clear = 1; static int ypxfr_prognum = 0; static struct sockaddr_in ypxfr_callback_addr; static struct yppushresp_xfr ypxfr_resp; static DB *dbp; static void ypxfr_exit(ypxfrstat retval, char *temp) { CLIENT *clnt; int sock = RPC_ANYSOCK; struct timeval timeout; /* Clean up no matter what happened previously. */ if (temp != NULL) { if (dbp != NULL) (void)(dbp->close)(dbp); if (unlink(temp) == -1) { yp_error("failed to unlink %s",strerror(errno)); } } if (ypxfr_prognum) { timeout.tv_sec = 20; timeout.tv_usec = 0; if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum, 1, timeout, &sock)) == NULL) { yp_error("%s", clnt_spcreateerror("failed to " "establish callback handle")); exit(1); } ypxfr_resp.status = (yppush_status)retval; if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { yp_error("%s", clnt_sperror(clnt, "callback failed")); clnt_destroy(clnt); exit(1); } clnt_destroy(clnt); } else { yp_error("Exiting: %s", ypxfrerr_string(retval)); } exit(0); } static void usage(void) { if (_rpcpmstart) { ypxfr_exit(YPXFR_BADARGS,NULL); } else { fprintf(stderr, "%s\n%s\n%s\n", "usage: ypxfr [-f] [-c] [-d target domain] [-h source host]", " [-s source domain] [-p path]", " [-C taskid program-number ipaddr port] mapname"); exit(1); } } int ypxfr_foreach(int status, char *key, int keylen, char *val, int vallen, char *data) { DBT dbkey, dbval; if (status != YP_TRUE) return (status); /* * XXX Do not attempt to write zero-length keys or * data into a Berkeley DB hash database. It causes a * strange failure mode where sequential searches get * caught in an infinite loop. */ if (keylen) { dbkey.data = key; dbkey.size = keylen; } else { dbkey.data = ""; dbkey.size = 1; } if (vallen) { dbval.data = val; dbval.size = vallen; } else { dbval.data = ""; dbval.size = 1; } if (yp_put_record(dbp, &dbkey, &dbval, 0) != YP_TRUE) return(yp_errno); return (0); } int main(int argc, char *argv[]) { int ch; int ypxfr_force = 0; char *ypxfr_dest_domain = NULL; char *ypxfr_source_host = NULL; char *ypxfr_source_domain = NULL; char *ypxfr_local_domain = NULL; char *ypxfr_master = NULL; unsigned long ypxfr_order = -1, ypxfr_skew_check = -1; char *ypxfr_mapname = NULL; int ypxfr_args = 0; char ypxfr_temp_map[MAXPATHLEN + 2]; char tempmap[MAXPATHLEN + 2]; char buf[MAXPATHLEN + 2]; DBT key, data; int remoteport; int interdom = 0; int secure = 0; - - debug = 1; if (!isatty(fileno(stderr))) { openlog("ypxfr", LOG_PID, LOG_DAEMON); _rpcpmstart = 1; } if (argc < 2) usage(); while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != -1) { int my_optind; switch (ch) { case 'f': ypxfr_force++; ypxfr_args++; break; case 'c': ypxfr_clear = 0; ypxfr_args++; break; case 'd': ypxfr_dest_domain = optarg; ypxfr_args += 2; break; case 'h': ypxfr_source_host = optarg; ypxfr_args += 2; break; case 's': ypxfr_source_domain = optarg; ypxfr_args += 2; break; case 'p': yp_dir = optarg; ypxfr_args += 2; break; case 'C': /* * Whoever decided that the -C flag should take * four arguments is a twit. */ my_optind = optind - 1; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("transaction ID not specified"); usage(); } ypxfr_resp.transid = atol(argv[my_optind]); my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("RPC program number not specified"); usage(); } ypxfr_prognum = atol(argv[my_optind]); my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("address not specified"); usage(); } if (!inet_aton(argv[my_optind], &ypxfr_callback_addr.sin_addr)) { yp_error("failed to convert '%s' to IP addr", argv[my_optind]); exit(1); } my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("port not specified"); usage(); } ypxfr_callback_addr.sin_port = htons((u_short)atoi(argv[my_optind])); ypxfr_args += 5; break; default: usage(); break; } } ypxfr_mapname = argv[ypxfr_args + 1]; if (ypxfr_mapname == NULL) { yp_error("no map name specified"); usage(); } /* Always the case. */ ypxfr_callback_addr.sin_family = AF_INET; /* Determine if local NIS client facilities are turned on. */ if (!yp_get_default_domain(&ypxfr_local_domain) && _yp_check(&ypxfr_local_domain)) ypxfr_use_yplib = 1; /* * If no destination domain is specified, assume that the * local default domain is to be used and try to obtain it. * Fails if NIS client facilities are turned off. */ if (ypxfr_dest_domain == NULL) { if (ypxfr_use_yplib) { yp_get_default_domain(&ypxfr_dest_domain); } else { yp_error("no destination domain specified and \ the local domain name isn't set"); ypxfr_exit(YPXFR_BADARGS,NULL); } } /* * If a source domain is not specified, assume it to * be the same as the destination domain. */ if (ypxfr_source_domain == NULL) { ypxfr_source_domain = ypxfr_dest_domain; } /* * If the source host is not specified, assume it to be the * master for the specified map. If local NIS client facilities * are turned on, we can figure this out using yp_master(). * If not, we have to see if a local copy of the map exists * and extract its YP_MASTER_NAME record. If _that_ fails, * we are stuck and must ask the user for more information. */ if (ypxfr_source_host == NULL) { if (!ypxfr_use_yplib) { /* * Double whammy: NIS isn't turned on and the user * didn't specify a source host. */ char *dptr; key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; if (yp_get_record(ypxfr_dest_domain, ypxfr_mapname, &key, &data, 1) != YP_TRUE) { yp_error("no source host specified"); ypxfr_exit(YPXFR_BADARGS,NULL); } dptr = data.data; dptr[data.size] = '\0'; ypxfr_master = ypxfr_source_host = strdup(dptr); } } else { if (ypxfr_use_yplib) ypxfr_use_yplib = 0; } if (ypxfr_master == NULL) { if ((ypxfr_master = ypxfr_get_master(ypxfr_source_domain, ypxfr_mapname, ypxfr_source_host, ypxfr_use_yplib)) == NULL) { yp_error("failed to find master of %s in domain %s: %s", ypxfr_mapname, ypxfr_source_domain, ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_MADDR,NULL); } } /* * If we got here and ypxfr_source_host is still undefined, * it means we had to resort to using yp_master() to find the * master server for the map. The source host and master should * be identical. */ if (ypxfr_source_host == NULL) ypxfr_source_host = ypxfr_master; /* * Don't talk to ypservs on unprivileged ports. */ remoteport = getrpcport(ypxfr_source_host, YPPROG, YPVERS, IPPROTO_UDP); if (remoteport >= IPPORT_RESERVED) { yp_error("ypserv on %s not running on reserved port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,NULL); } if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_INTERDOMAIN", sizeof("YP_INTERDOMAIN") - 1)) interdom++; if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_SECURE", sizeof("YP_SECURE") - 1)) secure++; key.data = "YP_LAST_MODIFIED"; key.size = sizeof("YP_LAST_MODIFIED") - 1; /* The order number is immaterial when the 'force' flag is set. */ if (!ypxfr_force) { int ignore = 0; if (yp_get_record(ypxfr_dest_domain,ypxfr_mapname,&key,&data,1) != YP_TRUE) { switch (yp_errno) { case YP_NOKEY: ypxfr_exit(YPXFR_FORCE,NULL); break; case YP_NOMAP: /* * If the map doesn't exist, we're * creating it. Ignore the error. */ ignore++; break; case YP_BADDB: default: ypxfr_exit(YPXFR_DBM,NULL); break; } } if (!ignore && ypxfr_order <= atoi(data.data)) ypxfr_exit(YPXFR_AGE, NULL); } /* Construct a temporary map file name */ snprintf(tempmap, sizeof(tempmap), "%s.%d",ypxfr_mapname, getpid()); snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir, ypxfr_dest_domain, tempmap); if ((remoteport = getrpcport(ypxfr_source_host, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, IPPROTO_TCP))) { /* Don't talk to rpc.ypxfrds on unprovileged ports. */ if (remoteport >= IPPORT_RESERVED) { yp_error("rpc.ypxfrd on %s not using privileged port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } /* Try to send using ypxfrd. If it fails, use old method. */ if (!ypxfrd_get_map(ypxfr_source_host, ypxfr_mapname, ypxfr_source_domain, ypxfr_temp_map)) goto leave; } /* Open the temporary map read/write. */ if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap, 0)) == NULL) { yp_error("failed to open temporary map file"); ypxfr_exit(YPXFR_DBM,NULL); } /* * Fill in the keys we already know, such as the order number, * master name, input file name (we actually make up a bogus * name for that) and output file name. */ snprintf(buf, sizeof(buf), "%lu", ypxfr_order); data.data = buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write order number to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; data.data = ypxfr_master; data.size = strlen(ypxfr_master); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write master name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } key.data = "YP_DOMAIN_NAME"; key.size = sizeof("YP_DOMAIN_NAME") - 1; data.data = ypxfr_dest_domain; data.size = strlen(ypxfr_dest_domain); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write domain name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } snprintf (buf, sizeof(buf), "%s:%s", ypxfr_source_host, ypxfr_mapname); key.data = "YP_INPUT_NAME"; key.size = sizeof("YP_INPUT_NAME") - 1; data.data = &buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write input name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, ypxfr_mapname); key.data = "YP_OUTPUT_NAME"; key.size = sizeof("YP_OUTPUT_NAME") - 1; data.data = &buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write output name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } if (interdom) { key.data = "YP_INTERDOMAIN"; key.size = sizeof("YP_INTERDOMAIN") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add interdomain flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } if (secure) { key.data = "YP_SECURE"; key.size = sizeof("YP_SECURE") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add secure flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } /* Now suck over the contents of the map from the master. */ if (ypxfr_get_map(ypxfr_mapname,ypxfr_source_domain, ypxfr_source_host, ypxfr_foreach)){ yp_error("failed to retrieve map from source host"); ypxfr_exit(YPXFR_YPERR,ypxfr_temp_map); } (void)(dbp->close)(dbp); dbp = NULL; /* <- yes, it seems this is necessary. */ leave: snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, ypxfr_mapname); /* Peek at the order number again and check for skew. */ if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,ypxfr_temp_map); } if (ypxfr_order != ypxfr_skew_check) ypxfr_exit(YPXFR_SKEW,ypxfr_temp_map); /* * Send a YPPROC_CLEAR to the local ypserv. */ if (ypxfr_clear) { char in = 0; char *out = NULL; int stat; if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, (xdrproc_t)xdr_void, (void *)&in, (xdrproc_t)xdr_void, (void *)out)) != RPC_SUCCESS) { yp_error("failed to send 'clear' to local ypserv: %s", clnt_sperrno((enum clnt_stat) stat)); ypxfr_exit(YPXFR_CLEAR, ypxfr_temp_map); } } /* * Put the new map in place immediately. I'm not sure if the * kernel does an unlink() and rename() atomically in the event * that we move a new copy of a map over the top of an existing * one, but there's less chance of a race condition happening * than if we were to do the unlink() ourselves. */ if (rename(ypxfr_temp_map, buf) == -1) { yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf, strerror(errno)); ypxfr_exit(YPXFR_FILE,NULL); } ypxfr_exit(YPXFR_SUCC,NULL); return(1); } Index: head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c =================================================================== --- head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c (revision 359676) +++ head/usr.sbin/rpc.yppasswdd/yppasswdd_main.c (revision 359677) @@ -1,354 +1,353 @@ /* * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995, 1996 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* getenv, exit */ #include /* strcmp */ #include #include #include #include #include /* for pmap_unset */ #include #include #include "yppasswd.h" #include "yppasswdd_extern.h" #include "yppasswd_private.h" #include "ypxfr_extern.h" #include "yp_extern.h" #ifndef SIG_PF #define SIG_PF void(*)(int) #endif #ifdef DEBUG #define RPC_SVC_FG #endif #define _RPCSVC_CLOSEDOWN 120 int _rpcpmstart = 0; /* Started by a port monitor ? */ static int _rpcfdtype; /* Whether Stream or Datagram ? */ /* States a server can be in wrt request */ #define _IDLE 0 #define _SERVED 1 #define _SERVING 2 +int debug; static char _localhost[] = "localhost"; static char _passwd_byname[] = "passwd.byname"; extern int _rpcsvcstate; /* Set when a request is serviced */ static char _progname[] = "rpc.yppasswdd"; char *progname = _progname; static char _yp_dir[] = _PATH_YP; char *yp_dir = _yp_dir; static char _passfile_default[] = _PATH_YP "master.passwd"; char *passfile_default = _passfile_default; char *passfile; char *yppasswd_domain = NULL; int no_chsh = 0; int no_chfn = 0; int allow_additions = 0; int multidomain = 0; int verbose = 0; int resvport = 1; int inplace = 0; char sockname[] = YP_SOCKNAME; static void terminate(int sig __unused) { rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); unlink(sockname); exit(0); } static void reload(int sig __unused) { load_securenets(); } static void closedown(int sig __unused) { if (_rpcsvcstate == _IDLE) { extern fd_set svc_fdset; static int size; int i, openfd; if (_rpcfdtype == SOCK_DGRAM) { unlink(sockname); exit(0); } if (size == 0) { size = getdtablesize(); } for (i = 0, openfd = 0; i < size && openfd < 2; i++) if (FD_ISSET(i, &svc_fdset)) openfd++; if (openfd <= 1) { unlink(sockname); exit(0); } } if (_rpcsvcstate == _SERVED) _rpcsvcstate = _IDLE; (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: rpc.yppasswdd [-t master.passwd file] [-d domain] [-p path] [-s]", " [-f] [-m] [-i] [-a] [-v] [-u] [-h]"); exit(1); } int main(int argc, char *argv[]) { struct rlimit rlim; SVCXPRT *transp = NULL; struct sockaddr_in saddr; socklen_t asize = sizeof (saddr); struct netconfig *nconf; struct sigaction sa; void *localhandle; int ch; char *mastername; char myname[MAXHOSTNAMELEN + 2]; int maxrec = RPC_MAXDATASIZE; - - extern int debug; debug = 1; while ((ch = getopt(argc, argv, "t:d:p:sfamuivh")) != -1) { switch (ch) { case 't': passfile_default = optarg; break; case 'd': yppasswd_domain = optarg; break; case 's': no_chsh++; break; case 'f': no_chfn++; break; case 'p': yp_dir = optarg; break; case 'a': allow_additions++; break; case 'm': multidomain++; break; case 'i': inplace++; break; case 'v': verbose++; break; case 'u': resvport = 0; break; default: case 'h': usage(); break; } } if (yppasswd_domain == NULL) { if (yp_get_default_domain(&yppasswd_domain)) { yp_error("no domain specified and system domain \ name isn't set -- aborting"); usage(); } } load_securenets(); if (getrpcport(_localhost, YPPROG, YPVERS, IPPROTO_UDP) <= 0) { yp_error("no ypserv processes registered with local portmap"); yp_error("this host is not an NIS server -- aborting"); exit(1); } if ((mastername = ypxfr_get_master(yppasswd_domain, _passwd_byname, _localhost, 0)) == NULL) { yp_error("can't get name of NIS master server for domain %s", yppasswd_domain); exit(1); } if (gethostname((char *)&myname, sizeof(myname)) == -1) { yp_error("can't get local hostname: %s", strerror(errno)); exit(1); } if (strncasecmp(mastername, (char *)&myname, sizeof(myname))) { yp_error("master of %s is %s, but we are %s", "passwd.byname", mastername, myname); yp_error("this host is not the NIS master server for \ the %s domain -- aborting", yppasswd_domain); exit(1); } debug = 0; if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { socklen_t ssize = sizeof (int); if (saddr.sin_family != AF_INET) exit(1); if (getsockopt(0, SOL_SOCKET, SO_TYPE, (char *)&_rpcfdtype, &ssize) == -1) exit(1); _rpcpmstart = 1; } if (!debug && _rpcpmstart == 0) { if (daemon(0,0)) { err(1,"cannot fork"); } } openlog("rpc.yppasswdd", LOG_PID, LOG_DAEMON); memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDWAIT; sigaction(SIGCHLD, &sa, NULL); rpcb_unset(YPPASSWDPROG, YPPASSWDVERS, NULL); rpcb_unset(MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, NULL); rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); if (svc_create(yppasswdprog_1, YPPASSWDPROG, YPPASSWDVERS, "netpath") == 0) { yp_error("cannot create yppasswd service."); exit(1); } if (svc_create(master_yppasswdprog_1, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, "netpath") == 0) { yp_error("cannot create master_yppasswd service."); exit(1); } nconf = NULL; localhandle = setnetconfig(); while ((nconf = getnetconfig(localhandle)) != NULL) { if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) break; } if (nconf == NULL) { yp_error("getnetconfigent unix: %s", nc_sperror()); exit(1); } unlink(sockname); transp = svcunix_create(RPC_ANYSOCK, 0, 0, sockname); if (transp == NULL) { yp_error("cannot create AF_LOCAL service."); exit(1); } if (!svc_reg(transp, MASTER_YPPASSWDPROG, MASTER_YPPASSWDVERS, master_yppasswdprog_1, nconf)) { yp_error("unable to register (MASTER_YPPASSWDPROG, \ MASTER_YPPASSWDVERS, unix)."); exit(1); } endnetconfig(localhandle); /* Only root may connect() to the AF_UNIX link. */ if (chmod(sockname, 0)) err(1, "chmod of %s failed", sockname); if (transp == (SVCXPRT *)NULL) { yp_error("could not create a handle"); exit(1); } if (_rpcpmstart) { (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } /* Unlimited resource limits. */ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &rlim); (void)setrlimit(RLIMIT_FSIZE, &rlim); (void)setrlimit(RLIMIT_STACK, &rlim); (void)setrlimit(RLIMIT_DATA, &rlim); (void)setrlimit(RLIMIT_RSS, &rlim); /* Don't drop core (not really necessary, but GP's). */ rlim.rlim_cur = rlim.rlim_max = 0; (void)setrlimit(RLIMIT_CORE, &rlim); /* Turn off signals. */ (void)signal(SIGALRM, SIG_IGN); (void)signal(SIGHUP, (SIG_PF) reload); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGPIPE, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTERM, (SIG_PF) terminate); svc_run(); yp_error("svc_run returned"); exit(1); /* NOTREACHED */ } Index: head/usr.sbin/rpc.ypupdated/ypupdated_main.c =================================================================== --- head/usr.sbin/rpc.ypupdated/ypupdated_main.c (revision 359676) +++ head/usr.sbin/rpc.ypupdated/ypupdated_main.c (revision 359677) @@ -1,287 +1,289 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995, 1996 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "ypupdate_prot.h" #include #include /* getenv, exit */ #include /* for pmap_unset */ #include #include /* strcmp */ #include #ifdef __cplusplus #include /* getdtablesize, open */ #endif /* __cplusplus */ #include #include #include #include #include #include #include #include #include "ypupdated_extern.h" #include "yp_extern.h" #ifndef SIG_PF #define SIG_PF void(*)(int) #endif #ifdef DEBUG #define RPC_SVC_FG #endif #define _RPCSVC_CLOSEDOWN 120 int _rpcpmstart; /* Started by a port monitor ? */ static int _rpcfdtype; /* Whether Stream or Datagram ? */ /* States a server can be in wrt request */ #define _IDLE 0 #define _SERVED 1 #define _SERVING 2 extern int _rpcsvcstate; /* Set when a request is serviced */ +int debug; + char *progname = "rpc.ypupdated"; char *yp_dir = "/var/yp/"; static void _msgout(char* msg) { #ifdef RPC_SVC_FG if (_rpcpmstart) syslog(LOG_ERR, "%s", msg); else warnx("%s", msg); #else syslog(LOG_ERR, "%s", msg); #endif } static void closedown(int sig) { if (_rpcsvcstate == _IDLE) { extern fd_set svc_fdset; static int size; int i, openfd; if (_rpcfdtype == SOCK_DGRAM) exit(0); if (size == 0) { size = getdtablesize(); } for (i = 0, openfd = 0; i < size && openfd < 2; i++) if (FD_ISSET(i, &svc_fdset)) openfd++; if (openfd <= 1) exit(0); } if (_rpcsvcstate == _SERVED) _rpcsvcstate = _IDLE; (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } static void ypupdated_svc_run(void) { #ifdef FD_SETSIZE fd_set readfds; #else int readfds; #endif /* def FD_SETSIZE */ extern int forked; int pid; int fd_setsize = _rpc_dtablesize(); /* Establish the identity of the parent ypupdated process. */ pid = getpid(); for (;;) { #ifdef FD_SETSIZE readfds = svc_fdset; #else readfds = svc_fds; #endif /* def FD_SETSIZE */ switch (select(fd_setsize, &readfds, NULL, NULL, (struct timeval *)0)) { case -1: if (errno == EINTR) { continue; } warn("svc_run: - select failed"); return; case 0: continue; default: svc_getreqset(&readfds); if (forked && pid != getpid()) exit(0); } } } static void reaper(int sig) { int status; if (sig == SIGHUP) { #ifdef foo load_securenets(); #endif return; } if (sig == SIGCHLD) { while (wait3(&status, WNOHANG, NULL) > 0) children--; } else { (void) pmap_unset(YPU_PROG, YPU_VERS); exit(0); } } void usage(void) { fprintf(stderr, "rpc.ypupdatedd [-p path]\n"); exit(0); } int main(int argc, char *argv[]) { register SVCXPRT *transp = NULL; int sock; int proto = 0; struct sockaddr_in saddr; int asize = sizeof (saddr); int ch; while ((ch = getopt(argc, argv, "p:h")) != -1) { switch (ch) { case 'p': yp_dir = optarg; break; default: usage(); break; } } #ifdef foo load_securenets(); #endif if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1) { yp_error("failed to register AUTH_DES flavor"); exit(1); } if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { int ssize = sizeof (int); if (saddr.sin_family != AF_INET) exit(1); if (getsockopt(0, SOL_SOCKET, SO_TYPE, (char *)&_rpcfdtype, &ssize) == -1) exit(1); sock = 0; _rpcpmstart = 1; proto = 0; openlog("rpc.ypupdatedd", LOG_PID, LOG_DAEMON); } else { #ifndef RPC_SVC_FG if (daemon(0,0)) { err(1, "cannot fork"); } openlog("rpc.ypupdated", LOG_PID, LOG_DAEMON); #endif sock = RPC_ANYSOCK; (void) pmap_unset(YPU_PROG, YPU_VERS); } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { transp = svcudp_create(sock); if (transp == NULL) { _msgout("cannot create udp service."); exit(1); } if (!_rpcpmstart) proto = IPPROTO_UDP; if (!svc_register(transp, YPU_PROG, YPU_VERS, ypu_prog_1, proto)) { _msgout("unable to register (YPU_PROG, YPU_VERS, udp)."); exit(1); } } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { transp = svctcp_create(sock, 0, 0); if (transp == NULL) { _msgout("cannot create tcp service."); exit(1); } if (!_rpcpmstart) proto = IPPROTO_TCP; if (!svc_register(transp, YPU_PROG, YPU_VERS, ypu_prog_1, proto)) { _msgout("unable to register (YPU_PROG, YPU_VERS, tcp)."); exit(1); } } if (transp == (SVCXPRT *)NULL) { _msgout("could not create a handle"); exit(1); } if (_rpcpmstart) { (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } (void) signal(SIGPIPE, SIG_IGN); (void) signal(SIGCHLD, (SIG_PF) reaper); (void) signal(SIGTERM, (SIG_PF) reaper); (void) signal(SIGINT, (SIG_PF) reaper); (void) signal(SIGHUP, (SIG_PF) reaper); ypupdated_svc_run(); _msgout("svc_run returned"); exit(1); /* NOTREACHED */ } Index: head/usr.sbin/rpc.ypxfrd/ypxfrd_main.c =================================================================== --- head/usr.sbin/rpc.ypxfrd/ypxfrd_main.c (revision 359676) +++ head/usr.sbin/rpc.ypxfrd/ypxfrd_main.c (revision 359677) @@ -1,304 +1,306 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995, 1996 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "ypxfrd.h" #include #include #include #include #include /* getenv, exit */ #include #include /* for pmap_unset */ #include #include /* strcmp */ #include #include /* TIOCNOTTY */ #ifdef __cplusplus #include /* getdtablesize, open */ #endif /* __cplusplus */ #include #include #include #include #include "ypxfrd_extern.h" #include #include #ifndef SIG_PF #define SIG_PF void(*)(int) #endif #ifdef DEBUG #define RPC_SVC_FG #endif #define _RPCSVC_CLOSEDOWN 120 int _rpcpmstart; /* Started by a port monitor ? */ static int _rpcfdtype; /* Whether Stream or Datagram ? */ /* States a server can be in wrt request */ #define _IDLE 0 #define _SERVED 1 #define _SERVING 2 extern int _rpcsvcstate; /* Set when a request is serviced */ +int debug; + char *progname = "rpc.ypxfrd"; char *yp_dir = "/var/yp/"; static void _msgout(char *msg) { #ifdef RPC_SVC_FG if (_rpcpmstart) syslog(LOG_ERR, "%s", msg); else warnx("%s", msg); #else syslog(LOG_ERR, "%s", msg); #endif } static void closedown(int sig) { if (_rpcsvcstate == _IDLE) { extern fd_set svc_fdset; static int size; int i, openfd; if (_rpcfdtype == SOCK_DGRAM) exit(0); if (size == 0) { size = getdtablesize(); } for (i = 0, openfd = 0; i < size && openfd < 2; i++) if (FD_ISSET(i, &svc_fdset)) openfd++; if (openfd <= 1) exit(0); } if (_rpcsvcstate == _SERVED) _rpcsvcstate = _IDLE; (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } static void ypxfrd_svc_run(void) { #ifdef FD_SETSIZE fd_set readfds; #else int readfds; #endif /* def FD_SETSIZE */ extern int forked; int pid; int fd_setsize = _rpc_dtablesize(); /* Establish the identity of the parent ypserv process. */ pid = getpid(); for (;;) { #ifdef FD_SETSIZE readfds = svc_fdset; #else readfds = svc_fds; #endif /* def FD_SETSIZE */ switch (select(fd_setsize, &readfds, NULL, NULL, (struct timeval *)0)) { case -1: if (errno == EINTR) { continue; } warn("svc_run: - select failed"); return; case 0: continue; default: svc_getreqset(&readfds); if (forked && pid != getpid()) exit(0); } } } static void reaper(int sig) { int status; int saved_errno; saved_errno = errno; if (sig == SIGHUP) { load_securenets(); errno = saved_errno; return; } if (sig == SIGCHLD) { while (wait3(&status, WNOHANG, NULL) > 0) children--; } else { (void) pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS); exit(0); } errno = saved_errno; return; } void usage(void) { fprintf(stderr, "usage: rpc.ypxfrd [-p path]\n"); exit(0); } int main(int argc, char *argv[]) { register SVCXPRT *transp = NULL; int sock; int proto = 0; struct sockaddr_in saddr; int asize = sizeof (saddr); int ch; while ((ch = getopt(argc, argv, "p:h")) != -1) { switch (ch) { case 'p': yp_dir = optarg; break; default: usage(); break; } } load_securenets(); if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { int ssize = sizeof (int); if (saddr.sin_family != AF_INET) exit(1); if (getsockopt(0, SOL_SOCKET, SO_TYPE, (char *)&_rpcfdtype, &ssize) == -1) exit(1); sock = 0; _rpcpmstart = 1; proto = 0; openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON); } else { #ifndef RPC_SVC_FG int size; int pid, i; pid = fork(); if (pid < 0) err(1, "fork"); if (pid) exit(0); size = getdtablesize(); for (i = 0; i < size; i++) (void) close(i); i = open(_PATH_CONSOLE, 2); (void) dup2(i, 1); (void) dup2(i, 2); i = open(_PATH_TTY, 2); if (i >= 0) { (void) ioctl(i, TIOCNOTTY, (char *)NULL); (void) close(i); } openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON); #endif sock = RPC_ANYSOCK; (void) pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS); } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { transp = svcudp_create(sock); if (transp == NULL) { _msgout("cannot create udp service."); exit(1); } if (!_rpcpmstart) proto = IPPROTO_UDP; if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) { _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, udp)."); exit(1); } } if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { transp = svctcp_create(sock, 0, 0); if (transp == NULL) { _msgout("cannot create tcp service."); exit(1); } if (!_rpcpmstart) proto = IPPROTO_TCP; if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) { _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, tcp)."); exit(1); } } if (transp == (SVCXPRT *)NULL) { _msgout("could not create a handle"); exit(1); } if (_rpcpmstart) { (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } (void) signal(SIGPIPE, SIG_IGN); (void) signal(SIGCHLD, (SIG_PF) reaper); (void) signal(SIGTERM, (SIG_PF) reaper); (void) signal(SIGINT, (SIG_PF) reaper); (void) signal(SIGHUP, (SIG_PF) reaper); ypxfrd_svc_run(); _msgout("svc_run returned"); exit(1); /* NOTREACHED */ } Index: head/usr.sbin/ypldap/ypldap.c =================================================================== --- head/usr.sbin/ypldap/ypldap.c (revision 359676) +++ head/usr.sbin/ypldap/ypldap.c (revision 359677) @@ -1,650 +1,652 @@ /* $OpenBSD: ypldap.c,v 1.16 2015/11/02 10:06:06 jmatthew Exp $ */ /* $FreeBSD */ /* * Copyright (c) 2008 Pierre-Yves Ritschard * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ypldap.h" +enum ypldap_process_type ypldap_process; + __dead2 void usage(void); int check_child(pid_t, const char *); void main_sig_handler(int, short, void *); void main_shutdown(void); void main_dispatch_client(int, short, void *); void main_configure_client(struct env *); void main_init_timer(int, short, void *); void main_start_update(struct env *); void main_trash_update(struct env *); void main_end_update(struct env *); int main_create_user_groups(struct env *); void purge_config(struct env *); void reconfigure(struct env *); int pipe_main2client[2]; pid_t client_pid = 0; char *conffile = YPLDAP_CONF_FILE; int opts = 0; void usage(void) { extern const char *__progname; fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n", __progname); exit(1); } int check_child(pid_t pid, const char *pname) { int status; if (waitpid(pid, &status, WNOHANG) > 0) { if (WIFEXITED(status)) { log_warnx("check_child: lost child %s exited", pname); return (1); } if (WIFSIGNALED(status)) { log_warnx("check_child: lost child %s terminated; " "signal %d", pname, WTERMSIG(status)); return (1); } } return (0); } /* ARGUSED */ void main_sig_handler(int sig, short event, void *p) { int die = 0; switch (sig) { case SIGTERM: case SIGINT: die = 1; /* FALLTHROUGH */ case SIGCHLD: if (check_child(client_pid, "ldap client")) { client_pid = 0; die = 1; } if (die) main_shutdown(); break; case SIGHUP: /* reconfigure */ break; default: fatalx("unexpected signal"); } } void main_shutdown(void) { _exit(0); } void main_start_update(struct env *env) { env->update_trashed = 0; log_debug("starting directory update"); env->sc_user_line_len = 0; env->sc_group_line_len = 0; if ((env->sc_user_names_t = calloc(1, sizeof(*env->sc_user_names_t))) == NULL || (env->sc_group_names_t = calloc(1, sizeof(*env->sc_group_names_t))) == NULL) fatal(NULL); RB_INIT(env->sc_user_names_t); RB_INIT(env->sc_group_names_t); } /* * XXX: Currently this function should only be called when updating is * finished. A notification should be send to ldapclient that it should stop * sending new pwd/grp entries before it can be called from different places. */ void main_trash_update(struct env *env) { struct userent *ue; struct groupent *ge; env->update_trashed = 1; while ((ue = RB_ROOT(env->sc_user_names_t)) != NULL) { RB_REMOVE(user_name_tree, env->sc_user_names_t, ue); free(ue->ue_line); free(ue->ue_netid_line); free(ue); } free(env->sc_user_names_t); env->sc_user_names_t = NULL; while ((ge = RB_ROOT(env->sc_group_names_t)) != NULL) { RB_REMOVE(group_name_tree, env->sc_group_names_t, ge); free(ge->ge_line); free(ge); } free(env->sc_group_names_t); env->sc_group_names_t = NULL; } int main_create_user_groups(struct env *env) { struct userent *ue; struct userent ukey; struct groupent *ge; gid_t pw_gid; char *bp, *cp; char *p; const char *errstr = NULL; size_t len; RB_FOREACH(ue, user_name_tree, env->sc_user_names_t) { bp = cp = ue->ue_line; /* name */ bp += strlen(bp) + 1; /* password */ bp += strcspn(bp, ":") + 1; /* uid */ bp += strcspn(bp, ":") + 1; /* gid */ bp[strcspn(bp, ":")] = '\0'; pw_gid = (gid_t)strtonum(bp, 0, GID_MAX, &errstr); if (errstr) { log_warnx("main: failed to parse gid for uid: %d\n", ue->ue_uid); return (-1); } /* bring gid column back to its proper state */ bp[strlen(bp)] = ':'; if ((ue->ue_netid_line = calloc(1, LINE_WIDTH)) == NULL) { return (-1); } if (snprintf(ue->ue_netid_line, LINE_WIDTH-1, "%d:%d", ue->ue_uid, pw_gid) >= LINE_WIDTH) { return (-1); } ue->ue_gid = pw_gid; } RB_FOREACH(ge, group_name_tree, env->sc_group_names_t) { bp = cp = ge->ge_line; /* name */ bp += strlen(bp) + 1; /* password */ bp += strcspn(bp, ":") + 1; /* gid */ bp += strcspn(bp, ":") + 1; cp = bp; if (*bp == '\0') continue; bp = cp; for (;;) { if (!(cp = strsep(&bp, ","))) break; ukey.ue_line = cp; if ((ue = RB_FIND(user_name_tree, env->sc_user_names_t, &ukey)) == NULL) { /* User not found */ log_warnx("main: unknown user %s in group %s\n", ukey.ue_line, ge->ge_line); if (bp != NULL) *(bp-1) = ','; continue; } if (bp != NULL) *(bp-1) = ','; /* Make sure the new group doesn't equal to the main gid */ if (ge->ge_gid == ue->ue_gid) continue; len = strlen(ue->ue_netid_line); p = ue->ue_netid_line + len; if ((snprintf(p, LINE_WIDTH-len-1, ",%d", ge->ge_gid)) >= (int)(LINE_WIDTH-len)) { return (-1); } } } return (0); } void main_end_update(struct env *env) { struct userent *ue; struct groupent *ge; if (env->update_trashed) return; log_debug("updates are over, cleaning up trees now"); if (main_create_user_groups(env) == -1) { main_trash_update(env); return; } if (env->sc_user_names == NULL) { env->sc_user_names = env->sc_user_names_t; env->sc_user_lines = NULL; env->sc_user_names_t = NULL; env->sc_group_names = env->sc_group_names_t; env->sc_group_lines = NULL; env->sc_group_names_t = NULL; flatten_entries(env); goto make_uids; } /* * clean previous tree. */ while ((ue = RB_ROOT(env->sc_user_names)) != NULL) { RB_REMOVE(user_name_tree, env->sc_user_names, ue); free(ue->ue_netid_line); free(ue); } free(env->sc_user_names); free(env->sc_user_lines); env->sc_user_names = env->sc_user_names_t; env->sc_user_lines = NULL; env->sc_user_names_t = NULL; while ((ge = RB_ROOT(env->sc_group_names)) != NULL) { RB_REMOVE(group_name_tree, env->sc_group_names, ge); free(ge); } free(env->sc_group_names); free(env->sc_group_lines); env->sc_group_names = env->sc_group_names_t; env->sc_group_lines = NULL; env->sc_group_names_t = NULL; flatten_entries(env); /* * trees are flat now. build up uid, gid and netid trees. */ make_uids: RB_INIT(&env->sc_user_uids); RB_INIT(&env->sc_group_gids); RB_FOREACH(ue, user_name_tree, env->sc_user_names) RB_INSERT(user_uid_tree, &env->sc_user_uids, ue); RB_FOREACH(ge, group_name_tree, env->sc_group_names) RB_INSERT(group_gid_tree, &env->sc_group_gids, ge); } void main_dispatch_client(int fd, short events, void *p) { int n; int shut = 0; struct env *env = p; struct imsgev *iev = env->sc_iev; struct imsgbuf *ibuf = &iev->ibuf; struct idm_req ir; struct imsg imsg; if ((events & (EV_READ | EV_WRITE)) == 0) fatalx("unknown event"); if (events & EV_READ) { if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) fatal("imsg_read error"); if (n == 0) shut = 1; } if (events & EV_WRITE) { if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) fatal("msgbuf_write"); if (n == 0) shut = 1; goto done; } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("main_dispatch_client: imsg_get error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_START_UPDATE: main_start_update(env); break; case IMSG_PW_ENTRY: { struct userent *ue; size_t len; if (env->update_trashed) break; (void)memcpy(&ir, imsg.data, sizeof(ir)); if ((ue = calloc(1, sizeof(*ue))) == NULL || (ue->ue_line = strdup(ir.ir_line)) == NULL) { /* * should cancel tree update instead. */ fatal("out of memory"); } ue->ue_uid = ir.ir_key.ik_uid; len = strlen(ue->ue_line) + 1; ue->ue_line[strcspn(ue->ue_line, ":")] = '\0'; if (RB_INSERT(user_name_tree, env->sc_user_names_t, ue) != NULL) { /* dup */ free(ue->ue_line); free(ue); } else env->sc_user_line_len += len; break; } case IMSG_GRP_ENTRY: { struct groupent *ge; size_t len; if (env->update_trashed) break; (void)memcpy(&ir, imsg.data, sizeof(ir)); if ((ge = calloc(1, sizeof(*ge))) == NULL || (ge->ge_line = strdup(ir.ir_line)) == NULL) { /* * should cancel tree update instead. */ fatal("out of memory"); } ge->ge_gid = ir.ir_key.ik_gid; len = strlen(ge->ge_line) + 1; ge->ge_line[strcspn(ge->ge_line, ":")] = '\0'; if (RB_INSERT(group_name_tree, env->sc_group_names_t, ge) != NULL) { /* dup */ free(ge->ge_line); free(ge); } else env->sc_group_line_len += len; break; } case IMSG_TRASH_UPDATE: main_trash_update(env); break; case IMSG_END_UPDATE: { main_end_update(env); break; } default: log_debug("main_dispatch_client: unexpected imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } done: if (!shut) imsg_event_add(iev); else { log_debug("king bula sez: ran into dead pipe"); event_del(&iev->ev); event_loopexit(NULL); } } void main_configure_client(struct env *env) { struct idm *idm; struct imsgev *iev = env->sc_iev; imsg_compose_event(iev, IMSG_CONF_START, 0, 0, -1, env, sizeof(*env)); TAILQ_FOREACH(idm, &env->sc_idms, idm_entry) { imsg_compose_event(iev, IMSG_CONF_IDM, 0, 0, -1, idm, sizeof(*idm)); } imsg_compose_event(iev, IMSG_CONF_END, 0, 0, -1, NULL, 0); } void main_init_timer(int fd, short event, void *p) { struct env *env = p; main_configure_client(env); } void purge_config(struct env *env) { struct idm *idm; while ((idm = TAILQ_FIRST(&env->sc_idms)) != NULL) { TAILQ_REMOVE(&env->sc_idms, idm, idm_entry); free(idm); } } int main(int argc, char *argv[]) { int c; int debug; struct passwd *pw; struct env env; struct event ev_sigint; struct event ev_sigterm; struct event ev_sigchld; struct event ev_sighup; struct event ev_timer; struct timeval tv; debug = 0; ypldap_process = PROC_MAIN; log_init(1); while ((c = getopt(argc, argv, "dD:nf:v")) != -1) { switch (c) { case 'd': debug = 2; break; case 'D': if (cmdline_symset(optarg) < 0) log_warnx("could not parse macro definition %s", optarg); break; case 'n': debug = 2; opts |= YPLDAP_OPT_NOACTION; break; case 'f': conffile = optarg; break; case 'v': opts |= YPLDAP_OPT_VERBOSE; break; default: usage(); } } argc -= optind; argv += optind; if (argc) usage(); RB_INIT(&env.sc_user_uids); RB_INIT(&env.sc_group_gids); if (parse_config(&env, conffile, opts)) exit(1); if (opts & YPLDAP_OPT_NOACTION) { fprintf(stderr, "configuration OK\n"); exit(0); } if (geteuid()) errx(1, "need root privileges"); log_init(debug); if (!debug) { if (daemon(1, 0) == -1) err(1, "failed to daemonize"); } log_info("startup%s", (debug > 1)?" [debug mode]":""); if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC, pipe_main2client) == -1) fatal("socketpair"); client_pid = ldapclient(pipe_main2client); setproctitle("parent"); event_init(); signal_set(&ev_sigint, SIGINT, main_sig_handler, &env); signal_set(&ev_sigterm, SIGTERM, main_sig_handler, &env); signal_set(&ev_sighup, SIGHUP, main_sig_handler, &env); signal_set(&ev_sigchld, SIGCHLD, main_sig_handler, &env); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal_add(&ev_sighup, NULL); signal_add(&ev_sigchld, NULL); close(pipe_main2client[1]); if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL) fatal(NULL); imsg_init(&env.sc_iev->ibuf, pipe_main2client[0]); env.sc_iev->handler = main_dispatch_client; env.sc_iev->events = EV_READ; env.sc_iev->data = &env; event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events, env.sc_iev->handler, &env); event_add(&env.sc_iev->ev, NULL); yp_init(&env); if ((pw = getpwnam(YPLDAP_USER)) == NULL) fatal("getpwnam"); #ifndef DEBUG if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("cannot drop privileges"); #else #warning disabling privilege revocation in debug mode #endif memset(&tv, 0, sizeof(tv)); evtimer_set(&ev_timer, main_init_timer, &env); evtimer_add(&ev_timer, &tv); yp_enable_events(); event_dispatch(); main_shutdown(); return (0); } void imsg_event_add(struct imsgev *iev) { if (iev->handler == NULL) { imsg_flush(&iev->ibuf); return; } iev->events = EV_READ; if (iev->ibuf.w.queued) iev->events |= EV_WRITE; event_del(&iev->ev); event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data); event_add(&iev->ev, NULL); } int imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) { int ret; if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, datalen)) != -1) imsg_event_add(iev); return (ret); } Index: head/usr.sbin/ypldap/ypldap.h =================================================================== --- head/usr.sbin/ypldap/ypldap.h (revision 359676) +++ head/usr.sbin/ypldap/ypldap.h (revision 359677) @@ -1,223 +1,224 @@ /* $OpenBSD: ypldap.h,v 1.16 2015/01/16 06:40:22 deraadt Exp $ */ /* $FreeBSD$ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #define YPLDAP_USER "_ypldap" #define YPLDAP_CONF_FILE "/etc/ypldap.conf" #define DEFAULT_INTERVAL 600 #define LINE_WIDTH 1024 #define FILTER_WIDTH 128 #define ATTR_WIDTH 32 #define MAX_SERVERS_DNS 8 enum imsg_type { IMSG_NONE, IMSG_CONF_START, IMSG_CONF_IDM, IMSG_CONF_END, IMSG_START_UPDATE, IMSG_END_UPDATE, IMSG_TRASH_UPDATE, IMSG_PW_ENTRY, IMSG_GRP_ENTRY, IMSG_HOST_DNS }; struct ypldap_addr { TAILQ_ENTRY(ypldap_addr) next; struct sockaddr_storage ss; }; TAILQ_HEAD(ypldap_addr_list, ypldap_addr); -enum { +enum ypldap_process_type { PROC_MAIN, PROC_CLIENT -} ypldap_process; +}; +extern enum ypldap_process_type ypldap_process; struct userent { RB_ENTRY(userent) ue_name_node; RB_ENTRY(userent) ue_uid_node; uid_t ue_uid; char *ue_line; char *ue_netid_line; gid_t ue_gid; }; struct groupent { RB_ENTRY(groupent) ge_name_node; RB_ENTRY(groupent) ge_gid_node; gid_t ge_gid; char *ge_line; }; enum client_state { STATE_NONE, STATE_DNS_INPROGRESS, STATE_DNS_TEMPFAIL, STATE_DNS_DONE, STATE_LDAP_FAIL, STATE_LDAP_DONE }; /* * beck, djm, dlg: pay attention to the struct name */ struct idm { TAILQ_ENTRY(idm) idm_entry; u_int32_t idm_id; char idm_name[MAXHOSTNAMELEN]; #define F_SSL 0x00100000 #define F_CONFIGURING 0x00200000 #define F_NEEDAUTH 0x00400000 #define F_FIXED_ATTR(n) (1<. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "yp_extern.h" #ifdef TCP_WRAPPER #include "tcpd.h" #endif -extern int debug; - static const char *yp_procs[] = { /* NIS v1 */ "ypoldproc_null", "ypoldproc_domain", "ypoldproc_domain_nonack", "ypoldproc_match", "ypoldproc_first", "ypoldproc_next", "ypoldproc_poll", "ypoldproc_push", "ypoldproc_get", "badproc1", /* placeholder */ "badproc2", /* placeholder */ "badproc3", /* placeholder */ /* NIS v2 */ "ypproc_null", "ypproc_domain", "ypproc_domain_nonack", "ypproc_match", "ypproc_first", "ypproc_next", "ypproc_xfr", "ypproc_clear", "ypproc_all", "ypproc_master", "ypproc_order", "ypproc_maplist" }; struct securenet { struct in_addr net; struct in_addr mask; struct securenet *next; }; static struct securenet *securenets; #define LINEBUFSZ 1024 #ifdef TCP_WRAPPER int hosts_ctl(char *, char *, char *, char *); #endif /* * Read /var/yp/securenets file and initialize the securenets * list. If the file doesn't exist, we set up a dummy entry that * allows all hosts to connect. */ void load_securenets(void) { FILE *fp; char path[MAXPATHLEN + 2]; char linebuf[1024 + 2]; struct securenet *tmp; /* * If securenets is not NULL, we are being called to reload * the list; free the existing list before re-reading the * securenets file. */ while (securenets) { tmp = securenets->next; free(securenets); securenets = tmp; } snprintf(path, MAXPATHLEN, "%s/securenets", yp_dir); if ((fp = fopen(path, "r")) == NULL) { if (errno == ENOENT) { securenets = malloc(sizeof(struct securenet)); securenets->net.s_addr = INADDR_ANY; securenets->mask.s_addr = INADDR_ANY; securenets->next = NULL; return; } else { yp_error("fopen(%s) failed: %s", path, strerror(errno)); exit(1); } } securenets = NULL; while (fgets(linebuf, LINEBUFSZ, fp)) { char addr1[20], addr2[20]; if ((linebuf[0] == '#') || (strspn(linebuf, " \t\r\n") == strlen(linebuf))) continue; if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) { yp_error("badly formatted securenets entry: %s", linebuf); continue; } tmp = malloc(sizeof(struct securenet)); if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) { yp_error("badly formatted securenets entry: %s", addr1); free(tmp); continue; } if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) { yp_error("badly formatted securenets entry: %s", addr2); free(tmp); continue; } tmp->next = securenets; securenets = tmp; } fclose(fp); } /* * Access control functions. * * yp_access() checks the mapname and client host address and watches for * the following things: * * - If the client is referencing one of the master.passwd.* or shadow.* maps, * it must be using a privileged port to make its RPC to us. If it is, then * we can assume that the caller is root and allow the RPC to succeed. If it * isn't access is denied. * * - The client's IP address is checked against the securenets rules. * There are two kinds of securenets support: the built-in support, * which is very simple and depends on the presence of a * /var/yp/securenets file, and tcp-wrapper support, which requires * Wietse Venema's libwrap.a and tcpd.h. (Since the tcp-wrapper * package does not ship with FreeBSD, we use the built-in support * by default. Users can recompile the server with the tcp-wrapper library * if they already have it installed and want to use hosts.allow and * hosts.deny to control access instead of having a separate securenets * file.) * * If no /var/yp/securenets file is present, the host access checks * are bypassed and all hosts are allowed to connect. * * The yp_validdomain() function checks the domain specified by the caller * to make sure it's actually served by this server. This is more a sanity * check than an a security check, but this seems to be the best place for * it. */ #ifdef DB_CACHE int yp_access(const char *map, const char *domain, const struct svc_req *rqstp) #else int yp_access(const char *map, const struct svc_req *rqstp) #endif { struct sockaddr_in *rqhost; int status_securenets = 0; #ifdef TCP_WRAPPER int status_tcpwrap; #endif static unsigned long oldaddr = 0; struct securenet *tmp; const char *yp_procedure = NULL; char procbuf[50]; if (rqstp->rq_prog != YPPASSWDPROG && rqstp->rq_prog != YPPROG) { snprintf(procbuf, sizeof(procbuf), "#%lu/#%lu", (unsigned long)rqstp->rq_prog, (unsigned long)rqstp->rq_proc); yp_procedure = (char *)&procbuf; } else { yp_procedure = rqstp->rq_prog == YPPASSWDPROG ? "yppasswdprog_update" : yp_procs[rqstp->rq_proc + (12 * (rqstp->rq_vers - 1))]; } rqhost = svc_getcaller(rqstp->rq_xprt); if (debug) { yp_error("procedure %s called from %s:%d", yp_procedure, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); if (map != NULL) yp_error("client is referencing map \"%s\".", map); } /* Check the map name if one was supplied. */ if (map != NULL) { if (strchr(map, '/')) { yp_error("embedded slash in map name \"%s\" -- \ possible spoof attempt from %s:%d", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); return(1); } #ifdef DB_CACHE if ((yp_testflag((char *)map, (char *)domain, YP_SECURE) || #else if ((strstr(map, "master.passwd.") || strstr(map, "shadow.") || #endif (rqstp->rq_prog == YPPROG && rqstp->rq_proc == YPPROC_XFR) || (rqstp->rq_prog == YPXFRD_FREEBSD_PROG && rqstp->rq_proc == YPXFRD_GETMAP)) && ntohs(rqhost->sin_port) >= IPPORT_RESERVED) { yp_error("access to %s denied -- client %s:%d \ not privileged", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); return(1); } } #ifdef TCP_WRAPPER status_tcpwrap = hosts_ctl("ypserv", STRING_UNKNOWN, inet_ntoa(rqhost->sin_addr), ""); #endif tmp = securenets; while (tmp) { if (((rqhost->sin_addr.s_addr & ~tmp->mask.s_addr) | tmp->net.s_addr) == rqhost->sin_addr.s_addr) { status_securenets = 1; break; } tmp = tmp->next; } #ifdef TCP_WRAPPER if (status_securenets == 0 || status_tcpwrap == 0) { #else if (status_securenets == 0) { #endif /* * One of the following two events occurred: * * (1) The /var/yp/securenets exists and the remote host does not * match any of the networks specified in it. * (2) The hosts.allow file has denied access and TCP_WRAPPER is * defined. * * In either case deny access. */ if (rqhost->sin_addr.s_addr != oldaddr) { yp_error("connect from %s:%d to procedure %s refused", inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port), yp_procedure); oldaddr = rqhost->sin_addr.s_addr; } return(1); } return(0); } int yp_validdomain(const char *domain) { struct stat statbuf; char dompath[MAXPATHLEN + 2]; if (domain == NULL || strstr(domain, "binding") || !strcmp(domain, ".") || !strcmp(domain, "..") || strchr(domain, '/') || strlen(domain) > YPMAXDOMAIN) return(1); snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain); if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) return(1); return(0); } Index: head/usr.sbin/ypserv/yp_error.c =================================================================== --- head/usr.sbin/ypserv/yp_error.c (revision 359676) +++ head/usr.sbin/ypserv/yp_error.c (revision 359677) @@ -1,75 +1,73 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); /* * error logging/reporting facilities * stolen from /usr/libexec/mail.local via ypserv */ #include #include #include #include #include "yp_extern.h" -int debug; - extern int _rpcpmstart; extern char *progname; static void __verr(const char *fmt, va_list ap) __printflike(1, 0); static void __verr(const char *fmt, va_list ap) { if (debug && !_rpcpmstart) { fprintf(stderr,"%s: ",progname); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } else { vsyslog(LOG_NOTICE, fmt, ap); } } void yp_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); __verr(fmt,ap); va_end(ap); } Index: head/usr.sbin/ypserv/yp_main.c =================================================================== --- head/usr.sbin/ypserv/yp_main.c (revision 359676) +++ head/usr.sbin/ypserv/yp_main.c (revision 359677) @@ -1,581 +1,581 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * ypserv startup function. * We need out own main() since we have to do some additional work * that rpcgen won't do for us. Most of this file was generated using * rpcgen.new, and later modified. */ #include #include #include #include #include #include "yp.h" #include #include #include #include #include #include #include /* getenv, exit */ #include /* strcmp */ #include #include #ifdef __cplusplus #include /* getdtablesize, open */ #endif /* __cplusplus */ #include #include #include "yp_extern.h" #include #include #include #ifndef SIG_PF #define SIG_PF void(*)(int) #endif #define _RPCSVC_CLOSEDOWN 120 int _rpcpmstart; /* Started by a port monitor ? */ static int _rpcfdtype; /* Whether Stream or Datagram? */ static int _rpcaf; static int _rpcfd; /* States a server can be in wrt request */ #define _IDLE 0 #define _SERVED 1 #define _SERVING 2 extern void ypprog_1(struct svc_req *, SVCXPRT *); extern void ypprog_2(struct svc_req *, SVCXPRT *); extern int _rpc_dtablesize(void); extern int _rpcsvcstate; /* Set when a request is serviced */ char *progname = "ypserv"; char *yp_dir = _PATH_YP; -/*int debug = 0;*/ +int debug; int do_dns = 0; int resfd; struct socklistent { int sle_sock; struct sockaddr_storage sle_ss; SLIST_ENTRY(socklistent) sle_next; }; static SLIST_HEAD(, socklistent) sle_head = SLIST_HEAD_INITIALIZER(sle_head); struct bindaddrlistent { const char *ble_hostname; SLIST_ENTRY(bindaddrlistent) ble_next; }; static SLIST_HEAD(, bindaddrlistent) ble_head = SLIST_HEAD_INITIALIZER(ble_head); static char *servname = "0"; static void _msgout(char* msg, ...) { va_list ap; va_start(ap, msg); if (debug) { if (_rpcpmstart) vsyslog(LOG_ERR, msg, ap); else vwarnx(msg, ap); } else vsyslog(LOG_ERR, msg, ap); va_end(ap); } pid_t yp_pid; static void yp_svc_run(void) { #ifdef FD_SETSIZE fd_set readfds; #else int readfds; #endif /* def FD_SETSIZE */ int fd_setsize = _rpc_dtablesize(); struct timeval timeout; /* Establish the identity of the parent ypserv process. */ yp_pid = getpid(); for (;;) { #ifdef FD_SETSIZE readfds = svc_fdset; #else readfds = svc_fds; #endif /* def FD_SETSIZE */ FD_SET(resfd, &readfds); timeout.tv_sec = RESOLVER_TIMEOUT; timeout.tv_usec = 0; switch (select(fd_setsize, &readfds, NULL, NULL, &timeout)) { case -1: if (errno == EINTR) { continue; } warn("svc_run: - select failed"); return; case 0: if (getpid() == yp_pid) yp_prune_dnsq(); break; default: if (getpid() == yp_pid) { if (FD_ISSET(resfd, &readfds)) { yp_run_dnsq(); FD_CLR(resfd, &readfds); } svc_getreqset(&readfds); } } if (yp_pid != getpid()) _exit(0); } } static void unregister(void) { (void)svc_unreg(YPPROG, YPVERS); (void)svc_unreg(YPPROG, YPOLDVERS); } static void reaper(int sig) { int status; int saved_errno; saved_errno = errno; if (sig == SIGHUP) { load_securenets(); #ifdef DB_CACHE yp_flush_all(); #endif errno = saved_errno; return; } if (sig == SIGCHLD) { while (wait3(&status, WNOHANG, NULL) > 0) children--; } else { unregister(); exit(0); } errno = saved_errno; return; } static void usage(void) { fprintf(stderr, "usage: ypserv [-h addr] [-d] [-n] [-p path] [-P port]\n"); exit(1); } static void closedown(int sig) { if (_rpcsvcstate == _IDLE) { extern fd_set svc_fdset; static int size; int i, openfd; if (_rpcfdtype == SOCK_DGRAM) { unregister(); exit(0); } if (size == 0) { size = getdtablesize(); } for (i = 0, openfd = 0; i < size && openfd < 2; i++) if (FD_ISSET(i, &svc_fdset)) openfd++; if (openfd <= 1) { unregister(); exit(0); } } if (_rpcsvcstate == _SERVED) _rpcsvcstate = _IDLE; (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } static int create_service(const int sock, const struct netconfig *nconf, const struct __rpc_sockinfo *si) { int error; SVCXPRT *transp; struct addrinfo hints, *res, *res0; struct socklistent *slep; struct bindaddrlistent *blep; struct netbuf svcaddr; SLIST_INIT(&sle_head); memset(&hints, 0, sizeof(hints)); memset(&svcaddr, 0, sizeof(svcaddr)); hints.ai_family = si->si_af; hints.ai_socktype = si->si_socktype; hints.ai_protocol = si->si_proto; /* * Build socketlist from bindaddrlist. */ if (sock == RPC_ANYFD) { SLIST_FOREACH(blep, &ble_head, ble_next) { if (blep->ble_hostname == NULL) hints.ai_flags = AI_PASSIVE; else hints.ai_flags = 0; error = getaddrinfo(blep->ble_hostname, servname, &hints, &res0); if (error) { _msgout("getaddrinfo(): %s", gai_strerror(error)); return -1; } for (res = res0; res; res = res->ai_next) { int s; s = __rpc_nconf2fd(nconf); if (s < 0) { if (errno == EAFNOSUPPORT) _msgout("unsupported" " transport: %s", nconf->nc_netid); else _msgout("cannot create" " %s socket: %s", nconf->nc_netid, strerror(errno)); freeaddrinfo(res0); return -1; } if (bindresvport_sa(s, res->ai_addr) == -1) { if ((errno != EPERM) || (bind(s, res->ai_addr, res->ai_addrlen) == -1)) { _msgout("cannot bind " "%s socket: %s", nconf->nc_netid, strerror(errno)); freeaddrinfo(res0); close(sock); return -1; } } if (nconf->nc_semantics != NC_TPI_CLTS) listen(s, SOMAXCONN); slep = malloc(sizeof(*slep)); if (slep == NULL) { _msgout("malloc failed: %s", strerror(errno)); freeaddrinfo(res0); close(s); return -1; } memset(slep, 0, sizeof(*slep)); memcpy(&slep->sle_ss, res->ai_addr, res->ai_addrlen); slep->sle_sock = s; SLIST_INSERT_HEAD(&sle_head, slep, sle_next); /* * If servname == "0", redefine it by using * the bound socket. */ if (strncmp("0", servname, 1) == 0) { struct sockaddr *sap; socklen_t slen; char *sname; sname = malloc(NI_MAXSERV); if (sname == NULL) { _msgout("malloc(): %s", strerror(errno)); freeaddrinfo(res0); close(s); return -1; } memset(sname, 0, NI_MAXSERV); sap = (struct sockaddr *)&slep->sle_ss; slen = sizeof(*sap); error = getsockname(s, sap, &slen); if (error) { _msgout("getsockname(): %s", strerror(errno)); freeaddrinfo(res0); close(s); free(sname); return -1; } error = getnameinfo(sap, slen, NULL, 0, sname, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if (error) { _msgout("getnameinfo(): %s", strerror(errno)); freeaddrinfo(res0); close(s); free(sname); return -1; } servname = sname; } } freeaddrinfo(res0); } } else { slep = malloc(sizeof(*slep)); if (slep == NULL) { _msgout("malloc failed: %s", strerror(errno)); return -1; } memset(slep, 0, sizeof(*slep)); slep->sle_sock = sock; SLIST_INSERT_HEAD(&sle_head, slep, sle_next); } /* * Traverse socketlist and create rpc service handles for each socket. */ SLIST_FOREACH(slep, &sle_head, sle_next) { if (nconf->nc_semantics == NC_TPI_CLTS) transp = svc_dg_create(slep->sle_sock, 0, 0); else transp = svc_vc_create(slep->sle_sock, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (transp == NULL) { _msgout("unable to create service: %s", nconf->nc_netid); continue; } if (!svc_reg(transp, YPPROG, YPOLDVERS, ypprog_1, NULL)) { svc_destroy(transp); close(slep->sle_sock); _msgout("unable to register (YPPROG, YPOLDVERS, %s):" " %s", nconf->nc_netid, strerror(errno)); continue; } if (!svc_reg(transp, YPPROG, YPVERS, ypprog_2, NULL)) { svc_destroy(transp); close(slep->sle_sock); _msgout("unable to register (YPPROG, YPVERS, %s): %s", nconf->nc_netid, strerror(errno)); continue; } } while(!(SLIST_EMPTY(&sle_head))) SLIST_REMOVE_HEAD(&sle_head, sle_next); /* * Register RPC service to rpcbind by using AI_PASSIVE address. */ hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, servname, &hints, &res0); if (error) { _msgout("getaddrinfo(): %s", gai_strerror(error)); return -1; } svcaddr.buf = res0->ai_addr; svcaddr.len = res0->ai_addrlen; if (si->si_af == AF_INET) { /* XXX: ignore error intentionally */ rpcb_set(YPPROG, YPOLDVERS, nconf, &svcaddr); } /* XXX: ignore error intentionally */ rpcb_set(YPPROG, YPVERS, nconf, &svcaddr); freeaddrinfo(res0); return 0; } int main(int argc, char *argv[]) { int ch; int error; int ntrans; void *nc_handle; struct netconfig *nconf; struct __rpc_sockinfo si; struct bindaddrlistent *blep; memset(&si, 0, sizeof(si)); SLIST_INIT(&ble_head); while ((ch = getopt(argc, argv, "dh:np:P:")) != -1) { switch (ch) { case 'd': debug = ypdb_debug = 1; break; case 'h': blep = malloc(sizeof(*blep)); if (blep == NULL) err(1, "malloc() failed: -h %s", optarg); blep->ble_hostname = optarg; SLIST_INSERT_HEAD(&ble_head, blep, ble_next); break; case 'n': do_dns = 1; break; case 'p': yp_dir = optarg; break; case 'P': servname = optarg; break; default: usage(); } } /* * Add "anyaddr" entry if no -h is specified. */ if (SLIST_EMPTY(&ble_head)) { blep = malloc(sizeof(*blep)); if (blep == NULL) err(1, "malloc() failed"); memset(blep, 0, sizeof(*blep)); SLIST_INSERT_HEAD(&ble_head, blep, ble_next); } load_securenets(); yp_init_resolver(); #ifdef DB_CACHE yp_init_dbs(); #endif nc_handle = setnetconfig(); if (nc_handle == NULL) err(1, "cannot read %s", NETCONFIG); if (__rpc_fd2sockinfo(0, &si) != 0) { /* invoked from inetd */ _rpcpmstart = 1; _rpcfdtype = si.si_socktype; _rpcaf = si.si_af; _rpcfd = 0; openlog("ypserv", LOG_PID, LOG_DAEMON); } else { /* standalone mode */ if (!debug) { if (daemon(0,0)) { err(1,"cannot fork"); } openlog("ypserv", LOG_PID, LOG_DAEMON); } _rpcpmstart = 0; _rpcaf = AF_INET; _rpcfd = RPC_ANYFD; unregister(); } if (madvise(NULL, 0, MADV_PROTECT) != 0) _msgout("madvise(): %s", strerror(errno)); /* * Create RPC service for each transport. */ ntrans = 0; while((nconf = getnetconfig(nc_handle))) { if ((nconf->nc_flag & NC_VISIBLE)) { if (__rpc_nconf2sockinfo(nconf, &si) == 0) { _msgout("cannot get information for %s. " "Ignored.", nconf->nc_netid); continue; } if (_rpcpmstart) { if (si.si_socktype != _rpcfdtype || si.si_af != _rpcaf) continue; } else if (si.si_af != _rpcaf) continue; error = create_service(_rpcfd, nconf, &si); if (error) { endnetconfig(nc_handle); exit(1); } ntrans++; } } endnetconfig(nc_handle); while(!(SLIST_EMPTY(&ble_head))) SLIST_REMOVE_HEAD(&ble_head, ble_next); if (ntrans == 0) { _msgout("no transport is available. Aborted."); exit(1); } if (_rpcpmstart) { (void) signal(SIGALRM, (SIG_PF) closedown); (void) alarm(_RPCSVC_CLOSEDOWN/2); } /* * Make sure SIGPIPE doesn't blow us away while servicing TCP * connections. */ (void) signal(SIGPIPE, SIG_IGN); (void) signal(SIGCHLD, (SIG_PF) reaper); (void) signal(SIGTERM, (SIG_PF) reaper); (void) signal(SIGINT, (SIG_PF) reaper); (void) signal(SIGHUP, (SIG_PF) reaper); yp_svc_run(); _msgout("svc_run returned"); exit(1); /* NOTREACHED */ }