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"
29 #include "../libcli/security/security.h"
31 #if 0 /* when made a module use this */
33 static int tdbsam_debug_level
= DBGC_ALL
;
35 #define DBGC_CLASS tdbsam_debug_level
40 #define DBGC_CLASS DBGC_PASSDB
44 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */
45 #define TDBSAM_MINOR_VERSION 0 /* Most recent TDBSAM minor version */
46 #define TDBSAM_VERSION_STRING "INFO/version"
47 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version"
48 #define PASSDB_FILE_NAME "passdb.tdb"
49 #define USERPREFIX "USER_"
50 #define USERPREFIX_LEN 5
51 #define RIDPREFIX "RID_"
52 #define PRIVPREFIX "PRIV_"
53 #define NEXT_RID_STRING "NEXT_RID"
55 /* GLOBAL TDB SAM CONTEXT */
57 static struct db_context
*db_sam
;
58 static char *tdbsam_filename
;
60 struct tdbsam_convert_state
{
65 static int tdbsam_convert_one(struct db_record
*rec
, void *priv
)
67 struct tdbsam_convert_state
*state
=
68 (struct tdbsam_convert_state
*)priv
;
74 if (rec
->key
.dsize
< USERPREFIX_LEN
) {
77 if (strncmp((char *)rec
->key
.dptr
, USERPREFIX
, USERPREFIX_LEN
) != 0) {
81 user
= samu_new(talloc_tos());
83 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
84 state
->success
= false;
88 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
89 "(version:%d)\n", rec
->key
.dptr
, state
->from
));
91 switch (state
->from
) {
93 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V0
,
94 (uint8
*)rec
->value
.dptr
,
98 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V1
,
99 (uint8
*)rec
->value
.dptr
,
103 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V2
,
104 (uint8
*)rec
->value
.dptr
,
108 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V3
,
109 (uint8
*)rec
->value
.dptr
,
113 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V4
,
114 (uint8
*)rec
->value
.dptr
,
118 /* unknown tdbsam version */
122 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
123 "from TDB (key:%s) (version:%d)\n", rec
->key
.dptr
,
126 state
->success
= false;
130 data
.dsize
= init_buffer_from_samu(&data
.dptr
, user
, false);
133 if (data
.dsize
== -1) {
134 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
135 "the new format\n"));
136 state
->success
= false;
140 status
= rec
->store(rec
, data
, TDB_MODIFY
);
141 if (!NT_STATUS_IS_OK(status
)) {
142 DEBUG(0, ("Could not store the new record: %s\n",
144 state
->success
= false;
151 /**********************************************************************
152 Struct and function to backup an old record.
153 *********************************************************************/
155 struct tdbsam_backup_state
{
156 struct db_context
*new_db
;
160 static int backup_copy_fn(struct db_record
*orig_rec
, void *state
)
162 struct tdbsam_backup_state
*bs
= (struct tdbsam_backup_state
*)state
;
163 struct db_record
*new_rec
;
166 new_rec
= bs
->new_db
->fetch_locked(bs
->new_db
, talloc_tos(), orig_rec
->key
);
167 if (new_rec
== NULL
) {
172 status
= new_rec
->store(new_rec
, orig_rec
->value
, TDB_INSERT
);
174 TALLOC_FREE(new_rec
);
176 if (!NT_STATUS_IS_OK(status
)) {
183 /**********************************************************************
184 Make a backup of an old passdb and replace the new one with it. We
185 have to do this as between 3.0.x and 3.2.x the hash function changed
186 by mistake (used unsigned char * instead of char *). This means the
187 previous simple update code will fail due to not being able to find
188 existing records to replace in the tdbsam_convert_one() function. JRA.
189 *********************************************************************/
191 static bool tdbsam_convert_backup(const char *dbname
, struct db_context
**pp_db
)
193 TALLOC_CTX
*frame
= talloc_stackframe();
194 const char *tmp_fname
= NULL
;
195 struct db_context
*tmp_db
= NULL
;
196 struct db_context
*orig_db
= *pp_db
;
197 struct tdbsam_backup_state bs
;
200 tmp_fname
= talloc_asprintf(frame
, "%s.tmp", dbname
);
208 /* Remember to open this on the NULL context. We need
209 * it to stay around after we return from here. */
211 tmp_db
= db_open(NULL
, tmp_fname
, 0,
212 TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
213 if (tmp_db
== NULL
) {
214 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
215 "[%s]\n", tmp_fname
));
220 if (orig_db
->transaction_start(orig_db
) != 0) {
221 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
227 if (tmp_db
->transaction_start(tmp_db
) != 0) {
228 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
229 orig_db
->transaction_cancel(orig_db
);
239 ret
= orig_db
->traverse(orig_db
, backup_copy_fn
, (void *)&bs
);
241 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
246 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
250 if (orig_db
->transaction_commit(orig_db
) != 0) {
251 smb_panic("tdbsam_convert_backup: orig commit failed\n");
253 if (tmp_db
->transaction_commit(tmp_db
) != 0) {
254 smb_panic("tdbsam_convert_backup: orig commit failed\n");
257 /* be sure to close the DBs _before_ renaming the file */
259 TALLOC_FREE(orig_db
);
262 /* This is safe from other users as we know we're
263 * under a mutex here. */
265 if (rename(tmp_fname
, dbname
) == -1) {
266 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
270 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
275 /* re-open the converted TDB */
277 orig_db
= db_open(NULL
, dbname
, 0,
278 TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
279 if (orig_db
== NULL
) {
280 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
281 "converted passdb TDB [%s]\n", dbname
));
285 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
288 /* Replace the global db pointer. */
294 if (orig_db
->transaction_cancel(orig_db
) != 0) {
295 smb_panic("tdbsam_convert: transaction_cancel failed");
298 if (tmp_db
->transaction_cancel(tmp_db
) != 0) {
299 smb_panic("tdbsam_convert: transaction_cancel failed");
308 static bool tdbsam_upgrade_next_rid(struct db_context
*db
)
314 ok
= dbwrap_fetch_uint32(db
, NEXT_RID_STRING
, &rid
);
319 tdb
= tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
320 TDB_DEFAULT
, O_RDONLY
, 0644);
323 ok
= tdb_fetch_uint32(tdb
, "RID_COUNTER", &rid
);
332 if (dbwrap_store_uint32(db
, NEXT_RID_STRING
, rid
) != 0) {
339 static bool tdbsam_convert(struct db_context
**pp_db
, const char *name
, int32 from
)
341 struct tdbsam_convert_state state
;
342 struct db_context
*db
= NULL
;
345 /* We only need the update backup for local db's. */
346 if (db_is_local(name
) && !tdbsam_convert_backup(name
, pp_db
)) {
347 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name
));
353 state
.success
= true;
355 if (db
->transaction_start(db
) != 0) {
356 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
360 if (!tdbsam_upgrade_next_rid(db
)) {
361 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
365 ret
= db
->traverse(db
, tdbsam_convert_one
, &state
);
367 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
371 if (!state
.success
) {
372 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
376 if (dbwrap_store_int32(db
, TDBSAM_VERSION_STRING
,
377 TDBSAM_VERSION
) != 0) {
378 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n"));
382 if (dbwrap_store_int32(db
, TDBSAM_MINOR_VERSION_STRING
,
383 TDBSAM_MINOR_VERSION
) != 0) {
384 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor version\n"));
388 if (db
->transaction_commit(db
) != 0) {
389 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
396 if (db
->transaction_cancel(db
) != 0) {
397 smb_panic("tdbsam_convert: transaction_cancel failed");
403 /*********************************************************************
404 Open the tdbsam file based on the absolute path specified.
405 Uses a reference count to allow multiple open calls.
406 *********************************************************************/
408 static bool tdbsam_open( const char *name
)
413 /* check if we are already open */
419 /* Try to open tdb passwd. Create a new one if necessary */
421 db_sam
= db_open(NULL
, name
, 0, TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
422 if (db_sam
== NULL
) {
423 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
428 /* Check the version */
429 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
431 version
= 0; /* Version not found, assume version 0 */
434 /* Get the minor version */
435 minor_version
= dbwrap_fetch_int32(db_sam
, TDBSAM_MINOR_VERSION_STRING
);
436 if (minor_version
== -1) {
437 minor_version
= 0; /* Minor version not found, assume 0 */
440 /* Compare the version */
441 if (version
> TDBSAM_VERSION
) {
442 /* Version more recent than the latest known */
443 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
448 if ( version
< TDBSAM_VERSION
||
449 (version
== TDBSAM_VERSION
&&
450 minor_version
< TDBSAM_MINOR_VERSION
) ) {
452 * Ok - we think we're going to have to convert.
453 * Due to the backup process we now must do to
454 * upgrade we have to get a mutex and re-check
455 * the version. Someone else may have upgraded
456 * whilst we were checking.
459 struct named_mutex
*mtx
= grab_named_mutex(NULL
,
460 "tdbsam_upgrade_mutex",
464 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
469 /* Re-check the version */
470 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
472 version
= 0; /* Version not found, assume version 0 */
475 /* Re-check the minor version */
476 minor_version
= dbwrap_fetch_int32(db_sam
, TDBSAM_MINOR_VERSION_STRING
);
477 if (minor_version
== -1) {
478 minor_version
= 0; /* Minor version not found, assume 0 */
481 /* Compare the version */
482 if (version
> TDBSAM_VERSION
) {
483 /* Version more recent than the latest known */
484 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
490 if ( version
< TDBSAM_VERSION
||
491 (version
== TDBSAM_VERSION
&&
492 minor_version
< TDBSAM_MINOR_VERSION
) ) {
494 * Note that minor versions we read that are greater
495 * than the current minor version we have hard coded
496 * are assumed to be compatible if they have the same
497 * major version. That allows previous versions of the
498 * passdb code that don't know about minor versions to
499 * still use this database. JRA.
502 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
507 TDBSAM_MINOR_VERSION
));
509 if ( !tdbsam_convert(&db_sam
, name
, version
) ) {
510 DEBUG(0, ("tdbsam_open: Error when trying to convert "
511 "tdbsam [%s]\n",name
));
517 DEBUG(3, ("TDBSAM converted successfully.\n"));
522 DEBUG(4,("tdbsam_open: successfully opened %s\n", name
));
527 /******************************************************************
528 Lookup a name in the SAM TDB
529 ******************************************************************/
531 static NTSTATUS
tdbsam_getsampwnam (struct pdb_methods
*my_methods
,
532 struct samu
*user
, const char *sname
)
539 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
540 return NT_STATUS_NO_MEMORY
;
543 /* Data is stored in all lower-case */
544 fstrcpy(name
, sname
);
548 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
550 /* open the database */
552 if ( !tdbsam_open( tdbsam_filename
) ) {
553 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
554 return NT_STATUS_ACCESS_DENIED
;
559 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
561 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
562 DEBUGADD(5, (" Key: %s\n", keystr
));
563 return NT_STATUS_NO_SUCH_USER
;
566 /* unpack the buffer */
568 if (!init_samu_from_buffer(user
, SAMU_BUFFER_LATEST
, data
.dptr
, data
.dsize
)) {
569 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
570 SAFE_FREE(data
.dptr
);
571 return NT_STATUS_NO_MEMORY
;
576 TALLOC_FREE(data
.dptr
);
581 /***************************************************************************
583 **************************************************************************/
585 static NTSTATUS
tdbsam_getsampwrid (struct pdb_methods
*my_methods
,
586 struct samu
*user
, uint32 rid
)
588 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
594 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
600 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
602 /* open the database */
604 if ( !tdbsam_open( tdbsam_filename
) ) {
605 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename
));
606 return NT_STATUS_ACCESS_DENIED
;
611 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
613 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid
, keystr
));
614 return NT_STATUS_UNSUCCESSFUL
;
617 fstrcpy(name
, (const char *)data
.dptr
);
618 TALLOC_FREE(data
.dptr
);
620 return tdbsam_getsampwnam (my_methods
, user
, name
);
623 static NTSTATUS
tdbsam_getsampwsid(struct pdb_methods
*my_methods
,
624 struct samu
* user
, const struct dom_sid
*sid
)
628 if ( !sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
) )
629 return NT_STATUS_UNSUCCESSFUL
;
631 return tdbsam_getsampwrid(my_methods
, user
, rid
);
634 static bool tdb_delete_samacct_only( struct samu
*sam_pass
)
640 fstrcpy(name
, pdb_get_username(sam_pass
));
643 /* set the search key */
645 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
647 /* it's outaa here! 8^) */
648 if ( !tdbsam_open( tdbsam_filename
) ) {
649 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
654 status
= dbwrap_delete_bystring(db_sam
, keystr
);
655 if (!NT_STATUS_IS_OK(status
)) {
656 DEBUG(5, ("Error deleting entry from tdb passwd "
657 "database: %s!\n", nt_errstr(status
)));
664 /***************************************************************************
665 Delete a struct samu records for the username and RID key
666 ****************************************************************************/
668 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
669 struct samu
*sam_pass
)
671 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
676 /* open the database */
678 if ( !tdbsam_open( tdbsam_filename
) ) {
679 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
681 return NT_STATUS_ACCESS_DENIED
;
684 fstrcpy(name
, pdb_get_username(sam_pass
));
687 /* set the search key */
689 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
691 rid
= pdb_get_user_rid(sam_pass
);
693 /* it's outaa here! 8^) */
695 if (db_sam
->transaction_start(db_sam
) != 0) {
696 DEBUG(0, ("Could not start transaction\n"));
697 return NT_STATUS_UNSUCCESSFUL
;
700 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
701 if (!NT_STATUS_IS_OK(nt_status
)) {
702 DEBUG(5, ("Error deleting entry from tdb passwd "
703 "database: %s!\n", nt_errstr(nt_status
)));
707 /* set the search key */
709 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
711 /* it's outaa here! 8^) */
713 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
714 if (!NT_STATUS_IS_OK(nt_status
)) {
715 DEBUG(5, ("Error deleting entry from tdb rid "
716 "database: %s!\n", nt_errstr(nt_status
)));
720 if (db_sam
->transaction_commit(db_sam
) != 0) {
721 DEBUG(0, ("Could not commit transaction\n"));
722 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
728 if (db_sam
->transaction_cancel(db_sam
) != 0) {
729 smb_panic("transaction_cancel failed");
736 /***************************************************************************
737 Update the TDB SAM account record only
738 Assumes that the tdbsam is already open
739 ****************************************************************************/
740 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
749 /* copy the struct samu struct into a BYTE buffer for storage */
751 if ( (data
.dsize
=init_buffer_from_samu(&buf
, newpwd
, False
)) == -1 ) {
752 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
757 fstrcpy(name
, pdb_get_username(newpwd
));
760 DEBUG(5, ("Storing %saccount %s with RID %d\n",
761 flag
== TDB_INSERT
? "(new) " : "", name
,
762 pdb_get_user_rid(newpwd
)));
764 /* setup the USER index key */
765 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
767 /* add the account */
769 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
770 if (!NT_STATUS_IS_OK(status
)) {
771 DEBUG(0, ("Unable to modify passwd TDB: %s!",
784 /***************************************************************************
785 Update the TDB SAM RID record only
786 Assumes that the tdbsam is already open
787 ****************************************************************************/
788 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
795 fstrcpy(name
, pdb_get_username(newpwd
));
799 data
= string_term_tdb_data(name
);
801 /* setup the RID index key */
802 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
,
803 pdb_get_user_rid(newpwd
));
805 /* add the reference */
806 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
807 if (!NT_STATUS_IS_OK(status
)) {
808 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
817 /***************************************************************************
819 ****************************************************************************/
821 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
827 if (!(newrid
= pdb_get_user_rid(newpwd
))) {
828 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
829 pdb_get_username(newpwd
)));
835 /* open the database */
837 if ( !tdbsam_open( tdbsam_filename
) ) {
838 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
842 if (db_sam
->transaction_start(db_sam
) != 0) {
843 DEBUG(0, ("Could not start transaction\n"));
847 /* If we are updating, we may be changing this users RID. Retrieve the old RID
850 if (flag
== TDB_MODIFY
) {
851 struct samu
*account
= samu_new(talloc_tos());
852 if (account
== NULL
) {
853 DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
856 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods
, account
, pdb_get_username(newpwd
)))) {
857 DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
858 pdb_get_username(newpwd
)));
859 TALLOC_FREE(account
);
862 if (!(oldrid
= pdb_get_user_rid(account
))) {
863 DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
864 TALLOC_FREE(account
);
867 TALLOC_FREE(account
);
870 /* Update the new samu entry. */
871 if (!tdb_update_samacct_only(newpwd
, flag
)) {
875 /* Now take care of the case where the RID changed. We need
876 * to delete the old RID key and add the new. */
878 if (flag
== TDB_MODIFY
&& newrid
!= oldrid
) {
881 /* Delete old RID key */
882 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid
));
883 slprintf(keystr
, sizeof(keystr
) - 1, "%s%.8x", RIDPREFIX
, oldrid
);
884 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam
, keystr
))) {
885 DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr
));
888 /* Insert new RID key */
889 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid
));
890 if (!tdb_update_ridrec_only(newpwd
, TDB_INSERT
)) {
894 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
895 flag
== TDB_MODIFY
? "Updating" : "Inserting", newrid
));
896 if (!tdb_update_ridrec_only(newpwd
, flag
)) {
901 if (db_sam
->transaction_commit(db_sam
) != 0) {
902 DEBUG(0, ("Could not commit transaction\n"));
909 if (db_sam
->transaction_cancel(db_sam
) != 0) {
910 smb_panic("transaction_cancel failed");
915 /***************************************************************************
916 Modifies an existing struct samu
917 ****************************************************************************/
919 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
921 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
922 return NT_STATUS_UNSUCCESSFUL
;
927 /***************************************************************************
928 Adds an existing struct samu
929 ****************************************************************************/
931 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
933 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
934 return NT_STATUS_UNSUCCESSFUL
;
939 /***************************************************************************
940 Renames a struct samu
941 - check for the posix user/rename user script
942 - Add and lock the new user record
943 - rename the posix user
944 - rewrite the rid->username record
945 - delete the old user
946 - unlock the new user record
947 ***************************************************************************/
948 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
949 struct samu
*old_acct
,
952 struct samu
*new_acct
= NULL
;
953 char *rename_script
= NULL
;
955 fstring oldname_lower
;
956 fstring newname_lower
;
958 /* can't do anything without an external script */
960 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
961 return NT_STATUS_NO_MEMORY
;
964 rename_script
= talloc_strdup(new_acct
, lp_renameuser_script());
965 if (!rename_script
) {
966 TALLOC_FREE(new_acct
);
967 return NT_STATUS_NO_MEMORY
;
969 if (!*rename_script
) {
970 TALLOC_FREE(new_acct
);
971 return NT_STATUS_ACCESS_DENIED
;
974 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
975 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
977 TALLOC_FREE(new_acct
);
978 return NT_STATUS_NO_MEMORY
;
981 /* open the database */
982 if ( !tdbsam_open( tdbsam_filename
) ) {
983 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
985 TALLOC_FREE(new_acct
);
986 return NT_STATUS_ACCESS_DENIED
;
989 if (db_sam
->transaction_start(db_sam
) != 0) {
990 DEBUG(0, ("Could not start transaction\n"));
991 TALLOC_FREE(new_acct
);
992 return NT_STATUS_ACCESS_DENIED
;
996 /* add the new account and lock it */
997 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
1001 /* Rename the posix user. Follow the semantics of _samr_create_user()
1002 so that we lower case the posix name but preserve the case in passdb */
1004 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
1005 strlower_m( oldname_lower
);
1007 fstrcpy( newname_lower
, newname
);
1008 strlower_m( newname_lower
);
1010 rename_script
= talloc_string_sub2(new_acct
,
1017 if (!rename_script
) {
1020 rename_script
= talloc_string_sub2(new_acct
,
1027 if (!rename_script
) {
1030 rename_ret
= smbrun(rename_script
, NULL
);
1032 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
1033 rename_script
, rename_ret
));
1035 if (rename_ret
!= 0) {
1039 smb_nscd_flush_user_cache();
1041 /* rewrite the rid->username record */
1043 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
1047 tdb_delete_samacct_only( old_acct
);
1049 if (db_sam
->transaction_commit(db_sam
) != 0) {
1051 * Ok, we're screwed. We've changed the posix account, but
1052 * could not adapt passdb.tdb. Shall we change the posix
1055 DEBUG(0, ("transaction_commit failed\n"));
1056 TALLOC_FREE(new_acct
);
1057 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1060 TALLOC_FREE(new_acct
);
1061 return NT_STATUS_OK
;
1064 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1065 smb_panic("transaction_cancel failed");
1068 TALLOC_FREE(new_acct
);
1070 return NT_STATUS_ACCESS_DENIED
;
1073 static uint32_t tdbsam_capabilities(struct pdb_methods
*methods
)
1075 return PDB_CAP_STORE_RIDS
;
1078 static bool tdbsam_new_rid(struct pdb_methods
*methods
, uint32
*prid
)
1083 rid
= BASE_RID
; /* Default if not set */
1085 if (!tdbsam_open(tdbsam_filename
)) {
1086 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1091 status
= dbwrap_trans_change_uint32_atomic(db_sam
, NEXT_RID_STRING
,
1093 if (!NT_STATUS_IS_OK(status
)) {
1094 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1095 NEXT_RID_STRING
, nt_errstr(status
)));
1104 struct tdbsam_search_state
{
1105 struct pdb_methods
*methods
;
1106 uint32_t acct_flags
;
1114 static int tdbsam_collect_rids(struct db_record
*rec
, void *private_data
)
1116 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1117 private_data
, struct tdbsam_search_state
);
1118 size_t prefixlen
= strlen(RIDPREFIX
);
1121 if ((rec
->key
.dsize
< prefixlen
)
1122 || (strncmp((char *)rec
->key
.dptr
, RIDPREFIX
, prefixlen
))) {
1126 rid
= strtoul((char *)rec
->key
.dptr
+prefixlen
, NULL
, 16);
1128 ADD_TO_LARGE_ARRAY(state
, uint32
, rid
, &state
->rids
, &state
->num_rids
,
1129 &state
->array_size
);
1134 static void tdbsam_search_end(struct pdb_search
*search
)
1136 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1137 search
->private_data
, struct tdbsam_search_state
);
1141 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
1142 struct samr_displayentry
*entry
)
1144 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1145 search
->private_data
, struct tdbsam_search_state
);
1146 struct samu
*user
= NULL
;
1152 user
= samu_new(talloc_tos());
1154 DEBUG(0, ("samu_new failed\n"));
1158 if (state
->current
== state
->num_rids
) {
1162 rid
= state
->rids
[state
->current
++];
1164 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
1166 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1168 * Someone has deleted that user since we listed the RIDs
1173 if (!NT_STATUS_IS_OK(status
)) {
1174 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1175 nt_errstr(status
)));
1180 if ((state
->acct_flags
!= 0) &&
1181 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
1185 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
1187 entry
->account_name
= talloc_strdup(search
, pdb_get_username(user
));
1188 entry
->fullname
= talloc_strdup(search
, pdb_get_fullname(user
));
1189 entry
->description
= talloc_strdup(search
, pdb_get_acct_desc(user
));
1193 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
1194 || (entry
->description
== NULL
)) {
1195 DEBUG(0, ("talloc_strdup failed\n"));
1202 static bool tdbsam_search_users(struct pdb_methods
*methods
,
1203 struct pdb_search
*search
,
1206 struct tdbsam_search_state
*state
;
1208 if (!tdbsam_open(tdbsam_filename
)) {
1209 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1214 state
= talloc_zero(search
, struct tdbsam_search_state
);
1215 if (state
== NULL
) {
1216 DEBUG(0, ("talloc failed\n"));
1219 state
->acct_flags
= acct_flags
;
1220 state
->methods
= methods
;
1222 db_sam
->traverse_read(db_sam
, tdbsam_collect_rids
, state
);
1224 search
->private_data
= state
;
1225 search
->next_entry
= tdbsam_search_next_entry
;
1226 search
->search_end
= tdbsam_search_end
;
1231 /*********************************************************************
1232 Initialize the tdb sam backend. Setup the dispath table of methods,
1233 open the tdb, etc...
1234 *********************************************************************/
1236 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
1239 char *tdbfile
= NULL
;
1240 const char *pfile
= location
;
1242 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
1246 (*pdb_method
)->name
= "tdbsam";
1248 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
1249 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
1250 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
1251 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
1252 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
1253 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
1254 (*pdb_method
)->search_users
= tdbsam_search_users
;
1256 (*pdb_method
)->capabilities
= tdbsam_capabilities
;
1257 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
1259 /* save the path for later */
1262 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
1263 PASSDB_FILE_NAME
) < 0) {
1264 return NT_STATUS_NO_MEMORY
;
1268 tdbsam_filename
= SMB_STRDUP(pfile
);
1269 if (!tdbsam_filename
) {
1270 return NT_STATUS_NO_MEMORY
;
1274 /* no private data */
1276 (*pdb_method
)->private_data
= NULL
;
1277 (*pdb_method
)->free_private_data
= NULL
;
1279 return NT_STATUS_OK
;
1282 NTSTATUS
pdb_tdbsam_init(void)
1284 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);