root/opal/mca/pmix/pmix4x/pmix/src/mca/psec/munge/psec_munge.c

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

DEFINITIONS

This source file includes following definitions.
  1. munge_init
  2. munge_finalize
  3. create_cred
  4. validate_cred

   1 /*
   2  * Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
   3  *
   4  * NOTE: THE MUNGE CLIENT LIBRARY (libmunge) IS LICENSED AS LGPL
   5  *
   6  * $COPYRIGHT$
   7  *
   8  * Additional copyrights may follow
   9  *
  10  * $HEADER$
  11  */
  12 
  13 #include <src/include/pmix_config.h>
  14 
  15 #include <pmix_common.h>
  16 
  17 #include "src/include/pmix_globals.h"
  18 #include "src/util/argv.h"
  19 #include "src/util/error.h"
  20 #include "src/util/output.h"
  21 
  22 #include <unistd.h>
  23 #ifdef HAVE_SYS_TYPES_H
  24 #include <sys/types.h>
  25 #endif
  26 #include <munge.h>
  27 
  28 #include "src/threads/threads.h"
  29 #include "src/mca/psec/psec.h"
  30 #include "psec_munge.h"
  31 
  32 static pmix_status_t munge_init(void);
  33 static void munge_finalize(void);
  34 static pmix_status_t create_cred(struct pmix_peer_t *peer,
  35                                  const pmix_info_t directives[], size_t ndirs,
  36                                  pmix_info_t **info, size_t *ninfo,
  37                                  pmix_byte_object_t *cred);
  38 static pmix_status_t validate_cred(struct pmix_peer_t *peer,
  39                                    const pmix_info_t directives[], size_t ndirs,
  40                                    pmix_info_t **info, size_t *ninfo,
  41                                    const pmix_byte_object_t *cred);
  42 
  43 pmix_psec_module_t pmix_munge_module = {
  44     .name = "munge",
  45     .init = munge_init,
  46     .finalize = munge_finalize,
  47     .create_cred = create_cred,
  48     .validate_cred = validate_cred
  49 };
  50 
  51 static pmix_lock_t lock;
  52 static char *mycred = NULL;
  53 static bool initialized = false;
  54 static bool refresh = false;
  55 
  56 static pmix_status_t munge_init(void)
  57 {
  58     int rc;
  59 
  60     pmix_output_verbose(2, pmix_globals.debug_output,
  61                         "psec: munge init");
  62 
  63     PMIX_CONSTRUCT_LOCK(&lock);
  64     lock.active = false;
  65 
  66     /* attempt to get a credential as a way of checking that
  67      * the munge server is available - cache the credential
  68      * for later use */
  69 
  70     if (EMUNGE_SUCCESS != (rc = munge_encode(&mycred, NULL, NULL, 0))) {
  71         pmix_output_verbose(2, pmix_globals.debug_output,
  72                             "psec: munge failed to create credential: %s",
  73                             munge_strerror(rc));
  74         return PMIX_ERR_SERVER_NOT_AVAIL;
  75     }
  76 
  77     initialized = true;
  78 
  79     return PMIX_SUCCESS;
  80 }
  81 
  82 static void munge_finalize(void)
  83 {
  84     PMIX_ACQUIRE_THREAD(&lock);
  85 
  86     pmix_output_verbose(2, pmix_globals.debug_output,
  87                         "psec: munge finalize");
  88     if (initialized) {
  89         if (NULL != mycred) {
  90             free(mycred);
  91             mycred = NULL;
  92         }
  93     }
  94     PMIX_RELEASE_THREAD(&lock);
  95     PMIX_DESTRUCT_LOCK(&lock);
  96 }
  97 
  98 static pmix_status_t create_cred(struct pmix_peer_t *peer,
  99                                  const pmix_info_t directives[], size_t ndirs,
 100                                  pmix_info_t **info, size_t *ninfo,
 101                                  pmix_byte_object_t *cred)
 102 {
 103     int rc;
 104     bool takeus;
 105     char **types;
 106     size_t n, m;
 107 
 108     PMIX_ACQUIRE_THREAD(&lock);
 109 
 110     pmix_output_verbose(2, pmix_globals.debug_output,
 111                         "psec: munge create_cred");
 112 
 113     /* ensure initialization */
 114     PMIX_BYTE_OBJECT_CONSTRUCT(cred);
 115 
 116     /* if we are responding to a local request to create a credential,
 117      * then see if they specified a mechanism */
 118     if (NULL != directives && 0 < ndirs) {
 119         for (n=0; n < ndirs; n++) {
 120             if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) {
 121                 /* split the specified string */
 122                 types = pmix_argv_split(directives[n].value.data.string, ',');
 123                 takeus = false;
 124                 for (m=0; NULL != types[m]; m++) {
 125                     if (0 == strcmp(types[m], "munge")) {
 126                         /* it's us! */
 127                         takeus = true;
 128                         break;
 129                     }
 130                 }
 131                 pmix_argv_free(types);
 132                 if (!takeus) {
 133                     PMIX_RELEASE_THREAD(&lock);
 134                     return PMIX_ERR_NOT_SUPPORTED;
 135                 }
 136             }
 137         }
 138     }
 139 
 140     if (initialized) {
 141         if (!refresh) {
 142             refresh = true;
 143             cred->bytes = strdup(mycred);
 144             cred->size = strlen(mycred) + 1;
 145         } else {
 146             /* munge does not allow reuse of a credential, so we have to
 147              * refresh it for every use */
 148             if (NULL != mycred) {
 149                 free(mycred);
 150             }
 151             if (EMUNGE_SUCCESS != (rc = munge_encode(&mycred, NULL, NULL, 0))) {
 152                 pmix_output_verbose(2, pmix_globals.debug_output,
 153                                     "psec: munge failed to create credential: %s",
 154                                     munge_strerror(rc));
 155                 PMIX_RELEASE_THREAD(&lock);
 156                 return PMIX_ERR_NOT_SUPPORTED;
 157             }
 158             cred->bytes = strdup(mycred);
 159             cred->size = strlen(mycred) + 1;
 160         }
 161     }
 162     if (NULL != info) {
 163         /* mark that this came from us */
 164         PMIX_INFO_CREATE(*info, 1);
 165         if (NULL == *info) {
 166             PMIX_RELEASE_THREAD(&lock);
 167             return PMIX_ERR_NOMEM;
 168         }
 169         *ninfo = 1;
 170         PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING);
 171     }
 172     PMIX_RELEASE_THREAD(&lock);
 173     return PMIX_SUCCESS;
 174 }
 175 
 176 static pmix_status_t validate_cred(struct pmix_peer_t *peer,
 177                                    const pmix_info_t directives[], size_t ndirs,
 178                                    pmix_info_t **info, size_t *ninfo,
 179                                    const pmix_byte_object_t *cred)
 180 {
 181     pmix_peer_t *pr = (pmix_peer_t*)peer;
 182     uid_t euid;
 183     gid_t egid;
 184     munge_err_t rc;
 185     bool takeus;
 186     char **types;
 187     size_t n, m;
 188     uint32_t u32;
 189 
 190     pmix_output_verbose(2, pmix_globals.debug_output,
 191                         "psec: munge validate_cred %s",
 192                         (NULL == cred) ? "NULL" : "NON-NULL");
 193 
 194     /* if we are responding to a local request to validate a credential,
 195      * then see if they specified a mechanism */
 196     if (NULL != directives && 0 < ndirs) {
 197         for (n=0; n < ndirs; n++) {
 198             if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) {
 199                 /* split the specified string */
 200                 types = pmix_argv_split(directives[n].value.data.string, ',');
 201                 takeus = false;
 202                 for (m=0; NULL != types[m]; m++) {
 203                     if (0 == strcmp(types[m], "munge")) {
 204                         /* it's us! */
 205                         takeus = true;
 206                         break;
 207                     }
 208                 }
 209                 pmix_argv_free(types);
 210                 if (!takeus) {
 211                     return PMIX_ERR_NOT_SUPPORTED;
 212                 }
 213             }
 214         }
 215     }
 216 
 217     /* parse the inbound string */
 218     if (EMUNGE_SUCCESS != (rc = munge_decode(cred->bytes, NULL, NULL, NULL, &euid, &egid))) {
 219         pmix_output_verbose(2, pmix_globals.debug_output,
 220                             "psec: munge failed to decode credential: %s",
 221                             munge_strerror(rc));
 222         return PMIX_ERR_INVALID_CRED;
 223     }
 224 
 225     /* check uid */
 226     if (euid != pr->info->uid) {
 227         return PMIX_ERR_INVALID_CRED;
 228     }
 229 
 230     /* check guid */
 231     if (egid != pr->info->gid) {
 232         return PMIX_ERR_INVALID_CRED;
 233     }
 234 
 235     pmix_output_verbose(2, pmix_globals.debug_output,
 236                         "psec: munge credential valid");
 237     if (NULL != info) {
 238         PMIX_INFO_CREATE(*info, 3);
 239         if (NULL == *info) {
 240             return PMIX_ERR_NOMEM;
 241         }
 242         *ninfo = 3;
 243         /* mark that this came from us */
 244         PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING);
 245         /* provide the uid it contained */
 246         u32 = euid;
 247         PMIX_INFO_LOAD(info[1], PMIX_USERID, &u32, PMIX_UINT32);
 248         /* provide the gid it contained */
 249         u32 = egid;
 250         PMIX_INFO_LOAD(info[2], PMIX_GRPID, &u32, PMIX_UINT32);
 251     }
 252     return PMIX_SUCCESS;
 253 }

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