#include "src/include/pmix_config.h"
#include "src/include/pmix_socket_errno.h"
#include "src/include/pmix_stdint.h"
#include "include/pmix.h"
#include "pmix_common.h"
#include "include/pmix_server.h"
#include "src/mca/bfrops/bfrops.h"
#include "src/mca/psec/psec.h"
#include "src/mca/ptl/ptl.h"
#include "src/threads/pmix_threads.h"
#include "src/util/pmix_argv.h"
#include "src/util/pmix_error.h"
#include "src/util/pmix_output.h"
#include "src/client/pmix_client_ops.h"
#include "src/include/pmix_globals.h"
#include "src/server/pmix_server_ops.h"
static void getcbfunc(struct pmix_peer_t *peer, pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata)
{
pmix_query_caddy_t *cd = (pmix_query_caddy_t *) cbdata;
pmix_status_t rc, status = PMIX_ERR_UNPACK_FAILURE;
int cnt;
pmix_byte_object_t cred;
pmix_info_t *info = NULL;
size_t ninfo = 0;
PMIX_HIDE_UNUSED_PARAMS(hdr);
pmix_output_verbose(2, pmix_globals.debug_output,
"pmix:security cback from server with %d bytes", (int) buf->bytes_used);
if (PMIX_BUFFER_IS_EMPTY(buf)) {
if (NULL != cd->credcbfunc) {
cd->credcbfunc(PMIX_ERR_COMM_FAILURE, NULL, NULL, 0, cd->cbdata);
}
PMIX_RELEASE(cd);
return;
}
PMIX_BYTE_OBJECT_CONSTRUCT(&cred);
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &status, &cnt, PMIX_STATUS);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
if (PMIX_SUCCESS != status) {
goto complete;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &cred, &cnt, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &ninfo, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
if (0 < ninfo) {
PMIX_INFO_CREATE(info, ninfo);
cnt = ninfo;
PMIX_BFROPS_UNPACK(rc, peer, buf, info, &cnt, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
}
complete:
pmix_output_verbose(2, pmix_globals.debug_output, "pmix:security cback from server releasing");
if (NULL != cd->credcbfunc) {
cd->credcbfunc(status, &cred, info, ninfo, cd->cbdata);
}
PMIX_BYTE_OBJECT_DESTRUCT(&cred);
if (NULL != info) {
PMIX_INFO_FREE(info, ninfo);
}
PMIX_RELEASE(cd);
}
static void mycdcb(pmix_status_t status, pmix_byte_object_t *credential,
pmix_info_t info[], size_t ninfo, void *cbdata)
{
pmix_query_caddy_t *cb = (pmix_query_caddy_t *) cbdata;
PMIX_HIDE_UNUSED_PARAMS(info, ninfo);
PMIX_ACQUIRE_OBJECT(cb);
cb->status = status;
if (PMIX_SUCCESS == status && NULL != credential) {
cb->bo.bytes = malloc(credential->size);
memcpy(cb->bo.bytes, credential->bytes, credential->size);
cb->bo.size = credential->size;
}
PMIX_WAKEUP_THREAD(&cb->lock);
}
PMIX_EXPORT pmix_status_t PMIx_Get_credential(const pmix_info_t info[], size_t ninfo,
pmix_byte_object_t *credential)
{
pmix_query_caddy_t cb;
pmix_status_t rc;
PMIX_CONSTRUCT(&cb, pmix_query_caddy_t);
rc = PMIx_Get_credential_nb(info, ninfo, mycdcb, &cb);
if (PMIX_SUCCESS == rc) {
PMIX_WAIT_THREAD(&cb.lock);
rc = cb.status;
if (NULL != cb.bo.bytes) {
credential->bytes = malloc(cb.bo.size);
memcpy(credential->bytes, cb.bo.bytes, cb.bo.size);
credential->size = cb.bo.size;
}
}
PMIX_DESTRUCT(&cb);
return rc;
}
PMIX_EXPORT pmix_status_t PMIx_Get_credential_nb(const pmix_info_t info[], size_t ninfo,
pmix_credential_cbfunc_t cbfunc, void *cbdata)
{
pmix_buffer_t *msg;
pmix_cmd_t cmd = PMIX_GET_CREDENTIAL_CMD;
pmix_status_t rc;
pmix_query_caddy_t *cb;
pmix_byte_object_t cred;
pmix_info_t *results = NULL;
size_t nresults = 0;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
pmix_output_verbose(2, pmix_globals.debug_output, "pmix: Get_credential called with %d info",
(int) ninfo);
if (pmix_globals.init_cntr <= 0) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_INIT;
}
if (PMIX_PEER_IS_SERVER(pmix_globals.mypeer) && !PMIX_PEER_IS_LAUNCHER(pmix_globals.mypeer)) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
if (NULL == pmix_host_server.get_credential) {
PMIX_BYTE_OBJECT_CONSTRUCT(&cred);
PMIX_PSEC_CREATE_CRED(rc, pmix_globals.mypeer, info, ninfo, &results, &nresults, &cred);
if (PMIX_SUCCESS == rc) {
if (NULL != cbfunc) {
cbfunc(PMIX_SUCCESS, &cred, results, nresults, cbdata);
if (NULL != results) {
PMIX_INFO_FREE(results, nresults);
}
PMIX_BYTE_OBJECT_DESTRUCT(&cred);
}
}
return rc;
}
pmix_output_verbose(2, pmix_globals.debug_output, "pmix:get_credential handed to RM");
rc = pmix_host_server.get_credential(&pmix_globals.myid, info, ninfo, cbfunc, cbdata);
return rc;
}
if (!pmix_globals.connected) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
PMIX_BYTE_OBJECT_CONSTRUCT(&cred);
PMIX_PSEC_CREATE_CRED(rc, pmix_globals.mypeer, info, ninfo, &results, &nresults, &cred);
if (PMIX_SUCCESS == rc) {
if (NULL != cbfunc) {
cbfunc(PMIX_SUCCESS, &cred, results, nresults, cbdata);
if (NULL != results) {
PMIX_INFO_FREE(results, nresults);
}
PMIX_BYTE_OBJECT_DESTRUCT(&cred);
}
}
return rc;
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
msg = PMIX_NEW(pmix_buffer_t);
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, &cmd, 1, PMIX_COMMAND);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, &ninfo, 1, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
if (0 < ninfo) {
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, info, ninfo, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
}
cb = PMIX_NEW(pmix_query_caddy_t);
cb->credcbfunc = cbfunc;
cb->cbdata = cbdata;
PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver, msg, getcbfunc, (void *) cb);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(msg);
PMIX_RELEASE(cb);
}
return rc;
}
static void valid_cbfunc(struct pmix_peer_t *peer, pmix_ptl_hdr_t *hdr,
pmix_buffer_t *buf, void *cbdata)
{
pmix_query_caddy_t *cd = (pmix_query_caddy_t *) cbdata;
pmix_status_t rc, status = PMIX_ERR_UNPACK_FAILURE;
int cnt;
pmix_info_t *info = NULL;
size_t ninfo = 0;
PMIX_HIDE_UNUSED_PARAMS(hdr);
pmix_output_verbose(2, pmix_globals.debug_output,
"pmix:security cback from server with %d bytes", (int) buf->bytes_used);
if (PMIX_BUFFER_IS_EMPTY(buf)) {
if (NULL != cd->validcbfunc) {
cd->validcbfunc(PMIX_ERR_COMM_FAILURE, NULL, 0, cd->cbdata);
}
PMIX_RELEASE(cd);
return;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &status, &cnt, PMIX_STATUS);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
if (PMIX_SUCCESS != status) {
goto complete;
}
cnt = 1;
PMIX_BFROPS_UNPACK(rc, peer, buf, &ninfo, &cnt, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
if (0 < ninfo) {
PMIX_INFO_CREATE(info, ninfo);
cnt = ninfo;
PMIX_BFROPS_UNPACK(rc, peer, buf, info, &cnt, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
goto complete;
}
}
complete:
pmix_output_verbose(2, pmix_globals.debug_output, "pmix:security cback from server releasing");
if (NULL != cd->validcbfunc) {
cd->validcbfunc(status, info, ninfo, cd->cbdata);
}
if (NULL != info) {
PMIX_INFO_FREE(info, ninfo);
}
PMIX_RELEASE(cd);
}
static void myvalcb(pmix_status_t status, pmix_info_t info[], size_t ninfo, void *cbdata)
{
pmix_query_caddy_t *cb = (pmix_query_caddy_t *) cbdata;
size_t n;
PMIX_ACQUIRE_OBJECT(cb);
cb->status = status;
if (PMIX_SUCCESS == status && NULL != info) {
cb->ninfo = ninfo;
PMIX_INFO_CREATE(cb->info, cb->ninfo);
for (n = 0; n < ninfo; n++) {
PMIX_INFO_XFER(&cb->info[n], &info[n]);
}
}
PMIX_WAKEUP_THREAD(&cb->lock);
}
PMIX_EXPORT pmix_status_t PMIx_Validate_credential(const pmix_byte_object_t *cred,
const pmix_info_t directives[], size_t ndirs,
pmix_info_t *results[], size_t *nresults)
{
pmix_query_caddy_t cb;
pmix_status_t rc;
PMIX_CONSTRUCT(&cb, pmix_query_caddy_t);
rc = PMIx_Validate_credential_nb(cred, directives, ndirs, myvalcb, &cb);
if (PMIX_SUCCESS == rc) {
PMIX_WAIT_THREAD(&cb.lock);
rc = cb.status;
if (NULL != cb.info) {
*results = cb.info;
*nresults = cb.ninfo;
cb.info = NULL;
cb.ninfo = 0;
}
}
PMIX_DESTRUCT(&cb);
return rc;
}
PMIX_EXPORT pmix_status_t PMIx_Validate_credential_nb(const pmix_byte_object_t *cred,
const pmix_info_t directives[], size_t ndirs,
pmix_validation_cbfunc_t cbfunc, void *cbdata)
{
pmix_buffer_t *msg;
pmix_cmd_t cmd = PMIX_VALIDATE_CRED_CMD;
pmix_status_t rc;
pmix_query_caddy_t *cb;
pmix_info_t *results = NULL;
size_t nresults = 0;
PMIX_ACQUIRE_THREAD(&pmix_global_lock);
pmix_output_verbose(2, pmix_globals.debug_output, "pmix: monitor called");
if (pmix_globals.init_cntr <= 0) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
return PMIX_ERR_INIT;
}
if (PMIX_PEER_IS_SERVER(pmix_globals.mypeer) && !PMIX_PEER_IS_LAUNCHER(pmix_globals.mypeer)) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
if (NULL == pmix_host_server.validate_credential) {
PMIX_PSEC_VALIDATE_CRED(rc, pmix_globals.mypeer, directives, ndirs, &results, &nresults,
cred);
if (PMIX_SUCCESS == rc) {
if (NULL != cbfunc) {
cbfunc(PMIX_SUCCESS, results, nresults, cbdata);
if (NULL != results) {
PMIX_INFO_FREE(results, nresults);
}
}
}
return rc;
}
pmix_output_verbose(2, pmix_globals.debug_output, "pmix:get_credential handed to RM");
rc = pmix_host_server.validate_credential(&pmix_globals.myid, cred, directives, ndirs,
cbfunc, cbdata);
return rc;
}
if (!pmix_globals.connected) {
PMIX_RELEASE_THREAD(&pmix_global_lock);
PMIX_PSEC_VALIDATE_CRED(rc, pmix_globals.mypeer, directives, ndirs, &results, &nresults,
cred);
if (PMIX_SUCCESS == rc) {
if (NULL != cbfunc) {
cbfunc(PMIX_SUCCESS, results, nresults, cbdata);
if (NULL != results) {
PMIX_INFO_FREE(results, nresults);
}
}
}
return rc;
}
PMIX_RELEASE_THREAD(&pmix_global_lock);
msg = PMIX_NEW(pmix_buffer_t);
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, &cmd, 1, PMIX_COMMAND);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, cred, 1, PMIX_BYTE_OBJECT);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, &ndirs, 1, PMIX_SIZE);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
if (0 < ndirs) {
PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver, msg, directives, ndirs, PMIX_INFO);
if (PMIX_SUCCESS != rc) {
PMIX_ERROR_LOG(rc);
PMIX_RELEASE(msg);
return rc;
}
}
cb = PMIX_NEW(pmix_query_caddy_t);
cb->validcbfunc = cbfunc;
cb->cbdata = cbdata;
PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver, msg, valid_cbfunc, (void *) cb);
if (PMIX_SUCCESS != rc) {
PMIX_RELEASE(msg);
PMIX_RELEASE(cb);
}
return rc;
}