174462Salfred/* $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ */ 274462Salfred/* $FreeBSD$ */ 374462Salfred 4258564Shrs/*- 5258564Shrs * Copyright (c) 2009, Sun Microsystems, Inc. 6258564Shrs * All rights reserved. 7258564Shrs * 8258564Shrs * Redistribution and use in source and binary forms, with or without 9258564Shrs * modification, are permitted provided that the following conditions are met: 10258564Shrs * - Redistributions of source code must retain the above copyright notice, 11258564Shrs * this list of conditions and the following disclaimer. 12258564Shrs * - Redistributions in binary form must reproduce the above copyright notice, 13258564Shrs * this list of conditions and the following disclaimer in the documentation 14258564Shrs * and/or other materials provided with the distribution. 15258564Shrs * - Neither the name of Sun Microsystems, Inc. nor the names of its 16258564Shrs * contributors may be used to endorse or promote products derived 17258564Shrs * from this software without specific prior written permission. 18258564Shrs * 19258564Shrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20258564Shrs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21258564Shrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22258564Shrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23258564Shrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24258564Shrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25258564Shrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26258564Shrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27258564Shrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28258564Shrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29258564Shrs * POSSIBILITY OF SUCH DAMAGE. 3074462Salfred */ 3174462Salfred/* 3274462Salfred * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. 3374462Salfred */ 3474462Salfred 3574462Salfred/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */ 3674462Salfred 3774462Salfred#if 0 3874462Salfred#ifndef lint 3974462Salfredstatic char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro"; 4074462Salfred#endif 4174462Salfred#endif 4274462Salfred 4374462Salfred/* 4474462Salfred * pmap_svc.c 4574462Salfred * The server procedure for the version 2 portmaper. 4674462Salfred * All the portmapper related interface from the portmap side. 4774462Salfred */ 4874462Salfred 4974462Salfred#ifdef PORTMAP 5074462Salfred#include <sys/types.h> 5174462Salfred#include <sys/socket.h> 5274462Salfred#include <stdio.h> 5374462Salfred#include <rpc/rpc.h> 5474462Salfred#include <rpc/pmap_prot.h> 5574462Salfred#include <rpc/rpcb_prot.h> 5674462Salfred#ifdef RPCBIND_DEBUG 5774462Salfred#include <stdlib.h> 5874462Salfred#endif 5974462Salfred#include "rpcbind.h" 6074462Salfred 61173412Skevlostatic struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, 62173412Skevlo rpcprot_t); 63173412Skevlostatic bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long); 64173412Skevlostatic bool_t pmapproc_getport(struct svc_req *, SVCXPRT *); 65173412Skevlostatic bool_t pmapproc_dump(struct svc_req *, SVCXPRT *); 6674462Salfred 6774462Salfred/* 6874462Salfred * Called for all the version 2 inquiries. 6974462Salfred */ 7074462Salfredvoid 7174462Salfredpmap_service(struct svc_req *rqstp, SVCXPRT *xprt) 7274462Salfred{ 7374462Salfred rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc); 7474462Salfred switch (rqstp->rq_proc) { 7574462Salfred case PMAPPROC_NULL: 7674462Salfred /* 7774462Salfred * Null proc call 7874462Salfred */ 7974462Salfred#ifdef RPCBIND_DEBUG 8074462Salfred if (debugging) 8174462Salfred fprintf(stderr, "PMAPPROC_NULL\n"); 8274462Salfred#endif 8374462Salfred check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS); 8474462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) && 8574462Salfred debugging) { 8674462Salfred if (doabort) { 8774462Salfred rpcbind_abort(); 8874462Salfred } 8974462Salfred } 9074462Salfred break; 9174462Salfred 9274462Salfred case PMAPPROC_SET: 9374462Salfred /* 9474462Salfred * Set a program, version to port mapping 9574462Salfred */ 9674462Salfred pmapproc_change(rqstp, xprt, rqstp->rq_proc); 9774462Salfred break; 9874462Salfred 9974462Salfred case PMAPPROC_UNSET: 10074462Salfred /* 10174462Salfred * Remove a program, version to port mapping. 10274462Salfred */ 10374462Salfred pmapproc_change(rqstp, xprt, rqstp->rq_proc); 10474462Salfred break; 10574462Salfred 10674462Salfred case PMAPPROC_GETPORT: 10774462Salfred /* 10874462Salfred * Lookup the mapping for a program, version and return its 10974462Salfred * port number. 11074462Salfred */ 11174462Salfred pmapproc_getport(rqstp, xprt); 11274462Salfred break; 11374462Salfred 11474462Salfred case PMAPPROC_DUMP: 11574462Salfred /* 11674462Salfred * Return the current set of mapped program, version 11774462Salfred */ 11874462Salfred#ifdef RPCBIND_DEBUG 11974462Salfred if (debugging) 12074462Salfred fprintf(stderr, "PMAPPROC_DUMP\n"); 12174462Salfred#endif 12274462Salfred pmapproc_dump(rqstp, xprt); 12374462Salfred break; 12474462Salfred 12574462Salfred case PMAPPROC_CALLIT: 12674462Salfred /* 12774462Salfred * Calls a procedure on the local machine. If the requested 12874462Salfred * procedure is not registered this procedure does not return 12974462Salfred * error information!! 13074462Salfred * This procedure is only supported on rpc/udp and calls via 13174462Salfred * rpc/udp. It passes null authentication parameters. 13274462Salfred */ 13374462Salfred rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS); 13474462Salfred break; 13574462Salfred 13674462Salfred default: 13774462Salfred svcerr_noproc(xprt); 13874462Salfred break; 13974462Salfred } 14074462Salfred} 14174462Salfred 14274462Salfred/* 14374462Salfred * returns the item with the given program, version number. If that version 14474462Salfred * number is not found, it returns the item with that program number, so that 14574462Salfred * the port number is now returned to the caller. The caller when makes a 14674462Salfred * call to this program, version number, the call will fail and it will 14774462Salfred * return with PROGVERS_MISMATCH. The user can then determine the highest 14874462Salfred * and the lowest version number for this program using clnt_geterr() and 14974462Salfred * use those program version numbers. 15074462Salfred */ 15174462Salfredstatic struct pmaplist * 15274462Salfredfind_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot) 15374462Salfred{ 15474462Salfred register struct pmaplist *hit = NULL; 15574462Salfred register struct pmaplist *pml; 15674462Salfred 15774462Salfred for (pml = list_pml; pml != NULL; pml = pml->pml_next) { 15874462Salfred if ((pml->pml_map.pm_prog != prog) || 15974462Salfred (pml->pml_map.pm_prot != prot)) 16074462Salfred continue; 16174462Salfred hit = pml; 16274462Salfred if (pml->pml_map.pm_vers == vers) 16374462Salfred break; 16474462Salfred } 16574462Salfred return (hit); 16674462Salfred} 16774462Salfred 16874462Salfredstatic bool_t 169104592Salfredpmapproc_change(struct svc_req *rqstp __unused, SVCXPRT *xprt, unsigned long op) 17074462Salfred{ 17174462Salfred struct pmap reg; 17274462Salfred RPCB rpcbreg; 17374462Salfred long ans; 17474462Salfred struct sockaddr_in *who; 17574627Salfred uid_t uid; 17674462Salfred char uidbuf[32]; 17774462Salfred 17874462Salfred#ifdef RPCBIND_DEBUG 17974462Salfred if (debugging) 18074462Salfred fprintf(stderr, "%s request for (%lu, %lu) : ", 18174462Salfred op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET", 18274462Salfred reg.pm_prog, reg.pm_vers); 18374462Salfred#endif 18474462Salfred 18574462Salfred if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 18674462Salfred svcerr_decode(xprt); 18774462Salfred return (FALSE); 18874462Salfred } 18974462Salfred 19074462Salfred if (!check_access(xprt, op, ®, PMAPVERS)) { 19174462Salfred svcerr_weakauth(xprt); 19274462Salfred return FALSE; 19374462Salfred } 19474462Salfred 19574462Salfred who = svc_getcaller(xprt); 19674462Salfred 19774462Salfred /* 19874462Salfred * Can't use getpwnam here. We might end up calling ourselves 19974462Salfred * and looping. 20074462Salfred */ 20174627Salfred if (__rpc_get_local_uid(xprt, &uid) < 0) 20274462Salfred rpcbreg.r_owner = "unknown"; 20374627Salfred else if (uid == 0) 20474462Salfred rpcbreg.r_owner = "superuser"; 20574462Salfred else { 20674462Salfred /* r_owner will be strdup-ed later */ 20774627Salfred snprintf(uidbuf, sizeof uidbuf, "%d", uid); 20874462Salfred rpcbreg.r_owner = uidbuf; 20974462Salfred } 21074462Salfred 21174462Salfred rpcbreg.r_prog = reg.pm_prog; 21274462Salfred rpcbreg.r_vers = reg.pm_vers; 21374462Salfred 21474462Salfred if (op == PMAPPROC_SET) { 21574462Salfred char buf[32]; 21674462Salfred 21779719Siedowse snprintf(buf, sizeof buf, "0.0.0.0.%d.%d", 21879719Siedowse (int)((reg.pm_port >> 8) & 0xff), 21979719Siedowse (int)(reg.pm_port & 0xff)); 22074462Salfred rpcbreg.r_addr = buf; 22174462Salfred if (reg.pm_prot == IPPROTO_UDP) { 22274462Salfred rpcbreg.r_netid = udptrans; 22374462Salfred } else if (reg.pm_prot == IPPROTO_TCP) { 22474462Salfred rpcbreg.r_netid = tcptrans; 22574462Salfred } else { 22674462Salfred ans = FALSE; 22774462Salfred goto done_change; 22874462Salfred } 22974462Salfred ans = map_set(&rpcbreg, rpcbreg.r_owner); 23074462Salfred } else if (op == PMAPPROC_UNSET) { 23174462Salfred bool_t ans1, ans2; 23274462Salfred 23374462Salfred rpcbreg.r_addr = NULL; 23474462Salfred rpcbreg.r_netid = tcptrans; 23574462Salfred ans1 = map_unset(&rpcbreg, rpcbreg.r_owner); 23674462Salfred rpcbreg.r_netid = udptrans; 23774462Salfred ans2 = map_unset(&rpcbreg, rpcbreg.r_owner); 23874462Salfred ans = ans1 || ans2; 23974462Salfred } else { 24074462Salfred ans = FALSE; 24174462Salfred } 24274462Salfreddone_change: 24374462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) && 24474462Salfred debugging) { 24574462Salfred fprintf(stderr, "portmap: svc_sendreply\n"); 24674462Salfred if (doabort) { 24774462Salfred rpcbind_abort(); 24874462Salfred } 24974462Salfred } 25074462Salfred#ifdef RPCBIND_DEBUG 25174462Salfred if (debugging) 25274462Salfred fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 25374462Salfred#endif 25474462Salfred if (op == PMAPPROC_SET) 25574462Salfred rpcbs_set(RPCBVERS_2_STAT, ans); 25674462Salfred else 25774462Salfred rpcbs_unset(RPCBVERS_2_STAT, ans); 25874462Salfred return (TRUE); 25974462Salfred} 26074462Salfred 26174462Salfred/* ARGSUSED */ 26274462Salfredstatic bool_t 263104592Salfredpmapproc_getport(struct svc_req *rqstp __unused, SVCXPRT *xprt) 26474462Salfred{ 26574462Salfred struct pmap reg; 26674462Salfred long lport; 26774462Salfred int port = 0; 26874462Salfred struct pmaplist *fnd; 26974462Salfred#ifdef RPCBIND_DEBUG 27074462Salfred char *uaddr; 27174462Salfred#endif 27274462Salfred 27374462Salfred if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 27474462Salfred svcerr_decode(xprt); 27574462Salfred return (FALSE); 27674462Salfred } 27774462Salfred 27874462Salfred if (!check_access(xprt, PMAPPROC_GETPORT, ®, PMAPVERS)) { 27974462Salfred svcerr_weakauth(xprt); 28074462Salfred return FALSE; 28174462Salfred } 28274462Salfred 28374462Salfred#ifdef RPCBIND_DEBUG 28474462Salfred if (debugging) { 28574462Salfred uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid), 28674462Salfred svc_getrpccaller(xprt)); 28774462Salfred fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :", 28874462Salfred reg.pm_prog, reg.pm_vers, 28974462Salfred reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr); 29074462Salfred free(uaddr); 29174462Salfred } 29274462Salfred#endif 29374462Salfred fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot); 29474462Salfred if (fnd) { 29574462Salfred char serveuaddr[32], *ua; 29674462Salfred int h1, h2, h3, h4, p1, p2; 29774462Salfred char *netid; 29874462Salfred 29974462Salfred if (reg.pm_prot == IPPROTO_UDP) { 30074462Salfred ua = udp_uaddr; 30174462Salfred netid = udptrans; 30274462Salfred } else { 30374462Salfred ua = tcp_uaddr; /* To get the len */ 30474462Salfred netid = tcptrans; 30574462Salfred } 30674462Salfred if (ua == NULL) { 30774462Salfred goto sendreply; 30874462Salfred } 30974462Salfred if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3, 31074462Salfred &h4, &p1, &p2) == 6) { 31174462Salfred p1 = (fnd->pml_map.pm_port >> 8) & 0xff; 31274462Salfred p2 = (fnd->pml_map.pm_port) & 0xff; 31379719Siedowse snprintf(serveuaddr, sizeof serveuaddr, 31479719Siedowse "%d.%d.%d.%d.%d.%d", h1, h2, h3, h4, p1, p2); 31574462Salfred if (is_bound(netid, serveuaddr)) { 31674462Salfred port = fnd->pml_map.pm_port; 31774462Salfred } else { /* this service is dead; delete it */ 31874462Salfred delete_prog(reg.pm_prog); 31974462Salfred } 32074462Salfred } 32174462Salfred } 32274462Salfredsendreply: 32374462Salfred lport = port; 32474462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) && 32574462Salfred debugging) { 32674462Salfred (void) fprintf(stderr, "portmap: svc_sendreply\n"); 32774462Salfred if (doabort) { 32874462Salfred rpcbind_abort(); 32974462Salfred } 33074462Salfred } 33174462Salfred#ifdef RPCBIND_DEBUG 33274462Salfred if (debugging) 33374462Salfred fprintf(stderr, "port = %d\n", port); 33474462Salfred#endif 33574462Salfred rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers, 33674462Salfred reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans, 33774462Salfred port ? udptrans : ""); 33874462Salfred 33974462Salfred return (TRUE); 34074462Salfred} 34174462Salfred 34274462Salfred/* ARGSUSED */ 34374462Salfredstatic bool_t 344104592Salfredpmapproc_dump(struct svc_req *rqstp __unused, SVCXPRT *xprt) 34574462Salfred{ 34674462Salfred if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) { 34774462Salfred svcerr_decode(xprt); 34874462Salfred return (FALSE); 34974462Salfred } 35074462Salfred 35174462Salfred if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) { 35274462Salfred svcerr_weakauth(xprt); 35374462Salfred return FALSE; 35474462Salfred } 35574462Salfred 35674462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr, 35774462Salfred (caddr_t)&list_pml)) && debugging) { 35874462Salfred if (debugging) 35974462Salfred (void) fprintf(stderr, "portmap: svc_sendreply\n"); 36074462Salfred if (doabort) { 36174462Salfred rpcbind_abort(); 36274462Salfred } 36374462Salfred } 36474462Salfred return (TRUE); 36574462Salfred} 36674462Salfred 36774462Salfred#endif /* PORTMAP */ 368