示例#1
0
static void
N2N_check_priv(
	void			*buf,
	char			*dc_str)
{
	nss_pheader_t		*phdr = (nss_pheader_t *)buf;
	ucred_t			*uc = NULL;
	const priv_set_t	*eset;
	zoneid_t		zoneid;
	int			errnum;
	char			*me = "N2N_check_priv";

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

		NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
	}

	eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
	zoneid = ucred_getzoneid(uc);

	if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) ||
	    eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) :
	    ucred_geteuid(uc) != 0) {

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT)
		(me, "%s call failed(cred): caller pid %d, uid %d, "
		    "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc),
		    ucred_getruid(uc), ucred_geteuid(uc), zoneid);
		ucred_free(uc);

		NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES);
	}

	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
	(me, "nscd received %s cmd from pid %d, uid %d, "
	    "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc),
	    ucred_getruid(uc), ucred_geteuid(uc), zoneid);

	ucred_free(uc);

	NSCD_RETURN_STATUS_SUCCESS(phdr);
}
示例#2
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);
	}
}
示例#3
0
/*
 * Check to see if we have the permissions to set scheduler parameters and
 * policy, based on Linux' demand that such commands fail with errno set to
 * EPERM if the current euid is not the euid or ruid of the process in
 * question.
 */
static int
check_schedperms(pid_t pid)
{
	size_t sz;
	ucred_t *cr;
	uid_t euid;

	euid = geteuid();

	if (pid == getpid()) {
		/*
		 * If we're the process to be checked, simply check the euid
		 * against our ruid.
		 */
		if (euid != getuid())
			return (-EPERM);

		return (0);
	}

	/*
	 * We allocate a ucred_t ourselves rather than call ucred_get(3C)
	 * because ucred_get() calls malloc(3C), which the brand library cannot
	 * use.  Because we allocate the space with SAFE_ALLOCA(), there's
	 * no need to free it when we're done.
	 */
	sz = ucred_size();
	cr = (ucred_t *)SAFE_ALLOCA(sz);

	if (cr == NULL)
		return (-ENOMEM);

	/*
	 * If we can't access the process' credentials, fail with errno EPERM
	 * as the call would not have succeeded anyway.
	 */
	if (syscall(SYS_ucredsys, UCREDSYS_UCREDGET, pid, cr) != 0)
		return ((errno == EACCES) ? -EPERM : -errno);

	if ((euid != ucred_geteuid(cr)) && (euid != ucred_getruid(cr)))
		return (-EPERM);

	return (0);
}
示例#4
0
文件: ctrls.c 项目: flxflx/weasel
static int ctrls_get_creds_peerucred(int sockfd, uid_t *uid, gid_t *gid) {
  ucred_t *cred = NULL;

  if (getpeerucred(sockfd, &cred) < 0) {
    int xerrno = errno;

    pr_trace_msg(trace_channel, 7, "error obtaining credentials using "
      "getpeerucred(3) on fd %d: %s", sockfd, strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  if (uid)
    *uid = ucred_getruid(cred);

  if (gid)
    *gid = ucred_getrgid(cred);

  ucred_free(cred);
  return 0;
}
示例#5
0
/* ARGSUSED */
void
ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
    uint_t n_desc)
{
	ipmgmt_door_info_t	*infop = NULL;
	ipmgmt_retval_t		retval;
	int			i;
	uint_t			err;
	ucred_t			*cred = NULL;

	for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {
		if (i_ipmgmt_door_info_tbl[i].idi_cmd ==
		    ((ipmgmt_arg_t *)(void *)argp)->ia_cmd) {
			infop = &i_ipmgmt_door_info_tbl[i];
			break;
		}
	}

	if (infop == NULL) {
		ipmgmt_log(LOG_ERR, "Invalid door command specified");
		err = EINVAL;
		goto fail;
	}

	/* check for solaris.network.interface.config authorization */
	if (infop->idi_set) {
		uid_t		uid;
		struct passwd	pwd;
		char		buf[1024];

		if (door_ucred(&cred) != 0) {
			err = errno;
			ipmgmt_log(LOG_ERR, "Could not get user credentials.");
			goto fail;
		}
		uid = ucred_getruid(cred);
		if ((int)uid < 0) {
			err = errno;
			ipmgmt_log(LOG_ERR, "Could not get user id.");
			goto fail;
		}
		if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) ==
		    NULL) {
			err = errno;
			ipmgmt_log(LOG_ERR, "Could not get password entry.");
			goto fail;
		}
		if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH,
		    pwd.pw_name) != 1) {
			err = EPERM;
			ipmgmt_log(LOG_ERR, "Not authorized for operation.");
			goto fail;
		}
		ucred_free(cred);
	}

	/* individual handlers take care of calling door_return */
	infop->idi_handler((void *)argp);
	return;
fail:
	ucred_free(cred);
	retval.ir_err = err;
	(void) door_return((char *)&retval, sizeof (retval), NULL, 0);
}
示例#6
0
文件: door.c 项目: bahamas10/openzfs
/*
 * build_mgmt_request -- extracts the request info from the given XML doc.
 *
 * x_doc: ptr to the request XML doc
 * req: ptr to the request struct to be filled up.
 *
 * Return value: ISNS_RSP_SUCCESSFUL if successful or an error code.
 */
static int
process_mgmt_request(xmlDocPtr x_doc, request_t *req, ucred_t *uc)
{
	result_code_t   ret;
	int		op;
	xmlXPathContextPtr ctext = NULL;
	uid_t			user;
	struct passwd		pwds, *pwd;
	char			buf_pwd[1024];


	isnslog(LOG_DEBUG, "process_mgmt_request", "entered");
	(void) memset(req, 0, sizeof (request_t));
	/* get the operation first. */
	ctext = xmlXPathNewContext(x_doc);
	if (ctext == NULL) {
	    return (ERR_XML_FAILED_TO_SET_XPATH_CONTEXT);
	}

	isnslog(LOG_DEBUG, "process_mgmt_request", "xpath context succeeded");
	op = get_op_id_from_doc(ctext);
	if (op == -1) {
	    if (ctext) xmlXPathFreeContext(ctext);
	    return (ERR_XML_VALID_OPERATION_NOT_FOUND);
	}

	user = ucred_getruid(uc);
	ret = getpwuid_r(user, &pwds, buf_pwd, sizeof (buf_pwd), &pwd);
	if (ret != 0) {
	    if (ctext) xmlXPathFreeContext(ctext);
	    return (ERR_DOOR_SERVER_DETECTED_INVALID_USER);
	}

	/* write operations are restricted. */
	if ((op == delete_op) || (op == createModify_op)) {
	    if (!chkauthattr(ISNS_ADMIN_WRITE_AUTH, pwd->pw_name)) {
		if (ctext) xmlXPathFreeContext(ctext);
		return (ERR_DOOR_SERVER_DETECTED_NOT_AUTHORIZED_USER);
	    }
	}

	req->op_info.op = op;

	if (ISNS_MGMT_OPERATION_TYPE_ENABLED()) {
	    ISNS_MGMT_OPERATION_TYPE(op);
	}

	switch (op) {
	    case (get_op):
		ret = process_get_request_from_doc(ctext, req);
		break;
	    case (getAssociated_op):
		ret = process_getAssociated_request_from_doc(ctext, req);
		break;
	    case (enumerate_op):
		ret = process_enumerate_request_from_doc(ctext, req);
		break;
	    case (delete_op):
		ret = process_delete_request_from_doc(ctext, req);
		break;
	    case (createModify_op):
		ret = process_createModify_request_from_doc(ctext, req);
		break;
	    default:
		ret = ERR_XML_VALID_OPERATION_NOT_FOUND;
	}

	if (ctext) xmlXPathFreeContext(ctext);
	return (ret);
}
示例#7
0
文件: getpw.c 项目: andreiw/polaris
void
getpw_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now)
{
	int		out_of_date;
	nsc_bucket_t	*retb;
	char 		**bucket;

	static time_t	lastmod;

	int bufferspace = maxsize - sizeof (nsc_return_t);

	if (current_admin.passwd.nsc_enabled == 0) {
		out->nsc_return_code = NOSERVER;
		out->nsc_bufferbytesused = sizeof (*out);
		return;
	}

	mutex_lock(&passwd_lock);

	if (current_admin.passwd.nsc_check_files) {
		struct stat buf;

		if (stat("/etc/passwd", &buf) < 0) {
			/*EMPTY*/;
		} else if (lastmod == 0) {
			lastmod = buf.st_mtime;
		} else if (lastmod < buf.st_mtime) {
			getpw_invalidate_unlocked();
			lastmod = buf.st_mtime;
		}
	}

	if (current_admin.debug_level >= DBG_ALL) {
		if (MASKUPDATEBIT(in->nsc_callnumber) == GETPWUID) {
			logit("getpw_lookup: looking for uid %d\n",
				in->nsc_u.uid);
		} else {
			logit("getpw_lookup: looking for name %s\n",
				in->nsc_u.name);
		}
	}

	for (;;) {
		if (MASKUPDATEBIT(in->nsc_callnumber) == GETPWUID) {
			bucket = get_hash(uid_hash, (char *)in->nsc_u.uid);
		} else { /* make reasonableness check here  */
			if (strlen(in->nsc_u.name) > NSCDMAXNAMELEN) {
				ucred_t *uc = NULL;

				if (door_ucred(&uc) != 0) {
					logit("getpw_lookup: Name too long, "
					    "but no user credential: %s\n",
					    strerror(errno));
				} else {

					logit("getpw_lookup: Name too long "
					    "from pid %d uid %d\n",
					    ucred_getpid(uc),
					    ucred_getruid(uc));
					ucred_free(uc);
				}


				out->nsc_errno = NSS_NOTFOUND;
				out->nsc_return_code = NOTFOUND;
				out->nsc_bufferbytesused = sizeof (*out);
				goto getout;
			}
			bucket = get_hash(nam_hash, in->nsc_u.name);
		}

		if (*bucket == (char *)-1) {	/* pending lookup */
			if (get_clearance(in->nsc_callnumber) != 0) {
				/* no threads available */
				out->nsc_return_code = NOSERVER;
				/* cannot process now */
				out->nsc_bufferbytesused = sizeof (*out);
				current_admin.passwd.nsc_throttle_count++;
				goto getout;
			}
			nscd_wait(&passwd_wait, &passwd_lock, bucket);
			release_clearance(in->nsc_callnumber);
			continue; /* go back and relookup hash bucket */
		}
		break;
	}

	/*
	 * check for no name_service mode
	 */

	if (*bucket == NULL && current_admin.avoid_nameservice) {
		out->nsc_return_code = NOTFOUND;
		out->nsc_bufferbytesused = sizeof (*out);
	} else if (*bucket == NULL ||
	    (in->nsc_callnumber & UPDATEBIT) ||
	    (out_of_date = (!current_admin.avoid_nameservice &&
		(current_admin.passwd.nsc_old_data_ok == 0) &&
		(((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) {
		/*
		 * time has expired
		 */
		int saved_errno;
		int saved_hits = 0;
		struct passwd *p;

		if (get_clearance(in->nsc_callnumber) != 0) {
			/* no threads available */
			out->nsc_return_code = NOSERVER;
			/* cannot process now */
			out->nsc_bufferbytesused = sizeof (*out);
			current_admin.passwd.nsc_throttle_count++;
			goto getout;
		}
		if (*bucket != NULL) {
			saved_hits = ((nsc_bucket_t *)*bucket)->nsc_hits;
		}

		/*
		 *  block any threads accessing this bucket if data
		 *  is non-existent or out of date
		 */

		if (*bucket == NULL || out_of_date) {
			update_pw_bucket((nsc_bucket_t **)bucket,
					(nsc_bucket_t *)-1,
					in->nsc_callnumber);
		} else {
			/*
			 * if still not -1 bucket we are doing
			 * update... mark to prevent pileups of threads if
			 * the name service is hanging..
			 */
			((nsc_bucket_t *)(*bucket))->nsc_status |=
				ST_UPDATE_PENDING;
			/* cleared by deletion of old data */
		}
		mutex_unlock(&passwd_lock);

		if (MASKUPDATEBIT(in->nsc_callnumber) == GETPWUID) {
			p = _uncached_getpwuid_r(in->nsc_u.uid, &out->nsc_u.pwd,
				out->nsc_u.buff+sizeof (struct passwd),
				bufferspace);
			saved_errno = errno;
		} else {
			p = _uncached_getpwnam_r(in->nsc_u.name,
				&out->nsc_u.pwd,
				out->nsc_u.buff+sizeof (struct passwd),
				bufferspace);
			saved_errno = errno;
		}

		mutex_lock(&passwd_lock);

		release_clearance(in->nsc_callnumber);

		if (p == NULL) { /* data not found */
			if (current_admin.debug_level >= DBG_CANT_FIND) {
				if (MASKUPDATEBIT(in->nsc_callnumber) ==
					GETPWUID) {
			logit("getpw_lookup: nscd COULDN'T FIND uid %d\n",
					in->nsc_u.uid);
				} else {
		logit("getpw_lookup: nscd COULDN'T FIND passwd name %s\n",
						in->nsc_u.name);
				}
			}

			if (!(UPDATEBIT & in->nsc_callnumber))
			    current_admin.passwd.nsc_neg_cache_misses++;

			retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t));

			retb->nsc_refcount = 1;
			retb->nsc_data.nsc_bufferbytesused =
				sizeof (nsc_return_t);
			retb->nsc_data.nsc_return_code = NOTFOUND;
			retb->nsc_data.nsc_errno = saved_errno;
			memcpy(out, &retb->nsc_data,
				retb->nsc_data.nsc_bufferbytesused);
			update_pw_bucket((nsc_bucket_t **)bucket, retb,
				in->nsc_callnumber);
			goto getout;
		} else {
			if (current_admin.debug_level >= DBG_ALL) {
				if (MASKUPDATEBIT(in->nsc_callnumber) ==
					GETPWUID) {
				logit("getpw_lookup: nscd FOUND uid %d\n",
						in->nsc_u.uid);
				} else {
			logit("getpw_lookup: nscd FOUND passwd name %s\n",
						in->nsc_u.name);
				}
			}
			if (!(UPDATEBIT & in->nsc_callnumber))
			    current_admin.passwd.nsc_pos_cache_misses++;

			retb = fixbuffer(out, bufferspace);
			update_pw_bucket((nsc_bucket_t **)bucket,
				retb, in->nsc_callnumber);
			if (saved_hits)
				retb->nsc_hits = saved_hits;
		}
	} else { 	/* found entry in cache */
		retb = (nsc_bucket_t *)*bucket;

		retb->nsc_hits++;

		memcpy(out, &(retb->nsc_data),
			retb->nsc_data.nsc_bufferbytesused);

		if (out->nsc_return_code == SUCCESS) {
			if (!(UPDATEBIT & in->nsc_callnumber))
			    current_admin.passwd.nsc_pos_cache_hits++;
			if (current_admin.debug_level >= DBG_ALL) {
				if (MASKUPDATEBIT(in->nsc_callnumber) ==
					GETPWUID) {
			logit("getpw_lookup: found uid %d in cache\n",
						in->nsc_u.uid);
				} else {
			logit("getpw_lookup: found name %s in cache\n",
						in->nsc_u.name);
				}
			}
		} else {
			if (!(UPDATEBIT & in->nsc_callnumber))
			    current_admin.passwd.nsc_neg_cache_hits++;
			if (current_admin.debug_level >= DBG_ALL) {
				if (MASKUPDATEBIT(in->nsc_callnumber) ==
					GETPWUID) {
		logit("getpw_lookup: %d marked as NOT FOUND in cache.\n",
						in->nsc_u.uid);
				} else {
		logit("getpw_lookup: %s marked as NOT FOUND in cache.\n",
						in->nsc_u.name);
				}
			}
		}

		if ((retb->nsc_timestamp < now) &&
			!(in->nsc_callnumber & UPDATEBIT) &&
			!(retb->nsc_status & ST_UPDATE_PENDING)) {
			logit("launch update since time = %d\n",
				retb->nsc_timestamp);
			retb->nsc_status |= ST_UPDATE_PENDING;
			/* cleared by deletion of old data */
			launch_update(in);
		}
	}

getout:

	mutex_unlock(&passwd_lock);

	/*
	 *	secure mode check - blank out passwd if call sucessfull
	 *	and caller != effective id
	 */
	if ((current_admin.passwd.nsc_secure_mode != 0) &&
		(out->nsc_return_code == SUCCESS) &&
		!(UPDATEBIT & in->nsc_callnumber)) {

		ucred_t *uc = NULL;

		if (door_ucred(&uc) != 0) {
			perror("door_ucred");
		} else {
			if (ucred_geteuid(uc) != out->nsc_u.pwd.pw_uid) {
				/*
				 *  write *NP* into passwd field if
				 *  not already that way... we fixed
				 *  the buffer code so there's always room.
				 */
				int len;

				char *foo = out->nsc_u.buff
					+ sizeof (struct passwd)
					+ (int)out->nsc_u.pwd.pw_passwd;

				len = strlen(foo);
				if (len > 0 &&
				    strcmp(foo, "*NP*") != 0 &&
				    strcmp(foo, "x") != 0) {
					if (len < 5)
						len = 5;
					strncpy(foo, "*NP*", len);
					/*
					 * strncpy will
					 * blank all
					 */
				}
			}
			ucred_free(uc);
		}
	}
}
示例#8
0
/*ARGSUSED*/
void
iod_dispatch(void *cookie, char *argp, size_t argsz,
    door_desc_t *dp, uint_t n_desc)
{
	smb_iod_ssn_t *ssn;
	ucred_t *ucred;
	uid_t cl_uid;
	int rc;

	/*
	 * Verify that the calling process has the same UID.
	 * Paranoia:  The door we created has mode 0600, so
	 * this check is probably redundant.
	 */
	ucred = NULL;
	if (door_ucred(&ucred) != 0) {
		rc = EACCES;
		goto out;
	}
	cl_uid = ucred_getruid(ucred);
	ucred_free(ucred);
	ucred = NULL;
	if (cl_uid != getuid()) {
		DPRINT("iod_dispatch: wrong UID\n");
		rc = EACCES;
		goto out;
	}

	/*
	 * The library uses a NULL arg call to check if
	 * the deamon is running.  Just return zero.
	 */
	if (argp == NULL) {
		rc = 0;
		goto out;
	}

	/*
	 * Otherwise, the arg must be the (fixed size)
	 * smb_iod_ssn_t
	 */
	if (argsz != sizeof (*ssn)) {
		rc = EINVAL;
		goto out;
	}

	mutex_lock(&iod_mutex);
	if (iod_terminating) {
		mutex_unlock(&iod_mutex);
		DPRINT("iod_dispatch: terminating\n");
		rc = EINTR;
		goto out;
	}
	if (iod_thr_count++ == 0) {
		alarm(0);
		DPRINT("iod_dispatch: cancelled alarm\n");
	}
	mutex_unlock(&iod_mutex);

	ssn = (void *) argp;
	rc = iod_newvc(ssn);

	mutex_lock(&iod_mutex);
	if (--iod_thr_count == 0) {
		DPRINT("iod_dispatch: schedule alarm\n");
		alarm(ALARM_TIME);
	}
	mutex_unlock(&iod_mutex);

out:
	door_return((void *)&rc, sizeof (rc), NULL, 0);
}
示例#9
0
/*
 * Accept a new client request.  A struct ilbd_client_t is allocated to
 * store the client info.  The accepted socket is port_associate() with
 * the given port.  And the allocated ilbd_client_t struct is passed as
 * the user pointer.
 */
static void
new_req(int ev_port, int listener, void *ev_obj)
{
	struct sockaddr	sa;
	int		sa_len;
	int		new_sd;
	int		sflags;
	ilbd_client_t	*cli;
	int		res;
	uid_t		uid;

	sa_len = sizeof (sa);
	if ((new_sd = accept(listener, &sa, &sa_len)) == -1) {
		/* don't log if we're out of file descriptors */
		if (errno != EINTR && errno != EMFILE)
			logperror("new_req: accept failed");
		goto done;
	}

	/* Set the new socket to be non-blocking. */
	if ((sflags = fcntl(new_sd, F_GETFL, 0)) == -1) {
		logperror("new_req: fcntl(F_GETFL)");
		goto clean_up;
	}
	if (fcntl(new_sd, F_SETFL, sflags | O_NONBLOCK) == -1) {
		logperror("new_req: fcntl(F_SETFL)");
		goto clean_up;
	}
	if (fcntl(new_sd, F_SETFD, FD_CLOEXEC) == -1) {
		logperror("new_req: fcntl(FD_CLOEXEC)");
		goto clean_up;
	}
	if ((cli = calloc(1, sizeof (ilbd_client_t))) == NULL) {
		logerr("new_req: malloc(ilbd_client_t)");
		goto clean_up;
	}
	res = getpeerucred(new_sd, &cli->cli_peer_ucredp);
	if (res == -1) {
		logperror("new_req: getpeerucred failed");
		goto clean_up;
	}
	if ((uid = ucred_getruid(cli->cli_peer_ucredp)) == (uid_t)-1) {
		logperror("new_req: ucred_getruid failed");
		goto clean_up;
	}
	cli->cli_pw_bufsz = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX);
	if ((cli->cli_pw_buf = malloc(cli->cli_pw_bufsz)) == NULL) {
		free(cli);
		logerr("new_req: malloc(cli_pw_buf)");
		goto clean_up;
	}
	if (getpwuid_r(uid, &cli->cli_pw, cli->cli_pw_buf,
	    cli->cli_pw_bufsz) == NULL) {
		free(cli->cli_pw_buf);
		free(cli);
		logperror("new_req: invalid user");
		goto clean_up;
	}
	cli->cli_ev = ILBD_EVENT_REQ;
	cli->cli_sd = new_sd;
	cli->cli_cmd = ILBD_BAD_CMD;
	cli->cli_saved_reply = NULL;
	cli->cli_saved_size = 0;
	if (port_associate(ev_port, PORT_SOURCE_FD, new_sd, POLLRDNORM,
	    cli) == -1) {
		logperror("new_req: port_associate(cli) failed");
		free(cli->cli_pw_buf);
		free(cli);
clean_up:
		(void) close(new_sd);
	}

done:
	/* Re-associate the listener with the event port. */
	if (port_associate(ev_port, PORT_SOURCE_FD, listener, POLLRDNORM,
	    ev_obj) == -1) {
		logperror("new_req: port_associate(listener) failed");
		exit(1);
	}
}