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); }
/* * 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"); }
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); }
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 *) # 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); }
/* * "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); }
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); } }
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); }
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); }
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); }
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 }
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; }
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); }
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); } }
/* 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, ¶ms) < 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; }
/* * 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); }
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, ¶m); 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); }
/* 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; }
/* * 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; }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
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); }