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 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_"
49 struct pwent_list *prev, *next;
52 static struct pwent_list *tdbsam_pwent_list;
53 static BOOL pwent_initialized;
55 /* GLOBAL TDB SAM CONTEXT */
57 static TDB_CONTEXT *tdbsam;
58 static int ref_count = 0;
59 static pstring tdbsam_filename;
61 /**********************************************************************
62 Marshall/unmarshall struct samu structs.
63 *********************************************************************/
65 #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
66 #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
68 /*********************************************************************
69 *********************************************************************/
71 static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
74 /* times are stored as 32bit integer
75 take care on system with 64bit wide time_t
82 pass_must_change_time;
83 char *username = NULL;
85 char *nt_username = NULL;
86 char *dir_drive = NULL;
87 char *unknown_str = NULL;
88 char *munged_dial = NULL;
89 char *fullname = NULL;
91 char *logon_script = NULL;
92 char *profile_path = NULL;
93 char *acct_desc = NULL;
94 char *workstations = NULL;
95 uint32 username_len, domain_len, nt_username_len,
96 dir_drive_len, unknown_str_len, munged_dial_len,
97 fullname_len, homedir_len, logon_script_len,
98 profile_path_len, acct_desc_len, workstations_len;
100 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
101 uint16 acct_ctrl, logon_divs;
102 uint16 bad_password_count, logon_count;
104 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
106 uint32 lm_pw_len, nt_pw_len, hourslen;
109 if(sampass == NULL || buf == NULL) {
110 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
114 /* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
116 /* unpack the buffer into variables */
117 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
119 &logoff_time, /* d */
120 &kickoff_time, /* d */
121 &pass_last_set_time, /* d */
122 &pass_can_change_time, /* d */
123 &pass_must_change_time, /* d */
124 &username_len, &username, /* B */
125 &domain_len, &domain, /* B */
126 &nt_username_len, &nt_username, /* B */
127 &fullname_len, &fullname, /* B */
128 &homedir_len, &homedir, /* B */
129 &dir_drive_len, &dir_drive, /* B */
130 &logon_script_len, &logon_script, /* B */
131 &profile_path_len, &profile_path, /* B */
132 &acct_desc_len, &acct_desc, /* B */
133 &workstations_len, &workstations, /* B */
134 &unknown_str_len, &unknown_str, /* B */
135 &munged_dial_len, &munged_dial, /* B */
138 &lm_pw_len, &lm_pw_ptr, /* B */
139 &nt_pw_len, &nt_pw_ptr, /* B */
141 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
144 &hourslen, &hours, /* B */
145 &bad_password_count, /* w */
146 &logon_count, /* w */
149 if (len == (uint32) -1) {
154 pdb_set_logon_time(sampass, logon_time, PDB_SET);
155 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
156 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
157 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
158 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
159 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
161 pdb_set_username(sampass, username, PDB_SET);
162 pdb_set_domain(sampass, domain, PDB_SET);
163 pdb_set_nt_username(sampass, nt_username, PDB_SET);
164 pdb_set_fullname(sampass, fullname, PDB_SET);
167 pdb_set_homedir(sampass, homedir, PDB_SET);
170 pdb_set_homedir(sampass,
171 talloc_sub_basic(sampass, username, lp_logon_home()),
176 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
178 pdb_set_dir_drive(sampass,
179 talloc_sub_basic(sampass, username, lp_logon_drive()),
184 pdb_set_logon_script(sampass, logon_script, PDB_SET);
186 pdb_set_logon_script(sampass,
187 talloc_sub_basic(sampass, username, lp_logon_script()),
192 pdb_set_profile_path(sampass, profile_path, PDB_SET);
194 pdb_set_profile_path(sampass,
195 talloc_sub_basic(sampass, username, lp_logon_path()),
199 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
200 pdb_set_workstations(sampass, workstations, PDB_SET);
201 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
203 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
204 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
210 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
211 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
217 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
218 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
219 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
220 pdb_set_hours_len(sampass, hours_len, PDB_SET);
221 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
222 pdb_set_logon_count(sampass, logon_count, PDB_SET);
223 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
224 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
225 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
226 pdb_set_hours(sampass, hours, PDB_SET);
232 SAFE_FREE(nt_username);
235 SAFE_FREE(dir_drive);
236 SAFE_FREE(logon_script);
237 SAFE_FREE(profile_path);
238 SAFE_FREE(acct_desc);
239 SAFE_FREE(workstations);
240 SAFE_FREE(munged_dial);
241 SAFE_FREE(unknown_str);
242 SAFE_FREE(lm_pw_ptr);
243 SAFE_FREE(nt_pw_ptr);
249 /*********************************************************************
250 *********************************************************************/
252 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
255 /* times are stored as 32bit integer
256 take care on system with 64bit wide time_t
263 pass_can_change_time,
264 pass_must_change_time;
265 char *username = NULL;
267 char *nt_username = NULL;
268 char *dir_drive = NULL;
269 char *unknown_str = NULL;
270 char *munged_dial = NULL;
271 char *fullname = NULL;
272 char *homedir = NULL;
273 char *logon_script = NULL;
274 char *profile_path = NULL;
275 char *acct_desc = NULL;
276 char *workstations = NULL;
277 uint32 username_len, domain_len, nt_username_len,
278 dir_drive_len, unknown_str_len, munged_dial_len,
279 fullname_len, homedir_len, logon_script_len,
280 profile_path_len, acct_desc_len, workstations_len;
282 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
283 uint16 acct_ctrl, logon_divs;
284 uint16 bad_password_count, logon_count;
286 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
288 uint32 lm_pw_len, nt_pw_len, hourslen;
291 if(sampass == NULL || buf == NULL) {
292 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
296 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
298 /* unpack the buffer into variables */
299 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
301 &logoff_time, /* d */
302 &kickoff_time, /* d */
303 /* Change from V0 is addition of bad_password_time field. */
304 &bad_password_time, /* d */
305 &pass_last_set_time, /* d */
306 &pass_can_change_time, /* d */
307 &pass_must_change_time, /* d */
308 &username_len, &username, /* B */
309 &domain_len, &domain, /* B */
310 &nt_username_len, &nt_username, /* B */
311 &fullname_len, &fullname, /* B */
312 &homedir_len, &homedir, /* B */
313 &dir_drive_len, &dir_drive, /* B */
314 &logon_script_len, &logon_script, /* B */
315 &profile_path_len, &profile_path, /* B */
316 &acct_desc_len, &acct_desc, /* B */
317 &workstations_len, &workstations, /* B */
318 &unknown_str_len, &unknown_str, /* B */
319 &munged_dial_len, &munged_dial, /* B */
322 &lm_pw_len, &lm_pw_ptr, /* B */
323 &nt_pw_len, &nt_pw_ptr, /* B */
328 &hourslen, &hours, /* B */
329 &bad_password_count, /* w */
330 &logon_count, /* w */
333 if (len == (uint32) -1) {
338 pdb_set_logon_time(sampass, logon_time, PDB_SET);
339 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
340 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
342 /* Change from V0 is addition of bad_password_time field. */
343 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
344 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
345 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
346 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
348 pdb_set_username(sampass, username, PDB_SET);
349 pdb_set_domain(sampass, domain, PDB_SET);
350 pdb_set_nt_username(sampass, nt_username, PDB_SET);
351 pdb_set_fullname(sampass, fullname, PDB_SET);
354 pdb_set_homedir(sampass, homedir, PDB_SET);
357 pdb_set_homedir(sampass,
358 talloc_sub_basic(sampass, username, lp_logon_home()),
363 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
365 pdb_set_dir_drive(sampass,
366 talloc_sub_basic(sampass, username, lp_logon_drive()),
371 pdb_set_logon_script(sampass, logon_script, PDB_SET);
373 pdb_set_logon_script(sampass,
374 talloc_sub_basic(sampass, username, lp_logon_script()),
379 pdb_set_profile_path(sampass, profile_path, PDB_SET);
381 pdb_set_profile_path(sampass,
382 talloc_sub_basic(sampass, username, lp_logon_path()),
386 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
387 pdb_set_workstations(sampass, workstations, PDB_SET);
388 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
390 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
391 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
397 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
398 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
404 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
406 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
407 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
408 pdb_set_hours_len(sampass, hours_len, PDB_SET);
409 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
410 pdb_set_logon_count(sampass, logon_count, PDB_SET);
411 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
412 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
413 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
414 pdb_set_hours(sampass, hours, PDB_SET);
420 SAFE_FREE(nt_username);
423 SAFE_FREE(dir_drive);
424 SAFE_FREE(logon_script);
425 SAFE_FREE(profile_path);
426 SAFE_FREE(acct_desc);
427 SAFE_FREE(workstations);
428 SAFE_FREE(munged_dial);
429 SAFE_FREE(unknown_str);
430 SAFE_FREE(lm_pw_ptr);
431 SAFE_FREE(nt_pw_ptr);
437 /**********************************************************************
438 Intialize a struct samu struct from a BYTE buffer of size len
439 *********************************************************************/
441 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
443 return init_sam_from_buffer_v2(sampass, buf, buflen);
446 /**********************************************************************
447 Intialize a BYTE buffer from a struct samu struct
448 *********************************************************************/
450 static uint32 init_buffer_from_sam (uint8 **buf, const struct samu *sampass, BOOL size_only)
452 return init_buffer_from_sam_v2(buf, sampass, size_only);
455 /**********************************************************************
456 Intialize a BYTE buffer from a struct samu struct
457 *********************************************************************/
459 static BOOL tdbsam_convert(int32 from)
461 const char *vstring = TDBSAM_VERSION_STRING;
462 const char *prefix = USERPREFIX;
463 TDB_DATA data, key, old_key;
467 /* handle a Samba upgrade */
468 tdb_lock_bystring(tdbsam, vstring, 0);
470 /* Enumerate all records and convert them */
471 key = tdb_firstkey(tdbsam);
475 /* skip all non-USER entries (eg. RIDs) */
476 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
478 /* increment to next in line */
479 key = tdb_nextkey(tdbsam, key);
480 SAFE_FREE(old_key.dptr);
484 struct samu *user = NULL;
486 /* read from tdbsam */
487 data = tdb_fetch(tdbsam, key);
489 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
493 /* unpack the buffer from the former format */
494 if ( !(user = samu_new( NULL )) ) {
495 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
496 SAFE_FREE( data.dptr );
499 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
502 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
505 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
508 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
511 /* unknown tdbsam version */
515 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
516 SAFE_FREE(data.dptr);
521 /* We're finished with the old data. */
522 SAFE_FREE(data.dptr);
524 /* pack from the buffer into the new format */
526 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
527 data.dsize = init_buffer_from_sam (&buf, user, False);
530 if ( data.dsize == -1 ) {
531 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
534 data.dptr = (char *)buf;
536 /* Store the buffer inside the TDBSAM */
537 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
538 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
539 SAFE_FREE(data.dptr);
543 SAFE_FREE(data.dptr);
545 /* increment to next in line */
547 key = tdb_nextkey(tdbsam, key);
548 SAFE_FREE(old_key.dptr);
554 /* upgrade finished */
555 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
556 tdb_unlock_bystring(tdbsam, vstring);
561 /*********************************************************************
562 Open the tdbsam file based on the absolute path specified.
563 Uses a reference count to allow multiple open calls.
564 *********************************************************************/
566 static BOOL tdbsam_open( const char *name )
570 /* check if we are already open */
574 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
579 SMB_ASSERT( ref_count == 0 );
581 /* Try to open tdb passwd. Create a new one if necessary */
583 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
584 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
588 /* Check the version */
589 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
592 version = 0; /* Version not found, assume version 0 */
594 /* Compare the version */
595 if (version > TDBSAM_VERSION) {
596 /* Version more recent than the latest known */
597 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
603 if ( version < TDBSAM_VERSION ) {
604 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
605 version, TDBSAM_VERSION));
607 if ( !tdbsam_convert(version) ) {
608 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
613 DEBUG(3, ("TDBSAM converted successfully.\n"));
616 /* set the initial reference count */
620 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
625 /****************************************************************************
626 wrapper atound tdb_close() to handle the reference count
627 ****************************************************************************/
629 void tdbsam_close( void )
633 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
635 SMB_ASSERT(ref_count >= 0 );
637 if ( ref_count == 0 ) {
645 /****************************************************************************
646 creates a list of user keys
647 ****************************************************************************/
649 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
651 const char *prefix = USERPREFIX;
652 int prefixlen = strlen (prefix);
653 struct pwent_list *ptr;
655 if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
656 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
657 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
659 /* just return 0 and let the traversal continue */
664 /* save a copy of the key */
666 ptr->key.dptr = memdup( key.dptr, key.dsize );
667 ptr->key.dsize = key.dsize;
669 DLIST_ADD( tdbsam_pwent_list, ptr );
677 /***************************************************************
678 Open the TDB passwd database for SAM account enumeration.
679 Save a list of user keys for iteration.
680 ****************************************************************/
682 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
684 if ( !tdbsam_open( tdbsam_filename ) ) {
685 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
686 return NT_STATUS_ACCESS_DENIED;
689 tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
690 pwent_initialized = True;
696 /***************************************************************
697 End enumeration of the TDB passwd list.
698 ****************************************************************/
700 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
702 struct pwent_list *ptr, *ptr_next;
704 /* close the tdb only if we have a valid pwent state */
706 if ( pwent_initialized ) {
707 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
711 /* clear out any remaining entries in the list */
713 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
714 ptr_next = ptr->next;
715 DLIST_REMOVE( tdbsam_pwent_list, ptr );
716 SAFE_FREE( ptr->key.dptr);
720 pwent_initialized = False;
723 /*****************************************************************
724 Get one struct samu from the TDB (next in line)
725 *****************************************************************/
727 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
729 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
731 struct pwent_list *pkey;
734 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
738 if ( !tdbsam_pwent_list ) {
739 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
743 /* pull the next entry */
745 pkey = tdbsam_pwent_list;
746 DLIST_REMOVE( tdbsam_pwent_list, pkey );
748 data = tdb_fetch(tdbsam, pkey->key);
750 SAFE_FREE( pkey->key.dptr);
754 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
758 if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
759 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
762 SAFE_FREE( data.dptr );
767 /******************************************************************
768 Lookup a name in the SAM TDB
769 ******************************************************************/
771 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
779 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
780 return NT_STATUS_NO_MEMORY;
783 /* Data is stored in all lower-case */
784 fstrcpy(name, sname);
788 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
790 key.dsize = strlen(keystr) + 1;
792 /* open the database */
794 if ( !tdbsam_open( tdbsam_filename ) ) {
795 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
796 return NT_STATUS_ACCESS_DENIED;
801 data = tdb_fetch(tdbsam, key);
803 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
804 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
805 DEBUGADD(5, (" Key: %s\n", keystr));
806 result = NT_STATUS_NO_SUCH_USER;
810 /* unpack the buffer */
812 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
813 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
814 SAFE_FREE(data.dptr);
815 result = NT_STATUS_NO_MEMORY;
819 result = NT_STATUS_OK;
822 SAFE_FREE(data.dptr);
828 /***************************************************************************
830 **************************************************************************/
832 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
834 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
840 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
846 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
848 key.dsize = strlen (keystr) + 1;
850 /* open the database */
852 if ( !tdbsam_open( tdbsam_filename ) ) {
853 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
854 return NT_STATUS_ACCESS_DENIED;
859 data = tdb_fetch (tdbsam, key);
861 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
862 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
863 nt_status = NT_STATUS_UNSUCCESSFUL;
867 fstrcpy(name, data.dptr);
868 SAFE_FREE(data.dptr);
870 nt_status = tdbsam_getsampwnam (my_methods, user, name);
880 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
884 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
885 return NT_STATUS_UNSUCCESSFUL;
887 return tdbsam_getsampwrid(my_methods, user, rid);
890 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
896 fstrcpy(name, pdb_get_username(sam_pass));
899 /* set the search key */
901 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
903 key.dsize = strlen (keystr) + 1;
905 /* it's outaa here! 8^) */
907 if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
908 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
909 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
916 /***************************************************************************
917 Delete a struct samu records for the username and RID key
918 ****************************************************************************/
920 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
922 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
928 /* make sure we have an open handle to the tdb. Should have happened
929 at module initialization time */
932 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
933 return NT_STATUS_NO_SUCH_USER;
936 fstrcpy(name, pdb_get_username(sam_pass));
939 /* set the search key */
941 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
943 key.dsize = strlen (keystr) + 1;
945 rid = pdb_get_user_rid(sam_pass);
947 /* open the database */
949 if ( !tdbsam_open( tdbsam_filename ) ) {
950 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
951 return NT_STATUS_ACCESS_DENIED;
954 /* it's outaa here! 8^) */
956 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
957 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
958 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
959 nt_status = NT_STATUS_UNSUCCESSFUL;
963 /* set the search key */
965 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
967 key.dsize = strlen (keystr) + 1;
969 /* it's outaa here! 8^) */
971 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
972 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
973 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
974 nt_status = NT_STATUS_UNSUCCESSFUL;
978 nt_status = NT_STATUS_OK;
987 /***************************************************************************
988 Update the TDB SAM account record only
989 Assumes that the tdbsam is already open
990 ****************************************************************************/
991 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
999 /* copy the struct samu struct into a BYTE buffer for storage */
1001 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1002 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1006 data.dptr = (char *)buf;
1008 fstrcpy(name, pdb_get_username(newpwd));
1011 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1012 flag == TDB_INSERT ? "(new) " : "", name,
1013 pdb_get_user_rid(newpwd)));
1015 /* setup the USER index key */
1016 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1018 key.dsize = strlen(keystr) + 1;
1020 /* add the account */
1022 if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
1023 DEBUG(0, ("Unable to modify passwd TDB!"));
1024 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1025 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1038 /***************************************************************************
1039 Update the TDB SAM RID record only
1040 Assumes that the tdbsam is already open
1041 ****************************************************************************/
1042 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1048 fstrcpy(name, pdb_get_username(newpwd));
1051 /* setup RID data */
1052 data.dsize = strlen(name) + 1;
1055 /* setup the RID index key */
1056 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1058 key.dsize = strlen (keystr) + 1;
1060 /* add the reference */
1061 if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
1062 DEBUG(0, ("Unable to modify TDB passwd !"));
1063 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1064 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1072 /***************************************************************************
1074 ****************************************************************************/
1076 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1081 /* invalidate the existing TDB iterator if it is open */
1083 tdbsam_endsampwent( my_methods );
1085 if ( !pdb_get_group_rid(newpwd) ) {
1086 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1087 "without a primary group RID\n", pdb_get_username(newpwd)));
1091 if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
1092 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1096 /* open the database */
1098 if ( !tdbsam_open( tdbsam_filename ) ) {
1099 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1103 if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1114 /***************************************************************************
1115 Modifies an existing struct samu
1116 ****************************************************************************/
1118 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1120 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1121 return NT_STATUS_UNSUCCESSFUL;
1123 return NT_STATUS_OK;
1126 /***************************************************************************
1127 Adds an existing struct samu
1128 ****************************************************************************/
1130 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1132 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1133 return NT_STATUS_UNSUCCESSFUL;
1135 return NT_STATUS_OK;
1138 /***************************************************************************
1139 Renames a struct samu
1140 - check for the posix user/rename user script
1141 - Add and lock the new user record
1142 - rename the posix user
1143 - rewrite the rid->username record
1144 - delete the old user
1145 - unlock the new user record
1146 ***************************************************************************/
1147 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1148 struct samu *old_acct,
1149 const char *newname)
1151 struct samu *new_acct = NULL;
1152 pstring rename_script;
1153 BOOL interim_account = False;
1156 /* make sure we have an open handle to the tdb. Should have happened
1157 at module initialization time */
1160 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
1161 return NT_STATUS_NO_SUCH_USER;
1164 /* can't do anything without an external script */
1166 pstrcpy(rename_script, lp_renameuser_script() );
1167 if ( ! *rename_script )
1168 return NT_STATUS_ACCESS_DENIED;
1170 /* invalidate the existing TDB iterator if it is open */
1172 tdbsam_endsampwent( my_methods );
1174 if ( !pdb_copy_sam_account(old_acct, &new_acct)
1175 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1177 TALLOC_FREE(new_acct );
1178 return NT_STATUS_NO_MEMORY;
1181 /* open the database */
1183 if ( !tdbsam_open( tdbsam_filename ) ) {
1184 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1185 TALLOC_FREE(new_acct );
1186 return NT_STATUS_ACCESS_DENIED;
1189 /* add the new account and lock it */
1191 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) )
1196 interim_account = True;
1198 if ( tdb_lock_bystring(tdbsam, newname, 30) == -1 ) {
1202 /* rename the posix user */
1204 pstring_sub(rename_script, "%unew", newname);
1205 pstring_sub(rename_script, "%uold", pdb_get_username(old_acct));
1206 rename_ret = smbrun(rename_script, NULL);
1208 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1213 /* rewrite the rid->username record */
1215 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) )
1217 interim_account = False;
1218 tdb_unlock_bystring( tdbsam, newname );
1220 tdb_delete_samacct_only( old_acct );
1224 TALLOC_FREE(new_acct );
1225 return NT_STATUS_OK;
1229 if (interim_account) {
1230 tdb_unlock_bystring(tdbsam, newname);
1231 tdb_delete_samacct_only(new_acct);
1237 TALLOC_FREE(new_acct);
1239 return NT_STATUS_ACCESS_DENIED;
1242 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1248 * Historically, winbind was responsible for allocating RIDs, so the next RID
1249 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1250 * but for compatibility reasons we still keep the the next RID counter in
1251 * winbindd_idmap.tdb.
1254 /*****************************************************************************
1255 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1256 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1257 winbind completely and store the RID counter in passdb.tdb.
1259 Dont' fully initialize with the HWM values, if it's new, we're only
1260 interested in the RID counter.
1261 *****************************************************************************/
1263 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1267 if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
1268 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1272 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1274 if (version == -1) {
1275 /* No key found, must be a new db */
1276 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1277 IDMAP_VERSION) != 0) {
1278 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1279 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1282 version = IDMAP_VERSION;
1285 if (version != IDMAP_VERSION) {
1286 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1287 "start winbind once\n", IDMAP_VERSION, version));
1288 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1292 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1296 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1302 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1303 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1306 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1310 if (!init_idmap_tdb(tdb)) {
1311 DEBUG(1, ("Could not init idmap\n"));
1315 rid = BASE_RID; /* Default if not set */
1317 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1318 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1326 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1327 smb_panic("tdb_close(idmap_tdb) failed\n");
1333 /*********************************************************************
1334 Initialize the tdb sam backend. Setup the dispath table of methods,
1335 open the tdb, etc...
1336 *********************************************************************/
1338 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1342 const char *pfile = location;
1344 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1348 (*pdb_method)->name = "tdbsam";
1350 (*pdb_method)->setsampwent = tdbsam_setsampwent;
1351 (*pdb_method)->endsampwent = tdbsam_endsampwent;
1352 (*pdb_method)->getsampwent = tdbsam_getsampwent;
1353 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1354 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1355 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1356 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1357 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1358 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1360 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1361 (*pdb_method)->new_rid = tdbsam_new_rid;
1363 /* save the path for later */
1366 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1369 pstrcpy( tdbsam_filename, pfile );
1371 /* no private data */
1373 (*pdb_method)->private_data = NULL;
1374 (*pdb_method)->free_private_data = NULL;
1376 return NT_STATUS_OK;
1379 NTSTATUS pdb_tdbsam_init(void)
1381 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);