pmap_svc.c revision 74462
1234353Sdim/* $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ */ 2193323Sed/* $FreeBSD: head/usr.sbin/rpcbind/pmap_svc.c 74462 2001-03-19 12:50:13Z alfred $ */ 3193323Sed 4193323Sed/* 5193323Sed * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 6193323Sed * unrestricted use provided that this legend is included on all tape 7193323Sed * media and as a part of the software program in whole or part. Users 8193323Sed * may copy or modify Sun RPC without charge, but are not authorized 9193323Sed * to license or distribute it to anyone else except as part of a product or 10224145Sdim * program developed by the user. 11193323Sed * 12193323Sed * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 13193323Sed * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 14193323Sed * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 15193323Sed * 16193323Sed * Sun RPC is provided with no support and without any obligation on the 17210299Sed * part of Sun Microsystems, Inc. to assist in its use, correction, 18249423Sdim * modification or enhancement. 19224145Sdim * 20193323Sed * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 21193323Sed * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 22224145Sdim * OR ANY PART THEREOF. 23224145Sdim * 24224145Sdim * In no event will Sun Microsystems, Inc. be liable for any lost revenue 25193323Sed * or profits or other special, indirect and consequential damages, even if 26193323Sed * Sun has been advised of the possibility of such damages. 27224145Sdim * 28193323Sed * Sun Microsystems, Inc. 29204642Srdivacky * 2550 Garcia Avenue 30198090Srdivacky * Mountain View, California 94043 31204642Srdivacky */ 32193323Sed/* 33193323Sed * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. 34198090Srdivacky */ 35198090Srdivacky 36198090Srdivacky/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */ 37198090Srdivacky 38198090Srdivacky#if 0 39193323Sed#ifndef lint 40193323Sedstatic char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro"; 41193323Sed#endif 42224145Sdim#endif 43193323Sed 44193323Sed/* 45263508Sdim * pmap_svc.c 46193323Sed * The server procedure for the version 2 portmaper. 47193323Sed * All the portmapper related interface from the portmap side. 48193323Sed */ 49193323Sed 50193323Sed#ifdef PORTMAP 51193323Sed#include <sys/types.h> 52234353Sdim#include <sys/socket.h> 53263508Sdim#include <stdio.h> 54234353Sdim#include <rpc/rpc.h> 55234353Sdim#include <rpc/pmap_prot.h> 56234353Sdim#include <rpc/rpcb_prot.h> 57234353Sdim#ifdef RPCBIND_DEBUG 58239462Sdim#include <stdlib.h> 59193323Sed#endif 60193323Sed#include "rpcbind.h" 61193323Sed 62204642Srdivackystatic struct pmaplist *find_service_pmap __P((rpcprog_t, rpcvers_t, 63193323Sed rpcprot_t)); 64193323Sedstatic bool_t pmapproc_change __P((struct svc_req *, SVCXPRT *, u_long)); 65193323Sedstatic bool_t pmapproc_getport __P((struct svc_req *, SVCXPRT *)); 66193323Sedstatic bool_t pmapproc_dump __P((struct svc_req *, SVCXPRT *)); 67193323Sed 68193323Sed/* 69193323Sed * Called for all the version 2 inquiries. 70193323Sed */ 71198090Srdivackyvoid 72198090Srdivackypmap_service(struct svc_req *rqstp, SVCXPRT *xprt) 73198090Srdivacky{ 74204642Srdivacky rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc); 75193323Sed switch (rqstp->rq_proc) { 76193323Sed case PMAPPROC_NULL: 77193323Sed /* 78193323Sed * Null proc call 79218893Sdim */ 80218893Sdim#ifdef RPCBIND_DEBUG 81218893Sdim if (debugging) 82195098Sed fprintf(stderr, "PMAPPROC_NULL\n"); 83195098Sed#endif 84195098Sed check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS); 85206124Srdivacky if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) && 86206124Srdivacky debugging) { 87206124Srdivacky if (doabort) { 88239462Sdim rpcbind_abort(); 89239462Sdim } 90212904Sdim } 91239462Sdim break; 92239462Sdim 93195098Sed case PMAPPROC_SET: 94195098Sed /* 95195098Sed * Set a program, version to port mapping 96195098Sed */ 97234353Sdim pmapproc_change(rqstp, xprt, rqstp->rq_proc); 98234353Sdim break; 99234353Sdim 100263508Sdim case PMAPPROC_UNSET: 101263508Sdim /* 102263508Sdim * Remove a program, version to port mapping. 103226633Sdim */ 104226633Sdim pmapproc_change(rqstp, xprt, rqstp->rq_proc); 105226633Sdim break; 106226633Sdim 107226633Sdim case PMAPPROC_GETPORT: 108226633Sdim /* 109226633Sdim * Lookup the mapping for a program, version and return its 110226633Sdim * port number. 111226633Sdim */ 112234353Sdim pmapproc_getport(rqstp, xprt); 113234353Sdim break; 114234353Sdim 115226633Sdim case PMAPPROC_DUMP: 116226633Sdim /* 117226633Sdim * Return the current set of mapped program, version 118226633Sdim */ 119226633Sdim#ifdef RPCBIND_DEBUG 120226633Sdim if (debugging) 121234353Sdim fprintf(stderr, "PMAPPROC_DUMP\n"); 122234353Sdim#endif 123234353Sdim pmapproc_dump(rqstp, xprt); 124243830Sdim break; 125243830Sdim 126243830Sdim case PMAPPROC_CALLIT: 127249423Sdim /* 128249423Sdim * Calls a procedure on the local machine. If the requested 129249423Sdim * procedure is not registered this procedure does not return 130249423Sdim * error information!! 131249423Sdim * This procedure is only supported on rpc/udp and calls via 132249423Sdim * rpc/udp. It passes null authentication parameters. 133263508Sdim */ 134263508Sdim rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS); 135263508Sdim break; 136249423Sdim 137249423Sdim default: 138249423Sdim svcerr_noproc(xprt); 139249423Sdim break; 140249423Sdim } 141249423Sdim} 142193323Sed 143193323Sed/* 144201360Srdivacky * returns the item with the given program, version number. If that version 145206083Srdivacky * number is not found, it returns the item with that program number, so that 146206083Srdivacky * the port number is now returned to the caller. The caller when makes a 147206083Srdivacky * call to this program, version number, the call will fail and it will 148204642Srdivacky * return with PROGVERS_MISMATCH. The user can then determine the highest 149207618Srdivacky * and the lowest version number for this program using clnt_geterr() and 150202375Srdivacky * use those program version numbers. 151202375Srdivacky */ 152226633Sdimstatic struct pmaplist * 153226633Sdimfind_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot) 154226633Sdim{ 155226633Sdim register struct pmaplist *hit = NULL; 156234353Sdim register struct pmaplist *pml; 157234353Sdim 158234353Sdim for (pml = list_pml; pml != NULL; pml = pml->pml_next) { 159234353Sdim if ((pml->pml_map.pm_prog != prog) || 160243830Sdim (pml->pml_map.pm_prot != prot)) 161243830Sdim continue; 162243830Sdim hit = pml; 163243830Sdim if (pml->pml_map.pm_vers == vers) 164234353Sdim break; 165234353Sdim } 166234353Sdim return (hit); 167249423Sdim} 168249423Sdim 169249423Sdimstatic bool_t 170249423Sdimpmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op) 171249423Sdim{ 172249423Sdim struct pmap reg; 173249423Sdim RPCB rpcbreg; 174251662Sdim long ans; 175251662Sdim struct sockaddr_in *who; 176251662Sdim struct cmsgcred *cmcred; 177249423Sdim char uidbuf[32]; 178263508Sdim 179263508Sdim#ifdef RPCBIND_DEBUG 180263508Sdim if (debugging) 181263508Sdim fprintf(stderr, "%s request for (%lu, %lu) : ", 182263508Sdim op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET", 183263508Sdim reg.pm_prog, reg.pm_vers); 184263508Sdim#endif 185263508Sdim 186263508Sdim if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 187193323Sed svcerr_decode(xprt); 188193323Sed return (FALSE); 189193323Sed } 190193323Sed 191193323Sed if (!check_access(xprt, op, ®, PMAPVERS)) { 192193323Sed svcerr_weakauth(xprt); 193193323Sed return FALSE; 194218893Sdim } 195210299Sed 196210299Sed who = svc_getcaller(xprt); 197239462Sdim cmcred = __svc_getcallercreds(xprt); 198234353Sdim 199234353Sdim /* 200193323Sed * Can't use getpwnam here. We might end up calling ourselves 201193323Sed * and looping. 202249423Sdim */ 203249423Sdim if (cmcred == NULL) 204249423Sdim rpcbreg.r_owner = "unknown"; 205224145Sdim else if (cmcred->cmcred_uid == 0) 206224145Sdim rpcbreg.r_owner = "superuser"; 207193323Sed else { 208193323Sed /* r_owner will be strdup-ed later */ 209193323Sed snprintf(uidbuf, sizeof uidbuf, "%d", cmcred->cmcred_uid); 210198090Srdivacky rpcbreg.r_owner = uidbuf; 211193323Sed } 212224145Sdim 213224145Sdim rpcbreg.r_prog = reg.pm_prog; 214224145Sdim rpcbreg.r_vers = reg.pm_vers; 215193323Sed 216193323Sed if (op == PMAPPROC_SET) { 217193323Sed char buf[32]; 218193323Sed 219193323Sed sprintf(buf, "0.0.0.0.%d.%d", (int)((reg.pm_port >> 8) & 0xff), 220193323Sed (int)(reg.pm_port & 0xff)); 221193323Sed rpcbreg.r_addr = buf; 222193323Sed if (reg.pm_prot == IPPROTO_UDP) { 223193323Sed rpcbreg.r_netid = udptrans; 224193323Sed } else if (reg.pm_prot == IPPROTO_TCP) { 225193323Sed rpcbreg.r_netid = tcptrans; 226193323Sed } else { 227224145Sdim ans = FALSE; 228193323Sed goto done_change; 229193323Sed } 230193323Sed ans = map_set(&rpcbreg, rpcbreg.r_owner); 231193323Sed } else if (op == PMAPPROC_UNSET) { 232193323Sed bool_t ans1, ans2; 233249423Sdim 234249423Sdim rpcbreg.r_addr = NULL; 235249423Sdim rpcbreg.r_netid = tcptrans; 236249423Sdim ans1 = map_unset(&rpcbreg, rpcbreg.r_owner); 237249423Sdim rpcbreg.r_netid = udptrans; 238249423Sdim ans2 = map_unset(&rpcbreg, rpcbreg.r_owner); 239249423Sdim ans = ans1 || ans2; 240249423Sdim } else { 241249423Sdim ans = FALSE; 242249423Sdim } 243193323Seddone_change: 244249423Sdim if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) && 245249423Sdim debugging) { 246249423Sdim fprintf(stderr, "portmap: svc_sendreply\n"); 247249423Sdim if (doabort) { 248249423Sdim rpcbind_abort(); 249249423Sdim } 250249423Sdim } 251249423Sdim#ifdef RPCBIND_DEBUG 252249423Sdim if (debugging) 253249423Sdim fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 254193323Sed#endif 255193323Sed if (op == PMAPPROC_SET) 256193323Sed rpcbs_set(RPCBVERS_2_STAT, ans); 257205218Srdivacky else 258193323Sed rpcbs_unset(RPCBVERS_2_STAT, ans); 259193323Sed return (TRUE); 260193323Sed} 261193323Sed 262193323Sed/* ARGSUSED */ 263193323Sedstatic bool_t 264193323Sedpmapproc_getport(struct svc_req *rqstp, SVCXPRT *xprt) 265234353Sdim{ 266234353Sdim struct pmap reg; 267263508Sdim long lport; 268249423Sdim int port = 0; 269249423Sdim struct pmaplist *fnd; 270193323Sed#ifdef RPCBIND_DEBUG 271193323Sed char *uaddr; 272193323Sed#endif 273218893Sdim 274206124Srdivacky if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 275239462Sdim svcerr_decode(xprt); 276239462Sdim return (FALSE); 277243830Sdim } 278243830Sdim 279234353Sdim if (!check_access(xprt, PMAPPROC_GETPORT, ®, PMAPVERS)) { 280263508Sdim svcerr_weakauth(xprt); 281226633Sdim return FALSE; 282226633Sdim } 283226633Sdim 284234353Sdim#ifdef RPCBIND_DEBUG 285226633Sdim if (debugging) { 286226633Sdim uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid), 287234353Sdim svc_getrpccaller(xprt)); 288243830Sdim fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :", 289249423Sdim reg.pm_prog, reg.pm_vers, 290249423Sdim reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr); 291263508Sdim free(uaddr); 292249423Sdim } 293249423Sdim#endif 294193323Sed fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot); 295206083Srdivacky if (fnd) { 296202375Srdivacky char serveuaddr[32], *ua; 297226633Sdim int h1, h2, h3, h4, p1, p2; 298234353Sdim char *netid; 299243830Sdim 300249423Sdim if (reg.pm_prot == IPPROTO_UDP) { 301249423Sdim ua = udp_uaddr; 302251662Sdim netid = udptrans; 303263508Sdim } else { 304263508Sdim ua = tcp_uaddr; /* To get the len */ 305263508Sdim netid = tcptrans; 306193323Sed } 307234353Sdim if (ua == NULL) { 308234353Sdim goto sendreply; 309221345Sdim } 310218893Sdim if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3, 311221345Sdim &h4, &p1, &p2) == 6) { 312221345Sdim p1 = (fnd->pml_map.pm_port >> 8) & 0xff; 313221345Sdim p2 = (fnd->pml_map.pm_port) & 0xff; 314221345Sdim sprintf(serveuaddr, "%d.%d.%d.%d.%d.%d", 315221345Sdim h1, h2, h3, h4, p1, p2); 316221345Sdim if (is_bound(netid, serveuaddr)) { 317221345Sdim port = fnd->pml_map.pm_port; 318243830Sdim } else { /* this service is dead; delete it */ 319243830Sdim delete_prog(reg.pm_prog); 320243830Sdim } 321243830Sdim } 322263508Sdim } 323263508Sdimsendreply: 324226633Sdim lport = port; 325226633Sdim if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) && 326210299Sed debugging) { 327218893Sdim (void) fprintf(stderr, "portmap: svc_sendreply\n"); 328210299Sed if (doabort) { 329234353Sdim rpcbind_abort(); 330243830Sdim } 331243830Sdim } 332243830Sdim#ifdef RPCBIND_DEBUG 333243830Sdim if (debugging) 334234353Sdim fprintf(stderr, "port = %d\n", port); 335218893Sdim#endif 336263508Sdim rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers, 337263508Sdim reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans, 338193323Sed port ? udptrans : ""); 339234353Sdim 340193323Sed return (TRUE); 341193323Sed} 342212904Sdim 343263508Sdim/* ARGSUSED */ 344212904Sdimstatic bool_t 345212904Sdimpmapproc_dump(struct svc_req *rqstp, SVCXPRT *xprt) 346193323Sed{ 347193323Sed if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) { 348193323Sed svcerr_decode(xprt); 349198090Srdivacky return (FALSE); 350198090Srdivacky } 351198090Srdivacky 352198090Srdivacky if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) { 353198090Srdivacky svcerr_weakauth(xprt); 354198090Srdivacky return FALSE; 355198090Srdivacky } 356198090Srdivacky 357198090Srdivacky if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr, 358198090Srdivacky (caddr_t)&list_pml)) && debugging) { 359256030Sdim if (debugging) 360256030Sdim (void) fprintf(stderr, "portmap: svc_sendreply\n"); 361204642Srdivacky if (doabort) { 362256030Sdim rpcbind_abort(); 363256030Sdim } 364256030Sdim } 365256030Sdim return (TRUE); 366256030Sdim} 367198090Srdivacky 368198090Srdivacky#endif /* PORTMAP */ 369198090Srdivacky