+ return nfsmask;
+}
+
+/*
+ * nfs4_wkid2sidd::
+ * mapid a wellknown identity to guid.
+ * Return 0 on success ENOENT if id does not map and EINVAL if the id is not a well known name.
+ */
+static int
+nfs4_wkid2sid(const char *id, ntsid_t *sp)
+{
+ size_t len = strnlen(id, MAXIDNAMELEN);
+
+ if (len == MAXIDNAMELEN || id[len - 1] != '@') {
+ return EINVAL;
+ }
+
+ bzero(sp, sizeof(ntsid_t));
+ sp->sid_kind = 1;
+ sp->sid_authcount = 1;
+ if (!strcmp(id, "OWNER@")) {
+ // S-1-3-0
+ sp->sid_authority[5] = 3;
+ sp->sid_authorities[0] = 0;
+ } else if (!strcmp(id, "GROUP@")) {
+ // S-1-3-1
+ sp->sid_authority[5] = 3;
+ sp->sid_authorities[0] = 1;
+ } else if (!strcmp(id, "EVERYONE@")) {
+ // S-1-1-0
+ sp->sid_authority[5] = 1;
+ sp->sid_authorities[0] = 0;
+ } else if (!strcmp(id, "INTERACTIVE@")) {
+ // S-1-5-4
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 4;
+ } else if (!strcmp(id, "NETWORK@")) {
+ // S-1-5-2
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 2;
+ } else if (!strcmp(id, "DIALUP@")) {
+ // S-1-5-1
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 1;
+ } else if (!strcmp(id, "BATCH@")) {
+ // S-1-5-3
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 3;
+ } else if (!strcmp(id, "ANONYMOUS@")) {
+ // S-1-5-7
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 7;
+ } else if (!strcmp(id, "AUTHENTICATED@")) {
+ // S-1-5-11
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 11;
+ } else if (!strcmp(id, "SERVICE@")) {
+ // S-1-5-6
+ sp->sid_authority[5] = 5;
+ sp->sid_authorities[0] = 6;
+ } else {
+ // S-1-0-0 "NOBODY"
+ sp->sid_authority[5] = 0;
+ sp->sid_authorities[0] = 0;
+ }
+ return 0;
+}
+
+static int
+nfs4_fallback_name(const char *id, int have_at)
+{
+ if (have_at) {
+ /* must be user@domain */
+ /* try to identify some well-known IDs */
+ if (!strncmp(id, "root@", 5)) {
+ return 0;
+ } else if (!strncmp(id, "wheel@", 6)) {
+ return 0;
+ } else if (!strncmp(id, "nobody@", 7)) {
+ return -2;
+ } else if (!strncmp(id, "nfsnobody@", 10)) {
+ return -2;
+ }
+ }
+ return -2;
+}
+
+static void
+nfs4_mapid_log(int error, const char *idstr, int isgroup, guid_t *gp)
+{
+ if (error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS)) {
+ printf("nfs4_id2guid: idmap failed for %s %s error %d\n", idstr, isgroup ? "G" : " ", error);
+ }
+ if (!error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_SUCCESSFUL_MAPPINGS)) {
+ printf("nfs4_id2guid: idmap for %s %s got guid "
+ "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x\n",
+ idstr, isgroup ? "G" : " ",
+ gp->g_guid[0], gp->g_guid[1], gp->g_guid[2], gp->g_guid[3],
+ gp->g_guid[4], gp->g_guid[5], gp->g_guid[6], gp->g_guid[7],
+ gp->g_guid[8], gp->g_guid[9], gp->g_guid[10], gp->g_guid[11],
+ gp->g_guid[12], gp->g_guid[13], gp->g_guid[14], gp->g_guid[15]);
+ }
+}
+
+static char *
+nfs4_map_domain(char *id, char **atp)
+{
+ char *at = *atp;
+ char *dsnode, *otw_nfs4domain;
+ char *new_id = NULL;
+ size_t otw_domain_len;
+ size_t otw_id_2_at_len;
+ int error;
+
+ if (at == NULL) {
+ at = strchr(id, '@');
+ }
+ if (at == NULL || *at != '@') {
+ return NULL;
+ }
+
+ otw_nfs4domain = at + 1;
+ otw_domain_len = strnlen(otw_nfs4domain, MAXPATHLEN);
+ otw_id_2_at_len = at - id + 1;
+
+ MALLOC_ZONE(dsnode, char*, MAXPATHLEN, M_NAMEI, M_WAITOK);
+ /* first try to map nfs4 domain to dsnode for scoped lookups */
+ error = kauth_cred_nfs4domain2dsnode(otw_nfs4domain, dsnode);
+ if (!error) {
+ /* Success! Make new id be id@dsnode */
+ size_t dsnode_len = strnlen(dsnode, MAXPATHLEN);
+ size_t new_id_len = otw_id_2_at_len + dsnode_len + 1;
+ char tmp;
+
+ MALLOC(new_id, char*, new_id_len, M_TEMP, M_WAITOK);
+ tmp = *otw_nfs4domain;
+ *otw_nfs4domain = '\0'; /* Chop of the old domain */
+ strlcpy(new_id, id, MAXPATHLEN);
+ *otw_nfs4domain = tmp; /* Be nice and preserve callers original id */
+ strlcat(new_id, dsnode, MAXPATHLEN);
+ at = strchr(new_id, '@');
+ } else {
+ /* Bummer:-( See if default nfs4 set for unscoped lookup */
+ size_t default_domain_len = strnlen(nfs4_default_domain, MAXPATHLEN);
+
+ if ((otw_domain_len == default_domain_len) &&
+ (strncmp(otw_nfs4domain, nfs4_default_domain, otw_domain_len) == 0)) {
+ /* Woohoo! We have matching domains, do unscoped lookups */
+ *at = '\0';
+ }
+ }
+ FREE_ZONE(dsnode, MAXPATHLEN, M_NAMEI);
+
+ if (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_SUCCESSFUL_MAPPINGS) {
+ printf("nfs4_id2guid: after domain mapping id is %s\n", id);
+ }
+
+ *atp = at;
+ return new_id;