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;
63 struct tdbsam_convert_state {
68 static int tdbsam_convert_one(struct db_record *rec, void *priv)
70 struct tdbsam_convert_state *state =
71 (struct tdbsam_convert_state *)priv;
79 key = dbwrap_record_get_key(rec);
81 if (key.dsize < USERPREFIX_LEN) {
84 if (strncmp((char *)key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
88 user = samu_new(talloc_tos());
90 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
91 state->success = false;
95 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
96 "(version:%d)\n", (char *)key.dptr, state->from));
98 value = dbwrap_record_get_value(rec);
100 switch (state->from) {
102 ret = init_samu_from_buffer(user, SAMU_BUFFER_V0,
107 ret = init_samu_from_buffer(user, SAMU_BUFFER_V1,
112 ret = init_samu_from_buffer(user, SAMU_BUFFER_V2,
117 ret = init_samu_from_buffer(user, SAMU_BUFFER_V3,
122 ret = init_samu_from_buffer(user, SAMU_BUFFER_V4,
127 /* unknown tdbsam version */
131 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
132 "from TDB (key:%s) (version:%d)\n", (char *)key.dptr,
135 state->success = false;
139 data.dsize = init_buffer_from_samu(&data.dptr, user, false);
142 if (data.dsize == -1) {
143 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
144 "the new format\n"));
145 state->success = false;
149 status = dbwrap_record_store(rec, data, TDB_MODIFY);
150 if (!NT_STATUS_IS_OK(status)) {
151 DEBUG(0, ("Could not store the new record: %s\n",
153 state->success = false;
160 /**********************************************************************
161 Struct and function to backup an old record.
162 *********************************************************************/
164 struct tdbsam_backup_state {
165 struct db_context *new_db;
169 static int backup_copy_fn(struct db_record *orig_rec, void *state)
171 struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state;
172 struct db_record *new_rec;
177 key = dbwrap_record_get_key(orig_rec);
179 new_rec = dbwrap_fetch_locked(bs->new_db, talloc_tos(), key);
180 if (new_rec == NULL) {
185 value = dbwrap_record_get_value(orig_rec);
187 status = dbwrap_record_store(new_rec, value, TDB_INSERT);
189 TALLOC_FREE(new_rec);
191 if (!NT_STATUS_IS_OK(status)) {
198 /**********************************************************************
199 Make a backup of an old passdb and replace the new one with it. We
200 have to do this as between 3.0.x and 3.2.x the hash function changed
201 by mistake (used unsigned char * instead of char *). This means the
202 previous simple update code will fail due to not being able to find
203 existing records to replace in the tdbsam_convert_one() function. JRA.
204 *********************************************************************/
206 static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db)
208 TALLOC_CTX *frame = talloc_stackframe();
209 const char *tmp_fname = NULL;
210 struct db_context *tmp_db = NULL;
211 struct db_context *orig_db = *pp_db;
212 struct tdbsam_backup_state bs;
215 tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname);
223 /* Remember to open this on the NULL context. We need
224 * it to stay around after we return from here. */
226 tmp_db = db_open(NULL, tmp_fname, 0,
227 TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
228 if (tmp_db == NULL) {
229 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
230 "[%s]\n", tmp_fname));
235 if (dbwrap_transaction_start(orig_db) != 0) {
236 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
242 if (dbwrap_transaction_start(tmp_db) != 0) {
243 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
244 dbwrap_transaction_cancel(orig_db);
254 status = dbwrap_traverse(orig_db, backup_copy_fn, (void *)&bs, NULL);
255 if (!NT_STATUS_IS_OK(status)) {
256 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
261 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
265 if (dbwrap_transaction_commit(orig_db) != 0) {
266 smb_panic("tdbsam_convert_backup: orig commit failed\n");
268 if (dbwrap_transaction_commit(tmp_db) != 0) {
269 smb_panic("tdbsam_convert_backup: orig commit failed\n");
272 /* be sure to close the DBs _before_ renaming the file */
274 TALLOC_FREE(orig_db);
277 /* This is safe from other users as we know we're
278 * under a mutex here. */
280 if (rename(tmp_fname, dbname) == -1) {
281 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
285 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
290 /* re-open the converted TDB */
292 orig_db = db_open(NULL, dbname, 0,
293 TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
294 if (orig_db == NULL) {
295 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
296 "converted passdb TDB [%s]\n", dbname));
300 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
303 /* Replace the global db pointer. */
309 if (dbwrap_transaction_cancel(orig_db) != 0) {
310 smb_panic("tdbsam_convert: transaction_cancel failed");
313 if (dbwrap_transaction_cancel(tmp_db) != 0) {
314 smb_panic("tdbsam_convert: transaction_cancel failed");
323 static bool tdbsam_upgrade_next_rid(struct db_context *db)
330 status = dbwrap_fetch_uint32(db, NEXT_RID_STRING, &rid);
331 if (NT_STATUS_IS_OK(status)) {
335 tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
336 TDB_DEFAULT, O_RDONLY, 0644);
339 ok = tdb_fetch_uint32(tdb, "RID_COUNTER", &rid);
348 if (dbwrap_store_uint32(db, NEXT_RID_STRING, rid) != 0) {
355 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from)
357 struct tdbsam_convert_state state;
358 struct db_context *db = NULL;
361 /* We only need the update backup for local db's. */
362 if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) {
363 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name));
369 state.success = true;
371 if (dbwrap_transaction_start(db) != 0) {
372 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
376 if (!tdbsam_upgrade_next_rid(db)) {
377 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
381 status = dbwrap_traverse(db, tdbsam_convert_one, &state, NULL);
382 if (!NT_STATUS_IS_OK(status)) {
383 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
387 if (!state.success) {
388 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
392 status = dbwrap_store_int32(db, TDBSAM_VERSION_STRING,
394 if (!NT_STATUS_IS_OK(status)) {
395 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version: "
396 "%s\n", nt_errstr(status)));
400 status = dbwrap_store_int32(db, TDBSAM_MINOR_VERSION_STRING,
401 TDBSAM_MINOR_VERSION);
402 if (!NT_STATUS_IS_OK(status)) {
403 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor "
404 "version: %s\n", nt_errstr(status)));
408 if (dbwrap_transaction_commit(db) != 0) {
409 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
416 if (dbwrap_transaction_cancel(db) != 0) {
417 smb_panic("tdbsam_convert: transaction_cancel failed");
423 /*********************************************************************
424 Open the tdbsam file based on the absolute path specified.
425 Uses a reference count to allow multiple open calls.
426 *********************************************************************/
428 static bool tdbsam_open( const char *name )
434 /* check if we are already open */
440 /* Try to open tdb passwd. Create a new one if necessary */
442 db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
443 if (db_sam == NULL) {
444 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
449 /* Check the version */
450 status = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING, &version);
451 if (!NT_STATUS_IS_OK(status)) {
452 version = 0; /* Version not found, assume version 0 */
455 /* Get the minor version */
456 status = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING,
458 if (!NT_STATUS_IS_OK(status)) {
459 minor_version = 0; /* Minor version not found, assume 0 */
462 /* Compare the version */
463 if (version > TDBSAM_VERSION) {
464 /* Version more recent than the latest known */
465 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
470 if ( version < TDBSAM_VERSION ||
471 (version == TDBSAM_VERSION &&
472 minor_version < TDBSAM_MINOR_VERSION) ) {
474 * Ok - we think we're going to have to convert.
475 * Due to the backup process we now must do to
476 * upgrade we have to get a mutex and re-check
477 * the version. Someone else may have upgraded
478 * whilst we were checking.
481 struct named_mutex *mtx = grab_named_mutex(NULL,
482 "tdbsam_upgrade_mutex",
486 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
491 /* Re-check the version */
492 status = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING,
494 if (!NT_STATUS_IS_OK(status)) {
495 version = 0; /* Version not found, assume version 0 */
498 /* Re-check the minor version */
499 status = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING,
501 if (!NT_STATUS_IS_OK(status)) {
502 minor_version = 0; /* Minor version not found, assume 0 */
505 /* Compare the version */
506 if (version > TDBSAM_VERSION) {
507 /* Version more recent than the latest known */
508 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
514 if ( version < TDBSAM_VERSION ||
515 (version == TDBSAM_VERSION &&
516 minor_version < TDBSAM_MINOR_VERSION) ) {
518 * Note that minor versions we read that are greater
519 * than the current minor version we have hard coded
520 * are assumed to be compatible if they have the same
521 * major version. That allows previous versions of the
522 * passdb code that don't know about minor versions to
523 * still use this database. JRA.
526 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
531 TDBSAM_MINOR_VERSION));
533 if ( !tdbsam_convert(&db_sam, name, version) ) {
534 DEBUG(0, ("tdbsam_open: Error when trying to convert "
535 "tdbsam [%s]\n",name));
541 DEBUG(3, ("TDBSAM converted successfully.\n"));
546 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
551 /******************************************************************
552 Lookup a name in the SAM TDB
553 ******************************************************************/
555 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
556 struct samu *user, const char *sname)
564 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
565 return NT_STATUS_NO_MEMORY;
568 /* Data is stored in all lower-case */
569 fstrcpy(name, sname);
573 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
575 /* open the database */
577 if ( !tdbsam_open( tdbsam_filename ) ) {
578 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
579 return NT_STATUS_ACCESS_DENIED;
584 status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
585 if (!NT_STATUS_IS_OK(status)) {
586 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
587 DEBUGADD(5, (" Key: %s\n", keystr));
588 return NT_STATUS_NO_SUCH_USER;
591 /* unpack the buffer */
593 if (!init_samu_from_buffer(user, SAMU_BUFFER_LATEST, data.dptr, data.dsize)) {
594 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
595 SAFE_FREE(data.dptr);
596 return NT_STATUS_NO_MEMORY;
601 TALLOC_FREE(data.dptr);
606 /***************************************************************************
608 **************************************************************************/
610 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
611 struct samu *user, uint32 rid)
613 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
619 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
625 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
627 /* open the database */
629 if ( !tdbsam_open( tdbsam_filename ) ) {
630 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename));
631 return NT_STATUS_ACCESS_DENIED;
636 nt_status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
637 if (!NT_STATUS_IS_OK(nt_status)) {
638 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
642 fstrcpy(name, (const char *)data.dptr);
643 TALLOC_FREE(data.dptr);
645 return tdbsam_getsampwnam (my_methods, user, name);
648 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
649 struct samu * user, const struct dom_sid *sid)
653 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
654 return NT_STATUS_UNSUCCESSFUL;
656 return tdbsam_getsampwrid(my_methods, user, rid);
659 static bool tdb_delete_samacct_only( struct samu *sam_pass )
665 fstrcpy(name, pdb_get_username(sam_pass));
668 /* set the search key */
670 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
672 /* it's outaa here! 8^) */
673 if ( !tdbsam_open( tdbsam_filename ) ) {
674 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
679 status = dbwrap_delete_bystring(db_sam, keystr);
680 if (!NT_STATUS_IS_OK(status)) {
681 DEBUG(5, ("Error deleting entry from tdb passwd "
682 "database: %s!\n", nt_errstr(status)));
689 /***************************************************************************
690 Delete a struct samu records for the username and RID key
691 ****************************************************************************/
693 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
694 struct samu *sam_pass)
696 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
701 /* open the database */
703 if ( !tdbsam_open( tdbsam_filename ) ) {
704 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
706 return NT_STATUS_ACCESS_DENIED;
709 fstrcpy(name, pdb_get_username(sam_pass));
712 /* set the search key */
714 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
716 rid = pdb_get_user_rid(sam_pass);
718 /* it's outaa here! 8^) */
720 if (dbwrap_transaction_start(db_sam) != 0) {
721 DEBUG(0, ("Could not start transaction\n"));
722 return NT_STATUS_UNSUCCESSFUL;
725 nt_status = dbwrap_delete_bystring(db_sam, keystr);
726 if (!NT_STATUS_IS_OK(nt_status)) {
727 DEBUG(5, ("Error deleting entry from tdb passwd "
728 "database: %s!\n", nt_errstr(nt_status)));
732 /* set the search key */
734 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
736 /* it's outaa here! 8^) */
738 nt_status = dbwrap_delete_bystring(db_sam, keystr);
739 if (!NT_STATUS_IS_OK(nt_status)) {
740 DEBUG(5, ("Error deleting entry from tdb rid "
741 "database: %s!\n", nt_errstr(nt_status)));
745 if (dbwrap_transaction_commit(db_sam) != 0) {
746 DEBUG(0, ("Could not commit transaction\n"));
747 return NT_STATUS_INTERNAL_DB_CORRUPTION;
753 if (dbwrap_transaction_cancel(db_sam) != 0) {
754 smb_panic("transaction_cancel failed");
761 /***************************************************************************
762 Update the TDB SAM account record only
763 Assumes that the tdbsam is already open
764 ****************************************************************************/
765 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
774 /* copy the struct samu struct into a BYTE buffer for storage */
776 if ( (data.dsize=init_buffer_from_samu(&buf, newpwd, False)) == -1 ) {
777 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
782 fstrcpy(name, pdb_get_username(newpwd));
785 DEBUG(5, ("Storing %saccount %s with RID %d\n",
786 flag == TDB_INSERT ? "(new) " : "", name,
787 pdb_get_user_rid(newpwd)));
789 /* setup the USER index key */
790 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
792 /* add the account */
794 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
795 if (!NT_STATUS_IS_OK(status)) {
796 DEBUG(0, ("Unable to modify passwd TDB: %s!",
809 /***************************************************************************
810 Update the TDB SAM RID record only
811 Assumes that the tdbsam is already open
812 ****************************************************************************/
813 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
820 fstrcpy(name, pdb_get_username(newpwd));
824 data = string_term_tdb_data(name);
826 /* setup the RID index key */
827 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
828 pdb_get_user_rid(newpwd));
830 /* add the reference */
831 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
832 if (!NT_STATUS_IS_OK(status)) {
833 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
842 /***************************************************************************
844 ****************************************************************************/
846 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
852 if (!(newrid = pdb_get_user_rid(newpwd))) {
853 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
854 pdb_get_username(newpwd)));
860 /* open the database */
862 if ( !tdbsam_open( tdbsam_filename ) ) {
863 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
867 if (dbwrap_transaction_start(db_sam) != 0) {
868 DEBUG(0, ("Could not start transaction\n"));
872 /* If we are updating, we may be changing this users RID. Retrieve the old RID
875 if (flag == TDB_MODIFY) {
876 struct samu *account = samu_new(talloc_tos());
877 if (account == NULL) {
878 DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
881 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods, account, pdb_get_username(newpwd)))) {
882 DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
883 pdb_get_username(newpwd)));
884 TALLOC_FREE(account);
887 if (!(oldrid = pdb_get_user_rid(account))) {
888 DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
889 TALLOC_FREE(account);
892 TALLOC_FREE(account);
895 /* Update the new samu entry. */
896 if (!tdb_update_samacct_only(newpwd, flag)) {
900 /* Now take care of the case where the RID changed. We need
901 * to delete the old RID key and add the new. */
903 if (flag == TDB_MODIFY && newrid != oldrid) {
906 /* Delete old RID key */
907 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid));
908 slprintf(keystr, sizeof(keystr) - 1, "%s%.8x", RIDPREFIX, oldrid);
909 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam, keystr))) {
910 DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr));
913 /* Insert new RID key */
914 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid));
915 if (!tdb_update_ridrec_only(newpwd, TDB_INSERT)) {
919 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
920 flag == TDB_MODIFY ? "Updating" : "Inserting", newrid));
921 if (!tdb_update_ridrec_only(newpwd, flag)) {
926 if (dbwrap_transaction_commit(db_sam) != 0) {
927 DEBUG(0, ("Could not commit transaction\n"));
934 if (dbwrap_transaction_cancel(db_sam) != 0) {
935 smb_panic("transaction_cancel failed");
940 /***************************************************************************
941 Modifies an existing struct samu
942 ****************************************************************************/
944 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
946 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
947 return NT_STATUS_UNSUCCESSFUL;
952 /***************************************************************************
953 Adds an existing struct samu
954 ****************************************************************************/
956 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
958 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
959 return NT_STATUS_UNSUCCESSFUL;
964 /***************************************************************************
965 Renames a struct samu
966 - check for the posix user/rename user script
967 - Add and lock the new user record
968 - rename the posix user
969 - rewrite the rid->username record
970 - delete the old user
971 - unlock the new user record
972 ***************************************************************************/
973 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
974 struct samu *old_acct,
977 struct samu *new_acct = NULL;
978 char *rename_script = NULL;
980 fstring oldname_lower;
981 fstring newname_lower;
983 /* can't do anything without an external script */
985 if ( !(new_acct = samu_new( talloc_tos() )) ) {
986 return NT_STATUS_NO_MEMORY;
989 rename_script = talloc_strdup(new_acct, lp_renameuser_script());
990 if (!rename_script) {
991 TALLOC_FREE(new_acct);
992 return NT_STATUS_NO_MEMORY;
994 if (!*rename_script) {
995 TALLOC_FREE(new_acct);
996 return NT_STATUS_ACCESS_DENIED;
999 if ( !pdb_copy_sam_account(new_acct, old_acct)
1000 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1002 TALLOC_FREE(new_acct);
1003 return NT_STATUS_NO_MEMORY;
1006 /* open the database */
1007 if ( !tdbsam_open( tdbsam_filename ) ) {
1008 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1010 TALLOC_FREE(new_acct);
1011 return NT_STATUS_ACCESS_DENIED;
1014 if (dbwrap_transaction_start(db_sam) != 0) {
1015 DEBUG(0, ("Could not start transaction\n"));
1016 TALLOC_FREE(new_acct);
1017 return NT_STATUS_ACCESS_DENIED;
1021 /* add the new account and lock it */
1022 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1026 /* Rename the posix user. Follow the semantics of _samr_create_user()
1027 so that we lower case the posix name but preserve the case in passdb */
1029 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1030 strlower_m( oldname_lower );
1032 fstrcpy( newname_lower, newname );
1033 strlower_m( newname_lower );
1035 rename_script = talloc_string_sub2(new_acct,
1042 if (!rename_script) {
1045 rename_script = talloc_string_sub2(new_acct,
1052 if (!rename_script) {
1055 rename_ret = smbrun(rename_script, NULL);
1057 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
1058 rename_script, rename_ret));
1060 if (rename_ret != 0) {
1064 smb_nscd_flush_user_cache();
1066 /* rewrite the rid->username record */
1068 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1072 tdb_delete_samacct_only( old_acct );
1074 if (dbwrap_transaction_commit(db_sam) != 0) {
1076 * Ok, we're screwed. We've changed the posix account, but
1077 * could not adapt passdb.tdb. Shall we change the posix
1080 DEBUG(0, ("transaction_commit failed\n"));
1081 TALLOC_FREE(new_acct);
1082 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1085 TALLOC_FREE(new_acct );
1086 return NT_STATUS_OK;
1089 if (dbwrap_transaction_cancel(db_sam) != 0) {
1090 smb_panic("transaction_cancel failed");
1093 TALLOC_FREE(new_acct);
1095 return NT_STATUS_ACCESS_DENIED;
1098 static uint32_t tdbsam_capabilities(struct pdb_methods *methods)
1100 return PDB_CAP_STORE_RIDS;
1103 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1108 rid = BASE_RID; /* Default if not set */
1110 if (!tdbsam_open(tdbsam_filename)) {
1111 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1116 status = dbwrap_trans_change_uint32_atomic(db_sam, NEXT_RID_STRING,
1118 if (!NT_STATUS_IS_OK(status)) {
1119 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1120 NEXT_RID_STRING, nt_errstr(status)));
1129 struct tdbsam_search_state {
1130 struct pdb_methods *methods;
1131 uint32_t acct_flags;
1139 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1141 struct tdbsam_search_state *state = talloc_get_type_abort(
1142 private_data, struct tdbsam_search_state);
1143 size_t prefixlen = strlen(RIDPREFIX);
1147 key = dbwrap_record_get_key(rec);
1149 if ((key.dsize < prefixlen)
1150 || (strncmp((char *)key.dptr, RIDPREFIX, prefixlen))) {
1154 rid = strtoul((char *)key.dptr+prefixlen, NULL, 16);
1156 ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1157 &state->array_size);
1162 static void tdbsam_search_end(struct pdb_search *search)
1164 struct tdbsam_search_state *state = talloc_get_type_abort(
1165 search->private_data, struct tdbsam_search_state);
1169 static bool tdbsam_search_next_entry(struct pdb_search *search,
1170 struct samr_displayentry *entry)
1172 struct tdbsam_search_state *state = talloc_get_type_abort(
1173 search->private_data, struct tdbsam_search_state);
1174 struct samu *user = NULL;
1180 user = samu_new(talloc_tos());
1182 DEBUG(0, ("samu_new failed\n"));
1186 if (state->current == state->num_rids) {
1190 rid = state->rids[state->current++];
1192 status = tdbsam_getsampwrid(state->methods, user, rid);
1194 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1196 * Someone has deleted that user since we listed the RIDs
1201 if (!NT_STATUS_IS_OK(status)) {
1202 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1203 nt_errstr(status)));
1208 if ((state->acct_flags != 0) &&
1209 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1213 entry->acct_flags = pdb_get_acct_ctrl(user);
1215 entry->account_name = talloc_strdup(search, pdb_get_username(user));
1216 entry->fullname = talloc_strdup(search, pdb_get_fullname(user));
1217 entry->description = talloc_strdup(search, pdb_get_acct_desc(user));
1221 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1222 || (entry->description == NULL)) {
1223 DEBUG(0, ("talloc_strdup failed\n"));
1230 static bool tdbsam_search_users(struct pdb_methods *methods,
1231 struct pdb_search *search,
1234 struct tdbsam_search_state *state;
1236 if (!tdbsam_open(tdbsam_filename)) {
1237 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1242 state = talloc_zero(search, struct tdbsam_search_state);
1243 if (state == NULL) {
1244 DEBUG(0, ("talloc failed\n"));
1247 state->acct_flags = acct_flags;
1248 state->methods = methods;
1250 dbwrap_traverse_read(db_sam, tdbsam_collect_rids, state, NULL);
1252 search->private_data = state;
1253 search->next_entry = tdbsam_search_next_entry;
1254 search->search_end = tdbsam_search_end;
1259 /*********************************************************************
1260 Initialize the tdb sam backend. Setup the dispath table of methods,
1261 open the tdb, etc...
1262 *********************************************************************/
1264 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1267 char *tdbfile = NULL;
1268 const char *pfile = location;
1270 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1274 (*pdb_method)->name = "tdbsam";
1276 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1277 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1278 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1279 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1280 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1281 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1282 (*pdb_method)->search_users = tdbsam_search_users;
1284 (*pdb_method)->capabilities = tdbsam_capabilities;
1285 (*pdb_method)->new_rid = tdbsam_new_rid;
1287 /* save the path for later */
1290 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1291 PASSDB_FILE_NAME) < 0) {
1292 return NT_STATUS_NO_MEMORY;
1296 tdbsam_filename = SMB_STRDUP(pfile);
1297 if (!tdbsam_filename) {
1298 return NT_STATUS_NO_MEMORY;
1302 /* no private data */
1304 (*pdb_method)->private_data = NULL;
1305 (*pdb_method)->free_private_data = NULL;
1307 return NT_STATUS_OK;
1310 NTSTATUS pdb_tdbsam_init(void)
1312 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);