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
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 2 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, write to the Free Software Foundation, Inc., 675
23 * Mass Ave, Cambridge, MA 02139, USA.
28 #if 0 /* when made a module use this */
30 static int tdbsam_debug_level = DBGC_ALL;
32 #define DBGC_CLASS tdbsam_debug_level
37 #define DBGC_CLASS DBGC_PASSDB
41 #define TDBSAM_VERSION 2 /* Most recent TDBSAM version */
42 #define TDBSAM_VERSION_STRING "INFO/version"
43 #define PASSDB_FILE_NAME "passdb.tdb"
44 #define USERPREFIX "USER_"
45 #define RIDPREFIX "RID_"
46 #define PRIVPREFIX "PRIV_"
47 #define tdbsamver_t int32
49 struct tdbsam_privates {
50 TDB_CONTEXT *passwd_tdb;
52 /* retrive-once info */
53 const char *tdbsam_location;
57 struct pwent_list *prev, *next;
60 static struct pwent_list *tdbsam_pwent_list;
64 * Convert old TDBSAM to the latest version.
65 * @param pdb_tdb A pointer to the opened TDBSAM file which must be converted.
66 * This file must be opened with read/write access.
67 * @param from Current version of the TDBSAM file.
68 * @return True if the conversion has been successful, false otherwise.
71 static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
73 const char * vstring = TDBSAM_VERSION_STRING;
74 SAM_ACCOUNT *user = NULL;
75 const char *prefix = USERPREFIX;
76 TDB_DATA data, key, old_key;
80 if (pdb_tdb == NULL) {
81 DEBUG(0,("tdbsam_convert: Bad TDB Context pointer.\n"));
85 /* handle a Samba upgrade */
86 tdb_lock_bystring(pdb_tdb, vstring, 0);
88 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
89 DEBUG(0,("tdbsam_convert: cannot initialized a SAM_ACCOUNT.\n"));
93 /* Enumerate all records and convert them */
94 key = tdb_firstkey(pdb_tdb);
98 /* skip all non-USER entries (eg. RIDs) */
99 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
101 /* increment to next in line */
102 key = tdb_nextkey(pdb_tdb, key);
103 SAFE_FREE(old_key.dptr);
108 /* read from tdbsam */
109 data = tdb_fetch(pdb_tdb, key);
111 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
115 if (!NT_STATUS_IS_OK(pdb_reset_sam(user))) {
116 DEBUG(0,("tdbsam_convert: cannot reset SAM_ACCOUNT.\n"));
117 SAFE_FREE(data.dptr);
121 /* unpack the buffer from the former format */
122 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
125 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
128 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
131 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
134 /* unknown tdbsam version */
138 DEBUG(0,("tdbsam_convert: Bad SAM_ACCOUNT entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
139 SAFE_FREE(data.dptr);
143 /* We're finished with the old data. */
144 SAFE_FREE(data.dptr);
146 /* pack from the buffer into the new format */
147 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
148 if ((data.dsize=init_buffer_from_sam (&buf, user, False)) == -1) {
149 DEBUG(0,("tdbsam_convert: cannot pack the SAM_ACCOUNT into the new format\n"));
150 SAFE_FREE(data.dptr);
153 data.dptr = (char *)buf;
155 /* Store the buffer inside the TDBSAM */
156 if (tdb_store(pdb_tdb, key, data, TDB_MODIFY) != TDB_SUCCESS) {
157 DEBUG(0,("tdbsam_convert: cannot store the SAM_ACCOUNT (key:%s) in new format\n",key.dptr));
158 SAFE_FREE(data.dptr);
162 SAFE_FREE(data.dptr);
164 /* increment to next in line */
166 key = tdb_nextkey(pdb_tdb, key);
167 SAFE_FREE(old_key.dptr);
174 /* upgrade finished */
175 tdb_store_int32(pdb_tdb, vstring, TDBSAM_VERSION);
176 tdb_unlock_bystring(pdb_tdb, vstring);
182 * Open the TDB passwd database, check version and convert it if needed.
183 * @param name filename of the tdbsam file.
184 * @param open_flags file access mode.
185 * @return a TDB_CONTEXT handle on the tdbsam file.
188 static TDB_CONTEXT * tdbsam_tdbopen (const char *name, int open_flags)
190 TDB_CONTEXT *pdb_tdb;
193 /* Try to open tdb passwd */
194 if (!(pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT,
195 open_flags, 0600))) {
196 DEBUG(0, ("Unable to open/create TDB passwd\n"));
200 /* Check the version */
201 version = (tdbsamver_t) tdb_fetch_int32(pdb_tdb,
202 TDBSAM_VERSION_STRING);
204 version = 0; /* Version not found, assume version 0 */
206 /* Compare the version */
207 if (version > TDBSAM_VERSION) {
208 /* Version more recent than the latest known */
209 DEBUG(0, ("TDBSAM version unknown: %d\n", version));
213 else if (version < TDBSAM_VERSION) {
214 /* Older version, must be converted */
215 DEBUG(1, ("TDBSAM version too old (%d), trying to convert it.\n", version));
217 /* Reopen the pdb file with read-write access if needed */
218 if (!(open_flags & O_RDWR)) {
219 DEBUG(10, ("tdbsam_tdbopen: TDB file opened with read only access, reopen it with read-write access.\n"));
221 pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, (open_flags & 07777770) | O_RDWR, 0600);
225 if (!tdbsam_convert(pdb_tdb, version)){
226 DEBUG(0, ("tdbsam_tdbopen: Error when trying to convert tdbsam: %s\n",name));
230 DEBUG(1, ("TDBSAM converted successfully.\n"));
233 /* Reopen the pdb file as it must be */
234 if (!(open_flags & O_RDWR)) {
236 pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, open_flags, 0600);
243 /*****************************************************************************
244 Utility functions to close the tdb sam database
245 ****************************************************************************/
247 static void tdbsam_tdbclose ( struct tdbsam_privates *state )
252 if ( state->passwd_tdb ) {
253 tdb_close( state->passwd_tdb );
254 state->passwd_tdb = NULL;
261 /****************************************************************************
262 creates a list of user keys
263 ****************************************************************************/
265 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
267 const char *prefix = USERPREFIX;
268 int prefixlen = strlen (prefix);
269 struct pwent_list *ptr;
271 if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
272 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
273 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
275 /* just return 0 and let the traversal continue */
280 /* save a copy of the key */
282 ptr->key.dptr = memdup( key.dptr, key.dsize );
283 ptr->key.dsize = key.dsize;
285 DLIST_ADD( tdbsam_pwent_list, ptr );
293 /***************************************************************
294 Open the TDB passwd database for SAM account enumeration.
295 Save a list of user keys for iteration.
296 ****************************************************************/
298 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
300 uint32 flags = update ? (O_RDWR|O_CREAT) : O_RDONLY;
302 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
304 if ( !(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, flags )) )
305 return NT_STATUS_UNSUCCESSFUL;
307 tdb_traverse( tdb_state->passwd_tdb, tdbsam_traverse_setpwent, NULL );
313 /***************************************************************
314 End enumeration of the TDB passwd list.
315 ****************************************************************/
317 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
319 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
320 struct pwent_list *ptr, *ptr_next;
322 tdbsam_tdbclose( tdb_state );
324 /* clear out any remaining entries in the list */
326 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
327 ptr_next = ptr->next;
328 DLIST_REMOVE( tdbsam_pwent_list, ptr );
329 SAFE_FREE( ptr->key.dptr);
333 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
336 /*****************************************************************
337 Get one SAM_ACCOUNT from the TDB (next in line)
338 *****************************************************************/
340 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
342 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
343 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
345 struct pwent_list *pkey;
348 DEBUG(0,("tdbsam_getsampwent: SAM_ACCOUNT is NULL.\n"));
352 if ( !tdbsam_pwent_list ) {
353 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
354 tdbsam_tdbclose( tdb_state );
358 if ( !tdb_state->passwd_tdb ) {
359 if ( !(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY)) )
363 /* pull the next entry */
365 pkey = tdbsam_pwent_list;
366 DLIST_REMOVE( tdbsam_pwent_list, pkey );
368 data = tdb_fetch(tdb_state->passwd_tdb, pkey->key);
370 SAFE_FREE( pkey->key.dptr);
374 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
378 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
379 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
382 SAFE_FREE( data.dptr );
388 /******************************************************************
389 Lookup a name in the SAM TDB
390 ******************************************************************/
392 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
394 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
395 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
396 TDB_CONTEXT *pwd_tdb;
402 DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
406 /* Data is stored in all lower-case */
407 fstrcpy(name, sname);
411 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
413 key.dsize = strlen(keystr) + 1;
415 /* open the accounts TDB */
416 if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
418 if (errno == ENOENT) {
420 * TDB file doesn't exist, so try to create new one. This is useful to avoid
421 * confusing error msg when adding user account first time
423 if ((pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_CREAT|O_RDWR )) != NULL) {
424 DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) did not exist. File successfully created.\n",
425 tdb_state->tdbsam_location));
428 DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) does not exist. Couldn't create new one. Error was: %s\n",
429 tdb_state->tdbsam_location, strerror(errno)));
432 /* requested user isn't there anyway */
433 nt_status = NT_STATUS_NO_SUCH_USER;
436 DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
441 data = tdb_fetch(pwd_tdb, key);
443 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
444 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
445 DEBUGADD(5, (" Key: %s\n", keystr));
450 /* unpack the buffer */
451 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
452 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
453 SAFE_FREE(data.dptr);
457 SAFE_FREE(data.dptr);
459 /* no further use for database, close it now */
465 /***************************************************************************
467 **************************************************************************/
469 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
471 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
472 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
473 TDB_CONTEXT *pwd_tdb;
479 DEBUG(0,("pdb_getsampwrid: SAM_ACCOUNT is NULL.\n"));
484 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
486 key.dsize = strlen (keystr) + 1;
488 /* open the accounts TDB */
489 if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
490 DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
495 data = tdb_fetch (pwd_tdb, key);
497 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
498 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
504 fstrcpy(name, data.dptr);
505 SAFE_FREE(data.dptr);
509 return tdbsam_getsampwnam (my_methods, user, name);
512 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
515 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
516 return NT_STATUS_UNSUCCESSFUL;
517 return tdbsam_getsampwrid(my_methods, user, rid);
520 static BOOL tdb_delete_samacct_only(TDB_CONTEXT *pwd_tdb,
521 struct pdb_methods *my_methods,
522 SAM_ACCOUNT *sam_pass)
528 fstrcpy(name, pdb_get_username(sam_pass));
531 /* set the search key */
532 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
534 key.dsize = strlen (keystr) + 1;
536 /* it's outaa here! 8^) */
537 if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
538 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
539 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
546 /***************************************************************************
548 ****************************************************************************/
550 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_pass)
552 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
553 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
554 TDB_CONTEXT *pwd_tdb;
560 fstrcpy(name, pdb_get_username(sam_pass));
564 if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR))) {
565 DEBUG(0, ("Unable to open TDB passwd!"));
569 /* set the search key */
570 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
572 key.dsize = strlen (keystr) + 1;
574 rid = pdb_get_user_rid(sam_pass);
576 /* it's outaa here! 8^) */
577 if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
578 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
579 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
584 /* delete also the RID key */
586 /* set the search key */
587 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
589 key.dsize = strlen (keystr) + 1;
591 /* it's outaa here! 8^) */
592 if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
593 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
594 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
605 /***************************************************************************
606 Update the TDB SAM account record only
607 ****************************************************************************/
608 static BOOL tdb_update_samacct_only(TDB_CONTEXT *pwd_tdb,
609 struct pdb_methods *my_methods,
610 SAM_ACCOUNT* newpwd, int flag)
618 /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
619 if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) {
620 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
624 data.dptr = (char *)buf;
626 fstrcpy(name, pdb_get_username(newpwd));
629 DEBUG(5, ("Storing %saccount %s with RID %d\n",
630 flag == TDB_INSERT ? "(new) " : "", name,
631 pdb_get_user_rid(newpwd)));
633 /* setup the USER index key */
634 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
636 key.dsize = strlen(keystr) + 1;
638 /* add the account */
639 if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
640 DEBUG(0, ("Unable to modify passwd TDB!"));
641 DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
642 DEBUGADD(0, (" occured while storing the main record (%s)\n",
655 /***************************************************************************
656 Update the TDB SAM RID record only
657 ****************************************************************************/
658 static BOOL tdb_update_ridrec_only(TDB_CONTEXT *pwd_tdb,
659 struct pdb_methods *my_methods,
660 SAM_ACCOUNT* newpwd, int flag)
666 fstrcpy(name, pdb_get_username(newpwd));
670 data.dsize = strlen(name) + 1;
673 /* setup the RID index key */
674 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
675 pdb_get_user_rid(newpwd));
677 key.dsize = strlen (keystr) + 1;
679 /* add the reference */
680 if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
681 DEBUG(0, ("Unable to modify TDB passwd !"));
682 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
683 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
691 /***************************************************************************
693 ****************************************************************************/
695 static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
697 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
698 TDB_CONTEXT *pwd_tdb = NULL;
702 /* invalidate the existing TDB iterator if it is open */
704 if (tdb_state->passwd_tdb) {
705 tdb_close(tdb_state->passwd_tdb);
706 tdb_state->passwd_tdb = NULL;
709 /* open the account TDB passwd*/
711 pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
714 DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
715 tdb_state->tdbsam_location));
719 if (!pdb_get_group_rid(newpwd)) {
720 DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
721 pdb_get_username(newpwd)));
726 if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
727 DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd)));
732 if (!tdb_update_samacct_only(pwd_tdb, my_methods, newpwd, flag) ||
733 !tdb_update_ridrec_only(pwd_tdb, my_methods, newpwd, flag)) {
745 /***************************************************************************
746 Modifies an existing SAM_ACCOUNT
747 ****************************************************************************/
749 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
751 if (tdb_update_sam(my_methods, newpwd, TDB_MODIFY))
754 return NT_STATUS_UNSUCCESSFUL;
757 /***************************************************************************
758 Adds an existing SAM_ACCOUNT
759 ****************************************************************************/
761 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
763 if (tdb_update_sam(my_methods, newpwd, TDB_INSERT))
766 return NT_STATUS_UNSUCCESSFUL;
769 /***************************************************************************
770 Renames a SAM_ACCOUNT
771 - check for the posix user/rename user script
772 - Add and lock the new user record
773 - rename the posix user
774 - rewrite the rid->username record
775 - delete the old user
776 - unlock the new user record
777 ***************************************************************************/
778 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
779 SAM_ACCOUNT *old_acct,
782 struct tdbsam_privates *tdb_state =
783 (struct tdbsam_privates *)my_methods->private_data;
784 SAM_ACCOUNT *new_acct = NULL;
785 pstring rename_script;
786 TDB_CONTEXT *pwd_tdb = NULL;
787 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
788 BOOL interim_account = False;
790 if (!*(lp_renameuser_script()))
793 if (!pdb_copy_sam_account(old_acct, &new_acct) ||
794 !pdb_set_username(new_acct, newname, PDB_CHANGED))
797 /* invalidate the existing TDB iterator if it is open */
799 if (tdb_state->passwd_tdb) {
800 tdb_close(tdb_state->passwd_tdb);
801 tdb_state->passwd_tdb = NULL;
804 /* open the account TDB passwd */
806 pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
809 DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
810 tdb_state->tdbsam_location));
814 /* add the new account and lock it */
815 if (!tdb_update_samacct_only(pwd_tdb, my_methods, new_acct,
818 interim_account = True;
820 if (tdb_lock_bystring(pwd_tdb, newname, 30) == -1) {
824 /* rename the posix user */
825 pstrcpy(rename_script, lp_renameuser_script());
827 if (*rename_script) {
830 pstring_sub(rename_script, "%unew", newname);
831 pstring_sub(rename_script, "%uold",
832 pdb_get_username(old_acct));
833 rename_ret = smbrun(rename_script, NULL);
835 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
843 /* rewrite the rid->username record */
844 if (!tdb_update_ridrec_only(pwd_tdb, my_methods, new_acct, TDB_MODIFY))
846 interim_account = False;
847 tdb_unlock_bystring(pwd_tdb, newname);
849 tdb_delete_samacct_only(pwd_tdb, my_methods, old_acct);
856 if (interim_account) {
857 tdb_unlock_bystring(pwd_tdb, newname);
858 tdb_delete_samacct_only(pwd_tdb, my_methods, new_acct);
863 pdb_free_sam(&new_acct);
868 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
874 * Historically, winbind was responsible for allocating RIDs, so the next RID
875 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
876 * but for compatibility reasons we still keep the the next RID counter in
877 * winbindd_idmap.tdb.
880 /*****************************************************************************
881 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
882 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
883 winbind completely and store the RID counter in passdb.tdb.
885 Dont' fully initialize with the HWM values, if it's new, we're only
886 interested in the RID counter.
887 *****************************************************************************/
889 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
893 if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
894 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
898 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
901 /* No key found, must be a new db */
902 if (tdb_store_int32(tdb, "IDMAP_VERSION",
903 IDMAP_VERSION) != 0) {
904 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
905 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
908 version = IDMAP_VERSION;
911 if (version != IDMAP_VERSION) {
912 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
913 "start winbind once\n", IDMAP_VERSION, version));
914 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
918 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
922 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
928 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
929 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
932 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
936 if (!init_idmap_tdb(tdb)) {
937 DEBUG(1, ("Could not init idmap\n"));
941 rid = BASE_RID; /* Default if not set */
943 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
944 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
952 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
953 smb_panic("tdb_close(idmap_tdb) failed\n");
959 static void free_private_data(void **vp)
961 struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
962 tdbsam_tdbclose(*tdb_state);
965 /* No need to free any further, as it is talloc()ed */
972 * Init tdbsam backend
974 * @param pdb_context initialised passdb context
975 * @param pdb_method backend methods structure to be filled with function pointers
976 * @param location the backend tdb file location
978 * @return nt_status code
981 static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
984 struct tdbsam_privates *tdb_state;
986 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
990 (*pdb_method)->name = "tdbsam";
992 (*pdb_method)->setsampwent = tdbsam_setsampwent;
993 (*pdb_method)->endsampwent = tdbsam_endsampwent;
994 (*pdb_method)->getsampwent = tdbsam_getsampwent;
995 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
996 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
997 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
998 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
999 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1000 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1002 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1003 (*pdb_method)->new_rid = tdbsam_new_rid;
1005 tdb_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct tdbsam_privates);
1008 DEBUG(0, ("talloc() failed for tdbsam private_data!\n"));
1009 return NT_STATUS_NO_MEMORY;
1013 tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location);
1016 get_private_directory(tdbfile);
1017 pstrcat(tdbfile, "/");
1018 pstrcat(tdbfile, PASSDB_FILE_NAME);
1019 tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
1022 (*pdb_method)->private_data = tdb_state;
1024 (*pdb_method)->free_private_data = free_private_data;
1026 return NT_STATUS_OK;
1029 NTSTATUS pdb_tdbsam_init(void)
1031 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);