int principal2uid(char *principal, uid_t * puid) { #ifdef _USE_NFSIDMAP gid_t gss_gid; uid_t gss_uid; int rc; if(uidmap_get(principal, (unsigned long *)&gss_uid) != ID_MAPPER_SUCCESS) { if(!nfsidmap_set_conf()) { LogCrit(COMPONENT_IDMAPPER, "principal2uid: nfsidmap_set_conf failed"); return 0; } /* nfs4_gss_princ_to_ids required to extract uid/gid from gss creds */ LogFullDebug(COMPONENT_IDMAPPER, "calling nfs4_gss_princ_to_ids() to map principal to uid/gid"); rc = nfs4_gss_princ_to_ids("krb5", principal, &gss_uid, &gss_gid); if(rc) { LogFullDebug(COMPONENT_IDMAPPER, "principal2uid: nfs4_gss_princ_to_ids %s failed %d (%s)", principal, -rc, strerror(-rc)); return 0; } if(uidmap_add(principal, gss_uid) != ID_MAPPER_SUCCESS) { LogCrit(COMPONENT_IDMAPPER, "principal2uid: uidmap_add %s %d failed", principal, gss_uid); return 0; } if(uidgidmap_add(gss_uid, gss_gid) != ID_MAPPER_SUCCESS) { LogCrit(COMPONENT_IDMAPPER, "principal2uid: uidgidmap_add gss_uid %d gss_gid %d failed", gss_uid, gss_gid); return 0; } } LogFullDebug(COMPONENT_IDMAPPER, "principal2uid: uidmap_get mapped %s to uid= %d", principal, gss_uid); *puid = gss_uid; return 1; #else return 0 ; #endif /* _USE_NFSIDMAP */ } /* principal2uid */
/** * * name2uid: convert a name to a uid * * convert a name to a uid * * @param name [IN] the name of the user * @param puid [OUT] the resulting uid * * return 1 if successful, 0 otherwise * */ int name2uid(char *name, uid_t * puid) { struct passwd passwd; struct passwd *ppasswd; char buff[NFS4_MAX_DOMAIN_LEN]; uid_t uid; #ifdef _HAVE_GSSAPI gid_t gss_gid; uid_t gss_uid; #endif #ifdef _USE_NFSIDMAP char fqname[NFS4_MAX_DOMAIN_LEN]; int rc; #endif /* NFsv4 specific features: RPCSEC_GSS will provide user like nfs/<host> * choice is made to map them to root */ if(!strncmp(name, "nfs/", 4)) { /* This is a "root" request made from the hostbased nfs principal, use root */ LogFullDebug(COMPONENT_IDMAPPER, "name2uid: mapping %s to root (uid = 0)", name); *puid = 0; return 1; } if(uidmap_get(name, (unsigned long *)&uid) == ID_MAPPER_SUCCESS) { LogFullDebug(COMPONENT_IDMAPPER, "name2uid: uidmap_get mapped %s to uid= %d", name, uid); *puid = uid; return 1 ; } else { #ifdef _SOLARIS if(getpwnam_r(name, &passwd, buff, NFS4_MAX_DOMAIN_LEN) != 0) #else if(getpwnam_r(name, &passwd, buff, NFS4_MAX_DOMAIN_LEN, &ppasswd) != 0) #endif /* _SOLARIS */ { LogFullDebug(COMPONENT_IDMAPPER, "name2uid: getpwnam_r %s failed", name); *puid = -1; return 0; } else { *puid = passwd.pw_uid; #ifdef _HAVE_GSSAPI if(uidgidmap_add(passwd.pw_uid, passwd.pw_gid) != ID_MAPPER_SUCCESS) { LogCrit(COMPONENT_IDMAPPER, "name2uid: uidgidmap_add gss_uid %d gss_gid %d failed", gss_uid, gss_gid); return 0; } #endif /* _HAVE_GSSAPI */ if(uidmap_add(name, passwd.pw_uid) != ID_MAPPER_SUCCESS) { LogCrit(COMPONENT_IDMAPPER, "name2uid: uidmap_add %s %d failed", name, passwd.pw_uid); return 0; } return 1 ; /* Job is done */ } #ifdef _USE_NFSIDMAP if(!nfsidmap_set_conf()) { LogCrit(COMPONENT_IDMAPPER, "name2uid: nfsidmap_set_conf failed"); return 0; } /* obtain fully qualified name */ if(strchr(name, '@') == NULL) sprintf(fqname, "%s@%s", name, idmap_domain); else strncpy(fqname, name, NFS4_MAX_DOMAIN_LEN - 1); rc = nfs4_name_to_uid(fqname, puid); if(rc) { LogFullDebug(COMPONENT_IDMAPPER, "name2uid: nfs4_name_to_uid %s failed %d (%s)", fqname, -rc, strerror(-rc)); return 0; } LogFullDebug(COMPONENT_IDMAPPER, "name2uid: nfs4_name_to_uid %s returned %d", fqname, *puid); if(uidmap_add(fqname, *puid) != ID_MAPPER_SUCCESS) { LogCrit(COMPONENT_IDMAPPER, "name2uid: uidmap_add %s %d failed", fqname, *puid); return 0; } #ifdef _HAVE_GSSAPI /* nfs4_gss_princ_to_ids required to extract uid/gid from gss creds * XXX: currently uses unqualified name as per libnfsidmap comments */ rc = nfs4_gss_princ_to_ids("krb5", name, &gss_uid, &gss_gid); if(rc) { LogFullDebug(COMPONENT_IDMAPPER, "name2uid: nfs4_gss_princ_to_ids %s failed %d (%s)", name, -rc, strerror(-rc)); return 0; } if(uidgidmap_add(gss_uid, gss_gid) != ID_MAPPER_SUCCESS) { LogCrit(COMPONENT_IDMAPPER, "name2uid: uidgidmap_add gss_uid %d gss_gid %d failed", gss_uid, gss_gid); return 0; } #endif /* _HAVE_GSSAPI */ #endif /* _USE_NFSIDMAP */ } return 1; } /* name2uid */
static int get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred) { u_int32_t maj_stat, min_stat; gss_buffer_desc name; char *sname; int res = -1; uid_t uid, gid; gss_OID name_type = GSS_C_NO_OID; char *secname; maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type); if (maj_stat != GSS_S_COMPLETE) { pgsserr("get_ids: gss_display_name", maj_stat, min_stat, mech); goto out; } if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */ !(sname = calloc(name.length + 1, 1))) { printerr(0, "WARNING: get_ids: error allocating %d bytes " "for sname\n", name.length + 1); gss_release_buffer(&min_stat, &name); goto out; } memcpy(sname, name.value, name.length); printerr(1, "sname = %s\n", sname); gss_release_buffer(&min_stat, &name); res = -EINVAL; if ((secname = mech2file(mech)) == NULL) { printerr(0, "WARNING: get_ids: error mapping mech to " "file for name '%s'\n", sname); goto out_free; } nfs4_init_name_mapping(NULL); /* XXX: should only do this once */ res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid); if (res < 0) { /* * -ENOENT means there was no mapping, any other error * value means there was an error trying to do the * mapping. * If there was no mapping, we send down the value -1 * to indicate that the anonuid/anongid for the export * should be used. */ if (res == -ENOENT) { cred->cr_uid = -1; cred->cr_gid = -1; cred->cr_ngroups = 0; res = 0; goto out_free; } printerr(1, "WARNING: get_ids: failed to map name '%s' " "to uid/gid: %s\n", sname, strerror(-res)); goto out_free; } cred->cr_uid = uid; cred->cr_gid = gid; add_supplementary_groups(secname, sname, cred); res = 0; out_free: free(sname); out: return res; }
/** * @brief Convert a principal (as returned by @c gss_display_name) to a UID * * @param[in] name The principal of the user * @param[out] uid The resulting UID * * @return true if successful, false otherwise */ bool principal2uid(char *principal, uid_t *uid, gid_t *gid) #endif { #ifdef USE_NFSIDMAP uid_t gss_uid = ANON_UID; gid_t gss_gid = ANON_GID; const gid_t *gss_gidres = NULL; int rc; bool success; struct gsh_buffdesc princbuff = { .addr = principal, .len = strlen(principal) }; #endif if (nfs_param.nfsv4_param.use_getpwnam) return false; #ifdef USE_NFSIDMAP PTHREAD_RWLOCK_rdlock(&idmapper_user_lock); success = idmapper_lookup_by_uname(&princbuff, &gss_uid, &gss_gidres, true); if (success && gss_gidres) gss_gid = *gss_gidres; PTHREAD_RWLOCK_unlock(&idmapper_user_lock); if (unlikely(!success)) { if ((princbuff.len >= 4) && (!memcmp(princbuff.addr, "nfs/", 4) || !memcmp(princbuff.addr, "root/", 5) || !memcmp(princbuff.addr, "host/", 5))) { /* NFSv4 specific features: RPCSEC_GSS will * provide user like * * nfs/<host> * root/<host> * host/<host> * choice is made to map them to root */ /* This is a "root" request made from the hostbased nfs principal, use root */ *uid = 0; return true; } /* nfs4_gss_princ_to_ids required to extract uid/gid from gss creds */ rc = nfs4_gss_princ_to_ids("krb5", principal, &gss_uid, &gss_gid); if (rc) { #ifdef _MSPAC_SUPPORT bool found_uid = false; bool found_gid = false; if (gd->flags & SVC_RPC_GSS_FLAG_MSPAC) { struct wbcAuthUserParams params; wbcErr wbc_err; struct wbcAuthUserInfo *info; struct wbcAuthErrorInfo *error = NULL; memset(¶ms, 0, sizeof(params)); params.level = WBC_AUTH_USER_LEVEL_PAC; params.password.pac.data = (uint8_t *) gd->pac.ms_pac.value; params.password.pac.length = gd->pac.ms_pac.length; wbc_err = wbcAuthenticateUserEx(¶ms, &info, &error); if (!WBC_ERROR_IS_OK(wbc_err)) { LogCrit(COMPONENT_IDMAPPER, "wbcAuthenticateUserEx returned %s", wbcErrorString(wbc_err)); return false; } if (error) { LogCrit(COMPONENT_IDMAPPER, "nt_status: %s, display_string %s", error->nt_string, error->display_string); wbcFreeMemory(error); return false; } /* 1st SID is account sid, see wbclient.h */ wbc_err = wbcSidToUid(&info->sids[0].sid, &gss_uid); if (!WBC_ERROR_IS_OK(wbc_err)) { LogCrit(COMPONENT_IDMAPPER, "wbcSidToUid for uid returned %s", wbcErrorString(wbc_err)); wbcFreeMemory(info); return false; } /* 2nd SID is primary_group sid, see wbclient.h */ wbc_err = wbcSidToGid(&info->sids[1].sid, &gss_gid); if (!WBC_ERROR_IS_OK(wbc_err)) { LogCrit(COMPONENT_IDMAPPER, "wbcSidToUid for gid returned %s\n", wbcErrorString(wbc_err)); wbcFreeMemory(info); return false; } wbcFreeMemory(info); found_uid = true; found_gid = true; } #endif /* _MSPAC_SUPPORT */ #ifdef _MSPAC_SUPPORT if ((found_uid == true) && (found_gid == true)) goto principal_found; #endif return false; } #ifdef _MSPAC_SUPPORT principal_found: #endif PTHREAD_RWLOCK_wrlock(&idmapper_user_lock); success = idmapper_add_user(&princbuff, gss_uid, &gss_gid, true); PTHREAD_RWLOCK_unlock(&idmapper_user_lock); if (!success) { LogMajor(COMPONENT_IDMAPPER, "idmapper_add_user(%s, %d, %d) failed", principal, gss_uid, gss_gid); } } *uid = gss_uid; *gid = gss_gid; return true; #else /* !USE_NFSIDMAP */ assert(!"prohibited by configuration"); return false; #endif }