diff options
-rw-r--r-- | source3/sam/idmap_tdb.c | 206 |
1 files changed, 115 insertions, 91 deletions
diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c index ad7c5c2e6c..b8d0ae1211 100644 --- a/source3/sam/idmap_tdb.c +++ b/source3/sam/idmap_tdb.c @@ -117,49 +117,8 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) return NT_STATUS_OK; } -/* Set the HWM if necessary */ -/* This is not transaction safe, but the tdb should be locked - in db_set_mapping anyway. */ -static NTSTATUS db_adjust_hwm(unid_t id, int id_type) -{ - int32 hwm; - - switch (id_type & ID_TYPEMASK) { - case ID_USERID: - hwm = tdb_fetch_int32(idmap_tdb, HWM_USER); - if (hwm == -1) - return NT_STATUS_INTERNAL_DB_ERROR; - - if ((id.uid < hwm) || (id.uid > idmap_state.uid_high)) - return NT_STATUS_OK; - - if (tdb_store_int32(idmap_tdb, HWM_USER, id.uid+1) != 0) - return NT_STATUS_UNSUCCESSFUL; - - break; - - case ID_GROUPID: - hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); - if (hwm == -1) - return NT_STATUS_INTERNAL_DB_ERROR; - - if ((id.gid < hwm) || (id.gid > idmap_state.gid_high)) - return NT_STATUS_OK; - - if (tdb_store_int32(idmap_tdb, HWM_GROUP, id.gid+1) != 0) - return NT_STATUS_UNSUCCESSFUL; - - break; - - default: - return NT_STATUS_INVALID_PARAMETER; - } - - return NT_STATUS_OK; -} - /* Get a sid from an id */ -static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) { TDB_DATA key, data; fstring keystr; @@ -193,14 +152,13 @@ static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) return ret; } -/* Get an id from a sid */ -static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) + +static NTSTATUS internal_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { - TDB_DATA data, key; - fstring keystr; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if (!sid || !id || !id_type) return NT_STATUS_INVALID_PARAMETER; + fstring keystr; + TDB_DATA key, data; + int type = *id_type & ID_TYPEMASK; /* Check if sid is present in database */ sid_to_string(keystr, sid); @@ -209,69 +167,135 @@ static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) key.dsize = strlen(keystr) + 1; data = tdb_fetch(idmap_tdb, key); + if (!data.dptr) + return ret; - if (data.dptr) { - int type = *id_type & ID_TYPEMASK; + if (type == ID_EMPTY || type == ID_USERID) { fstring scanstr; + /* Parse and return existing uid */ + fstrcpy(scanstr, "UID %d"); + + if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) { + /* uid ok? */ + if (type == ID_EMPTY) { + *id_type = ID_USERID; + } + ret = NT_STATUS_OK; + } + } + + if (!NT_STATUS_IS_OK(ret) + && (type == ID_EMPTY || type == ID_GROUPID)) { + fstring scanstr; + /* Parse and return existing gid */ + fstrcpy(scanstr, "GID %d"); + + if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) { + /* gid ok? */ + if (type == ID_EMPTY) { + *id_type = ID_GROUPID; + } + ret = NT_STATUS_OK; + } + } + + SAFE_FREE(data.dptr); - if (type == ID_EMPTY || type == ID_USERID) { - /* Parse and return existing uid */ - fstrcpy(scanstr, "UID %d"); + return ret; +} - if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) { - /* uid ok? */ - if (type == ID_EMPTY) { - *id_type = ID_USERID; - } - ret = NT_STATUS_OK; - goto idok; - } +/* Get a sid from an id */ +static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type_in) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + int id_type = id_type_in & ID_TYPEMASK; + unid_t id_tmp = id; + int id_type_tmp = id_type; + + ret = internal_get_sid_from_id(sid, id, id_type); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + + ret = internal_get_id_from_sid(&id_tmp, &id_type_tmp, sid); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + if (id_type_tmp != id_type) { + return NT_STATUS_UNSUCCESSFUL; + } else if (id_type == ID_USERID) { + if (id_tmp.uid != id.uid) { + return NT_STATUS_UNSUCCESSFUL; + } + } else if (id_type == ID_GROUPID) { + if (id_tmp.gid != id.gid) { + return NT_STATUS_UNSUCCESSFUL; } + } else { + return NT_STATUS_UNSUCCESSFUL; + } + return ret; +} +/* Get an id from a sid */ +static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (type == ID_EMPTY || type == ID_GROUPID) { - /* Parse and return existing gid */ - fstrcpy(scanstr, "GID %d"); + if (!sid || !id || !id_type) return NT_STATUS_INVALID_PARAMETER; - if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) { - /* gid ok? */ - if (type == ID_EMPTY) { - *id_type = ID_GROUPID; - } - ret = NT_STATUS_OK; + ret = internal_get_id_from_sid(id, id_type, sid); + if (NT_STATUS_IS_OK(ret)) { + DOM_SID sid_tmp; + ret = internal_get_sid_from_id(&sid_tmp, *id, *id_type); + if (NT_STATUS_IS_OK(ret)) { + if (!sid_equal(&sid_tmp, sid)) { + return ret = NT_STATUS_UNSUCCESSFUL; } } -idok: - SAFE_FREE(data.dptr); + } - } else if (!(*id_type & ID_NOMAP) && + if (!(*id_type & ID_NOMAP) && (!NT_STATUS_IS_OK(ret)) && (((*id_type & ID_TYPEMASK) == ID_USERID) || (*id_type & ID_TYPEMASK) == ID_GROUPID)) { - - /* Allocate a new id for this sid */ - ret = db_allocate_id(id, *id_type); - if (NT_STATUS_IS_OK(ret)) { - fstring keystr2; - + TDB_DATA sid_data; + TDB_DATA ugid_data; + fstring sid_string; + + sid_to_string(sid_string, sid); + + sid_data.dptr = sid_string; + sid_data.dsize = strlen(sid_string)+1; + + do { + fstring ugid_str; + /* Allocate a new id for this sid */ + ret = db_allocate_id(id, *id_type); + if (!NT_STATUS_IS_OK(ret)) + break; + /* Store new id */ if (*id_type & ID_USERID) { - slprintf(keystr2, sizeof(keystr2), "UID %d", (*id).uid); + slprintf(ugid_str, sizeof(ugid_str), "UID %d", (*id).uid); } else { - slprintf(keystr2, sizeof(keystr2), "GID %d", (*id).gid); + slprintf(ugid_str, sizeof(ugid_str), "GID %d", (*id).gid); } + + ugid_data.dptr = ugid_str; + ugid_data.dsize = strlen(ugid_str) + 1; - data.dptr = keystr2; - data.dsize = strlen(keystr2) + 1; - - if (tdb_store(idmap_tdb, key, data, TDB_REPLACE) == -1) { - /* TODO: print tdb error !! */ - return NT_STATUS_UNSUCCESSFUL; + /* Store the UID side */ + if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) { + ret = NT_STATUS_OK; + break; } - if (tdb_store(idmap_tdb, data, key, TDB_REPLACE) == -1) { + ret = NT_STATUS_UNSUCCESSFUL; + } while (idmap_tdb->ecode == TDB_ERR_EXISTS); + + if (NT_STATUS_IS_OK(ret)) { + if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) { /* TODO: print tdb error !! */ return NT_STATUS_UNSUCCESSFUL; } - - ret = NT_STATUS_OK; } } @@ -326,7 +350,7 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) DEBUG(0, ("idb_set_mapping: tdb_store 2 error: %s\n", tdb_errorstr(idmap_tdb))); return NT_STATUS_UNSUCCESSFUL; } - return db_adjust_hwm(id, id_type); + return NT_STATUS_OK; } /***************************************************************************** |