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 /* This is safe from other users as we know we're
254 * under a mutex here. */
256 if (rename(tmp_fname, dbname) == -1) {
257 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
261 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
265 TALLOC_FREE(orig_db);
267 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
270 /* Replace the global db pointer. */
276 if (orig_db->transaction_cancel(orig_db) != 0) {
277 smb_panic("tdbsam_convert: transaction_cancel failed");
280 if (tmp_db->transaction_cancel(tmp_db) != 0) {
281 smb_panic("tdbsam_convert: transaction_cancel failed");
290 static bool tdbsam_upgrade_next_rid(struct db_context *db)
296 ok = dbwrap_fetch_uint32(db, NEXT_RID_STRING, &rid);
301 tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
302 TDB_DEFAULT, O_RDONLY, 0644);
305 ok = tdb_fetch_uint32(tdb, "RID_COUNTER", &rid);
314 if (dbwrap_store_uint32(db, NEXT_RID_STRING, rid) != 0) {
321 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from)
323 struct tdbsam_convert_state state;
324 struct db_context *db = NULL;
327 /* We only need the update backup for local db's. */
328 if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) {
329 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name));
335 state.success = true;
337 if (db->transaction_start(db) != 0) {
338 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
342 if (!tdbsam_upgrade_next_rid(db)) {
343 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
347 ret = db->traverse(db, tdbsam_convert_one, &state);
349 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
353 if (!state.success) {
354 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
358 if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING,
359 TDBSAM_VERSION) != 0) {
360 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n"));
364 if (dbwrap_store_int32(db, TDBSAM_MINOR_VERSION_STRING,
365 TDBSAM_MINOR_VERSION) != 0) {
366 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor version\n"));
370 if (db->transaction_commit(db) != 0) {
371 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
378 if (db->transaction_cancel(db) != 0) {
379 smb_panic("tdbsam_convert: transaction_cancel failed");
385 /*********************************************************************
386 Open the tdbsam file based on the absolute path specified.
387 Uses a reference count to allow multiple open calls.
388 *********************************************************************/
390 static bool tdbsam_open( const char *name )
395 /* check if we are already open */
401 /* Try to open tdb passwd. Create a new one if necessary */
403 db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
404 if (db_sam == NULL) {
405 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
410 /* Check the version */
411 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
413 version = 0; /* Version not found, assume version 0 */
416 /* Get the minor version */
417 minor_version = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING);
418 if (minor_version == -1) {
419 minor_version = 0; /* Minor version not found, assume 0 */
422 /* Compare the version */
423 if (version > TDBSAM_VERSION) {
424 /* Version more recent than the latest known */
425 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
430 if ( version < TDBSAM_VERSION ||
431 (version == TDBSAM_VERSION &&
432 minor_version < TDBSAM_MINOR_VERSION) ) {
434 * Ok - we think we're going to have to convert.
435 * Due to the backup process we now must do to
436 * upgrade we have to get a mutex and re-check
437 * the version. Someone else may have upgraded
438 * whilst we were checking.
441 struct named_mutex *mtx = grab_named_mutex(NULL,
442 "tdbsam_upgrade_mutex",
446 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
451 /* Re-check the version */
452 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
454 version = 0; /* Version not found, assume version 0 */
457 /* Re-check the minor version */
458 minor_version = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING);
459 if (minor_version == -1) {
460 minor_version = 0; /* Minor version not found, assume 0 */
463 /* Compare the version */
464 if (version > TDBSAM_VERSION) {
465 /* Version more recent than the latest known */
466 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
472 if ( version < TDBSAM_VERSION ||
473 (version == TDBSAM_VERSION &&
474 minor_version < TDBSAM_MINOR_VERSION) ) {
476 * Note that minor versions we read that are greater
477 * than the current minor version we have hard coded
478 * are assumed to be compatible if they have the same
479 * major version. That allows previous versions of the
480 * passdb code that don't know about minor versions to
481 * still use this database. JRA.
484 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
489 TDBSAM_MINOR_VERSION));
491 if ( !tdbsam_convert(&db_sam, name, version) ) {
492 DEBUG(0, ("tdbsam_open: Error when trying to convert "
493 "tdbsam [%s]\n",name));
499 DEBUG(3, ("TDBSAM converted successfully.\n"));
504 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
509 /******************************************************************
510 Lookup a name in the SAM TDB
511 ******************************************************************/
513 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
514 struct samu *user, const char *sname)
521 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
522 return NT_STATUS_NO_MEMORY;
525 /* Data is stored in all lower-case */
526 fstrcpy(name, sname);
530 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
532 /* open the database */
534 if ( !tdbsam_open( tdbsam_filename ) ) {
535 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
536 return NT_STATUS_ACCESS_DENIED;
541 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
543 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
544 DEBUGADD(5, (" Key: %s\n", keystr));
545 return NT_STATUS_NO_SUCH_USER;
548 /* unpack the buffer */
550 if (!init_samu_from_buffer(user, SAMU_BUFFER_LATEST, data.dptr, data.dsize)) {
551 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
552 SAFE_FREE(data.dptr);
553 return NT_STATUS_NO_MEMORY;
558 TALLOC_FREE(data.dptr);
563 /***************************************************************************
565 **************************************************************************/
567 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
568 struct samu *user, uint32 rid)
570 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
576 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
582 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
584 /* open the database */
586 if ( !tdbsam_open( tdbsam_filename ) ) {
587 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename));
588 return NT_STATUS_ACCESS_DENIED;
593 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
595 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
596 return NT_STATUS_UNSUCCESSFUL;
599 fstrcpy(name, (const char *)data.dptr);
600 TALLOC_FREE(data.dptr);
602 return tdbsam_getsampwnam (my_methods, user, name);
605 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
606 struct samu * user, const DOM_SID *sid)
610 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
611 return NT_STATUS_UNSUCCESSFUL;
613 return tdbsam_getsampwrid(my_methods, user, rid);
616 static bool tdb_delete_samacct_only( struct samu *sam_pass )
622 fstrcpy(name, pdb_get_username(sam_pass));
625 /* set the search key */
627 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
629 /* it's outaa here! 8^) */
630 if ( !tdbsam_open( tdbsam_filename ) ) {
631 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
636 status = dbwrap_delete_bystring(db_sam, keystr);
637 if (!NT_STATUS_IS_OK(status)) {
638 DEBUG(5, ("Error deleting entry from tdb passwd "
639 "database: %s!\n", nt_errstr(status)));
646 /***************************************************************************
647 Delete a struct samu records for the username and RID key
648 ****************************************************************************/
650 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
651 struct samu *sam_pass)
653 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
658 /* open the database */
660 if ( !tdbsam_open( tdbsam_filename ) ) {
661 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
663 return NT_STATUS_ACCESS_DENIED;
666 fstrcpy(name, pdb_get_username(sam_pass));
669 /* set the search key */
671 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
673 rid = pdb_get_user_rid(sam_pass);
675 /* it's outaa here! 8^) */
677 if (db_sam->transaction_start(db_sam) != 0) {
678 DEBUG(0, ("Could not start transaction\n"));
679 return NT_STATUS_UNSUCCESSFUL;
682 nt_status = dbwrap_delete_bystring(db_sam, keystr);
683 if (!NT_STATUS_IS_OK(nt_status)) {
684 DEBUG(5, ("Error deleting entry from tdb passwd "
685 "database: %s!\n", nt_errstr(nt_status)));
689 /* set the search key */
691 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
693 /* it's outaa here! 8^) */
695 nt_status = dbwrap_delete_bystring(db_sam, keystr);
696 if (!NT_STATUS_IS_OK(nt_status)) {
697 DEBUG(5, ("Error deleting entry from tdb rid "
698 "database: %s!\n", nt_errstr(nt_status)));
702 if (db_sam->transaction_commit(db_sam) != 0) {
703 DEBUG(0, ("Could not commit transaction\n"));
704 return NT_STATUS_INTERNAL_DB_CORRUPTION;
710 if (db_sam->transaction_cancel(db_sam) != 0) {
711 smb_panic("transaction_cancel failed");
718 /***************************************************************************
719 Update the TDB SAM account record only
720 Assumes that the tdbsam is already open
721 ****************************************************************************/
722 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
731 /* copy the struct samu struct into a BYTE buffer for storage */
733 if ( (data.dsize=init_buffer_from_samu(&buf, newpwd, False)) == -1 ) {
734 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
739 fstrcpy(name, pdb_get_username(newpwd));
742 DEBUG(5, ("Storing %saccount %s with RID %d\n",
743 flag == TDB_INSERT ? "(new) " : "", name,
744 pdb_get_user_rid(newpwd)));
746 /* setup the USER index key */
747 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
749 /* add the account */
751 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
752 if (!NT_STATUS_IS_OK(status)) {
753 DEBUG(0, ("Unable to modify passwd TDB: %s!",
766 /***************************************************************************
767 Update the TDB SAM RID record only
768 Assumes that the tdbsam is already open
769 ****************************************************************************/
770 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
777 fstrcpy(name, pdb_get_username(newpwd));
781 data = string_term_tdb_data(name);
783 /* setup the RID index key */
784 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
785 pdb_get_user_rid(newpwd));
787 /* add the reference */
788 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
789 if (!NT_STATUS_IS_OK(status)) {
790 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
799 /***************************************************************************
801 ****************************************************************************/
803 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
806 if (!pdb_get_user_rid(newpwd)) {
807 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
808 pdb_get_username(newpwd)));
812 /* open the database */
814 if ( !tdbsam_open( tdbsam_filename ) ) {
815 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
819 if (db_sam->transaction_start(db_sam) != 0) {
820 DEBUG(0, ("Could not start transaction\n"));
824 if (!tdb_update_samacct_only(newpwd, flag)
825 || !tdb_update_ridrec_only(newpwd, flag)) {
829 if (db_sam->transaction_commit(db_sam) != 0) {
830 DEBUG(0, ("Could not commit transaction\n"));
837 if (db_sam->transaction_cancel(db_sam) != 0) {
838 smb_panic("transaction_cancel failed");
843 /***************************************************************************
844 Modifies an existing struct samu
845 ****************************************************************************/
847 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
849 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
850 return NT_STATUS_UNSUCCESSFUL;
855 /***************************************************************************
856 Adds an existing struct samu
857 ****************************************************************************/
859 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
861 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
862 return NT_STATUS_UNSUCCESSFUL;
867 /***************************************************************************
868 Renames a struct samu
869 - check for the posix user/rename user script
870 - Add and lock the new user record
871 - rename the posix user
872 - rewrite the rid->username record
873 - delete the old user
874 - unlock the new user record
875 ***************************************************************************/
876 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
877 struct samu *old_acct,
880 struct samu *new_acct = NULL;
881 char *rename_script = NULL;
883 fstring oldname_lower;
884 fstring newname_lower;
886 /* can't do anything without an external script */
888 if ( !(new_acct = samu_new( talloc_tos() )) ) {
889 return NT_STATUS_NO_MEMORY;
892 rename_script = talloc_strdup(new_acct, lp_renameuser_script());
893 if (!rename_script) {
894 TALLOC_FREE(new_acct);
895 return NT_STATUS_NO_MEMORY;
897 if (!*rename_script) {
898 TALLOC_FREE(new_acct);
899 return NT_STATUS_ACCESS_DENIED;
902 if ( !pdb_copy_sam_account(new_acct, old_acct)
903 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
905 TALLOC_FREE(new_acct);
906 return NT_STATUS_NO_MEMORY;
909 /* open the database */
910 if ( !tdbsam_open( tdbsam_filename ) ) {
911 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
913 TALLOC_FREE(new_acct);
914 return NT_STATUS_ACCESS_DENIED;
917 if (db_sam->transaction_start(db_sam) != 0) {
918 DEBUG(0, ("Could not start transaction\n"));
919 TALLOC_FREE(new_acct);
920 return NT_STATUS_ACCESS_DENIED;
924 /* add the new account and lock it */
925 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
929 /* Rename the posix user. Follow the semantics of _samr_create_user()
930 so that we lower case the posix name but preserve the case in passdb */
932 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
933 strlower_m( oldname_lower );
935 fstrcpy( newname_lower, newname );
936 strlower_m( newname_lower );
938 rename_script = talloc_string_sub2(new_acct,
945 if (!rename_script) {
948 rename_script = talloc_string_sub2(new_acct,
955 if (!rename_script) {
958 rename_ret = smbrun(rename_script, NULL);
960 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
961 rename_script, rename_ret));
963 if (rename_ret != 0) {
967 smb_nscd_flush_user_cache();
969 /* rewrite the rid->username record */
971 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
975 tdb_delete_samacct_only( old_acct );
977 if (db_sam->transaction_commit(db_sam) != 0) {
979 * Ok, we're screwed. We've changed the posix account, but
980 * could not adapt passdb.tdb. Shall we change the posix
983 DEBUG(0, ("transaction_commit failed\n"));
984 TALLOC_FREE(new_acct);
985 return NT_STATUS_INTERNAL_DB_CORRUPTION;
988 TALLOC_FREE(new_acct );
992 if (db_sam->transaction_cancel(db_sam) != 0) {
993 smb_panic("transaction_cancel failed");
996 TALLOC_FREE(new_acct);
998 return NT_STATUS_ACCESS_DENIED;
1001 static bool tdbsam_rid_algorithm(struct pdb_methods *methods)
1006 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1010 rid = BASE_RID; /* Default if not set */
1012 if (!tdbsam_open(tdbsam_filename)) {
1013 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1018 if (dbwrap_change_uint32_atomic(db_sam, NEXT_RID_STRING, &rid, 1) != 0) {
1019 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s\n",
1029 struct tdbsam_search_state {
1030 struct pdb_methods *methods;
1031 uint32_t acct_flags;
1039 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1041 struct tdbsam_search_state *state = talloc_get_type_abort(
1042 private_data, struct tdbsam_search_state);
1043 size_t prefixlen = strlen(RIDPREFIX);
1046 if ((rec->key.dsize < prefixlen)
1047 || (strncmp((char *)rec->key.dptr, RIDPREFIX, prefixlen))) {
1051 rid = strtoul((char *)rec->key.dptr+prefixlen, NULL, 16);
1053 ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1054 &state->array_size);
1059 static void tdbsam_search_end(struct pdb_search *search)
1061 struct tdbsam_search_state *state = talloc_get_type_abort(
1062 search->private_data, struct tdbsam_search_state);
1066 static bool tdbsam_search_next_entry(struct pdb_search *search,
1067 struct samr_displayentry *entry)
1069 struct tdbsam_search_state *state = talloc_get_type_abort(
1070 search->private_data, struct tdbsam_search_state);
1071 struct samu *user = NULL;
1077 user = samu_new(talloc_tos());
1079 DEBUG(0, ("samu_new failed\n"));
1083 if (state->current == state->num_rids) {
1087 rid = state->rids[state->current++];
1089 status = tdbsam_getsampwrid(state->methods, user, rid);
1091 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1093 * Someone has deleted that user since we listed the RIDs
1098 if (!NT_STATUS_IS_OK(status)) {
1099 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1100 nt_errstr(status)));
1105 if ((state->acct_flags != 0) &&
1106 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1110 entry->acct_flags = pdb_get_acct_ctrl(user);
1112 entry->account_name = talloc_strdup(search, pdb_get_username(user));
1113 entry->fullname = talloc_strdup(search, pdb_get_fullname(user));
1114 entry->description = talloc_strdup(search, pdb_get_acct_desc(user));
1118 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1119 || (entry->description == NULL)) {
1120 DEBUG(0, ("talloc_strdup failed\n"));
1127 static bool tdbsam_search_users(struct pdb_methods *methods,
1128 struct pdb_search *search,
1131 struct tdbsam_search_state *state;
1133 if (!tdbsam_open(tdbsam_filename)) {
1134 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1139 state = talloc_zero(search, struct tdbsam_search_state);
1140 if (state == NULL) {
1141 DEBUG(0, ("talloc failed\n"));
1144 state->acct_flags = acct_flags;
1145 state->methods = methods;
1147 db_sam->traverse_read(db_sam, tdbsam_collect_rids, state);
1149 search->private_data = state;
1150 search->next_entry = tdbsam_search_next_entry;
1151 search->search_end = tdbsam_search_end;
1156 /*********************************************************************
1157 Initialize the tdb sam backend. Setup the dispath table of methods,
1158 open the tdb, etc...
1159 *********************************************************************/
1161 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1164 char *tdbfile = NULL;
1165 const char *pfile = location;
1167 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1171 (*pdb_method)->name = "tdbsam";
1173 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1174 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1175 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1176 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1177 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1178 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1179 (*pdb_method)->search_users = tdbsam_search_users;
1181 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1182 (*pdb_method)->new_rid = tdbsam_new_rid;
1184 /* save the path for later */
1187 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1188 PASSDB_FILE_NAME) < 0) {
1189 return NT_STATUS_NO_MEMORY;
1193 tdbsam_filename = SMB_STRDUP(pfile);
1194 if (!tdbsam_filename) {
1195 return NT_STATUS_NO_MEMORY;
1199 /* no private data */
1201 (*pdb_method)->private_data = NULL;
1202 (*pdb_method)->free_private_data = NULL;
1204 return NT_STATUS_OK;
1207 NTSTATUS pdb_tdbsam_init(void)
1209 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);