The Samba-Bugzilla – Attachment 3998 Details for
Bug 6195
Migrating from 3.0.x to 3.3.x can fail to update passdb.tdb correctly.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Fix for 3.3.2.
look (text/plain), 10.20 KB, created by
Jeremy Allison
on 2009-03-18 18:42:04 UTC
(
hide
)
Description:
Fix for 3.3.2.
Filename:
MIME Type:
Creator:
Jeremy Allison
Created:
2009-03-18 18:42:04 UTC
Size:
10.20 KB
patch
obsolete
>diff --git a/source/Makefile.in b/source/Makefile.in >index e160a99..988ca2c 100644 >--- a/source/Makefile.in >+++ b/source/Makefile.in >@@ -575,7 +575,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ > passdb/util_unixsids.o passdb/lookup_sid.o \ > passdb/login_cache.o @PDB_STATIC@ \ > lib/account_pol.o $(PRIVILEGES_OBJ) \ >- lib/util_nscd.o lib/winbind_util.o >+ lib/util_nscd.o lib/winbind_util.o $(SERVER_MUTEX_OBJ) > > DEVEL_HELP_WEIRD_OBJ = modules/weird.o > CP850_OBJ = modules/CP850.o >@@ -670,7 +670,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ > smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \ > smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \ > smbd/vfs.o smbd/statcache.o smbd/seal.o \ >- smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \ >+ smbd/posix_acls.o lib/sysacls.o \ > smbd/process.o smbd/service.o smbd/error.o \ > printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \ > lib/sysquotas_xfs.o lib/sysquotas_4A.o \ >@@ -881,7 +881,7 @@ NET_OBJ = $(NET_OBJ1) \ > $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(LIBADDNS_OBJ0) \ > $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \ > $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \ >- $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \ >+ $(SMBLDAP_OBJ) $(DCUTIL_OBJ) \ > $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(READLINE_OBJ) \ > $(LDB_OBJ) $(LIBGPO_OBJ) @BUILD_INIPARSER@ $(DISPLAY_SEC_OBJ) \ > $(REG_SMBCONF_OBJ) @LIBNETAPI_STATIC@ $(LIBNET_OBJ) \ >@@ -1043,7 +1043,7 @@ WINBINDD_OBJ = \ > $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ > $(DCUTIL_OBJ) $(IDMAP_OBJ) $(NSS_INFO_OBJ) \ > $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \ >- $(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ) $(LDB_OBJ) >+ $(LIBADS_SERVER_OBJ) $(LDB_OBJ) > > WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ > $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ) \ >@@ -1109,7 +1109,7 @@ NTLM_AUTH_OBJ1 = utils/ntlm_auth.o utils/ntlm_auth_diagnostics.o > > NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ > libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \ >- $(SERVER_MUTEX_OBJ) $(LIBADS_SERVER_OBJ) \ >+ $(LIBADS_SERVER_OBJ) \ > $(PASSDB_OBJ) $(GROUPDB_OBJ) \ > $(SMBLDAP_OBJ) $(LIBNMB_OBJ) \ > $(LDB_OBJ) $(WBCOMMON_OBJ) @LIBWBCLIENT_STATIC@ \ >diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c >index 80faeb0..de49ed2 100644 >--- a/source/passdb/pdb_tdb.c >+++ b/source/passdb/pdb_tdb.c >@@ -142,6 +142,149 @@ static int tdbsam_convert_one(struct db_record *rec, void *priv) > return 0; > } > >+/********************************************************************** >+ Struct and function to backup an old record. >+ *********************************************************************/ >+ >+struct tdbsam_backup_state { >+ struct db_context *new_db; >+ bool success; >+}; >+ >+static int backup_copy_fn(struct db_record *orig_rec, void *state) >+{ >+ struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state; >+ struct db_record *new_rec; >+ NTSTATUS status; >+ >+ new_rec = bs->new_db->fetch_locked(bs->new_db, talloc_tos(), orig_rec->key); >+ if (new_rec == NULL) { >+ bs->success = false; >+ return 1; >+ } >+ >+ status = new_rec->store(new_rec, orig_rec->value, TDB_INSERT); >+ >+ TALLOC_FREE(new_rec); >+ >+ if (!NT_STATUS_IS_OK(status)) { >+ bs->success = false; >+ return 1; >+ } >+ return 0; >+} >+ >+/********************************************************************** >+ Make a backup of an old passdb and replace the new one with it. We >+ have to do this as between 3.0.x and 3.2.x the hash function changed >+ by mistake (used unsigned char * instead of char *). This means the >+ previous simple update code will fail due to not being able to find >+ existing records to replace in the tdbsam_convert_one() function. JRA. >+ *********************************************************************/ >+ >+static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) >+{ >+ TALLOC_CTX *frame = talloc_stackframe(); >+ const char *tmp_fname = NULL; >+ struct db_context *tmp_db = NULL; >+ struct db_context *orig_db = *pp_db; >+ struct tdbsam_backup_state bs; >+ int ret; >+ >+ tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname); >+ if (!tmp_fname) { >+ TALLOC_FREE(frame); >+ return false; >+ } >+ >+ unlink(tmp_fname); >+ >+ /* Remember to open this on the NULL context. We need >+ * it to stay around after we return from here. */ >+ >+ tmp_db = db_open(NULL, tmp_fname, 0, >+ TDB_DEFAULT, O_CREAT|O_RDWR, 0600); >+ if (tmp_db == NULL) { >+ DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " >+ "[%s]\n", tmp_fname)); >+ TALLOC_FREE(frame); >+ return false; >+ } >+ >+ if (orig_db->transaction_start(orig_db) != 0) { >+ DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n")); >+ unlink(tmp_fname); >+ TALLOC_FREE(tmp_db); >+ TALLOC_FREE(frame); >+ return false; >+ } >+ if (tmp_db->transaction_start(tmp_db) != 0) { >+ DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n")); >+ orig_db->transaction_cancel(orig_db); >+ unlink(tmp_fname); >+ TALLOC_FREE(tmp_db); >+ TALLOC_FREE(frame); >+ return false; >+ } >+ >+ bs.new_db = tmp_db; >+ bs.success = true; >+ >+ ret = orig_db->traverse(orig_db, backup_copy_fn, (void *)&bs); >+ if (ret < 0) { >+ DEBUG(0, ("tdbsam_convert_backup: traverse failed\n")); >+ goto cancel; >+ } >+ >+ if (!bs.success) { >+ DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n")); >+ goto cancel; >+ } >+ >+ if (orig_db->transaction_commit(orig_db) != 0) { >+ smb_panic("tdbsam_convert_backup: orig commit failed\n"); >+ } >+ if (tmp_db->transaction_commit(tmp_db) != 0) { >+ smb_panic("tdbsam_convert_backup: orig commit failed\n"); >+ } >+ >+ /* This is safe from other users as we know we're >+ * under a mutex here. */ >+ >+ if (rename(tmp_fname, dbname) == -1) { >+ DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n", >+ tmp_fname, >+ dbname, >+ strerror(errno))); >+ smb_panic("tdbsam_convert_backup: replace passdb failed\n"); >+ } >+ >+ TALLOC_FREE(frame); >+ TALLOC_FREE(orig_db); >+ >+ DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n", >+ dbname )); >+ >+ /* Replace the global db pointer. */ >+ *pp_db = tmp_db; >+ return true; >+ >+ cancel: >+ >+ if (orig_db->transaction_cancel(orig_db) != 0) { >+ smb_panic("tdbsam_convert: transaction_cancel failed"); >+ } >+ >+ if (tmp_db->transaction_cancel(tmp_db) != 0) { >+ smb_panic("tdbsam_convert: transaction_cancel failed"); >+ } >+ >+ unlink(tmp_fname); >+ TALLOC_FREE(tmp_db); >+ TALLOC_FREE(frame); >+ return false; >+} >+ > static bool tdbsam_upgrade_next_rid(struct db_context *db) > { > TDB_CONTEXT *tdb; >@@ -173,43 +316,50 @@ static bool tdbsam_upgrade_next_rid(struct db_context *db) > return true; > } > >-static bool tdbsam_convert(struct db_context *db, int32 from) >+static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from) > { > struct tdbsam_convert_state state; >+ struct db_context *db = NULL; > int ret; > >+ if (!tdbsam_convert_backup(name, pp_db)) { >+ DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name)); >+ return false; >+ } >+ >+ db = *pp_db; > state.from = from; > state.success = true; > > if (db->transaction_start(db) != 0) { >- DEBUG(0, ("Could not start transaction\n")); >+ DEBUG(0, ("tdbsam_convert: Could not start transaction\n")); > return false; > } > > if (!tdbsam_upgrade_next_rid(db)) { >- DEBUG(0, ("tdbsam_upgrade_next_rid failed\n")); >+ DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n")); > goto cancel; > } > > ret = db->traverse(db, tdbsam_convert_one, &state); > if (ret < 0) { >- DEBUG(0, ("traverse failed\n")); >+ DEBUG(0, ("tdbsam_convert: traverse failed\n")); > goto cancel; > } > > if (!state.success) { >- DEBUG(0, ("Converting records failed\n")); >+ DEBUG(0, ("tdbsam_convert: Converting records failed\n")); > goto cancel; > } > > if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING, > TDBSAM_VERSION) != 0) { >- DEBUG(0, ("Could not store tdbsam version\n")); >+ DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n")); > goto cancel; > } > > if (db->transaction_commit(db) != 0) { >- DEBUG(0, ("Could not commit transaction\n")); >+ DEBUG(0, ("tdbsam_convert: Could not commit transaction\n")); > return false; > } > >@@ -217,7 +367,7 @@ static bool tdbsam_convert(struct db_context *db, int32 from) > > cancel: > if (db->transaction_cancel(db) != 0) { >- smb_panic("transaction_cancel failed"); >+ smb_panic("tdbsam_convert: transaction_cancel failed"); > } > > return false; >@@ -262,17 +412,54 @@ static bool tdbsam_open( const char *name ) > } > > if ( version < TDBSAM_VERSION ) { >- DEBUG(1, ("tdbsam_open: Converting version %d database to " >- "version %d.\n", version, TDBSAM_VERSION)); >+ /* >+ * Ok - we think we're going to have to convert. >+ * Due to the backup process we now must do to >+ * upgrade we have to get a mutex and re-check >+ * the version. Someone else may have upgraded >+ * whilst we were checking. >+ */ >+ >+ struct named_mutex *mtx = grab_named_mutex(NULL, >+ "tdbsam_upgrade_mutex", >+ 600); > >- if ( !tdbsam_convert(db_sam, version) ) { >- DEBUG(0, ("tdbsam_open: Error when trying to convert " >- "tdbsam [%s]\n",name)); >+ if (!mtx) { >+ DEBUG(0, ("tdbsam_open: failed to grab mutex.\n")); > TALLOC_FREE(db_sam); > return false; > } > >- DEBUG(3, ("TDBSAM converted successfully.\n")); >+ /* Re-check the version */ >+ version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING); >+ if (version == -1) { >+ version = 0; /* Version not found, assume version 0 */ >+ } >+ >+ /* Compare the version */ >+ if (version > TDBSAM_VERSION) { >+ /* Version more recent than the latest known */ >+ DEBUG(0, ("tdbsam_open: unknown version => %d\n", version)); >+ TALLOC_FREE(db_sam); >+ TALLOC_FREE(mtx); >+ return false; >+ } >+ >+ if ( version < TDBSAM_VERSION ) { >+ DEBUG(1, ("tdbsam_open: Converting version %d database to " >+ "version %d.\n", version, TDBSAM_VERSION)); >+ >+ if ( !tdbsam_convert(&db_sam, name, version) ) { >+ DEBUG(0, ("tdbsam_open: Error when trying to convert " >+ "tdbsam [%s]\n",name)); >+ TALLOC_FREE(db_sam); >+ TALLOC_FREE(mtx); >+ return false; >+ } >+ >+ DEBUG(3, ("TDBSAM converted successfully.\n")); >+ } >+ TALLOC_FREE(mtx); > } > > DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 6195
: 3998 |
4031
|
4032