1272343Sngie/* $NetBSD: pmap_svc.c,v 1.2 2013/10/19 17:45:00 christos Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5272343Sngie * unrestricted use provided that this legend is included on all tape 6272343Sngie * media and as a part of the software program in whole or part. Users 7272343Sngie * may copy or modify Sun RPC without charge, but are not authorized 8272343Sngie * to license or distribute it to anyone else except as part of a product or 9272343Sngie * program developed by the user. 10272343Sngie * 11272343Sngie * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12272343Sngie * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13272343Sngie * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14272343Sngie * 15272343Sngie * Sun RPC is provided with no support and without any obligation on the 16272343Sngie * part of Sun Microsystems, Inc. to assist in its use, correction, 17272343Sngie * modification or enhancement. 18272343Sngie * 19272343Sngie * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20272343Sngie * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21272343Sngie * OR ANY PART THEREOF. 22272343Sngie * 23272343Sngie * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24272343Sngie * or profits or other special, indirect and consequential damages, even if 25272343Sngie * Sun has been advised of the possibility of such damages. 26272343Sngie * 27272343Sngie * Sun Microsystems, Inc. 28272343Sngie * 2550 Garcia Avenue 29272343Sngie * Mountain View, California 94043 30272343Sngie */ 31272343Sngie/* 32272343Sngie * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. 33272343Sngie */ 34272343Sngie 35272343Sngie/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */ 36272343Sngie 37272343Sngie#if 0 38272343Sngie#ifndef lint 39272343Sngiestatic char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro"; 40272343Sngie#endif 41272343Sngie#endif 42272343Sngie 43272343Sngie/* 44272343Sngie * pmap_svc.c 45272343Sngie * The server procedure for the version 2 portmapper. 46272343Sngie * All the portmapper related interface from the portmap side. 47272343Sngie */ 48272343Sngie 49272343Sngie#ifdef PORTMAP 50272343Sngie#include <sys/types.h> 51272343Sngie#include <sys/socket.h> 52272343Sngie#include <stdio.h> 53272343Sngie#include <rpc/rpc.h> 54272343Sngie#include <rpc/pmap_prot.h> 55272343Sngie#include <rpc/rpcb_prot.h> 56272343Sngie#ifdef RPCBIND_DEBUG 57272343Sngie#include <stdlib.h> 58272343Sngie#endif 59272343Sngie#include "rpcbind.h" 60272343Sngie 61272343Sngiestatic struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, rpcprot_t); 62272343Sngiestatic bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long); 63272343Sngiestatic bool_t pmapproc_getport(struct svc_req *, SVCXPRT *); 64272343Sngiestatic bool_t pmapproc_dump(struct svc_req *, SVCXPRT *); 65272343Sngie 66272343Sngie/* 67272343Sngie * Called for all the version 2 inquiries. 68272343Sngie */ 69272343Sngievoid 70272343Sngiepmap_service(struct svc_req *rqstp, SVCXPRT *xprt) 71272343Sngie{ 72272343Sngie rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc); 73272343Sngie switch (rqstp->rq_proc) { 74272343Sngie case PMAPPROC_NULL: 75272343Sngie /* 76272343Sngie * Null proc call 77272343Sngie */ 78272343Sngie#ifdef RPCBIND_DEBUG 79272343Sngie if (debugging) 80272343Sngie fprintf(stderr, "PMAPPROC_NULL\n"); 81272343Sngie#endif 82272343Sngie check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS); 83272343Sngie if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) && 84272343Sngie debugging) { 85272343Sngie if (doabort) { 86272343Sngie rpcbind_abort(); 87272343Sngie } 88272343Sngie } 89272343Sngie break; 90272343Sngie 91272343Sngie case PMAPPROC_SET: 92272343Sngie /* 93272343Sngie * Set a program, version to port mapping 94272343Sngie */ 95272343Sngie pmapproc_change(rqstp, xprt, rqstp->rq_proc); 96272343Sngie break; 97272343Sngie 98272343Sngie case PMAPPROC_UNSET: 99272343Sngie /* 100272343Sngie * Remove a program, version to port mapping. 101272343Sngie */ 102272343Sngie pmapproc_change(rqstp, xprt, rqstp->rq_proc); 103272343Sngie break; 104272343Sngie 105272343Sngie case PMAPPROC_GETPORT: 106272343Sngie /* 107272343Sngie * Lookup the mapping for a program, version and return its 108272343Sngie * port number. 109272343Sngie */ 110272343Sngie pmapproc_getport(rqstp, xprt); 111272343Sngie break; 112272343Sngie 113272343Sngie case PMAPPROC_DUMP: 114272343Sngie /* 115272343Sngie * Return the current set of mapped program, version 116272343Sngie */ 117272343Sngie#ifdef RPCBIND_DEBUG 118272343Sngie if (debugging) 119272343Sngie fprintf(stderr, "PMAPPROC_DUMP\n"); 120272343Sngie#endif 121272343Sngie pmapproc_dump(rqstp, xprt); 122272343Sngie break; 123272343Sngie 124272343Sngie case PMAPPROC_CALLIT: 125272343Sngie /* 126272343Sngie * Calls a procedure on the local machine. If the requested 127272343Sngie * procedure is not registered this procedure does not return 128272343Sngie * error information!! 129272343Sngie * This procedure is only supported on rpc/udp and calls via 130272343Sngie * rpc/udp. It passes null authentication parameters. 131272343Sngie */ 132272343Sngie rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS); 133272343Sngie break; 134272343Sngie 135272343Sngie default: 136272343Sngie svcerr_noproc(xprt); 137272343Sngie break; 138272343Sngie } 139272343Sngie} 140272343Sngie 141272343Sngie/* 142272343Sngie * returns the item with the given program, version number. If that version 143272343Sngie * number is not found, it returns the item with that program number, so that 144272343Sngie * the port number is now returned to the caller. The caller when makes a 145272343Sngie * call to this program, version number, the call will fail and it will 146272343Sngie * return with PROGVERS_MISMATCH. The user can then determine the highest 147272343Sngie * and the lowest version number for this program using clnt_geterr() and 148272343Sngie * use those program version numbers. 149272343Sngie */ 150272343Sngiestatic struct pmaplist * 151272343Sngiefind_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot) 152272343Sngie{ 153272343Sngie register struct pmaplist *hit = NULL; 154272343Sngie register struct pmaplist *pml; 155272343Sngie 156272343Sngie for (pml = list_pml; pml != NULL; pml = pml->pml_next) { 157272343Sngie if ((pml->pml_map.pm_prog != prog) || 158272343Sngie (pml->pml_map.pm_prot != prot)) 159272343Sngie continue; 160272343Sngie hit = pml; 161272343Sngie if (pml->pml_map.pm_vers == vers) 162272343Sngie break; 163272343Sngie } 164272343Sngie return (hit); 165272343Sngie} 166272343Sngie 167272343Sngiestatic bool_t 168272343Sngiepmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op) 169272343Sngie{ 170272343Sngie struct pmap reg; 171272343Sngie RPCB rpcbreg; 172272343Sngie long ans; 173272343Sngie struct sockcred *sc; 174272343Sngie char uidbuf[32]; 175272343Sngie 176272343Sngie#ifdef RPCBIND_DEBUG 177272343Sngie if (debugging) 178272343Sngie fprintf(stderr, "%s request for (%lu, %lu) : ", 179272343Sngie op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET", 180272343Sngie reg.pm_prog, reg.pm_vers); 181272343Sngie#endif 182272343Sngie 183272343Sngie if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 184272343Sngie svcerr_decode(xprt); 185272343Sngie return (FALSE); 186272343Sngie } 187272343Sngie 188272343Sngie if (!check_access(xprt, op, ®, PMAPVERS)) { 189272343Sngie svcerr_weakauth(xprt); 190272343Sngie return FALSE; 191272343Sngie } 192272343Sngie 193272343Sngie (void)svc_getcaller(xprt); 194272343Sngie sc = __svc_getcallercreds(xprt); 195272343Sngie 196272343Sngie /* 197272343Sngie * Can't use getpwnam here. We might end up calling ourselves 198272343Sngie * and looping. 199272343Sngie */ 200272343Sngie if (sc == NULL) 201272343Sngie rpcbreg.r_owner = __UNCONST(rpcbind_unknown); 202272343Sngie else if (sc->sc_uid == 0) 203272343Sngie rpcbreg.r_owner = __UNCONST(rpcbind_superuser); 204272343Sngie else { 205272343Sngie /* r_owner will be strdup-ed later */ 206272343Sngie snprintf(uidbuf, sizeof uidbuf, "%d", sc->sc_uid); 207272343Sngie rpcbreg.r_owner = uidbuf; 208272343Sngie } 209272343Sngie 210272343Sngie rpcbreg.r_prog = reg.pm_prog; 211272343Sngie rpcbreg.r_vers = reg.pm_vers; 212272343Sngie 213272343Sngie if (op == PMAPPROC_SET) { 214272343Sngie char buf[32]; 215272343Sngie 216272343Sngie snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d", 217272343Sngie (int)((reg.pm_port >> 8) & 0xff), 218272343Sngie (int)(reg.pm_port & 0xff)); 219272343Sngie rpcbreg.r_addr = buf; 220272343Sngie if (reg.pm_prot == IPPROTO_UDP) { 221272343Sngie rpcbreg.r_netid = __UNCONST(udptrans); 222272343Sngie } else if (reg.pm_prot == IPPROTO_TCP) { 223272343Sngie rpcbreg.r_netid = __UNCONST(tcptrans); 224272343Sngie } else { 225272343Sngie ans = FALSE; 226272343Sngie goto done_change; 227272343Sngie } 228272343Sngie ans = map_set(&rpcbreg, rpcbreg.r_owner); 229272343Sngie } else if (op == PMAPPROC_UNSET) { 230272343Sngie bool_t ans1, ans2; 231272343Sngie 232272343Sngie rpcbreg.r_addr = NULL; 233272343Sngie rpcbreg.r_netid = __UNCONST(tcptrans); 234272343Sngie ans1 = map_unset(&rpcbreg, rpcbreg.r_owner); 235272343Sngie rpcbreg.r_netid = __UNCONST(udptrans); 236272343Sngie ans2 = map_unset(&rpcbreg, rpcbreg.r_owner); 237272343Sngie ans = ans1 || ans2; 238272343Sngie } else { 239272343Sngie ans = FALSE; 240272343Sngie } 241272343Sngiedone_change: 242272343Sngie if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) && 243272343Sngie debugging) { 244272343Sngie fprintf(stderr, "portmap: svc_sendreply\n"); 245272343Sngie if (doabort) { 246272343Sngie rpcbind_abort(); 247272343Sngie } 248272343Sngie } 249272343Sngie#ifdef RPCBIND_DEBUG 250272343Sngie if (debugging) 251272343Sngie fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 252272343Sngie#endif 253272343Sngie if (op == PMAPPROC_SET) 254272343Sngie rpcbs_set(RPCBVERS_2_STAT, ans); 255272343Sngie else 256272343Sngie rpcbs_unset(RPCBVERS_2_STAT, ans); 257272343Sngie return (TRUE); 258272343Sngie} 259272343Sngie 260272343Sngie/* ARGSUSED */ 261272343Sngiestatic bool_t 262272343Sngiepmapproc_getport(struct svc_req *rqstp, SVCXPRT *xprt) 263272343Sngie{ 264272343Sngie struct pmap reg; 265272343Sngie long lport; 266272343Sngie int port = 0; 267272343Sngie struct pmaplist *fnd; 268272343Sngie#ifdef RPCBIND_DEBUG 269272343Sngie char *uaddr; 270272343Sngie#endif 271272343Sngie 272272343Sngie if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 273272343Sngie svcerr_decode(xprt); 274272343Sngie return (FALSE); 275272343Sngie } 276272343Sngie 277272343Sngie if (!check_access(xprt, PMAPPROC_GETPORT, ®, PMAPVERS)) { 278272343Sngie svcerr_weakauth(xprt); 279272343Sngie return FALSE; 280272343Sngie } 281272343Sngie 282272343Sngie#ifdef RPCBIND_DEBUG 283272343Sngie if (debugging) { 284272343Sngie uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid), 285272343Sngie svc_getrpccaller(xprt)); 286272343Sngie fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :", 287272343Sngie reg.pm_prog, reg.pm_vers, 288272343Sngie reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr); 289272343Sngie free(uaddr); 290272343Sngie } 291272343Sngie#endif 292272343Sngie fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot); 293272343Sngie if (fnd) { 294272343Sngie char serveuaddr[32]; 295272343Sngie int h1, h2, h3, h4, p1, p2; 296272343Sngie const char *netid, *ua; 297272343Sngie 298272343Sngie if (reg.pm_prot == IPPROTO_UDP) { 299272343Sngie ua = udp_uaddr; 300272343Sngie netid = udptrans; 301272343Sngie } else { 302272343Sngie ua = tcp_uaddr; /* To get the len */ 303272343Sngie netid = tcptrans; 304272343Sngie } 305272343Sngie if (ua == NULL) { 306272343Sngie goto sendreply; 307272343Sngie } 308272343Sngie if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3, 309272343Sngie &h4, &p1, &p2) == 6) { 310272343Sngie p1 = (fnd->pml_map.pm_port >> 8) & 0xff; 311272343Sngie p2 = (fnd->pml_map.pm_port) & 0xff; 312272343Sngie snprintf(serveuaddr, sizeof(serveuaddr), 313272343Sngie "%d.%d.%d.%d.%d.%d", h1, h2, h3, h4, p1, p2); 314272343Sngie if (is_bound(netid, serveuaddr)) { 315272343Sngie port = fnd->pml_map.pm_port; 316272343Sngie } else { /* this service is dead; delete it */ 317272343Sngie delete_prog(reg.pm_prog); 318272343Sngie } 319272343Sngie } 320272343Sngie } 321272343Sngiesendreply: 322272343Sngie lport = port; 323272343Sngie if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) && 324272343Sngie debugging) { 325272343Sngie (void) fprintf(stderr, "portmap: svc_sendreply\n"); 326272343Sngie if (doabort) { 327272343Sngie rpcbind_abort(); 328272343Sngie } 329272343Sngie } 330272343Sngie#ifdef RPCBIND_DEBUG 331272343Sngie if (debugging) 332272343Sngie fprintf(stderr, "port = %d\n", port); 333272343Sngie#endif 334272343Sngie rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers, 335272343Sngie reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans, 336272343Sngie port ? udptrans : ""); 337272343Sngie 338272343Sngie return (TRUE); 339272343Sngie} 340272343Sngie 341272343Sngie/* ARGSUSED */ 342272343Sngiestatic bool_t 343272343Sngiepmapproc_dump(struct svc_req *rqstp, SVCXPRT *xprt) 344272343Sngie{ 345272343Sngie if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) { 346272343Sngie svcerr_decode(xprt); 347272343Sngie return (FALSE); 348272343Sngie } 349272343Sngie 350272343Sngie if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) { 351272343Sngie svcerr_weakauth(xprt); 352272343Sngie return FALSE; 353272343Sngie } 354272343Sngie 355272343Sngie if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr, 356272343Sngie (caddr_t)&list_pml)) && debugging) { 357272343Sngie if (debugging) 358272343Sngie (void) fprintf(stderr, "portmap: svc_sendreply\n"); 359272343Sngie if (doabort) { 360272343Sngie rpcbind_abort(); 361272343Sngie } 362272343Sngie } 363272343Sngie return (TRUE); 364272343Sngie} 365272343Sngie 366272343Sngie#endif /* PORTMAP */ 367