mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
277 lines
7.0 KiB
C
277 lines
7.0 KiB
C
|
/*
|
||
|
* idmap_autorid_tdb: This file contains common code used by
|
||
|
* idmap_autorid and net idmap autorid utilities. The common
|
||
|
* code provides functions for performing various operations
|
||
|
* on autorid.tdb
|
||
|
*
|
||
|
* Copyright (C) Christian Ambach, 2010-2012
|
||
|
* Copyright (C) Atul Kulkarni, 2013
|
||
|
* Copyright (C) Michael Adam, 2012-2013
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "idmap_autorid_tdb.h"
|
||
|
|
||
|
static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
|
||
|
void *private_data)
|
||
|
{
|
||
|
NTSTATUS ret;
|
||
|
uint32_t rangenum, hwm;
|
||
|
char *numstr;
|
||
|
struct autorid_range_config *range;
|
||
|
|
||
|
range = (struct autorid_range_config *)private_data;
|
||
|
|
||
|
ret = dbwrap_fetch_uint32_bystring(db, range->keystr,
|
||
|
&(range->rangenum));
|
||
|
|
||
|
if (NT_STATUS_IS_OK(ret)) {
|
||
|
/* entry is already present*/
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
DEBUG(10, ("Acquiring new range for domain %s "
|
||
|
"(domain_range_index=%"PRIu32")\n",
|
||
|
range->domsid, range->domain_range_index));
|
||
|
|
||
|
/* fetch the current 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)));
|
||
|
ret = NT_STATUS_INTERNAL_ERROR;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/* do we have a range left? */
|
||
|
if (hwm >= range->globalcfg->maxranges) {
|
||
|
DEBUG(1, ("No more domain ranges available!\n"));
|
||
|
ret = NT_STATUS_NO_MEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/* increase the HWM */
|
||
|
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"));
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/* store away the new mapping in both directions */
|
||
|
ret = dbwrap_store_uint32_bystring(db, range->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", rangenum);
|
||
|
if (!numstr) {
|
||
|
ret = NT_STATUS_NO_MEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = dbwrap_store_bystring(db, numstr,
|
||
|
string_term_tdb_data(range->keystr), TDB_INSERT);
|
||
|
|
||
|
talloc_free(numstr);
|
||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||
|
DEBUG(1, ("Fatal error while storing "
|
||
|
"new domain->range assignment!\n"));
|
||
|
goto error;
|
||
|
}
|
||
|
DEBUG(5, ("Acquired new range #%d for domain %s "
|
||
|
"(domain_range_index=%"PRIu32")\n", rangenum, range->keystr,
|
||
|
range->domain_range_index));
|
||
|
|
||
|
range->rangenum = rangenum;
|
||
|
|
||
|
return NT_STATUS_OK;
|
||
|
|
||
|
error:
|
||
|
return ret;
|
||
|
|
||
|
}
|
||
|
|
||
|
NTSTATUS idmap_autorid_get_domainrange(struct db_context *db,
|
||
|
struct autorid_range_config *range,
|
||
|
bool read_only)
|
||
|
{
|
||
|
NTSTATUS ret;
|
||
|
|
||
|
/*
|
||
|
* try to find mapping without locking the database,
|
||
|
* if it is not found create a mapping in a transaction unless
|
||
|
* read-only mode has been set
|
||
|
*/
|
||
|
if (range->domain_range_index > 0) {
|
||
|
snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32,
|
||
|
range->domsid, range->domain_range_index);
|
||
|
} else {
|
||
|
fstrcpy(range->keystr, range->domsid);
|
||
|
}
|
||
|
|
||
|
ret = dbwrap_fetch_uint32_bystring(db, range->keystr,
|
||
|
&(range->rangenum));
|
||
|
|
||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||
|
if (read_only) {
|
||
|
return NT_STATUS_NOT_FOUND;
|
||
|
}
|
||
|
ret = dbwrap_trans_do(db,
|
||
|
idmap_autorid_get_domainrange_action, range);
|
||
|
}
|
||
|
|
||
|
range->low_id = range->globalcfg->minvalue
|
||
|
+ range->rangenum * range->globalcfg->rangesize;
|
||
|
|
||
|
DEBUG(10, ("Using range #%d for domain %s "
|
||
|
"(domain_range_index=%"PRIu32", low_id=%"PRIu32")\n",
|
||
|
range->rangenum, range->domsid, range->domain_range_index,
|
||
|
range->low_id));
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* initialize the given HWM to 0 if it does not exist yet */
|
||
|
NTSTATUS idmap_autorid_init_hwm(struct db_context *db, const char *hwm)
|
||
|
{
|
||
|
NTSTATUS status;
|
||
|
uint32_t hwmval;
|
||
|
|
||
|
status = dbwrap_fetch_uint32_bystring(db, hwm, &hwmval);
|
||
|
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
||
|
status = dbwrap_trans_store_int32_bystring(db, hwm, 0);
|
||
|
if (!NT_STATUS_IS_OK(status)) {
|
||
|
DEBUG(0,
|
||
|
("Unable to initialise HWM (%s) in autorid "
|
||
|
"database: %s\n", hwm, nt_errstr(status)));
|
||
|
return NT_STATUS_INTERNAL_DB_ERROR;
|
||
|
}
|
||
|
} else if (!NT_STATUS_IS_OK(status)) {
|
||
|
DEBUG(0, ("unable to fetch HWM (%s) from autorid "
|
||
|
"database: %s\n", hwm, nt_errstr(status)));
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
return NT_STATUS_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* open and initialize the database which stores the ranges for the domains
|
||
|
*/
|
||
|
NTSTATUS idmap_autorid_db_init(const char *path,
|
||
|
TALLOC_CTX *mem_ctx,
|
||
|
struct db_context **db)
|
||
|
{
|
||
|
NTSTATUS status;
|
||
|
|
||
|
if (*db != NULL) {
|
||
|
/* its already open */
|
||
|
return NT_STATUS_OK;
|
||
|
}
|
||
|
|
||
|
/* Open idmap repository */
|
||
|
*db = db_open(mem_ctx, path, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644,
|
||
|
DBWRAP_LOCK_ORDER_1);
|
||
|
|
||
|
if (*db == NULL) {
|
||
|
DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path));
|
||
|
return NT_STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
/* Initialize high water mark for the currently used range to 0 */
|
||
|
|
||
|
status = idmap_autorid_init_hwm(*db, HWM);
|
||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||
|
|
||
|
status = idmap_autorid_init_hwm(*db, ALLOC_HWM_UID);
|
||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||
|
|
||
|
status = idmap_autorid_init_hwm(*db, ALLOC_HWM_GID);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
struct autorid_global_config *idmap_autorid_loadconfig(struct db_context *db,
|
||
|
TALLOC_CTX *ctx)
|
||
|
{
|
||
|
|
||
|
TDB_DATA data;
|
||
|
struct autorid_global_config *cfg;
|
||
|
unsigned long minvalue, rangesize, maxranges;
|
||
|
NTSTATUS status;
|
||
|
|
||
|
status = dbwrap_fetch_bystring(db, ctx, CONFIGKEY, &data);
|
||
|
|
||
|
if (!NT_STATUS_IS_OK(status)) {
|
||
|
DEBUG(10, ("No saved config found\n"));
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
cfg = talloc_zero(ctx, struct autorid_global_config);
|
||
|
if (!cfg) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (sscanf((char *)data.dptr,
|
||
|
"minvalue:%lu rangesize:%lu maxranges:%lu",
|
||
|
&minvalue, &rangesize, &maxranges) != 3) {
|
||
|
DEBUG(1,
|
||
|
("Found invalid configuration data"
|
||
|
"creating new config\n"));
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
cfg->minvalue = minvalue;
|
||
|
cfg->rangesize = rangesize;
|
||
|
cfg->maxranges = maxranges;
|
||
|
|
||
|
DEBUG(10, ("Loaded previously stored configuration "
|
||
|
"minvalue:%d rangesize:%d\n",
|
||
|
cfg->minvalue, cfg->rangesize));
|
||
|
|
||
|
return cfg;
|
||
|
|
||
|
}
|
||
|
|
||
|
NTSTATUS idmap_autorid_saveconfig(struct db_context *db,
|
||
|
struct autorid_global_config *cfg)
|
||
|
{
|
||
|
|
||
|
NTSTATUS status;
|
||
|
TDB_DATA data;
|
||
|
char *cfgstr;
|
||
|
|
||
|
cfgstr =
|
||
|
talloc_asprintf(talloc_tos(),
|
||
|
"minvalue:%u rangesize:%u maxranges:%u",
|
||
|
cfg->minvalue, cfg->rangesize, cfg->maxranges);
|
||
|
|
||
|
if (!cfgstr) {
|
||
|
return NT_STATUS_NO_MEMORY;
|
||
|
}
|
||
|
|
||
|
data = string_tdb_data(cfgstr);
|
||
|
|
||
|
status = dbwrap_trans_store_bystring(db, CONFIGKEY, data, TDB_REPLACE);
|
||
|
|
||
|
talloc_free(cfgstr);
|
||
|
|
||
|
return status;
|
||
|
}
|