2 * Unix SMB/CIFS implementation.
3 * SMB parameters and setup
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Simo Sorce 2000-2003
6 * Copyright (C) Gerald Carter 2000-2006
7 * Copyright (C) Jeremy Allison 2001-2009
8 * Copyright (C) Andrew Bartlett 2002
9 * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
11 * This program is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 3 of the License, or (at your option)
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License along with
22 * this program; if not, see <http://www.gnu.org/licenses/>.
27 #if 0 /* when made a module use this */
29 static int tdbsam_debug_level = DBGC_ALL;
31 #define DBGC_CLASS tdbsam_debug_level
36 #define DBGC_CLASS DBGC_PASSDB
40 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */
41 #define TDBSAM_MINOR_VERSION 0 /* Most recent TDBSAM minor version */
42 #define TDBSAM_VERSION_STRING "INFO/version"
43 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version"
44 #define PASSDB_FILE_NAME "passdb.tdb"
45 #define USERPREFIX "USER_"
46 #define USERPREFIX_LEN 5
47 #define RIDPREFIX "RID_"
48 #define PRIVPREFIX "PRIV_"
49 #define NEXT_RID_STRING "NEXT_RID"
51 /* GLOBAL TDB SAM CONTEXT */
53 static struct db_context *db_sam;
54 static char *tdbsam_filename;
56 struct tdbsam_convert_state {
61 static int tdbsam_convert_one(struct db_record *rec, void *priv)
63 struct tdbsam_convert_state *state =
64 (struct tdbsam_convert_state *)priv;
70 if (rec->key.dsize < USERPREFIX_LEN) {
73 if (strncmp((char *)rec->key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
77 user = samu_new(talloc_tos());
79 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
80 state->success = false;
84 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
85 "(version:%d)\n", rec->key.dptr, state->from));
87 switch (state->from) {
89 ret = init_samu_from_buffer(user, SAMU_BUFFER_V0,
90 (uint8 *)rec->value.dptr,
94 ret = init_samu_from_buffer(user, SAMU_BUFFER_V1,
95 (uint8 *)rec->value.dptr,
99 ret = init_samu_from_buffer(user, SAMU_BUFFER_V2,
100 (uint8 *)rec->value.dptr,
104 ret = init_samu_from_buffer(user, SAMU_BUFFER_V3,
105 (uint8 *)rec->value.dptr,
109 ret = init_samu_from_buffer(user, SAMU_BUFFER_V4,
110 (uint8 *)rec->value.dptr,
114 /* unknown tdbsam version */
118 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
119 "from TDB (key:%s) (version:%d)\n", rec->key.dptr,
122 state->success = false;
126 data.dsize = init_buffer_from_samu(&data.dptr, user, false);
129 if (data.dsize == -1) {
130 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
131 "the new format\n"));
132 state->success = false;
136 status = rec->store(rec, data, TDB_MODIFY);
137 if (!NT_STATUS_IS_OK(status)) {
138 DEBUG(0, ("Could not store the new record: %s\n",
140 state->success = false;
147 /**********************************************************************
148 Struct and function to backup an old record.
149 *********************************************************************/
151 struct tdbsam_backup_state {
152 struct db_context *new_db;
156 static int backup_copy_fn(struct db_record *orig_rec, void *state)
158 struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state;
159 struct db_record *new_rec;
162 new_rec = bs->new_db->fetch_locked(bs->new_db, talloc_tos(), orig_rec->key);
163 if (new_rec == NULL) {
168 status = new_rec->store(new_rec, orig_rec->value, TDB_INSERT);
170 TALLOC_FREE(new_rec);
172 if (!NT_STATUS_IS_OK(status)) {
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 *********************************************************************/
187 static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db)
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;
196 tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname);
204 /* Remember to open this on the NULL context. We need
205 * it to stay around after we return from here. */
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));
216 if (orig_db->transaction_start(orig_db) != 0) {
217 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
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);
235 ret = orig_db->traverse(orig_db, backup_copy_fn, (void *)&bs);
237 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
242 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
246 if (orig_db->transaction_commit(orig_db) != 0) {
247 smb_panic("tdbsam_convert_backup: orig commit failed\n");
249 if (tmp_db->transaction_commit(tmp_db) != 0) {
250 smb_panic("tdbsam_convert_backup: orig commit failed\n");
253 /* be sure to close the DBs _before_ renaming the file */
255 TALLOC_FREE(orig_db);
258 /* This is safe from other users as we know we're
259 * under a mutex here. */
261 if (rename(tmp_fname, dbname) == -1) {
262 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
266 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
271 /* re-open the converted TDB */
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));
281 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
284 /* Replace the global db pointer. */
290 if (orig_db->transaction_cancel(orig_db) != 0) {
291 smb_panic("tdbsam_convert: transaction_cancel failed");
294 if (tmp_db->transaction_cancel(tmp_db) != 0) {
295 smb_panic("tdbsam_convert: transaction_cancel failed");
304 static bool tdbsam_upgrade_next_rid(struct db_context *db)
310 ok = dbwrap_fetch_uint32(db, NEXT_RID_STRING, &rid);
315 tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
316 TDB_DEFAULT, O_RDONLY, 0644);
319 ok = tdb_fetch_uint32(tdb, "RID_COUNTER", &rid);
328 if (dbwrap_store_uint32(db, NEXT_RID_STRING, rid) != 0) {
335 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from)
337 struct tdbsam_convert_state state;
338 struct db_context *db = NULL;
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));
349 state.success = true;
351 if (db->transaction_start(db) != 0) {
352 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
356 if (!tdbsam_upgrade_next_rid(db)) {
357 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
361 ret = db->traverse(db, tdbsam_convert_one, &state);
363 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
367 if (!state.success) {
368 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
372 if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING,
373 TDBSAM_VERSION) != 0) {
374 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n"));
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"));
384 if (db->transaction_commit(db) != 0) {
385 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
392 if (db->transaction_cancel(db) != 0) {
393 smb_panic("tdbsam_convert: transaction_cancel failed");
399 /*********************************************************************
400 Open the tdbsam file based on the absolute path specified.
401 Uses a reference count to allow multiple open calls.
402 *********************************************************************/
404 static bool tdbsam_open( const char *name )
409 /* check if we are already open */
415 /* Try to open tdb passwd. Create a new one if necessary */
417 db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
418 if (db_sam == NULL) {
419 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
424 /* Check the version */
425 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
427 version = 0; /* Version not found, assume version 0 */
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 */
436 /* Compare the version */
437 if (version > TDBSAM_VERSION) {
438 /* Version more recent than the latest known */
439 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
444 if ( version < TDBSAM_VERSION ||
445 (version == TDBSAM_VERSION &&
446 minor_version < TDBSAM_MINOR_VERSION) ) {
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.
455 struct named_mutex *mtx = grab_named_mutex(NULL,
456 "tdbsam_upgrade_mutex",
460 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
465 /* Re-check the version */
466 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
468 version = 0; /* Version not found, assume version 0 */
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 */
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));
486 if ( version < TDBSAM_VERSION ||
487 (version == TDBSAM_VERSION &&
488 minor_version < TDBSAM_MINOR_VERSION) ) {
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.
498 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
503 TDBSAM_MINOR_VERSION));
505 if ( !tdbsam_convert(&db_sam, name, version) ) {
506 DEBUG(0, ("tdbsam_open: Error when trying to convert "
507 "tdbsam [%s]\n",name));
513 DEBUG(3, ("TDBSAM converted successfully.\n"));
518 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
523 /******************************************************************
524 Lookup a name in the SAM TDB
525 ******************************************************************/
527 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
528 struct samu *user, const char *sname)
535 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
536 return NT_STATUS_NO_MEMORY;
539 /* Data is stored in all lower-case */
540 fstrcpy(name, sname);
544 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
546 /* open the database */
548 if ( !tdbsam_open( tdbsam_filename ) ) {
549 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
550 return NT_STATUS_ACCESS_DENIED;
555 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
557 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
558 DEBUGADD(5, (" Key: %s\n", keystr));
559 return NT_STATUS_NO_SUCH_USER;
562 /* unpack the buffer */
564 if (!init_samu_from_buffer(user, SAMU_BUFFER_LATEST, data.dptr, data.dsize)) {
565 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
566 SAFE_FREE(data.dptr);
567 return NT_STATUS_NO_MEMORY;
572 TALLOC_FREE(data.dptr);
577 /***************************************************************************
579 **************************************************************************/
581 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
582 struct samu *user, uint32 rid)
584 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
590 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
596 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
598 /* open the database */
600 if ( !tdbsam_open( tdbsam_filename ) ) {
601 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename));
602 return NT_STATUS_ACCESS_DENIED;
607 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
609 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
610 return NT_STATUS_UNSUCCESSFUL;
613 fstrcpy(name, (const char *)data.dptr);
614 TALLOC_FREE(data.dptr);
616 return tdbsam_getsampwnam (my_methods, user, name);
619 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
620 struct samu * user, const DOM_SID *sid)
624 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
625 return NT_STATUS_UNSUCCESSFUL;
627 return tdbsam_getsampwrid(my_methods, user, rid);
630 static bool tdb_delete_samacct_only( struct samu *sam_pass )
636 fstrcpy(name, pdb_get_username(sam_pass));
639 /* set the search key */
641 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
643 /* it's outaa here! 8^) */
644 if ( !tdbsam_open( tdbsam_filename ) ) {
645 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
650 status = dbwrap_delete_bystring(db_sam, keystr);
651 if (!NT_STATUS_IS_OK(status)) {
652 DEBUG(5, ("Error deleting entry from tdb passwd "
653 "database: %s!\n", nt_errstr(status)));
660 /***************************************************************************
661 Delete a struct samu records for the username and RID key
662 ****************************************************************************/
664 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
665 struct samu *sam_pass)
667 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
672 /* open the database */
674 if ( !tdbsam_open( tdbsam_filename ) ) {
675 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
677 return NT_STATUS_ACCESS_DENIED;
680 fstrcpy(name, pdb_get_username(sam_pass));
683 /* set the search key */
685 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
687 rid = pdb_get_user_rid(sam_pass);
689 /* it's outaa here! 8^) */
691 if (db_sam->transaction_start(db_sam) != 0) {
692 DEBUG(0, ("Could not start transaction\n"));
693 return NT_STATUS_UNSUCCESSFUL;
696 nt_status = dbwrap_delete_bystring(db_sam, keystr);
697 if (!NT_STATUS_IS_OK(nt_status)) {
698 DEBUG(5, ("Error deleting entry from tdb passwd "
699 "database: %s!\n", nt_errstr(nt_status)));
703 /* set the search key */
705 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
707 /* it's outaa here! 8^) */
709 nt_status = dbwrap_delete_bystring(db_sam, keystr);
710 if (!NT_STATUS_IS_OK(nt_status)) {
711 DEBUG(5, ("Error deleting entry from tdb rid "
712 "database: %s!\n", nt_errstr(nt_status)));
716 if (db_sam->transaction_commit(db_sam) != 0) {
717 DEBUG(0, ("Could not commit transaction\n"));
718 return NT_STATUS_INTERNAL_DB_CORRUPTION;
724 if (db_sam->transaction_cancel(db_sam) != 0) {
725 smb_panic("transaction_cancel failed");
732 /***************************************************************************
733 Update the TDB SAM account record only
734 Assumes that the tdbsam is already open
735 ****************************************************************************/
736 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
745 /* copy the struct samu struct into a BYTE buffer for storage */
747 if ( (data.dsize=init_buffer_from_samu(&buf, newpwd, False)) == -1 ) {
748 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
753 fstrcpy(name, pdb_get_username(newpwd));
756 DEBUG(5, ("Storing %saccount %s with RID %d\n",
757 flag == TDB_INSERT ? "(new) " : "", name,
758 pdb_get_user_rid(newpwd)));
760 /* setup the USER index key */
761 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
763 /* add the account */
765 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
766 if (!NT_STATUS_IS_OK(status)) {
767 DEBUG(0, ("Unable to modify passwd TDB: %s!",
780 /***************************************************************************
781 Update the TDB SAM RID record only
782 Assumes that the tdbsam is already open
783 ****************************************************************************/
784 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
791 fstrcpy(name, pdb_get_username(newpwd));
795 data = string_term_tdb_data(name);
797 /* setup the RID index key */
798 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
799 pdb_get_user_rid(newpwd));
801 /* add the reference */
802 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
803 if (!NT_STATUS_IS_OK(status)) {
804 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
813 /***************************************************************************
815 ****************************************************************************/
817 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
820 if (!pdb_get_user_rid(newpwd)) {
821 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
822 pdb_get_username(newpwd)));
826 /* open the database */
828 if ( !tdbsam_open( tdbsam_filename ) ) {
829 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
833 if (db_sam->transaction_start(db_sam) != 0) {
834 DEBUG(0, ("Could not start transaction\n"));
838 if (!tdb_update_samacct_only(newpwd, flag)
839 || !tdb_update_ridrec_only(newpwd, flag)) {
843 if (db_sam->transaction_commit(db_sam) != 0) {
844 DEBUG(0, ("Could not commit transaction\n"));
851 if (db_sam->transaction_cancel(db_sam) != 0) {
852 smb_panic("transaction_cancel failed");
857 /***************************************************************************
858 Modifies an existing struct samu
859 ****************************************************************************/
861 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
863 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
864 return NT_STATUS_UNSUCCESSFUL;
869 /***************************************************************************
870 Adds an existing struct samu
871 ****************************************************************************/
873 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
875 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
876 return NT_STATUS_UNSUCCESSFUL;
881 /***************************************************************************
882 Renames a struct samu
883 - check for the posix user/rename user script
884 - Add and lock the new user record
885 - rename the posix user
886 - rewrite the rid->username record
887 - delete the old user
888 - unlock the new user record
889 ***************************************************************************/
890 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
891 struct samu *old_acct,
894 struct samu *new_acct = NULL;
895 char *rename_script = NULL;
897 fstring oldname_lower;
898 fstring newname_lower;
900 /* can't do anything without an external script */
902 if ( !(new_acct = samu_new( talloc_tos() )) ) {
903 return NT_STATUS_NO_MEMORY;
906 rename_script = talloc_strdup(new_acct, lp_renameuser_script());
907 if (!rename_script) {
908 TALLOC_FREE(new_acct);
909 return NT_STATUS_NO_MEMORY;
911 if (!*rename_script) {
912 TALLOC_FREE(new_acct);
913 return NT_STATUS_ACCESS_DENIED;
916 if ( !pdb_copy_sam_account(new_acct, old_acct)
917 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
919 TALLOC_FREE(new_acct);
920 return NT_STATUS_NO_MEMORY;
923 /* open the database */
924 if ( !tdbsam_open( tdbsam_filename ) ) {
925 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
927 TALLOC_FREE(new_acct);
928 return NT_STATUS_ACCESS_DENIED;
931 if (db_sam->transaction_start(db_sam) != 0) {
932 DEBUG(0, ("Could not start transaction\n"));
933 TALLOC_FREE(new_acct);
934 return NT_STATUS_ACCESS_DENIED;
938 /* add the new account and lock it */
939 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
943 /* Rename the posix user. Follow the semantics of _samr_create_user()
944 so that we lower case the posix name but preserve the case in passdb */
946 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
947 strlower_m( oldname_lower );
949 fstrcpy( newname_lower, newname );
950 strlower_m( newname_lower );
952 rename_script = talloc_string_sub2(new_acct,
959 if (!rename_script) {
962 rename_script = talloc_string_sub2(new_acct,
969 if (!rename_script) {
972 rename_ret = smbrun(rename_script, NULL);
974 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
975 rename_script, rename_ret));
977 if (rename_ret != 0) {
981 smb_nscd_flush_user_cache();
983 /* rewrite the rid->username record */
985 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
989 tdb_delete_samacct_only( old_acct );
991 if (db_sam->transaction_commit(db_sam) != 0) {
993 * Ok, we're screwed. We've changed the posix account, but
994 * could not adapt passdb.tdb. Shall we change the posix
997 DEBUG(0, ("transaction_commit failed\n"));
998 TALLOC_FREE(new_acct);
999 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1002 TALLOC_FREE(new_acct );
1003 return NT_STATUS_OK;
1006 if (db_sam->transaction_cancel(db_sam) != 0) {
1007 smb_panic("transaction_cancel failed");
1010 TALLOC_FREE(new_acct);
1012 return NT_STATUS_ACCESS_DENIED;
1015 static bool tdbsam_rid_algorithm(struct pdb_methods *methods)
1020 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1024 rid = BASE_RID; /* Default if not set */
1026 if (!tdbsam_open(tdbsam_filename)) {
1027 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1032 if (dbwrap_change_uint32_atomic(db_sam, NEXT_RID_STRING, &rid, 1) != 0) {
1033 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s\n",
1043 struct tdbsam_search_state {
1044 struct pdb_methods *methods;
1045 uint32_t acct_flags;
1053 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1055 struct tdbsam_search_state *state = talloc_get_type_abort(
1056 private_data, struct tdbsam_search_state);
1057 size_t prefixlen = strlen(RIDPREFIX);
1060 if ((rec->key.dsize < prefixlen)
1061 || (strncmp((char *)rec->key.dptr, RIDPREFIX, prefixlen))) {
1065 rid = strtoul((char *)rec->key.dptr+prefixlen, NULL, 16);
1067 ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1068 &state->array_size);
1073 static void tdbsam_search_end(struct pdb_search *search)
1075 struct tdbsam_search_state *state = talloc_get_type_abort(
1076 search->private_data, struct tdbsam_search_state);
1080 static bool tdbsam_search_next_entry(struct pdb_search *search,
1081 struct samr_displayentry *entry)
1083 struct tdbsam_search_state *state = talloc_get_type_abort(
1084 search->private_data, struct tdbsam_search_state);
1085 struct samu *user = NULL;
1091 user = samu_new(talloc_tos());
1093 DEBUG(0, ("samu_new failed\n"));
1097 if (state->current == state->num_rids) {
1101 rid = state->rids[state->current++];
1103 status = tdbsam_getsampwrid(state->methods, user, rid);
1105 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1107 * Someone has deleted that user since we listed the RIDs
1112 if (!NT_STATUS_IS_OK(status)) {
1113 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1114 nt_errstr(status)));
1119 if ((state->acct_flags != 0) &&
1120 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1124 entry->acct_flags = pdb_get_acct_ctrl(user);
1126 entry->account_name = talloc_strdup(search, pdb_get_username(user));
1127 entry->fullname = talloc_strdup(search, pdb_get_fullname(user));
1128 entry->description = talloc_strdup(search, pdb_get_acct_desc(user));
1132 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1133 || (entry->description == NULL)) {
1134 DEBUG(0, ("talloc_strdup failed\n"));
1141 static bool tdbsam_search_users(struct pdb_methods *methods,
1142 struct pdb_search *search,
1145 struct tdbsam_search_state *state;
1147 if (!tdbsam_open(tdbsam_filename)) {
1148 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1153 state = talloc_zero(search, struct tdbsam_search_state);
1154 if (state == NULL) {
1155 DEBUG(0, ("talloc failed\n"));
1158 state->acct_flags = acct_flags;
1159 state->methods = methods;
1161 db_sam->traverse_read(db_sam, tdbsam_collect_rids, state);
1163 search->private_data = state;
1164 search->next_entry = tdbsam_search_next_entry;
1165 search->search_end = tdbsam_search_end;
1170 /*********************************************************************
1171 Initialize the tdb sam backend. Setup the dispath table of methods,
1172 open the tdb, etc...
1173 *********************************************************************/
1175 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1178 char *tdbfile = NULL;
1179 const char *pfile = location;
1181 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1185 (*pdb_method)->name = "tdbsam";
1187 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1188 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1189 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1190 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1191 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1192 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1193 (*pdb_method)->search_users = tdbsam_search_users;
1195 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1196 (*pdb_method)->new_rid = tdbsam_new_rid;
1198 /* save the path for later */
1201 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1202 PASSDB_FILE_NAME) < 0) {
1203 return NT_STATUS_NO_MEMORY;
1207 tdbsam_filename = SMB_STRDUP(pfile);
1208 if (!tdbsam_filename) {
1209 return NT_STATUS_NO_MEMORY;
1213 /* no private data */
1215 (*pdb_method)->private_data = NULL;
1216 (*pdb_method)->free_private_data = NULL;
1218 return NT_STATUS_OK;
1221 NTSTATUS pdb_tdbsam_init(void)
1223 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);