This source file includes following definitions.
- native_init
- native_finalize
- create_cred
- validate_cred
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 #include <src/include/pmix_config.h>
  14 
  15 #include <unistd.h>
  16 #ifdef HAVE_SYS_TYPES_H
  17 #include <sys/types.h>
  18 #endif
  19 
  20 #include <pmix_common.h>
  21 
  22 #include "src/include/pmix_socket_errno.h"
  23 #include "src/include/pmix_globals.h"
  24 #include "src/util/argv.h"
  25 #include "src/util/error.h"
  26 #include "src/util/output.h"
  27 
  28 #include "src/mca/psec/base/base.h"
  29 #include "psec_native.h"
  30 
  31 static pmix_status_t native_init(void);
  32 static void native_finalize(void);
  33 static pmix_status_t create_cred(struct pmix_peer_t *peer,
  34                                  const pmix_info_t directives[], size_t ndirs,
  35                                  pmix_info_t **info, size_t *ninfo,
  36                                  pmix_byte_object_t *cred);
  37 static pmix_status_t validate_cred(struct pmix_peer_t *peer,
  38                                    const pmix_info_t directives[], size_t ndirs,
  39                                    pmix_info_t **info, size_t *ninfo,
  40                                    const pmix_byte_object_t *cred);
  41 
  42 pmix_psec_module_t pmix_native_module = {
  43     .name = "native",
  44     .init = native_init,
  45     .finalize = native_finalize,
  46     .create_cred = create_cred,
  47     .validate_cred = validate_cred
  48 };
  49 
  50 static pmix_status_t native_init(void)
  51 {
  52     pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
  53                         "psec: native init");
  54     return PMIX_SUCCESS;
  55 }
  56 
  57 static void native_finalize(void)
  58 {
  59     pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
  60                         "psec: native finalize");
  61 }
  62 
  63 static pmix_status_t create_cred(struct pmix_peer_t *peer,
  64                                  const pmix_info_t directives[], size_t ndirs,
  65                                  pmix_info_t **info, size_t *ninfo,
  66                                  pmix_byte_object_t *cred)
  67 {
  68     pmix_peer_t *pr = (pmix_peer_t*)peer;
  69     char **types;
  70     size_t n, m;
  71     bool takeus;
  72     uid_t euid;
  73     gid_t egid;
  74     char *tmp, *ptr;
  75 
  76     
  77     PMIX_BYTE_OBJECT_CONSTRUCT(cred);
  78 
  79     
  80 
  81     if (NULL != directives && 0 < ndirs) {
  82         
  83 
  84         takeus = true;
  85         for (n=0; n < ndirs; n++) {
  86             if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) {
  87                 
  88                 types = pmix_argv_split(directives[n].value.data.string, ',');
  89                 
  90                 takeus = false;
  91                 for (m=0; NULL != types[m]; m++) {
  92                     if (0 == strcmp(types[m], "native")) {
  93                         
  94                         takeus = true;
  95                         break;
  96                     }
  97                 }
  98                 pmix_argv_free(types);
  99                 break;
 100             }
 101         }
 102         if (!takeus) {
 103             PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
 104             return PMIX_ERR_NOT_SUPPORTED;
 105         }
 106     }
 107 
 108     if (PMIX_PROTOCOL_V1 == pr->protocol) {
 109         
 110         goto complete;
 111     } else if (PMIX_PROTOCOL_V2 == pr->protocol) {
 112         
 113 
 114         tmp = (char*)malloc(sizeof(uid_t) + sizeof(gid_t));
 115         if (NULL == tmp) {
 116             return PMIX_ERR_NOMEM;
 117         }
 118         euid = geteuid();
 119         memcpy(tmp, &euid, sizeof(uid_t));
 120         ptr = tmp + sizeof(uid_t);
 121         egid = getegid();
 122         memcpy(ptr, &egid, sizeof(gid_t));
 123         cred->bytes = tmp;
 124         cred->size = sizeof(uid_t) + sizeof(gid_t);
 125         goto complete;
 126     } else {
 127         
 128         PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
 129         return PMIX_ERR_NOT_SUPPORTED;
 130     }
 131 
 132   complete:
 133     if (NULL != info) {
 134         
 135         PMIX_INFO_CREATE(*info, 1);
 136         if (NULL == *info) {
 137             return PMIX_ERR_NOMEM;
 138         }
 139         *ninfo = 1;
 140         PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "native", PMIX_STRING);
 141     }
 142     return PMIX_SUCCESS;
 143 }
 144 
 145 static pmix_status_t validate_cred(struct pmix_peer_t *peer,
 146                                    const pmix_info_t directives[], size_t ndirs,
 147                                    pmix_info_t **info, size_t *ninfo,
 148                                    const pmix_byte_object_t *cred)
 149 {
 150     pmix_peer_t *pr = (pmix_peer_t*)peer;
 151 
 152 #if defined(SO_PEERCRED)
 153 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
 154 #define HAVE_STRUCT_UCRED_UID
 155     struct sockpeercred ucred;
 156 #else
 157     struct ucred ucred;
 158 #endif
 159     socklen_t crlen = sizeof (ucred);
 160 #endif
 161     uid_t euid = -1;
 162     gid_t egid = -1;
 163     char *ptr;
 164     size_t ln;
 165     bool takeus;
 166     char **types;
 167     size_t n, m;
 168     uint32_t u32;
 169 
 170     pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 171                         "psec: native validate_cred %s",
 172                         (NULL == cred) ? "NULL" : "NON-NULL");
 173 
 174     if (PMIX_PROTOCOL_V1 == pr->protocol) {
 175         
 176 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
 177         
 178         pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 179                             "psec:native checking getsockopt on socket %d for peer credentials", pr->sd);
 180         if (getsockopt(pr->sd, SOL_SOCKET, SO_PEERCRED, &ucred, &crlen) < 0) {
 181             pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 182                                 "psec: getsockopt SO_PEERCRED failed: %s",
 183                                 strerror (pmix_socket_errno));
 184             return PMIX_ERR_INVALID_CRED;
 185         }
 186 #if defined(HAVE_STRUCT_UCRED_UID)
 187         euid = ucred.uid;
 188         egid = ucred.gid;
 189 #else
 190         euid = ucred.cr_uid;
 191         egid = ucred.cr_gid;
 192 #endif
 193 
 194 #elif defined(HAVE_GETPEEREID)
 195         pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 196                             "psec:native checking getpeereid on socket %d for peer credentials", pr->sd);
 197         if (0 != getpeereid(pr->sd, &euid, &egid)) {
 198             pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 199                                 "psec: getsockopt getpeereid failed: %s",
 200                                 strerror (pmix_socket_errno));
 201             return PMIX_ERR_INVALID_CRED;
 202     }
 203 #else
 204         return PMIX_ERR_NOT_SUPPORTED;
 205 #endif
 206     } else if (PMIX_PROTOCOL_V2 == pr->protocol) {
 207         
 208 
 209         if (NULL == cred) {
 210             
 211             return PMIX_ERR_INVALID_CRED;
 212         }
 213         ln = cred->size;
 214         euid = 0;
 215         egid = 0;
 216         if (sizeof(uid_t) <= ln) {
 217             memcpy(&euid, cred->bytes, sizeof(uid_t));
 218             ln -= sizeof(uid_t);
 219             ptr = cred->bytes + sizeof(uid_t);
 220         } else {
 221             return PMIX_ERR_INVALID_CRED;
 222         }
 223         if (sizeof(gid_t) <= ln) {
 224             memcpy(&egid, ptr, sizeof(gid_t));
 225         } else {
 226             return PMIX_ERR_INVALID_CRED;
 227         }
 228     } else if (PMIX_PROTOCOL_UNDEF != pr->protocol) {
 229         
 230         return PMIX_ERR_NOT_SUPPORTED;
 231     }
 232 
 233     
 234 
 235     if (NULL != directives && 0 < ndirs) {
 236         for (n=0; n < ndirs; n++) {
 237             if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) {
 238                 
 239                 types = pmix_argv_split(directives[n].value.data.string, ',');
 240                 takeus = false;
 241                 for (m=0; NULL != types[m]; m++) {
 242                     if (0 == strcmp(types[m], "native")) {
 243                         
 244                         takeus = true;
 245                         break;
 246                     }
 247                 }
 248                 pmix_argv_free(types);
 249                 if (!takeus) {
 250                     return PMIX_ERR_NOT_SUPPORTED;
 251                 }
 252             }
 253         }
 254     }
 255 
 256     
 257     if (euid != pr->info->uid) {
 258         pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 259                             "psec: socket cred contains invalid uid %u", euid);
 260         return PMIX_ERR_INVALID_CRED;
 261     }
 262 
 263     
 264     if (egid != pr->info->gid) {
 265         pmix_output_verbose(2, pmix_psec_base_framework.framework_output,
 266                             "psec: socket cred contains invalid gid %u", egid);
 267         return PMIX_ERR_INVALID_CRED;
 268     }
 269 
 270     
 271     if (NULL != info) {
 272         PMIX_INFO_CREATE(*info, 3);
 273         if (NULL == *info) {
 274             return PMIX_ERR_NOMEM;
 275         }
 276         *ninfo = 3;
 277         
 278         PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING);
 279         
 280         u32 = euid;
 281         PMIX_INFO_LOAD(info[1], PMIX_USERID, &u32, PMIX_UINT32);
 282         
 283         u32 = egid;
 284         PMIX_INFO_LOAD(info[2], PMIX_GRPID, &u32, PMIX_UINT32);
 285     }
 286     return PMIX_SUCCESS;
 287 
 288 }