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 #include "../libcli/security/security.h"
29 #if 0 /* when made a module use this */
31 static int tdbsam_debug_level
= DBGC_ALL
;
33 #define DBGC_CLASS tdbsam_debug_level
38 #define DBGC_CLASS DBGC_PASSDB
42 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */
43 #define TDBSAM_MINOR_VERSION 0 /* Most recent TDBSAM minor version */
44 #define TDBSAM_VERSION_STRING "INFO/version"
45 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version"
46 #define PASSDB_FILE_NAME "passdb.tdb"
47 #define USERPREFIX "USER_"
48 #define USERPREFIX_LEN 5
49 #define RIDPREFIX "RID_"
50 #define PRIVPREFIX "PRIV_"
51 #define NEXT_RID_STRING "NEXT_RID"
53 /* GLOBAL TDB SAM CONTEXT */
55 static struct db_context
*db_sam
;
56 static char *tdbsam_filename
;
58 struct tdbsam_convert_state
{
63 static int tdbsam_convert_one(struct db_record
*rec
, void *priv
)
65 struct tdbsam_convert_state
*state
=
66 (struct tdbsam_convert_state
*)priv
;
72 if (rec
->key
.dsize
< USERPREFIX_LEN
) {
75 if (strncmp((char *)rec
->key
.dptr
, USERPREFIX
, USERPREFIX_LEN
) != 0) {
79 user
= samu_new(talloc_tos());
81 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
82 state
->success
= false;
86 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
87 "(version:%d)\n", rec
->key
.dptr
, state
->from
));
89 switch (state
->from
) {
91 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V0
,
92 (uint8
*)rec
->value
.dptr
,
96 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V1
,
97 (uint8
*)rec
->value
.dptr
,
101 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V2
,
102 (uint8
*)rec
->value
.dptr
,
106 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V3
,
107 (uint8
*)rec
->value
.dptr
,
111 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V4
,
112 (uint8
*)rec
->value
.dptr
,
116 /* unknown tdbsam version */
120 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
121 "from TDB (key:%s) (version:%d)\n", rec
->key
.dptr
,
124 state
->success
= false;
128 data
.dsize
= init_buffer_from_samu(&data
.dptr
, user
, false);
131 if (data
.dsize
== -1) {
132 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
133 "the new format\n"));
134 state
->success
= false;
138 status
= rec
->store(rec
, data
, TDB_MODIFY
);
139 if (!NT_STATUS_IS_OK(status
)) {
140 DEBUG(0, ("Could not store the new record: %s\n",
142 state
->success
= false;
149 /**********************************************************************
150 Struct and function to backup an old record.
151 *********************************************************************/
153 struct tdbsam_backup_state
{
154 struct db_context
*new_db
;
158 static int backup_copy_fn(struct db_record
*orig_rec
, void *state
)
160 struct tdbsam_backup_state
*bs
= (struct tdbsam_backup_state
*)state
;
161 struct db_record
*new_rec
;
164 new_rec
= bs
->new_db
->fetch_locked(bs
->new_db
, talloc_tos(), orig_rec
->key
);
165 if (new_rec
== NULL
) {
170 status
= new_rec
->store(new_rec
, orig_rec
->value
, TDB_INSERT
);
172 TALLOC_FREE(new_rec
);
174 if (!NT_STATUS_IS_OK(status
)) {
181 /**********************************************************************
182 Make a backup of an old passdb and replace the new one with it. We
183 have to do this as between 3.0.x and 3.2.x the hash function changed
184 by mistake (used unsigned char * instead of char *). This means the
185 previous simple update code will fail due to not being able to find
186 existing records to replace in the tdbsam_convert_one() function. JRA.
187 *********************************************************************/
189 static bool tdbsam_convert_backup(const char *dbname
, struct db_context
**pp_db
)
191 TALLOC_CTX
*frame
= talloc_stackframe();
192 const char *tmp_fname
= NULL
;
193 struct db_context
*tmp_db
= NULL
;
194 struct db_context
*orig_db
= *pp_db
;
195 struct tdbsam_backup_state bs
;
198 tmp_fname
= talloc_asprintf(frame
, "%s.tmp", dbname
);
206 /* Remember to open this on the NULL context. We need
207 * it to stay around after we return from here. */
209 tmp_db
= db_open(NULL
, tmp_fname
, 0,
210 TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
211 if (tmp_db
== NULL
) {
212 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
213 "[%s]\n", tmp_fname
));
218 if (orig_db
->transaction_start(orig_db
) != 0) {
219 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
225 if (tmp_db
->transaction_start(tmp_db
) != 0) {
226 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
227 orig_db
->transaction_cancel(orig_db
);
237 ret
= orig_db
->traverse(orig_db
, backup_copy_fn
, (void *)&bs
);
239 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
244 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
248 if (orig_db
->transaction_commit(orig_db
) != 0) {
249 smb_panic("tdbsam_convert_backup: orig commit failed\n");
251 if (tmp_db
->transaction_commit(tmp_db
) != 0) {
252 smb_panic("tdbsam_convert_backup: orig commit failed\n");
255 /* be sure to close the DBs _before_ renaming the file */
257 TALLOC_FREE(orig_db
);
260 /* This is safe from other users as we know we're
261 * under a mutex here. */
263 if (rename(tmp_fname
, dbname
) == -1) {
264 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
268 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
273 /* re-open the converted TDB */
275 orig_db
= db_open(NULL
, dbname
, 0,
276 TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
277 if (orig_db
== NULL
) {
278 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
279 "converted passdb TDB [%s]\n", dbname
));
283 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
286 /* Replace the global db pointer. */
292 if (orig_db
->transaction_cancel(orig_db
) != 0) {
293 smb_panic("tdbsam_convert: transaction_cancel failed");
296 if (tmp_db
->transaction_cancel(tmp_db
) != 0) {
297 smb_panic("tdbsam_convert: transaction_cancel failed");
306 static bool tdbsam_upgrade_next_rid(struct db_context
*db
)
312 ok
= dbwrap_fetch_uint32(db
, NEXT_RID_STRING
, &rid
);
317 tdb
= tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
318 TDB_DEFAULT
, O_RDONLY
, 0644);
321 ok
= tdb_fetch_uint32(tdb
, "RID_COUNTER", &rid
);
330 if (dbwrap_store_uint32(db
, NEXT_RID_STRING
, rid
) != 0) {
337 static bool tdbsam_convert(struct db_context
**pp_db
, const char *name
, int32 from
)
339 struct tdbsam_convert_state state
;
340 struct db_context
*db
= NULL
;
343 /* We only need the update backup for local db's. */
344 if (db_is_local(name
) && !tdbsam_convert_backup(name
, pp_db
)) {
345 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name
));
351 state
.success
= true;
353 if (db
->transaction_start(db
) != 0) {
354 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
358 if (!tdbsam_upgrade_next_rid(db
)) {
359 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
363 ret
= db
->traverse(db
, tdbsam_convert_one
, &state
);
365 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
369 if (!state
.success
) {
370 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
374 if (dbwrap_store_int32(db
, TDBSAM_VERSION_STRING
,
375 TDBSAM_VERSION
) != 0) {
376 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n"));
380 if (dbwrap_store_int32(db
, TDBSAM_MINOR_VERSION_STRING
,
381 TDBSAM_MINOR_VERSION
) != 0) {
382 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor version\n"));
386 if (db
->transaction_commit(db
) != 0) {
387 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
394 if (db
->transaction_cancel(db
) != 0) {
395 smb_panic("tdbsam_convert: transaction_cancel failed");
401 /*********************************************************************
402 Open the tdbsam file based on the absolute path specified.
403 Uses a reference count to allow multiple open calls.
404 *********************************************************************/
406 static bool tdbsam_open( const char *name
)
411 /* check if we are already open */
417 /* Try to open tdb passwd. Create a new one if necessary */
419 db_sam
= db_open(NULL
, name
, 0, TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
420 if (db_sam
== NULL
) {
421 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
426 /* Check the version */
427 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
429 version
= 0; /* Version not found, assume version 0 */
432 /* Get the minor version */
433 minor_version
= dbwrap_fetch_int32(db_sam
, TDBSAM_MINOR_VERSION_STRING
);
434 if (minor_version
== -1) {
435 minor_version
= 0; /* Minor version not found, assume 0 */
438 /* Compare the version */
439 if (version
> TDBSAM_VERSION
) {
440 /* Version more recent than the latest known */
441 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
446 if ( version
< TDBSAM_VERSION
||
447 (version
== TDBSAM_VERSION
&&
448 minor_version
< TDBSAM_MINOR_VERSION
) ) {
450 * Ok - we think we're going to have to convert.
451 * Due to the backup process we now must do to
452 * upgrade we have to get a mutex and re-check
453 * the version. Someone else may have upgraded
454 * whilst we were checking.
457 struct named_mutex
*mtx
= grab_named_mutex(NULL
,
458 "tdbsam_upgrade_mutex",
462 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
467 /* Re-check the version */
468 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
470 version
= 0; /* Version not found, assume version 0 */
473 /* Re-check the minor version */
474 minor_version
= dbwrap_fetch_int32(db_sam
, TDBSAM_MINOR_VERSION_STRING
);
475 if (minor_version
== -1) {
476 minor_version
= 0; /* Minor version not found, assume 0 */
479 /* Compare the version */
480 if (version
> TDBSAM_VERSION
) {
481 /* Version more recent than the latest known */
482 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
488 if ( version
< TDBSAM_VERSION
||
489 (version
== TDBSAM_VERSION
&&
490 minor_version
< TDBSAM_MINOR_VERSION
) ) {
492 * Note that minor versions we read that are greater
493 * than the current minor version we have hard coded
494 * are assumed to be compatible if they have the same
495 * major version. That allows previous versions of the
496 * passdb code that don't know about minor versions to
497 * still use this database. JRA.
500 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
505 TDBSAM_MINOR_VERSION
));
507 if ( !tdbsam_convert(&db_sam
, name
, version
) ) {
508 DEBUG(0, ("tdbsam_open: Error when trying to convert "
509 "tdbsam [%s]\n",name
));
515 DEBUG(3, ("TDBSAM converted successfully.\n"));
520 DEBUG(4,("tdbsam_open: successfully opened %s\n", name
));
525 /******************************************************************
526 Lookup a name in the SAM TDB
527 ******************************************************************/
529 static NTSTATUS
tdbsam_getsampwnam (struct pdb_methods
*my_methods
,
530 struct samu
*user
, const char *sname
)
537 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
538 return NT_STATUS_NO_MEMORY
;
541 /* Data is stored in all lower-case */
542 fstrcpy(name
, sname
);
546 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
548 /* open the database */
550 if ( !tdbsam_open( tdbsam_filename
) ) {
551 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
552 return NT_STATUS_ACCESS_DENIED
;
557 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
559 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
560 DEBUGADD(5, (" Key: %s\n", keystr
));
561 return NT_STATUS_NO_SUCH_USER
;
564 /* unpack the buffer */
566 if (!init_samu_from_buffer(user
, SAMU_BUFFER_LATEST
, data
.dptr
, data
.dsize
)) {
567 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
568 SAFE_FREE(data
.dptr
);
569 return NT_STATUS_NO_MEMORY
;
574 TALLOC_FREE(data
.dptr
);
579 /***************************************************************************
581 **************************************************************************/
583 static NTSTATUS
tdbsam_getsampwrid (struct pdb_methods
*my_methods
,
584 struct samu
*user
, uint32 rid
)
586 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
592 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
598 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
600 /* open the database */
602 if ( !tdbsam_open( tdbsam_filename
) ) {
603 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename
));
604 return NT_STATUS_ACCESS_DENIED
;
609 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
611 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid
, keystr
));
612 return NT_STATUS_UNSUCCESSFUL
;
615 fstrcpy(name
, (const char *)data
.dptr
);
616 TALLOC_FREE(data
.dptr
);
618 return tdbsam_getsampwnam (my_methods
, user
, name
);
621 static NTSTATUS
tdbsam_getsampwsid(struct pdb_methods
*my_methods
,
622 struct samu
* user
, const struct dom_sid
*sid
)
626 if ( !sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
) )
627 return NT_STATUS_UNSUCCESSFUL
;
629 return tdbsam_getsampwrid(my_methods
, user
, rid
);
632 static bool tdb_delete_samacct_only( struct samu
*sam_pass
)
638 fstrcpy(name
, pdb_get_username(sam_pass
));
641 /* set the search key */
643 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
645 /* it's outaa here! 8^) */
646 if ( !tdbsam_open( tdbsam_filename
) ) {
647 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
652 status
= dbwrap_delete_bystring(db_sam
, keystr
);
653 if (!NT_STATUS_IS_OK(status
)) {
654 DEBUG(5, ("Error deleting entry from tdb passwd "
655 "database: %s!\n", nt_errstr(status
)));
662 /***************************************************************************
663 Delete a struct samu records for the username and RID key
664 ****************************************************************************/
666 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
667 struct samu
*sam_pass
)
669 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
674 /* open the database */
676 if ( !tdbsam_open( tdbsam_filename
) ) {
677 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
679 return NT_STATUS_ACCESS_DENIED
;
682 fstrcpy(name
, pdb_get_username(sam_pass
));
685 /* set the search key */
687 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
689 rid
= pdb_get_user_rid(sam_pass
);
691 /* it's outaa here! 8^) */
693 if (db_sam
->transaction_start(db_sam
) != 0) {
694 DEBUG(0, ("Could not start transaction\n"));
695 return NT_STATUS_UNSUCCESSFUL
;
698 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
699 if (!NT_STATUS_IS_OK(nt_status
)) {
700 DEBUG(5, ("Error deleting entry from tdb passwd "
701 "database: %s!\n", nt_errstr(nt_status
)));
705 /* set the search key */
707 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
709 /* it's outaa here! 8^) */
711 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
712 if (!NT_STATUS_IS_OK(nt_status
)) {
713 DEBUG(5, ("Error deleting entry from tdb rid "
714 "database: %s!\n", nt_errstr(nt_status
)));
718 if (db_sam
->transaction_commit(db_sam
) != 0) {
719 DEBUG(0, ("Could not commit transaction\n"));
720 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
726 if (db_sam
->transaction_cancel(db_sam
) != 0) {
727 smb_panic("transaction_cancel failed");
734 /***************************************************************************
735 Update the TDB SAM account record only
736 Assumes that the tdbsam is already open
737 ****************************************************************************/
738 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
747 /* copy the struct samu struct into a BYTE buffer for storage */
749 if ( (data
.dsize
=init_buffer_from_samu(&buf
, newpwd
, False
)) == -1 ) {
750 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
755 fstrcpy(name
, pdb_get_username(newpwd
));
758 DEBUG(5, ("Storing %saccount %s with RID %d\n",
759 flag
== TDB_INSERT
? "(new) " : "", name
,
760 pdb_get_user_rid(newpwd
)));
762 /* setup the USER index key */
763 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
765 /* add the account */
767 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
768 if (!NT_STATUS_IS_OK(status
)) {
769 DEBUG(0, ("Unable to modify passwd TDB: %s!",
782 /***************************************************************************
783 Update the TDB SAM RID record only
784 Assumes that the tdbsam is already open
785 ****************************************************************************/
786 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
793 fstrcpy(name
, pdb_get_username(newpwd
));
797 data
= string_term_tdb_data(name
);
799 /* setup the RID index key */
800 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
,
801 pdb_get_user_rid(newpwd
));
803 /* add the reference */
804 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
805 if (!NT_STATUS_IS_OK(status
)) {
806 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
815 /***************************************************************************
817 ****************************************************************************/
819 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
825 if (!(newrid
= pdb_get_user_rid(newpwd
))) {
826 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
827 pdb_get_username(newpwd
)));
833 /* open the database */
835 if ( !tdbsam_open( tdbsam_filename
) ) {
836 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
840 if (db_sam
->transaction_start(db_sam
) != 0) {
841 DEBUG(0, ("Could not start transaction\n"));
845 /* If we are updating, we may be changing this users RID. Retrieve the old RID
848 if (flag
== TDB_MODIFY
) {
849 struct samu
*account
= samu_new(talloc_tos());
850 if (account
== NULL
) {
851 DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
854 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods
, account
, pdb_get_username(newpwd
)))) {
855 DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
856 pdb_get_username(newpwd
)));
857 TALLOC_FREE(account
);
860 if (!(oldrid
= pdb_get_user_rid(account
))) {
861 DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
862 TALLOC_FREE(account
);
865 TALLOC_FREE(account
);
868 /* Update the new samu entry. */
869 if (!tdb_update_samacct_only(newpwd
, flag
)) {
873 /* Now take care of the case where the RID changed. We need
874 * to delete the old RID key and add the new. */
876 if (flag
== TDB_MODIFY
&& newrid
!= oldrid
) {
879 /* Delete old RID key */
880 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid
));
881 slprintf(keystr
, sizeof(keystr
) - 1, "%s%.8x", RIDPREFIX
, oldrid
);
882 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam
, keystr
))) {
883 DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr
));
886 /* Insert new RID key */
887 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid
));
888 if (!tdb_update_ridrec_only(newpwd
, TDB_INSERT
)) {
892 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
893 flag
== TDB_MODIFY
? "Updating" : "Inserting", newrid
));
894 if (!tdb_update_ridrec_only(newpwd
, flag
)) {
899 if (db_sam
->transaction_commit(db_sam
) != 0) {
900 DEBUG(0, ("Could not commit transaction\n"));
907 if (db_sam
->transaction_cancel(db_sam
) != 0) {
908 smb_panic("transaction_cancel failed");
913 /***************************************************************************
914 Modifies an existing struct samu
915 ****************************************************************************/
917 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
919 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
920 return NT_STATUS_UNSUCCESSFUL
;
925 /***************************************************************************
926 Adds an existing struct samu
927 ****************************************************************************/
929 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
931 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
932 return NT_STATUS_UNSUCCESSFUL
;
937 /***************************************************************************
938 Renames a struct samu
939 - check for the posix user/rename user script
940 - Add and lock the new user record
941 - rename the posix user
942 - rewrite the rid->username record
943 - delete the old user
944 - unlock the new user record
945 ***************************************************************************/
946 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
947 struct samu
*old_acct
,
950 struct samu
*new_acct
= NULL
;
951 char *rename_script
= NULL
;
953 fstring oldname_lower
;
954 fstring newname_lower
;
956 /* can't do anything without an external script */
958 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
959 return NT_STATUS_NO_MEMORY
;
962 rename_script
= talloc_strdup(new_acct
, lp_renameuser_script());
963 if (!rename_script
) {
964 TALLOC_FREE(new_acct
);
965 return NT_STATUS_NO_MEMORY
;
967 if (!*rename_script
) {
968 TALLOC_FREE(new_acct
);
969 return NT_STATUS_ACCESS_DENIED
;
972 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
973 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
975 TALLOC_FREE(new_acct
);
976 return NT_STATUS_NO_MEMORY
;
979 /* open the database */
980 if ( !tdbsam_open( tdbsam_filename
) ) {
981 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
983 TALLOC_FREE(new_acct
);
984 return NT_STATUS_ACCESS_DENIED
;
987 if (db_sam
->transaction_start(db_sam
) != 0) {
988 DEBUG(0, ("Could not start transaction\n"));
989 TALLOC_FREE(new_acct
);
990 return NT_STATUS_ACCESS_DENIED
;
994 /* add the new account and lock it */
995 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
999 /* Rename the posix user. Follow the semantics of _samr_create_user()
1000 so that we lower case the posix name but preserve the case in passdb */
1002 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
1003 strlower_m( oldname_lower
);
1005 fstrcpy( newname_lower
, newname
);
1006 strlower_m( newname_lower
);
1008 rename_script
= talloc_string_sub2(new_acct
,
1015 if (!rename_script
) {
1018 rename_script
= talloc_string_sub2(new_acct
,
1025 if (!rename_script
) {
1028 rename_ret
= smbrun(rename_script
, NULL
);
1030 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
1031 rename_script
, rename_ret
));
1033 if (rename_ret
!= 0) {
1037 smb_nscd_flush_user_cache();
1039 /* rewrite the rid->username record */
1041 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
1045 tdb_delete_samacct_only( old_acct
);
1047 if (db_sam
->transaction_commit(db_sam
) != 0) {
1049 * Ok, we're screwed. We've changed the posix account, but
1050 * could not adapt passdb.tdb. Shall we change the posix
1053 DEBUG(0, ("transaction_commit failed\n"));
1054 TALLOC_FREE(new_acct
);
1055 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1058 TALLOC_FREE(new_acct
);
1059 return NT_STATUS_OK
;
1062 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1063 smb_panic("transaction_cancel failed");
1066 TALLOC_FREE(new_acct
);
1068 return NT_STATUS_ACCESS_DENIED
;
1071 static uint32_t tdbsam_capabilities(struct pdb_methods
*methods
)
1073 return PDB_CAP_STORE_RIDS
;
1076 static bool tdbsam_new_rid(struct pdb_methods
*methods
, uint32
*prid
)
1081 rid
= BASE_RID
; /* Default if not set */
1083 if (!tdbsam_open(tdbsam_filename
)) {
1084 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1089 status
= dbwrap_trans_change_uint32_atomic(db_sam
, NEXT_RID_STRING
,
1091 if (!NT_STATUS_IS_OK(status
)) {
1092 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1093 NEXT_RID_STRING
, nt_errstr(status
)));
1102 struct tdbsam_search_state
{
1103 struct pdb_methods
*methods
;
1104 uint32_t acct_flags
;
1112 static int tdbsam_collect_rids(struct db_record
*rec
, void *private_data
)
1114 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1115 private_data
, struct tdbsam_search_state
);
1116 size_t prefixlen
= strlen(RIDPREFIX
);
1119 if ((rec
->key
.dsize
< prefixlen
)
1120 || (strncmp((char *)rec
->key
.dptr
, RIDPREFIX
, prefixlen
))) {
1124 rid
= strtoul((char *)rec
->key
.dptr
+prefixlen
, NULL
, 16);
1126 ADD_TO_LARGE_ARRAY(state
, uint32
, rid
, &state
->rids
, &state
->num_rids
,
1127 &state
->array_size
);
1132 static void tdbsam_search_end(struct pdb_search
*search
)
1134 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1135 search
->private_data
, struct tdbsam_search_state
);
1139 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
1140 struct samr_displayentry
*entry
)
1142 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1143 search
->private_data
, struct tdbsam_search_state
);
1144 struct samu
*user
= NULL
;
1150 user
= samu_new(talloc_tos());
1152 DEBUG(0, ("samu_new failed\n"));
1156 if (state
->current
== state
->num_rids
) {
1160 rid
= state
->rids
[state
->current
++];
1162 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
1164 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1166 * Someone has deleted that user since we listed the RIDs
1171 if (!NT_STATUS_IS_OK(status
)) {
1172 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1173 nt_errstr(status
)));
1178 if ((state
->acct_flags
!= 0) &&
1179 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
1183 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
1185 entry
->account_name
= talloc_strdup(search
, pdb_get_username(user
));
1186 entry
->fullname
= talloc_strdup(search
, pdb_get_fullname(user
));
1187 entry
->description
= talloc_strdup(search
, pdb_get_acct_desc(user
));
1191 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
1192 || (entry
->description
== NULL
)) {
1193 DEBUG(0, ("talloc_strdup failed\n"));
1200 static bool tdbsam_search_users(struct pdb_methods
*methods
,
1201 struct pdb_search
*search
,
1204 struct tdbsam_search_state
*state
;
1206 if (!tdbsam_open(tdbsam_filename
)) {
1207 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1212 state
= talloc_zero(search
, struct tdbsam_search_state
);
1213 if (state
== NULL
) {
1214 DEBUG(0, ("talloc failed\n"));
1217 state
->acct_flags
= acct_flags
;
1218 state
->methods
= methods
;
1220 db_sam
->traverse_read(db_sam
, tdbsam_collect_rids
, state
);
1222 search
->private_data
= state
;
1223 search
->next_entry
= tdbsam_search_next_entry
;
1224 search
->search_end
= tdbsam_search_end
;
1229 /*********************************************************************
1230 Initialize the tdb sam backend. Setup the dispath table of methods,
1231 open the tdb, etc...
1232 *********************************************************************/
1234 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
1237 char *tdbfile
= NULL
;
1238 const char *pfile
= location
;
1240 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
1244 (*pdb_method
)->name
= "tdbsam";
1246 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
1247 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
1248 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
1249 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
1250 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
1251 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
1252 (*pdb_method
)->search_users
= tdbsam_search_users
;
1254 (*pdb_method
)->capabilities
= tdbsam_capabilities
;
1255 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
1257 /* save the path for later */
1260 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
1261 PASSDB_FILE_NAME
) < 0) {
1262 return NT_STATUS_NO_MEMORY
;
1266 tdbsam_filename
= SMB_STRDUP(pfile
);
1267 if (!tdbsam_filename
) {
1268 return NT_STATUS_NO_MEMORY
;
1272 /* no private data */
1274 (*pdb_method
)->private_data
= NULL
;
1275 (*pdb_method
)->free_private_data
= NULL
;
1277 return NT_STATUS_OK
;
1280 NTSTATUS
pdb_tdbsam_init(void)
1282 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);