summaryrefslogtreecommitdiffstats
path: root/gnu/usr.sbin/ypserv/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.sbin/ypserv/server.c')
-rw-r--r--gnu/usr.sbin/ypserv/server.c1327
1 files changed, 1327 insertions, 0 deletions
diff --git a/gnu/usr.sbin/ypserv/server.c b/gnu/usr.sbin/ypserv/server.c
new file mode 100644
index 0000000..1ed70bc
--- /dev/null
+++ b/gnu/usr.sbin/ypserv/server.c
@@ -0,0 +1,1327 @@
+/*
+** server.c YP server routines.
+**
+** Copyright (c) 1993 Signum Support AB, Sweden
+**
+** This file is part of the NYS YP Server.
+**
+** The NYS YP Server is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of the
+** License, or (at your option) any later version.
+**
+** The NYS YP Server is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public
+** License along with the NYS YP Server; see the file COPYING. If
+** not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+** Cambridge, MA 02139, USA.
+**
+** Author: Peter Eriksson <pen@signum.se>
+** Ported to FreeBSD and hacked all to pieces
+** by Bill Paul <wpaul@ctr.columbia.edu>
+**
+** $Id$
+**
+*/
+
+#include "system.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <limits.h>
+#include <db.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+#include "yp.h"
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#define PERM_SECURE (S_IRUSR|S_IWUSR)
+HASHINFO openinfo = {
+ 4096, /* bsize */
+ 32, /* ffactor */
+ 256, /* nelem */
+ 2048 * 1024, /* cachesize */
+ NULL, /* hash */
+ 0, /* lorder */
+};
+
+#if TCP_WRAPPER
+#include "log_tcp.h"
+int allow_severity=LOG_INFO;
+int deny_severity=LOG_WARNING;
+#endif
+
+void verr __P((const char *, _BSD_VA_LIST_));
+void Perror __P((const char *, ...));
+
+extern char *dnsname();
+extern char *dnsaddr();
+extern char *_gethostbydnsaddr();
+
+extern char *progname;
+extern int errno;
+
+int debug_flag = 0;
+int dns_flag = 0;
+
+
+void verr(fmt, ap)
+ const char *fmt;
+ _BSD_VA_LIST_ ap;
+
+{
+ if (debug_flag)
+ vfprintf(stderr, fmt, ap);
+ else
+ vsyslog(LOG_AUTH, fmt, ap);
+}
+
+void
+#ifdef __STDC__
+Perror(const char *fmt, ...)
+#else
+Perror(fmt, va_list)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ verr(fmt,ap);
+ va_end(ap);
+}
+
+
+/*
+** Return 1 if request comes from an authorized host
+**
+** XXX This function should implement the "securenets" functionality
+*/
+static int is_valid_host(struct sockaddr_in *sin)
+{
+#if TCP_WRAPPER
+ extern int hosts_ctl(char *, char *, char *, char *);
+ int status;
+ static long oldaddr=0; /* so we dont log multiple times */
+ static int oldstatus=-1;
+ char *h=NULL;
+
+#ifdef TRYRESOLVE
+ struct hostent *hp;
+
+ hp = _gethostbydnsaddr((char *) &sin->sin_addr.s_addr,
+ sizeof (sin->sin_addr.s_addr), AF_INET);
+
+ h = (hp && hp->h_name) ? hp->h_name : NULL;
+#endif
+
+ status = hosts_ctl(progname,
+ h?h:FROM_UNKNOWN,
+ inet_ntoa(sin->sin_addr),
+ "");
+
+ if (sin->sin_addr.s_addr != oldaddr || status != oldstatus ) {
+ syslog(status?allow_severity:deny_severity,
+ "%sconnect from %s\n",status?"":"refused ",
+ h?h:inet_ntoa(sin->sin_addr));
+ oldaddr=sin->sin_addr.s_addr;
+ oldstatus=status;
+ }
+ return status;
+#else
+ return 1;
+#endif
+}
+
+
+void *ypproc_null_2_svc(void *dummy,
+ struct svc_req *rqstp)
+{
+ static int foo;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+ if (!is_valid_host(rqhost))
+ return NULL;
+
+ if (debug_flag)
+ Perror("ypproc_null() [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ return (void *) &foo;
+}
+
+
+/*
+** Return 1 if the name is a valid domain name served by us, else 0.
+*/
+static int is_valid_domain(const char *domain)
+{
+ struct stat sbuf;
+
+
+ if (domain == NULL ||
+ strcmp(domain, "binding") == 0 ||
+ strcmp(domain, "..") == 0 ||
+ strcmp(domain, ".") == 0 ||
+ strchr(domain, '/'))
+ return 0;
+
+ if (stat(domain, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
+ return 0;
+
+ return 1;
+}
+
+
+
+bool_t *ypproc_domain_2_svc(domainname *name,
+ struct svc_req *rqstp)
+{
+ static bool_t result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ Perror("ypproc_domain(\"%s\") [From: %s:%d]\n",
+ *name,
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ if (is_valid_domain(*name))
+ result = TRUE;
+ else
+ result = FALSE;
+
+ if (debug_flag)
+ Perror("\t-> %s.\n",
+ (result == TRUE ? "Ok" : "Not served by us"));
+
+ return &result;
+}
+
+
+bool_t *ypproc_domain_nonack_2_svc(domainname *name,
+ struct svc_req *rqstp)
+{
+ static bool_t result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ Perror("ypproc_domain_nonack(\"%s\") [From: %s:%d]\n",
+ *name,
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ if (!is_valid_domain(*name))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid domain)\n");
+
+ /* Bail out and don't return any RPC value */
+ return NULL;
+ }
+
+ if (debug_flag)
+ Perror("\t-> OK.\n");
+
+ result = TRUE;
+ return &result;
+}
+
+
+/*
+** Open a DB database
+*/
+static DB *open_database(const char *domain,
+ const char *map)
+{
+ DB *dbp;
+ char buf[1025];
+
+
+ if (map[0] == '.' || strchr(map, '/'))
+ return 0;
+
+ strcpy(buf, domain);
+ strcat(buf, "/");
+ strcat(buf, map);
+
+ dbp = dbopen(buf,O_RDONLY|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
+
+ if (debug_flag > 1 && dbp == NULL)
+ Perror("dbopen(): ",strerror(errno));
+
+ return dbp;
+}
+
+
+#define F_ALL 0x01
+#define F_NEXT 0x02
+
+/*
+** Get a record from a DB database.
+** This looks ugly because it emulates the behavior of the original
+** GDBM-based routines. Blech.
+*/
+int read_database(DB *dbp,
+ const DBT *ikey,
+ DBT *okey,
+ DBT *dval,
+ int flags)
+{
+ int first_flag = 0;
+ DBT nkey, ckey, dummyval;
+
+
+ if (ikey == NULL || ikey->data == NULL)
+ {
+ (dbp->seq)(dbp,&ckey,&dummyval,R_FIRST);
+ first_flag = 1;
+ }
+ else
+ {
+ if ((flags & F_NEXT))
+ {
+ /*
+ ** This crap would be unnecessary if R_CURSOR actually worked.
+ */
+ (dbp->seq)(dbp,&ckey,&dummyval,R_FIRST);
+ while(strncmp((char *)ikey->data,ckey.data,(int)ikey->size) ||
+ ikey->size != ckey.size)
+ (dbp->seq)(dbp,&ckey,&dummyval,R_NEXT);
+ if ((dbp->seq)(dbp,&ckey,&dummyval,R_NEXT))
+ ckey.data = NULL;
+ free(dummyval.data);
+ }
+ else
+ ckey = *ikey;
+ }
+
+ if (ckey.data == NULL)
+ {
+ return (flags & F_NEXT) ? YP_NOMORE : YP_NOKEY;
+ }
+
+ while (1)
+ {
+ if ((dbp->get)(dbp,&ckey,dval,0))
+ {
+ /* Free key, unless it comes from the caller! */
+ if (ikey == NULL || ckey.data != ikey->data)
+ free(ckey.data);
+
+ if (ikey && ikey->data != NULL)
+ {
+ return YP_NOKEY;
+ }
+ else
+ if (first_flag)
+ return YP_BADDB;
+ else
+ return YP_FALSE;
+ }
+
+ if ((flags & F_ALL) || strncmp(ckey.data, "YP_", 3) != 0)
+ {
+ if (okey)
+ *okey = ckey;
+ else if (ikey == NULL || ikey->data != ckey.data)
+ free(ckey.data);
+
+ return YP_TRUE;
+ }
+
+ /* Free old value */
+ free(dval->data);
+
+ if ((dbp->seq)(dbp,&nkey,&dummyval,R_NEXT))
+ nkey.data = NULL;
+ free(dummyval.data);
+
+ /* Free old key, unless it comes from the caller! */
+ if (ikey == NULL || ckey.data != ikey->data)
+ free(ckey.data);
+
+ if (ckey.data == NULL || nkey.data == NULL)
+ return YP_NOMORE;
+
+ ckey = nkey;
+ }
+}
+
+
+/*
+** Get the DateTimeModified value for a certain map database
+*/
+static unsigned long get_dtm(const char *domain,
+ const char *map)
+{
+ struct stat sbuf;
+ char buf[1025];
+
+
+ strcpy(buf, domain);
+ strcat(buf, "/");
+ strcat(buf, map);
+
+ if (stat(buf, &sbuf) < 0)
+ return 0;
+ else
+ return (unsigned long) sbuf.st_mtime;
+}
+
+
+/*
+** YP function "MATCH" implementation
+*/
+ypresp_val *ypproc_match_2_svc(ypreq_key *key,
+ struct svc_req *rqstp)
+{
+ static ypresp_val result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_match(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\t\tdomainname = \"%s\"\n",
+ key->domain);
+ Perror("\t\tmapname = \"%s\"\n",
+ key->map);
+ Perror("\t\tkeydat = \"%.*s\"\n",
+ (int) key->key.keydat_len,
+ key->key.keydat_val);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ /*
+ ** If this request deals with master.passwd.* and it didn't
+ ** originate on a privileged port (< 1024), return a YP_YPERR.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (strstr(key->map, "master.passwd") != NULL &&
+ ntohs(rqhost->sin_port) > 1023)
+ {
+ result.stat = YP_YPERR;
+ return &result;
+ }
+
+ result.val.valdat_len = 0;
+ if (result.val.valdat_val)
+ {
+ free(result.val.valdat_val);
+ result.val.valdat_val = NULL;
+ }
+
+ if (key->domain[0] == '\0' || key->map[0] == '\0')
+ result.stat = YP_BADARGS;
+ else if (!is_valid_domain(key->domain))
+ result.stat = YP_NODOM;
+ else
+ {
+ DBT rdat, qdat;
+
+ DB *dbp = open_database(key->domain, key->map);
+ if (dbp == NULL)
+ result.stat = YP_NOMAP;
+ else
+ {
+ qdat.size = key->key.keydat_len;
+ qdat.data = key->key.keydat_val;
+
+ result.stat = read_database(dbp, &qdat, NULL, &rdat, F_ALL);
+
+ if (result.stat == YP_TRUE)
+ {
+ result.val.valdat_len = rdat.size;
+ result.val.valdat_val = rdat.data;
+ }
+
+ (void)(dbp->close)(dbp);
+ }
+ }
+
+ if (debug_flag)
+ {
+ if (result.stat == YP_TRUE)
+ Perror("\t-> Value = \"%.*s\"\n",
+ (int) result.val.valdat_len,
+ result.val.valdat_val);
+ else
+ Perror("\t-> Error #%d\n", result.stat);
+ }
+
+
+ /*
+ ** Do the jive thing if we didn't find the host in the YP map
+ ** and we have enabled the magic DNS lookup stuff.
+ **
+ ** XXX Perhaps this should be done in a sub-process for performance
+ ** reasons. Later.
+ */
+ if (result.stat != YP_TRUE && dns_flag)
+ {
+ char *cp = NULL;
+
+ key->key.keydat_val[key->key.keydat_len] = '\0';
+
+ if (debug_flag)
+ Perror("Doing DNS lookup of %s\n", key->key.keydat_val);
+
+ if (strcmp(key->map, "hosts.byname") == 0)
+ cp = dnsname(key->key.keydat_val);
+ else if (strcmp(key->map, "hosts.byaddr") == 0)
+ cp = dnsaddr(key->key.keydat_val);
+
+ if (cp)
+ {
+
+ if (debug_flag)
+ Perror("\t-> OK (%s)\n", cp);
+
+ result.val.valdat_len = strlen(cp);
+ result.val.valdat_val = cp;
+ result.stat = YP_TRUE;
+ }
+ else
+ {
+ if (debug_flag)
+ {
+ Perror("\t-> Not Found\n");
+ Perror("DNS lookup: %s",strerror(errno));
+ }
+
+ result.stat = YP_NOKEY;
+ }
+ }
+
+ return &result;
+}
+
+
+
+ypresp_key_val *ypproc_first_2_svc(ypreq_nokey *key,
+ struct svc_req *rqstp)
+{
+ static ypresp_key_val result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_first(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\tdomainname = \"%s\"\n", key->domain);
+ Perror("\tmapname = \"%s\"\n", key->map);
+#if 0
+ Perror("\tkeydat = \"%.*s\"\n",
+ (int) key->key.keydat_len,
+ key->key.keydat_val);
+#endif
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ /*
+ ** If this request deals with master.passwd.* and it didn't
+ ** originate on a privileged port (< 1024), return a YP_YPERR.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (strstr(key->map, "master.passwd") != NULL &&
+ ntohs(rqhost->sin_port) > 1023)
+ {
+ result.stat = YP_YPERR;
+ return &result;
+ }
+
+ result.key.keydat_len = 0;
+ if (result.key.keydat_val)
+ {
+ free(result.key.keydat_val);
+ result.key.keydat_val = NULL;
+ }
+
+ result.val.valdat_len = 0;
+ if (result.val.valdat_val)
+ {
+ free(result.val.valdat_val);
+ result.val.valdat_val = NULL;
+ }
+
+ if (key->map[0] == '\0' || key->domain[0] == '\0')
+ result.stat = YP_BADARGS;
+ else if (!is_valid_domain(key->domain))
+ result.stat = YP_NODOM;
+ else
+ {
+ DBT dkey, dval;
+
+ DB *dbp = open_database(key->domain, key->map);
+ if (dbp == NULL)
+ result.stat = YP_NOMAP;
+ else
+ {
+ result.stat = read_database(dbp, NULL, &dkey, &dval, 0);
+
+ if (result.stat == YP_TRUE)
+ {
+ result.key.keydat_len = dkey.size;
+ result.key.keydat_val = dkey.data;
+
+ result.val.valdat_len = dval.size;
+ result.val.valdat_val = dval.data;
+ }
+
+ (void)(dbp->close)(dbp);
+ }
+ }
+
+ if (debug_flag)
+ {
+ if (result.stat == YP_TRUE)
+ Perror("\t-> Key = \"%.*s\", Value = \"%.*s\"\n",
+ (int) result.key.keydat_len,
+ result.key.keydat_val,
+ (int) result.val.valdat_len,
+ result.val.valdat_val);
+
+ else
+ Perror("\t-> Error #%d\n", result.stat);
+ }
+
+ return &result;
+}
+
+
+ypresp_key_val *ypproc_next_2_svc(ypreq_key *key,
+ struct svc_req *rqstp)
+{
+ static ypresp_key_val result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_next(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\tdomainname = \"%s\"\n", key->domain);
+ Perror("\tmapname = \"%s\"\n", key->map);
+ Perror("\tkeydat = \"%.*s\"\n",
+ (int) key->key.keydat_len,
+ key->key.keydat_val);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ /*
+ ** If this request deals with master.passwd.* and it didn't
+ ** originate on a privileged port (< 1024), return a YP_YPERR.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (strstr(key->map, "master.passwd") != NULL &&
+ ntohs(rqhost->sin_port) > 1023)
+ {
+ result.stat = YP_YPERR;
+ return &result;
+ }
+
+ result.key.keydat_len = 0;
+ if (result.key.keydat_val)
+ {
+ free(result.key.keydat_val);
+ result.key.keydat_val = NULL;
+ }
+
+ result.val.valdat_len = 0;
+ if (result.val.valdat_val)
+ {
+ free(result.val.valdat_val);
+ result.val.valdat_val = NULL;
+ }
+
+ if (key->map[0] == '\0' || key->domain[0] == '\0')
+ result.stat = YP_BADARGS;
+ else if (!is_valid_domain(key->domain))
+ result.stat = YP_NODOM;
+ else
+ {
+ DBT dkey, dval, okey;
+
+
+ DB *dbp = open_database(key->domain, key->map);
+ if (dbp == NULL)
+ result.stat = YP_NOMAP;
+ else
+ {
+ dkey.size = key->key.keydat_len;
+ dkey.data = key->key.keydat_val;
+
+ result.stat = read_database(dbp, &dkey, &okey, &dval, F_NEXT);
+
+ if (result.stat == YP_TRUE)
+ {
+ result.key.keydat_len = okey.size;
+ result.key.keydat_val = okey.data;
+
+ result.val.valdat_len = dval.size;
+ result.val.valdat_val = dval.data;
+ }
+ (void)(dbp->close)(dbp);
+ }
+ }
+
+ if (debug_flag)
+ {
+ if (result.stat == YP_TRUE)
+ Perror("\t-> Key = \"%.*s\", Value = \"%.*s\"\n",
+ (int) result.key.keydat_len,
+ result.key.keydat_val,
+ (int) result.val.valdat_len,
+ result.val.valdat_val);
+ else
+ Perror("\t-> Error #%d\n", result.stat);
+ }
+
+ return &result;
+}
+
+
+
+static void print_ypmap_parms(const struct ypmap_parms *pp)
+{
+ Perror("\t\tdomain = \"%s\"\n", pp->domain);
+ Perror("\t\tmap = \"%s\"\n", pp->map);
+ Perror("\t\tordernum = %u\n", pp->ordernum);
+ Perror("\t\tpeer = \"%s\"\n", pp->peer);
+}
+
+
+/*
+** Stole the ypxfr implementation from the yps package.
+*/
+ypresp_xfr *ypproc_xfr_2_svc(ypreq_xfr *xfr,
+ struct svc_req *rqstp)
+{
+ static ypresp_xfr result;
+ struct sockaddr_in *rqhost;
+ char ypxfr_command[MAXPATHLEN];
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_xfr_2_svc(): [From: %s:%d]\n\tmap_parms:\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ print_ypmap_parms(&xfr->map_parms);
+ Perror("\t\ttransid = %u\n", xfr->transid);
+ Perror("\t\tprog = %u\n", xfr->prog);
+ Perror("\t\tport = %u\n", xfr->port);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ /*
+ ** If this request originates on a non-privileged port (< 1024),
+ ** refuse it. We really only need to guard the master.passwd.*
+ ** maps, but what the hell.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (ntohs(rqhost->sin_port) > 1023)
+ {
+ result.xfrstat = YPXFR_REFUSED;
+ return &result;
+ }
+
+ switch(fork())
+ {
+ case 0:
+ {
+ char g[11], t[11], p[11];
+
+ sprintf (ypxfr_command, "%s/ypxfr", INSTDIR);
+ sprintf (t, "%u", xfr->transid);
+ sprintf (g, "%u", xfr->prog);
+ sprintf (p, "%u", xfr->port);
+ execl(ypxfr_command, "ypxfr", "-d", xfr->map_parms.domain, "-h",
+ xfr->map_parms.peer, "-f", "-C", t, g,
+ inet_ntoa(rqhost->sin_addr), p, xfr->map_parms.map, NULL);
+ Perror("ypxfr execl(): %s",strerror(errno));
+ exit(0);
+ }
+ case -1:
+ Perror("fork(): %s",strerror(errno));
+ result.xfrstat = YPXFR_XFRERR;
+ default:
+ {
+ int st;
+
+ wait4(-1, &st, WNOHANG, NULL);
+ result.xfrstat = YPXFR_SUCC;
+ break;
+ }
+ }
+
+ result.transid = xfr->transid;
+ return &result;
+}
+
+
+void *ypproc_clear_2_svc(void *dummy,
+ struct svc_req *rqstp)
+{
+ static int foo;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ Perror("ypproc_clear_2_svc() [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ return (void *) &foo;
+}
+
+
+static int ypall_close(void *data)
+{
+ DB *locptr;
+
+ if (debug_flag && data == NULL)
+ {
+ Perror("ypall_close() called with NULL pointer.\n");
+ return 0;
+ }
+
+ locptr = (DB *)data;
+ (void)(locptr->close)(locptr);
+ return 0;
+}
+
+
+static int ypall_encode(ypresp_key_val *val,
+ void *data)
+{
+ DBT dkey, dval, okey;
+
+ dkey.data = val->key.keydat_val;
+ dkey.size = val->key.keydat_len;
+
+ val->stat = read_database((DB *) data, &dkey, &okey, &dval, F_NEXT);
+
+ if (val->stat == YP_TRUE)
+ {
+ val->key.keydat_val = okey.data;
+ val->key.keydat_len = okey.size;
+
+ val->val.valdat_val = dval.data;
+ val->val.valdat_len = dval.size;
+ }
+
+
+ return val->stat;
+}
+
+
+ypresp_all *ypproc_all_2_svc(ypreq_nokey *nokey,
+ struct svc_req *rqstp)
+{
+ static ypresp_all result;
+ extern __xdr_ypall_cb_t __xdr_ypall_cb;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_all_2_svc(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\t\tdomain = \"%s\"\n", nokey->domain);
+ Perror("\t\tmap = \"%s\"\n", nokey->map);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ __xdr_ypall_cb.u.encode = NULL;
+ __xdr_ypall_cb.u.close = NULL;
+ __xdr_ypall_cb.data = NULL;
+
+ result.more = TRUE;
+
+ /*
+ ** If this request deals with master.passwd.* and it didn't
+ ** originate on a privileged port (< 1024), return a YP_YPERR.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (strstr(nokey->map, "master.passwd") != NULL &&
+ ntohs(rqhost->sin_port) > 1023)
+ {
+ result.ypresp_all_u.val.stat = YP_YPERR;
+ return &result;
+ }
+
+ if (nokey->map[0] == '\0' || nokey->domain[0] == '\0')
+ result.ypresp_all_u.val.stat = YP_BADARGS;
+ else if (!is_valid_domain(nokey->domain))
+ result.ypresp_all_u.val.stat = YP_NODOM;
+ else
+ {
+ DBT dkey, dval;
+
+ DB *dbp = open_database(nokey->domain, nokey->map);
+ if (dbp == NULL)
+ result.ypresp_all_u.val.stat = YP_NOMAP;
+ else
+ {
+ result.ypresp_all_u.val.stat = read_database(dbp,
+ NULL,
+ &dkey,
+ &dval,
+ 0);
+
+ if (result.ypresp_all_u.val.stat == YP_TRUE)
+ {
+ result.ypresp_all_u.val.key.keydat_len = dkey.size;
+ result.ypresp_all_u.val.key.keydat_val = dkey.data;
+
+ result.ypresp_all_u.val.val.valdat_len = dval.size;
+ result.ypresp_all_u.val.val.valdat_val = dval.data;
+
+ __xdr_ypall_cb.u.encode = ypall_encode;
+ __xdr_ypall_cb.u.close = ypall_close;
+ __xdr_ypall_cb.data = (void *) dbp;
+
+ return &result;
+ }
+
+ (void)(dbp->close)(dbp);
+ }
+ }
+
+ return &result;
+}
+
+
+ypresp_master *ypproc_master_2_svc(ypreq_nokey *nokey,
+ struct svc_req *rqstp)
+{
+ static ypresp_master result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_master_2_svc(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\t\tdomain = \"%s\"\n", nokey->domain);
+ Perror("\t\tmap = \"%s\"\n", nokey->map);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ /*
+ ** If this request deals with master.passwd.* and it didn't
+ ** originate on a privileged port (< 1024), return a YP_YPERR.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (strstr(nokey->map, "master.passwd") != NULL &&
+ ntohs(rqhost->sin_port) > 1023)
+ {
+ result.stat = YP_YPERR;
+ return &result;
+ }
+
+ if (result.peer)
+ {
+ free(result.peer);
+ result.peer = NULL;
+ }
+
+ if (nokey->domain[0] == '\0')
+ result.stat = YP_BADARGS;
+ else if (!is_valid_domain(nokey->domain))
+ result.stat = YP_NODOM;
+ else
+ {
+ DB *dbp = open_database(nokey->domain, nokey->map);
+ if (dbp == NULL)
+ result.stat = YP_NOMAP;
+ else
+ {
+ DBT key, val;
+
+ key.size = sizeof("YP_MASTER_NAME")-1;
+ key.data = "YP_MASTER_NAME";
+
+ if ((dbp->get)(dbp,&key,&val,0))
+ val.data = NULL;
+
+ if (val.data == NULL)
+ {
+ /* No YP_MASTER_NAME record in map? Assume we are Master */
+ static char hostbuf[1025];
+
+ gethostname((char *)&hostbuf, sizeof(hostbuf)-1);
+ Perror("Hostname: [%s]",hostbuf);
+ result.peer = strdup(hostbuf);
+ }
+ else
+ {
+ *(((char *)val.data)+val.size) = '\0';
+ result.peer = val.data;
+ }
+
+ result.stat = YP_TRUE;
+ (void)(dbp->close)(dbp);
+ }
+ }
+
+ if (result.peer == NULL)
+ result.peer = strdup("");
+
+ if (debug_flag)
+ Perror("\t-> Peer = \"%s\"\n", result.peer);
+
+ return &result;
+}
+
+
+ypresp_order *ypproc_order_2_svc(ypreq_nokey *nokey,
+ struct svc_req *rqstp)
+{
+ static ypresp_order result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_order_2_svc(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\t\tdomain = \"%s\"\n", nokey->domain);
+ Perror("\t\tmap = \"%s\"\n", nokey->map);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ /*
+ ** If this request deals with master.passwd.* and it didn't
+ ** originate on a privileged port (< 1024), return a YP_YPERR.
+ ** This is our half-assed way of preventing non-root users
+ ** on NIS clients from getting at the real password map. Bah.
+ */
+
+ if (strstr(nokey->map, "master.passwd") != NULL &&
+ ntohs(rqhost->sin_port) > 1023)
+ {
+ result.stat = YP_YPERR;
+ return &result;
+ }
+
+ result.ordernum = 0;
+
+ if (nokey->domain[0] == '\0')
+ result.stat = YP_BADARGS;
+ else if (!is_valid_domain(nokey->domain))
+ result.stat = YP_NODOM;
+ else
+ {
+ DB *dbp = open_database(nokey->domain, nokey->map);
+ if (dbp == NULL)
+ result.stat = YP_NOMAP;
+ else
+ {
+ DBT key, val;
+
+ key.size = sizeof("YP_LAST_MODIFIED")-1;
+ key.data = "YP_LAST_MODIFIED";
+
+ (dbp->get)(dbp,&key,&val,0);
+ if (val.data == NULL)
+ {
+ /* No YP_LAST_MODIFIED record in map? Use DTM timestamp.. */
+ result.ordernum = get_dtm(nokey->domain, nokey->map);
+ }
+ else
+ {
+ result.ordernum = atoi(val.data);
+ free(val.data);
+ }
+
+ result.stat = YP_TRUE;
+ (void)(dbp->close)(dbp);
+ }
+ }
+
+ if (debug_flag)
+ Perror("-> Order # %d\n", result.ordernum);
+
+ return &result;
+}
+
+
+static void free_maplist(ypmaplist *mlp)
+{
+ ypmaplist *next;
+
+ while (mlp != NULL)
+ {
+ next = mlp->next;
+ free(mlp->map);
+ free(mlp);
+ mlp = next;
+ }
+}
+
+static int add_maplist(ypmaplist **mlhp,
+ char *map)
+{
+ ypmaplist *mlp;
+
+ if (!strncmp(map, ".", strlen(map)) || !strncmp(map, "..", strlen(map)))
+ return 0;
+
+ mlp = malloc(sizeof(*mlp));
+ if (mlp == NULL)
+ return -1;
+
+ mlp->map = strdup(map);
+ if (mlp->map == NULL)
+ {
+ free(mlp);
+ return -1;
+ }
+
+ mlp->next = *mlhp;
+ *mlhp = mlp;
+
+ return 0;
+}
+
+
+ypresp_maplist *ypproc_maplist_2_svc(domainname *name,
+ struct svc_req *rqstp)
+{
+ static ypresp_maplist result;
+ struct sockaddr_in *rqhost;
+
+
+ rqhost = svc_getcaller(rqstp->rq_xprt);
+
+ if (debug_flag)
+ {
+ Perror("ypproc_maplist_2_svc(): [From: %s:%d]\n",
+ inet_ntoa(rqhost->sin_addr),
+ ntohs(rqhost->sin_port));
+
+ Perror("\t\tdomain = \"%s\"\n", *name);
+ }
+
+ if (!is_valid_host(rqhost))
+ {
+ if (debug_flag)
+ Perror("\t-> Ignored (not a valid source host)\n");
+
+ return NULL;
+ }
+
+ if (result.maps)
+ free_maplist(result.maps);
+
+ result.maps = NULL;
+
+ if ((*name)[0] == '\0')
+ result.stat = YP_BADARGS;
+ else if (!is_valid_domain(*name))
+ result.stat = YP_NODOM;
+ else
+ {
+ DIR *dp;
+ char dirname[MAXPATHLEN];
+
+ sprintf(dirname,"./%s",*name);
+ dp = opendir(dirname);
+ if (dp == NULL)
+ {
+ if (debug_flag)
+ {
+ Perror("%s: opendir: %s", progname,strerror(errno));
+ }
+
+ result.stat = YP_BADDB;
+ }
+ else
+ {
+ struct dirent *dep;
+
+ while ((dep = readdir(dp)) != NULL)
+ if (add_maplist(&result.maps, dep->d_name) < 0)
+ {
+ result.stat = YP_YPERR;
+ break;
+ }
+ closedir(dp);
+ result.stat = YP_TRUE;
+ }
+ }
+
+ if (debug_flag)
+ {
+ if (result.stat == YP_TRUE)
+ {
+ ypmaplist *p;
+
+ p = result.maps;
+ Perror("-> ");
+ while (p->next)
+ {
+ Perror("%s,", p->map);
+ p = p->next;
+ }
+ putc('\n', stderr);
+ }
+ else
+ Perror("\t-> Error #%d\n", result.stat);
+ }
+
+ return &result;
+}
OpenPOWER on IntegriCloud