📄 portmap.c
字号:
/*- * Copyright (c) 1990 The Regents of the University of California. * 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 the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1990 The Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint *//*@(#)portmap.c 2.3 88/08/11 4.0 RPCSRCstatic char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";*//* * portmap.c, Implements the program,version to port number mapping for * rpc. *//* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */#include <rpc/rpc.h>#include <rpc/pmap_prot.h>#include <stdio.h>#include <unistd.h>#include <syslog.h>#include <netdb.h>#include <errno.h>#include <fcntl.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/wait.h>#include <sys/signal.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/types.h>#ifdef SYSV40#include <netinet/in.h>#endif#include <arpa/inet.h>#include <stdlib.h>#include <pwd.h>#ifndef LOG_PERROR#define LOG_PERROR 0#endif#ifndef LOG_DAEMON#define LOG_DAEMON 0#endif/* Older SYSV. */#if !defined(SIGCHLD) && defined(SIGCLD)#define SIGCHLD SIGCLD#endif#ifndef svc_getcaller /* SYSV4 */# define svc_getcaller svc_getrpccaller#endifstatic void reg_service(struct svc_req *rqstp, SVCXPRT *xprt);#ifndef IGNORE_SIGCHLD /* Lionel Cons <cons@dxcern.cern.ch> */static void reap(int);#endifstatic void callit(struct svc_req *rqstp, SVCXPRT *xprt);struct pmaplist *pmaplist;int debugging = 0;int store_fd = -1;static void dump_table(void);static void load_table(void);#include "pmap_check.h" /* * How desperate can one be. It is possible to prevent an attacker from * manipulating your portmapper tables from outside with requests that * contain spoofed source address information. The countermeasure is to * force all rpc servers to register and unregister with the portmapper via * the loopback network interface, instead of via the primary network * interface that every host can talk to. For this countermeasure to work it * is necessary to #define LOOPBACK_SETUNSET, to disable source routing in * the kernel, and to modify libc so that get_myaddress() chooses the * loopback interface address. */#ifdef LOOPBACK_SETUNSETstatic SVCXPRT *ludpxprt, *ltcpxprt;static int on = 1;#ifndef INADDR_LOOPBACK#define INADDR_LOOPBACK ntohl(inet_addr("127.0.0.1"))#endif#endif#ifdef DAEMON_UIDint daemon_uid = DAEMON_UID;int daemon_gid = DAEMON_GID;#elseint daemon_uid = 1;int daemon_gid = 1;#endif/* * We record with each registration a flag telling whether it was * registered with a privilege port or not. * If it was, it can only be unregistered with a privileged port. * So that we can still use standard pmap xdr routines, we store * this flag in a structure wrapped around a pmaplist. */struct flagged_pml { struct pmaplist pml; int priv;};intmain(int argc, char **argv){ SVCXPRT *xprt; int sock, c; struct sockaddr_in addr; int len = sizeof(struct sockaddr_in); struct pmaplist *pml; struct flagged_pml *fpml; char *chroot_path = NULL; struct in_addr bindaddr; int have_bindaddr = 0; int foreground = 0; int have_uid = 0; while ((c = getopt(argc, argv, "Vdflt:vi:u:g:")) != EOF) { switch (c) { case 'V': printf("portmap version 6.0 - 2007-May-11\n"); exit(1); case 'u': daemon_uid = atoi(optarg); if (daemon_uid <= 0) { fprintf(stderr, "portmap: illegal uid: %s\n", optarg); exit(1); } have_uid = 1; break; case 'g': daemon_gid = atoi(optarg); if (daemon_gid <= 0) { fprintf(stderr, "portmap: illegal gid: %s\n", optarg); exit(1); } have_uid = 1; break; case 'd': debugging = 1; case 'f': foreground = 1; break; case 't': chroot_path = optarg; break; case 'v': verboselog = 1; break; case 'l': optarg = "127.0.0.1"; /* FALL THROUGH */ case 'i': have_bindaddr = inet_aton(optarg, &bindaddr); break; default: fprintf(stderr, "usage: %s [-dflv] [-t dir] [-i address] " "[-u uid] [-g gid]\n", argv[0]); fprintf(stderr, "-d: debugging mode\n"); fprintf(stderr, "-f: don't daemonize, log to standard error\n"); fprintf(stderr, "-t dir: chroot into dir\n"); fprintf(stderr, "-v: verbose logging\n"); fprintf(stderr, "-i address: bind to address\n"); fprintf(stderr, "-l: same as -i 127.0.0.1\n"); fprintf(stderr, "-u uid : setuid to this uid\n"); fprintf(stderr, "-g uid : setgid to this gid\n"); exit(1); } } if (!foreground && daemon(0, 0)) { (void) fprintf(stderr, "portmap: fork: %s", strerror(errno)); exit(1); }#ifdef LOG_DAEMON openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0), FACILITY);#else openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0));#endif#ifdef RPCUSER if (!have_uid) { struct passwd *pwent; pwent = getpwnam(RPCUSER); if (pwent) { daemon_uid = pwent->pw_uid; daemon_gid = pwent->pw_gid; } else syslog(LOG_WARNING, "user '" RPCUSER "' not found, reverting to default uid"); }#endif if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { syslog(LOG_ERR, "cannot create udp socket: %m"); exit(1); }#ifdef LOOPBACK_SETUNSET setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);#endif memset((char *) &addr, 0, sizeof(addr)); addr.sin_addr.s_addr = 0; addr.sin_family = AF_INET; addr.sin_port = htons(PMAPPORT); if (have_bindaddr) memcpy(&addr.sin_addr, &bindaddr, sizeof(bindaddr)); if (bind(sock, (struct sockaddr *)&addr, len) != 0) { syslog(LOG_ERR, "cannot bind udp: %m"); exit(1); } if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { syslog(LOG_ERR, "couldn't do udp_create"); exit(1); } /* make an entry for ourself */ fpml = malloc(sizeof(struct flagged_pml)); pml = &fpml->pml; fpml->priv = 1; pml->pml_next = NULL; pml->pml_map.pm_prog = PMAPPROG; pml->pml_map.pm_vers = PMAPVERS; pml->pml_map.pm_prot = IPPROTO_UDP; pml->pml_map.pm_port = PMAPPORT; pmaplist = pml; if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { syslog(LOG_ERR, "cannot create tcp socket: %m"); exit(1); }#ifdef LOOPBACK_SETUNSET setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);#endif if (bind(sock, (struct sockaddr *)&addr, len) != 0) { syslog(LOG_ERR, "cannot bind tcp: %m"); exit(1); } if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) == (SVCXPRT *)NULL) { syslog(LOG_ERR, "couldn't do tcp_create"); exit(1); } /* make an entry for ourself */ fpml = malloc(sizeof(struct flagged_pml)); pml = &fpml->pml; fpml->priv = 1; pml->pml_map.pm_prog = PMAPPROG; pml->pml_map.pm_vers = PMAPVERS; pml->pml_map.pm_prot = IPPROTO_TCP; pml->pml_map.pm_port = PMAPPORT; pml->pml_next = pmaplist; pmaplist = pml;#ifdef LOOPBACK_SETUNSET if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { syslog(LOG_ERR, "cannot create udp socket: %m"); exit(1); } setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(sock, (struct sockaddr *)&addr, len) != 0) { syslog(LOG_ERR, "cannot bind udp: %m"); exit(1); } if ((ludpxprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { syslog(LOG_ERR, "couldn't do udp_create"); exit(1); } if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { syslog(LOG_ERR, "cannot create tcp socket: %m"); exit(1); } setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); if (bind(sock, (struct sockaddr *)&addr, len) != 0) { syslog(LOG_ERR, "cannot bind tcp: %m"); exit(1); } if ((ltcpxprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) == (SVCXPRT *)NULL) { syslog(LOG_ERR, "couldn't do tcp_create"); exit(1); }#endif (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE); store_fd = open("/var/run/portmap_mapping", O_RDWR|O_CREAT, 0600); load_table(); /* additional initializations */ if (chroot_path) { if (chroot(chroot_path) < 0) { syslog(LOG_ERR, "couldn't do chroot"); exit(1); } } check_startup();#ifdef IGNORE_SIGCHLD /* Lionel Cons <cons@dxcern.cern.ch> */ (void)signal(SIGCHLD, SIG_IGN);#else (void)signal(SIGCHLD, reap);#endif (void)signal(SIGPIPE, SIG_IGN); svc_run(); syslog(LOG_ERR, "run_svc returned unexpectedly"); abort();}/* need to override perror calls in rpc library */void perror(const char *what){ syslog(LOG_ERR, "%s: %m", what);}static struct pmaplist *find_service(u_long prog, u_long vers, u_long prot){ struct pmaplist *hit = NULL; struct pmaplist *pml; for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { if ((pml->pml_map.pm_prog != prog) || (pml->pml_map.pm_prot != prot)) continue; hit = pml; if (pml->pml_map.pm_vers == vers) break; } return (hit);}/* * 1 OK, 0 not */static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt){ struct pmap reg; struct pmaplist *pml, *prevpml, *fnd; struct flagged_pml *fpml; int ans, port; caddr_t t; /* * Later wrappers change the logging severity on the fly. Reset to * defaults before handling the next request. */ allow_severity = LOG_INFO;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -