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); } }
static void selfcred_fork( void *buf, int doorfd, int cslot, uid_t uid, gid_t gid) { int ret; nscd_fork_t f; nss_pheader_t *phdr = (nss_pheader_t *)buf; char *me = "selfcred_fork"; /* if no door fd, do nothing */ if (doorfd == -1) { NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, NSCD_SELF_CRED_NO_DOOR); } _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "sending fork request to door %d for slot %d " "(uid = %d, gid = %d)\n", doorfd, cslot, uid, gid); f.slot = cslot; f.uid = uid; f.gid = gid; ret = _nscd_doorcall_fd(doorfd, NSCD_FORK|(_whoami&NSCD_WHOAMI), &f, sizeof (f), NULL, 0, phdr); _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "fork request sent to door %d for slot %d (rc = %d)\n", doorfd, cslot, ret); if (NSCD_STATUS_IS_NOT_OK(phdr)) { _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "fork request sent to door %d for slot %d failed: " "status = %d, errno = %s, nscd status = %d\n", doorfd, cslot, NSCD_GET_STATUS(phdr), strerror(NSCD_GET_ERRNO(phdr)), NSCD_GET_NSCD_STATUS(phdr)); } }
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, ¶m); 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); }
nss_status_t _nscd_doorcall_sendfd(int fd, int callnum, void *indata, int indlen, nss_pheader_t *phdr) { void *uptr; void *dptr; void *datap; size_t ndata; size_t adata; size_t buflen; nss_pheader_t *phdr_d; door_desc_t desc; char *me = "_nscd_doorcall_sendfd"; _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); desc.d_attributes = DOOR_DESCRIPTOR; desc.d_data.d_desc.d_descriptor = fd; send_doorfd(&dptr, &ndata, &adata, &desc); phdr_d = (nss_pheader_t *)dptr; if (NSCD_STATUS_IS_NOT_OK(phdr_d)) { if (phdr != NULL) *phdr = *phdr_d; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "door call (%d) failed (status = %d, error = %s)\n", callnum, NSCD_GET_STATUS(phdr_d), strerror(NSCD_GET_ERRNO(phdr_d))); } return (NSCD_GET_STATUS(phdr_d)); }
void _nscd_proc_alt_get( void *buf, int *door) { int errnum; uid_t set2uid; gid_t set2gid; nss_pheader_t *phdr = (nss_pheader_t *)buf; char *me = "_nscd_proc_alt_get"; ucred_t *uc = NULL; child_t *ch; _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "getting an alternate door ...\n"); /* make sure there is a door to talk to the forker */ if (forking_door == -1) { _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR) (me, "no door to talk to the forker\n"); NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, NSCD_SELF_CRED_NO_FORKER); } /* get door client's credential information */ 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); } /* get door client's effective uid and effective gid */ set2uid = ucred_geteuid(uc); set2gid = ucred_getegid(uc); ucred_free(uc); uc = NULL; _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "child uid = %d, gid = %d\n", set2uid, set2gid); /* is a slot available ? if not, no one to serve */ if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) { _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "no child slot available (child array = %p, slot = %d)\n", child, ch->child_slot); NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, NSCD_SELF_CRED_NO_CHILD_SLOT); } /* create the per user nscd if necessary */ if (ch->child_state != CHILD_STATE_PIDKNOWN) { nss_pheader_t phdr1; NSCD_CLEAR_STATUS(&phdr1); (void) mutex_lock(ch->mutex); if (ch->child_state == CHILD_STATE_UIDKNOWN) { /* ask forker to fork a new child */ selfcred_fork(&phdr1, forking_door, ch->child_slot, set2uid, set2gid); if (NSCD_STATUS_IS_NOT_OK(&phdr1)) { (void) mutex_unlock(ch->mutex); NSCD_COPY_STATUS(phdr, &phdr1); return; } ch->child_state = CHILD_STATE_FORKSENT; } _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "waiting for door (slot = %d, uid = %d, gid = %d)\n", ch->child_slot, set2uid, set2gid); /* wait for the per user nscd to become available */ while (ch->child_state == CHILD_STATE_FORKSENT) { timestruc_t to; int err; int ttl = 5; to.tv_sec = ttl; to.tv_nsec = 0; _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "cond_reltimedwait %d seconds\n", ttl); err = cond_reltimedwait(ch->cond, ch->mutex, &to); if (err == ETIME) { ch->child_state = CHILD_STATE_UIDKNOWN; _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "door wait timedout (slot = %d)\n", ch->child_slot); break; } } (void) mutex_unlock(ch->mutex); } if (ch->child_state != CHILD_STATE_PIDKNOWN) { NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, NSCD_SELF_CRED_INVALID_SLOT_STATE); } *door = ch->child_door; _NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG) (me, "returning door %d for slot %d, uid %d, gid = %d\n", *door, ch->child_slot, set2uid, set2gid); NSCD_RETURN_STATUS(phdr, NSS_ALTRETRY, 0); }