summaryrefslogtreecommitdiff
path: root/rpc.ypxfrd/ypxfrd_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpc.ypxfrd/ypxfrd_server.c')
-rw-r--r--rpc.ypxfrd/ypxfrd_server.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/rpc.ypxfrd/ypxfrd_server.c b/rpc.ypxfrd/ypxfrd_server.c
new file mode 100644
index 0000000..48c35b3
--- /dev/null
+++ b/rpc.ypxfrd/ypxfrd_server.c
@@ -0,0 +1,223 @@
+/* Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002, 2009, 2014 Thorsten Kukuk
+ Author: Thorsten Kukuk <kukuk@suse.de>
+
+ The YP Server is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ The 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 YP Server; see the file COPYING. If
+ not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include "log_msg.h"
+#include "ypxfrd.h"
+#include "access.h"
+#include "yp_db.h"
+
+static int file = 0;
+
+/* Read a block from a file and call xdr_xfr for sending */
+static bool_t
+xdr_ypxfrd_xfr (register XDR *xdrs, xfr *objp)
+{
+ static unsigned char buf[XFRBLOCKSIZE];
+ long len;
+
+ while (1)
+ {
+ if ((len = read (file, &buf, XFRBLOCKSIZE)) != -1)
+ {
+ /* We could send the next data block */
+ objp->ok = TRUE;
+ objp->xfr_u.xfrblock_buf.xfrblock_buf_len = len;
+ objp->xfr_u.xfrblock_buf.xfrblock_buf_val = (char *) &buf;
+ }
+ else
+ {
+ /* We could not read the next data block, so send an
+ error status */
+ objp->ok = FALSE;
+ objp->xfr_u.xfrstat = XFR_READ_ERR;
+ log_msg ("read error: %s", strerror (errno));
+ }
+
+ /* call the next function for sending the data or status */
+ if (!xdr_xfr (xdrs, objp))
+ return FALSE;
+
+ /* We have send the status report successfully, so exit the function
+ with an OK message. This does not mean that there were no errors
+ when reading the map, it only means that there were no errors
+ while sending data or the status. */
+ if (objp->ok == FALSE)
+ return TRUE;
+
+ /* Now, if we have send the last packet successfully, we could
+ send the XFR_DONE message and quit the function with the
+ return code of the xdr_xfr function */
+ if (objp->xfr_u.xfrblock_buf.xfrblock_buf_len < XFRBLOCKSIZE)
+ {
+ /* This was the last packet, send the XFR_DONE message */
+ objp->ok = FALSE;
+ objp->xfr_u.xfrstat = XFR_DONE;
+ return (xdr_xfr (xdrs, objp));
+ }
+ }
+}
+
+struct xfr *
+ypxfrd_getmap_1_svc (ypxfr_mapname *argp, struct svc_req *rqstp)
+{
+ static struct xfr result;
+ char buf[MAXPATHLEN];
+ int valid;
+
+ if (debug_flag)
+ {
+ struct netconfig *nconf;
+ struct netbuf *rqhost = svc_getrpccaller(rqstp->rq_xprt);
+
+ if ((nconf = getnetconfigent (rqstp->rq_xprt->xp_netid)) == NULL)
+ svcerr_systemerr (rqstp->rq_xprt);
+ else
+ {
+ char namebuf6[INET6_ADDRSTRLEN];
+
+ log_msg ("ypproc_null() [From: %s port: %d]",
+ taddr2ipstr (nconf, rqhost,
+ namebuf6, sizeof (namebuf6)),
+ taddr2port (nconf, rqhost));
+ log_msg ("\txfrdomain=%s", argp->xfrdomain);
+ log_msg ("\txfrmap=%s", argp->xfrmap);
+ log_msg ("\txfrmap_filename=%s", argp->xfrmap_filename);
+ freenetconfigent (nconf);
+ }
+ }
+ result.ok = FALSE;
+ result.xfr_u.xfrstat = XFR_DENIED;
+
+ if ((valid = is_valid (rqstp, argp->xfrmap, argp->xfrdomain)) < 1)
+ {
+ if (valid == 0)
+ {
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid source host)");
+ }
+ else
+ {
+ if (debug_flag)
+ log_msg ("\t-> Ignored (not a valid domain/map)");
+ }
+ ypdb_close_all ();
+
+ return &result;
+ }
+ ypdb_close_all ();
+
+#if defined(HAVE_LIBGDBM)
+#if SIZEOF_LONG == 8
+ if ((argp->xfr_db_type != XFR_DB_GNU_GDBM64) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#else
+ if ((argp->xfr_db_type != XFR_DB_GNU_GDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#endif
+#elif defined (HAVE_LIBNDBM)
+#if defined(__sun__) || defined(sun)
+ if ((argp->xfr_db_type != XFR_DB_NDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#else
+ if ((argp->xfr_db_type != XFR_DB_BSD_NDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#endif /* sun */
+#elif defined (HAVE_LIBQDBM)
+ if ((argp->xfr_db_type != XFR_DB_QDBM) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#elif defined (HAVE_LIBTC)
+ if ((argp->xfr_db_type != XFR_DB_TC) &&
+ (argp->xfr_db_type != XFR_DB_ANY))
+#else
+ if (argp->xfr_db_type != XFR_DB_ANY)
+#endif
+ {
+ result.xfr_u.xfrstat = XFR_DB_TYPE_MISMATCH;
+ return &result;
+ }
+
+#if defined(WORDS_BIGENDIAN)
+ if ((argp->xfr_byte_order != XFR_ENDIAN_BIG) &&
+ (argp->xfr_byte_order != XFR_ENDIAN_ANY))
+#else
+ if ((argp->xfr_byte_order != XFR_ENDIAN_LITTLE) &&
+ (argp->xfr_byte_order != XFR_ENDIAN_ANY))
+#endif
+ {
+ result.xfr_u.xfrstat = XFR_DB_ENDIAN_MISMATCH;
+ return &result;
+ }
+
+ /* check, if the xfrmap and xfrmap_filename means the same map,
+ not that some bad boys tell us that they will have the mail.aliases map,
+ but put "../../../etc/shadow" in the xfrmap_filename. */
+ if (strchr (argp->xfrmap_filename, '/') != NULL)
+ {
+ /* We don't have files in other directorys */
+ result.xfr_u.xfrstat = XFR_NOFILE;
+ return &result;
+ }
+
+ if (strncmp (argp->xfrmap, argp->xfrmap_filename, strlen (argp->xfrmap))
+ != 0)
+ return &result;
+
+ if (strlen (argp->xfrdomain) + strlen (argp->xfrmap_filename) + 2
+ < sizeof (buf))
+ sprintf (buf, "%s/%s", argp->xfrdomain, argp->xfrmap_filename);
+ else
+ {
+ log_msg ("Buffer overflow! [%s|%d]", __FILE__, __LINE__);
+ result.xfr_u.xfrstat = XFR_NOFILE;
+ return &result;
+ }
+
+ if (access ((char *) &buf, R_OK) == -1)
+ {
+ result.xfr_u.xfrstat = XFR_ACCESS;
+ return &result;
+ }
+
+ if ((file = open ((char *) &buf, O_RDONLY)) == -1)
+ {
+ result.xfr_u.xfrstat = XFR_READ_ERR;
+ return (&result);
+ }
+
+ /* Start with sending the database file */
+ svc_sendreply (rqstp->rq_xprt, (xdrproc_t) xdr_ypxfrd_xfr, (char *) &result);
+
+ close (file);
+
+ return NULL;
+}