s3:idmap:autorid: rename domainnum to rangenum
[obnox/samba/samba-obnox.git] / source3 / winbindd / idmap_autorid.c
index 08dcc6595f5b6b26127121e7409b7e0905b5fa3f..ad0f32c55be5e1cc22533f98f9988d71a8cb11cc 100644 (file)
@@ -51,7 +51,9 @@ struct autorid_global_config {
 
 struct autorid_domain_config {
        fstring sid;
-       uint32_t domainnum;
+       fstring keystr;
+       uint32_t rangenum;
+       uint32_t multiplier;
        struct autorid_global_config *globalcfg;
 };
 
@@ -62,23 +64,25 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
                                              void *private_data)
 {
        NTSTATUS ret;
-       uint32_t domainnum, hwm;
+       uint32_t rangenum, hwm;
        char *numstr;
        struct autorid_domain_config *cfg;
 
        cfg = (struct autorid_domain_config *)private_data;
 
-       ret = dbwrap_fetch_uint32(db, cfg->sid, &(cfg->domainnum));
+       ret = dbwrap_fetch_uint32_bystring(db, cfg->keystr,
+                                          &(cfg->rangenum));
 
        if (NT_STATUS_IS_OK(ret)) {
                /* entry is already present*/
                return ret;
        }
 
-       DEBUG(10, ("Acquiring new range for domain %s\n", cfg->sid));
+       DEBUG(10, ("Acquiring new range for domain %s (multiplier=%"PRIu32")\n",
+                  cfg->sid, cfg->multiplier));
 
        /* fetch the current HWM */
-       ret = dbwrap_fetch_uint32(db, HWM, &hwm);
+       ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(1, ("Fatal error while fetching current "
                          "HWM value: %s\n", nt_errstr(ret)));
@@ -94,7 +98,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
        }
 
        /* increase the HWM */
-       ret = dbwrap_change_uint32_atomic(db, HWM, &domainnum, 1);
+       ret = dbwrap_change_uint32_atomic_bystring(db, HWM, &rangenum, 1);
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(1, ("Fatal error while fetching a new "
                          "domain range value!\n"));
@@ -102,21 +106,21 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
        }
 
        /* store away the new mapping in both directions */
-       ret = dbwrap_store_uint32(db, cfg->sid, domainnum);
+       ret = dbwrap_store_uint32_bystring(db, cfg->keystr, rangenum);
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(1, ("Fatal error while storing new "
                          "domain->range assignment!\n"));
                goto error;
        }
 
-       numstr = talloc_asprintf(db, "%u", domainnum);
+       numstr = talloc_asprintf(db, "%u", rangenum);
        if (!numstr) {
                ret = NT_STATUS_NO_MEMORY;
                goto error;
        }
 
        ret = dbwrap_store_bystring(db, numstr,
-                       string_term_tdb_data(cfg->sid), TDB_INSERT);
+                       string_term_tdb_data(cfg->keystr), TDB_INSERT);
 
        talloc_free(numstr);
        if (!NT_STATUS_IS_OK(ret)) {
@@ -124,10 +128,11 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
                          "new domain->range assignment!\n"));
                goto error;
        }
-       DEBUG(5, ("Acquired new range #%d for domain %s\n",
-                 domainnum, cfg->sid));
+       DEBUG(5, ("Acquired new range #%d for domain %s "
+                 "(multiplier=%"PRIu32")\n", rangenum, cfg->keystr,
+                 cfg->multiplier));
 
-       cfg->domainnum = domainnum;
+       cfg->rangenum = rangenum;
 
        return NT_STATUS_OK;
 
@@ -146,7 +151,15 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
         * if it is not found create a mapping in a transaction unless
         * read-only mode has been set
         */
-       ret = dbwrap_fetch_uint32(autorid_db, dom->sid, &(dom->domainnum));
+       if (dom->multiplier > 0) {
+               snprintf(dom->keystr, FSTRING_LEN, "%s#%"PRIu32, dom->sid,
+                       dom->multiplier);
+       } else {
+               fstrcpy(dom->keystr, dom->sid);
+       }
+
+       ret = dbwrap_fetch_uint32_bystring(autorid_db, dom->keystr,
+                                          &(dom->rangenum));
 
        if (!NT_STATUS_IS_OK(ret)) {
                if (read_only) {
@@ -156,8 +169,8 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
                              idmap_autorid_get_domainrange_action, dom);
        }
 
-       DEBUG(10, ("Using range #%d for domain %s\n", dom->domainnum,
-                  dom->sid));
+       DEBUG(10, ("Using range #%d for domain %s (multiplier=%"PRIu32")\n",
+                  dom->rangenum, dom->sid, dom->multiplier));
 
        return ret;
 }
@@ -206,7 +219,7 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
        }
 
        xid->id = globalcfg->minvalue +
-                 globalcfg->rangesize * domaincfg.domainnum +
+                 globalcfg->rangesize * domaincfg.rangenum +
                  xid->id;
 
        DEBUG(10, ("Returned new %s %d from allocation range\n",
@@ -243,10 +256,13 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
                                        struct id_map *map)
 {
        uint32_t range;
-       TDB_DATA data;
+       uint32_t multiplier = 0;
+       TDB_DATA data = tdb_null;
        char *keystr;
        struct dom_sid sid;
        NTSTATUS status;
+       bool ok;
+       const char *q = NULL;
 
        /* can this be one of our ids? */
        if (map->xid.id < cfg->minvalue) {
@@ -296,18 +312,31 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
                return idmap_autorid_map_id_to_sid(dom, map);
        }
 
-       string_to_sid(&sid, (const char *)data.dptr);
+       ok = dom_sid_parse_endp((const char *)data.dptr, &sid, &q);
        TALLOC_FREE(data.dptr);
+       if (!ok) {
+               map->status = ID_UNKNOWN;
+               return NT_STATUS_OK;
+       }
+       if (q != NULL)
+               if (sscanf(q+1, "%"SCNu32, &multiplier) != 1) {
+                       DEBUG(10, ("Multiplier not found! "
+                                  "ignoring mapping request\n"));
+                       map->status = ID_UNKNOWN;
+                       return NT_STATUS_OK;
+               }
 
        sid_compose(map->sid, &sid,
                    (map->xid.id - cfg->minvalue -
-                    range * cfg->rangesize));
+                    range * cfg->rangesize + (cfg->rangesize * multiplier)));
 
        /* We **really** should have some way of validating
           the SID exists and is the correct type here.  But
           that is a deficiency in the idmap_rid design. */
 
        map->status = ID_MAPPED;
+       map->xid.type = ID_TYPE_BOTH;
+
        return NT_STATUS_OK;
 }
 
@@ -323,15 +352,10 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 
        sid_peek_rid(map->sid, &rid);
 
-       /* if the rid is higher than the size of the range, we cannot map it */
-       if (rid >= global->rangesize) {
-               map->status = ID_UNKNOWN;
-               DEBUG(2, ("RID %d is larger then size of range (%d), "
-                         "user cannot be mapped\n", rid, global->rangesize));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
        map->xid.id = global->minvalue +
-           (global->rangesize * domain->domainnum)+rid;
+           (global->rangesize * domain->rangenum) + rid -
+           (global->rangesize * domain->multiplier);
+       map->xid.type = ID_TYPE_BOTH;
 
        /* We **really** should have some way of validating
           the SID exists and is the correct type here.  But
@@ -435,7 +459,11 @@ static NTSTATUS idmap_autorid_map_sid_to_id(struct idmap_domain *dom,
                   sid_string_dbg(map->sid)));
 
        /* create new mapping */
-       dbwrap_transaction_start(ctx->db);
+       res = dbwrap_transaction_start(ctx->db);
+       if (res != 0) {
+               DEBUG(2, ("transaction_start failed\n"));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
 
        ret = idmap_tdb_common_new_mapping(dom, map);
 
@@ -550,6 +578,9 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
                domaincfg.globalcfg = global;
                sid_to_fstring(domaincfg.sid, &domainsid);
 
+               /* Calculate multiplier for multi-range support */
+               domaincfg.multiplier = rid / (global->rangesize);
+
                ret = idmap_autorid_get_domainrange(&domaincfg, dom->read_only);
 
                /* read-only mode and a new domain range would be required? */
@@ -601,9 +632,9 @@ static NTSTATUS idmap_autorid_init_hwm(const char *hwm) {
        NTSTATUS status;
        uint32_t hwmval;
 
-       status = dbwrap_fetch_uint32(autorid_db, hwm, &hwmval);
+       status = dbwrap_fetch_uint32_bystring(autorid_db, hwm, &hwmval);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))  {
-               status = dbwrap_trans_store_int32(autorid_db, hwm, 0);
+               status = dbwrap_trans_store_int32_bystring(autorid_db, hwm, 0);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0,
                              ("Unable to initialise HWM (%s) in autorid "
@@ -839,7 +870,7 @@ static NTSTATUS idmap_autorid_initialize(struct idmap_domain *dom)
        /* read previously stored config and current HWM */
        storedconfig = idmap_autorid_loadconfig(talloc_tos());
 
-       status = dbwrap_fetch_uint32(autorid_db, HWM, &hwm);
+       status = dbwrap_fetch_uint32_bystring(autorid_db, HWM, &hwm);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Fatal error while fetching current "
                          "HWM value: %s\n", nt_errstr(status)));