return ret;
}
+static bool idmap_autorid_sid_is_special(struct dom_sid *sid)
+{
+ bool match;
+
+ match = sid_check_is_in_wellknown_domain(sid);
+ if (match) {
+ return true;
+ }
+
+ return false;
+}
+
+static NTSTATUS idmap_autorid_sid_to_id_special(struct idmap_domain *dom,
+ struct id_map *map)
+{
+ struct idmap_tdb_common_context *common =
+ talloc_get_type_abort(dom->private_data,
+ struct idmap_tdb_common_context);
+ uint32_t count;
+ struct autorid_range_config range;
+ NTSTATUS status;
+ uint32_t free_id;
+
+ status = idmap_autorid_get_alloc_range(dom, &range);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Take the next free ID, counting from the top */
+ free_id = 0;
+ for (count = 0; count < IDMAP_AUTORID_ALLOC_RESERVED; count++) {
+ struct id_map test_map;
+ struct dom_sid sid;
+
+ test_map.sid = &sid;
+ test_map.xid.type = map->xid.type;
+ test_map.xid.id = range.high_id - count;
+ test_map.status = ID_UNKNOWN;
+
+ status = idmap_tdb_common_unixid_to_sid(dom, &test_map);
+ if (NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, status)) {
+ free_id = test_map.xid.id;
+ break;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ /* error - get out */
+ return status;
+ }
+
+ /* mapping exists - try next ID */
+ }
+
+ if (free_id == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ map->status = ID_MAPPED;
+ map->xid.id = free_id;
+
+ status = common->rw_ops->set_mapping(dom, map);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2, ("Error storing new mapping: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+struct idmap_autorid_sid_to_id_alloc_ctx {
+ struct idmap_domain *dom;
+ struct id_map *map;
+};
+
+static NTSTATUS idmap_autorid_sid_to_id_alloc_action(
+ struct db_context *db,
+ void *private_data)
+{
+ struct idmap_autorid_sid_to_id_alloc_ctx *ctx;
+
+ ctx = (struct idmap_autorid_sid_to_id_alloc_ctx *)private_data;
+
+ if (idmap_autorid_sid_is_special(ctx->map->sid)) {
+ NTSTATUS ret;
+
+ ret = idmap_autorid_sid_to_id_special(ctx->dom, ctx->map);
+ if (NT_STATUS_IS_OK(ret)) {
+ return NT_STATUS_OK;
+ }
+ if (!NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, ret)) {
+ return ret;
+ }
+
+ DEBUG(10, ("Sepecial sid %s not mapped. falling back to "
+ "regular allocation\n",
+ sid_string_dbg(ctx->map->sid)));
+ }
+
+ return idmap_tdb_common_new_mapping(ctx->dom, ctx->map);
+}
+
/*
* map a SID to xid using the idmap_tdb like pool
*/
-static NTSTATUS idmap_autorid_sid_to_id_alloc(struct idmap_domain *dom,
- struct id_map *map,
- struct idmap_tdb_common_context *ctx)
+static NTSTATUS idmap_autorid_sid_to_id_alloc(
+ struct idmap_tdb_common_context *ctx,
+ struct idmap_domain *dom,
+ struct id_map *map)
{
NTSTATUS ret;
- int res;
+ struct idmap_autorid_sid_to_id_alloc_ctx alloc_ctx;
map->status = ID_UNKNOWN;
DEBUG(10, ("Creating new mapping in pool for %s\n",
sid_string_dbg(map->sid)));
- /* create new mapping */
- res = dbwrap_transaction_start(ctx->db);
- if (res != 0) {
- DEBUG(2, ("transaction_start failed\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
+ alloc_ctx.dom = dom;
+ alloc_ctx.map = map;
- ret = idmap_tdb_common_new_mapping(dom, map);
+ ret = dbwrap_trans_do(ctx->db, idmap_autorid_sid_to_id_alloc_action,
+ &alloc_ctx);
if (!NT_STATUS_IS_OK(ret)) {
- if (dbwrap_transaction_cancel(ctx->db) != 0) {
- smb_panic("Cancelling transaction failed");
- }
- map->status = ID_UNMAPPED;
- return ret;
+ DEBUG(1, ("Failed to create a new mapping in alloc range: %s\n",
+ nt_errstr(ret)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- res = dbwrap_transaction_commit(ctx->db);
- if (res == 0) {
- map->status = ID_MAPPED;
- return NT_STATUS_OK;
- }
+ map->status = ID_MAPPED;
+ return NT_STATUS_OK;
+}
+
+static bool idmap_autorid_domsid_is_for_alloc(struct dom_sid *sid)
+{
+ bool match;
- DEBUG(2, ("transaction_commit failed\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ match = sid_check_is_wellknown_domain(sid, NULL);
+ if (match) {
+ return true;
+ }
+ return false;
}
static NTSTATUS idmap_autorid_sid_to_id(struct idmap_tdb_common_context *common,
return NT_STATUS_NONE_MAPPED;
}
- if (sid_check_is_wellknown_domain(&domainsid, NULL)) {
- DEBUG(10, ("SID %s is well-known, using pool\n",
+ if (idmap_autorid_domsid_is_for_alloc(&domainsid)) {
+ DEBUG(10, ("SID %s is for ALLOC range.\n",
sid_string_dbg(map->sid)));
- return idmap_autorid_sid_to_id_alloc(dom, map, common);
+ return idmap_autorid_sid_to_id_alloc(common, dom, map);
}
if (dom_sid_equal(&domainsid, &global_sid_Builtin) && ignore_builtin) {