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_getsampwrid: 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^) */
403 if ( !tdbsam_open( tdbsam_filename
) ) {
404 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
409 status
= dbwrap_delete_bystring(db_sam
, keystr
);
410 if (!NT_STATUS_IS_OK(status
)) {
411 DEBUG(5, ("Error deleting entry from tdb passwd "
412 "database: %s!\n", nt_errstr(status
)));
419 /***************************************************************************
420 Delete a struct samu records for the username and RID key
421 ****************************************************************************/
423 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
424 struct samu
*sam_pass
)
426 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
431 /* open the database */
433 if ( !tdbsam_open( tdbsam_filename
) ) {
434 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
436 return NT_STATUS_ACCESS_DENIED
;
439 fstrcpy(name
, pdb_get_username(sam_pass
));
442 /* set the search key */
444 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
446 rid
= pdb_get_user_rid(sam_pass
);
448 /* it's outaa here! 8^) */
450 if (db_sam
->transaction_start(db_sam
) != 0) {
451 DEBUG(0, ("Could not start transaction\n"));
452 return NT_STATUS_UNSUCCESSFUL
;
455 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
456 if (!NT_STATUS_IS_OK(nt_status
)) {
457 DEBUG(5, ("Error deleting entry from tdb passwd "
458 "database: %s!\n", nt_errstr(nt_status
)));
462 /* set the search key */
464 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
466 /* it's outaa here! 8^) */
468 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
469 if (!NT_STATUS_IS_OK(nt_status
)) {
470 DEBUG(5, ("Error deleting entry from tdb rid "
471 "database: %s!\n", nt_errstr(nt_status
)));
475 if (db_sam
->transaction_commit(db_sam
) != 0) {
476 DEBUG(0, ("Could not commit transaction\n"));
477 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
483 if (db_sam
->transaction_cancel(db_sam
) != 0) {
484 smb_panic("transaction_cancel failed");
491 /***************************************************************************
492 Update the TDB SAM account record only
493 Assumes that the tdbsam is already open
494 ****************************************************************************/
495 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
504 /* copy the struct samu struct into a BYTE buffer for storage */
506 if ( (data
.dsize
=init_buffer_from_samu(&buf
, newpwd
, False
)) == -1 ) {
507 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
512 fstrcpy(name
, pdb_get_username(newpwd
));
515 DEBUG(5, ("Storing %saccount %s with RID %d\n",
516 flag
== TDB_INSERT
? "(new) " : "", name
,
517 pdb_get_user_rid(newpwd
)));
519 /* setup the USER index key */
520 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
522 /* add the account */
524 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
525 if (!NT_STATUS_IS_OK(status
)) {
526 DEBUG(0, ("Unable to modify passwd TDB: %s!",
539 /***************************************************************************
540 Update the TDB SAM RID record only
541 Assumes that the tdbsam is already open
542 ****************************************************************************/
543 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
550 fstrcpy(name
, pdb_get_username(newpwd
));
554 data
= string_term_tdb_data(name
);
556 /* setup the RID index key */
557 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
,
558 pdb_get_user_rid(newpwd
));
560 /* add the reference */
561 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
562 if (!NT_STATUS_IS_OK(status
)) {
563 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
572 /***************************************************************************
574 ****************************************************************************/
576 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
579 if (!pdb_get_user_rid(newpwd
)) {
580 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
581 pdb_get_username(newpwd
)));
585 /* open the database */
587 if ( !tdbsam_open( tdbsam_filename
) ) {
588 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
592 if (db_sam
->transaction_start(db_sam
) != 0) {
593 DEBUG(0, ("Could not start transaction\n"));
597 if (!tdb_update_samacct_only(newpwd
, flag
)
598 || !tdb_update_ridrec_only(newpwd
, flag
)) {
602 if (db_sam
->transaction_commit(db_sam
) != 0) {
603 DEBUG(0, ("Could not commit transaction\n"));
610 if (db_sam
->transaction_cancel(db_sam
) != 0) {
611 smb_panic("transaction_cancel failed");
616 /***************************************************************************
617 Modifies an existing struct samu
618 ****************************************************************************/
620 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
622 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
623 return NT_STATUS_UNSUCCESSFUL
;
628 /***************************************************************************
629 Adds an existing struct samu
630 ****************************************************************************/
632 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
634 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
635 return NT_STATUS_UNSUCCESSFUL
;
640 /***************************************************************************
641 Renames a struct samu
642 - check for the posix user/rename user script
643 - Add and lock the new user record
644 - rename the posix user
645 - rewrite the rid->username record
646 - delete the old user
647 - unlock the new user record
648 ***************************************************************************/
649 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
650 struct samu
*old_acct
,
653 struct samu
*new_acct
= NULL
;
654 char *rename_script
= NULL
;
656 fstring oldname_lower
;
657 fstring newname_lower
;
659 /* can't do anything without an external script */
661 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
662 return NT_STATUS_NO_MEMORY
;
665 rename_script
= talloc_strdup(new_acct
, lp_renameuser_script());
666 if (!rename_script
) {
667 TALLOC_FREE(new_acct
);
668 return NT_STATUS_NO_MEMORY
;
670 if (!*rename_script
) {
671 TALLOC_FREE(new_acct
);
672 return NT_STATUS_ACCESS_DENIED
;
675 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
676 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
678 TALLOC_FREE(new_acct
);
679 return NT_STATUS_NO_MEMORY
;
682 /* open the database */
683 if ( !tdbsam_open( tdbsam_filename
) ) {
684 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
686 TALLOC_FREE(new_acct
);
687 return NT_STATUS_ACCESS_DENIED
;
690 if (db_sam
->transaction_start(db_sam
) != 0) {
691 DEBUG(0, ("Could not start transaction\n"));
692 TALLOC_FREE(new_acct
);
693 return NT_STATUS_ACCESS_DENIED
;
697 /* add the new account and lock it */
698 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
702 /* Rename the posix user. Follow the semantics of _samr_create_user()
703 so that we lower case the posix name but preserve the case in passdb */
705 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
706 strlower_m( oldname_lower
);
708 fstrcpy( newname_lower
, newname
);
709 strlower_m( newname_lower
);
711 rename_script
= talloc_string_sub2(new_acct
,
718 if (!rename_script
) {
721 rename_script
= talloc_string_sub2(new_acct
,
728 if (!rename_script
) {
731 rename_ret
= smbrun(rename_script
, NULL
);
733 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
734 rename_script
, rename_ret
));
736 if (rename_ret
!= 0) {
740 smb_nscd_flush_user_cache();
742 /* rewrite the rid->username record */
744 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
748 tdb_delete_samacct_only( old_acct
);
750 if (db_sam
->transaction_commit(db_sam
) != 0) {
752 * Ok, we're screwed. We've changed the posix account, but
753 * could not adapt passdb.tdb. Shall we change the posix
756 DEBUG(0, ("transaction_commit failed\n"));
757 TALLOC_FREE(new_acct
);
758 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
761 TALLOC_FREE(new_acct
);
765 if (db_sam
->transaction_cancel(db_sam
) != 0) {
766 smb_panic("transaction_cancel failed");
769 TALLOC_FREE(new_acct
);
771 return NT_STATUS_ACCESS_DENIED
;
774 static bool tdbsam_rid_algorithm(struct pdb_methods
*methods
)
779 static bool tdbsam_new_rid(struct pdb_methods
*methods
, uint32
*prid
)
783 rid
= BASE_RID
; /* Default if not set */
785 if (!tdbsam_open(tdbsam_filename
)) {
786 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
791 if (dbwrap_change_uint32_atomic(db_sam
, NEXT_RID_STRING
, &rid
, 1) != 0) {
792 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s\n",
802 struct tdbsam_search_state
{
803 struct pdb_methods
*methods
;
812 static int tdbsam_collect_rids(struct db_record
*rec
, void *private_data
)
814 struct tdbsam_search_state
*state
= talloc_get_type_abort(
815 private_data
, struct tdbsam_search_state
);
816 size_t prefixlen
= strlen(RIDPREFIX
);
819 if ((rec
->key
.dsize
< prefixlen
)
820 || (strncmp((char *)rec
->key
.dptr
, RIDPREFIX
, prefixlen
))) {
824 rid
= strtoul((char *)rec
->key
.dptr
+prefixlen
, NULL
, 16);
826 ADD_TO_LARGE_ARRAY(state
, uint32
, rid
, &state
->rids
, &state
->num_rids
,
832 static void tdbsam_search_end(struct pdb_search
*search
)
834 struct tdbsam_search_state
*state
= talloc_get_type_abort(
835 search
->private_data
, struct tdbsam_search_state
);
839 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
840 struct samr_displayentry
*entry
)
842 struct tdbsam_search_state
*state
= talloc_get_type_abort(
843 search
->private_data
, struct tdbsam_search_state
);
844 struct samu
*user
= NULL
;
850 user
= samu_new(talloc_tos());
852 DEBUG(0, ("samu_new failed\n"));
856 if (state
->current
== state
->num_rids
) {
860 rid
= state
->rids
[state
->current
++];
862 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
864 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
866 * Someone has deleted that user since we listed the RIDs
871 if (!NT_STATUS_IS_OK(status
)) {
872 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
878 if ((state
->acct_flags
!= 0) &&
879 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
883 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
885 entry
->account_name
= talloc_strdup(search
, pdb_get_username(user
));
886 entry
->fullname
= talloc_strdup(search
, pdb_get_fullname(user
));
887 entry
->description
= talloc_strdup(search
, pdb_get_acct_desc(user
));
891 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
892 || (entry
->description
== NULL
)) {
893 DEBUG(0, ("talloc_strdup failed\n"));
900 static bool tdbsam_search_users(struct pdb_methods
*methods
,
901 struct pdb_search
*search
,
904 struct tdbsam_search_state
*state
;
906 if (!tdbsam_open(tdbsam_filename
)) {
907 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
912 state
= talloc_zero(search
, struct tdbsam_search_state
);
914 DEBUG(0, ("talloc failed\n"));
917 state
->acct_flags
= acct_flags
;
918 state
->methods
= methods
;
920 db_sam
->traverse_read(db_sam
, tdbsam_collect_rids
, state
);
922 search
->private_data
= state
;
923 search
->next_entry
= tdbsam_search_next_entry
;
924 search
->search_end
= tdbsam_search_end
;
929 /*********************************************************************
930 Initialize the tdb sam backend. Setup the dispath table of methods,
932 *********************************************************************/
934 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
937 char *tdbfile
= NULL
;
938 const char *pfile
= location
;
940 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
944 (*pdb_method
)->name
= "tdbsam";
946 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
947 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
948 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
949 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
950 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
951 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
952 (*pdb_method
)->search_users
= tdbsam_search_users
;
954 (*pdb_method
)->rid_algorithm
= tdbsam_rid_algorithm
;
955 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
957 /* save the path for later */
960 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
961 PASSDB_FILE_NAME
) < 0) {
962 return NT_STATUS_NO_MEMORY
;
966 tdbsam_filename
= SMB_STRDUP(pfile
);
967 if (!tdbsam_filename
) {
968 return NT_STATUS_NO_MEMORY
;
972 /* no private data */
974 (*pdb_method
)->private_data
= NULL
;
975 (*pdb_method
)->free_private_data
= NULL
;
980 NTSTATUS
pdb_tdbsam_init(void)
982 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);