ID_TYPE_NOT_SPECIFIED,
ID_TYPE_UID,
ID_TYPE_GID,
- ID_TYPE_BOTH
+ ID_TYPE_BOTH,
+ /*
+ * This are internal between winbindd
+ * parent and child.
+ *
+ * It means the idmap backend/child requires a valid type_hint
+ * for wbint_Sids2UnixIDs():
+ *
+ * - ID_TYPE_UID or ID_TYPE_GID means the user/group exists
+ * - ID_TYPE_BOTH means that only the domain exist
+ */
+ ID_TYPE_WB_REQUIRE_TYPE
} id_type;
typedef [public] struct {
ID_UNKNOWN,
ID_MAPPED,
ID_UNMAPPED,
- ID_EXPIRED
+ ID_EXPIRED,
+ /*
+ * This means the idmap backend requires a valid type_hint
+ * in order to map a sid to a unix id.
+ *
+ * - ID_TYPE_UID or ID_TYPE_GID means the user/group exists
+ * - ID_TYPE_BOTH means that only the domain exist
+ */
+ ID_REQUIRE_TYPE
} id_mapping;
typedef [public] struct {
break;
case ID_TYPE_NOT_SPECIFIED:
break;
+ case ID_TYPE_WB_REQUIRE_TYPE:
+ /*
+ * these are internal between winbindd
+ * parent and child.
+ */
+ smb_panic(__location__);
+ break;
}
}
* range.
*/
- DBG_NOTICE("Allocating range for domain %s refused\n", range.domsid);
- map->status = ID_UNMAPPED;
- return NT_STATUS_NONE_MAPPED;
+ DBG_NOTICE("Allocating range for domain %s required type_hint\n", range.domsid);
+ map->status = ID_REQUIRE_TYPE;
+ return NT_STATUS_SOME_NOT_MAPPED;
allocate:
ret = idmap_autorid_acquire_range(autorid_db, &range);
LDAP_ATTR_GIDNUMBER);
break;
+ case ID_TYPE_BOTH:
+ /*
+ * This is not supported here yet and
+ * already handled in idmap_rw_new_mapping()
+ */
+ FALL_THROUGH;
+ case ID_TYPE_NOT_SPECIFIED:
+ /*
+ * This is handled in idmap_rw_new_mapping()
+ */
+ FALL_THROUGH;
default:
DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
return NT_STATUS_INVALID_PARAMETER;
const char **attr_list;
char *filter = NULL;
bool multi = False;
+ size_t num_required = 0;
int idx = 0;
int bidx = 0;
int count;
ids[i]->status = ID_UNMAPPED;
if (ids[i]->sid != NULL) {
ret = idmap_ldap_new_mapping(dom, ids[i]);
+ DBG_DEBUG("idmap_ldap_new_mapping returned %s\n",
+ nt_errstr(ret));
+ if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) {
+ if (ids[i]->status == ID_REQUIRE_TYPE) {
+ num_required += 1;
+ continue;
+ }
+ }
if (!NT_STATUS_IS_OK(ret)) {
+ /*
+ * If we can't create
+ * a new mapping it's unlikely
+ * that it will work for the
+ * next entry.
+ */
goto done;
}
}
}
ret = NT_STATUS_OK;
+ if (num_required > 0) {
+ ret = STATUS_SOME_UNMAPPED;
+ }
done:
talloc_free(memctx);
return NT_STATUS_INVALID_PARAMETER;
}
- if ((map->xid.type != ID_TYPE_UID) && (map->xid.type != ID_TYPE_GID)) {
+ if (map->sid == NULL) {
return NT_STATUS_INVALID_PARAMETER;
}
- if (map->sid == NULL) {
+ switch (map->xid.type) {
+ case ID_TYPE_NOT_SPECIFIED:
+ /*
+ * We need to know if we need a user or group mapping.
+ * Ask the winbindd parent to provide a valid type hint.
+ */
+ DBG_INFO("%s ID_TYPE_NOT_SPECIFIED => ID_REQUIRE_TYPE\n",
+ dom_sid_str_buf(map->sid, &buf));
+ map->status = ID_REQUIRE_TYPE;
+ return NT_STATUS_SOME_NOT_MAPPED;
+
+ case ID_TYPE_BOTH:
+ /*
+ * For now we still require
+ * an explicit type as hint
+ * and don't support ID_TYPE_BOTH
+ */
+ DBG_INFO("%s ID_TYPE_BOTH => ID_REQUIRE_TYPE\n",
+ dom_sid_str_buf(map->sid, &buf));
+ map->status = ID_REQUIRE_TYPE;
+ return NT_STATUS_SOME_NOT_MAPPED;
+
+ case ID_TYPE_UID:
+ break;
+
+ case ID_TYPE_GID:
+ break;
+
+ default:
return NT_STATUS_INVALID_PARAMETER;
}
hwmtype = "GID";
break;
+ case ID_TYPE_BOTH:
+ /*
+ * This is not supported here yet and
+ * already handled in idmap_rw_new_mapping()
+ */
+ FALL_THROUGH;
+ case ID_TYPE_NOT_SPECIFIED:
+ /*
+ * This is handled in idmap_rw_new_mapping()
+ */
+ FALL_THROUGH;
default:
DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
return NT_STATUS_INVALID_PARAMETER;
void *private_data)
{
struct idmap_tdb_common_sids_to_unixids_context *state = private_data;
- size_t i, num_mapped = 0;
+ size_t i, num_mapped = 0, num_required = 0;
NTSTATUS ret = NT_STATUS_OK;
DEBUG(10, ("idmap_tdb_common_sids_to_unixids: "
state->ids[i]);
DBG_DEBUG("idmap_tdb_common_new_mapping returned %s\n",
nt_errstr(ret));
+ if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) {
+ if (state->ids[i]->status == ID_REQUIRE_TYPE) {
+ num_required += 1;
+ continue;
+ }
+ }
if (!NT_STATUS_IS_OK(ret)) {
ret = STATUS_SOME_UNMAPPED;
continue;
} else {
ret = NT_STATUS_OK;
}
+ if (num_required > 0) {
+ ret = STATUS_SOME_UNMAPPED;
+ }
}
return ret;
for (si=0; si < src->num_ids; si++) {
uint32_t di = state->tmp_idx[si];
+ if (src->ids[si].xid.type == ID_TYPE_WB_REQUIRE_TYPE) {
+ /*
+ * This should not happen yet, as we always
+ * do a lookupsids and fill type_hint.
+ *
+ * Make sure we don't expose ID_TYPE_WB_REQUIRE_TYPE
+ * outside of winbindd!
+ */
+ src->ids[si].xid.type = ID_TYPE_NOT_SPECIFIED;
+ }
+
if (src->ids[si].xid.type != ID_TYPE_NOT_SPECIFIED) {
dst->ids[di].xid = src->ids[si].xid;
}
for (i=0; i<num_ids; i++) {
struct id_map *m = id_map_ptrs[i];
+ if (m->status == ID_REQUIRE_TYPE) {
+ ids[i].xid.id = UINT32_MAX;
+ ids[i].xid.type = ID_TYPE_WB_REQUIRE_TYPE;
+ continue;
+ }
+
if (!idmap_unix_id_is_in_range(m->xid.id, dom)) {
DBG_DEBUG("id %"PRIu32" is out of range "
"%"PRIu32"-%"PRIu32" for domain %s\n",
case ID_TYPE_BOTH:
include_gid = true;
break;
+ case ID_TYPE_WB_REQUIRE_TYPE:
+ /*
+ * these are internal between winbindd
+ * parent and child.
+ */
+ smb_panic(__location__);
+ break;
}
if (!include_gid) {