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
8 * Copyright (C) Andrew Bartlett 2002
9 * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
11 * This program is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 3 of the License, or (at your option)
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License along with
22 * this program; if not, see <http://www.gnu.org/licenses/>.
27 #if 0 /* when made a module use this */
29 static int tdbsam_debug_level
= DBGC_ALL
;
31 #define DBGC_CLASS tdbsam_debug_level
36 #define DBGC_CLASS DBGC_PASSDB
40 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */
41 #define TDBSAM_VERSION_STRING "INFO/version"
42 #define PASSDB_FILE_NAME "passdb.tdb"
43 #define USERPREFIX "USER_"
44 #define USERPREFIX_LEN 5
45 #define RIDPREFIX "RID_"
46 #define PRIVPREFIX "PRIV_"
47 #define NEXT_RID_STRING "NEXT_RID"
49 /* GLOBAL TDB SAM CONTEXT */
51 static struct db_context
*db_sam
;
52 static char *tdbsam_filename
;
54 struct tdbsam_convert_state
{
59 static int tdbsam_convert_one(struct db_record
*rec
, void *priv
)
61 struct tdbsam_convert_state
*state
=
62 (struct tdbsam_convert_state
*)priv
;
68 if (rec
->key
.dsize
< USERPREFIX_LEN
) {
71 if (strncmp((char *)rec
->key
.dptr
, USERPREFIX
, USERPREFIX_LEN
) != 0) {
75 user
= samu_new(talloc_tos());
77 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
78 state
->success
= false;
82 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
83 "(version:%d)\n", rec
->key
.dptr
, state
->from
));
85 switch (state
->from
) {
87 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V0
,
88 (uint8
*)rec
->value
.dptr
,
92 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V1
,
93 (uint8
*)rec
->value
.dptr
,
97 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V2
,
98 (uint8
*)rec
->value
.dptr
,
102 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V3
,
103 (uint8
*)rec
->value
.dptr
,
106 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V4
,
107 (uint8
*)rec
->value
.dptr
,
111 /* unknown tdbsam version */
115 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
116 "from TDB (key:%s) (version:%d)\n", rec
->key
.dptr
,
119 state
->success
= false;
123 data
.dsize
= init_buffer_from_samu(&data
.dptr
, user
, false);
126 if (data
.dsize
== -1) {
127 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
128 "the new format\n"));
129 state
->success
= false;
133 status
= rec
->store(rec
, data
, TDB_MODIFY
);
134 if (!NT_STATUS_IS_OK(status
)) {
135 DEBUG(0, ("Could not store the new record: %s\n",
137 state
->success
= false;
144 static bool tdbsam_upgrade_next_rid(struct db_context
*db
)
150 ok
= dbwrap_fetch_uint32(db
, NEXT_RID_STRING
, &rid
);
155 tdb
= tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
156 TDB_DEFAULT
, O_RDONLY
, 0644);
159 ok
= tdb_fetch_uint32(tdb
, "RID_COUNTER", &rid
);
168 if (dbwrap_store_uint32(db
, NEXT_RID_STRING
, rid
) != 0) {
175 static bool tdbsam_convert(struct db_context
*db
, int32 from
)
177 struct tdbsam_convert_state state
;
181 state
.success
= true;
183 if (db
->transaction_start(db
) != 0) {
184 DEBUG(0, ("Could not start transaction\n"));
188 if (!tdbsam_upgrade_next_rid(db
)) {
189 DEBUG(0, ("tdbsam_upgrade_next_rid failed\n"));
193 ret
= db
->traverse(db
, tdbsam_convert_one
, &state
);
195 DEBUG(0, ("traverse failed\n"));
199 if (!state
.success
) {
200 DEBUG(0, ("Converting records failed\n"));
204 if (dbwrap_store_int32(db
, TDBSAM_VERSION_STRING
,
205 TDBSAM_VERSION
) != 0) {
206 DEBUG(0, ("Could not store tdbsam version\n"));
210 if (db
->transaction_commit(db
) != 0) {
211 DEBUG(0, ("Could not commit transaction\n"));
218 if (db
->transaction_cancel(db
) != 0) {
219 smb_panic("transaction_cancel failed");
225 /*********************************************************************
226 Open the tdbsam file based on the absolute path specified.
227 Uses a reference count to allow multiple open calls.
228 *********************************************************************/
230 static bool tdbsam_open( const char *name
)
234 /* check if we are already open */
240 /* Try to open tdb passwd. Create a new one if necessary */
242 db_sam
= db_open(NULL
, name
, 0, TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
243 if (db_sam
== NULL
) {
244 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
249 /* Check the version */
250 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
252 version
= 0; /* Version not found, assume version 0 */
255 /* Compare the version */
256 if (version
> TDBSAM_VERSION
) {
257 /* Version more recent than the latest known */
258 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
263 if ( version
< TDBSAM_VERSION
) {
264 DEBUG(1, ("tdbsam_open: Converting version %d database to "
265 "version %d.\n", version
, TDBSAM_VERSION
));
267 if ( !tdbsam_convert(db_sam
, version
) ) {
268 DEBUG(0, ("tdbsam_open: Error when trying to convert "
269 "tdbsam [%s]\n",name
));
274 DEBUG(3, ("TDBSAM converted successfully.\n"));
277 DEBUG(4,("tdbsam_open: successfully opened %s\n", name
));
282 /******************************************************************
283 Lookup a name in the SAM TDB
284 ******************************************************************/
286 static NTSTATUS
tdbsam_getsampwnam (struct pdb_methods
*my_methods
,
287 struct samu
*user
, const char *sname
)
294 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
295 return NT_STATUS_NO_MEMORY
;
298 /* Data is stored in all lower-case */
299 fstrcpy(name
, sname
);
303 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
305 /* open the database */
307 if ( !tdbsam_open( tdbsam_filename
) ) {
308 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
309 return NT_STATUS_ACCESS_DENIED
;
314 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
316 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
317 DEBUGADD(5, (" Key: %s\n", keystr
));
318 return NT_STATUS_NO_SUCH_USER
;
321 /* unpack the buffer */
323 if (!init_samu_from_buffer(user
, SAMU_BUFFER_LATEST
, data
.dptr
, data
.dsize
)) {
324 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
325 SAFE_FREE(data
.dptr
);
326 return NT_STATUS_NO_MEMORY
;
331 TALLOC_FREE(data
.dptr
);
336 /***************************************************************************
338 **************************************************************************/
340 static NTSTATUS
tdbsam_getsampwrid (struct pdb_methods
*my_methods
,
341 struct samu
*user
, uint32 rid
)
343 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
349 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
355 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
357 /* open the database */
359 if ( !tdbsam_open( tdbsam_filename
) ) {
360 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
361 return NT_STATUS_ACCESS_DENIED
;
366 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
368 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid
, keystr
));
369 return NT_STATUS_UNSUCCESSFUL
;
372 fstrcpy(name
, (const char *)data
.dptr
);
373 TALLOC_FREE(data
.dptr
);
375 return tdbsam_getsampwnam (my_methods
, user
, name
);
378 static NTSTATUS
tdbsam_getsampwsid(struct pdb_methods
*my_methods
,
379 struct samu
* user
, const DOM_SID
*sid
)
383 if ( !sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
) )
384 return NT_STATUS_UNSUCCESSFUL
;
386 return tdbsam_getsampwrid(my_methods
, user
, rid
);
389 static bool tdb_delete_samacct_only( struct samu
*sam_pass
)
395 fstrcpy(name
, pdb_get_username(sam_pass
));
398 /* set the search key */
400 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
402 /* it's outaa here! 8^) */
404 status
= dbwrap_delete_bystring(db_sam
, keystr
);
405 if (!NT_STATUS_IS_OK(status
)) {
406 DEBUG(5, ("Error deleting entry from tdb passwd "
407 "database: %s!\n", nt_errstr(status
)));
414 /***************************************************************************
415 Delete a struct samu records for the username and RID key
416 ****************************************************************************/
418 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
419 struct samu
*sam_pass
)
421 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
426 /* open the database */
428 if ( !tdbsam_open( tdbsam_filename
) ) {
429 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
431 return NT_STATUS_ACCESS_DENIED
;
434 fstrcpy(name
, pdb_get_username(sam_pass
));
437 /* set the search key */
439 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
441 rid
= pdb_get_user_rid(sam_pass
);
443 /* it's outaa here! 8^) */
445 if (db_sam
->transaction_start(db_sam
) != 0) {
446 DEBUG(0, ("Could not start transaction\n"));
447 return NT_STATUS_UNSUCCESSFUL
;
450 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
451 if (!NT_STATUS_IS_OK(nt_status
)) {
452 DEBUG(5, ("Error deleting entry from tdb passwd "
453 "database: %s!\n", nt_errstr(nt_status
)));
457 /* set the search key */
459 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
461 /* it's outaa here! 8^) */
463 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
464 if (!NT_STATUS_IS_OK(nt_status
)) {
465 DEBUG(5, ("Error deleting entry from tdb rid "
466 "database: %s!\n", nt_errstr(nt_status
)));
470 if (db_sam
->transaction_commit(db_sam
) != 0) {
471 DEBUG(0, ("Could not commit transaction\n"));
472 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
478 if (db_sam
->transaction_cancel(db_sam
) != 0) {
479 smb_panic("transaction_cancel failed");
486 /***************************************************************************
487 Update the TDB SAM account record only
488 Assumes that the tdbsam is already open
489 ****************************************************************************/
490 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
499 /* copy the struct samu struct into a BYTE buffer for storage */
501 if ( (data
.dsize
=init_buffer_from_samu(&buf
, newpwd
, False
)) == -1 ) {
502 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
507 fstrcpy(name
, pdb_get_username(newpwd
));
510 DEBUG(5, ("Storing %saccount %s with RID %d\n",
511 flag
== TDB_INSERT
? "(new) " : "", name
,
512 pdb_get_user_rid(newpwd
)));
514 /* setup the USER index key */
515 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
517 /* add the account */
519 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
520 if (!NT_STATUS_IS_OK(status
)) {
521 DEBUG(0, ("Unable to modify passwd TDB: %s!",
534 /***************************************************************************
535 Update the TDB SAM RID record only
536 Assumes that the tdbsam is already open
537 ****************************************************************************/
538 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
545 fstrcpy(name
, pdb_get_username(newpwd
));
549 data
= string_term_tdb_data(name
);
551 /* setup the RID index key */
552 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
,
553 pdb_get_user_rid(newpwd
));
555 /* add the reference */
556 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
557 if (!NT_STATUS_IS_OK(status
)) {
558 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
567 /***************************************************************************
569 ****************************************************************************/
571 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
574 if (!pdb_get_user_rid(newpwd
)) {
575 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
576 pdb_get_username(newpwd
)));
580 /* open the database */
582 if ( !tdbsam_open( tdbsam_filename
) ) {
583 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
587 if (db_sam
->transaction_start(db_sam
) != 0) {
588 DEBUG(0, ("Could not start transaction\n"));
592 if (!tdb_update_samacct_only(newpwd
, flag
)
593 || !tdb_update_ridrec_only(newpwd
, flag
)) {
597 if (db_sam
->transaction_commit(db_sam
) != 0) {
598 DEBUG(0, ("Could not commit transaction\n"));
605 if (db_sam
->transaction_cancel(db_sam
) != 0) {
606 smb_panic("transaction_cancel failed");
611 /***************************************************************************
612 Modifies an existing struct samu
613 ****************************************************************************/
615 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
617 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
618 return NT_STATUS_UNSUCCESSFUL
;
623 /***************************************************************************
624 Adds an existing struct samu
625 ****************************************************************************/
627 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
629 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
630 return NT_STATUS_UNSUCCESSFUL
;
635 /***************************************************************************
636 Renames a struct samu
637 - check for the posix user/rename user script
638 - Add and lock the new user record
639 - rename the posix user
640 - rewrite the rid->username record
641 - delete the old user
642 - unlock the new user record
643 ***************************************************************************/
644 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
645 struct samu
*old_acct
,
648 struct samu
*new_acct
= NULL
;
649 char *rename_script
= NULL
;
651 fstring oldname_lower
;
652 fstring newname_lower
;
654 /* can't do anything without an external script */
656 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
657 return NT_STATUS_NO_MEMORY
;
660 rename_script
= talloc_strdup(new_acct
, lp_renameuser_script());
661 if (!rename_script
) {
662 TALLOC_FREE(new_acct
);
663 return NT_STATUS_NO_MEMORY
;
665 if (!*rename_script
) {
666 TALLOC_FREE(new_acct
);
667 return NT_STATUS_ACCESS_DENIED
;
670 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
671 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
673 TALLOC_FREE(new_acct
);
674 return NT_STATUS_NO_MEMORY
;
677 /* open the database */
678 if ( !tdbsam_open( tdbsam_filename
) ) {
679 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
681 TALLOC_FREE(new_acct
);
682 return NT_STATUS_ACCESS_DENIED
;
685 if (db_sam
->transaction_start(db_sam
) != 0) {
686 DEBUG(0, ("Could not start transaction\n"));
687 TALLOC_FREE(new_acct
);
688 return NT_STATUS_ACCESS_DENIED
;
692 /* add the new account and lock it */
693 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
697 /* Rename the posix user. Follow the semantics of _samr_create_user()
698 so that we lower case the posix name but preserve the case in passdb */
700 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
701 strlower_m( oldname_lower
);
703 fstrcpy( newname_lower
, newname
);
704 strlower_m( newname_lower
);
706 rename_script
= talloc_string_sub2(new_acct
,
713 if (!rename_script
) {
716 rename_script
= talloc_string_sub2(new_acct
,
723 if (!rename_script
) {
726 rename_ret
= smbrun(rename_script
, NULL
);
728 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
729 rename_script
, rename_ret
));
731 if (rename_ret
!= 0) {
735 smb_nscd_flush_user_cache();
737 /* rewrite the rid->username record */
739 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
743 tdb_delete_samacct_only( old_acct
);
745 if (db_sam
->transaction_commit(db_sam
) != 0) {
747 * Ok, we're screwed. We've changed the posix account, but
748 * could not adapt passdb.tdb. Shall we change the posix
751 DEBUG(0, ("transaction_commit failed\n"));
752 TALLOC_FREE(new_acct
);
753 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
756 TALLOC_FREE(new_acct
);
760 if (db_sam
->transaction_cancel(db_sam
) != 0) {
761 smb_panic("transaction_cancel failed");
764 TALLOC_FREE(new_acct
);
766 return NT_STATUS_ACCESS_DENIED
;
769 static bool tdbsam_rid_algorithm(struct pdb_methods
*methods
)
774 static bool tdbsam_new_rid(struct pdb_methods
*methods
, uint32
*prid
)
778 rid
= BASE_RID
; /* Default if not set */
780 if (dbwrap_change_uint32_atomic(db_sam
, NEXT_RID_STRING
, &rid
, 1) != 0) {
781 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s\n",
791 struct tdbsam_search_state
{
792 struct pdb_methods
*methods
;
801 static int tdbsam_collect_rids(struct db_record
*rec
, void *private_data
)
803 struct tdbsam_search_state
*state
= talloc_get_type_abort(
804 private_data
, struct tdbsam_search_state
);
805 size_t prefixlen
= strlen(RIDPREFIX
);
808 if ((rec
->key
.dsize
< prefixlen
)
809 || (strncmp((char *)rec
->key
.dptr
, RIDPREFIX
, prefixlen
))) {
813 rid
= strtoul((char *)rec
->key
.dptr
+prefixlen
, NULL
, 16);
815 ADD_TO_LARGE_ARRAY(state
, uint32
, rid
, &state
->rids
, &state
->num_rids
,
821 static void tdbsam_search_end(struct pdb_search
*search
)
823 struct tdbsam_search_state
*state
= talloc_get_type_abort(
824 search
->private_data
, struct tdbsam_search_state
);
828 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
829 struct samr_displayentry
*entry
)
831 struct tdbsam_search_state
*state
= talloc_get_type_abort(
832 search
->private_data
, struct tdbsam_search_state
);
833 struct samu
*user
= NULL
;
839 user
= samu_new(talloc_tos());
841 DEBUG(0, ("samu_new failed\n"));
845 if (state
->current
== state
->num_rids
) {
849 rid
= state
->rids
[state
->current
++];
851 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
853 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
855 * Someone has deleted that user since we listed the RIDs
860 if (!NT_STATUS_IS_OK(status
)) {
861 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
867 if ((state
->acct_flags
!= 0) &&
868 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
872 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
874 entry
->account_name
= talloc_strdup(
875 search
->mem_ctx
, pdb_get_username(user
));
876 entry
->fullname
= talloc_strdup(
877 search
->mem_ctx
, pdb_get_fullname(user
));
878 entry
->description
= talloc_strdup(
879 search
->mem_ctx
, pdb_get_acct_desc(user
));
883 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
884 || (entry
->description
== NULL
)) {
885 DEBUG(0, ("talloc_strdup failed\n"));
892 static bool tdbsam_search_users(struct pdb_methods
*methods
,
893 struct pdb_search
*search
,
896 struct tdbsam_search_state
*state
;
898 if (!tdbsam_open(tdbsam_filename
)) {
899 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
904 state
= TALLOC_ZERO_P(search
->mem_ctx
, struct tdbsam_search_state
);
906 DEBUG(0, ("talloc failed\n"));
909 state
->acct_flags
= acct_flags
;
910 state
->methods
= methods
;
912 db_sam
->traverse_read(db_sam
, tdbsam_collect_rids
, state
);
914 search
->private_data
= state
;
915 search
->next_entry
= tdbsam_search_next_entry
;
916 search
->search_end
= tdbsam_search_end
;
921 /*********************************************************************
922 Initialize the tdb sam backend. Setup the dispath table of methods,
924 *********************************************************************/
926 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
929 char *tdbfile
= NULL
;
930 const char *pfile
= location
;
932 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
936 (*pdb_method
)->name
= "tdbsam";
938 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
939 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
940 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
941 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
942 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
943 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
944 (*pdb_method
)->search_users
= tdbsam_search_users
;
946 (*pdb_method
)->rid_algorithm
= tdbsam_rid_algorithm
;
947 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
949 /* save the path for later */
952 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
953 PASSDB_FILE_NAME
) < 0) {
954 return NT_STATUS_NO_MEMORY
;
958 tdbsam_filename
= SMB_STRDUP(pfile
);
959 if (!tdbsam_filename
) {
960 return NT_STATUS_NO_MEMORY
;
964 /* no private data */
966 (*pdb_method
)->private_data
= NULL
;
967 (*pdb_method
)->free_private_data
= NULL
;
972 NTSTATUS
pdb_tdbsam_init(void)
974 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);