Changeset 223 for branches/samba-3.3.x/source/passdb/pdb_tdb.c
- Timestamp:
- May 24, 2009, 7:51:24 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/samba-3.3.x/source/passdb/pdb_tdb.c
r221 r223 5 5 * Copyright (C) Simo Sorce 2000-2003 6 6 * Copyright (C) Gerald Carter 2000-2006 7 * Copyright (C) Jeremy Allison 2001 7 * Copyright (C) Jeremy Allison 2001-2009 8 8 * Copyright (C) Andrew Bartlett 2002 9 9 * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005 … … 39 39 40 40 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */ 41 #define TDBSAM_MINOR_VERSION 0 /* Most recent TDBSAM minor version */ 41 42 #define TDBSAM_VERSION_STRING "INFO/version" 43 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version" 42 44 #define PASSDB_FILE_NAME "passdb.tdb" 43 45 #define USERPREFIX "USER_" … … 103 105 (uint8 *)rec->value.dptr, 104 106 rec->value.dsize); 107 break; 105 108 case 4: 106 109 ret = init_samu_from_buffer(user, SAMU_BUFFER_V4, … … 142 145 } 143 146 147 /********************************************************************** 148 Struct and function to backup an old record. 149 *********************************************************************/ 150 151 struct tdbsam_backup_state { 152 struct db_context *new_db; 153 bool success; 154 }; 155 156 static int backup_copy_fn(struct db_record *orig_rec, void *state) 157 { 158 struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state; 159 struct db_record *new_rec; 160 NTSTATUS status; 161 162 new_rec = bs->new_db->fetch_locked(bs->new_db, talloc_tos(), orig_rec->key); 163 if (new_rec == NULL) { 164 bs->success = false; 165 return 1; 166 } 167 168 status = new_rec->store(new_rec, orig_rec->value, TDB_INSERT); 169 170 TALLOC_FREE(new_rec); 171 172 if (!NT_STATUS_IS_OK(status)) { 173 bs->success = false; 174 return 1; 175 } 176 return 0; 177 } 178 179 /********************************************************************** 180 Make a backup of an old passdb and replace the new one with it. We 181 have to do this as between 3.0.x and 3.2.x the hash function changed 182 by mistake (used unsigned char * instead of char *). This means the 183 previous simple update code will fail due to not being able to find 184 existing records to replace in the tdbsam_convert_one() function. JRA. 185 *********************************************************************/ 186 187 static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) 188 { 189 TALLOC_CTX *frame = talloc_stackframe(); 190 const char *tmp_fname = NULL; 191 struct db_context *tmp_db = NULL; 192 struct db_context *orig_db = *pp_db; 193 struct tdbsam_backup_state bs; 194 int ret; 195 196 tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname); 197 if (!tmp_fname) { 198 TALLOC_FREE(frame); 199 return false; 200 } 201 202 unlink(tmp_fname); 203 204 /* Remember to open this on the NULL context. We need 205 * it to stay around after we return from here. */ 206 207 tmp_db = db_open(NULL, tmp_fname, 0, 208 TDB_DEFAULT, O_CREAT|O_RDWR, 0600); 209 if (tmp_db == NULL) { 210 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " 211 "[%s]\n", tmp_fname)); 212 TALLOC_FREE(frame); 213 return false; 214 } 215 216 if (orig_db->transaction_start(orig_db) != 0) { 217 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n")); 218 unlink(tmp_fname); 219 TALLOC_FREE(tmp_db); 220 TALLOC_FREE(frame); 221 return false; 222 } 223 if (tmp_db->transaction_start(tmp_db) != 0) { 224 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n")); 225 orig_db->transaction_cancel(orig_db); 226 unlink(tmp_fname); 227 TALLOC_FREE(tmp_db); 228 TALLOC_FREE(frame); 229 return false; 230 } 231 232 bs.new_db = tmp_db; 233 bs.success = true; 234 235 ret = orig_db->traverse(orig_db, backup_copy_fn, (void *)&bs); 236 if (ret < 0) { 237 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n")); 238 goto cancel; 239 } 240 241 if (!bs.success) { 242 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n")); 243 goto cancel; 244 } 245 246 if (orig_db->transaction_commit(orig_db) != 0) { 247 smb_panic("tdbsam_convert_backup: orig commit failed\n"); 248 } 249 if (tmp_db->transaction_commit(tmp_db) != 0) { 250 smb_panic("tdbsam_convert_backup: orig commit failed\n"); 251 } 252 253 /* be sure to close the DBs _before_ renaming the file */ 254 255 TALLOC_FREE(orig_db); 256 TALLOC_FREE(tmp_db); 257 258 /* This is safe from other users as we know we're 259 * under a mutex here. */ 260 261 if (rename(tmp_fname, dbname) == -1) { 262 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n", 263 tmp_fname, 264 dbname, 265 strerror(errno))); 266 smb_panic("tdbsam_convert_backup: replace passdb failed\n"); 267 } 268 269 TALLOC_FREE(frame); 270 271 /* re-open the converted TDB */ 272 273 orig_db = db_open(NULL, dbname, 0, 274 TDB_DEFAULT, O_CREAT|O_RDWR, 0600); 275 if (orig_db == NULL) { 276 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open " 277 "converted passdb TDB [%s]\n", dbname)); 278 return false; 279 } 280 281 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n", 282 dbname )); 283 284 /* Replace the global db pointer. */ 285 *pp_db = orig_db; 286 return true; 287 288 cancel: 289 290 if (orig_db->transaction_cancel(orig_db) != 0) { 291 smb_panic("tdbsam_convert: transaction_cancel failed"); 292 } 293 294 if (tmp_db->transaction_cancel(tmp_db) != 0) { 295 smb_panic("tdbsam_convert: transaction_cancel failed"); 296 } 297 298 unlink(tmp_fname); 299 TALLOC_FREE(tmp_db); 300 TALLOC_FREE(frame); 301 return false; 302 } 303 144 304 static bool tdbsam_upgrade_next_rid(struct db_context *db) 145 305 { … … 173 333 } 174 334 175 static bool tdbsam_convert(struct db_context * db, int32 from)335 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from) 176 336 { 177 337 struct tdbsam_convert_state state; 338 struct db_context *db = NULL; 178 339 int ret; 179 340 341 /* We only need the update backup for local db's. */ 342 if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) { 343 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name)); 344 return false; 345 } 346 347 db = *pp_db; 180 348 state.from = from; 181 349 state.success = true; 182 350 183 351 if (db->transaction_start(db) != 0) { 184 DEBUG(0, (" Could not start transaction\n"));352 DEBUG(0, ("tdbsam_convert: Could not start transaction\n")); 185 353 return false; 186 354 } 187 355 188 356 if (!tdbsam_upgrade_next_rid(db)) { 189 DEBUG(0, ("tdbsam_ upgrade_next_rid failed\n"));357 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n")); 190 358 goto cancel; 191 359 } … … 193 361 ret = db->traverse(db, tdbsam_convert_one, &state); 194 362 if (ret < 0) { 195 DEBUG(0, ("t raverse failed\n"));363 DEBUG(0, ("tdbsam_convert: traverse failed\n")); 196 364 goto cancel; 197 365 } 198 366 199 367 if (!state.success) { 200 DEBUG(0, (" Converting records failed\n"));368 DEBUG(0, ("tdbsam_convert: Converting records failed\n")); 201 369 goto cancel; 202 370 } … … 204 372 if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING, 205 373 TDBSAM_VERSION) != 0) { 206 DEBUG(0, ("Could not store tdbsam version\n")); 374 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n")); 375 goto cancel; 376 } 377 378 if (dbwrap_store_int32(db, TDBSAM_MINOR_VERSION_STRING, 379 TDBSAM_MINOR_VERSION) != 0) { 380 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor version\n")); 207 381 goto cancel; 208 382 } 209 383 210 384 if (db->transaction_commit(db) != 0) { 211 DEBUG(0, (" Could not commit transaction\n"));385 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n")); 212 386 return false; 213 387 } … … 217 391 cancel: 218 392 if (db->transaction_cancel(db) != 0) { 219 smb_panic("t ransaction_cancel failed");393 smb_panic("tdbsam_convert: transaction_cancel failed"); 220 394 } 221 395 … … 231 405 { 232 406 int32 version; 407 int32 minor_version; 233 408 234 409 /* check if we are already open */ … … 251 426 if (version == -1) { 252 427 version = 0; /* Version not found, assume version 0 */ 428 } 429 430 /* Get the minor version */ 431 minor_version = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING); 432 if (minor_version == -1) { 433 minor_version = 0; /* Minor version not found, assume 0 */ 253 434 } 254 435 … … 261 442 } 262 443 263 if ( version < TDBSAM_VERSION ) { 264 DEBUG(1, ("tdbsam_open: Converting version %d database to " 265 "version %d.\n", version, TDBSAM_VERSION)); 266 267 if ( !tdbsam_convert(db_sam, version) ) { 268 DEBUG(0, ("tdbsam_open: Error when trying to convert " 269 "tdbsam [%s]\n",name)); 444 if ( version < TDBSAM_VERSION || 445 (version == TDBSAM_VERSION && 446 minor_version < TDBSAM_MINOR_VERSION) ) { 447 /* 448 * Ok - we think we're going to have to convert. 449 * Due to the backup process we now must do to 450 * upgrade we have to get a mutex and re-check 451 * the version. Someone else may have upgraded 452 * whilst we were checking. 453 */ 454 455 struct named_mutex *mtx = grab_named_mutex(NULL, 456 "tdbsam_upgrade_mutex", 457 600); 458 459 if (!mtx) { 460 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n")); 270 461 TALLOC_FREE(db_sam); 271 462 return false; 272 463 } 273 464 274 DEBUG(3, ("TDBSAM converted successfully.\n")); 465 /* Re-check the version */ 466 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING); 467 if (version == -1) { 468 version = 0; /* Version not found, assume version 0 */ 469 } 470 471 /* Re-check the minor version */ 472 minor_version = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING); 473 if (minor_version == -1) { 474 minor_version = 0; /* Minor version not found, assume 0 */ 475 } 476 477 /* Compare the version */ 478 if (version > TDBSAM_VERSION) { 479 /* Version more recent than the latest known */ 480 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version)); 481 TALLOC_FREE(db_sam); 482 TALLOC_FREE(mtx); 483 return false; 484 } 485 486 if ( version < TDBSAM_VERSION || 487 (version == TDBSAM_VERSION && 488 minor_version < TDBSAM_MINOR_VERSION) ) { 489 /* 490 * Note that minor versions we read that are greater 491 * than the current minor version we have hard coded 492 * are assumed to be compatible if they have the same 493 * major version. That allows previous versions of the 494 * passdb code that don't know about minor versions to 495 * still use this database. JRA. 496 */ 497 498 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to " 499 "version %d.%d.\n", 500 version, 501 minor_version, 502 TDBSAM_VERSION, 503 TDBSAM_MINOR_VERSION)); 504 505 if ( !tdbsam_convert(&db_sam, name, version) ) { 506 DEBUG(0, ("tdbsam_open: Error when trying to convert " 507 "tdbsam [%s]\n",name)); 508 TALLOC_FREE(db_sam); 509 TALLOC_FREE(mtx); 510 return false; 511 } 512 513 DEBUG(3, ("TDBSAM converted successfully.\n")); 514 } 515 TALLOC_FREE(mtx); 275 516 } 276 517
Note:
See TracChangeset
for help on using the changeset viewer.