Exemple #1
0
int main (int argc, char **argv)
{
	int fd;
	long num;
	long res;
	door_arg_t door_args;

	if (argc != 3)
		err_quit ("Usage: door_cli1 path number");

	if ((fd = open (argv [1], O_RDWR)) == -1)
		err_msg ("Can't open door");

	num = atol (argv [2]);

	door_args.data_ptr = (char *) #
	door_args.data_size = sizeof (long);
	door_args.desc_ptr = NULL;
	door_args.desc_num = 0;
	door_args.rbuf = (char *) &res;
	door_args.rsize = sizeof (long);

	if (door_call (fd, &door_args) == -1)
		err_msg ("door_call failed");

	printf ("Result = %ld\n", res);

	return (0);
}
Exemple #2
0
/*
 * We use a copy of the door arg because doorfs may change data_ptr
 * and we want to detect that when freeing the door buffers.  After
 * this call, response data must be referenced via rbuf and rsize.
 */
static int
smb_door_call_private(int fd, smb_doorarg_t *da)
{
    door_arg_t door_arg;
    int rc;
    int i;

    bcopy(&da->da_arg, &door_arg, sizeof (door_arg_t));

    for (i = 0; i < SMB_DOOR_CALL_RETRIES; ++i) {
        errno = 0;

        if ((rc = door_call(fd, &door_arg)) == 0)
            break;

        if (errno != EAGAIN && errno != EINTR)
            return (-1);
    }

    if (rc != 0 || door_arg.data_size == 0 || door_arg.rsize == 0) {
        if (errno == 0)
            errno = EIO;
        return (-1);
    }

    da->da_arg.rbuf = door_arg.data_ptr;
    da->da_arg.rsize = door_arg.rsize;
    return (rc);
}
static PyObject *
send(PyObject *self, PyObject *args){
    char *msg, res[64];
    if (! PyArg_Parse(args, "(s)", &msg))
        return NULL;

    int fd;

    door_arg_t door_args ={0};//zero all members
    fd=open("111", O_RDWR);
    door_args.data_ptr=msg;
    door_args.data_size=sizeof(msg)*strlen(msg);

    //skipping desc_ptr and desc_num. both were zero initialized
    door_args.rbuf=(char*)&res; // the result will be written to rbuf
    door_args.rsize=sizeof(res);
    if(door_call(fd, &door_args)==0)
    {
        return Py_BuildValue("s", res);
    }
    else
        printf("error: send nothing!\n");

    return Py_BuildValue("s", "nothing");
}
Exemple #4
0
static int
zp_ping_proxy(void)
{
	int doorfd;
	int *res;
	int cmd[2];
	door_arg_t dparam;

	if ((doorfd = open(ZP_DOOR_PATH, O_RDONLY)) < 0) {
		if (errno == ENOENT) {
			return (-2);
		} else {
			perror("open");
			return (-1);
		}
	}


	cmd[0] = ZP_CMD_PING;

	dparam.data_ptr = (char *)cmd;
	dparam.data_size = sizeof (cmd);
	dparam.desc_ptr = (door_desc_t *)NULL;
	dparam.desc_num = 0;
	dparam.rbuf = NULL;
	dparam.rsize = 0;

	if (door_call(doorfd, &dparam) < 0) {
		if (errno == EBADF) {
			(void) close(doorfd);
			return (-2);
		} else {
			perror("door_call");
			(void) close(doorfd);
			return (-1);
		}
	}

	(void) close(doorfd);
	/* LINTED */
	res = (int *)dparam.data_ptr;

	if (res[1] != ZP_STATUS_OK) {
		zp_perror(res[1]);
		return (-1);
	}

	return (0);
}
Exemple #5
0
int main (int argc, char **argv)
{
	int fd;
	long num;
	long res;
	pid_t pid;
	door_arg_t door_args;

	if (argc != 3)
		err_quit ("Usage: term_door_cli1 path number");

	if ((fd = open (argv [1], O_RDWR)) == -1)
		err_msg ("Can't open door");

	num = atol (argv [2]);

	door_args.data_ptr = (char *) &num;
	door_args.data_size = sizeof (long);
	door_args.desc_ptr = NULL;
	door_args.desc_num = 0;
	door_args.rbuf = (char *) &res;
	door_args.rsize = sizeof (long);

	if (sigset (SIGCHLD, sig_chld) == SIG_ERR)
		err_msg ("sigset failed");

	if ((pid = fork ()) == -1)
		err_msg ("fork failed");
	else if (pid == 0) {
		sleep (2);
		_exit (0);
	}

	for (;;) {
		printf ("Calling door_call\n");
		if (door_call (fd, &door_args) == 0)
			break;
		if ((errno == EINTR) && (flag == 1))
			flag = 0;
		else
			err_msg ("door_call failed");
	}

	printf ("Result = %ld\n", res);

	return (0);
}
Exemple #6
0
/*
 * "ping" to see if a daemon is already running
 */
static int
daemon_exists(void)
{
	door_arg_t	darg;
	picl_reqping_t	req_ping;
	picl_retping_t	ret_ping;
	int		doorh;
	door_info_t	dinfo;

	doorh = open(PICLD_DOOR, O_RDONLY);
	if (doorh < 0)
		return (0);

	if (door_info(doorh, &dinfo) < 0) {
		(void) close(doorh);
		return (0);
	}

	if ((dinfo.di_attributes & DOOR_REVOKED) ||
	    (dinfo.di_data != (uintptr_t)PICLD_DOOR_COOKIE)) {
		(void) close(doorh);
		return (0);
	}

	if (dinfo.di_target != getpid()) {
		(void) close(doorh);
		return (1);
	}

	req_ping.cnum = PICL_CNUM_PING;

	darg.data_ptr = (char *)&req_ping;
	darg.data_size = sizeof (picl_reqping_t);
	darg.desc_ptr = NULL;
	darg.desc_num = 0;
	darg.rbuf = (char *)&ret_ping;
	darg.rsize = sizeof (picl_retping_t);

	if (door_call(doorh, &darg) < 0) {
		(void) close(doorh);
		return (0);
	}

	(void) close(doorh);
	return (1);
}
Exemple #7
0
int
main(int argc, char *argv[])
{
  int fd = -1;
  int blen = 0;
  char *buf = NULL;
  door_arg_t door_args = {0};
  int success = 1;
  blen = strlen(argv[1]) + 1;

  buf = (char *)alloca(blen);
  if (buf == NULL) {
    LOG_OOM(blen);
    return (1);
  }
  strlcpy(buf, argv[1], blen);

  door_args.data_ptr = buf;
  door_args.data_size = blen;

  door_args.rsize = RETURN_SZ;
  door_args.rbuf = alloca(RETURN_SZ);
  if (door_args.rbuf == NULL) {
    LOG_OOM(RETURN_SZ);
    return (1);
  }
  memset(door_args.rbuf, 0, RETURN_SZ);

  fd = open(DOOR, O_RDWR);
  if (fd < 0)
    perror("fifodoor: open (of door FD) failed");

  if (door_call(fd, &door_args) < 0) {
    perror("fifodoor: door_call failed");
    return (1);
  } else {
    success = (*(door_args.rbuf) == '1');
    if (success) {
      fprintf(stdout, "%s\n", (door_args.rbuf + 1));
    } else {
      fprintf(stderr, "error: %s\n", (door_args.rbuf + 1));
    }
    munmap(door_args.rbuf, door_args.rsize);
    return (success);
  }
}
Exemple #8
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);
}
Exemple #9
0
static int
zp_unregister_zone(void)
{
	int doorfd;
	int *res;
	int cmd[2];
	door_arg_t dparam;
	zoneid_t zid;

	if ((doorfd = open(ZP_DOOR_PATH, O_RDONLY)) < 0) {
		perror("open");
		return (-1);
	}

	zid = getzoneid();

	cmd[0] = ZP_CMD_REMOVE_LISTENER;
	cmd[1] = zid;

	dparam.data_ptr = (char *)cmd;
	dparam.data_size = sizeof (cmd);
	dparam.desc_ptr = (door_desc_t *)NULL;
	dparam.desc_num = 0;
	dparam.rbuf = NULL;
	dparam.rsize = 0;

	if (door_call(doorfd, &dparam) < 0) {
		perror("door_call");
		(void) close(doorfd);
		return (-1);
	}

	(void) close(doorfd);
	/* LINTED */
	res = (int *)dparam.data_ptr;

	if (res[1] != ZP_STATUS_OK) {
		zp_perror(res[1]);
		return (-1);
	}

	return (0);
}
Exemple #10
0
int
main(int argc, char **argv)
{
	int		fd, rc;
	long	ival, oval;
	door_arg_t	arg;

	if (argc != 3)
		err_quit("usage: clientintr3 <server-pathname> <integer-value>");

	fd = Open(argv[1], O_RDWR);		/* open the door */

		/* 4set up the arguments and pointer to result */
	ival = atol(argv[2]);
	arg.data_ptr = (char *) &ival;	/* data arguments */
	arg.data_size = sizeof(long);	/* size of data arguments */
	arg.desc_ptr = NULL;
	arg.desc_num = 0;
	arg.rbuf = (char *) &oval;		/* data results */
	arg.rsize = sizeof(long);		/* size of data results */

	Signal(SIGCHLD, sig_chld);
	if (Fork() == 0) {
		sleep(2);		/* child */
		exit(0);		/* generates SIGCHLD */	
	}

		/* 4parent: call server procedure and print result */
	for ( ; ; ) {
		printf("calling door_call\n");
		if ( (rc = door_call(fd, &arg)) == 0)
			break;		/* success */
		if (errno == EINTR && caught_sigchld) {
			caught_sigchld = 0;
			continue;	/* call door_call() again */
		}
		err_sys("door_call error");
	}
	printf("result: %ld\n", oval);

	exit(0);
}
Exemple #11
0
static krb5_error_code
try_door(krb5_context context, const krb5_kcmcache *k,
	 krb5_data *request_data,
	 krb5_data *response_data)
{
#ifdef HAVE_DOOR_CREATE
    door_arg_t arg;
    int fd;
    int ret;

    memset(&arg, 0, sizeof(arg));
	   
    fd = open(k->door_path, O_RDWR);
    if (fd < 0)
	return KRB5_CC_IO;

    arg.data_ptr = request_data->data;
    arg.data_size = request_data->length;
    arg.desc_ptr = NULL;
    arg.desc_num = 0;
    arg.rbuf = NULL;
    arg.rsize = 0;

    ret = door_call(fd, &arg);
    close(fd);
    if (ret != 0)
	return KRB5_CC_IO;

    ret = krb5_data_copy(response_data, arg.rbuf, arg.rsize);
    munmap(arg.rbuf, arg.rsize);
    if (ret)
	return ret;

    return 0;
#else
    return KRB5_CC_IO;
#endif
}
Exemple #12
0
int
door_send_sms(const char *to,
	      const char *msg)
{
    struct door_arg da;
    DOORSMS dsp;
    int rc;
    char rbuf[1024];
    

    if (door_fd < 0)
	return -1;
    
    memset(&dsp, 0, sizeof(dsp));
    strncpy(dsp.phone, to, sizeof(dsp.phone)-1);
    strncpy(dsp.message, msg, sizeof(dsp.message)-1);
    
    memset(&da, 0, sizeof(da));
    da.data_ptr = (char *) &dsp;
    da.data_size = sizeof(dsp);
    da.desc_ptr = NULL;
    da.desc_num = 0;
    da.rbuf = rbuf;
    da.rsize = sizeof(rbuf);
    
    while ((rc = door_call(door_fd, &da)) < 0 && errno == EINTR)
	;
    
    if (rc < 0)
	return -2;
    
    if (sizeof(rc) != da.data_size)
	return -3;
    
    return * (int *) da.data_ptr;
}
Exemple #13
0
static int
is_server_running(rmedia_handle_t *handle)
{
	door_arg_t	door_args;
	smedia_reqping_t	reqping;
	smedia_retping_t	*retping;
	int		ret_val;
	int		door_fd;
	CLIENT		*clnt;
	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
	smserver_info	*server_info;

	/*
	 * We will assume that we are running at level 2 or greater
	 * and attempt to contact the server using RPC mecahnisms.
	 * If that fails then we will attempt to contact the server
	 * using non-rpc mechanism. This will enable the libsmedia
	 * to be used in SINGLE user mode when inetd is not running.
	 * We expect the server to have been started manually by user.
	 *
	 * Note that "localhost" is used (vs hostname (eg, "uname -n")),
	 * as this minimizes interference with common IPSec rules.
	 */

	clnt = clnt_create("localhost", SMSERVERPROG, SMSERVERVERS,
	    "circuit_v");
	if (clnt == (CLIENT *)NULL) {
		/*
		 * The failure could be that we are running at level 1
		 */
		door_fd = open(smedia_service, O_RDONLY, 0644);
		if (door_fd < 0) {
			DPRINTF1("Error in opening %s\n",
			    smedia_service);
			return (0);
		}

		DPRINTF1("rbuf address=%p\n", rbuf);
		reqping.cnum = SMEDIA_CNUM_PING;
		door_args.data_ptr = (char *)&reqping;
		door_args.data_size = sizeof (smedia_services_t);
		door_args.desc_ptr = NULL;
		door_args.desc_num = 0;
		door_args.rbuf = rbuf;
		door_args.rsize = sizeof (rbuf);

		ret_val = door_call(door_fd, &door_args);
		(void) close(door_fd);
		if (ret_val < 0) {
			return (0);
		}
		DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
		    door_args.rsize, door_args.data_size,
		    door_args.data_ptr);
		retping = (smedia_retping_t *)(
		    (void *)door_args.data_ptr);
		if (retping->cnum != SMEDIA_CNUM_PING) {
			DPRINTF1("*** door call failed *** cnum "
			    "returned = 0x%x\n", retping->cnum);
			return (0);
		}
		return (1);
	}
	server_info = smserverproc_get_serverinfo_1(NULL, clnt);
	if (server_info == NULL) {
		if (clnt)
			clnt_destroy(clnt);
		return (0);
	}
	if (server_info->status != 0) {
		if (clnt)
			clnt_destroy(clnt);
		DPRINTF1("get server_info call failed. "
		    "status = %d\n", server_info->status);
		return (0);
	}
	if (server_info->vernum != SMSERVERVERS) {
		if (clnt)
			clnt_destroy(clnt);
		DPRINTF2("version expected = %d version "
		    "returned = %d\n", SMSERVERVERS,
		    server_info->vernum);
		return (0);
	}

	door_fd = open(smedia_service, O_RDONLY, 0644);
	if (door_fd < 0) {
		DPRINTF1("Error in opening %s\n", smedia_service);
		return (0);
	}

	DPRINTF1("rbuf address=%p\n", rbuf);
	reqping.cnum = SMEDIA_CNUM_PING;
	door_args.data_ptr = (char *)&reqping;
	door_args.data_size = sizeof (smedia_services_t);
	door_args.desc_ptr = NULL;
	door_args.desc_num = 0;
	door_args.rbuf = rbuf;
	door_args.rsize = sizeof (rbuf);

	ret_val = door_call(door_fd, &door_args);
	(void) close(door_fd);
	if (ret_val < 0) {
		return (0);
	}
	DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
	    door_args.rsize, door_args.data_size,
	    door_args.data_ptr);
	retping = (smedia_retping_t *)((void *)door_args.data_ptr);
	if (retping->cnum != SMEDIA_CNUM_PING) {
		DPRINTF1("*** door call failed *** cnum returned "
		    "= 0x%x\n", retping->cnum);
		return (0);
	}
	handle->sm_clnt = clnt;
	return (1);
}
Exemple #14
0
smedia_handle_t
get_handle_from_fd(int32_t fd)
{
	rmedia_handle_t	*handle;
	void	*lib_handle;
	int	door_fd, door_server;
	int	ret_val;
	door_arg_t	door_args;
	smedia_reqopen_t	reqopen;
	smedia_reterror_t	*reterror;
	door_desc_t	ddesc[2];
	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
	struct stat	stat;

	DPRINTF("smedia_get_handle called\n");
	handle = (rmedia_handle_t *)malloc(sizeof (rmedia_handle_t));
	if (handle == NULL) {
		DPRINTF("Could not allocate memory for handle\n");
		return (NULL);
	}
	(void) memset((void *) handle, 0, sizeof (rmedia_handle_t));
	handle->sm_fd = -1;
	handle->sm_door = -1;
	handle->sm_death_door = -1;
	handle->sm_buffd = -1;
	handle->sm_buf = NULL;
	handle->sm_bufsize = 0;

	if (ioctl(fd, DKIOCINFO, &handle->sm_dkinfo) == -1) {
		free(handle);
		PERROR("DKIOCINFO failed");
		return (NULL);
	}
	lib_handle = get_dev_library_handle(fd);
	if (lib_handle == NULL) {
		free(handle);
		DPRINTF("lib_Handle is NULL\n");
		errno = ENOTSUP;
		return (NULL);
	}
	DPRINTF("Handle initialised successfully.\n");
	/* Initialise the handle elements */
	handle->sm_lib_handle = lib_handle;
	handle->sm_signature = LIBSMEDIA_SIGNATURE;
	DPRINTF2("fd=%d signature=0x%x\n", handle->sm_fd, handle->sm_signature);

	if ((handle->sm_dkinfo.dki_ctype == DKC_SCSI_CCS) ||
	    (handle->sm_dkinfo.dki_ctype == DKC_MD21) ||
	    (handle->sm_dkinfo.dki_ctype == DKC_CDROM)) {

		ret_val = is_server_running(handle);
		if (ret_val == 0) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			return (NULL);
		}
		door_fd = open(smedia_service, O_RDONLY, 0644);
		if (door_fd < 0) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			DPRINTF1("Error in opening %s\n", smedia_service);
			PERROR(smedia_service);
			return (NULL);
		}

		DPRINTF1("rbuf address=%p\n", rbuf);
		ddesc[0].d_data.d_desc.d_descriptor = fd;
		ddesc[0].d_attributes = DOOR_DESCRIPTOR;
		reqopen.cnum = SMEDIA_CNUM_OPEN_FD;
		door_args.data_ptr = (char *)&reqopen;
		door_args.data_size = sizeof (smedia_services_t);
		door_args.desc_ptr = &ddesc[0];
		door_args.desc_num = 1;
		door_args.rbuf = rbuf;
		door_args.rsize = sizeof (rbuf);

		ret_val = door_call(door_fd, &door_args);
		(void) close(door_fd);
		if (ret_val < 0) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			PERROR("door_call");
			return (NULL);
		}
		DPRINTF3("rsize = %d data_size = %d data_ptr = %p \n",
		    door_args.rsize, door_args.data_size,
		    door_args.data_ptr);
		reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
		if (reterror->cnum != SMEDIA_CNUM_OPEN_FD) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			DPRINTF1(
	"*** door call failed *** cnum returned = 0x%x\n", reterror->cnum);
			errno = reterror->errnum;
			return (NULL);
		}
		/*
		 * 2 door descriptors are returned after the above door call.
		 * The first door descriptor is the one that will be used
		 * in subsequent smedia calls. A dedicated thread is
		 * associated with this door to handle client calls.
		 * The second door descriptor is needed to signal unexpected
		 * death of the client to the server. This will help the server
		 * to do the necessary cleanup.
		 */
		if (door_args.desc_num != 2) {
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			DPRINTF("Num of door descriptors returned by "
			    "server is not 2");
			if (door_args.desc_num)
				(void) close(door_args.desc_ptr->\
				    d_data.d_desc.d_descriptor);
			return (NULL);
		}
		door_server = door_args.desc_ptr->d_data.d_desc.d_descriptor;
		/* Check if the descriptor returned is S_IFDOOR */
		if (fstat(door_server, &stat) < 0) {
			PERROR("fstat");
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			return (NULL);
		}
		if (!S_ISDOOR(stat.st_mode)) {
			DPRINTF(
		"Descriptor returned by door_call is not of type DOOR\n");
			(void) dlclose(handle->sm_lib_handle);
			free(handle);
			if (handle->sm_clnt)
				clnt_destroy(handle->sm_clnt);
			return (NULL);
		}
		handle->sm_door = door_server;
		handle->sm_fd = fd;
		door_args.desc_ptr++;
		handle->sm_death_door =
		    door_args.desc_ptr->d_data.d_desc.d_descriptor;
		DPRINTF("door call succeeded.\n");
		return ((smedia_handle_t)handle);

	} else {
		handle->sm_fd = fd;
		return ((smedia_handle_t)handle);
	}

}
Exemple #15
0
/* ARGSUSED */
static enum clnt_stat
clnt_door_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp,
	xdrproc_t xresults, caddr_t resultsp, struct timeval utimeout)
{
/* LINTED pointer alignment */
	struct cu_data	*cu = (struct cu_data *)cl->cl_private;
	XDR 		xdrs;
	door_arg_t	params;
	char		*outbuf_ref;
	struct rpc_msg	reply_msg;
	bool_t		need_to_unmap;
	int		nrefreshes = 2;	/* number of times to refresh cred */

	rpc_callerr.re_errno = 0;
	rpc_callerr.re_terrno = 0;

	if ((params.rbuf = alloca(cu->cu_sendsz)) == NULL) {
		rpc_callerr.re_terrno = 0;
		rpc_callerr.re_errno = errno;
		return (rpc_callerr.re_status = RPC_SYSTEMERROR);
	}
	outbuf_ref = params.rbuf;
	params.rsize = cu->cu_sendsz;
	if ((params.data_ptr = alloca(cu->cu_sendsz)) == NULL) {
		rpc_callerr.re_terrno = 0;
		rpc_callerr.re_errno = errno;
		return (rpc_callerr.re_status = RPC_SYSTEMERROR);
	}

call_again:
	xdrmem_create(&xdrs, params.data_ptr, cu->cu_sendsz, XDR_ENCODE);
/* LINTED pointer alignment */
	(*(uint32_t *)cu->cu_header)++;	/* increment XID */
	(void) memcpy(params.data_ptr, cu->cu_header, cu->cu_xdrpos);
	XDR_SETPOS(&xdrs, cu->cu_xdrpos);

	if ((!XDR_PUTINT32(&xdrs, (int32_t *)&proc)) ||
				(!AUTH_MARSHALL(cl->cl_auth, &xdrs)) ||
					(!(*xargs)(&xdrs, argsp))) {
		return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
	}
	params.data_size = (int)XDR_GETPOS(&xdrs);

	params.desc_ptr = NULL;
	params.desc_num = 0;
	if (door_call(cu->cu_fd, &params) < 0) {
		rpc_callerr.re_errno = errno;
		return (rpc_callerr.re_status = RPC_CANTSEND);
	}

	if (params.rbuf == NULL || params.rsize == 0) {
		return (rpc_callerr.re_status = RPC_FAILED);
	}
	need_to_unmap = (params.rbuf != outbuf_ref);

/* LINTED pointer alignment */
	if (*(uint32_t *)params.rbuf != *(uint32_t *)cu->cu_header) {
		rpc_callerr.re_status = RPC_CANTDECODERES;
		goto done;
	}

	xdrmem_create(&xdrs, params.rbuf, params.rsize, XDR_DECODE);
	reply_msg.acpted_rply.ar_verf = _null_auth;
	reply_msg.acpted_rply.ar_results.where = resultsp;
	reply_msg.acpted_rply.ar_results.proc = xresults;

	if (xdr_replymsg(&xdrs, &reply_msg)) {
		if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
				reply_msg.acpted_rply.ar_stat == SUCCESS)
			rpc_callerr.re_status = RPC_SUCCESS;
		else
			__seterr_reply(&reply_msg, &rpc_callerr);

		if (rpc_callerr.re_status == RPC_SUCCESS) {
			if (!AUTH_VALIDATE(cl->cl_auth,
					    &reply_msg.acpted_rply.ar_verf)) {
				rpc_callerr.re_status = RPC_AUTHERROR;
				rpc_callerr.re_why = AUTH_INVALIDRESP;
			}
			if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
				xdrs.x_op = XDR_FREE;
				(void) xdr_opaque_auth(&xdrs,
					&(reply_msg.acpted_rply.ar_verf));
			}
		}
		/*
		 * If unsuccesful AND error is an authentication error
		 * then refresh credentials and try again, else break
		 */
		else if (rpc_callerr.re_status == RPC_AUTHERROR) {
			/*
			 * maybe our credentials need to be refreshed ...
			 */
			if (nrefreshes-- &&
			    AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
				if (need_to_unmap)
					(void) munmap(params.rbuf,
								params.rsize);
				goto call_again;
			} else
				/*
				 * We are setting rpc_callerr here given that
				 * libnsl is not reentrant thereby
				 * reinitializing the TSD.  If not set here then
				 * success could be returned even though refresh
				 * failed.
				 */
				rpc_callerr.re_status = RPC_AUTHERROR;
		}
	} else
		rpc_callerr.re_status = RPC_CANTDECODERES;

done:
	if (need_to_unmap)
		(void) munmap(params.rbuf, params.rsize);
	return (rpc_callerr.re_status);
}
/*
 * Enqueue attach-on-demand command to the given JVM
 */
static
int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) {
    size_t size;
    door_arg_t door_args;
    char res_buffer[RES_BUF_SIZE];
    int rc, i;
    char* buf = NULL;
    int result = -1;

    /*
     * First we get the command string and create the start of the
     * argument string to send to the target VM:
     * <ver>\0<cmd>\0
     */
    if (cstr == NULL) {
        print_debug("command name is NULL\n");
        goto quit;
    }
    size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
    buf = (char*)malloc(size);
    if (buf != NULL) {
        char* pos = buf;
        strcpy(buf, PROTOCOL_VERSION);
        pos += strlen(PROTOCOL_VERSION)+1;
        strcpy(pos, cstr);
    } else {
        set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
        print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__);
        goto quit;
    }

    /*
     * Next we iterate over the arguments and extend the buffer
     * to include them.
     */
    for (i=0; i<arg_count; i++) {
        cstr = args[i];
        if (cstr != NULL) {
            size_t len = strlen(cstr);
            char* newbuf = (char*)realloc(buf, size+len+1);
            if (newbuf == NULL) {
                set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
                print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__);
                goto quit;
            }
            buf = newbuf;
            strcpy(buf+size, cstr);
            size += len+1;
        }
    }

    /*
     * The arguments to the door function are in 'buf' so we now
     * do the door call
     */
    door_args.data_ptr = buf;
    door_args.data_size = size;
    door_args.desc_ptr = NULL;
    door_args.desc_num = 0;
    door_args.rbuf = (char*)&res_buffer;
    door_args.rsize = sizeof(res_buffer);

    RESTARTABLE(door_call(jvm->door_fd, &door_args), rc);

    /*
     * door_call failed
     */
    if (rc == -1) {
        print_debug("door_call failed\n");
    } else {
        /*
         * door_call succeeded but the call didn't return the the expected jint.
         */
        if (door_args.data_size < sizeof(int)) {
            print_debug("Enqueue error - reason unknown as result is truncated!");
        } else {
            int* res = (int*)(door_args.data_ptr);
            if (*res != 0) {
                const char* msg = translate_error(*res);
                if (msg == NULL) {
                    print_debug("Unable to enqueue command to target VM: %d\n", *res);
                } else {
                    print_debug("Unable to enqueue command to target VM: %s\n", msg);
                }
            } else {
                /*
                 * The door call should return a file descriptor to one end of
                 * a socket pair
                 */
                if ((door_args.desc_ptr != NULL) &&
                    (door_args.desc_num == 1) &&
                    (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
                    result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
                } else {
                    print_debug("Reply from enqueue missing descriptor!\n");
                }
            }
        }
    }

quit:
    if (buf) free(buf);
    return result;
}
Exemple #17
0
/*
 * For each provider found in pkcs11.conf: expand $ISA if necessary,
 * verify the module is signed, load the provider, find all of its
 * slots, and store the function list and disabled policy.
 *
 * This function requires that the uentrylist_t and pkcs11_slottable_t
 * already have memory allocated, and that the uentrylist_t is already
 * populated with provider and policy information.
 *
 * pInitArgs can be set to NULL, but is normally the same value
 * the framework's C_Initialize() was called with.
 *
 * Unless metaslot is explicitly disabled, it is setup when all other
 * providers are loaded.
 */
CK_RV
pkcs11_slot_mapping(uentrylist_t *pplist, CK_VOID_PTR pInitArgs)
{
	CK_RV rv = CKR_OK;
	CK_RV prov_rv;			/* Provider's return code */
	CK_INFO prov_info;
	CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
	CK_FUNCTION_LIST_PTR prov_funcs = NULL; /* Provider's function list */
	CK_ULONG prov_slot_count; 		/* Number of slots */
	CK_SLOT_ID slot_id; 		/* slotID assigned for framework */
	CK_SLOT_ID_PTR prov_slots = NULL; 	/* Provider's slot list */
					/* Enabled or Disabled policy */
	CK_MECHANISM_TYPE_PTR prov_pol_mechs = NULL;

	void *dldesc = NULL;
	char *isa, *fullpath = NULL, *dl_error;
	uentrylist_t *phead;
	uint_t prov_count = 0;
	pkcs11_slot_t *cur_slot;
	CK_ULONG i;
	size_t len;
	uentry_t *metaslot_entry = NULL;
	/* number of slots in the framework, not including metaslot */
	uint_t slot_count = 0;

	ELFsign_status_t estatus = ELFSIGN_UNKNOWN;
	char *estatus_str = NULL;
	int kcfdfd = -1;
	door_arg_t	darg;
	kcf_door_arg_t *kda = NULL;
	kcf_door_arg_t *rkda = NULL;
	int r;

	phead = pplist;

	/* Loop through all of the provider listed in pkcs11.conf */
	while (phead != NULL) {
		if (!strcasecmp(phead->puent->name, "metaslot")) {
			/*
			 * Skip standard processing for metaslot
			 * entry since it is not an actual library
			 * that can be dlopened.
			 * It will be initialized later.
			 */
			if (metaslot_entry != NULL) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: multiple entries for metaslot "
				    "detected.  All but the first entry will "
				    "be ignored");
			} else {
				metaslot_entry = phead->puent;
			}
			goto contparse;
		}

		/* Check for Instruction Set Architecture indicator */
		if ((isa = strstr(phead->puent->name, PKCS11_ISA)) != NULL) {
			/* Substitute the architecture dependent path */
			len = strlen(phead->puent->name) -
			    strlen(PKCS11_ISA) +
			    strlen(PKCS11_ISA_DIR) + 1;
			if ((fullpath = (char *)malloc(len)) == NULL) {
				cryptoerror(LOG_ERR,
				    "libpksc11: parsing %s, out of memory. "
				    "Cannot continue parsing.",
				    _PATH_PKCS11_CONF);
				rv = CKR_HOST_MEMORY;
				goto conferror;
			}
			*isa = '\000';
			isa += strlen(PKCS11_ISA);
			(void) snprintf(fullpath, len, "%s%s%s",
			    phead->puent->name, PKCS11_ISA_DIR, isa);
		} else if ((fullpath = strdup(phead->puent->name)) == 0) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: parsing %s, out of memory. "
			    "Cannot continue parsing.",
			    _PATH_PKCS11_CONF);
			rv = CKR_HOST_MEMORY;
			goto conferror;
		}

		/*
		 * Open the provider. Use RTLD_NOW to make sure we
		 * will not encounter symbol referencing errors later.
		 * Use RTLD_GROUP to limit the provider to it's own
		 * symbols, which prevents it from mistakenly accessing
		 * the framework's C_* functions.
		 */
		dldesc = dlopen(fullpath, RTLD_NOW|RTLD_GROUP);

		/*
		 * If we failed to load it, we will just skip this
		 * provider and move on to the next one.
		 */
		if (dldesc == NULL) {
			dl_error = dlerror();
			cryptoerror(LOG_ERR,
			    "libpkcs11: Cannot load PKCS#11 library %s.  "
			    "dlerror: %s. %s",
			    fullpath, dl_error != NULL ? dl_error : "Unknown",
			    conf_err);
			goto contparse;
		}

		/* Get the pointer to provider's C_GetFunctionList() */
		Tmp_C_GetFunctionList =
		    (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");

		/*
		 * If we failed to get the pointer to C_GetFunctionList(),
		 * skip this provider and continue to the next one.
		 */
		if (Tmp_C_GetFunctionList == NULL) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not dlsym() C_GetFunctionList() "
			    "for %s. May not be a PKCS#11 library. %s",
			    fullpath, conf_err);
			(void) dlclose(dldesc);
			goto contparse;
		}


		/* Get the provider's function list */
		prov_rv = Tmp_C_GetFunctionList(&prov_funcs);

		/*
		 * If we failed to get the provider's function list,
		 * skip this provider and continue to the next one.
		 */
		if (prov_rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not get function list for %s. "
			    "%s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) dlclose(dldesc);
			goto contparse;
		}

		/* Initialize this provider */
		prov_rv = prov_funcs->C_Initialize(pInitArgs);

		/*
		 * If we failed to initialize this provider,
		 * skip this provider and continue to the next one.
		 */
		if ((prov_rv != CKR_OK) &&
		    (prov_rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not initialize %s. "
			    "%s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Make sure this provider is implementing the same
		 * major version, and at least the same minor version
		 * that we are.
		 */
		prov_rv = prov_funcs->C_GetInfo(&prov_info);

		/*
		 * If we can't verify that we are implementing the
		 * same major version, or if it is definitely not the same
		 * version, we need to skip this provider.
		 */
		if ((prov_rv != CKR_OK) ||
		    (prov_info.cryptokiVersion.major !=
			CRYPTOKI_VERSION_MAJOR))  {
			if (prov_rv != CKR_OK) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Could not verify version of "
				    "%s. %s Error: %s.", fullpath,
				    conf_err, pkcs11_strerror(prov_rv));
			} else {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Only CRYPTOKI major version "
				    "%d is supported.  %s is major "
				    "version %d. %s",
				    CRYPTOKI_VERSION_MAJOR, fullpath,
				    prov_info.cryptokiVersion.major, conf_err);
			}
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Warn the administrator (at debug) that a provider with
		 * a significantly older or newer version of
		 * CRYPTOKI is being used.  It should not cause
		 * problems, but logging a warning makes it easier
		 * to debug later.
		 */
		if ((prov_info.cryptokiVersion.minor <
			CRYPTOKI_VERSION_WARN_MINOR) ||
		    (prov_info.cryptokiVersion.minor >
			CRYPTOKI_VERSION_MINOR)) {
			cryptoerror(LOG_DEBUG,
			    "libpkcs11: %s CRYPTOKI minor version, %d, may "
			    "not be compatible with minor version %d.",
			    fullpath, prov_info.cryptokiVersion.minor,
			    CRYPTOKI_VERSION_MINOR);
		}

		/*
		 * Find out how many slots this provider has,
		 * call with tokenPresent set to FALSE so all
		 * potential slots are returned.
		 */
		prov_rv = prov_funcs->C_GetSlotList(FALSE,
		    NULL, &prov_slot_count);

		/*
		 * If the call failed, or if no slots are returned,
		 * then skip this provider and continue to next one.
		 */
		if (prov_rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpksc11: Could not get slot list from %s. "
			    "%s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		if (prov_slot_count == 0) {
			cryptodebug("libpkcs11: No slots presented from %s. "
			    "Skipping this plug-in at this time.\n",
			    fullpath);
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Verify that the module is signed correctly.
		 *
		 * NOTE: there is a potential race condition here,
		 * since the module is verified well after we have
		 * opened the provider via dlopen().  This could be
		 * resolved by a variant of dlopen() that would take a
		 * file descriptor as an argument and by changing the
		 * kcfd libelfsign door protocol to use and fd instead
		 * of a path - but that wouldn't work in the kernel case.
		 */
		while ((kcfdfd = open(_PATH_KCFD_DOOR, O_RDONLY)) == -1) {
			if (!(errno == EINTR || errno == EAGAIN))
				break;
		}
		if (kcfdfd == -1) {
			cryptoerror(LOG_ERR, "libpkcs11: open %s: %s",
				_PATH_KCFD_DOOR,
			    strerror(errno));
			goto verifycleanup;
		}

		/* Mark the door "close on exec" */
		(void) fcntl(kcfdfd, F_SETFD, FD_CLOEXEC);

		if ((kda = malloc(sizeof (kcf_door_arg_t))) == NULL) {
			cryptoerror(LOG_ERR, "libpkcs11: malloc of kda "
				"failed: %s", strerror(errno));
			goto verifycleanup;
		}
		kda->da_version = KCF_KCFD_VERSION1;
		kda->da_iskernel = B_FALSE;
		(void) strlcpy(kda->da_u.filename, fullpath,
		    strlen(fullpath) + 1);

		darg.data_ptr = (char *)kda;
		darg.data_size = sizeof (kcf_door_arg_t);
		darg.desc_ptr = NULL;
		darg.desc_num = 0;
		darg.rbuf = (char *)kda;
		darg.rsize = sizeof (kcf_door_arg_t);

		while ((r = door_call(kcfdfd, &darg)) != 0) {
			if (!(errno == EINTR || errno == EAGAIN))
				break;
		}

		if (r != 0) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Unable to contact kcfd: %s",
			    strerror(errno));
			goto verifycleanup;
		}

		/*LINTED*/
		rkda = (kcf_door_arg_t *)darg.rbuf;
		if (rkda->da_version != KCF_KCFD_VERSION1) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: kcfd and libelfsign versions "
			    "don't match: got %d expected %d",
			    rkda->da_version, KCF_KCFD_VERSION1);
			goto verifycleanup;
		}
		estatus = rkda->da_u.result.status;
verifycleanup:
		if (kcfdfd != -1) {
			(void) close(kcfdfd);
		}
		if (rkda != NULL && rkda != kda)
			(void) munmap((char *)rkda, darg.rsize);
		if (kda != NULL) {
			bzero(kda, sizeof (kda));
			free(kda);
			kda = NULL;
			rkda = NULL;	/* rkda is an alias of kda */
		}

		switch (estatus) {
		case ELFSIGN_SUCCESS:
		case ELFSIGN_RESTRICTED:
			break;
		case ELFSIGN_NOTSIGNED:
			estatus_str = strdup("not a signed provider.");
			break;
		case ELFSIGN_FAILED:
			estatus_str = strdup("signature verification failed.");
			break;
		default:
			estatus_str = strdup("unexpected failure in ELF "
			    "signature verification. "
			    "System may have been tampered with.");
		}
		if (estatus_str != NULL) {
			cryptoerror(LOG_ERR, "libpkcs11: %s %s %s",
			    fullpath, estatus_str ? estatus_str : "",
			    estatus == ELFSIGN_UNKNOWN ?
			    "Cannot continue parsing " _PATH_PKCS11_CONF:
			    conf_err);
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			free(estatus_str);
			estatus_str = NULL;
			if (estatus == ELFSIGN_UNKNOWN) {
				prov_funcs = NULL;
				dldesc = NULL;
				rv = CKR_GENERAL_ERROR;
				goto conferror;
			}
			goto contparse;
		}

		/* Allocate memory for the slot list */
		prov_slots = calloc(prov_slot_count, sizeof (CK_SLOT_ID));

		if (prov_slots == NULL) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Could not allocate memory for "
			    "plug-in slots. Cannot continue parsing %s\n",
			    _PATH_PKCS11_CONF);
			rv = CKR_HOST_MEMORY;
			goto conferror;
		}

		/* Get slot list from provider */
		prov_rv = prov_funcs->C_GetSlotList(FALSE,
		    prov_slots, &prov_slot_count);

		/* if second call fails, drop this provider */
		if (prov_rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: Second call to C_GetSlotList() for %s "
			    "failed. %s Error: %s.",
			    fullpath, conf_err, pkcs11_strerror(prov_rv));
			(void) prov_funcs->C_Finalize(NULL);
			(void) dlclose(dldesc);
			goto contparse;
		}

		/*
		 * Parse the list of disabled or enabled mechanisms, will
		 * apply to each of the provider's slots.
		 */
		if (phead->puent->count > 0) {
			rv = pkcs11_mech_parse(phead->puent->policylist,
			    &prov_pol_mechs, phead->puent->count);

			if (rv == CKR_HOST_MEMORY) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Could not parse configuration,"
				    "out of memory. Cannot continue parsing "
				    "%s.", _PATH_PKCS11_CONF);
				goto conferror;
			} else if (rv == CKR_MECHANISM_INVALID) {
				/*
				 * Configuration file is corrupted for this
				 * provider.
				 */
				cryptoerror(LOG_ERR,
				    "libpkcs11: Policy invalid or corrupted "
				    "for %s. Use cryptoadm(1M) to fix "
				    "this. Skipping this plug-in.",
				    fullpath);
				(void) prov_funcs->C_Finalize(NULL);
				(void) dlclose(dldesc);
				goto contparse;
			}
		}

		/* Allocate memory in our slottable for these slots */
		rv = pkcs11_slottable_increase(prov_slot_count);

		/*
		 * If any error is returned, it will be memory related,
		 * so we need to abort the attempt at filling the
		 * slottable.
		 */
		if (rv != CKR_OK) {
			cryptoerror(LOG_ERR,
			    "libpkcs11: slottable could not increase. "
			    "Cannot continue parsing %s.",
			    _PATH_PKCS11_CONF);
			goto conferror;
		}

		/* Configure information for each new slot */
		for (i = 0; i < prov_slot_count; i++) {
			/* allocate slot in framework */
			rv = pkcs11_slot_allocate(&slot_id);
			if (rv != CKR_OK) {
				cryptoerror(LOG_ERR,
				    "libpkcs11: Could not allocate "
				    "new slot.  Cannot continue parsing %s.",
				    _PATH_PKCS11_CONF);
				goto conferror;
			}
			slot_count++;
			cur_slot = slottable->st_slots[slot_id];
			(void) pthread_mutex_lock(&cur_slot->sl_mutex);
			cur_slot->sl_id = prov_slots[i];
			cur_slot->sl_func_list = prov_funcs;
			cur_slot->sl_enabledpol =
			    phead->puent->flag_enabledlist;
			cur_slot->sl_pol_mechs = prov_pol_mechs;
			cur_slot->sl_pol_count = phead->puent->count;
			cur_slot->sl_norandom = phead->puent->flag_norandom;
			cur_slot->sl_dldesc = dldesc;
			cur_slot->sl_prov_id = prov_count + 1;
			(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
		}


		/* Set and reset values to process next provider */
		prov_count++;
contparse:
		prov_slot_count = 0;
		Tmp_C_GetFunctionList = NULL;
		prov_funcs = NULL;
		dldesc = NULL;
		if (fullpath != NULL) {
			free(fullpath);
			fullpath = NULL;
		}
		if (prov_slots != NULL) {
			free(prov_slots);
			prov_slots = NULL;
		}
		phead = phead->next;
	}

	if (slot_count == 0) {
		/*
		 * there's no other slot in the framework,
		 * there is nothing to do
		 */
		goto config_complete;
	}

	/* determine if metaslot should be enabled */

	/*
	 * Check to see if any environment variable is defined
	 * by the user for configuring metaslot.  Users'
	 * setting always take precedence over the system wide
	 * setting.  So, we will first check for any user's
	 * defined env variables before looking at the system-wide
	 * configuration.
	 */
	get_user_metaslot_config();

	/* no metaslot entry in /etc/crypto/pkcs11.conf */
	if (!metaslot_entry) {
		/*
		 * If user env variable indicates metaslot should be enabled,
		 * but there's no entry in /etc/crypto/pkcs11.conf for
		 * metaslot at all, will respect the user's defined value
		 */
		if ((metaslot_config.enabled_specified) &&
		    (metaslot_config.enabled)) {
			metaslot_enabled = B_TRUE;
		}
	} else {
		if (!metaslot_config.enabled_specified) {
			/*
			 * take system wide value if
			 * it is not specified by user
			 */
			metaslot_enabled
			    = metaslot_entry->flag_metaslot_enabled;
		} else {
			metaslot_enabled = metaslot_config.enabled;
		}
	}

	/*
	 *
	 * As long as the user or system configuration file does not
	 * disable metaslot, it will be enabled regardless of the
	 * number of slots plugged into the framework.  Therefore,
	 * metaslot is enabled even when there's only one slot
	 * plugged into the framework.  This is necessary for
	 * presenting a consistent token label view to applications.
	 *
	 * However, for the case where there is only 1 slot plugged into
	 * the framework, we can use "fastpath".
	 *
	 * "fastpath" will pass all of the application's requests
	 * directly to the underlying provider.  Only when policy is in
	 * effect will we need to keep slotID around.
	 *
	 * When metaslot is enabled, and fastpath is enabled,
	 * all the metaslot processing will be skipped.
	 * When there is only 1 slot, there's
	 * really not much metaslot can do in terms of combining functionality
	 * of different slots, and object migration.
	 *
	 */

	/* check to see if fastpath can be used */
	if (slottable->st_last == slottable->st_first) {

		cur_slot = slottable->st_slots[slottable->st_first];

		(void) pthread_mutex_lock(&cur_slot->sl_mutex);

		if ((cur_slot->sl_pol_count == 0) &&
		    (!cur_slot->sl_enabledpol) && (!cur_slot->sl_norandom)) {
			/* No policy is in effect, don't need slotid */
			fast_funcs = cur_slot->sl_func_list;
			purefastpath = B_TRUE;
		} else {
			fast_funcs = cur_slot->sl_func_list;
			fast_slot = slottable->st_first;
			policyfastpath = B_TRUE;
		}

		(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
	}

	if ((purefastpath || policyfastpath) && (!metaslot_enabled)) {
		goto config_complete;
	}

	/*
	 * If we get here, there are more than 2 slots in the framework,
	 * we need to set up metaslot if it is enabled
	 */
	if (metaslot_enabled) {
		rv = setup_metaslot(metaslot_entry);
		if (rv != CKR_OK) {
			goto conferror;
		}
	}


config_complete:

	return (CKR_OK);

conferror:
	/*
	 * This cleanup code is only exercised when a major,
	 * unrecoverable error like "out of memory" occurs.
	 */
	if (prov_funcs != NULL) {
		(void) prov_funcs->C_Finalize(NULL);
	}
	if (dldesc != NULL) {
		(void) dlclose(dldesc);
	}
	if (fullpath != NULL) {
		free(fullpath);
		fullpath = NULL;
	}
	if (prov_slots != NULL) {
		free(prov_slots);
		prov_slots = NULL;
	}

	return (rv);
}
Exemple #18
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);
}
Exemple #19
0
/* saslauthd-authenticated login */
static int saslauthd_verify_password(const char *saslauthd_path,
                                     const char *userid,
                                     const char *passwd,
                                     const char *service,
                                     const char *user_realm)
{
    char response[1024];
    char query[8192];
    char *query_end = query;
    int s;
    struct sockaddr_un srvaddr;
    int r;
    unsigned short count;
    char pwpath[sizeof(srvaddr.sun_path)];
#ifdef USE_DOORS
    door_arg_t arg;
#endif

    if(!service) service = "imap";
    if(!user_realm) user_realm = "";
    if(!userid || !passwd) return -1;

    if (saslauthd_path) {
        strncpy(pwpath, saslauthd_path, sizeof(pwpath));
    } else {
        if (strlen(PATH_SASLAUTHD_RUNDIR) + 4 + 1 > sizeof(pwpath))
            return -1;

        strcpy(pwpath, PATH_SASLAUTHD_RUNDIR);
        strcat(pwpath, "/mux");
    }

    /*
     * build request of the form:
     *
     * count authid count password count service count realm
     */
    {
        unsigned short u_len, p_len, s_len, r_len;

        u_len = htons(strlen(userid));
        p_len = htons(strlen(passwd));
        s_len = htons(strlen(service));
        r_len = htons((user_realm ? strlen(user_realm) : 0));

        memcpy(query_end, &u_len, sizeof(unsigned short));
        query_end += sizeof(unsigned short);
        while (*userid) *query_end++ = *userid++;

        memcpy(query_end, &p_len, sizeof(unsigned short));
        query_end += sizeof(unsigned short);
        while (*passwd) *query_end++ = *passwd++;

        memcpy(query_end, &s_len, sizeof(unsigned short));
        query_end += sizeof(unsigned short);
        while (*service) *query_end++ = *service++;

        memcpy(query_end, &r_len, sizeof(unsigned short));
        query_end += sizeof(unsigned short);
        if (user_realm) while (*user_realm) *query_end++ = *user_realm++;
    }

#ifdef USE_DOORS
    s = open(pwpath, O_RDONLY);
    if (s < 0) {
        perror("open");
        return -1;
    }

    arg.data_ptr = query;
    arg.data_size = query_end - query;
    arg.desc_ptr = NULL;
    arg.desc_num = 0;
    arg.rbuf = response;
    arg.rsize = sizeof(response);

    if(door_call(s, &arg) != 0) {
        printf("NO \"door_call failed\"\n");
        return -1;
    }

    assert(arg.data_size < sizeof(response));
    response[arg.data_size] = '\0';

    close(s);
#else
    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s == -1) {
        perror("socket() ");
        return -1;
    }

    memset((char *)&srvaddr, 0, sizeof(srvaddr));
    srvaddr.sun_family = AF_UNIX;
    strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path));

    r = connect(s, (struct sockaddr *) &srvaddr, sizeof(srvaddr));
    if (r == -1) {
        perror("connect() ");
        return -1;
    }

    {
        struct iovec iov[8];

        iov[0].iov_len = query_end - query;
        iov[0].iov_base = query;

        if (retry_writev(s, iov, 1) == -1) {
            fprintf(stderr,"write failed\n");
            return -1;
        }
    }

    /*
     * read response of the form:
     *
     * count result
     */
    if (retry_read(s, &count, sizeof(count)) < (int) sizeof(count)) {
        fprintf(stderr,"size read failed\n");
        return -1;
    }

    count = ntohs(count);
    if (count < 2) { /* MUST have at least "OK" or "NO" */
        close(s);
        fprintf(stderr,"bad response from saslauthd\n");
        return -1;
    }

    count = (int)sizeof(response) < count ? sizeof(response) : count;
    if (retry_read(s, response, count) < count) {
        close(s);
        fprintf(stderr,"read failed\n");
        return -1;
    }
    response[count] = '\0';

    close(s);
#endif /* USE_DOORS */

    if (!strncmp(response, "OK", 2)) {
        printf("OK \"Success.\"\n");
        return 0;
    }

    printf("NO \"authentication failed\"\n");
    return -1;
}
Exemple #20
0
/*
 * Class:     sun_tools_attach_VirtualMachineImpl
 * Method:    enqueue
 * Signature: (JILjava/lang/String;[Ljava/lang/Object;)V
 */
JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue
  (JNIEnv *env, jclass cls, jint fd, jstring cmd, jobjectArray args)
{
    jint arg_count, i;
    size_t size;
    jboolean isCopy;
    door_arg_t door_args;
    char res_buffer[128];
    jint result = -1;
    int rc;
    const char* cstr;
    char* buf;

    /*
     * First we get the command string and create the start of the
     * argument string to send to the target VM:
     * <ver>\0<cmd>\0
     */
    cstr = JNU_GetStringPlatformChars(env, cmd, &isCopy);
    if (cstr == NULL) {
        return -1;              /* pending exception */
    }
    size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
    buf = (char*)malloc(size);
    if (buf != NULL) {
        char* pos = buf;
        strcpy(buf, PROTOCOL_VERSION);
        pos += strlen(PROTOCOL_VERSION)+1;
        strcpy(pos, cstr);
    }
    if (isCopy) {
        JNU_ReleaseStringPlatformChars(env, cmd, cstr);
    }
    if (buf == NULL) {
        JNU_ThrowOutOfMemoryError(env, "malloc failed");
        return -1;
    }

    /*
     * Next we iterate over the arguments and extend the buffer
     * to include them.
     */
    arg_count = (*env)->GetArrayLength(env, args);

    for (i=0; i<arg_count; i++) {
        jobject obj = (*env)->GetObjectArrayElement(env, args, i);
        if (obj != NULL) {
            cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
            if (cstr != NULL) {
                size_t len = strlen(cstr);
                char* newbuf = (char*)realloc(buf, size+len+1);
                if (newbuf != NULL) {
                    buf = newbuf;
                    strcpy(buf+size, cstr);
                    size += len+1;
                }
                if (isCopy) {
                    JNU_ReleaseStringPlatformChars(env, obj, cstr);
                }
                if (newbuf == NULL) {
                    free(buf);
                    JNU_ThrowOutOfMemoryError(env, "realloc failed");
                    return -1;
                }
            }
        }
        if ((*env)->ExceptionOccurred(env)) {
            free(buf);
            return -1;
        }
    }

    /*
     * The arguments to the door function are in 'buf' so we now
     * do the door call
     */
    door_args.data_ptr = buf;
    door_args.data_size = size;
    door_args.desc_ptr = NULL;
    door_args.desc_num = 0;
    door_args.rbuf = (char*)&res_buffer;
    door_args.rsize = sizeof(res_buffer);

    RESTARTABLE(door_call(fd, &door_args), rc);

    /*
     * door_call failed
     */
    if (rc == -1) {
        JNU_ThrowIOExceptionWithLastError(env, "door_call");
    } else {
        /*
         * door_call succeeded but the call didn't return the expected jint.
         */
        if (door_args.data_size < sizeof(jint)) {
            JNU_ThrowIOException(env, "Enqueue error - reason unknown as result is truncated!");
        } else {
            jint* res = (jint*)(door_args.data_ptr);
            if (*res != JNI_OK) {
                const char* msg = translate_error(*res);
                char buf[255];
                if (msg == NULL) {
                    sprintf(buf, "Unable to enqueue command to target VM: %d", *res);
                } else {
                    sprintf(buf, "Unable to enqueue command to target VM: %s", msg);
                }
                JNU_ThrowIOException(env, buf);
            } else {
                /*
                 * The door call should return a file descriptor to one end of
                 * a socket pair
                 */
                if ((door_args.desc_ptr != NULL) &&
                    (door_args.desc_num == 1) &&
                    (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
                    result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
                } else {
                    JNU_ThrowIOException(env, "Reply from enqueue missing descriptor!");
                }
            }
        }
    }

    free(buf);
    return result;
}
Exemple #21
0
/*
 * Convert a gid into its utf-8 string representation.
 */
int
nfs_idmap_gid_str(gid_t gid,		/* gid to map */
		utf8string *g8s)	/* resulting utf-8 string for gid */
{
	struct mapid_arg maparg;
	struct mapid_res mapres;
	struct mapid_res *mapresp = &mapres;
	struct mapid_res *resp = mapresp;
	door_arg_t	door_args;
	int		error = 0;
	int		doorfd;
	static int	msg_done = 0;

	if (gid == GID_NOBODY) {
		g8s->utf8string_len = strlen("nobody");
		g8s->utf8string_val = nobody_str;
		goto g2s_done;

	}

	/*
	 * Daemon call...
	 */
	maparg.cmd = NFSMAPID_GID_STR;
	maparg.u_arg.gid = gid;

	door_args.data_ptr = (char *)&maparg;
	door_args.data_size = sizeof (struct mapid_arg);
	door_args.desc_ptr = NULL;
	door_args.desc_num = 0;
	door_args.rbuf = (char *)mapresp;
	door_args.rsize = sizeof (struct mapid_res);

	if ((doorfd = nfs_idmap_doorget()) == -1) {
		if (!msg_done) {
			fprintf(stderr, "nfs_idmap_uid_str: Can't "
				"communicate with mapping daemon nfsmapid\n");
			msg_done = 1;
		}
		error = ECOMM;
		goto g2s_done;
	}

	if (door_call(doorfd, &door_args) == -1) {
		perror("door_call failed");
		error = EINVAL;
		goto g2s_done;
	}

	resp = (struct mapid_res *)door_args.rbuf;
	if (resp->status != NFSMAPID_OK) {
		error = resp->status;
		goto g2s_done;
	}

	if (resp->u_res.len != strlen(resp->str)) {
		(void) fprintf(stderr, "Incorrect length %d expected %d\n",
			resp->u_res.len, strlen(resp->str));
		error = NFSMAPID_INVALID;
		goto g2s_done;
	}
	g8s->utf8string_len = resp->u_res.len;
	bcopy(resp->str, g8s->utf8string_val, g8s->utf8string_len);

g2s_done:
	if (resp != mapresp)
		munmap(door_args.rbuf, door_args.rsize);
	return (error);
}
Exemple #22
0
/*
 * Convert a group utf-8 string identifier into its local gid.
 */
int
nfs_idmap_str_gid(utf8string *u8s, gid_t *gid)
{
	struct mapid_arg *mapargp;
	struct mapid_res mapres;
	struct mapid_res *mapresp = &mapres;
	struct mapid_res *resp = mapresp;
	door_arg_t	door_args;
	int		doorfd;
	int		error = 0;
	static int	msg_done = 0;

	if (!u8s || !u8s->utf8string_val || !u8s->utf8string_len ||
		(u8s->utf8string_val[0] == '\0')) {
		error = EINVAL;
		goto s2g_done;
	}

	if (bcmp(u8s->utf8string_val, "nobody", 6) == 0) {
		/*
		 * If "nobody", just short circuit and bail
		 */
		*gid = GID_NOBODY;
		goto s2g_done;

	}

	if ((mapargp = malloc(MAPID_ARG_LEN(u8s->utf8string_len))) == NULL) {
		(void) fprintf(stderr, "Unable to malloc %d bytes\n",
				MAPID_ARG_LEN(u8s->utf8string_len));
		error = ENOMEM;
		goto s2g_done;
	}
	mapargp->cmd = NFSMAPID_STR_GID;
	mapargp->u_arg.len = u8s->utf8string_len;
	(void) bcopy(u8s->utf8string_val, mapargp->str, mapargp->u_arg.len);
	mapargp->str[mapargp->u_arg.len] = '\0';

	door_args.data_ptr = (char *)mapargp;
	door_args.data_size = MAPID_ARG_LEN(mapargp->u_arg.len);
	door_args.desc_ptr = NULL;
	door_args.desc_num = 0;
	door_args.rbuf = (char *)mapresp;
	door_args.rsize = sizeof (struct mapid_res);

	/*
	 * call to the nfsmapid daemon
	 */
	if ((doorfd = nfs_idmap_doorget()) == -1) {
		if (!msg_done) {
			fprintf(stderr, "nfs_idmap_str_uid: Can't communicate"
				" with mapping daemon nfsmapid\n");
			msg_done = 1;
		}
		error = ECOMM;
		free(mapargp);
		goto s2g_done;
	}

	if (door_call(doorfd, &door_args) == -1) {
		perror("door_call failed");
		error = EINVAL;
		free(mapargp);
		goto s2g_done;
	}

	free(mapargp);

	resp = (struct mapid_res *)door_args.rbuf;
	switch (resp->status) {
	case NFSMAPID_OK:
		*gid = resp->u_res.gid;
		break;

	case NFSMAPID_NUMSTR:
		*gid = resp->u_res.gid;
		error = resp->status;
		goto out;

	default:
	case NFSMAPID_UNMAPPABLE:
	case NFSMAPID_INVALID:
	case NFSMAPID_INTERNAL:
	case NFSMAPID_BADDOMAIN:
	case NFSMAPID_BADID:
	case NFSMAPID_NOTFOUND:
		error = resp->status;
		goto s2g_done;
	}

s2g_done:
	if (error)
		*gid = GID_NOBODY;
out:
	if (resp != mapresp)
		munmap(door_args.rbuf, door_args.rsize);
	return (error);
}
Exemple #23
0
/*
 * Get event service from a named door.
 *
 * This is similar to sysevent_post_event(), except that it deals with
 * the "return buffer problem":
 *	Typically, the door service places the return buffer on the stack
 *	when calling door_return(). This places an artificial limit on the
 *	size of the return buffer.
 * This problem is solved by placing large buffers on the heap, referenced
 * through door_info. When client detects a large buffer, it will make a
 * second door_call() to free the buffer. The client and the server agrees
 * on a size, which is defined as BUF_THRESHOLD.
 *
 * Returns -1 if message not delivered. With errno set to cause of error.
 * Returns 0 for success with the results returned in posting buffer.
 */
int
get_event_service(char *door_name, void *data, size_t datalen,
    void **result, size_t *rlen)
{
	int service_door, error;
	door_arg_t door_arg;

	/*
	 * Open the service door
	 */
	if ((service_door = open(door_name, O_RDONLY, 0)) == -1) {
		errno = ESRCH;
		return (-1);
	}

retry1:
	door_arg.rbuf = NULL;	/* doorfs will provide return buf */
	door_arg.rsize = 0;
	door_arg.data_ptr = data;
	door_arg.data_size = datalen;
	door_arg.desc_ptr = NULL;
	door_arg.desc_num = 0;

	/*
	 * Make door call
	 * EAGAIN is returned when the door server is temporarily
	 * out of threads to service the door call. So retry.
	 */
	if ((error = door_call(service_door, &door_arg)) == -1 &&
	    errno == EAGAIN) {
		(void) sleep(1);
		goto retry1;
	}

	if ((error == 0) && result) {

		uint64_t seq_num = 0;

		*result = NULL;
		*rlen = 0;
		if (door_arg.rbuf == NULL || door_arg.rsize == 0) {
			dprint("bad return from door call\n");
			(void) close(service_door);
			errno = EFAULT;
			return (-1);
		}

		(void) nvlist_unpack(door_arg.rbuf, door_arg.rsize,
		    (nvlist_t **)result, 0);
		(void) munmap(door_arg.rbuf, door_arg.rsize);

		/*
		 * If requiring a buf free, make another door call.  There is
		 * no need to call munmap() after this door call, though.
		 */
		if (lookup_seq_num((nvlist_t *)*result, &seq_num) == 0) {
retry2:
			door_arg.rbuf = NULL;
			door_arg.rsize = 0;
			door_arg.data_ptr = (char *)&seq_num;
			door_arg.data_size = sizeof (seq_num);
			door_arg.desc_ptr = NULL;
			door_arg.desc_num = 0;
			if (door_call(service_door, &door_arg) == -1) {
				if (errno == EAGAIN) {
					(void) sleep(1);
					goto retry2;
				}
				dprint("fail to free event buf in server\n");
			}
		}
	}

	(void) close(service_door);
	return (error);
}
Exemple #24
0
/*
 * setup_mgmt_door -- Create a door portal for management application requests
 *
 * First check to see if another daemon is already running by attempting
 * to send an empty request to the door. If successful it means this
 * daemon should exit.
 */
int
setup_mgmt_door(msg_queue_t *sys_q)
{
	int fd, door_id;
	struct stat buf;
	door_arg_t darg;

	isnslog(LOG_DEBUG, "setup_mgmt_door", "entered");
	/* check if a door is already running. */
	if ((fd = open(ISNS_DOOR_NAME, 0)) >= 0) {
		darg.data_ptr = "<?xml version='1.0' encoding='UTF-8'?>"
				"<isnsRequest><get><isnsObject>"
				"<DiscoveryDomain name=\"default\">"
				"</DiscoveryDomain></isnsObject></get>"
				"</isnsRequest>";
		darg.data_size = xmlStrlen((xmlChar *)darg.data_ptr) + 1;
		darg.desc_ptr = NULL;
		darg.desc_num = 0;
		darg.rbuf = NULL;
		darg.rsize = 0;

		if (door_call(fd, &darg) == 0) {
			/* door already running. */
			(void) close(fd);
			isnslog(LOG_DEBUG, "setup_mgmt_door",
			    "management door is already runninng.");
			if (darg.rsize > darg.data_size) {
			    (void) munmap(darg.rbuf, darg.rsize);
			}
			door_created = B_FALSE;
			return (0);
		}
		(void) close(fd);
	}

	if ((door_id = door_create(door_server, (void *)sys_q, 0)) < 0) {
		isnslog(LOG_DEBUG, "setup_mgmt_door",
			"Failed to create managment door");
		exit(1);
	}

	if (stat(ISNS_DOOR_NAME, &buf) < 0) {
	    if ((fd = creat(ISNS_DOOR_NAME, 0666)) < 0) {
		isnslog(LOG_DEBUG, "setup_mgmt_door",
		    "open failed on %s errno = %d", ISNS_DOOR_NAME, errno);
		exit(1);
	    }
	    (void) close(fd);
	}

	/* make sure the file permission set to general access. */
	(void) chmod(ISNS_DOOR_NAME, 0666);
	(void) fdetach(ISNS_DOOR_NAME);

	if (fattach(door_id, ISNS_DOOR_NAME) < 0) {
		syslog(LOG_DEBUG, "setup_mgmt_door",
		    "fattach failed on %s errno=%d",
		    ISNS_DOOR_NAME, errno);
		return (-1);
	}

	door_created = B_TRUE;

	return (0);
}
Exemple #25
0
static int
zp_register_socket(int sock, int *fdp)
{
	int doorfd;
	int *res;
	int cmd[2];
	door_arg_t dparam;
	door_desc_t doord;
	zoneid_t zid;

	if ((doorfd = open(ZP_DOOR_PATH, O_RDONLY)) < 0) {
		perror("open");
		return (-1);
	}

	zid = getzoneid();

	cmd[0] = ZP_CMD_NEW_LISTENER;
	cmd[1] = zid;

	doord.d_attributes = DOOR_DESCRIPTOR;
	doord.d_data.d_desc.d_descriptor = sock;

	dparam.data_ptr = (char *)cmd;
	dparam.data_size = sizeof (cmd);
	dparam.desc_ptr = (door_desc_t *)&doord;
	dparam.desc_num = 1;
	dparam.rbuf = NULL;
	dparam.rsize = 0;

	if (door_call(doorfd, &dparam) < 0) {
		perror("door_call");
		(void) close(doorfd);
		return (-1);
	}

	(void) close(doorfd);
	/* LINTED */
	res = (int *)dparam.data_ptr;

	if (res[1] != ZP_STATUS_OK) {
		zp_perror(res[1]);
		return (-1);
	}

	/* Caller should have passed us a pipe fd */
	if (dparam.desc_num > 1) {
		close_door_descs(dparam.desc_ptr + 1, dparam.desc_num - 1);
	}

	if (dparam.desc_num > 0) {
		if (fdp) {
			*fdp = dparam.desc_ptr->d_data.d_desc.d_descriptor;
		} else {
			(void) close(
			    dparam.desc_ptr->d_data.d_desc.d_descriptor);
		}
	} else {
		(void) fprintf(stderr, "Daemon didn't return pipefd\n");
		return (-1);
	}

	return (0);
}