diff options
Diffstat (limited to 'rpc.ypxfrd/ypxfrd_server.c')
-rw-r--r-- | rpc.ypxfrd/ypxfrd_server.c | 223 |
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; +} |