Hello Tim, hello everyone,
in February I have posted a winbind idmap recovery tool ("wbidmap")
for dumping and restoring the id mapping tdb, plus a patch for
winbindd_idmap.c to enable logging of newly created mappings in
a way that can be replayed by wbidmap.
Has this approach been considered in the meanwhile?
No, I won't ask for getting it into 2.2.4 at this point :)
But in any case, for everyone who found it useful, I have updated
it for 2.2.4 (int32 instead of int value byte order, the
IDMAP_VERSION key, and the modified SID format).
Attached is the source file wbidmap.c, a patch for Makefile.in
such that it can be built using "make bin/wbidmap", and the logging
patch against current winbindd_idmap.c.
Cheers!
Michael
/*
Unix SMB/Netbios implementation.
Version 2.0
Winbind idmap tdb manipulation program.
Michael Steffens <[EMAIL PROTECTED]>
Copyright (C) Hewlett-Packard 2002
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#define IDMAP_VERSION_KEY "IDMAP_VERSION"
#define IDMAP_VERSION 2
/* High water mark keys */
#define HWM_GROUP "GROUP HWM"
#define HWM_USER "USER HWM"
/* idmap TDB key/data types */
#define TYPE_UNKNOWN 0
#define TYPE_HWM 1
#define TYPE_UID 2
#define TYPE_SID 3
#define TYPE_VERSION 4
/* Globals */
static TDB_CONTEXT *idmap_tdb = NULL;
static char *tdb_file = NULL;
static BOOL do_preview = False;
static BOOL do_dump = False;
static BOOL do_create = False;
static BOOL do_merge = False;
static BOOL do_overwrite = False;
static BOOL do_terminate = False;
/* We need a termination signal handler to avoid getting interrupted
while inserting/deleting idmap pairs */
static void termination_handler(int signum)
{
do_terminate = True;
}
/* Print program usage */
static void usage(void)
{
fprintf(stderr, "Usage: wbidmap [-f file] -d | -c | -m[op]\n");
fprintf(stderr, "\t-f file\t\t\tuse file as mapping TDB (default %s)\n",
lock_path("winbindd_idmap.tdb"));
fprintf(stderr, "\t-d\t\t\tdump TDB mappings to stdout\n");
fprintf(stderr, "\t-c\t\t\tcreate new mapping TDB from stdin\n");
fprintf(stderr, "\t-m\t\t\tmerge stdin into mapping TDB\n");
fprintf(stderr, "\t-o\t\t\toverwrite conflicting mappings in TDB on merge\n");
fprintf(stderr, "\t-p\t\t\tpreview, do not change TDB on merge\n");
}
/* Return True if s is a valid decimal as UID/GID or RID value. No leading
zeroes are allowed, unless the entire number is zero. s is parsed until
a '\0' character is encountered, but at most "size" characters. */
BOOL is_decimal(const char *s, int size)
{
const char *c;
int i = 0;
if (size <= 0)
return False;
c = s;
do {
if (strchr("0123456789", *c) == 0)
return False;
c++;
i++;
} while (i < size && *c);
/* accept leading '0' only if it's the only didgit */
if (*s == '0' && i > 1)
return False;
return True;
}
/* Parse data for type, whether it's UID/GID, SID, or HWM. UID and GID
are of same type TYPE_UID (read it as "UnixID" :-), and are distinguished
via isgroup. For TYPE_UID the numerical ID is returned in value. */
int type_tdb_data(TDB_DATA data, BOOL *isgroup, int *value)
{
int i;
if (!data.dptr)
return TYPE_UNKNOWN;
if (data.dsize == (strlen(IDMAP_VERSION_KEY) + 1) && strncmp(data.dptr, IDMAP_VERSION_KEY, strlen(IDMAP_VERSION_KEY)) == 0) {
return TYPE_VERSION;
}
if (data.dsize == (strlen(HWM_USER) + 1) && strncmp(data.dptr, HWM_USER, strlen(HWM_USER)) == 0) {
if (isgroup)
*isgroup = False;
return TYPE_HWM;
}
if (data.dsize == (strlen(HWM_GROUP) + 1) && strncmp(data.dptr, HWM_GROUP, strlen(HWM_GROUP)) == 0) {
if (isgroup)
*isgroup = True;
return TYPE_HWM;
}
if (data.dsize > 5 && strncmp(data.dptr, "UID ", 4) == 0 && is_decimal(data.dptr + 4, data.dsize - 4)) {
if (value)
*value = strtol(data.dptr + 4, NULL, 10);
if (isgroup)
*isgroup = False;
return TYPE_UID;
}
if (data.dsize > 5 && strncmp(data.dptr, "GID ", 4) == 0 && is_decimal(data.dptr + 4, data.dsize - 4)) {
if (value)
*value = strtol(data.dptr + 4, NULL, 10);
if (isgroup)
*isgroup = True;
return TYPE_UID;
}
if (data.dsize > 3 && strncmp(data.dptr, "S-", 2) == 0) {
for (i = 2; i < data.dsize && data.dptr[i]; i++) {
if (!strchr("-0123456789", data.dptr[i]))
return TYPE_UNKNOWN;
}
return TYPE_SID;
}
return TYPE_UNKNOWN;
}
/* Read and parse one "UID <uid>:<sid>", or "GID <uid>:<sid>"
record from stdin. Lines may have additional colon separated fields, which
are being ignored. Return False on EOF, True otherwise.
Failure is indicated by setting uid_data.dptr and sid_data.dptr to NULL */
BOOL idmap_readline(TDB_DATA *uid_data, TDB_DATA *sid_data, BOOL *isgroup, int *value)
{
static char buf[1024];
char *s1, *s2;
uid_data->dptr = NULL;
sid_data->dptr = NULL;
if (fgets(buf, 1024, stdin) == NULL) {
if (feof(stdin)) {
return False;
} else {
fprintf(stderr, "wbidmap: read error on stdin: %s\n", strerror(errno));
goto fail;
}
}
if (buf[strlen(buf) - 1] == '\n') {
buf[strlen(buf) - 1] = '\0';
} else {
fprintf(stderr, "wbidmap: line too long on stdin: %s\n", buf);
goto fail;
}
if ((s1 = strchr(buf, ':')) == NULL) {
fprintf(stderr, "wbidmap: line must have at least two fields: %s\n", buf);
goto fail;
}
if ((uid_data->dptr = malloc((s1 - buf) + 1)) == NULL) {
fprintf(stderr, "wbidmap: %s\n", strerror(errno));
goto fail;
}
strncpy(uid_data->dptr, buf, (s1 - buf));
uid_data->dptr[(s1 - buf)] = '\0';
uid_data->dsize = (s1 - buf) + 1;
s1++;
if ((s2 = strchr(s1, ':')) == NULL)
s2 = buf + strlen(buf);
if ((sid_data->dptr = malloc((s2 - s1) + 1)) == NULL) {
fprintf(stderr, "wbidmap: %s\n", strerror(errno));
goto fail;
}
strncpy(sid_data->dptr, s1, (s2 - s1));
sid_data->dptr[(s2 - s1)] = '\0';
sid_data->dsize = (s2 - s1) + 1;
if (type_tdb_data(*uid_data, isgroup, value) != TYPE_UID) {
fprintf(stderr, "wbidmap: malformed UID/GID token: \"%s\"\n", uid_data->dptr);
goto fail;
}
if (type_tdb_data(*sid_data, NULL, NULL) != TYPE_SID) {
fprintf(stderr, "wbidmap: malformed SID token: \"%s\"\n", sid_data->dptr);
goto fail;
}
return True;
fail:
SAFE_FREE(uid_data->dptr);
SAFE_FREE(sid_data->dptr);
return True;
}
/* Return True if data1 and data2 are equal. NULL data records are
never considered equal to anything. */
BOOL tdb_data_equal(TDB_DATA data1, TDB_DATA data2)
{
if (data1.dptr && data2.dptr && data1.dsize == data2.dsize &&
strncmp(data1.dptr, data2.dptr, data1.dsize) == 0) {
return True;
} else {
return False;
}
}
/* Return True if the data:key complementary exists for key:data in TDB */
BOOL reverse_lookup(TDB_DATA key, TDB_DATA data)
{
TDB_DATA complement;
BOOL result = False;
complement = tdb_fetch(idmap_tdb, data);
if (!complement.dptr) {
fprintf(stderr, "Unable to reverse lookup %s from %s : %s\n", key.dptr, data.dptr, tdb_errorstr(idmap_tdb));
} else {
if (tdb_data_equal(complement, key)) {
result = True;
} else {
fprintf(stderr, "Inconsistent complement %s:%s for %s:%s\n",
complement.dptr, data.dptr, key.dptr, data.dptr);
}
SAFE_FREE(complement.dptr);
}
return result;
}
/* Dump TDB contents to stdout. Database is checked for consistency, whether
keys and data are well formatted, and whether all ID entries do have
they complementary counterparts. HWM values are computed and compared
with the actual ones. The result of HWM computation is printed to stderr
after the end of dump. */
BOOL dump_idmap_tdb(void)
{
BOOL result = True;
TDB_DATA key, nextkey, data;
int value;
BOOL isgroup;
int uid, hwm;
int hwm_user, hwm_group, idmap_version;
int my_hwm_user = 0, my_hwm_group = 0;
int key_type;
BOOL have_hwm_user = False, have_hwm_group = False;
if ((idmap_version = tdb_fetch_int32(idmap_tdb, IDMAP_VERSION_KEY)) == -1) {
fprintf(stderr, "Unable to retrieve %s : %s\n", IDMAP_VERSION_KEY,
tdb_errorstr(idmap_tdb));
} else if (idmap_version != IDMAP_VERSION) {
fprintf(stderr, "Wrong %s in source tdb: %d\n", IDMAP_VERSION_KEY, idmap_version);
}
key = tdb_firstkey(idmap_tdb);
while (key.dptr) {
if (do_terminate) {
fprintf(stderr, "wbidmap: Terminated\n");
return False;
}
switch (type_tdb_data(key, &isgroup, &value)) {
case TYPE_UID:
data = tdb_fetch(idmap_tdb, key);
if (!data.dptr) {
fprintf(stderr, "Unable to retrieve SID for %s : %s\n", key.dptr, tdb_errorstr(idmap_tdb));
result = False;
break;
}
if (type_tdb_data(data, NULL, NULL) != TYPE_SID) {
fprintf(stderr, "Invalid SID %s for %s\n", data.dptr, key.dptr);
SAFE_FREE(data.dptr);
result = False;
break;
}
if (!reverse_lookup(key, data))
result = False;
printf("%s:%s\n", key.dptr, data.dptr);
if (isgroup) {
my_hwm_group = (value + 1 > my_hwm_group ? value + 1 : my_hwm_group);
} else {
my_hwm_user = (value + 1 > my_hwm_user ? value + 1 : my_hwm_user);
}
SAFE_FREE(data.dptr);
break;
case TYPE_SID:
data = tdb_fetch(idmap_tdb, key);
if (!data.dptr) {
fprintf(stderr, "Unable to retrieve UID/GID for %s : %s\n", key.dptr, tdb_errorstr(idmap_tdb));
result = False;
break;
}
key_type = type_tdb_data(data, NULL, NULL);
if (key_type != TYPE_UID) {
fprintf(stderr, "Invalid UID/GID %s for %s\n", data.dptr, key.dptr);
SAFE_FREE(data.dptr);
result = False;
break;
}
if (!reverse_lookup(key, data));
result = False;
SAFE_FREE(data.dptr);
break;
case TYPE_HWM:
if (isgroup && have_hwm_group || !isgroup && have_hwm_user) {
/* this should only happen if TDB is REALLY broken... */
fprintf(stderr, "OOOPS! More than one %s key found! skipping...\n", (isgroup ? HWM_GROUP : HWM_USER));
result = False;
break;
}
if ((hwm = tdb_fetch_int32(idmap_tdb, key.dptr)) == -1) {
fprintf(stderr, "Unable to retrieve value for %s : %s\n",
(isgroup ? HWM_GROUP : HWM_USER), tdb_errorstr(idmap_tdb));
result = False;
} else {
if (isgroup) {
hwm_group = hwm;
have_hwm_group = True;
} else {
hwm_user = hwm;
have_hwm_user = True;
}
}
break;
case TYPE_VERSION:
/* Already dealt with it in the beginning */
break;
default:
fprintf(stderr, "Unknown key type %s\n", key.dptr);
break;
}
nextkey = tdb_nextkey(idmap_tdb, key);
SAFE_FREE(key.dptr);
key = nextkey;
}
/* Check whether HWM values have been read and are matching the
ones we have computed ourself */
if (have_hwm_user) {
if (hwm_user == my_hwm_user) {
fprintf(stderr, "%s is %d\n", HWM_USER, hwm_user);
} else {
fprintf(stderr, "%s is %d, should be %d\n", HWM_USER, hwm_user, my_hwm_user);
result = False;
}
} else {
fprintf(stderr, "No %s found! Should be %d\n", HWM_USER, my_hwm_user);
result = False;
}
if (have_hwm_group) {
if (hwm_group == my_hwm_group) {
fprintf(stderr, "%s is %d\n", HWM_GROUP, hwm_group);
} else {
fprintf(stderr, "%s is %d, should be %d\n", HWM_GROUP, hwm_group, my_hwm_group);
result = False;
}
} else {
fprintf(stderr, "No %s found! Should be %d\n", HWM_GROUP, my_hwm_group);
result = False;
}
return result;
}
/* Merge incoming mappings from stdin into TDB file. Also used for creation
with TDB_CLEAR_IF_FIRST and O_CREAT set on tdb_open() */
BOOL merge_idmap_tdb(void)
{
BOOL result, isgroup;
int value, hwm_user, hwm_group, idmap_version;
TDB_DATA uid_new, sid_new, uid_old, sid_old;
if ((idmap_version = tdb_fetch_int32(idmap_tdb, IDMAP_VERSION_KEY)) > 0 && idmap_version != 2) {
fprintf(stderr, "Wrong %s in target tdb: %d\n", IDMAP_VERSION_KEY, idmap_version);
return False;
}
if (tdb_store_int32(idmap_tdb, IDMAP_VERSION_KEY, IDMAP_VERSION) != 0) {
fprintf(stderr, "Unable to store %s=%d: %s\n", IDMAP_VERSION_KEY, IDMAP_VERSION,
tdb_errorstr(idmap_tdb));
return False;
}
if (do_merge) {
if ((hwm_user = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) {
fprintf(stderr, "Unable to retrieve %s : %s\n", HWM_USER, tdb_errorstr(idmap_tdb));
return False;
}
if ((hwm_group = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
fprintf(stderr, "Unable to retrieve %s : %s\n", HWM_GROUP, tdb_errorstr(idmap_tdb));
return False;
}
} else {
hwm_user = 0;
hwm_group = 0;
}
while (1) {
if (do_terminate) {
fprintf(stderr, "wbidmap: Terminated\n");
return False;
}
/* EOF */
if (!idmap_readline(&uid_new, &sid_new, &isgroup, &value))
return True;
/* read error */
if (!uid_new.dptr || !sid_new.dptr)
return False;
/* Check whether sid_new or uid_new are already in TDB. TDB_ERR_NOEXIST
is fine, because we have no conflict, then. */
sid_old = tdb_fetch(idmap_tdb, uid_new);
if (!sid_old.dptr && tdb_error(idmap_tdb) != TDB_ERR_NOEXIST) {
fprintf(stderr, "Unable to lookup old SID for %s : %s\n", uid_new.dptr, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
uid_old = tdb_fetch(idmap_tdb, sid_new);
if (!uid_old.dptr && tdb_error(idmap_tdb) != TDB_ERR_NOEXIST) {
fprintf(stderr, "Unable to lookup old UID/GID for %s : %s\n", sid_new.dptr, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
if (sid_old.dptr || uid_old.dptr) {
/* If mapping already exists and is the same: be happy and go ahead */
if (tdb_data_equal(uid_new, uid_old) && tdb_data_equal(sid_new, sid_old))
goto cleanup;
/* Conflicts found */
if (sid_old.dptr) {
fprintf(stderr, "New %s:%s %s %s:%s\n", uid_new.dptr, sid_new.dptr,
(do_overwrite ? "overwriting" : "conflicting with"),
uid_new.dptr, sid_old.dptr);
if (!do_overwrite)
goto cleanup;
if (!do_preview) {
if (tdb_delete(idmap_tdb, uid_new) != 0 ||
tdb_delete(idmap_tdb, sid_old) != 0) {
fprintf(stderr, "Unable to delete old mapping for %s:%s : %s\n",
uid_new.dptr, sid_old.dptr, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
}
}
if (uid_old.dptr) {
fprintf(stderr, "New %s:%s %s %s:%s\n", uid_new.dptr, sid_new.dptr,
(do_overwrite ? "overwriting" : "conflicting with"),
uid_old.dptr, sid_new.dptr);
if (!do_overwrite)
goto cleanup;
if (!do_preview) {
if (tdb_delete(idmap_tdb, uid_old) != 0 ||
tdb_delete(idmap_tdb, sid_new) != 0) {
fprintf(stderr, "Unable to delete old mapping for %s:%s : %s\n",
uid_old.dptr, sid_new.dptr, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
}
}
}
/* Store new mapping. Conflicting mappings, if any, should have
been deleted above, so use TDB_INSERT */
if (!do_preview) {
if (tdb_store(idmap_tdb, uid_new, sid_new, TDB_INSERT) != 0 ||
tdb_store(idmap_tdb, sid_new, uid_new, TDB_INSERT) != 0) {
fprintf(stderr, "Unable to store new mapping %s:%s : %s\n",
uid_new.dptr, sid_new.dptr, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
/* adjust corresponding HWM */
if (isgroup) {
if (value >= hwm_group) {
hwm_group = value + 1;
if (tdb_store_int32(idmap_tdb, HWM_GROUP, hwm_group) != 0) {
fprintf(stderr, "Unable to store %s : %s\n",
HWM_GROUP, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
}
} else {
if (value >= hwm_user) {
hwm_user = value + 1;
if (tdb_store_int32(idmap_tdb, HWM_USER, hwm_user) != 0) {
fprintf(stderr, "Unable to store %s : %s\n",
HWM_USER, tdb_errorstr(idmap_tdb));
do_terminate = True;
goto cleanup;
}
}
}
}
cleanup:
SAFE_FREE(uid_new.dptr);
SAFE_FREE(sid_new.dptr);
SAFE_FREE(uid_old.dptr);
SAFE_FREE(sid_old.dptr);
}
return True;
}
/* Main program */
int main(int argc, char **argv)
{
int result = 0;
int tdb_flags, open_flags;
if (!lp_load(CONFIGFILE, True, False, False)) {
fprintf(stderr, "wbidmap: error opening config file %s: %s\n",
CONFIGFILE, strerror(errno));
return 1;
}
/* Parse command line options */
if (argc == 1) {
usage();
return 1;
}
while (optind < argc) {
switch (getopt(argc, argv, "f:dcmop")) {
case 'f':
if (tdb_file) {
usage();
return 1;
}
tdb_file = optarg;
break;
case 'd':
if (do_dump || do_create || do_merge || do_overwrite || do_preview) {
usage();
return 1;
}
do_dump = True;
tdb_flags = 0;
open_flags = O_RDONLY;
break;
case 'c':
if (do_dump || do_create || do_merge || do_overwrite || do_preview) {
usage();
return 1;
}
do_create = True;
tdb_flags = TDB_CLEAR_IF_FIRST;
open_flags = O_RDWR | O_CREAT;
break;
case 'm':
if (do_dump || do_create || do_merge) {
usage();
return 1;
}
do_merge = True;
tdb_flags = 0;
open_flags = O_RDWR;
break;
case 'o':
if (do_dump || do_create || do_overwrite) {
usage();
return 1;
}
do_overwrite = True;
break;
case 'p':
if (do_preview || do_dump || do_create ) {
usage();
return 1;
}
do_preview = True;
break;
default:
usage();
return 1;
}
}
CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */
CatchSignal(SIGQUIT, termination_handler);
CatchSignal(SIGTERM, termination_handler);
CatchSignal(SIGPIPE, termination_handler);
if (!(idmap_tdb = tdb_open((tdb_file ? tdb_file : lock_path("winbindd_idmap.tdb")), 0,
tdb_flags, open_flags, 0600))) {
fprintf(stderr, "Unable to open idmap database %s: %s\n",
(tdb_file ? tdb_file : lock_path("winbindd_idmap.tdb")), strerror(errno));
return 1;
}
if (do_dump) {
if (!dump_idmap_tdb())
result = 1;
} else if (do_create) {
if (!merge_idmap_tdb())
result = 1;
} else if (do_merge) {
if (!merge_idmap_tdb())
result = 1;
}
if (idmap_tdb)
return (tdb_close(idmap_tdb) == 0);
/* Clean exit */
return result;
}
Index: source/Makefile.in
===================================================================
RCS file: /cvsroot/samba/source/Makefile.in,v
retrieving revision 1.227.2.133
diff -u -r1.227.2.133 Makefile.in
--- source/Makefile.in 30 Apr 2002 07:59:05 -0000 1.227.2.133
+++ source/Makefile.in 30 Apr 2002 12:28:48 -0000
@@ -405,6 +405,8 @@
WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o \
passdb/secrets.o
+WBIDMAP_OBJ = nsswitch/wbidmap.o
+
WINBIND_NSS_OBJ = nsswitch/winbind_nss.o nsswitch/wb_common.o @WINBIND_NSS_EXTRA_OBJS@
WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.po)
@@ -690,6 +692,12 @@
$(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(LINK) -o $@ $(WBINFO_OBJ) $(PARAM_OBJ) $(LIB_OBJ) $(NOPROTO_OBJ) \
+ $(UBIQX_OBJ) $(LIBS) @BUILD_POPT@
+
+bin/wbidmap: $(WBIDMAP_OBJ) $(PARAM_OBJ) $(LIB_OBJ) $(NOPROTO_OBJ) \
+ $(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
+ @echo Linking $@
+ @$(LINK) -o $@ $(WBIDMAP_OBJ) $(PARAM_OBJ) $(LIB_OBJ) $(NOPROTO_OBJ) \
$(UBIQX_OBJ) $(LIBS) @BUILD_POPT@
bin/tdbbackup: $(TDBBACKUP_OBJ) bin/.dummy
Index: source/nsswitch/winbindd_idmap.c
===================================================================
RCS file: /cvsroot/samba/source/nsswitch/winbindd_idmap.c,v
retrieving revision 1.3.4.13
diff -u -r1.3.4.13 winbindd_idmap.c
--- source/nsswitch/winbindd_idmap.c 27 Apr 2002 03:04:08 -0000 1.3.4.13
+++ source/nsswitch/winbindd_idmap.c 30 Apr 2002 12:26:34 -0000
@@ -68,6 +68,30 @@
return True;
}
+/* Log id mapping. Reopen log file for every entry, because information
+ would be lost when someone unlinks the file while winbindd has it open */
+
+static BOOL log_idmap(TDB_DATA id, TDB_DATA sid)
+{
+ FILE *logfile;
+
+ if ((logfile = fopen(lock_path("winbindd_idmap.log"), "a")) == NULL) {
+ DEBUG(1, ("cannot open %s : %s\n",
+ lock_path("winbindd_idmap.log"), strerror(errno)));
+ return False;
+ }
+
+ if (fprintf(logfile, "%s:%s\n", id.dptr, sid.dptr) < 0) {
+ DEBUG(1, ("cannot write %s:%s to %s : %s\n", id.dptr, sid.dptr,
+ lock_path("winbindd_idmap.log"), strerror(errno)));
+ fclose(logfile);
+ return False;
+ }
+
+ fclose(logfile);
+ return True;
+}
+
/* Get an id from a rid */
static BOOL get_id_from_sid(DOM_SID *sid, uid_t *id, BOOL isgroup)
{
@@ -115,10 +139,14 @@
data.dptr = keystr2;
data.dsize = strlen(keystr2) + 1;
- tdb_store(idmap_tdb, key, data, TDB_REPLACE);
- tdb_store(idmap_tdb, data, key, TDB_REPLACE);
+ /* have mapping depend on successful log in order to avoid
+ data loss for recovery */
- result = True;
+ if (log_idmap(data, key)) {
+ tdb_store(idmap_tdb, key, data, TDB_REPLACE);
+ tdb_store(idmap_tdb, data, key, TDB_REPLACE);
+ result = True;
+ }
}
}