*id_to_*id call reshape to return NTSTATUS errors
[ira/wip.git] / source3 / sam / idmap_tdb.c
index 8ecf4d6e7eff49923b67237db5435b1df75a939b..ab86eaf4ebf76c6f06522b15dbc76f1c126eb231 100644 (file)
@@ -60,7 +60,7 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type)
                        }
 
                        if (hwm > idmap_state.uid_high) {
-                               DEBUG(0, ("idmap Fatal Error: UID range full!!\n"));
+                               DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high));
                                return NT_STATUS_UNSUCCESSFUL;
                        }
 
@@ -75,7 +75,7 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type)
                        }
 
                        if (hwm > idmap_state.gid_high) {
-                               DEBUG(0, ("idmap Fatal Error: GID range full!!\n"));
+                               DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %u)\n", idmap_state.gid_high));
                                return NT_STATUS_UNSUCCESSFUL;
                        }
 
@@ -211,9 +211,9 @@ idok:
        return ret;
 }
 
-static NTSTATUS db_set_mapping(DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
 {
-       TDB_DATA ksid, kid;
+       TDB_DATA ksid, kid, data;
        fstring ksidstr;
        fstring kidstr;
 
@@ -224,7 +224,6 @@ static NTSTATUS db_set_mapping(DOM_SID *sid, unid_t id, int id_type)
        ksid.dptr = ksidstr;
        ksid.dsize = strlen(ksidstr) + 1;
 
-       id_type &= ID_TYPEMASK;
        if (id_type & ID_USERID) {
                slprintf(kidstr, sizeof(kidstr), "UID %d", id.uid);
        } else if (id_type & ID_GROUPID) {
@@ -236,12 +235,26 @@ static NTSTATUS db_set_mapping(DOM_SID *sid, unid_t id, int id_type)
        kid.dptr = kidstr;
        kid.dsize = strlen(kidstr) + 1;
 
+       /* *DELETE* prevoius mappings if any.
+        * This is done both SID and [U|G]ID passed in */
+       
+       data = tdb_fetch(idmap_tdb, ksid);
+       if (data.dptr) {
+               tdb_delete(idmap_tdb, data);
+               tdb_delete(idmap_tdb, ksid);
+       }
+       data = tdb_fetch(idmap_tdb, kid);
+       if (data.dptr) {
+               tdb_delete(idmap_tdb, data);
+               tdb_delete(idmap_tdb, kid);
+       }
+
        if (tdb_store(idmap_tdb, ksid, kid, TDB_INSERT) == -1) {
-               /* TODO: print tdb error !! */
+               DEBUG(0, ("idb_set_mapping: tdb_store 1 error: %s\n", tdb_errorstr(idmap_tdb)));
                return NT_STATUS_UNSUCCESSFUL;
        }
        if (tdb_store(idmap_tdb, kid, ksid, TDB_INSERT) == -1) {
-               /* TODO: print tdb error !! */
+               DEBUG(0, ("idb_set_mapping: tdb_store 2 error: %s\n", tdb_errorstr(idmap_tdb)));
                return NT_STATUS_UNSUCCESSFUL;
        }
        return NT_STATUS_OK;
@@ -253,35 +266,76 @@ static NTSTATUS db_set_mapping(DOM_SID *sid, unid_t id, int id_type)
 static NTSTATUS db_idmap_init(void)
 {
        SMB_STRUCT_STAT stbuf;
+       char *tdbfile = NULL;
+       int32 version;
+       BOOL tdb_is_new = False;
 
-       /* move to the new database on first startup */
+       /* use the old database if present */
        if (!file_exist(lock_path("idmap.tdb"), &stbuf)) {
                if (file_exist(lock_path("winbindd_idmap.tdb"), &stbuf)) {
-                       DEBUG(0, ("idmap_init: winbindd_idmap.tdb is present and idmap.tdb is not!\nPlease RUN winbindd first to convert the db to the new format!\n"));
-                       return NT_STATUS_UNSUCCESSFUL;
+                       DEBUG(0, ("idmap_init: using winbindd_idmap.tdb file!\n"));
+                       tdbfile = strdup(lock_path("winbindd_idmap.tdb"));
+                       if (!tdbfile) {
+                               DEBUG(0, ("idmap_init: out of memory!\n"));
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               } else {
+                       tdb_is_new = True;
+               }
+       }
+       if (!tdbfile) {
+               tdbfile = strdup(lock_path("idmap.tdb"));
+               if (!tdbfile) {
+                       DEBUG(0, ("idmap_init: out of memory!\n"));
+                       return NT_STATUS_NO_MEMORY;
                }
        }
 
        /* Open tdb cache */
-       if (!(idmap_tdb = tdb_open_log(lock_path("idmap.tdb"), 0,
+       if (!(idmap_tdb = tdb_open_log(tdbfile, 0,
                                       TDB_DEFAULT, O_RDWR | O_CREAT,
                                       0600))) {
                DEBUG(0, ("idmap_init: Unable to open idmap database\n"));
+               SAFE_FREE(tdbfile);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       /* Create high water marks for group and user id */
-       if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) {
-               if (tdb_store_int32(idmap_tdb, HWM_USER, idmap_state.uid_low) == -1) {
-                       DEBUG(0, ("idmap_init: Unable to initialise user hwm in idmap database\n"));
+       SAFE_FREE(tdbfile);
+
+       /* check against earlier versions */
+       if (tdb_is_new) {
+               /* TODO: delete the file if this fail */
+               tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION);
+       } else {
+               version = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
+               if (version != IDMAP_VERSION) {
+                       DEBUG(0, ("idmap_init: Unable to open idmap database, it's in an old format!\n"));
                        return NT_STATUS_INTERNAL_DB_ERROR;
                }
        }
 
-       if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) {
-               if (tdb_store_int32(idmap_tdb, HWM_GROUP, idmap_state.gid_low) == -1) {
-                       DEBUG(0, ("idmap_init: Unable to initialise group hwm in idmap database\n"));
-                       return NT_STATUS_INTERNAL_DB_ERROR;
+       /* Create high water marks for group and user id */
+       if (!lp_idmap_uid(&idmap_state.uid_low, &idmap_state.uid_high)) {
+               DEBUG(0, ("idmap uid range missing or invalid\n"));
+               DEBUGADD(0, ("idmap will be unable to map foreign SIDs\n"));
+       } else {
+               if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) {
+                       if (tdb_store_int32(idmap_tdb, HWM_USER, idmap_state.uid_low) == -1) {
+                               DEBUG(0, ("idmap_init: Unable to initialise user hwm in idmap database\n"));
+                               return NT_STATUS_INTERNAL_DB_ERROR;
+                       }
+               }
+       }
+
+       if (!lp_idmap_gid(&idmap_state.gid_low, &idmap_state.gid_high)) {
+               DEBUG(0, ("idmap gid range missing or invalid\n"));
+               DEBUGADD(0, ("idmap will be unable to map foreign SIDs\n"));
+       } else {
+               if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) {
+                       if (tdb_store_int32(idmap_tdb, HWM_GROUP, idmap_state.gid_low) == -1) {
+                               DEBUG(0, ("idmap_init: Unable to initialise group hwm in idmap database\n"));
+                               return NT_STATUS_INTERNAL_DB_ERROR;
+                       }
                }
        }
 
@@ -387,4 +441,3 @@ NTSTATUS idmap_reg_tdb(struct idmap_methods **meth)
 
        return NT_STATUS_OK;
 }
-