s3:idmap_tdb2: give idmap_tdb2_alloc_load() and idmap domain arguemnt
[amitay/samba.git] / source3 / winbindd / idmap_tdb2.c
index 4eebb8e049b3a49c2acee77c65818d3405f9b3d7..dba5690bfbad5532f7506c5b3efc12a126d90ad7 100644 (file)
@@ -37,8 +37,6 @@
 #define DBGC_CLASS DBGC_IDMAP
 
 struct idmap_tdb2_context {
-       uint32_t filter_low_id;
-       uint32_t filter_high_id;
        const char *script; /* script to provide idmaps */
 };
 
@@ -59,7 +57,7 @@ static NTSTATUS idmap_tdb2_new_mapping(struct idmap_domain *dom,
 /* handle to the permanent tdb */
 static struct db_context *idmap_tdb2;
 
-static NTSTATUS idmap_tdb2_alloc_load(void);
+static NTSTATUS idmap_tdb2_alloc_load(struct idmap_domain *dom);
 
 static NTSTATUS idmap_tdb2_load_ranges(void)
 {
@@ -101,7 +99,7 @@ static NTSTATUS idmap_tdb2_load_ranges(void)
 /*
   open the permanent tdb
  */
-static NTSTATUS idmap_tdb2_open_db(void)
+static NTSTATUS idmap_tdb2_open_db(struct idmap_domain *dom)
 {
        char *db_path;
 
@@ -129,14 +127,14 @@ static NTSTATUS idmap_tdb2_open_db(void)
        }
 
        /* load the ranges and high/low water marks */
-       return idmap_tdb2_alloc_load();
+       return idmap_tdb2_alloc_load(dom);
 }
 
 
 /*
   load the idmap allocation ranges and high/low water marks
 */
-static NTSTATUS idmap_tdb2_alloc_load(void)
+static NTSTATUS idmap_tdb2_alloc_load(struct idmap_domain *dom)
 {
        NTSTATUS status;
        uint32 low_id;
@@ -151,10 +149,10 @@ static NTSTATUS idmap_tdb2_alloc_load(void)
        /* Create high water marks for group and user id */
 
        low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_USER);
-       if ((low_id == -1) || (low_id < idmap_tdb2_state.low_uid)) {
+       if ((low_id == -1) || (low_id < dom->low_id)) {
                if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32(
                                             idmap_tdb2, HWM_USER,
-                                            idmap_tdb2_state.low_uid))) {
+                                            dom->low_id))) {
                        DEBUG(0, ("Unable to initialise user hwm in idmap "
                                  "database\n"));
                        return NT_STATUS_INTERNAL_DB_ERROR;
@@ -162,10 +160,10 @@ static NTSTATUS idmap_tdb2_alloc_load(void)
        }
 
        low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_GROUP);
-       if ((low_id == -1) || (low_id < idmap_tdb2_state.low_gid)) {
+       if ((low_id == -1) || (low_id < dom->low_id)) {
                if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32(
                                             idmap_tdb2, HWM_GROUP,
-                                            idmap_tdb2_state.low_gid))) {
+                                            dom->low_id))) {
                        DEBUG(0, ("Unable to initialise group hwm in idmap "
                                  "database\n"));
                        return NT_STATUS_INTERNAL_DB_ERROR;
@@ -241,14 +239,11 @@ static NTSTATUS idmap_tdb2_allocate_id(struct idmap_domain *dom,
        uint32_t high_hwm;
        uint32_t hwm = 0;
        NTSTATUS status;
-       struct idmap_tdb2_context *ctx;
        struct idmap_tdb2_allocate_id_context state;
 
-       status = idmap_tdb2_open_db();
+       status = idmap_tdb2_open_db(dom);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
-
        /* Get current high water mark */
        switch (xid->type) {
 
@@ -267,7 +262,7 @@ static NTSTATUS idmap_tdb2_allocate_id(struct idmap_domain *dom,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       high_hwm = ctx->filter_high_id;
+       high_hwm = dom->high_id;
 
        state.hwm = hwm;
        state.high_hwm = high_hwm;
@@ -332,42 +327,13 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom,
        }
 
        if (strequal(dom->name, "*")) {
-               uid_t low_uid = 0;
-               uid_t high_uid = 0;
-               gid_t low_gid = 0;
-               gid_t high_gid = 0;
-
-               ctx->filter_low_id = 0;
-               ctx->filter_high_id = 0;
-
-               if (lp_idmap_uid(&low_uid, &high_uid)) {
-                       ctx->filter_low_id = low_uid;
-                       ctx->filter_high_id = high_uid;
-               } else {
-                       DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
-               }
-
-               if (lp_idmap_gid(&low_gid, &high_gid)) {
-                       if ((low_gid != low_uid) || (high_gid != high_uid)) {
-                               DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
-                                     " ranges do not agree -- building "
-                                     "intersection\n"));
-                               ctx->filter_low_id = MAX(ctx->filter_low_id,
-                                                        low_gid);
-                               ctx->filter_high_id = MIN(ctx->filter_high_id,
-                                                         high_gid);
-                       }
-               } else {
-                       DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
-               }
-
                ctx->script = lp_parm_const_string(-1, "idmap", "script", NULL);
                if (ctx->script) {
                        DEBUG(1, ("using idmap script '%s'\n", ctx->script));
                }
        } else {
                char *config_option = NULL;
-               const char *range;
+
                config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
                if ( ! config_option) {
                        DEBUG(0, ("Out of memory!\n"));
@@ -375,29 +341,21 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom,
                        goto failed;
                }
 
-               range = lp_parm_const_string(-1, config_option, "range", NULL);
-               if (( ! range) ||
-                   (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2))
-               {
-                       ctx->filter_low_id = 0;
-                       ctx->filter_high_id = 0;
+               ctx->script = lp_parm_const_string(-1, config_option, "script", NULL);
+               if (ctx->script) {
+                       DEBUG(1, ("using idmap script '%s'\n", ctx->script));
                }
 
                talloc_free(config_option);
        }
 
-       if (ctx->filter_low_id > ctx->filter_high_id) {
-               ctx->filter_low_id = 0;
-               ctx->filter_high_id = 0;
-       }
+       dom->private_data = ctx;
 
-       ret = idmap_tdb2_open_db();
+       ret = idmap_tdb2_open_db(dom);
        if (!NT_STATUS_IS_OK(ret)) {
                goto failed;
        }
 
-       dom->private_data = ctx;
-
        return NT_STATUS_OK;
 
 failed:
@@ -527,25 +485,28 @@ static NTSTATUS idmap_tdb2_script(struct idmap_tdb2_context *ctx, struct id_map
 /*
   Single id to sid lookup function. 
 */
-static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_map *map)
+static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_domain *dom, struct id_map *map)
 {
        NTSTATUS ret;
        TDB_DATA data;
        char *keystr;
        NTSTATUS status;
+       struct idmap_tdb2_context *ctx;
 
-       status = idmap_tdb2_open_db();
-       NT_STATUS_NOT_OK_RETURN(status);
 
-       if (!ctx || !map) {
+       if (!dom || !map) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       status = idmap_tdb2_open_db(dom);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
        /* apply filters before checking */
-       if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
-           (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+       if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
                DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
-                               map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+                               map->xid.id, dom->low_id, dom->high_id));
                return NT_STATUS_NONE_MAPPED;
        }
 
@@ -628,17 +589,20 @@ done:
 /*
  Single sid to id lookup function. 
 */
-static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_map *map)
+static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_domain *dom, struct id_map *map)
 {
        NTSTATUS ret;
        TDB_DATA data;
        char *keystr;
        unsigned long rec_id = 0;
+       struct idmap_tdb2_context *ctx;
        TALLOC_CTX *tmp_ctx = talloc_stackframe();
 
-       ret = idmap_tdb2_open_db();
+       ret = idmap_tdb2_open_db(dom);
        NT_STATUS_NOT_OK_RETURN(ret);
 
+       ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
        keystr = sid_string_talloc(tmp_ctx, map->sid);
        if (keystr == NULL) {
                DEBUG(0, ("Out of memory!\n"));
@@ -668,14 +632,10 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m
                }
 
                /* apply filters before returning result */
-               if ((ctx->filter_low_id
-                    && (map->xid.id < ctx->filter_low_id)) ||
-                   (ctx->filter_high_id
-                    && (map->xid.id > ctx->filter_high_id))) {
+               if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
                        DEBUG(5, ("Script returned id (%u) out of range "
                                  "(%u - %u). Filtered!\n",
-                                 map->xid.id,
-                                 ctx->filter_low_id, ctx->filter_high_id));
+                                 map->xid.id, dom->low_id, dom->high_id));
                        ret = NT_STATUS_NONE_MAPPED;
                        goto done;
                }
@@ -716,10 +676,9 @@ static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_m
        }
 
        /* apply filters before returning result */
-       if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
-           (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+       if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
                DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
-                               map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+                               map->xid.id, dom->low_id, dom->high_id));
                ret = NT_STATUS_NONE_MAPPED;
        }
 
@@ -733,7 +692,6 @@ done:
 */
 static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
 {
-       struct idmap_tdb2_context *ctx;
        NTSTATUS ret;
        int i;
 
@@ -742,10 +700,8 @@ static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_m
                ids[i]->status = ID_UNKNOWN;
        }
 
-       ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
-
        for (i = 0; ids[i]; i++) {
-               ret = idmap_tdb2_id_to_sid(ctx, ids[i]);
+               ret = idmap_tdb2_id_to_sid(dom, ids[i]);
                if ( ! NT_STATUS_IS_OK(ret)) {
 
                        /* if it is just a failed mapping continue */
@@ -785,7 +741,6 @@ static NTSTATUS idmap_tdb2_sids_to_unixids_action(struct db_context *db,
 {
        struct idmap_tdb2_sids_to_unixids_context *state;
        int i;
-       struct idmap_tdb2_context *ctx;
        NTSTATUS ret = NT_STATUS_OK;
 
        state = (struct idmap_tdb2_sids_to_unixids_context *)private_data;
@@ -795,10 +750,6 @@ static NTSTATUS idmap_tdb2_sids_to_unixids_action(struct db_context *db,
                   state->dom->name,
                   state->allocate_unmapped ? "yes" : "no"));
 
-       ctx = talloc_get_type(state->dom->private_data,
-                             struct idmap_tdb2_context);
-
-
        for (i = 0; state->ids[i]; i++) {
                if ((state->ids[i]->status == ID_UNKNOWN) ||
                    /* retry if we could not map in previous run: */
@@ -806,7 +757,7 @@ static NTSTATUS idmap_tdb2_sids_to_unixids_action(struct db_context *db,
                {
                        NTSTATUS ret2;
 
-                       ret2 = idmap_tdb2_sid_to_id(ctx, state->ids[i]);
+                       ret2 = idmap_tdb2_sid_to_id(state->dom, state->ids[i]);
                        if (!NT_STATUS_IS_OK(ret2)) {
 
                                /* if it is just a failed mapping, continue */
@@ -857,7 +808,7 @@ static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_m
 
        ret = idmap_tdb2_sids_to_unixids_action(idmap_tdb2, &state);
 
-       if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) {
+       if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED) && !dom->read_only) {
                state.allocate_unmapped = true;
                ret = dbwrap_trans_do(idmap_tdb2,
                                      idmap_tdb2_sids_to_unixids_action,