/* get uid/gid from RPC credentials */ int getcreds(struct svc_req *rp, uid_t *u, gid_t *g, SVCXPRT *nfsxprt) { struct authunix_parms *aup = (struct authunix_parms *) NULL; #ifdef HAVE_RPC_AUTH_DES_H struct authdes_cred *adp; #endif /* HAVE_RPC_AUTH_DES_H */ switch (rp->rq_cred.oa_flavor) { case AUTH_UNIX: aup = (struct authunix_parms *) rp->rq_clntcred; *u = aup->aup_uid; *g = aup->aup_gid; break; #ifdef HAVE_RPC_AUTH_DES_H case AUTH_DES: adp = (struct authdes_cred *) rp->rq_clntcred; *g = INVALIDID; /* some unknown group id */ if (sscanf(adp->adc_fullname.name, "unix.%lu@", (u_long *) u) == 1) break; /* fall through */ #endif /* HAVE_RPC_AUTH_DES_H */ default: *u = *g = INVALIDID; /* just in case */ svcerr_weakauth(nfsxprt); return -1; } return 0; /* everything is ok */ }
//****************************************// //*** Dispatch Function ***// //****************************************// static void exm_proc(struct svc_req *rqstp, SVCXPRT *transp) { //printf("* in Dispatch Func.\n"); union { int varIn; } argument; char *result; xdrproc_t xdr_argument; xdrproc_t xdr_result; char *(*proc)(char *); switch (rqstp->rq_proc) { case PROCSIMPLEPING: { //printf("** in PROCPONG dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_int; xdr_result = (xdrproc_t)xdr_int; proc = (char *(*)(char *))simplePing; break; } case PROGSYSERROR: { //Simulate an error svcerr_systemerr(transp); return; } case PROGAUTHERROR: { //Simulate an authentification error svcerr_weakauth(transp); return; } default: { //Proc is unavaible svcerr_noproc(transp); return; } } memset((char *)&argument, (int)0, sizeof(argument)); if (svc_getargs(transp, xdr_argument, (char *)&argument) == FALSE) { svcerr_decode(transp); return; } result = (char *)(*proc)((char *)&argument); if ((result != NULL) && (svc_sendreply(transp, xdr_result, (char *)result) == FALSE)) { svcerr_systemerr(transp); } if (svc_freeargs(transp, xdr_argument, (char *)&argument) == FALSE) { (void)fprintf(stderr, "unable to free arguments\n"); exit(1); } }
static void server_program_1(struct svc_req *rqstp, register SVCXPRT *transp) { rpc_gss_rawcred_t *rcred; rpc_gss_ucred_t *ucred; int i, num; if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) { svcerr_weakauth(transp); return; } if (!rpc_gss_getcred(rqstp, &rcred, &ucred, NULL)) { svcerr_systemerr(transp); return; } printf("svc=%d, mech=%s, uid=%d, gid=%d, gids={", rcred->service, rcred->mechanism, ucred->uid, ucred->gid); for (i = 0; i < ucred->gidlen; i++) { if (i > 0) printf(","); printf("%d", ucred->gidlist[i]); } printf("}\n"); switch (rqstp->rq_proc) { case 0: if (!svc_getargs(transp, (xdrproc_t) xdr_void, 0)) { svcerr_decode(transp); goto out; } if (!svc_sendreply(transp, (xdrproc_t) xdr_void, 0)) { svcerr_systemerr(transp); } goto out; case 1: if (!svc_getargs(transp, (xdrproc_t) xdr_int, (char *) &num)) { svcerr_decode(transp); goto out; } num += 100; if (!svc_sendreply(transp, (xdrproc_t) xdr_int, (char *) &num)) { svcerr_systemerr(transp); } goto out; default: svcerr_noproc(transp); goto out; } out: return; }
/** * Feeds or notifies a downstream LDM. This function returns either NULL or a * reply to be sent to the downstream LDM (e.g., a RECLASS message) or * terminates this process (hopefully after sending some data). * * @param xprt [in/out] Pointer to server-side transport handle. * @param want [in] Pointer to subscription by downstream LDM. * May contain a "signature" product-specification. * @param isNotifier [in] Whether or not the upstream LDM is a feeder or a * notifier. * @param maxHereis Maximum HEREIS size parameter. Ignored if "isNotifier" * is true. * @return The reply for the downstream LDM or NULL if no reply * should be made. */ static fornme_reply_t* feed_or_notify( SVCXPRT* const xprt, const prod_class_t* const want, const int isNotifier, const max_hereis_t maxHereis) { struct sockaddr_in downAddr = *svc_getcaller(xprt); ErrorObj* errObj; int status; char* downName = NULL; prod_class_t* origSub = NULL; prod_class_t* allowSub = NULL; const signaturet* signature = NULL; UpFilter* upFilter = NULL; fornme_reply_t* reply = NULL; int isPrimary; static fornme_reply_t theReply; static prod_class_t* uldbSub = NULL; /* * Clean-up from a (possibly) previous invocation */ (void)memset(&theReply, 0, sizeof(theReply)); if (uldbSub != NULL) { free_prod_class(uldbSub); uldbSub = NULL; } downName = strdup(hostbyaddr(&downAddr)); if (NULL == downName) { LOG_ADD1("Couldn't duplicate downstream host name: \"%s\"", hostbyaddr(&downAddr)); log_log(LOG_ERR); svcerr_systemerr(xprt); goto return_or_exit; } set_abbr_ident(downName, isNotifier ? "(noti)" : "(feed)"); /* * Remove any "signature" specification from the subscription. */ if ((errObj = separateProductClass(want, &origSub, &signature)) != NULL) { err_log_and_free(errObj, ERR_FAILURE); svcerr_systemerr(xprt); goto free_down_name; } /* * Get the upstream filter */ errObj = lcf_getUpstreamFilter(downName, &downAddr.sin_addr, origSub, &upFilter); if (errObj) { err_log_and_free(ERR_NEW(0, errObj, "Couldn't get \"upstream\" filter"), ERR_FAILURE); svcerr_systemerr(xprt); goto free_orig_sub; } if (NULL == upFilter) { err_log_and_free(ERR_NEW1(0, NULL, "Upstream filter prevents data-transfer: %s", s_prod_class(NULL, 0, origSub)), ERR_FAILURE); svcerr_weakauth(xprt); goto free_orig_sub; } /* TODO: adjust time? */ /* * Reduce the subscription according to what the downstream host is allowed * to receive. */ status = lcf_reduceToAllowed(downName, &downAddr.sin_addr, origSub, &allowSub); if (status == ENOMEM) { LOG_SERROR0("Couldn't compute wanted/allowed product intersection"); log_log(LOG_ERR); svcerr_systemerr(xprt); goto free_up_filter; } if (status == EINVAL) { LOG_ADD1("Invalid pattern in product-class: %s", s_prod_class(NULL, 0, origSub)); log_log(LOG_WARNING); theReply.code = BADPATTERN; reply = &theReply; goto free_up_filter; } assert(status == 0); (void) logIfReduced(origSub, allowSub, "ALLOW entries"); /* * Reduce the subscription according to existing subscriptions from the * same downstream host and, if `isAntiDosEnabled()` returns `true`, * terminate every previously-existing upstream LDM process that's feeding * (not notifying) a subset of the subscription to the same IP address. * * The following relies on atexit()-registered cleanup for removal of the * entry from the upstream LDM database. */ isPrimary = maxHereis > UINT_MAX / 2; status = uldb_addProcess(getpid(), 6, &downAddr, allowSub, &uldbSub, isNotifier, isPrimary); if (status) { LOG_ADD0("Couldn't add this process to the upstream LDM database"); log_log(LOG_ERR); svcerr_systemerr(xprt); goto free_allow_sub; } (void) logIfReduced(allowSub, uldbSub, "existing subscriptions"); /* * Send a RECLASS reply to the downstream LDM if appropriate. */ if (!clss_eq(origSub, uldbSub)) { theReply.code = RECLASS; if (0 < uldbSub->psa.psa_len) { /* * The downstream LDM is allowed less than it requested and was * entered into the upstream LDM database. */ (void)uldb_remove(getpid()); /* maybe next time */ theReply.fornme_reply_t_u.prod_class = uldbSub; } else { /* * The downstream LDM isn't allowed anything and wasn't entered * into the upstream LDM database. */ static prod_class noSub = { { 0, 0 }, /* TS_ZERO */ { 0, 0 }, /* TS_ZERO */ { 0, (prod_spec *) NULL } }; theReply.fornme_reply_t_u.prod_class = &noSub; } reply = &theReply; goto free_allow_sub; } /* * Reply to the downstream LDM that the subscription will be honored. */ theReply.code = OK; theReply.fornme_reply_t_u.id = (unsigned) getpid(); if (!svc_sendreply(xprt, (xdrproc_t)xdr_fornme_reply_t, (caddr_t)&theReply)) { LOG_ADD0("svc_sendreply(...) failure"); log_log(LOG_ERR); svcerr_systemerr(xprt); goto free_allow_sub; } /* * Wait a second before sending anything to the downstream LDM. */ (void) sleep(1); status = isNotifier ? up6_new_notifier(xprt->xp_sock, downName, &downAddr, uldbSub, signature, getQueuePath(), interval, upFilter) : up6_new_feeder(xprt->xp_sock, downName, &downAddr, uldbSub, signature, getQueuePath(), interval, upFilter, isPrimary); svc_destroy(xprt); /* closes the socket */ exit(status); /* * Reply and error handling: */ free_allow_sub: free_prod_class(allowSub); free_up_filter: upFilter_free(upFilter); free_orig_sub: free_prod_class(origSub); free_down_name: free(downName); return_or_exit: return reply; }
/* * The nfsuserd rpc service */ static void nfsuserdsrv(struct svc_req *rqstp, SVCXPRT *transp) { struct passwd *pwd; struct group *grp; int error; u_short sport; struct info info; struct nfsd_idargs nid; u_int32_t saddr; /* * Only handle requests from 127.0.0.1 on a reserved port number. * (Since a reserved port # at localhost implies a client with * local root, there won't be a security breach. This is about * the only case I can think of where a reserved port # means * something.) */ sport = ntohs(transp->xp_raddr.sin_port); saddr = ntohl(transp->xp_raddr.sin_addr.s_addr); if ((rqstp->rq_proc != NULLPROC && sport >= IPPORT_RESERVED) || saddr != 0x7f000001) { syslog(LOG_ERR, "req from ip=0x%x port=%d\n", saddr, sport); svcerr_weakauth(transp); return; } switch (rqstp->rq_proc) { case NULLPROC: if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) syslog(LOG_ERR, "Can't send reply"); return; case RPCNFSUSERD_GETUID: if (!svc_getargs(transp, (xdrproc_t)xdr_getid, (caddr_t)&info)) { svcerr_decode(transp); return; } pwd = getpwuid((uid_t)info.id); info.retval = 0; if (pwd != NULL) { nid.nid_usertimeout = defusertimeout; nid.nid_uid = pwd->pw_uid; nid.nid_name = pwd->pw_name; } else { nid.nid_usertimeout = 5; nid.nid_uid = (uid_t)info.id; nid.nid_name = defaultuser; } nid.nid_namelen = strlen(nid.nid_name); nid.nid_flag = NFSID_ADDUID; error = nfssvc(NFSSVC_IDNAME, &nid); if (error) { info.retval = error; syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name); } else if (verbose) { syslog(LOG_ERR,"Added uid=%d name=%s\n", nid.nid_uid, nid.nid_name); } if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, (caddr_t)&info)) syslog(LOG_ERR, "Can't send reply"); return; case RPCNFSUSERD_GETGID: if (!svc_getargs(transp, (xdrproc_t)xdr_getid, (caddr_t)&info)) { svcerr_decode(transp); return; } grp = getgrgid((gid_t)info.id); info.retval = 0; if (grp != NULL) { nid.nid_usertimeout = defusertimeout; nid.nid_gid = grp->gr_gid; nid.nid_name = grp->gr_name; } else { nid.nid_usertimeout = 5; nid.nid_gid = (gid_t)info.id; nid.nid_name = defaultgroup; } nid.nid_namelen = strlen(nid.nid_name); nid.nid_flag = NFSID_ADDGID; error = nfssvc(NFSSVC_IDNAME, &nid); if (error) { info.retval = error; syslog(LOG_ERR, "Can't add group %s\n", grp->gr_name); } else if (verbose) { syslog(LOG_ERR,"Added gid=%d name=%s\n", nid.nid_gid, nid.nid_name); } if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, (caddr_t)&info)) syslog(LOG_ERR, "Can't send reply"); return; case RPCNFSUSERD_GETUSER: if (!svc_getargs(transp, (xdrproc_t)xdr_getname, (caddr_t)&info)) { svcerr_decode(transp); return; } pwd = getpwnam(info.name); info.retval = 0; if (pwd != NULL) { nid.nid_usertimeout = defusertimeout; nid.nid_uid = pwd->pw_uid; nid.nid_name = pwd->pw_name; } else { nid.nid_usertimeout = 5; nid.nid_uid = defaultuid; nid.nid_name = info.name; } nid.nid_namelen = strlen(nid.nid_name); nid.nid_flag = NFSID_ADDUSERNAME; error = nfssvc(NFSSVC_IDNAME, &nid); if (error) { info.retval = error; syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name); } else if (verbose) { syslog(LOG_ERR,"Added uid=%d name=%s\n", nid.nid_uid, nid.nid_name); } if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, (caddr_t)&info)) syslog(LOG_ERR, "Can't send reply"); return; case RPCNFSUSERD_GETGROUP: if (!svc_getargs(transp, (xdrproc_t)xdr_getname, (caddr_t)&info)) { svcerr_decode(transp); return; } grp = getgrnam(info.name); info.retval = 0; if (grp != NULL) { nid.nid_usertimeout = defusertimeout; nid.nid_gid = grp->gr_gid; nid.nid_name = grp->gr_name; } else { nid.nid_usertimeout = 5; nid.nid_gid = defaultgid; nid.nid_name = info.name; } nid.nid_namelen = strlen(nid.nid_name); nid.nid_flag = NFSID_ADDGROUPNAME; error = nfssvc(NFSSVC_IDNAME, &nid); if (error) { info.retval = error; syslog(LOG_ERR, "Can't add group %s\n", grp->gr_name); } else if (verbose) { syslog(LOG_ERR,"Added gid=%d name=%s\n", nid.nid_gid, nid.nid_name); } if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, (caddr_t)&info)) syslog(LOG_ERR, "Can't send reply"); return; default: svcerr_noproc(transp); return; }; }
/* * Called by svc_getreqset. There is a separate server handle for * every transport that it waits on. */ void rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp) { union { RPCB rpcbproc_set_3_arg; RPCB rpcbproc_unset_3_arg; RPCB rpcbproc_getaddr_3_local_arg; struct rpcb_rmtcallargs rpcbproc_callit_3_arg; char *rpcbproc_uaddr2taddr_3_arg; struct netbuf rpcbproc_taddr2uaddr_3_arg; } argument; char *result; xdrproc_t xdr_argument, xdr_result; void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t); rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc); switch (rqstp->rq_proc) { case NULLPROC: /* * Null proc call */ #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_NULL\n"); #endif /* This call just logs, no actual checks */ check_access(transp, rqstp->rq_proc, NULL, RPCBVERS); (void) svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL); return; case RPCBPROC_SET: xdr_argument = (xdrproc_t )xdr_rpcb; xdr_result = (xdrproc_t )xdr_bool; local = rpcbproc_set_com; break; case RPCBPROC_UNSET: xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_bool; local = rpcbproc_unset_com; break; case RPCBPROC_GETADDR: xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_wrapstring; local = rpcbproc_getaddr_3_local; break; case RPCBPROC_DUMP: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_DUMP\n"); #endif xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_rpcblist_ptr; local = rpcbproc_dump_3_local; break; case RPCBPROC_CALLIT: rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS); return; case RPCBPROC_GETTIME: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_GETTIME\n"); #endif xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_u_long; local = rpcbproc_gettime_com; break; case RPCBPROC_UADDR2TADDR: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_UADDR2TADDR\n"); #endif xdr_argument = (xdrproc_t)xdr_wrapstring; xdr_result = (xdrproc_t)xdr_netbuf; local = rpcbproc_uaddr2taddr_com; break; case RPCBPROC_TADDR2UADDR: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_TADDR2UADDR\n"); #endif xdr_argument = (xdrproc_t)xdr_netbuf; xdr_result = (xdrproc_t)xdr_wrapstring; local = rpcbproc_taddr2uaddr_com; break; default: svcerr_noproc(transp); return; } (void) memset((char *)&argument, 0, sizeof (argument)); if (!svc_getargs(transp, (xdrproc_t) xdr_argument, (char *) &argument)) { svcerr_decode(transp); if (debugging) (void) fprintf(stderr, "rpcbind: could not decode\n"); return; } if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS)) { svcerr_weakauth(transp); goto done; } result = (*local)(&argument, rqstp, transp, RPCBVERS); if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { svcerr_systemerr(transp); if (debugging) { (void) fprintf(stderr, "rpcbind: svc_sendreply\n"); if (doabort) { rpcbind_abort(); } } } done: if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *) &argument)) { if (debugging) { (void) fprintf(stderr, "unable to free arguments\n"); if (doabort) { rpcbind_abort(); } } } }
static void nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) { struct nfsrv_descript nd; struct nfsrvcache *rp = NULL; int cacherep, credflavor; memset(&nd, 0, sizeof(nd)); if (rqst->rq_vers == NFS_VER2) { if (rqst->rq_proc > NFSV2PROC_STATFS) { svcerr_noproc(rqst); svc_freereq(rqst); goto out; } nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc]; nd.nd_flag = ND_NFSV2; } else if (rqst->rq_vers == NFS_VER3) { if (rqst->rq_proc >= NFS_V3NPROCS) { svcerr_noproc(rqst); svc_freereq(rqst); goto out; } nd.nd_procnum = rqst->rq_proc; nd.nd_flag = ND_NFSV3; } else { if (rqst->rq_proc != NFSPROC_NULL && rqst->rq_proc != NFSV4PROC_COMPOUND) { svcerr_noproc(rqst); svc_freereq(rqst); goto out; } nd.nd_procnum = rqst->rq_proc; nd.nd_flag = ND_NFSV4; } /* * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP * mounts. */ nd.nd_mrep = rqst->rq_args; rqst->rq_args = NULL; newnfs_realign(&nd.nd_mrep, M_WAITOK); nd.nd_md = nd.nd_mrep; nd.nd_dpos = mtod(nd.nd_md, caddr_t); nd.nd_nam = svc_getrpccaller(rqst); nd.nd_nam2 = rqst->rq_addr; nd.nd_mreq = NULL; nd.nd_cred = NULL; if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) { /* Check if source port is privileged */ u_short port; struct sockaddr *nam = nd.nd_nam; struct sockaddr_in *sin; sin = (struct sockaddr_in *)nam; /* * INET/INET6 - same code: * sin_port and sin6_port are at same offset */ port = ntohs(sin->sin_port); if (port >= IPPORT_RESERVED && nd.nd_procnum != NFSPROC_NULL) { #ifdef INET6 char b6[INET6_ADDRSTRLEN]; #if defined(KLD_MODULE) /* Do not use ip6_sprintf: the nfs module should work without INET6. */ #define ip6_sprintf(buf, a) \ (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ (a)->s6_addr16[0], (a)->s6_addr16[1], \ (a)->s6_addr16[2], (a)->s6_addr16[3], \ (a)->s6_addr16[4], (a)->s6_addr16[5], \ (a)->s6_addr16[6], (a)->s6_addr16[7]), \ (buf)) #endif #endif printf("NFS request from unprivileged port (%s:%d)\n", #ifdef INET6 sin->sin_family == AF_INET6 ? ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : #if defined(KLD_MODULE) #undef ip6_sprintf #endif #endif inet_ntoa(sin->sin_addr), port); svcerr_weakauth(rqst); svc_freereq(rqst); m_freem(nd.nd_mrep); goto out; } } if (nd.nd_procnum != NFSPROC_NULL) { if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { svcerr_weakauth(rqst); svc_freereq(rqst); m_freem(nd.nd_mrep); goto out; } /* Set the flag based on credflavor */ if (credflavor == RPCSEC_GSS_KRB5) { nd.nd_flag |= ND_GSS; } else if (credflavor == RPCSEC_GSS_KRB5I) { nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY); } else if (credflavor == RPCSEC_GSS_KRB5P) { nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY); } else if (credflavor != AUTH_SYS) { svcerr_weakauth(rqst); svc_freereq(rqst); m_freem(nd.nd_mrep); goto out; } #ifdef MAC mac_cred_associate_nfsd(nd.nd_cred); #endif /* * Get a refcnt (shared lock) on nfsd_suspend_lock. * NFSSVC_SUSPENDNFSD will take an exclusive lock on * nfsd_suspend_lock to suspend these threads. * This must be done here, before the check of * nfsv4root exports by nfsvno_v4rootexport(). */ NFSLOCKV4ROOTMUTEX(); nfsv4_getref(&nfsd_suspend_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); NFSUNLOCKV4ROOTMUTEX(); if ((nd.nd_flag & ND_NFSV4) != 0) { nd.nd_repstat = nfsvno_v4rootexport(&nd); if (nd.nd_repstat != 0) { NFSLOCKV4ROOTMUTEX(); nfsv4_relref(&nfsd_suspend_lock); NFSUNLOCKV4ROOTMUTEX(); svcerr_weakauth(rqst); svc_freereq(rqst); m_freem(nd.nd_mrep); goto out; } } cacherep = nfs_proc(&nd, rqst->rq_xid, xprt, &rp); NFSLOCKV4ROOTMUTEX(); nfsv4_relref(&nfsd_suspend_lock); NFSUNLOCKV4ROOTMUTEX(); } else { NFSMGET(nd.nd_mreq); nd.nd_mreq->m_len = 0; cacherep = RC_REPLY; } if (nd.nd_mrep != NULL) m_freem(nd.nd_mrep); if (nd.nd_cred != NULL) crfree(nd.nd_cred); if (cacherep == RC_DROPIT) { if (nd.nd_mreq != NULL) m_freem(nd.nd_mreq); svc_freereq(rqst); goto out; } if (nd.nd_mreq == NULL) { svcerr_decode(rqst); svc_freereq(rqst); goto out; } if (nd.nd_repstat & NFSERR_AUTHERR) { svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); if (nd.nd_mreq != NULL) m_freem(nd.nd_mreq); } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { svcerr_systemerr(rqst); } if (rp != NULL) { nfsrvd_sentcache(rp, (rqst->rq_reply_seq != 0 || SVC_ACK(xprt, NULL)), rqst->rq_reply_seq); } svc_freereq(rqst); out: NFSEXITCODE(0); }
/* * Called by svc_getreqset. There is a separate server handle for * every transport that it waits on. */ void rpcb_service_4(struct svc_req *rqstp, SVCXPRT *transp) { union { rpcb rpcbproc_set_4_arg; rpcb rpcbproc_unset_4_arg; rpcb rpcbproc_getaddr_4_local_arg; char *rpcbproc_uaddr2taddr_4_arg; struct netbuf rpcbproc_taddr2uaddr_4_arg; } argument; char *result; xdrproc_t xdr_argument, xdr_result; void *(*local) __P((void *, struct svc_req *, SVCXPRT *, rpcvers_t)); rpcprog_t setprog = 0; rpcbs_procinfo(RPCBVERS_4_STAT, rqstp->rq_proc); switch (rqstp->rq_proc) { case NULLPROC: /* * Null proc call */ #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_NULL\n"); #endif check_access(transp, rqstp->rq_proc, 0, RPCBVERS4); (void) svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL); return; case RPCBPROC_SET: /* * Check to see whether the message came from * loopback transports (for security reasons) */ xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_bool; local = rpcbproc_set_com; break; case RPCBPROC_UNSET: /* * Check to see whether the message came from * loopback transports (for security reasons) */ xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_bool; local = rpcbproc_unset_com; break; case RPCBPROC_GETADDR: xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_wrapstring; local = rpcbproc_getaddr_4_local; break; case RPCBPROC_GETVERSADDR: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_GETVERSADDR\n"); #endif xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_wrapstring; local = rpcbproc_getversaddr_4_local; break; case RPCBPROC_DUMP: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_DUMP\n"); #endif xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_rpcblist_ptr; local = rpcbproc_dump_4_local; break; case RPCBPROC_INDIRECT: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_INDIRECT\n"); #endif rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4); return; /* case RPCBPROC_CALLIT: */ case RPCBPROC_BCAST: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_BCAST\n"); #endif rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4); return; case RPCBPROC_GETTIME: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_GETTIME\n"); #endif xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_u_long; local = rpcbproc_gettime_com; break; case RPCBPROC_UADDR2TADDR: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_UADDR2TADDR\n"); #endif xdr_argument = (xdrproc_t)xdr_wrapstring; xdr_result = (xdrproc_t)xdr_netbuf; local = rpcbproc_uaddr2taddr_com; break; case RPCBPROC_TADDR2UADDR: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_TADDR2UADDR\n"); #endif xdr_argument = (xdrproc_t)xdr_netbuf; xdr_result = (xdrproc_t)xdr_wrapstring; local = rpcbproc_taddr2uaddr_com; break; case RPCBPROC_GETADDRLIST: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_GETADDRLIST\n"); #endif xdr_argument = (xdrproc_t)xdr_rpcb; xdr_result = (xdrproc_t)xdr_rpcb_entry_list_ptr; local = rpcbproc_getaddrlist_4_local; break; case RPCBPROC_GETSTAT: #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "RPCBPROC_GETSTAT\n"); #endif xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_rpcb_stat_byvers; local = rpcbproc_getstat; break; default: svcerr_noproc(transp); return; } memset((char *)&argument, 0, sizeof (argument)); if (!svc_getargs(transp, (xdrproc_t) xdr_argument, (char *)&argument)) { svcerr_decode(transp); if (debugging) (void) fprintf(stderr, "rpcbind: could not decode\n"); return; } if (rqstp->rq_proc == RPCBPROC_SET || rqstp->rq_proc == RPCBPROC_UNSET || rqstp->rq_proc == RPCBPROC_GETADDR) setprog = argument.rpcbproc_set_4_arg.r_prog; if (!check_access(transp, rqstp->rq_proc, setprog, RPCBVERS4)) { svcerr_weakauth(transp); goto done; } result = (*local)(&argument, rqstp, transp, RPCBVERS4); if (result != NULL && !svc_sendreply(transp, (xdrproc_t) xdr_result, result)) { svcerr_systemerr(transp); if (debugging) { (void) fprintf(stderr, "rpcbind: svc_sendreply\n"); if (doabort) { rpcbind_abort(); } } } done: if (!svc_freeargs(transp, (xdrproc_t) xdr_argument, (char *)&argument)) { if (debugging) { (void) fprintf(stderr, "unable to free arguments\n"); if (doabort) { rpcbind_abort(); } } } return; }
/* * Handles server to client callbacks. */ static void nfscb_program(struct svc_req *rqst, SVCXPRT *xprt) { struct nfsrv_descript nd; int cacherep, credflavor; memset(&nd, 0, sizeof(nd)); if (rqst->rq_proc != NFSPROC_NULL && rqst->rq_proc != NFSV4PROC_CBCOMPOUND) { svcerr_noproc(rqst); svc_freereq(rqst); return; } nd.nd_procnum = rqst->rq_proc; nd.nd_flag = (ND_NFSCB | ND_NFSV4); /* * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP * mounts. */ nd.nd_mrep = rqst->rq_args; rqst->rq_args = NULL; newnfs_realign(&nd.nd_mrep, M_WAITOK); nd.nd_md = nd.nd_mrep; nd.nd_dpos = mtod(nd.nd_md, caddr_t); nd.nd_nam = svc_getrpccaller(rqst); nd.nd_nam2 = rqst->rq_addr; nd.nd_mreq = NULL; nd.nd_cred = NULL; NFSCL_DEBUG(1, "cbproc=%d\n",nd.nd_procnum); if (nd.nd_procnum != NFSPROC_NULL) { if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { svcerr_weakauth(rqst); svc_freereq(rqst); m_freem(nd.nd_mrep); return; } /* For now, I don't care what credential flavor was used. */ #ifdef notyet #ifdef MAC mac_cred_associate_nfsd(nd.nd_cred); #endif #endif cacherep = nfs_cbproc(&nd, rqst->rq_xid); } else { NFSMGET(nd.nd_mreq); nd.nd_mreq->m_len = 0; cacherep = RC_REPLY; } if (nd.nd_mrep != NULL) m_freem(nd.nd_mrep); if (nd.nd_cred != NULL) crfree(nd.nd_cred); if (cacherep == RC_DROPIT) { if (nd.nd_mreq != NULL) m_freem(nd.nd_mreq); svc_freereq(rqst); return; } if (nd.nd_mreq == NULL) { svcerr_decode(rqst); svc_freereq(rqst); return; } if (nd.nd_repstat & NFSERR_AUTHERR) { svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); if (nd.nd_mreq != NULL) m_freem(nd.nd_mreq); } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) svcerr_systemerr(rqst); else NFSCL_DEBUG(1, "cbrep sent\n"); svc_freereq(rqst); }
/* * setup RPC service * * if can't authenticate return < 0 * any other error return > 0 */ int svc_init( struct svc_req *rqstp, /* RPC stuff */ int amode, /* R_OK | W_OK */ md_error_t *ep /* returned status */ ) { SVCXPRT *transp; if (sdssc_bind_library() == SDSSC_ERROR) { mdsyserror(ep, EACCES, "can't bind to cluster library"); return (1); } /* * if we have no rpc service info, we must have been * called recursively from within the daemon */ if (rqstp == NULL) { mdclrerror(ep); return (0); /* OK */ } /* * initialize */ transp = rqstp->rq_xprt; assert(transp != NULL); *ep = mdnullerror; /* * check credentials */ switch (rqstp->rq_cred.oa_flavor) { /* UNIX flavor */ case AUTH_SYS: { if (check_sys(rqstp, amode, ep) != 0) return (1); /* error */ break; } /* can't authenticate anything else */ default: svcerr_weakauth(transp); return (-1); /* weak authentication */ } /* * (re)initialize */ if (md_init_daemon("rpc.metad", ep) != 0) return (1); /* error */ if (set_snarf(ep)) return (1); sr_validate(); /* success */ return (0); }
/* * RPC boilerplate */ static void keyprogram(struct svc_req *rqstp, SVCXPRT *transp) { union { keybuf key_set_1_arg; cryptkeyarg key_encrypt_1_arg; cryptkeyarg key_decrypt_1_arg; netnamestr key_getcred_1_arg; cryptkeyarg key_encrypt_2_arg; cryptkeyarg key_decrypt_2_arg; netnamestr key_getcred_2_arg; cryptkeyarg2 key_encrypt_pk_2_arg; cryptkeyarg2 key_decrypt_pk_2_arg; key_netstarg key_net_put_2_arg; netobj key_get_conv_2_arg; } argument; char *result; xdrproc_t xdr_argument, xdr_result; char *(*local) (); uid_t uid = -1; int check_auth; switch (rqstp->rq_proc) { case NULLPROC: svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); return; case KEY_SET: xdr_argument = (xdrproc_t)xdr_keybuf; xdr_result = (xdrproc_t)xdr_int; local = (char *(*)()) key_set_1_svc_prog; check_auth = 1; break; case KEY_ENCRYPT: xdr_argument = (xdrproc_t)xdr_cryptkeyarg; xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_encrypt_1_svc_prog; check_auth = 1; break; case KEY_DECRYPT: xdr_argument = (xdrproc_t)xdr_cryptkeyarg; xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_decrypt_1_svc_prog; check_auth = 1; break; case KEY_GEN: xdr_argument = (xdrproc_t)xdr_void; xdr_result = (xdrproc_t)xdr_des_block; local = (char *(*)()) key_gen_1_svc_prog; check_auth = 0; break; case KEY_GETCRED: xdr_argument = (xdrproc_t)xdr_netnamestr; xdr_result = (xdrproc_t)xdr_getcredres; local = (char *(*)()) key_getcred_1_svc_prog; check_auth = 0; break; case KEY_ENCRYPT_PK: xdr_argument = (xdrproc_t)xdr_cryptkeyarg2; xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_encrypt_pk_2_svc_prog; check_auth = 1; break; case KEY_DECRYPT_PK: xdr_argument = (xdrproc_t)xdr_cryptkeyarg2; xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_decrypt_pk_2_svc_prog; check_auth = 1; break; case KEY_NET_PUT: xdr_argument = (xdrproc_t)xdr_key_netstarg; xdr_result = (xdrproc_t)xdr_keystatus; local = (char *(*)()) key_net_put_2_svc_prog; check_auth = 1; break; case KEY_NET_GET: xdr_argument = (xdrproc_t) xdr_void; xdr_result = (xdrproc_t)xdr_key_netstres; local = (char *(*)()) key_net_get_2_svc_prog; check_auth = 1; break; case KEY_GET_CONV: xdr_argument = (xdrproc_t) xdr_keybuf; xdr_result = (xdrproc_t)xdr_cryptkeyres; local = (char *(*)()) key_get_conv_2_svc_prog; check_auth = 1; break; default: svcerr_noproc(transp); return; } if (check_auth) { if (root_auth(transp, rqstp) == 0) { if (debugging) { fprintf(stderr, "not local privileged process\n"); } svcerr_weakauth(transp); return; } if (rqstp->rq_cred.oa_flavor != AUTH_SYS) { if (debugging) { fprintf(stderr, "not unix authentication\n"); } svcerr_weakauth(transp); return; } uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid; } memset(&argument, 0, sizeof (argument)); if (!svc_getargs(transp, xdr_argument, &argument)) { svcerr_decode(transp); return; } result = (*local) (uid, &argument); if (!svc_sendreply(transp, xdr_result, result)) { if (debugging) fprintf(stderr, "unable to reply\n"); svcerr_systemerr(transp); } if (!svc_freeargs(transp, xdr_argument, &argument)) { if (debugging) fprintf(stderr, "unable to free arguments\n"); exit(1); } return; }
void krb5_iprop_prog_1(struct svc_req *rqstp, register SVCXPRT *transp) { union { kdb_last_t iprop_get_updates_1_arg; } argument; char *result; bool_t (*_xdr_argument)(), (*_xdr_result)(); char *(*local)(/* union XXX *, struct svc_req * */); char *whoami = "krb5_iprop_prog_1"; if (!check_iprop_rpcsec_auth(rqstp)) { krb5_klog_syslog(LOG_ERR, "authentication attempt failed: %s, RPC authentication flavor %d", inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), rqstp->rq_cred.oa_flavor); svcerr_weakauth(transp); return; } switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply(transp, xdr_void, (char *)NULL); return; case IPROP_GET_UPDATES: _xdr_argument = xdr_kdb_last_t; _xdr_result = xdr_kdb_incr_result_t; local = (char *(*)()) iprop_get_updates_1_svc; break; case IPROP_FULL_RESYNC: _xdr_argument = xdr_void; _xdr_result = xdr_kdb_fullresync_result_t; local = (char *(*)()) iprop_full_resync_1_svc; break; default: krb5_klog_syslog(LOG_ERR, _("RPC unknown request: %d (%s)"), rqstp->rq_proc, whoami); svcerr_noproc(transp); return; } (void) memset((char *)&argument, 0, sizeof (argument)); if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) { krb5_klog_syslog(LOG_ERR, _("RPC svc_getargs failed (%s)"), whoami); svcerr_decode(transp); return; } result = (*local)(&argument, rqstp); if (_xdr_result && result != NULL && !svc_sendreply(transp, _xdr_result, result)) { krb5_klog_syslog(LOG_ERR, _("RPC svc_sendreply failed (%s)"), whoami); svcerr_systemerr(transp); } if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) { krb5_klog_syslog(LOG_ERR, _("RPC svc_freeargs failed (%s)"), whoami); exit(1); } if (rqstp->rq_proc == IPROP_GET_UPDATES) { /* LINTED */ kdb_incr_result_t *r = (kdb_incr_result_t *)result; if (r->ret == UPDATE_OK) { ulog_free_entries(r->updates.kdb_ulog_t_val, r->updates.kdb_ulog_t_len); r->updates.kdb_ulog_t_val = NULL; r->updates.kdb_ulog_t_len = 0; } } }
static bool_t pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op) { struct pmap reg; RPCB rpcbreg; long ans; struct sockcred *sc; char uidbuf[32]; if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { svcerr_decode(xprt); return (FALSE); } #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "%s request for (%lu, %lu) : ", op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET", reg.pm_prog, reg.pm_vers); #endif if (!check_access(xprt, op, ®, PMAPVERS)) { svcerr_weakauth(xprt); return FALSE; } (void)svc_getcaller(xprt); sc = __svc_getcallercreds(xprt); /* * Can't use getpwnam here. We might end up calling ourselves * and looping. */ if (sc == NULL) rpcbreg.r_owner = __UNCONST(rpcbind_unknown); else if (sc->sc_uid == 0) rpcbreg.r_owner = __UNCONST(rpcbind_superuser); else { /* r_owner will be strdup-ed later */ snprintf(uidbuf, sizeof uidbuf, "%d", sc->sc_uid); rpcbreg.r_owner = uidbuf; } rpcbreg.r_prog = reg.pm_prog; rpcbreg.r_vers = reg.pm_vers; if (op == PMAPPROC_SET) { char buf[32]; snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d", (int)((reg.pm_port >> 8) & 0xff), (int)(reg.pm_port & 0xff)); rpcbreg.r_addr = buf; if (reg.pm_prot == IPPROTO_UDP) { rpcbreg.r_netid = __UNCONST(udptrans); } else if (reg.pm_prot == IPPROTO_TCP) { rpcbreg.r_netid = __UNCONST(tcptrans); } else { ans = FALSE; goto done_change; } ans = map_set(&rpcbreg, rpcbreg.r_owner); } else if (op == PMAPPROC_UNSET) {
//****************************************// //*** Dispatch Function ***// //****************************************// void rcp_service(register struct svc_req *rqstp, register SVCXPRT *transp) { //printf("* in Dispatch Func.\n"); /*union { int varIn; } argument;*/ char *result; xdrproc_t xdr_argument; xdrproc_t xdr_result; char *(*proc)(union u_argument *, SVCXPRT *); enum auth_stat why; switch (rqstp->rq_proc) { case PROCSIMPLEPING: { //printf("** in PROCSIMPLEPING dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_int; xdr_result = (xdrproc_t)xdr_int; proc = (char *(*)(union u_argument *, SVCXPRT *))simplePing; break; } case SVCGETCALLTEST: { //printf("** in SVCGETCALLTEST dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_int; xdr_result = (xdrproc_t)xdr_int; proc = (char *(*)(union u_argument *, SVCXPRT *))svc_getcaller_test; break; } case PROGSYSERROR: { //printf("** in PROGSYSERROR dispatch Func.\n"); //Simulate an error svcerr_systemerr(transp); return; } case PROGAUTHERROR: { //printf("** in PROGAUTHERROR dispatch Func.\n"); //Simulate an authentification error svcerr_auth(transp, why); return; } case PROGWKAUTHERROR: { //printf("** in PROGWKAUTHERROR dispatch Func.\n"); //Simulate an authentification error svcerr_weakauth(transp); return; } case INTPROCNUM: { //printf("** in INTPROCNUM dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_int; xdr_result = (xdrproc_t)xdr_int; proc = (char *(*)(union u_argument *, SVCXPRT *))intTestProc; //(char *(*)(union u_argument *)) break; } case DBLPROCNUM: { //printf("** in DBLPROCNUM dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_double; xdr_result = (xdrproc_t)xdr_double; proc = (char *(*)(union u_argument *, SVCXPRT *))dblTestProc; break; } case LNGPROCNUM: { //printf("** in LNGPROCNUM dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_long; xdr_result = (xdrproc_t)xdr_long; proc = (char *(*)(union u_argument *, SVCXPRT *))lngTestProc; break; } case STRPROCNUM: { //printf("** in STRPROCNUM dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_wrapstring; xdr_result = (xdrproc_t)xdr_wrapstring; proc = (char *(*)(union u_argument *, SVCXPRT *))strTestProc; break; } case SVCGETARGSPROC: { //printf("** in SVCGETARGSPROC dispatch Func.\n"); xdr_argument = (xdrproc_t)xdr_int; xdr_result = (xdrproc_t)xdr_int; proc = (char *(*)(union u_argument *, SVCXPRT *))svcGetargsProc; break; } default: { //printf("** in NOT DEFINED dispatch Func.\n"); //Proc is unavaible svcerr_noproc(transp); return; } } memset((char *)&argument, (int)0, sizeof(argument)); if (svc_getargs(transp, xdr_argument, (char *)&argument) == FALSE) { svcerr_decode(transp); return; } result = (char *)(*proc)((union u_argument *)&argument, transp); if ((result != NULL) && (svc_sendreply(transp, xdr_result, result) == FALSE)) { svcerr_systemerr(transp); } if (svc_freeargs(transp, xdr_argument, (char *)&argument) == FALSE) { (void)fprintf(stderr, "unable to free arguments\n"); exit(1); } }
hiya_reply_t* hiya_6_svc( prod_class_t *offered, struct svc_req *rqstp) { const char* const pqfname = getQueuePath(); static hiya_reply_t reply; SVCXPRT * const xprt = rqstp->rq_xprt; struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt); const char *upName = hostbyaddr(upAddr); int error; int isPrimary; unsigned int maxHereis; static prod_class_t *accept; /* * Open the product-queue for writing. It will be closed by cleanup() * during process termination. */ if (pq) { (void) pq_close(pq); pq = NULL; } error = pq_open(pqfname, PQ_DEFAULT, &pq); if (error) { err_log_and_free(ERR_NEW2(error, NULL, "Couldn't open product-queue \"%s\" for writing: %s", pqfname, PQ_CORRUPT == error ? "The product-queue is inconsistent" : strerror(error)), ERR_FAILURE); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } /* else */ error = down6_init(upName, upAddr, pqfname, pq); if (error) { uerror("Couldn't initialize downstream LDM"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { uinfo("Downstream LDM initialized"); } /* * The previous "accept" is freed here -- rather than freeing the * soon-to-be-allocated "accept" at the end of its block -- because it can * be used in the reply. */ if (accept) { free_prod_class(accept); /* NULL safe */ accept = NULL; } error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered, &accept, &isPrimary); maxHereis = isPrimary ? UINT_MAX : 0; if (error) { serror("Couldn't validate HIYA"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { if (ulogIsDebug()) udebug("intersection: %s", s_prod_class(NULL, 0, accept)); if (accept->psa.psa_len == 0) { uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT " "entries", upName, s_prod_class(NULL, 0, offered)); svcerr_weakauth(xprt); svc_destroy(xprt); exit(0); } else { error = down6_set_prod_class(accept); if (error) { if (DOWN6_SYSTEM_ERROR == error) { serror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } else { uerror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } svcerr_systemerr(xprt); svc_destroy(xprt); exit(EXIT_FAILURE); } /* else */ if (clss_eq(offered, accept)) { unotice("hiya6: %s", s_prod_class(NULL, 0, offered)); reply.code = OK; reply.hiya_reply_t_u.max_hereis = maxHereis; } else { if (ulogIsVerbose()) { char off[512]; char acc[512]; (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class( acc, sizeof(acc), accept); uinfo("hiya6: RECLASS: %s -> %s", off, acc); } reply.code = RECLASS; reply.hiya_reply_t_u.feedPar.prod_class = accept; reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis; } } /* product-intersection != empty set */ } /* successful acl_check_hiya() */ return &reply; }
/* * Handles an incoming RPC connection on a socket. This method will fork(2) * a copy of this program, if appropriate, for handling incoming RPC messages. * * sock The socket with the incoming RPC connection. */ static void handle_connection( int sock) { struct sockaddr_in raddr; socklen_t len; int xp_sock; pid_t pid; SVCXPRT *xprt; int status = 1; /* EXIT_FAILURE assumed unless one_svc_run() success */ peer_info* remote = get_remote(); again: len = sizeof(raddr); (void) memset(&raddr, 0, len); xp_sock = accept(sock, (struct sockaddr *) &raddr, &len); (void) exitIfDone(0); if (xp_sock < 0) { if (errno == EINTR) { errno = 0; goto again; } /* else */ serror("accept"); return; } /* * Don't bother continuing if no more clients are allowed. */ if (cps_count() >= maxClients) { setremote(&raddr, xp_sock); unotice("Denying connection from [%s] because too many clients", remote->astr); (void) close(xp_sock); return; } pid = ldmfork(); if (pid == -1) { log_add("Couldn't fork process to handle incoming connection"); log_log(LOG_ERR); /* TODO: try again?*/ (void) close(xp_sock); return; } if (pid > 0) { /* parent */ /* unotice("child %d", pid); */ (void) close(xp_sock); if (cps_add(pid)) serror("Couldn't add child PID to set"); return; } /* else child */ setremote(&raddr, xp_sock); /* Access control */ if (!lcf_isHostOk(remote)) { ensureRemoteName(&raddr); if (!lcf_isHostOk(remote)) { if (remote->printname == remote->astr) { unotice("Denying connection from [%s] because not " "allowed", remote->astr); } else { unotice("Denying connection from \"%s\" because not " "allowed", remote_name()); } /* * Try to tell the other guy. * TODO: Why doesn't this work? */ xprt = svcfd_create(xp_sock, remote->sendsz, remote->recvsz); if (xprt != NULL ) { xprt->xp_raddr = raddr; xprt->xp_addrlen = (int) len; svcerr_weakauth(xprt); svc_destroy(xprt); } goto unwind_sock; } } /* else */ endpriv(); portIsMapped = 0; /* don't call pmap_unset() from child */ (void) close(sock); /* Set the ulog identifier, optional. */ set_abbr_ident(remote_name(), NULL ); uinfo("Connection from %s", remote_name()); xprt = svcfd_create(xp_sock, remote->sendsz, remote->recvsz); if (xprt == NULL ) { uerror("Can't create fd service."); goto unwind_sock; } /* hook up the remote address to the xprt. */ /* xprt->xp_raddr = raddr; */ xprt->xp_raddr = raddr; xprt->xp_addrlen = (int) len; if (!svc_register(xprt, LDMPROG, 4, ldmprog_4, 0)) { uerror("unable to register LDM-4 service."); svc_destroy(xprt); goto unwind_sock; } if (!svc_register(xprt, LDMPROG, FIVE, ldmprog_5, 0)) { uerror("unable to register LDM-5 service."); svc_destroy(xprt); goto unwind_sock; } if (!svc_register(xprt, LDMPROG, SIX, ldmprog_6, 0)) { uerror("unable to register LDM-6 service."); svc_destroy(xprt); goto unwind_sock; } #if WANT_MULTICAST if (!svc_register(xprt, LDMPROG, SEVEN, ldmprog_7, 0)) { uerror("unable to register LDM-7 service."); svc_destroy(xprt); goto unwind_sock; } #endif /* * handle rpc requests */ { const unsigned TIMEOUT = 2*interval; status = one_svc_run(xp_sock, TIMEOUT); (void) exitIfDone(0); if (status == 0) { log_add("Done"); log_log(LOG_INFO); } else if (status == ETIMEDOUT) { log_add("Connection from client LDM silent for %u seconds", TIMEOUT); log_log(LOG_NOTICE); } else { /* connection to client lost */ log_add("Connection with client LDM closed"); log_log(LOG_INFO); status = 0; /* EXIT_SUCCESS */ } } /* svc_destroy(xprt); done by svc_getreqset() */ unwind_sock: (void) close(xp_sock); exit(status); }
/* * The mount rpc service */ void mntsrv(struct svc_req *rqstp, SVCXPRT *transp) { char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN]; struct hostent *hp = NULL; struct exportlist *ep; sigset_t sighup_mask; int defset, hostset; struct fhreturn fhr; struct dirlist *dp; struct statfs fsb; struct stat stb; in_addr_t saddr; u_short sport; long bad = 0; sigemptyset(&sighup_mask); sigaddset(&sighup_mask, SIGHUP); saddr = transp->xp_raddr.sin_addr.s_addr; sport = ntohs(transp->xp_raddr.sin_port); switch (rqstp->rq_proc) { case NULLPROC: if (!svc_sendreply(transp, xdr_void, NULL)) syslog(LOG_ERR, "Can't send reply"); return; case RPCMNT_MOUNT: if (debug) fprintf(stderr, "Got mount request from %s\n", inet_ntoa(transp->xp_raddr.sin_addr)); if (sport >= IPPORT_RESERVED && resvport_only) { syslog(LOG_NOTICE, "Refused mount RPC from host %s port %d", inet_ntoa(transp->xp_raddr.sin_addr), sport); svcerr_weakauth(transp); return; } if (!svc_getargs(transp, xdr_dir, rpcpath)) { svcerr_decode(transp); return; } if (debug) fprintf(stderr, "rpcpath: %s\n", rpcpath); /* * Get the real pathname and make sure it is a file or * directory that exists. */ if (realpath(rpcpath, dirpath) == NULL) { bad = errno; if (debug) fprintf(stderr, "realpath failed on %s\n", rpcpath); strlcpy(dirpath, rpcpath, sizeof(dirpath)); } else if (stat(dirpath, &stb) < 0 || (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) || statfs(dirpath, &fsb) < 0) { if (debug) fprintf(stderr, "stat failed on %s\n", dirpath); bad = ENOENT; /* We will send error reply later */ } /* Check in the exports list */ sigprocmask(SIG_BLOCK, &sighup_mask, NULL); ep = ex_search(&fsb.f_fsid); hostset = defset = 0; if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) || ((dp = dirp_search(ep->ex_dirl, dirpath)) && chk_host(dp, saddr, &defset, &hostset)) || (defset && scan_tree(ep->ex_defdir, saddr) == 0 && scan_tree(ep->ex_dirl, saddr) == 0))) { if (bad) { if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) syslog(LOG_ERR, "Can't send reply"); sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); return; } if (hostset & DP_HOSTSET) fhr.fhr_flag = hostset; else fhr.fhr_flag = defset; fhr.fhr_vers = rqstp->rq_vers; /* Get the file handle */ memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t)); if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) { if (errno == ENOSYS) { syslog(LOG_ERR, "Kernel does not support NFS exporting, " "mountd aborting.."); _exit(1); } bad = errno; syslog(LOG_ERR, "Can't get fh for %s", dirpath); if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) syslog(LOG_ERR, "Can't send reply"); sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); return; } if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr)) syslog(LOG_ERR, "Can't send reply"); if (hp == NULL) hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); if (hp) add_mlist(hp->h_name, dirpath); else add_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); if (debug) { fprintf(stderr, "Mount successful for %s by %s.\n", dirpath, inet_ntoa(transp->xp_raddr.sin_addr)); } } else bad = EACCES; if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad)) syslog(LOG_ERR, "Can't send reply"); sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL); return; case RPCMNT_DUMP: if (!svc_sendreply(transp, xdr_mlist, NULL)) syslog(LOG_ERR, "Can't send reply"); return; case RPCMNT_UMOUNT: if (sport >= IPPORT_RESERVED && resvport_only) { svcerr_weakauth(transp); return; } if (!svc_getargs(transp, xdr_dir, dirpath)) { svcerr_decode(transp); return; } if (!svc_sendreply(transp, xdr_void, NULL)) syslog(LOG_ERR, "Can't send reply"); hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); if (hp) del_mlist(hp->h_name, dirpath); del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); return; case RPCMNT_UMNTALL: if (sport >= IPPORT_RESERVED && resvport_only) { svcerr_weakauth(transp); return; } if (!svc_sendreply(transp, xdr_void, NULL)) syslog(LOG_ERR, "Can't send reply"); hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); if (hp) del_mlist(hp->h_name, NULL); del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), NULL); return; case RPCMNT_EXPORT: if (!svc_sendreply(transp, xdr_explist, NULL)) syslog(LOG_ERR, "Can't send reply"); return; default: svcerr_noproc(transp); return; } }