root/opal/mca/pmix/pmix4x/pmix/src/common/pmix_security.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getcbfunc
  2. PMIx_Get_credential
  3. valid_cbfunc
  4. PMIx_Validate_credential

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
   4  * Copyright (c) 2016      Mellanox Technologies, Inc.
   5  *                         All rights reserved.
   6  * Copyright (c) 2016      IBM Corporation.  All rights reserved.
   7  * Copyright (c) 2019      Research Organization for Information Science
   8  *                         and Technology (RIST).  All rights reserved.
   9  * $COPYRIGHT$
  10  *
  11  * Additional copyrights may follow
  12  *
  13  * $HEADER$
  14  */
  15 #include <src/include/pmix_config.h>
  16 
  17 #include <src/include/pmix_stdint.h>
  18 #include <src/include/pmix_socket_errno.h>
  19 
  20 #include <pmix.h>
  21 #include <pmix_common.h>
  22 #include <pmix_server.h>
  23 #include <pmix_rename.h>
  24 
  25 #include "src/threads/threads.h"
  26 #include "src/util/argv.h"
  27 #include "src/util/error.h"
  28 #include "src/util/output.h"
  29 #include "src/mca/bfrops/bfrops.h"
  30 #include "src/mca/psec/psec.h"
  31 #include "src/mca/ptl/ptl.h"
  32 
  33 #include "src/client/pmix_client_ops.h"
  34 #include "src/server/pmix_server_ops.h"
  35 #include "src/include/pmix_globals.h"
  36 
  37 static void getcbfunc(struct pmix_peer_t *peer,
  38                       pmix_ptl_hdr_t *hdr,
  39                       pmix_buffer_t *buf, void *cbdata)
  40 {
  41     pmix_query_caddy_t *cd = (pmix_query_caddy_t*)cbdata;
  42     pmix_status_t rc, status;
  43     int cnt;
  44     pmix_byte_object_t cred;
  45     pmix_info_t *info = NULL;
  46     size_t ninfo = 0;
  47 
  48     pmix_output_verbose(2, pmix_globals.debug_output,
  49                         "pmix:security cback from server with %d bytes",
  50                         (int)buf->bytes_used);
  51 
  52     /* a zero-byte buffer indicates that this recv is being
  53      * completed due to a lost connection */
  54     if (PMIX_BUFFER_IS_EMPTY(buf)) {
  55         /* release the caller */
  56         if (NULL != cd->credcbfunc) {
  57             cd->credcbfunc(PMIX_ERR_COMM_FAILURE, NULL, NULL, 0, cd->cbdata);
  58         }
  59         PMIX_RELEASE(cd);
  60         return;
  61     }
  62 
  63     /* unpack the status */
  64     cnt = 1;
  65     PMIX_BFROPS_UNPACK(rc, peer, buf, &status, &cnt, PMIX_STATUS);
  66     if (PMIX_SUCCESS != rc) {
  67         PMIX_ERROR_LOG(rc);
  68         goto complete;
  69     }
  70     if (PMIX_SUCCESS != status) {
  71         goto complete;
  72     }
  73 
  74     /* unpack the credential */
  75     cnt = 1;
  76     PMIX_BFROPS_UNPACK(rc, peer, buf, &cred, &cnt, PMIX_BYTE_OBJECT);
  77     if (PMIX_SUCCESS != rc) {
  78         PMIX_ERROR_LOG(rc);
  79         goto complete;
  80     }
  81 
  82     /* unpack any returned info */
  83     cnt = 1;
  84     PMIX_BFROPS_UNPACK(rc, peer, buf, &ninfo, &cnt, PMIX_SIZE);
  85     if (PMIX_SUCCESS != rc) {
  86         PMIX_ERROR_LOG(rc);
  87         goto complete;
  88     }
  89     if (0 < ninfo) {
  90         PMIX_INFO_CREATE(info, ninfo);
  91         cnt = ninfo;
  92         PMIX_BFROPS_UNPACK(rc, peer, buf, info, &cnt, PMIX_INFO);
  93         if (PMIX_SUCCESS != rc) {
  94             PMIX_ERROR_LOG(rc);
  95             goto complete;
  96         }
  97     }
  98 
  99   complete:
 100     pmix_output_verbose(2, pmix_globals.debug_output,
 101                         "pmix:security cback from server releasing");
 102     /* release the caller */
 103     if (NULL != cd->credcbfunc) {
 104         cd->credcbfunc(status, &cred, info, ninfo, cd->cbdata);
 105     }
 106     PMIX_BYTE_OBJECT_DESTRUCT(&cred);
 107     if (NULL != info) {
 108         PMIX_INFO_FREE(info, ninfo);
 109     }
 110     PMIX_RELEASE(cd);
 111 }
 112 
 113 PMIX_EXPORT pmix_status_t PMIx_Get_credential(const pmix_info_t info[], size_t ninfo,
 114                                               pmix_credential_cbfunc_t cbfunc, void *cbdata)
 115 {
 116     pmix_buffer_t *msg;
 117     pmix_cmd_t cmd = PMIX_GET_CREDENTIAL_CMD;
 118     pmix_status_t rc;
 119     pmix_query_caddy_t *cb;
 120     pmix_byte_object_t cred;
 121     pmix_info_t *results = NULL;
 122     size_t nresults = 0;
 123 
 124     PMIX_ACQUIRE_THREAD(&pmix_global_lock);
 125 
 126     pmix_output_verbose(2, pmix_globals.debug_output,
 127                         "pmix: Get_credential called with %d info", (int)ninfo);
 128 
 129     if (pmix_globals.init_cntr <= 0) {
 130         PMIX_RELEASE_THREAD(&pmix_global_lock);
 131         return PMIX_ERR_INIT;
 132     }
 133 
 134     /* if we are the server */
 135     if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer) &&
 136         !PMIX_PROC_IS_LAUNCHER(pmix_globals.mypeer)) {
 137         PMIX_RELEASE_THREAD(&pmix_global_lock);
 138         /* if the host doesn't support this operation,
 139          * see if we can generate it ourselves */
 140         if (NULL == pmix_host_server.get_credential) {
 141             PMIX_BYTE_OBJECT_CONSTRUCT(&cred);
 142             PMIX_PSEC_CREATE_CRED(rc, pmix_globals.mypeer, info, ninfo,
 143                                   &results, &nresults, &cred);
 144             if (PMIX_SUCCESS == rc) {
 145                 /* pass it back in the callback function */
 146                 if (NULL != cbfunc) {
 147                     cbfunc(PMIX_SUCCESS, &cred, results, nresults, cbdata);
 148                     if (NULL != results) {
 149                         PMIX_INFO_FREE(results, nresults);
 150                     }
 151                     PMIX_BYTE_OBJECT_DESTRUCT(&cred);
 152                 }
 153             }
 154             return rc;
 155         }
 156         /* the host is available, so let them try to create it */
 157         pmix_output_verbose(2, pmix_globals.debug_output,
 158                             "pmix:get_credential handed to RM");
 159         rc = pmix_host_server.get_credential(&pmix_globals.myid,
 160                                              info, ninfo,
 161                                              cbfunc, cbdata);
 162         return rc;
 163     }
 164 
 165     /* if we are a client or tool and we aren't connected, see
 166      * if one of our internal plugins is capable of meeting the request */
 167     if (!pmix_globals.connected) {
 168         PMIX_RELEASE_THREAD(&pmix_global_lock);
 169         PMIX_BYTE_OBJECT_CONSTRUCT(&cred);
 170         PMIX_PSEC_CREATE_CRED(rc, pmix_globals.mypeer, info, ninfo,
 171                               &results, &nresults, &cred);
 172         if (PMIX_SUCCESS == rc) {
 173             /* pass it back in the callback function */
 174             if (NULL != cbfunc) {
 175                 cbfunc(PMIX_SUCCESS, &cred, results, nresults, cbdata);
 176                 if (NULL != results) {
 177                     PMIX_INFO_FREE(results, nresults);
 178                 }
 179                 PMIX_BYTE_OBJECT_DESTRUCT(&cred);
 180             }
 181         }
 182         return rc;
 183     }
 184     PMIX_RELEASE_THREAD(&pmix_global_lock);
 185 
 186     /* if we are a client, then relay this request to the server */
 187     msg = PMIX_NEW(pmix_buffer_t);
 188     /* pack the cmd */
 189     PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 190                      msg, &cmd, 1, PMIX_COMMAND);
 191     if (PMIX_SUCCESS != rc) {
 192         PMIX_ERROR_LOG(rc);
 193         PMIX_RELEASE(msg);
 194         return rc;
 195     }
 196 
 197     /* pack the directives */
 198     PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 199                      msg, &ninfo, 1, PMIX_SIZE);
 200     if (PMIX_SUCCESS != rc) {
 201         PMIX_ERROR_LOG(rc);
 202         PMIX_RELEASE(msg);
 203         return rc;
 204     }
 205     if (0 < ninfo) {
 206         PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 207                          msg, info, ninfo, PMIX_INFO);
 208         if (PMIX_SUCCESS != rc) {
 209             PMIX_ERROR_LOG(rc);
 210             PMIX_RELEASE(msg);
 211             return rc;
 212         }
 213     }
 214 
 215     /* create a callback object as we need to pass it to the
 216      * recv routine so we know which callback to use when
 217      * the return message is recvd */
 218     cb = PMIX_NEW(pmix_query_caddy_t);
 219     cb->credcbfunc = cbfunc;
 220     cb->cbdata = cbdata;
 221 
 222     /* push the message into our event base to send to the server */
 223     PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver,
 224                        msg, getcbfunc, (void*)cb);
 225     if (PMIX_SUCCESS != rc) {
 226         PMIX_RELEASE(msg);
 227         PMIX_RELEASE(cb);
 228     }
 229 
 230     return rc;
 231 }
 232 
 233 static void valid_cbfunc(struct pmix_peer_t *peer,
 234                          pmix_ptl_hdr_t *hdr,
 235                          pmix_buffer_t *buf, void *cbdata)
 236 {
 237     pmix_query_caddy_t *cd = (pmix_query_caddy_t*)cbdata;
 238     pmix_status_t rc, status;
 239     int cnt;
 240     pmix_info_t *info = NULL;
 241     size_t ninfo = 0;
 242 
 243     pmix_output_verbose(2, pmix_globals.debug_output,
 244                         "pmix:security cback from server with %d bytes",
 245                         (int)buf->bytes_used);
 246 
 247     /* a zero-byte buffer indicates that this recv is being
 248      * completed due to a lost connection */
 249     if (PMIX_BUFFER_IS_EMPTY(buf)) {
 250         /* release the caller */
 251         if (NULL != cd->validcbfunc) {
 252             cd->validcbfunc(PMIX_ERR_COMM_FAILURE, NULL, 0, cd->cbdata);
 253         }
 254         PMIX_RELEASE(cd);
 255         return;
 256     }
 257 
 258     /* unpack the status */
 259     cnt = 1;
 260     PMIX_BFROPS_UNPACK(rc, peer, buf, &status, &cnt, PMIX_STATUS);
 261     if (PMIX_SUCCESS != rc) {
 262         PMIX_ERROR_LOG(rc);
 263         goto complete;
 264     }
 265     if (PMIX_SUCCESS != status) {
 266         goto complete;
 267     }
 268 
 269     /* unpack any returned info */
 270     cnt = 1;
 271     PMIX_BFROPS_UNPACK(rc, peer, buf, &ninfo, &cnt, PMIX_SIZE);
 272     if (PMIX_SUCCESS != rc) {
 273         PMIX_ERROR_LOG(rc);
 274         goto complete;
 275     }
 276     if (0 < ninfo) {
 277         PMIX_INFO_CREATE(info, ninfo);
 278         cnt = ninfo;
 279         PMIX_BFROPS_UNPACK(rc, peer, buf, info, &cnt, PMIX_INFO);
 280         if (PMIX_SUCCESS != rc) {
 281             PMIX_ERROR_LOG(rc);
 282             goto complete;
 283         }
 284     }
 285 
 286   complete:
 287     pmix_output_verbose(2, pmix_globals.debug_output,
 288                         "pmix:security cback from server releasing");
 289     /* release the caller */
 290     if (NULL != cd->validcbfunc) {
 291         cd->validcbfunc(status, info, ninfo, cd->cbdata);
 292     }
 293     if (NULL != info) {
 294         PMIX_INFO_FREE(info, ninfo);
 295     }
 296     PMIX_RELEASE(cd);
 297 }
 298 
 299 PMIX_EXPORT pmix_status_t PMIx_Validate_credential(const pmix_byte_object_t *cred,
 300                                                    const pmix_info_t directives[], size_t ndirs,
 301                                                    pmix_validation_cbfunc_t cbfunc, void *cbdata)
 302 {
 303     pmix_buffer_t *msg;
 304     pmix_cmd_t cmd = PMIX_VALIDATE_CRED_CMD;
 305     pmix_status_t rc;
 306     pmix_query_caddy_t *cb;
 307     pmix_info_t *results = NULL;
 308     size_t nresults = 0;
 309 
 310     PMIX_ACQUIRE_THREAD(&pmix_global_lock);
 311 
 312     pmix_output_verbose(2, pmix_globals.debug_output,
 313                         "pmix: monitor called");
 314 
 315     if (pmix_globals.init_cntr <= 0) {
 316         PMIX_RELEASE_THREAD(&pmix_global_lock);
 317         return PMIX_ERR_INIT;
 318     }
 319 
 320     /* if we are the server */
 321     if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer) &&
 322         !PMIX_PROC_IS_LAUNCHER(pmix_globals.mypeer)) {
 323         PMIX_RELEASE_THREAD(&pmix_global_lock);
 324         /* if the host doesn't support this operation,
 325          * see if we can validate it ourselves */
 326         if (NULL == pmix_host_server.validate_credential) {
 327             PMIX_PSEC_VALIDATE_CRED(rc, pmix_globals.mypeer,
 328                                     directives, ndirs,
 329                                     &results, &nresults, cred);
 330             if (PMIX_SUCCESS == rc) {
 331                 /* pass it back in the callback function */
 332                 if (NULL != cbfunc) {
 333                     cbfunc(PMIX_SUCCESS, results, nresults, cbdata);
 334                     if (NULL != results) {
 335                         PMIX_INFO_FREE(results, nresults);
 336                     }
 337                 }
 338             }
 339             return rc;
 340         }
 341         /* the host is available, so let them try to validate it */
 342         pmix_output_verbose(2, pmix_globals.debug_output,
 343                             "pmix:get_credential handed to RM");
 344         rc = pmix_host_server.validate_credential(&pmix_globals.myid, cred,
 345                                                   directives, ndirs, cbfunc, cbdata);
 346         return rc;
 347     }
 348 
 349     /* if we are a client or tool and we aren't connected, see
 350      * if one of our internal plugins is capable of meeting the request */
 351     if (!pmix_globals.connected) {
 352         PMIX_RELEASE_THREAD(&pmix_global_lock);
 353         PMIX_PSEC_VALIDATE_CRED(rc, pmix_globals.mypeer,
 354                                 directives, ndirs,
 355                                 &results, &nresults, cred);
 356         if (PMIX_SUCCESS == rc) {
 357             /* pass it back in the callback function */
 358             if (NULL != cbfunc) {
 359                 cbfunc(PMIX_SUCCESS, results, nresults, cbdata);
 360                 if (NULL != results) {
 361                     PMIX_INFO_FREE(results, nresults);
 362                 }
 363             }
 364         }
 365         return rc;
 366     }
 367     PMIX_RELEASE_THREAD(&pmix_global_lock);
 368 
 369     /* if we are a client, then relay this request to the server */
 370     msg = PMIX_NEW(pmix_buffer_t);
 371     /* pack the cmd */
 372     PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 373                      msg, &cmd, 1, PMIX_COMMAND);
 374     if (PMIX_SUCCESS != rc) {
 375         PMIX_ERROR_LOG(rc);
 376         PMIX_RELEASE(msg);
 377         return rc;
 378     }
 379 
 380     /* pack the credential */
 381     PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 382                      msg, cred, 1, PMIX_BYTE_OBJECT);
 383     if (PMIX_SUCCESS != rc) {
 384         PMIX_ERROR_LOG(rc);
 385         PMIX_RELEASE(msg);
 386         return rc;
 387     }
 388 
 389     /* pack the directives */
 390     PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 391                      msg, &ndirs, 1, PMIX_SIZE);
 392     if (PMIX_SUCCESS != rc) {
 393         PMIX_ERROR_LOG(rc);
 394         PMIX_RELEASE(msg);
 395         return rc;
 396     }
 397     if (0 < ndirs) {
 398         PMIX_BFROPS_PACK(rc, pmix_client_globals.myserver,
 399                          msg, directives, ndirs, PMIX_INFO);
 400         if (PMIX_SUCCESS != rc) {
 401             PMIX_ERROR_LOG(rc);
 402             PMIX_RELEASE(msg);
 403             return rc;
 404         }
 405     }
 406 
 407     /* create a callback object as we need to pass it to the
 408      * recv routine so we know which callback to use when
 409      * the return message is recvd */
 410     cb = PMIX_NEW(pmix_query_caddy_t);
 411     cb->validcbfunc = cbfunc;
 412     cb->cbdata = cbdata;
 413 
 414     /* push the message into our event base to send to the server */
 415     PMIX_PTL_SEND_RECV(rc, pmix_client_globals.myserver,
 416                        msg, valid_cbfunc, (void*)cb);
 417     if (PMIX_SUCCESS != rc) {
 418         PMIX_RELEASE(msg);
 419         PMIX_RELEASE(cb);
 420     }
 421 
 422     return rc;
 423 }

/* [<][>][^][v][top][bottom][index][help] */