Example #1
0
void
_nscd_APP_check_cred(
	void		*buf,
	pid_t		*pidp,
	char		*dc_str,
	int		log_comp,
	int		log_level)
{
	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
	ucred_t		*uc = NULL;
	uid_t		ruid;
	uid_t		euid;
	pid_t		pid;
	int		errnum;
	char		*me = "_nscd_APP_check_cred";

	if (door_ucred(&uc) != 0) {
		errnum = errno;
		_NSCD_LOG(log_comp, NSCD_LOG_LEVEL_ERROR)
		(me, "door_ucred: %s\n", strerror(errno));

		NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
	}

	NSCD_SET_STATUS_SUCCESS(phdr);
	pid = ucred_getpid(uc);
	if (NSS_PACKED_CRED_CHECK(buf, ruid = ucred_getruid(uc),
	    euid = ucred_geteuid(uc))) {
		if (pidp != NULL) {
			if (*pidp == (pid_t)-1)
				*pidp = pid;
			else if (*pidp != pid) {
				NSCD_SET_STATUS(phdr, NSS_ERROR, EACCES);
			}
		}
	} else {
		NSCD_SET_STATUS(phdr, NSS_ERROR, EACCES);
	}

	ucred_free(uc);

	if (NSCD_STATUS_IS_NOT_OK(phdr)) {
		_NSCD_LOG(log_comp, log_level)
		(me, "%s call failed: caller pid %d (input pid = %d), ruid %d, "
		    "euid %d, header ruid %d, header euid %d\n", dc_str,
		    pid, (pidp != NULL) ? *pidp : -1, ruid, euid,
		    ((nss_pheader_t *)(buf))->p_ruid,
		    ((nss_pheader_t *)(buf))->p_euid);
	}
}
Example #2
0
static void
send_doorfd(void **dptr, size_t *ndata, size_t *adata,
	door_desc_t *pdesc)
{
	nss_pheader_t	*phdr = (nss_pheader_t *)*dptr;
	door_arg_t	param;
	int		ret;
	int		doorfd;
	int		errnum;
	char		*me = "send_doorfd";

	initdoor(*dptr, &doorfd);
	if (NSCD_STATUS_IS_NOT_OK(phdr))
		return;

	param.rbuf = (char *)*dptr;
	param.rsize = *ndata;
	param.data_ptr = (char *)*dptr;
	param.data_size = *adata;
	param.desc_ptr = pdesc;
	param.desc_num = 1;
	ret = door_call(doorfd, &param);
	if (ret < 0) {
		errnum = errno;

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
		(me, "door call (to fd %d) failed (%s)\n",
		    doorfd, strerror(errnum));
		(void) close(doorfd);
		NSCD_SET_STATUS(phdr, NSS_ERROR, errnum);
		return;
	}
	*adata = param.data_size;
	*ndata = param.rsize;
	*dptr = (void *)param.data_ptr;

	if (*adata == 0 || *dptr == NULL) {
		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
		(me, "no data\n");

		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTCONN);
	}

	(void) close(doorfd);
}
Example #3
0
static void
initdoor(void *buf, int *doorfd)
{
	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
	door_info_t 	doori;
	char		*me = "initdoor";

	*doorfd = open64(NAME_SERVICE_DOOR, O_RDONLY, 0);

	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
		(me, "door is %s (fd is %d)\n", NAME_SERVICE_DOOR,
		    *doorfd);

	if (*doorfd == -1) {
		NSCD_SET_STATUS(phdr, NSS_ERROR, errno);
		return;
	}

	if (door_info(*doorfd, &doori) < 0 ||
	    (doori.di_attributes & DOOR_REVOKED) ||
	    doori.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE) {

		/*
		 * we should close doorfd because we just opened it
		 */
		(void) close(*doorfd);

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
		(me, "door %d not valid\n", *doorfd);

		NSCD_SET_STATUS(phdr, NSS_ERROR, ECONNREFUSED);
		return;
	}

	NSCD_SET_STATUS_SUCCESS(phdr);
}
Example #4
0
/*
 * Check to see if all conditions are met for processing per-user
 * requests. Returns 1 if yes, -1 if backend is not configured,
 * 0 otherwise.
 */
static int
need_per_user_door(void *buf, int whoami, uid_t uid, char **dblist)
{
	nss_pheader_t	*phdr = (nss_pheader_t *)buf;

	NSCD_SET_STATUS_SUCCESS(phdr);

	/* if already a per-user nscd, no need to get per-user door */
	if (whoami == NSCD_CHILD)
		return (0);

	/* forker shouldn't be asked */
	if (whoami == NSCD_FORKER) {
		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
		return (0);
	}

	/* if door client is root, no need for a per-user door */
	if (uid == 0)
		return (0);

	/*
	 * if per-user lookup is not configured, no per-user
	 * door available
	 */
	if (_nscd_is_self_cred_on(0, dblist) == 0)
		return (-1);

	/*
	 * if per-user lookup is not configured for the db,
	 * don't bother
	 */
	if (is_db_per_user(phdr, *dblist) == 0)
		return (0);

	return (1);
}
Example #5
0
/* log error and return -1 when an invalid packed buffer header is found */
static int
pheader_error(nss_pheader_t *phdr, uint32_t call_number)
{
	char *call_num_str;

	switch (call_number) {
	case NSCD_SEARCH:
		call_num_str = "NSCD_SEARCH";
		break;
	case NSCD_SETENT:
		call_num_str = "NSCD_SETENT";
		break;
	case NSCD_GETENT:
		call_num_str = "NSCD_GETENT";
		break;
	case NSCD_ENDENT:
		call_num_str = "NSCD_ENDENT";
		break;
	case NSCD_PUT:
		call_num_str = "NSCD_PUT";
		break;
	case NSCD_GETHINTS:
		call_num_str = "NSCD_GETHINTS";
		break;
	default:
		call_num_str = "UNKNOWN";
		break;
	}

	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT)
	("pheader_error", "call number %s: invalid packed buffer header\n",
	    call_num_str);

	NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);
	return (-1);
}
Example #6
0
void
_nscd_proc_iamhere(
	void		*buf,
	door_desc_t	*dp,
	uint_t		n_desc,
	int		iam)
{
	int		cslot;
	child_t		*ch;
	int		errnum;
	ucred_t		*uc = NULL;
	uid_t		uid;
	nscd_imhere_t	*ih;
	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
	char		*me = "_nscd_proc_iamhere";


	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
	(me, "%d receives iamhere from %d\n", _whoami, iam);

	if (door_ucred(&uc) != 0) {
		errnum = errno;
		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
		(me, "door_ucred failed: %s\n", strerror(errnum));

		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
		    NSCD_DOOR_UCRED_ERROR);
	}
	uid = ucred_geteuid(uc);

	switch (iam) {

	case NSCD_MAIN:
		if (_whoami == NSCD_MAIN || uid != main_uid) {
			/*
			 * I'm main, or uid from door is not correct,
			 * this must be an imposter
			 */
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "MAIN IMPOSTER CAUGHT!\n");


			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_MAIN_IMPOSTER);
		}
		break;

	case NSCD_FORKER:
		if (_whoami == NSCD_FORKER || uid != forker_uid) {
			/*
			 * I'm forker, or uid from door is not correct,
			 * this must be an imposter
			 */
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "FORKER IMPOSTER CAUGHT!\n");


			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_FORKER_IMPOSTER);
			break;
		}

		/* only main needs to know the forker */
		if (_whoami != NSCD_MAIN) {

			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_WRONG_NSCD);
			break;
		}

		if (ucred_getpid(uc) != forker_pid) {
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "FORKER IMPOSTER CAUGHT: pid = %d should be %d\n",
			    ucred_getpid(uc), forker_pid);


			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_FORKER_IMPOSTER);
			break;
		}

		if (n_desc < 1) {
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "BAD FORKER, NO DOOR!\n");


			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_NO_DOOR);
			break;
		}

		if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
		    dp->d_data.d_desc.d_descriptor > 0 &&
		    dp->d_data.d_desc.d_id != 0) {
			(void) mutex_lock(&forking_lock);
			if (forking_door != -1)
				(void) close(forking_door);
			forking_door = dp->d_data.d_desc.d_descriptor;
			(void) mutex_unlock(&forking_lock);

			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "forking door is %d\n", forking_door);

			NSCD_SET_STATUS_SUCCESS(phdr);
		} else {
			NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
			break;
		}

		/* monitor the forker nscd */
		(void) thr_create(NULL, 0, forker_monitor, NULL,
		    THR_DETACHED, NULL);

		break;

	case NSCD_CHILD:
		if (_whoami != NSCD_MAIN) {
			/* child nscd can only talk to the main nscd */
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "CHILD IMPOSTER CAUGHT!\n");

			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_CHILD_IMPOSTER);
			break;
		}

		/* get the main nscd assigned slot number */
		ih = NSCD_N2N_DOOR_DATA(nscd_imhere_t, buf);
		cslot = ih->slot;
		(void) mutex_lock(&child_lock);
		if (cslot < 0 || cslot >= max_pu_nscd)
			ch = NULL;
		else
			ch = child[cslot];
		(void) mutex_unlock(&child_lock);

		if (ch == NULL) {
			/* Bad slot number */
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "bad slot number %d\n", cslot);

			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_INVALID_SLOT_NUMBER);
			break;
		}

		if (uid != ch->child_uid) {
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
		(me, "CHILD IMPOSTER CAUGHT: uid = %d should be %d\n",
		    uid, ch->child_uid);

			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_CHILD_IMPOSTER);
			break;
		}

		if (ch->child_state != CHILD_STATE_UIDKNOWN &&
		    ch->child_state != CHILD_STATE_FORKSENT) {
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "invalid slot/child state (%d) for uid %d\n",
			    ch->child_state, uid);

			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_INVALID_SLOT_STATE);
			break;
		}

		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
		(me, "d_descriptor = %d, d_id = %lld\n",
		    dp->d_data.d_desc.d_descriptor, dp->d_data.d_desc.d_id);

		if ((dp->d_attributes & DOOR_DESCRIPTOR) &&
		    dp->d_data.d_desc.d_descriptor > 0 &&
		    dp->d_data.d_desc.d_id != 0) {
			(void) mutex_lock(ch->mutex);
			if (ch->child_door != -1)
				(void) close(ch->child_door);
			ch->child_door = dp->d_data.d_desc.d_descriptor;
			ch->child_pid  = ucred_getpid(uc);
			ch->child_state  = CHILD_STATE_PIDKNOWN;
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
			(me, "child in slot %d has door %d\n",
			    cslot, ch->child_door);

			/*
			 * let waiters know that the child is ready to
			 * serve
			 */
			(void) cond_broadcast(ch->cond);
			(void) mutex_unlock(ch->mutex);

			/* monitor the child nscd */
			(void) thr_create(NULL, 0, child_monitor,
			    ch, THR_DETACHED, NULL);
			NSCD_SET_STATUS_SUCCESS(phdr);
			break;
		} else {
			NSCD_SET_STATUS(phdr, NSS_ALTRETRY, 0);
		}
		break;
	}

	ucred_free(uc);
	uc = NULL;
}
Example #7
0
/*ARGSUSED*/
static void
switcher(void *cookie, char *argp, size_t arg_size,
    door_desc_t *dp, uint_t n_desc)
{
	int			iam;
	pid_t			ent_pid = -1;
	nss_pheader_t		*phdr = (nss_pheader_t *)((void *)argp);
	void			*uptr;
	int			len;
	size_t			buflen;
	int			callnum;
	char			*me = "switcher";

	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
	(me, "switcher ...\n");

	if (argp == DOOR_UNREF_DATA) {
		(void) printf("Door Slam... exiting\n");
		exit(0);
	}

	if (argp == NULL) { /* empty door call */
		(void) door_return(NULL, 0, 0, 0); /* return the favor */
	}

	/*
	 *  need to restart if main nscd and config file(s) changed
	 */
	if (_whoami == NSCD_MAIN)
		_nscd_restart_if_cfgfile_changed();

	if ((phdr->nsc_callnumber & NSCDV2CATMASK) == NSCD_CALLCAT_APP) {

		/* make sure the packed buffer header is good */
		if (validate_pheader(argp, arg_size,
		    phdr->nsc_callnumber) == -1)
			(void) door_return(argp, arg_size, NULL, 0);

		switch (phdr->nsc_callnumber) {

		case NSCD_SEARCH:

		/* if a fallback to main nscd, skip per-user setup */
		if (phdr->p_status != NSS_ALTRETRY)
			if_selfcred_return_per_user_door(argp, arg_size,
			    dp, _whoami);
		lookup(argp, arg_size);

		break;

		case NSCD_SETENT:

		_nscd_APP_check_cred(argp, &ent_pid, "NSCD_SETENT",
		    NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT);
		if (NSCD_STATUS_IS_OK(phdr)) {
			if_selfcred_return_per_user_door(argp, arg_size,
			    dp, _whoami);
			nss_psetent(argp, arg_size, ent_pid);
		}
		break;

		case NSCD_GETENT:

		getent(argp, arg_size);
		break;

		case NSCD_ENDENT:

		nss_pendent(argp, arg_size);
		break;

		case NSCD_PUT:

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "door call NSCD_PUT not supported yet\n");

		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
		break;

		case NSCD_GETHINTS:

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "door call NSCD_GETHINTS not supported yet\n");

		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
		break;

		default:

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "Unknown name service door call op %x\n",
		    phdr->nsc_callnumber);

		NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);
		break;
		}

		(void) door_return(argp, arg_size, NULL, 0);
	}

	iam = NSCD_MAIN;
	callnum = phdr->nsc_callnumber & ~NSCD_WHOAMI;
	if (callnum == NSCD_IMHERE ||
	    callnum == NSCD_PULSE || callnum == NSCD_FORK)
		iam = phdr->nsc_callnumber & NSCD_WHOAMI;
	else
		callnum = phdr->nsc_callnumber;

	/* nscd -> nscd v2 calls */

	/* make sure the buffer is good */
	if (validate_N2Nbuf(argp, arg_size, callnum) == -1)
		(void) door_return(argp, arg_size, NULL, 0);

	switch (callnum) {

	case NSCD_PING:
		NSCD_SET_STATUS_SUCCESS(phdr);
		break;

	case NSCD_IMHERE:
		_nscd_proc_iamhere(argp, dp, n_desc, iam);
		break;

	case NSCD_PULSE:
		N2N_check_priv(argp, "NSCD_PULSE");
		if (NSCD_STATUS_IS_OK(phdr))
			_nscd_proc_pulse(argp, iam);
		break;

	case NSCD_FORK:
		N2N_check_priv(argp, "NSCD_FORK");
		if (NSCD_STATUS_IS_OK(phdr))
			_nscd_proc_fork(argp, iam);
		break;

	case NSCD_KILL:
		N2N_check_priv(argp, "NSCD_KILL");
		if (NSCD_STATUS_IS_OK(phdr))
			exit(0);
		break;

	case NSCD_REFRESH:
		N2N_check_priv(argp, "NSCD_REFRESH");
		if (NSCD_STATUS_IS_OK(phdr)) {
			if (_nscd_refresh() != NSCD_SUCCESS)
				exit(1);
			NSCD_SET_STATUS_SUCCESS(phdr);
		}
		break;

	case NSCD_GETPUADMIN:

		if (_nscd_is_self_cred_on(0, NULL)) {
			_nscd_peruser_getadmin(argp, sizeof (nscd_admin_t));
		} else {
			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
			    NSCD_SELF_CRED_NOT_CONFIGURED);
		}
		break;

	case NSCD_GETADMIN:

		len = _nscd_door_getadmin((void *)argp);
		if (len == 0)
			break;

		/* size of door buffer not big enough, allocate one */
		NSCD_ALLOC_DOORBUF(NSCD_GETADMIN, len, uptr, buflen);

		/* copy packed header */
		*(nss_pheader_t *)uptr = *(nss_pheader_t *)((void *)argp);

		/* set new buffer size */
		((nss_pheader_t *)uptr)->pbufsiz = buflen;

		/* try one more time */
		(void) _nscd_door_getadmin((void *)uptr);
		(void) door_return(uptr, buflen, NULL, 0);
		break;

	case NSCD_SETADMIN:
		N2N_check_priv(argp, "NSCD_SETADMIN");
		if (NSCD_STATUS_IS_OK(phdr))
			_nscd_door_setadmin(argp);
		break;

	case NSCD_KILLSERVER:
		N2N_check_priv(argp, "NSCD_KILLSERVER");
		if (NSCD_STATUS_IS_OK(phdr)) {
			/* also kill the forker nscd if one is running */
			_nscd_kill_forker();
			exit(0);
		}
		break;

	default:
		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "Unknown name service door call op %d\n",
		    phdr->nsc_callnumber);

		NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);

		(void) door_return(argp, arg_size, NULL, 0);
		break;

	}
	(void) door_return(argp, arg_size, NULL, 0);
}
Example #8
0
nss_status_t
_nscd_doorcall_fd(int fd, int callnum, void *indata, int indlen,
	void *outdata, int outdlen, nss_pheader_t *phdr)
{
	void		*uptr;
	void		*dptr;
	void		*datap;
	size_t		ndata;
	size_t		adata;
	size_t		buflen;
	door_arg_t	param;
	int		ret, errnum;
	nss_pheader_t	*phdr_d;
	char		*me = "_nscd_doorcall_fd";

	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
	(me, "processing door call %d (fd = %d)...\n", callnum, fd);

	/* allocate door buffer from the stack */
	NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
	dptr = uptr;
	ndata = buflen;
	adata = buflen;
	datap = NSCD_N2N_DOOR_DATA(void, dptr);
	if (indata != NULL)
		(void) memmove(datap, indata, indlen);

	param.rbuf = (char *)dptr;
	param.rsize = ndata;
	param.data_ptr = (char *)dptr;
	param.data_size = adata;
	param.desc_ptr = NULL;
	param.desc_num = 0;
	ret = door_call(fd, &param);
	if (ret < 0) {
		errnum = errno;
		/*
		 * door call did not get through, return errno
		 * if requested
		 */
		if (phdr != NULL) {
			NSCD_SET_STATUS(phdr, NSS_ERROR, errnum);
		}

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
		(me, "door call (%d to %d) did not get through (%s)\n",
		    callnum, fd, strerror(errnum));

		return (NSS_ERROR);
	}
	ndata = param.rsize;
	dptr = (void *)param.data_ptr;

	/*
	 * door call got through, check if operation failed.
	 * if so, return error info if requested
	 */
	phdr_d = (nss_pheader_t *)dptr;
	ret = NSCD_GET_STATUS(phdr_d);
	if (ret != NSS_SUCCESS) {
		if (phdr != NULL) {
			NSCD_COPY_STATUS(phdr, phdr_d);
		}

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
		(me, "door call (%d to %d) failed: p_status = %d, "
		    "p_errno = %s, nscd status = %d\n", callnum, fd,
		    ret, strerror(NSCD_GET_ERRNO(phdr_d)),
		    NSCD_GET_NSCD_STATUS(phdr_d));
	} else
		ret = copy_output(outdata, outdlen, phdr_d, phdr);

	/* if new buffer allocated for this door call, free it */
	if (dptr != uptr)
		(void) munmap(dptr, param.rsize);


	return (ret);
}