static pmix_status_t send_connect_ack(int sd) { char *msg; pmix_usock_hdr_t hdr; size_t sdsize=0, csize=0; pmix_byte_object_t cred; pmix_status_t rc; char *sec, *bfrops, *gds; pmix_bfrop_buffer_type_t bftype; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix: SEND CONNECT ACK"); /* setup the header */ memset(&hdr, 0, sizeof(pmix_usock_hdr_t)); hdr.pindex = -1; hdr.tag = UINT32_MAX; /* reserve space for the nspace and rank info */ sdsize = strlen(pmix_globals.myid.nspace) + 1 + sizeof(int); /* get a credential, if the security system provides one. Not * every SPC will do so, thus we must first check */ PMIX_BYTE_OBJECT_CONSTRUCT(&cred); PMIX_PSEC_CREATE_CRED(rc, pmix_globals.mypeer, NULL, 0, NULL, 0, &cred); if (PMIX_SUCCESS != rc) { return rc; } /* add the name of our active sec module - we selected it * in pmix_client.c prior to entering here */ sec = pmix_globals.mypeer->nptr->compat.psec->name; /* add our active bfrops module name */ bfrops = pmix_globals.mypeer->nptr->compat.bfrops->version; /* and the type of buffer we are using */ bftype = pmix_globals.mypeer->nptr->compat.type; /* add our active gds module for working with the server */ gds = (char*)pmix_client_globals.myserver->nptr->compat.gds->name; /* set the number of bytes to be read beyond the header */ hdr.nbytes = sdsize + (strlen(PMIX_VERSION) + 1) + \ (sizeof(size_t) + cred.size) + \ (strlen(sec) + 1) + \ (strlen(bfrops) + 1) + sizeof(bftype) + \ (strlen(gds) + 1); // must NULL terminate the strings! /* create a space for our message */ sdsize = (sizeof(hdr) + hdr.nbytes); if (NULL == (msg = (char*)malloc(sdsize))) { PMIX_BYTE_OBJECT_DESTRUCT(&cred); return PMIX_ERR_OUT_OF_RESOURCE; } memset(msg, 0, sdsize); /* load the message */ csize=0; memcpy(msg, &hdr, sizeof(pmix_usock_hdr_t)); csize += sizeof(pmix_usock_hdr_t); /* pass our nspace */ memcpy(msg+csize, pmix_globals.myid.nspace, strlen(pmix_globals.myid.nspace)); csize += strlen(pmix_globals.myid.nspace)+1; /* pass our rank */ memcpy(msg+csize, &pmix_globals.myid.rank, sizeof(int)); csize += sizeof(int); /* pass our version string */ memcpy(msg+csize, PMIX_VERSION, strlen(PMIX_VERSION)); csize += strlen(PMIX_VERSION)+1; /* pass the size of the credential */ memcpy(msg+csize, &cred.size, sizeof(size_t)); csize += sizeof(size_t); if (0 < cred.size) { memcpy(msg+csize, cred.bytes, cred.size); csize += cred.size; } PMIX_BYTE_OBJECT_DESTRUCT(&cred); /* pass our active sec module */ memcpy(msg+csize, sec, strlen(sec)); csize += strlen(sec)+1; /* provide our active bfrops module */ memcpy(msg+csize, bfrops, strlen(bfrops)); csize += strlen(bfrops)+1; /* provide the bfrops type */ memcpy(msg+csize, &bftype, sizeof(bftype)); csize += sizeof(bftype); /* provide the gds module */ memcpy(msg+csize, gds, strlen(gds)); /* send the entire msg across */ if (PMIX_SUCCESS != pmix_ptl_base_send_blocking(sd, msg, sdsize)) { free(msg); return PMIX_ERR_UNREACH; } free(msg); return PMIX_SUCCESS; }
static pmix_status_t create_cred(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, pmix_byte_object_t *cred) { pmix_peer_t *pr = (pmix_peer_t*)peer; char **types; size_t n, m; bool takeus; uid_t euid; gid_t egid; char *tmp, *ptr; /* ensure initialization */ PMIX_BYTE_OBJECT_CONSTRUCT(cred); /* we may be responding to a local request for a credential, so * see if they specified a mechanism */ if (NULL != directives && 0 < ndirs) { /* cycle across the provided info and see if they specified * any desired credential types */ takeus = true; for (n=0; n < ndirs; n++) { if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) { /* see if we are included */ types = pmix_argv_split(directives[n].value.data.string, ','); /* start by assuming they don't want us */ takeus = false; for (m=0; NULL != types[m]; m++) { if (0 == strcmp(types[m], "native")) { /* it's us! */ takeus = true; break; } } pmix_argv_free(types); break; } } if (!takeus) { PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; } } if (PMIX_PROTOCOL_V1 == pr->protocol) { /* usock protocol - nothing to do */ goto complete; } else if (PMIX_PROTOCOL_V2 == pr->protocol) { /* tcp protocol - need to provide our effective * uid and gid for validation on remote end */ tmp = (char*)malloc(sizeof(uid_t) + sizeof(gid_t)); if (NULL == tmp) { return PMIX_ERR_NOMEM; } euid = geteuid(); memcpy(tmp, &euid, sizeof(uid_t)); ptr = tmp + sizeof(uid_t); egid = getegid(); memcpy(ptr, &egid, sizeof(gid_t)); cred->bytes = tmp; cred->size = sizeof(uid_t) + sizeof(gid_t); goto complete; } else { /* unrecognized protocol */ PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; } complete: if (NULL != info) { /* mark that this came from us */ PMIX_INFO_CREATE(*info, 1); if (NULL == *info) { return PMIX_ERR_NOMEM; } *ninfo = 1; PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "native", PMIX_STRING); } return PMIX_SUCCESS; }
static pmix_status_t send_connect_ack(int sd) { char *msg; pmix_ptl_hdr_t hdr; size_t sdsize=0, csize=0; pmix_byte_object_t cred; char *sec, *bfrops, *gds; pmix_bfrop_buffer_type_t bftype; pmix_status_t rc; uint8_t flag; uid_t euid; gid_t egid; uint32_t u32; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix:tcp SEND CONNECT ACK"); /* if we are a server, then we shouldn't be here */ if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) { return PMIX_ERR_NOT_SUPPORTED; } /* setup the header */ memset(&hdr, 0, sizeof(pmix_ptl_hdr_t)); hdr.pindex = -1; hdr.tag = UINT32_MAX; /* a security module was assigned to us during rte_init based * on a list of available security modules provided by our * local PMIx server, if known. Now use that module to * get a credential, if the security system provides one. Not * every psec module will do so, thus we must first check */ PMIX_BYTE_OBJECT_CONSTRUCT(&cred); PMIX_PSEC_CREATE_CRED(rc, pmix_globals.mypeer, NULL, 0, NULL, 0, &cred); if (PMIX_SUCCESS != rc) { pmix_output(0, "OUCH: %d", __LINE__); return rc; } /* allow space for a marker indicating client vs tool */ sdsize = 1; if (PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { flag = 0; /* reserve space for our nspace and rank info */ sdsize += strlen(pmix_globals.myid.nspace) + 1 + sizeof(int); } else { flag = 1; /* add space for our uid/gid for ACL purposes */ sdsize += 2*sizeof(uint32_t); } /* add the name of our active sec module - we selected it * in pmix_client.c prior to entering here */ sec = pmix_globals.mypeer->nptr->compat.psec->name; /* add our active bfrops module name */ bfrops = pmix_globals.mypeer->nptr->compat.bfrops->version; /* and the type of buffer we are using */ bftype = pmix_globals.mypeer->nptr->compat.type; /* add our active gds module for working with the server */ gds = (char*)pmix_client_globals.myserver->nptr->compat.gds->name; /* set the number of bytes to be read beyond the header */ hdr.nbytes = sdsize + strlen(PMIX_VERSION) + 1 + strlen(sec) + 1 \ + strlen(bfrops) + 1 + sizeof(bftype) \ + strlen(gds) + 1 + sizeof(uint32_t) + cred.size; // must NULL terminate the strings! /* create a space for our message */ sdsize = (sizeof(hdr) + hdr.nbytes); if (NULL == (msg = (char*)malloc(sdsize))) { PMIX_BYTE_OBJECT_DESTRUCT(&cred); free(sec); return PMIX_ERR_OUT_OF_RESOURCE; } memset(msg, 0, sdsize); /* load the message */ csize=0; memcpy(msg, &hdr, sizeof(pmix_ptl_hdr_t)); csize += sizeof(pmix_ptl_hdr_t); /* provide our active psec module */ memcpy(msg+csize, sec, strlen(sec)); csize += strlen(sec)+1; /* load the length of the credential - we put this in uint32_t * format as that is a fixed size, and convert to network * byte order for heterogeneity */ u32 = htonl((uint32_t)cred.size); memcpy(msg+csize, &u32, sizeof(uint32_t)); csize += sizeof(uint32_t); /* load the credential */ if (0 < u32) { memcpy(msg+csize, cred.bytes, cred.size); csize += cred.size; } PMIX_BYTE_OBJECT_DESTRUCT(&cred); /* load our process type - this is a single byte, * so no worry about heterogeneity here */ memcpy(msg+csize, &flag, 1); csize += 1; if (PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { /* if we are a client, provide our nspace/rank */ memcpy(msg+csize, pmix_globals.myid.nspace, strlen(pmix_globals.myid.nspace)); csize += strlen(pmix_globals.myid.nspace)+1; /* again, need to convert */ u32 = htonl((uint32_t)pmix_globals.myid.rank); memcpy(msg+csize, &u32, sizeof(uint32_t)); csize += sizeof(uint32_t); } else { /* if we are a tool, provide our uid/gid for ACL support - note * that we have to convert so we can handle heterogeneity */ euid = geteuid(); u32 = htonl(euid); memcpy(msg+csize, &u32, sizeof(uint32_t)); csize += sizeof(uint32_t); egid = getegid(); u32 = htonl(egid); memcpy(msg+csize, &u32, sizeof(uint32_t)); csize += sizeof(uint32_t); } /* provide our version */ memcpy(msg+csize, PMIX_VERSION, strlen(PMIX_VERSION)); csize += strlen(PMIX_VERSION)+1; /* provide our active bfrops module */ memcpy(msg+csize, bfrops, strlen(bfrops)); csize += strlen(bfrops)+1; /* provide the bfrops type */ memcpy(msg+csize, &bftype, sizeof(bftype)); csize += sizeof(bftype); /* provide the gds module */ memcpy(msg+csize, gds, strlen(gds)); csize += strlen(gds)+1; /* send the entire message across */ if (PMIX_SUCCESS != pmix_ptl_base_send_blocking(sd, msg, sdsize)) { free(msg); return PMIX_ERR_UNREACH; } free(msg); return PMIX_SUCCESS; }