2 * Unix SMB/CIFS implementation.
3 * SMB parameters and setup
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Simo Sorce 2000-2003
6 * Copyright (C) Gerald Carter 2000-2006
7 * Copyright (C) Jeremy Allison 2001-2009
8 * Copyright (C) Andrew Bartlett 2002
9 * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
11 * This program is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 3 of the License, or (at your option)
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License along with
22 * this program; if not, see <http://www.gnu.org/licenses/>.
26 #include "system/filesys.h"
28 #include "dbwrap/dbwrap.h"
29 #include "dbwrap/dbwrap_open.h"
30 #include "../libcli/security/security.h"
32 #include "passdb/pdb_tdb.h"
33 #include "lib/util/smb_strtox.h"
34 #include "lib/util/string_wrappers.h"
36 #if 0 /* when made a module use this */
38 static int tdbsam_debug_level
= DBGC_ALL
;
40 #define DBGC_CLASS tdbsam_debug_level
45 #define DBGC_CLASS DBGC_PASSDB
49 #define TDBSAM_VERSION 4 /* Most recent TDBSAM version */
50 #define TDBSAM_MINOR_VERSION 0 /* Most recent TDBSAM minor version */
51 #define TDBSAM_VERSION_STRING "INFO/version"
52 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version"
53 #define PASSDB_FILE_NAME "passdb.tdb"
54 #define USERPREFIX "USER_"
55 #define USERPREFIX_LEN 5
56 #define RIDPREFIX "RID_"
57 #define PRIVPREFIX "PRIV_"
58 #define NEXT_RID_STRING "NEXT_RID"
60 /* GLOBAL TDB SAM CONTEXT */
62 static struct db_context
*db_sam
;
63 static char *tdbsam_filename
;
64 static bool map_builtin
;
66 struct tdbsam_convert_state
{
71 static int tdbsam_convert_one(struct db_record
*rec
, void *priv
)
73 struct tdbsam_convert_state
*state
=
74 (struct tdbsam_convert_state
*)priv
;
82 key
= dbwrap_record_get_key(rec
);
84 if (key
.dsize
< USERPREFIX_LEN
) {
87 if (strncmp((char *)key
.dptr
, USERPREFIX
, USERPREFIX_LEN
) != 0) {
91 user
= samu_new(talloc_tos());
93 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
94 state
->success
= false;
98 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
99 "(version:%d)\n", (char *)key
.dptr
, state
->from
));
101 value
= dbwrap_record_get_value(rec
);
103 switch (state
->from
) {
105 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V0
,
106 (uint8_t *)value
.dptr
,
110 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V1
,
111 (uint8_t *)value
.dptr
,
115 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V2
,
116 (uint8_t *)value
.dptr
,
120 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V3
,
121 (uint8_t *)value
.dptr
,
125 ret
= init_samu_from_buffer(user
, SAMU_BUFFER_V4
,
126 (uint8_t *)value
.dptr
,
130 /* unknown tdbsam version */
134 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
135 "from TDB (key:%s) (version:%d)\n", (char *)key
.dptr
,
138 state
->success
= false;
142 data
.dsize
= init_buffer_from_samu(&data
.dptr
, user
, false);
145 if (data
.dsize
== -1) {
146 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
147 "the new format\n"));
148 state
->success
= false;
152 status
= dbwrap_record_store(rec
, data
, TDB_MODIFY
);
153 if (!NT_STATUS_IS_OK(status
)) {
154 DEBUG(0, ("Could not store the new record: %s\n",
156 state
->success
= false;
163 /**********************************************************************
164 Struct and function to backup an old record.
165 *********************************************************************/
167 struct tdbsam_backup_state
{
168 struct db_context
*new_db
;
172 static int backup_copy_fn(struct db_record
*orig_rec
, void *state
)
174 struct tdbsam_backup_state
*bs
= (struct tdbsam_backup_state
*)state
;
175 struct db_record
*new_rec
;
180 key
= dbwrap_record_get_key(orig_rec
);
182 new_rec
= dbwrap_fetch_locked(bs
->new_db
, talloc_tos(), key
);
183 if (new_rec
== NULL
) {
188 value
= dbwrap_record_get_value(orig_rec
);
190 status
= dbwrap_record_store(new_rec
, value
, TDB_INSERT
);
192 TALLOC_FREE(new_rec
);
194 if (!NT_STATUS_IS_OK(status
)) {
201 /**********************************************************************
202 Make a backup of an old passdb and replace the new one with it. We
203 have to do this as between 3.0.x and 3.2.x the hash function changed
204 by mistake (used unsigned char * instead of char *). This means the
205 previous simple update code will fail due to not being able to find
206 existing records to replace in the tdbsam_convert_one() function. JRA.
207 *********************************************************************/
209 static bool tdbsam_convert_backup(const char *dbname
, struct db_context
**pp_db
)
211 TALLOC_CTX
*frame
= talloc_stackframe();
212 const char *tmp_fname
= NULL
;
213 struct db_context
*tmp_db
= NULL
;
214 struct db_context
*orig_db
= *pp_db
;
215 struct tdbsam_backup_state bs
;
218 tmp_fname
= talloc_asprintf(frame
, "%s.tmp", dbname
);
226 /* Remember to open this on the NULL context. We need
227 * it to stay around after we return from here. */
229 tmp_db
= db_open(NULL
, tmp_fname
, 0,
230 TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600,
231 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
232 if (tmp_db
== NULL
) {
233 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
234 "[%s]\n", tmp_fname
));
239 if (dbwrap_transaction_start(orig_db
) != 0) {
240 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
246 if (dbwrap_transaction_start(tmp_db
) != 0) {
247 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
248 dbwrap_transaction_cancel(orig_db
);
258 status
= dbwrap_traverse(orig_db
, backup_copy_fn
, (void *)&bs
, NULL
);
259 if (!NT_STATUS_IS_OK(status
)) {
260 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
265 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
269 if (dbwrap_transaction_commit(orig_db
) != 0) {
270 smb_panic("tdbsam_convert_backup: orig commit failed\n");
272 if (dbwrap_transaction_commit(tmp_db
) != 0) {
273 smb_panic("tdbsam_convert_backup: orig commit failed\n");
276 /* be sure to close the DBs _before_ renaming the file */
278 TALLOC_FREE(orig_db
);
281 /* This is safe from other users as we know we're
282 * under a mutex here. */
284 if (rename(tmp_fname
, dbname
) == -1) {
285 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
289 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
294 /* re-open the converted TDB */
296 orig_db
= db_open(NULL
, dbname
, 0,
297 TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600,
298 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
299 if (orig_db
== NULL
) {
300 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
301 "converted passdb TDB [%s]\n", dbname
));
305 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
308 /* Replace the global db pointer. */
314 if (dbwrap_transaction_cancel(orig_db
) != 0) {
315 smb_panic("tdbsam_convert: transaction_cancel failed");
318 if (dbwrap_transaction_cancel(tmp_db
) != 0) {
319 smb_panic("tdbsam_convert: transaction_cancel failed");
328 static bool tdbsam_upgrade_next_rid(struct db_context
*db
)
336 status
= dbwrap_fetch_uint32_bystring(db
, NEXT_RID_STRING
, &rid
);
337 if (NT_STATUS_IS_OK(status
)) {
341 db_path
= state_path(talloc_tos(), "winbindd_idmap.tdb");
342 if (db_path
== NULL
) {
346 tdb
= tdb_open_log(db_path
, 0,
347 TDB_DEFAULT
, O_RDONLY
, 0644);
348 TALLOC_FREE(db_path
);
350 ok
= tdb_fetch_uint32(tdb
, "RID_COUNTER", &rid
);
359 status
= dbwrap_store_uint32_bystring(db
, NEXT_RID_STRING
, rid
);
360 if (!NT_STATUS_IS_OK(status
)) {
367 static bool tdbsam_convert(struct db_context
**pp_db
, const char *name
, int32_t from
)
369 struct tdbsam_convert_state state
;
370 struct db_context
*db
= NULL
;
373 /* We only need the update backup for local db's. */
374 if (db_is_local(name
) && !tdbsam_convert_backup(name
, pp_db
)) {
375 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name
));
381 state
.success
= true;
383 if (dbwrap_transaction_start(db
) != 0) {
384 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
388 if (!tdbsam_upgrade_next_rid(db
)) {
389 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
393 status
= dbwrap_traverse(db
, tdbsam_convert_one
, &state
, NULL
);
394 if (!NT_STATUS_IS_OK(status
)) {
395 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
399 if (!state
.success
) {
400 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
404 status
= dbwrap_store_int32_bystring(db
, TDBSAM_VERSION_STRING
,
406 if (!NT_STATUS_IS_OK(status
)) {
407 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version: "
408 "%s\n", nt_errstr(status
)));
412 status
= dbwrap_store_int32_bystring(db
, TDBSAM_MINOR_VERSION_STRING
,
413 TDBSAM_MINOR_VERSION
);
414 if (!NT_STATUS_IS_OK(status
)) {
415 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor "
416 "version: %s\n", nt_errstr(status
)));
420 if (dbwrap_transaction_commit(db
) != 0) {
421 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
428 if (dbwrap_transaction_cancel(db
) != 0) {
429 smb_panic("tdbsam_convert: transaction_cancel failed");
435 /*********************************************************************
436 Open the tdbsam file based on the absolute path specified.
437 Uses a reference count to allow multiple open calls.
438 *********************************************************************/
440 static bool tdbsam_open( const char *name
)
443 int32_t minor_version
;
446 /* check if we are already open */
452 /* Try to open tdb passwd. Create a new one if necessary */
454 db_sam
= db_open(NULL
, name
, 0, TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600,
455 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
456 if (db_sam
== NULL
) {
457 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
462 /* Check the version */
463 status
= dbwrap_fetch_int32_bystring(db_sam
, TDBSAM_VERSION_STRING
,
465 if (!NT_STATUS_IS_OK(status
)) {
466 version
= 0; /* Version not found, assume version 0 */
469 /* Get the minor version */
470 status
= dbwrap_fetch_int32_bystring(
471 db_sam
, TDBSAM_MINOR_VERSION_STRING
, &minor_version
);
472 if (!NT_STATUS_IS_OK(status
)) {
473 minor_version
= 0; /* Minor version not found, assume 0 */
476 /* Compare the version */
477 if (version
> TDBSAM_VERSION
) {
478 /* Version more recent than the latest known */
479 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
484 if ( version
< TDBSAM_VERSION
||
485 (version
== TDBSAM_VERSION
&&
486 minor_version
< TDBSAM_MINOR_VERSION
) ) {
488 * Ok - we think we're going to have to convert.
489 * Due to the backup process we now must do to
490 * upgrade we have to get a mutex and re-check
491 * the version. Someone else may have upgraded
492 * whilst we were checking.
495 struct named_mutex
*mtx
= grab_named_mutex(NULL
,
496 "tdbsam_upgrade_mutex",
500 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
505 /* Re-check the version */
506 status
= dbwrap_fetch_int32_bystring(
507 db_sam
, TDBSAM_VERSION_STRING
, &version
);
508 if (!NT_STATUS_IS_OK(status
)) {
509 version
= 0; /* Version not found, assume version 0 */
512 /* Re-check the minor version */
513 status
= dbwrap_fetch_int32_bystring(
514 db_sam
, TDBSAM_MINOR_VERSION_STRING
, &minor_version
);
515 if (!NT_STATUS_IS_OK(status
)) {
516 minor_version
= 0; /* Minor version not found, assume 0 */
519 /* Compare the version */
520 if (version
> TDBSAM_VERSION
) {
521 /* Version more recent than the latest known */
522 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
528 if ( version
< TDBSAM_VERSION
||
529 (version
== TDBSAM_VERSION
&&
530 minor_version
< TDBSAM_MINOR_VERSION
) ) {
532 * Note that minor versions we read that are greater
533 * than the current minor version we have hard coded
534 * are assumed to be compatible if they have the same
535 * major version. That allows previous versions of the
536 * passdb code that don't know about minor versions to
537 * still use this database. JRA.
540 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
545 TDBSAM_MINOR_VERSION
));
547 if ( !tdbsam_convert(&db_sam
, name
, version
) ) {
548 DEBUG(0, ("tdbsam_open: Error when trying to convert "
549 "tdbsam [%s]\n",name
));
555 DEBUG(3, ("TDBSAM converted successfully.\n"));
560 DEBUG(4,("tdbsam_open: successfully opened %s\n", name
));
565 /******************************************************************
566 Lookup a name in the SAM TDB
567 ******************************************************************/
569 static NTSTATUS
tdbsam_getsampwnam (struct pdb_methods
*my_methods
,
570 struct samu
*user
, const char *sname
)
578 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
579 return NT_STATUS_NO_MEMORY
;
582 /* Data is stored in all lower-case */
583 fstrcpy(name
, sname
);
584 if (!strlower_m(name
)) {
585 return NT_STATUS_INVALID_PARAMETER
;
589 fstr_sprintf(keystr
, "%s%s", USERPREFIX
, name
);
591 /* open the database */
593 if ( !tdbsam_open( tdbsam_filename
) ) {
594 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
595 return NT_STATUS_ACCESS_DENIED
;
600 status
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
, &data
);
601 if (!NT_STATUS_IS_OK(status
)) {
602 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
603 DEBUGADD(5, (" Key: %s\n", keystr
));
604 return NT_STATUS_NO_SUCH_USER
;
607 if (data
.dsize
== 0) {
608 DEBUG(5, ("%s: Got 0-sized record for key %s\n", __func__
,
610 return NT_STATUS_NO_SUCH_USER
;
613 /* unpack the buffer */
615 if (!init_samu_from_buffer(user
, SAMU_BUFFER_LATEST
, data
.dptr
, data
.dsize
)) {
616 DBG_ERR("Bad struct samu entry returned from TDB!\n");
617 TALLOC_FREE(data
.dptr
);
618 return NT_STATUS_NO_MEMORY
;
623 TALLOC_FREE(data
.dptr
);
628 /***************************************************************************
630 **************************************************************************/
632 static NTSTATUS
tdbsam_getsampwrid (struct pdb_methods
*my_methods
,
633 struct samu
*user
, uint32_t rid
)
635 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
641 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
647 fstr_sprintf(keystr
, "%s%.8x", RIDPREFIX
, rid
);
649 /* open the database */
651 if ( !tdbsam_open( tdbsam_filename
) ) {
652 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename
));
653 return NT_STATUS_ACCESS_DENIED
;
658 nt_status
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
, &data
);
659 if (!NT_STATUS_IS_OK(nt_status
)) {
660 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid
, keystr
));
664 fstrcpy(name
, (const char *)data
.dptr
);
665 TALLOC_FREE(data
.dptr
);
667 return tdbsam_getsampwnam (my_methods
, user
, name
);
670 static NTSTATUS
tdbsam_getsampwsid(struct pdb_methods
*my_methods
,
671 struct samu
* user
, const struct dom_sid
*sid
)
675 if ( !sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
) )
676 return NT_STATUS_UNSUCCESSFUL
;
678 return tdbsam_getsampwrid(my_methods
, user
, rid
);
681 static bool tdb_delete_samacct_only( struct samu
*sam_pass
)
687 fstrcpy(name
, pdb_get_username(sam_pass
));
688 if (!strlower_m(name
)) {
692 /* set the search key */
694 fstr_sprintf(keystr
, "%s%s", USERPREFIX
, name
);
696 /* it's outaa here! 8^) */
697 if ( !tdbsam_open( tdbsam_filename
) ) {
698 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
703 status
= dbwrap_delete_bystring(db_sam
, keystr
);
704 if (!NT_STATUS_IS_OK(status
)) {
705 DEBUG(5, ("Error deleting entry from tdb passwd "
706 "database: %s!\n", nt_errstr(status
)));
713 /***************************************************************************
714 Delete a struct samu records for the username and RID key
715 ****************************************************************************/
717 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
718 struct samu
*sam_pass
)
725 /* open the database */
727 if ( !tdbsam_open( tdbsam_filename
) ) {
728 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
730 return NT_STATUS_ACCESS_DENIED
;
733 fstrcpy(name
, pdb_get_username(sam_pass
));
734 if (!strlower_m(name
)) {
735 return NT_STATUS_INVALID_PARAMETER
;
738 /* set the search key */
740 fstr_sprintf(keystr
, "%s%s", USERPREFIX
, name
);
742 rid
= pdb_get_user_rid(sam_pass
);
744 /* it's outaa here! 8^) */
746 if (dbwrap_transaction_start(db_sam
) != 0) {
747 DEBUG(0, ("Could not start transaction\n"));
748 return NT_STATUS_UNSUCCESSFUL
;
751 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
752 if (!NT_STATUS_IS_OK(nt_status
)) {
753 DEBUG(5, ("Error deleting entry from tdb passwd "
754 "database: %s!\n", nt_errstr(nt_status
)));
758 /* set the search key */
760 fstr_sprintf(keystr
, "%s%.8x", RIDPREFIX
, rid
);
762 /* it's outaa here! 8^) */
764 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
765 if (!NT_STATUS_IS_OK(nt_status
)) {
766 DEBUG(5, ("Error deleting entry from tdb rid "
767 "database: %s!\n", nt_errstr(nt_status
)));
771 if (dbwrap_transaction_commit(db_sam
) != 0) {
772 DEBUG(0, ("Could not commit transaction\n"));
773 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
779 if (dbwrap_transaction_cancel(db_sam
) != 0) {
780 smb_panic("transaction_cancel failed");
787 /***************************************************************************
788 Update the TDB SAM account record only
789 Assumes that the tdbsam is already open
790 ****************************************************************************/
791 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
800 /* copy the struct samu struct into a BYTE buffer for storage */
802 if ( (data
.dsize
=init_buffer_from_samu(&buf
, newpwd
, False
)) == -1 ) {
803 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
808 fstrcpy(name
, pdb_get_username(newpwd
));
809 if (!strlower_m(name
)) {
813 DEBUG(5, ("Storing %saccount %s with RID %d\n",
814 flag
== TDB_INSERT
? "(new) " : "", name
,
815 pdb_get_user_rid(newpwd
)));
817 /* setup the USER index key */
818 fstr_sprintf(keystr
, "%s%s", USERPREFIX
, name
);
820 /* add the account */
822 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
823 if (!NT_STATUS_IS_OK(status
)) {
824 DEBUG(0, ("Unable to modify passwd TDB: %s!\n",
837 /***************************************************************************
838 Update the TDB SAM RID record only
839 Assumes that the tdbsam is already open
840 ****************************************************************************/
841 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
848 fstrcpy(name
, pdb_get_username(newpwd
));
849 if (!strlower_m(name
)) {
854 data
= string_term_tdb_data(name
);
856 /* setup the RID index key */
857 fstr_sprintf(keystr
, "%s%.8x", RIDPREFIX
, pdb_get_user_rid(newpwd
));
859 /* add the reference */
860 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
861 if (!NT_STATUS_IS_OK(status
)) {
862 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
871 /***************************************************************************
873 ****************************************************************************/
875 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
881 if (!(newrid
= pdb_get_user_rid(newpwd
))) {
882 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
883 pdb_get_username(newpwd
)));
889 /* open the database */
891 if ( !tdbsam_open( tdbsam_filename
) ) {
892 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
896 if (dbwrap_transaction_start(db_sam
) != 0) {
897 DEBUG(0, ("Could not start transaction\n"));
901 /* If we are updating, we may be changing this users RID. Retrieve the old RID
904 if (flag
== TDB_MODIFY
) {
905 struct samu
*account
= samu_new(talloc_tos());
906 if (account
== NULL
) {
907 DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
910 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods
, account
, pdb_get_username(newpwd
)))) {
911 DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
912 pdb_get_username(newpwd
)));
913 TALLOC_FREE(account
);
916 if (!(oldrid
= pdb_get_user_rid(account
))) {
917 DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
918 TALLOC_FREE(account
);
921 TALLOC_FREE(account
);
924 /* Update the new samu entry. */
925 if (!tdb_update_samacct_only(newpwd
, flag
)) {
929 /* Now take care of the case where the RID changed. We need
930 * to delete the old RID key and add the new. */
932 if (flag
== TDB_MODIFY
&& newrid
!= oldrid
) {
935 /* Delete old RID key */
936 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid
));
937 fstr_sprintf(keystr
, "%s%.8x", RIDPREFIX
, oldrid
);
938 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam
, keystr
))) {
939 DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr
));
942 /* Insert new RID key */
943 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid
));
944 if (!tdb_update_ridrec_only(newpwd
, TDB_INSERT
)) {
948 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
949 flag
== TDB_MODIFY
? "Updating" : "Inserting", newrid
));
950 if (!tdb_update_ridrec_only(newpwd
, flag
)) {
955 if (dbwrap_transaction_commit(db_sam
) != 0) {
956 DEBUG(0, ("Could not commit transaction\n"));
963 if (dbwrap_transaction_cancel(db_sam
) != 0) {
964 smb_panic("transaction_cancel failed");
969 /***************************************************************************
970 Modifies an existing struct samu
971 ****************************************************************************/
973 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
975 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
976 return NT_STATUS_UNSUCCESSFUL
;
981 /***************************************************************************
982 Adds an existing struct samu
983 ****************************************************************************/
985 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
987 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
988 return NT_STATUS_UNSUCCESSFUL
;
993 /***************************************************************************
994 Renames a struct samu
995 - check for the posix user/rename user script
996 - Add and lock the new user record
997 - rename the posix user
998 - rewrite the rid->username record
999 - delete the old user
1000 - unlock the new user record
1001 ***************************************************************************/
1002 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
1003 struct samu
*old_acct
,
1004 const char *newname
)
1006 const struct loadparm_substitution
*lp_sub
=
1007 loadparm_s3_global_substitution();
1008 struct samu
*new_acct
= NULL
;
1009 char *rename_script
= NULL
;
1011 fstring oldname_lower
;
1012 fstring newname_lower
;
1014 /* can't do anything without an external script */
1016 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
1017 return NT_STATUS_NO_MEMORY
;
1020 rename_script
= lp_rename_user_script(new_acct
, lp_sub
);
1021 if (!rename_script
) {
1022 TALLOC_FREE(new_acct
);
1023 return NT_STATUS_NO_MEMORY
;
1025 if (!*rename_script
) {
1026 TALLOC_FREE(new_acct
);
1027 return NT_STATUS_ACCESS_DENIED
;
1030 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
1031 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
1033 TALLOC_FREE(new_acct
);
1034 return NT_STATUS_NO_MEMORY
;
1037 /* open the database */
1038 if ( !tdbsam_open( tdbsam_filename
) ) {
1039 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1041 TALLOC_FREE(new_acct
);
1042 return NT_STATUS_ACCESS_DENIED
;
1045 if (dbwrap_transaction_start(db_sam
) != 0) {
1046 DEBUG(0, ("Could not start transaction\n"));
1047 TALLOC_FREE(new_acct
);
1048 return NT_STATUS_ACCESS_DENIED
;
1052 /* add the new account and lock it */
1053 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
1057 /* Rename the posix user. Follow the semantics of _samr_create_user()
1058 so that we lower case the posix name but preserve the case in passdb */
1060 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
1061 if (!strlower_m( oldname_lower
)) {
1065 fstrcpy( newname_lower
, newname
);
1066 if (!strlower_m( newname_lower
)) {
1070 rename_script
= talloc_string_sub2(new_acct
,
1077 if (!rename_script
) {
1080 rename_script
= talloc_string_sub2(new_acct
,
1087 if (!rename_script
) {
1090 rename_ret
= smbrun(rename_script
, NULL
, NULL
);
1092 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
1093 rename_script
, rename_ret
));
1095 if (rename_ret
!= 0) {
1099 smb_nscd_flush_user_cache();
1101 /* rewrite the rid->username record */
1103 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
1107 tdb_delete_samacct_only( old_acct
);
1109 if (dbwrap_transaction_commit(db_sam
) != 0) {
1111 * Ok, we're screwed. We've changed the posix account, but
1112 * could not adapt passdb.tdb. Shall we change the posix
1115 DEBUG(0, ("transaction_commit failed\n"));
1116 TALLOC_FREE(new_acct
);
1117 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1120 TALLOC_FREE(new_acct
);
1121 return NT_STATUS_OK
;
1124 if (dbwrap_transaction_cancel(db_sam
) != 0) {
1125 smb_panic("transaction_cancel failed");
1128 TALLOC_FREE(new_acct
);
1130 return NT_STATUS_ACCESS_DENIED
;
1133 static uint32_t tdbsam_capabilities(struct pdb_methods
*methods
)
1135 return PDB_CAP_STORE_RIDS
;
1138 static bool tdbsam_new_rid(struct pdb_methods
*methods
, uint32_t *prid
)
1143 rid
= BASE_RID
; /* Default if not set */
1145 if (!tdbsam_open(tdbsam_filename
)) {
1146 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1151 status
= dbwrap_trans_change_uint32_atomic_bystring(
1152 db_sam
, NEXT_RID_STRING
, &rid
, 1);
1153 if (!NT_STATUS_IS_OK(status
)) {
1154 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1155 NEXT_RID_STRING
, nt_errstr(status
)));
1164 struct tdbsam_search_state
{
1165 struct pdb_methods
*methods
;
1166 uint32_t acct_flags
;
1174 static int tdbsam_collect_rids(struct db_record
*rec
, void *private_data
)
1176 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1177 private_data
, struct tdbsam_search_state
);
1178 size_t prefixlen
= strlen(RIDPREFIX
);
1183 key
= dbwrap_record_get_key(rec
);
1185 if ((key
.dsize
< prefixlen
)
1186 || (strncmp((char *)key
.dptr
, RIDPREFIX
, prefixlen
))) {
1190 rid
= smb_strtoul((char *)key
.dptr
+prefixlen
,
1199 ADD_TO_LARGE_ARRAY(state
, uint32_t, rid
, &state
->rids
, &state
->num_rids
,
1200 &state
->array_size
);
1205 static void tdbsam_search_end(struct pdb_search
*search
)
1207 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1208 search
->private_data
, struct tdbsam_search_state
);
1212 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
1213 struct samr_displayentry
*entry
)
1215 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1216 search
->private_data
, struct tdbsam_search_state
);
1217 struct samu
*user
= NULL
;
1223 user
= samu_new(talloc_tos());
1225 DEBUG(0, ("samu_new failed\n"));
1229 if (state
->current
== state
->num_rids
) {
1234 rid
= state
->rids
[state
->current
++];
1236 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
1238 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1240 * Someone has deleted that user since we listed the RIDs
1245 if (!NT_STATUS_IS_OK(status
)) {
1246 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1247 nt_errstr(status
)));
1252 if ((state
->acct_flags
!= 0) &&
1253 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
1257 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
1259 entry
->account_name
= talloc_strdup(search
, pdb_get_username(user
));
1260 entry
->fullname
= talloc_strdup(search
, pdb_get_fullname(user
));
1261 entry
->description
= talloc_strdup(search
, pdb_get_acct_desc(user
));
1265 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
1266 || (entry
->description
== NULL
)) {
1267 DEBUG(0, ("talloc_strdup failed\n"));
1274 static bool tdbsam_search_users(struct pdb_methods
*methods
,
1275 struct pdb_search
*search
,
1276 uint32_t acct_flags
)
1278 struct tdbsam_search_state
*state
;
1280 if (!tdbsam_open(tdbsam_filename
)) {
1281 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1286 state
= talloc_zero(search
, struct tdbsam_search_state
);
1287 if (state
== NULL
) {
1288 DEBUG(0, ("talloc failed\n"));
1291 state
->acct_flags
= acct_flags
;
1292 state
->methods
= methods
;
1294 dbwrap_traverse_read(db_sam
, tdbsam_collect_rids
, state
, NULL
);
1296 search
->private_data
= state
;
1297 search
->next_entry
= tdbsam_search_next_entry
;
1298 search
->search_end
= tdbsam_search_end
;
1303 static bool tdbsam_is_responsible_for_builtin(struct pdb_methods
*m
)
1308 /*********************************************************************
1309 Initialize the tdb sam backend. Setup the dispatch table of methods,
1310 open the tdb, etc...
1311 *********************************************************************/
1313 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
1316 char *tdbfile
= NULL
;
1317 const char *pfile
= location
;
1319 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
1323 (*pdb_method
)->name
= "tdbsam";
1325 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
1326 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
1327 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
1328 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
1329 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
1330 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
1331 (*pdb_method
)->search_users
= tdbsam_search_users
;
1333 (*pdb_method
)->capabilities
= tdbsam_capabilities
;
1334 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
1336 (*pdb_method
)->is_responsible_for_builtin
=
1337 tdbsam_is_responsible_for_builtin
;
1338 map_builtin
= lp_parm_bool(-1, "tdbsam", "map builtin", true);
1340 /* save the path for later */
1343 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
1344 PASSDB_FILE_NAME
) < 0) {
1345 return NT_STATUS_NO_MEMORY
;
1349 tdbsam_filename
= SMB_STRDUP(pfile
);
1350 if (!tdbsam_filename
) {
1351 return NT_STATUS_NO_MEMORY
;
1355 /* no private data */
1357 (*pdb_method
)->private_data
= NULL
;
1358 (*pdb_method
)->free_private_data
= NULL
;
1360 return NT_STATUS_OK
;
1363 NTSTATUS
pdb_tdbsam_init(TALLOC_CTX
*ctx
)
1365 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);