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/>.
26 #include "system/filesys.h"
28 #include "dbwrap/dbwrap.h"
29 #include "dbwrap/dbwrap_open.h"
30 #include "../libcli/security/security.h"
32 #include "passdb/pdb_tdb.h"
34 #if 0 /* when made a module use this */
36 static int tdbsam_debug_level = DBGC_ALL;
38 #define DBGC_CLASS tdbsam_debug_level
43 #define DBGC_CLASS DBGC_PASSDB
47 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */
48 #define TDBSAM_MINOR_VERSION 0 /* Most recent TDBSAM minor version */
49 #define TDBSAM_VERSION_STRING "INFO/version"
50 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version"
51 #define PASSDB_FILE_NAME "passdb.tdb"
52 #define USERPREFIX "USER_"
53 #define USERPREFIX_LEN 5
54 #define RIDPREFIX "RID_"
55 #define PRIVPREFIX "PRIV_"
56 #define NEXT_RID_STRING "NEXT_RID"
58 /* GLOBAL TDB SAM CONTEXT */
60 static struct db_context *db_sam;
61 static char *tdbsam_filename;
62 static bool map_builtin;
64 struct tdbsam_convert_state {
69 static int tdbsam_convert_one(struct db_record *rec, void *priv)
71 struct tdbsam_convert_state *state =
72 (struct tdbsam_convert_state *)priv;
80 key = dbwrap_record_get_key(rec);
82 if (key.dsize < USERPREFIX_LEN) {
85 if (strncmp((char *)key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
89 user = samu_new(talloc_tos());
91 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
92 state->success = false;
96 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
97 "(version:%d)\n", (char *)key.dptr, state->from));
99 value = dbwrap_record_get_value(rec);
101 switch (state->from) {
103 ret = init_samu_from_buffer(user, SAMU_BUFFER_V0,
108 ret = init_samu_from_buffer(user, SAMU_BUFFER_V1,
113 ret = init_samu_from_buffer(user, SAMU_BUFFER_V2,
118 ret = init_samu_from_buffer(user, SAMU_BUFFER_V3,
123 ret = init_samu_from_buffer(user, SAMU_BUFFER_V4,
128 /* unknown tdbsam version */
132 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
133 "from TDB (key:%s) (version:%d)\n", (char *)key.dptr,
136 state->success = false;
140 data.dsize = init_buffer_from_samu(&data.dptr, user, false);
143 if (data.dsize == -1) {
144 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
145 "the new format\n"));
146 state->success = false;
150 status = dbwrap_record_store(rec, data, TDB_MODIFY);
151 if (!NT_STATUS_IS_OK(status)) {
152 DEBUG(0, ("Could not store the new record: %s\n",
154 state->success = false;
161 /**********************************************************************
162 Struct and function to backup an old record.
163 *********************************************************************/
165 struct tdbsam_backup_state {
166 struct db_context *new_db;
170 static int backup_copy_fn(struct db_record *orig_rec, void *state)
172 struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state;
173 struct db_record *new_rec;
178 key = dbwrap_record_get_key(orig_rec);
180 new_rec = dbwrap_fetch_locked(bs->new_db, talloc_tos(), key);
181 if (new_rec == NULL) {
186 value = dbwrap_record_get_value(orig_rec);
188 status = dbwrap_record_store(new_rec, value, TDB_INSERT);
190 TALLOC_FREE(new_rec);
192 if (!NT_STATUS_IS_OK(status)) {
199 /**********************************************************************
200 Make a backup of an old passdb and replace the new one with it. We
201 have to do this as between 3.0.x and 3.2.x the hash function changed
202 by mistake (used unsigned char * instead of char *). This means the
203 previous simple update code will fail due to not being able to find
204 existing records to replace in the tdbsam_convert_one() function. JRA.
205 *********************************************************************/
207 static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db)
209 TALLOC_CTX *frame = talloc_stackframe();
210 const char *tmp_fname = NULL;
211 struct db_context *tmp_db = NULL;
212 struct db_context *orig_db = *pp_db;
213 struct tdbsam_backup_state bs;
216 tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname);
224 /* Remember to open this on the NULL context. We need
225 * it to stay around after we return from here. */
227 tmp_db = db_open(NULL, tmp_fname, 0,
228 TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
229 DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
230 if (tmp_db == NULL) {
231 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
232 "[%s]\n", tmp_fname));
237 if (dbwrap_transaction_start(orig_db) != 0) {
238 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
244 if (dbwrap_transaction_start(tmp_db) != 0) {
245 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
246 dbwrap_transaction_cancel(orig_db);
256 status = dbwrap_traverse(orig_db, backup_copy_fn, (void *)&bs, NULL);
257 if (!NT_STATUS_IS_OK(status)) {
258 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
263 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
267 if (dbwrap_transaction_commit(orig_db) != 0) {
268 smb_panic("tdbsam_convert_backup: orig commit failed\n");
270 if (dbwrap_transaction_commit(tmp_db) != 0) {
271 smb_panic("tdbsam_convert_backup: orig commit failed\n");
274 /* be sure to close the DBs _before_ renaming the file */
276 TALLOC_FREE(orig_db);
279 /* This is safe from other users as we know we're
280 * under a mutex here. */
282 if (rename(tmp_fname, dbname) == -1) {
283 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
287 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
292 /* re-open the converted TDB */
294 orig_db = db_open(NULL, dbname, 0,
295 TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
296 DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
297 if (orig_db == NULL) {
298 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
299 "converted passdb TDB [%s]\n", dbname));
303 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
306 /* Replace the global db pointer. */
312 if (dbwrap_transaction_cancel(orig_db) != 0) {
313 smb_panic("tdbsam_convert: transaction_cancel failed");
316 if (dbwrap_transaction_cancel(tmp_db) != 0) {
317 smb_panic("tdbsam_convert: transaction_cancel failed");
326 static bool tdbsam_upgrade_next_rid(struct db_context *db)
334 status = dbwrap_fetch_uint32_bystring(db, NEXT_RID_STRING, &rid);
335 if (NT_STATUS_IS_OK(status)) {
339 db_path = state_path("winbindd_idmap.tdb");
340 if (db_path == NULL) {
344 tdb = tdb_open_log(db_path, 0,
345 TDB_DEFAULT, O_RDONLY, 0644);
346 TALLOC_FREE(db_path);
348 ok = tdb_fetch_uint32(tdb, "RID_COUNTER", &rid);
357 status = dbwrap_store_uint32_bystring(db, NEXT_RID_STRING, rid);
358 if (!NT_STATUS_IS_OK(status)) {
365 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from)
367 struct tdbsam_convert_state state;
368 struct db_context *db = NULL;
371 /* We only need the update backup for local db's. */
372 if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) {
373 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name));
379 state.success = true;
381 if (dbwrap_transaction_start(db) != 0) {
382 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
386 if (!tdbsam_upgrade_next_rid(db)) {
387 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
391 status = dbwrap_traverse(db, tdbsam_convert_one, &state, NULL);
392 if (!NT_STATUS_IS_OK(status)) {
393 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
397 if (!state.success) {
398 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
402 status = dbwrap_store_int32_bystring(db, TDBSAM_VERSION_STRING,
404 if (!NT_STATUS_IS_OK(status)) {
405 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version: "
406 "%s\n", nt_errstr(status)));
410 status = dbwrap_store_int32_bystring(db, TDBSAM_MINOR_VERSION_STRING,
411 TDBSAM_MINOR_VERSION);
412 if (!NT_STATUS_IS_OK(status)) {
413 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor "
414 "version: %s\n", nt_errstr(status)));
418 if (dbwrap_transaction_commit(db) != 0) {
419 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
426 if (dbwrap_transaction_cancel(db) != 0) {
427 smb_panic("tdbsam_convert: transaction_cancel failed");
433 /*********************************************************************
434 Open the tdbsam file based on the absolute path specified.
435 Uses a reference count to allow multiple open calls.
436 *********************************************************************/
438 static bool tdbsam_open( const char *name )
444 /* check if we are already open */
450 /* Try to open tdb passwd. Create a new one if necessary */
452 db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
453 DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
454 if (db_sam == NULL) {
455 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
460 /* Check the version */
461 status = dbwrap_fetch_int32_bystring(db_sam, TDBSAM_VERSION_STRING,
463 if (!NT_STATUS_IS_OK(status)) {
464 version = 0; /* Version not found, assume version 0 */
467 /* Get the minor version */
468 status = dbwrap_fetch_int32_bystring(
469 db_sam, TDBSAM_MINOR_VERSION_STRING, &minor_version);
470 if (!NT_STATUS_IS_OK(status)) {
471 minor_version = 0; /* Minor version not found, assume 0 */
474 /* Compare the version */
475 if (version > TDBSAM_VERSION) {
476 /* Version more recent than the latest known */
477 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
482 if ( version < TDBSAM_VERSION ||
483 (version == TDBSAM_VERSION &&
484 minor_version < TDBSAM_MINOR_VERSION) ) {
486 * Ok - we think we're going to have to convert.
487 * Due to the backup process we now must do to
488 * upgrade we have to get a mutex and re-check
489 * the version. Someone else may have upgraded
490 * whilst we were checking.
493 struct named_mutex *mtx = grab_named_mutex(NULL,
494 "tdbsam_upgrade_mutex",
498 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
503 /* Re-check the version */
504 status = dbwrap_fetch_int32_bystring(
505 db_sam, TDBSAM_VERSION_STRING, &version);
506 if (!NT_STATUS_IS_OK(status)) {
507 version = 0; /* Version not found, assume version 0 */
510 /* Re-check the minor version */
511 status = dbwrap_fetch_int32_bystring(
512 db_sam, TDBSAM_MINOR_VERSION_STRING, &minor_version);
513 if (!NT_STATUS_IS_OK(status)) {
514 minor_version = 0; /* Minor version not found, assume 0 */
517 /* Compare the version */
518 if (version > TDBSAM_VERSION) {
519 /* Version more recent than the latest known */
520 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
526 if ( version < TDBSAM_VERSION ||
527 (version == TDBSAM_VERSION &&
528 minor_version < TDBSAM_MINOR_VERSION) ) {
530 * Note that minor versions we read that are greater
531 * than the current minor version we have hard coded
532 * are assumed to be compatible if they have the same
533 * major version. That allows previous versions of the
534 * passdb code that don't know about minor versions to
535 * still use this database. JRA.
538 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
543 TDBSAM_MINOR_VERSION));
545 if ( !tdbsam_convert(&db_sam, name, version) ) {
546 DEBUG(0, ("tdbsam_open: Error when trying to convert "
547 "tdbsam [%s]\n",name));
553 DEBUG(3, ("TDBSAM converted successfully.\n"));
558 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
563 /******************************************************************
564 Lookup a name in the SAM TDB
565 ******************************************************************/
567 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
568 struct samu *user, const char *sname)
576 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
577 return NT_STATUS_NO_MEMORY;
580 /* Data is stored in all lower-case */
581 fstrcpy(name, sname);
582 if (!strlower_m(name)) {
583 return NT_STATUS_INVALID_PARAMETER;
587 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
589 /* open the database */
591 if ( !tdbsam_open( tdbsam_filename ) ) {
592 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
593 return NT_STATUS_ACCESS_DENIED;
598 status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
599 if (!NT_STATUS_IS_OK(status)) {
600 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
601 DEBUGADD(5, (" Key: %s\n", keystr));
602 return NT_STATUS_NO_SUCH_USER;
605 /* unpack the buffer */
607 if (!init_samu_from_buffer(user, SAMU_BUFFER_LATEST, data.dptr, data.dsize)) {
608 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
609 SAFE_FREE(data.dptr);
610 return NT_STATUS_NO_MEMORY;
615 TALLOC_FREE(data.dptr);
620 /***************************************************************************
622 **************************************************************************/
624 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
625 struct samu *user, uint32 rid)
627 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
633 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
639 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
641 /* open the database */
643 if ( !tdbsam_open( tdbsam_filename ) ) {
644 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename));
645 return NT_STATUS_ACCESS_DENIED;
650 nt_status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
651 if (!NT_STATUS_IS_OK(nt_status)) {
652 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
656 fstrcpy(name, (const char *)data.dptr);
657 TALLOC_FREE(data.dptr);
659 return tdbsam_getsampwnam (my_methods, user, name);
662 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
663 struct samu * user, const struct dom_sid *sid)
667 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
668 return NT_STATUS_UNSUCCESSFUL;
670 return tdbsam_getsampwrid(my_methods, user, rid);
673 static bool tdb_delete_samacct_only( struct samu *sam_pass )
679 fstrcpy(name, pdb_get_username(sam_pass));
680 if (!strlower_m(name)) {
684 /* set the search key */
686 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
688 /* it's outaa here! 8^) */
689 if ( !tdbsam_open( tdbsam_filename ) ) {
690 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
695 status = dbwrap_delete_bystring(db_sam, keystr);
696 if (!NT_STATUS_IS_OK(status)) {
697 DEBUG(5, ("Error deleting entry from tdb passwd "
698 "database: %s!\n", nt_errstr(status)));
705 /***************************************************************************
706 Delete a struct samu records for the username and RID key
707 ****************************************************************************/
709 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
710 struct samu *sam_pass)
712 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
717 /* open the database */
719 if ( !tdbsam_open( tdbsam_filename ) ) {
720 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
722 return NT_STATUS_ACCESS_DENIED;
725 fstrcpy(name, pdb_get_username(sam_pass));
726 if (!strlower_m(name)) {
727 return NT_STATUS_INVALID_PARAMETER;
730 /* set the search key */
732 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
734 rid = pdb_get_user_rid(sam_pass);
736 /* it's outaa here! 8^) */
738 if (dbwrap_transaction_start(db_sam) != 0) {
739 DEBUG(0, ("Could not start transaction\n"));
740 return NT_STATUS_UNSUCCESSFUL;
743 nt_status = dbwrap_delete_bystring(db_sam, keystr);
744 if (!NT_STATUS_IS_OK(nt_status)) {
745 DEBUG(5, ("Error deleting entry from tdb passwd "
746 "database: %s!\n", nt_errstr(nt_status)));
750 /* set the search key */
752 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
754 /* it's outaa here! 8^) */
756 nt_status = dbwrap_delete_bystring(db_sam, keystr);
757 if (!NT_STATUS_IS_OK(nt_status)) {
758 DEBUG(5, ("Error deleting entry from tdb rid "
759 "database: %s!\n", nt_errstr(nt_status)));
763 if (dbwrap_transaction_commit(db_sam) != 0) {
764 DEBUG(0, ("Could not commit transaction\n"));
765 return NT_STATUS_INTERNAL_DB_CORRUPTION;
771 if (dbwrap_transaction_cancel(db_sam) != 0) {
772 smb_panic("transaction_cancel failed");
779 /***************************************************************************
780 Update the TDB SAM account record only
781 Assumes that the tdbsam is already open
782 ****************************************************************************/
783 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
792 /* copy the struct samu struct into a BYTE buffer for storage */
794 if ( (data.dsize=init_buffer_from_samu(&buf, newpwd, False)) == -1 ) {
795 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
800 fstrcpy(name, pdb_get_username(newpwd));
801 if (!strlower_m(name)) {
805 DEBUG(5, ("Storing %saccount %s with RID %d\n",
806 flag == TDB_INSERT ? "(new) " : "", name,
807 pdb_get_user_rid(newpwd)));
809 /* setup the USER index key */
810 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
812 /* add the account */
814 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
815 if (!NT_STATUS_IS_OK(status)) {
816 DEBUG(0, ("Unable to modify passwd TDB: %s!",
829 /***************************************************************************
830 Update the TDB SAM RID record only
831 Assumes that the tdbsam is already open
832 ****************************************************************************/
833 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
840 fstrcpy(name, pdb_get_username(newpwd));
841 if (!strlower_m(name)) {
846 data = string_term_tdb_data(name);
848 /* setup the RID index key */
849 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
850 pdb_get_user_rid(newpwd));
852 /* add the reference */
853 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
854 if (!NT_STATUS_IS_OK(status)) {
855 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
864 /***************************************************************************
866 ****************************************************************************/
868 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
874 if (!(newrid = pdb_get_user_rid(newpwd))) {
875 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
876 pdb_get_username(newpwd)));
882 /* open the database */
884 if ( !tdbsam_open( tdbsam_filename ) ) {
885 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
889 if (dbwrap_transaction_start(db_sam) != 0) {
890 DEBUG(0, ("Could not start transaction\n"));
894 /* If we are updating, we may be changing this users RID. Retrieve the old RID
897 if (flag == TDB_MODIFY) {
898 struct samu *account = samu_new(talloc_tos());
899 if (account == NULL) {
900 DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
903 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods, account, pdb_get_username(newpwd)))) {
904 DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
905 pdb_get_username(newpwd)));
906 TALLOC_FREE(account);
909 if (!(oldrid = pdb_get_user_rid(account))) {
910 DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
911 TALLOC_FREE(account);
914 TALLOC_FREE(account);
917 /* Update the new samu entry. */
918 if (!tdb_update_samacct_only(newpwd, flag)) {
922 /* Now take care of the case where the RID changed. We need
923 * to delete the old RID key and add the new. */
925 if (flag == TDB_MODIFY && newrid != oldrid) {
928 /* Delete old RID key */
929 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid));
930 slprintf(keystr, sizeof(keystr) - 1, "%s%.8x", RIDPREFIX, oldrid);
931 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam, keystr))) {
932 DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr));
935 /* Insert new RID key */
936 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid));
937 if (!tdb_update_ridrec_only(newpwd, TDB_INSERT)) {
941 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
942 flag == TDB_MODIFY ? "Updating" : "Inserting", newrid));
943 if (!tdb_update_ridrec_only(newpwd, flag)) {
948 if (dbwrap_transaction_commit(db_sam) != 0) {
949 DEBUG(0, ("Could not commit transaction\n"));
956 if (dbwrap_transaction_cancel(db_sam) != 0) {
957 smb_panic("transaction_cancel failed");
962 /***************************************************************************
963 Modifies an existing struct samu
964 ****************************************************************************/
966 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
968 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
969 return NT_STATUS_UNSUCCESSFUL;
974 /***************************************************************************
975 Adds an existing struct samu
976 ****************************************************************************/
978 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
980 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
981 return NT_STATUS_UNSUCCESSFUL;
986 /***************************************************************************
987 Renames a struct samu
988 - check for the posix user/rename user script
989 - Add and lock the new user record
990 - rename the posix user
991 - rewrite the rid->username record
992 - delete the old user
993 - unlock the new user record
994 ***************************************************************************/
995 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
996 struct samu *old_acct,
999 struct samu *new_acct = NULL;
1000 char *rename_script = NULL;
1002 fstring oldname_lower;
1003 fstring newname_lower;
1005 /* can't do anything without an external script */
1007 if ( !(new_acct = samu_new( talloc_tos() )) ) {
1008 return NT_STATUS_NO_MEMORY;
1011 rename_script = lp_rename_user_script(new_acct);
1012 if (!rename_script) {
1013 TALLOC_FREE(new_acct);
1014 return NT_STATUS_NO_MEMORY;
1016 if (!*rename_script) {
1017 TALLOC_FREE(new_acct);
1018 return NT_STATUS_ACCESS_DENIED;
1021 if ( !pdb_copy_sam_account(new_acct, old_acct)
1022 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1024 TALLOC_FREE(new_acct);
1025 return NT_STATUS_NO_MEMORY;
1028 /* open the database */
1029 if ( !tdbsam_open( tdbsam_filename ) ) {
1030 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1032 TALLOC_FREE(new_acct);
1033 return NT_STATUS_ACCESS_DENIED;
1036 if (dbwrap_transaction_start(db_sam) != 0) {
1037 DEBUG(0, ("Could not start transaction\n"));
1038 TALLOC_FREE(new_acct);
1039 return NT_STATUS_ACCESS_DENIED;
1043 /* add the new account and lock it */
1044 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1048 /* Rename the posix user. Follow the semantics of _samr_create_user()
1049 so that we lower case the posix name but preserve the case in passdb */
1051 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1052 if (!strlower_m( oldname_lower )) {
1056 fstrcpy( newname_lower, newname );
1057 if (!strlower_m( newname_lower )) {
1061 rename_script = talloc_string_sub2(new_acct,
1068 if (!rename_script) {
1071 rename_script = talloc_string_sub2(new_acct,
1078 if (!rename_script) {
1081 rename_ret = smbrun(rename_script, NULL);
1083 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
1084 rename_script, rename_ret));
1086 if (rename_ret != 0) {
1090 smb_nscd_flush_user_cache();
1092 /* rewrite the rid->username record */
1094 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1098 tdb_delete_samacct_only( old_acct );
1100 if (dbwrap_transaction_commit(db_sam) != 0) {
1102 * Ok, we're screwed. We've changed the posix account, but
1103 * could not adapt passdb.tdb. Shall we change the posix
1106 DEBUG(0, ("transaction_commit failed\n"));
1107 TALLOC_FREE(new_acct);
1108 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1111 TALLOC_FREE(new_acct );
1112 return NT_STATUS_OK;
1115 if (dbwrap_transaction_cancel(db_sam) != 0) {
1116 smb_panic("transaction_cancel failed");
1119 TALLOC_FREE(new_acct);
1121 return NT_STATUS_ACCESS_DENIED;
1124 static uint32_t tdbsam_capabilities(struct pdb_methods *methods)
1126 return PDB_CAP_STORE_RIDS;
1129 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1134 rid = BASE_RID; /* Default if not set */
1136 if (!tdbsam_open(tdbsam_filename)) {
1137 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1142 status = dbwrap_trans_change_uint32_atomic_bystring(
1143 db_sam, NEXT_RID_STRING, &rid, 1);
1144 if (!NT_STATUS_IS_OK(status)) {
1145 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1146 NEXT_RID_STRING, nt_errstr(status)));
1155 struct tdbsam_search_state {
1156 struct pdb_methods *methods;
1157 uint32_t acct_flags;
1165 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1167 struct tdbsam_search_state *state = talloc_get_type_abort(
1168 private_data, struct tdbsam_search_state);
1169 size_t prefixlen = strlen(RIDPREFIX);
1173 key = dbwrap_record_get_key(rec);
1175 if ((key.dsize < prefixlen)
1176 || (strncmp((char *)key.dptr, RIDPREFIX, prefixlen))) {
1180 rid = strtoul((char *)key.dptr+prefixlen, NULL, 16);
1182 ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1183 &state->array_size);
1188 static void tdbsam_search_end(struct pdb_search *search)
1190 struct tdbsam_search_state *state = talloc_get_type_abort(
1191 search->private_data, struct tdbsam_search_state);
1195 static bool tdbsam_search_next_entry(struct pdb_search *search,
1196 struct samr_displayentry *entry)
1198 struct tdbsam_search_state *state = talloc_get_type_abort(
1199 search->private_data, struct tdbsam_search_state);
1200 struct samu *user = NULL;
1206 user = samu_new(talloc_tos());
1208 DEBUG(0, ("samu_new failed\n"));
1212 if (state->current == state->num_rids) {
1217 rid = state->rids[state->current++];
1219 status = tdbsam_getsampwrid(state->methods, user, rid);
1221 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1223 * Someone has deleted that user since we listed the RIDs
1228 if (!NT_STATUS_IS_OK(status)) {
1229 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1230 nt_errstr(status)));
1235 if ((state->acct_flags != 0) &&
1236 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1240 entry->acct_flags = pdb_get_acct_ctrl(user);
1242 entry->account_name = talloc_strdup(search, pdb_get_username(user));
1243 entry->fullname = talloc_strdup(search, pdb_get_fullname(user));
1244 entry->description = talloc_strdup(search, pdb_get_acct_desc(user));
1248 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1249 || (entry->description == NULL)) {
1250 DEBUG(0, ("talloc_strdup failed\n"));
1257 static bool tdbsam_search_users(struct pdb_methods *methods,
1258 struct pdb_search *search,
1261 struct tdbsam_search_state *state;
1263 if (!tdbsam_open(tdbsam_filename)) {
1264 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1269 state = talloc_zero(search, struct tdbsam_search_state);
1270 if (state == NULL) {
1271 DEBUG(0, ("talloc failed\n"));
1274 state->acct_flags = acct_flags;
1275 state->methods = methods;
1277 dbwrap_traverse_read(db_sam, tdbsam_collect_rids, state, NULL);
1279 search->private_data = state;
1280 search->next_entry = tdbsam_search_next_entry;
1281 search->search_end = tdbsam_search_end;
1286 static bool tdbsam_is_responsible_for_builtin(struct pdb_methods *m)
1291 /*********************************************************************
1292 Initialize the tdb sam backend. Setup the dispath table of methods,
1293 open the tdb, etc...
1294 *********************************************************************/
1296 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1299 char *tdbfile = NULL;
1300 const char *pfile = location;
1302 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1306 (*pdb_method)->name = "tdbsam";
1308 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1309 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1310 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1311 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1312 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1313 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1314 (*pdb_method)->search_users = tdbsam_search_users;
1316 (*pdb_method)->capabilities = tdbsam_capabilities;
1317 (*pdb_method)->new_rid = tdbsam_new_rid;
1319 (*pdb_method)->is_responsible_for_builtin =
1320 tdbsam_is_responsible_for_builtin;
1321 map_builtin = lp_parm_bool(-1, "tdbsam", "map builtin", true);
1323 /* save the path for later */
1326 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1327 PASSDB_FILE_NAME) < 0) {
1328 return NT_STATUS_NO_MEMORY;
1332 tdbsam_filename = SMB_STRDUP(pfile);
1333 if (!tdbsam_filename) {
1334 return NT_STATUS_NO_MEMORY;
1338 /* no private data */
1340 (*pdb_method)->private_data = NULL;
1341 (*pdb_method)->free_private_data = NULL;
1343 return NT_STATUS_OK;
1346 NTSTATUS pdb_tdbsam_init(void)
1348 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);