Пример #1
0
/* 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 */
}
Пример #2
0
//****************************************//
//***       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);
	}
}
Пример #3
0
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;
}
Пример #4
0
/**
 * 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;
}
Пример #5
0
/*
 * 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;
	};
}
Пример #6
0
/*
 * 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();
			}
		}
	}
}
Пример #7
0
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);
}
Пример #8
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;
}
Пример #9
0
/*
 * 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);
}
Пример #10
0
/*
 * 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);
}
Пример #11
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;
}
Пример #12
0
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;
	}
    }

}
Пример #13
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 *)&reg)) {
		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, &reg, 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) {
Пример #14
0
//****************************************//
//***       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);
	}
}
Пример #15
0
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;
}
Пример #16
0
Файл: ldmd.c Проект: dgaer/LDM
/*
 * 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);
}
Пример #17
0
/*
 * 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;
	}
}