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_hours_len(sampass, hours_len, PDB_SET);
220 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
221 pdb_set_logon_count(sampass, logon_count, PDB_SET);
222 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
223 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
224 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
225 pdb_set_hours(sampass, hours, PDB_SET);
231 SAFE_FREE(nt_username);
234 SAFE_FREE(dir_drive);
235 SAFE_FREE(logon_script);
236 SAFE_FREE(profile_path);
237 SAFE_FREE(acct_desc);
238 SAFE_FREE(workstations);
239 SAFE_FREE(munged_dial);
240 SAFE_FREE(unknown_str);
241 SAFE_FREE(lm_pw_ptr);
242 SAFE_FREE(nt_pw_ptr);
248 /*********************************************************************
249 *********************************************************************/
251 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
254 /* times are stored as 32bit integer
255 take care on system with 64bit wide time_t
262 pass_can_change_time,
263 pass_must_change_time;
264 char *username = NULL;
266 char *nt_username = NULL;
267 char *dir_drive = NULL;
268 char *unknown_str = NULL;
269 char *munged_dial = NULL;
270 char *fullname = NULL;
271 char *homedir = NULL;
272 char *logon_script = NULL;
273 char *profile_path = NULL;
274 char *acct_desc = NULL;
275 char *workstations = NULL;
276 uint32 username_len, domain_len, nt_username_len,
277 dir_drive_len, unknown_str_len, munged_dial_len,
278 fullname_len, homedir_len, logon_script_len,
279 profile_path_len, acct_desc_len, workstations_len;
281 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
282 uint16 acct_ctrl, logon_divs;
283 uint16 bad_password_count, logon_count;
285 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
287 uint32 lm_pw_len, nt_pw_len, hourslen;
290 if(sampass == NULL || buf == NULL) {
291 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
295 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
297 /* unpack the buffer into variables */
298 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
300 &logoff_time, /* d */
301 &kickoff_time, /* d */
302 /* Change from V0 is addition of bad_password_time field. */
303 &bad_password_time, /* d */
304 &pass_last_set_time, /* d */
305 &pass_can_change_time, /* d */
306 &pass_must_change_time, /* d */
307 &username_len, &username, /* B */
308 &domain_len, &domain, /* B */
309 &nt_username_len, &nt_username, /* B */
310 &fullname_len, &fullname, /* B */
311 &homedir_len, &homedir, /* B */
312 &dir_drive_len, &dir_drive, /* B */
313 &logon_script_len, &logon_script, /* B */
314 &profile_path_len, &profile_path, /* B */
315 &acct_desc_len, &acct_desc, /* B */
316 &workstations_len, &workstations, /* B */
317 &unknown_str_len, &unknown_str, /* B */
318 &munged_dial_len, &munged_dial, /* B */
321 &lm_pw_len, &lm_pw_ptr, /* B */
322 &nt_pw_len, &nt_pw_ptr, /* B */
327 &hourslen, &hours, /* B */
328 &bad_password_count, /* w */
329 &logon_count, /* w */
332 if (len == (uint32) -1) {
337 pdb_set_logon_time(sampass, logon_time, PDB_SET);
338 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
339 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
341 /* Change from V0 is addition of bad_password_time field. */
342 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
343 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
344 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
345 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
347 pdb_set_username(sampass, username, PDB_SET);
348 pdb_set_domain(sampass, domain, PDB_SET);
349 pdb_set_nt_username(sampass, nt_username, PDB_SET);
350 pdb_set_fullname(sampass, fullname, PDB_SET);
353 pdb_set_homedir(sampass, homedir, PDB_SET);
356 pdb_set_homedir(sampass,
357 talloc_sub_basic(sampass, username, lp_logon_home()),
362 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
364 pdb_set_dir_drive(sampass,
365 talloc_sub_basic(sampass, username, lp_logon_drive()),
370 pdb_set_logon_script(sampass, logon_script, PDB_SET);
372 pdb_set_logon_script(sampass,
373 talloc_sub_basic(sampass, username, lp_logon_script()),
378 pdb_set_profile_path(sampass, profile_path, PDB_SET);
380 pdb_set_profile_path(sampass,
381 talloc_sub_basic(sampass, username, lp_logon_path()),
385 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
386 pdb_set_workstations(sampass, workstations, PDB_SET);
387 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
389 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
390 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
396 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
397 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
403 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
405 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
406 pdb_set_hours_len(sampass, hours_len, PDB_SET);
407 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
408 pdb_set_logon_count(sampass, logon_count, PDB_SET);
409 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
410 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
411 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
412 pdb_set_hours(sampass, hours, PDB_SET);
418 SAFE_FREE(nt_username);
421 SAFE_FREE(dir_drive);
422 SAFE_FREE(logon_script);
423 SAFE_FREE(profile_path);
424 SAFE_FREE(acct_desc);
425 SAFE_FREE(workstations);
426 SAFE_FREE(munged_dial);
427 SAFE_FREE(unknown_str);
428 SAFE_FREE(lm_pw_ptr);
429 SAFE_FREE(nt_pw_ptr);
435 /**********************************************************************
436 Intialize a struct samu struct from a BYTE buffer of size len
437 *********************************************************************/
439 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
441 return init_sam_from_buffer_v2(sampass, buf, buflen);
444 /**********************************************************************
445 Intialize a BYTE buffer from a struct samu struct
446 *********************************************************************/
448 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
450 return init_buffer_from_sam_v2(buf, sampass, size_only);
453 /**********************************************************************
454 Intialize a BYTE buffer from a struct samu struct
455 *********************************************************************/
457 static BOOL tdbsam_convert(int32 from)
459 const char *vstring = TDBSAM_VERSION_STRING;
460 const char *prefix = USERPREFIX;
461 TDB_DATA data, key, old_key;
465 /* handle a Samba upgrade */
466 tdb_lock_bystring(tdbsam, vstring, 0);
468 /* Enumerate all records and convert them */
469 key = tdb_firstkey(tdbsam);
473 /* skip all non-USER entries (eg. RIDs) */
474 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
476 /* increment to next in line */
477 key = tdb_nextkey(tdbsam, key);
478 SAFE_FREE(old_key.dptr);
482 struct samu *user = NULL;
484 /* read from tdbsam */
485 data = tdb_fetch(tdbsam, key);
487 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
491 /* unpack the buffer from the former format */
492 if ( !(user = samu_new( NULL )) ) {
493 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
494 SAFE_FREE( data.dptr );
497 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
500 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
503 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
506 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
509 /* unknown tdbsam version */
513 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
514 SAFE_FREE(data.dptr);
519 /* We're finished with the old data. */
520 SAFE_FREE(data.dptr);
522 /* pack from the buffer into the new format */
524 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
525 data.dsize = init_buffer_from_sam (&buf, user, False);
528 if ( data.dsize == -1 ) {
529 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
532 data.dptr = (char *)buf;
534 /* Store the buffer inside the TDBSAM */
535 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
536 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
537 SAFE_FREE(data.dptr);
541 SAFE_FREE(data.dptr);
543 /* increment to next in line */
545 key = tdb_nextkey(tdbsam, key);
546 SAFE_FREE(old_key.dptr);
552 /* upgrade finished */
553 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
554 tdb_unlock_bystring(tdbsam, vstring);
559 /*********************************************************************
560 Open the tdbsam file based on the absolute path specified.
561 Uses a reference count to allow multiple open calls.
562 *********************************************************************/
564 static BOOL tdbsam_open( const char *name )
568 /* check if we are already open */
572 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
577 SMB_ASSERT( ref_count == 0 );
579 /* Try to open tdb passwd. Create a new one if necessary */
581 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
582 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
586 /* Check the version */
587 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
590 version = 0; /* Version not found, assume version 0 */
592 /* Compare the version */
593 if (version > TDBSAM_VERSION) {
594 /* Version more recent than the latest known */
595 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
601 if ( version < TDBSAM_VERSION ) {
602 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
603 version, TDBSAM_VERSION));
605 if ( !tdbsam_convert(version) ) {
606 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
611 DEBUG(3, ("TDBSAM converted successfully.\n"));
614 /* set the initial reference count */
618 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
623 /****************************************************************************
624 wrapper atound tdb_close() to handle the reference count
625 ****************************************************************************/
627 void tdbsam_close( void )
631 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
633 SMB_ASSERT(ref_count >= 0 );
635 if ( ref_count == 0 ) {
643 /****************************************************************************
644 creates a list of user keys
645 ****************************************************************************/
647 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
649 const char *prefix = USERPREFIX;
650 int prefixlen = strlen (prefix);
651 struct pwent_list *ptr;
653 if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
654 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
655 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
657 /* just return 0 and let the traversal continue */
662 /* save a copy of the key */
664 ptr->key.dptr = memdup( key.dptr, key.dsize );
665 ptr->key.dsize = key.dsize;
667 DLIST_ADD( tdbsam_pwent_list, ptr );
675 /***************************************************************
676 Open the TDB passwd database for SAM account enumeration.
677 Save a list of user keys for iteration.
678 ****************************************************************/
680 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
682 if ( !tdbsam_open( tdbsam_filename ) ) {
683 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
684 return NT_STATUS_ACCESS_DENIED;
687 tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
688 pwent_initialized = True;
694 /***************************************************************
695 End enumeration of the TDB passwd list.
696 ****************************************************************/
698 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
700 struct pwent_list *ptr, *ptr_next;
702 /* close the tdb only if we have a valid pwent state */
704 if ( pwent_initialized ) {
705 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
709 /* clear out any remaining entries in the list */
711 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
712 ptr_next = ptr->next;
713 DLIST_REMOVE( tdbsam_pwent_list, ptr );
714 SAFE_FREE( ptr->key.dptr);
718 pwent_initialized = False;
721 /*****************************************************************
722 Get one struct samu from the TDB (next in line)
723 *****************************************************************/
725 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
727 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
729 struct pwent_list *pkey;
732 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
736 if ( !tdbsam_pwent_list ) {
737 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
741 /* pull the next entry */
743 pkey = tdbsam_pwent_list;
744 DLIST_REMOVE( tdbsam_pwent_list, pkey );
746 data = tdb_fetch(tdbsam, pkey->key);
748 SAFE_FREE( pkey->key.dptr);
752 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
756 if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
757 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
760 SAFE_FREE( data.dptr );
765 /******************************************************************
766 Lookup a name in the SAM TDB
767 ******************************************************************/
769 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
777 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
778 return NT_STATUS_NO_MEMORY;
781 /* Data is stored in all lower-case */
782 fstrcpy(name, sname);
786 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
788 key.dsize = strlen(keystr) + 1;
790 /* open the database */
792 if ( !tdbsam_open( tdbsam_filename ) ) {
793 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
794 return NT_STATUS_ACCESS_DENIED;
799 data = tdb_fetch(tdbsam, key);
801 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
802 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
803 DEBUGADD(5, (" Key: %s\n", keystr));
804 result = NT_STATUS_NO_SUCH_USER;
808 /* unpack the buffer */
810 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
811 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
812 SAFE_FREE(data.dptr);
813 result = NT_STATUS_NO_MEMORY;
817 result = NT_STATUS_OK;
820 SAFE_FREE(data.dptr);
826 /***************************************************************************
828 **************************************************************************/
830 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
832 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
838 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
844 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
846 key.dsize = strlen (keystr) + 1;
848 /* open the database */
850 if ( !tdbsam_open( tdbsam_filename ) ) {
851 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
852 return NT_STATUS_ACCESS_DENIED;
857 data = tdb_fetch (tdbsam, key);
859 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
860 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
861 nt_status = NT_STATUS_UNSUCCESSFUL;
865 fstrcpy(name, data.dptr);
866 SAFE_FREE(data.dptr);
868 nt_status = tdbsam_getsampwnam (my_methods, user, name);
878 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
882 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
883 return NT_STATUS_UNSUCCESSFUL;
885 return tdbsam_getsampwrid(my_methods, user, rid);
888 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
894 fstrcpy(name, pdb_get_username(sam_pass));
897 /* set the search key */
899 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
901 key.dsize = strlen (keystr) + 1;
903 /* it's outaa here! 8^) */
905 if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
906 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
907 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
914 /***************************************************************************
915 Delete a struct samu records for the username and RID key
916 ****************************************************************************/
918 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
920 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
926 /* make sure we have an open handle to the tdb. Should have happened
927 at module initialization time */
930 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
931 return NT_STATUS_NO_SUCH_USER;
934 fstrcpy(name, pdb_get_username(sam_pass));
937 /* set the search key */
939 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
941 key.dsize = strlen (keystr) + 1;
943 rid = pdb_get_user_rid(sam_pass);
945 /* open the database */
947 if ( !tdbsam_open( tdbsam_filename ) ) {
948 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
949 return NT_STATUS_ACCESS_DENIED;
952 /* it's outaa here! 8^) */
954 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
955 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
956 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
957 nt_status = NT_STATUS_UNSUCCESSFUL;
961 /* set the search key */
963 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
965 key.dsize = strlen (keystr) + 1;
967 /* it's outaa here! 8^) */
969 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
970 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
971 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
972 nt_status = NT_STATUS_UNSUCCESSFUL;
976 nt_status = NT_STATUS_OK;
985 /***************************************************************************
986 Update the TDB SAM account record only
987 Assumes that the tdbsam is already open
988 ****************************************************************************/
989 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
997 /* copy the struct samu struct into a BYTE buffer for storage */
999 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1000 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1004 data.dptr = (char *)buf;
1006 fstrcpy(name, pdb_get_username(newpwd));
1009 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1010 flag == TDB_INSERT ? "(new) " : "", name,
1011 pdb_get_user_rid(newpwd)));
1013 /* setup the USER index key */
1014 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1016 key.dsize = strlen(keystr) + 1;
1018 /* add the account */
1020 if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
1021 DEBUG(0, ("Unable to modify passwd TDB!"));
1022 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1023 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1036 /***************************************************************************
1037 Update the TDB SAM RID record only
1038 Assumes that the tdbsam is already open
1039 ****************************************************************************/
1040 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1046 fstrcpy(name, pdb_get_username(newpwd));
1049 /* setup RID data */
1050 data.dsize = strlen(name) + 1;
1053 /* setup the RID index key */
1054 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1056 key.dsize = strlen (keystr) + 1;
1058 /* add the reference */
1059 if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
1060 DEBUG(0, ("Unable to modify TDB passwd !"));
1061 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1062 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1070 /***************************************************************************
1072 ****************************************************************************/
1074 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1079 /* invalidate the existing TDB iterator if it is open */
1081 tdbsam_endsampwent( my_methods );
1083 if ( !pdb_get_group_rid(newpwd) ) {
1084 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1085 "without a primary group RID\n", pdb_get_username(newpwd)));
1089 if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
1090 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1094 /* open the database */
1096 if ( !tdbsam_open( tdbsam_filename ) ) {
1097 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1101 if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1112 /***************************************************************************
1113 Modifies an existing struct samu
1114 ****************************************************************************/
1116 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1118 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1119 return NT_STATUS_UNSUCCESSFUL;
1121 return NT_STATUS_OK;
1124 /***************************************************************************
1125 Adds an existing struct samu
1126 ****************************************************************************/
1128 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1130 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1131 return NT_STATUS_UNSUCCESSFUL;
1133 return NT_STATUS_OK;
1136 /***************************************************************************
1137 Renames a struct samu
1138 - check for the posix user/rename user script
1139 - Add and lock the new user record
1140 - rename the posix user
1141 - rewrite the rid->username record
1142 - delete the old user
1143 - unlock the new user record
1144 ***************************************************************************/
1145 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1146 struct samu *old_acct,
1147 const char *newname)
1149 struct samu *new_acct = NULL;
1150 pstring rename_script;
1151 BOOL interim_account = False;
1154 /* make sure we have an open handle to the tdb. Should have happened
1155 at module initialization time */
1158 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
1159 return NT_STATUS_NO_SUCH_USER;
1162 /* can't do anything without an external script */
1164 pstrcpy(rename_script, lp_renameuser_script() );
1165 if ( ! *rename_script )
1166 return NT_STATUS_ACCESS_DENIED;
1168 /* invalidate the existing TDB iterator if it is open */
1170 tdbsam_endsampwent( my_methods );
1172 if ( !(new_acct = samu_new( NULL )) ) {
1173 return NT_STATUS_NO_MEMORY;
1176 if ( !pdb_copy_sam_account(new_acct, old_acct)
1177 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1179 TALLOC_FREE(new_acct );
1180 return NT_STATUS_NO_MEMORY;
1183 /* open the database */
1185 if ( !tdbsam_open( tdbsam_filename ) ) {
1186 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1187 TALLOC_FREE(new_acct );
1188 return NT_STATUS_ACCESS_DENIED;
1191 /* add the new account and lock it */
1193 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) )
1198 interim_account = True;
1200 if ( tdb_lock_bystring(tdbsam, newname, 30) == -1 ) {
1204 /* rename the posix user */
1205 string_sub2(rename_script, "%unew", newname, sizeof(pstring),
1207 string_sub2(rename_script, "%uold", pdb_get_username(old_acct),
1208 sizeof(pstring), True, False, True);
1209 rename_ret = smbrun(rename_script, NULL);
1211 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1216 /* rewrite the rid->username record */
1218 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) )
1220 interim_account = False;
1221 tdb_unlock_bystring( tdbsam, newname );
1223 tdb_delete_samacct_only( old_acct );
1227 TALLOC_FREE(new_acct );
1228 return NT_STATUS_OK;
1232 if (interim_account) {
1233 tdb_unlock_bystring(tdbsam, newname);
1234 tdb_delete_samacct_only(new_acct);
1240 TALLOC_FREE(new_acct);
1242 return NT_STATUS_ACCESS_DENIED;
1245 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1251 * Historically, winbind was responsible for allocating RIDs, so the next RID
1252 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1253 * but for compatibility reasons we still keep the the next RID counter in
1254 * winbindd_idmap.tdb.
1257 /*****************************************************************************
1258 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1259 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1260 winbind completely and store the RID counter in passdb.tdb.
1262 Dont' fully initialize with the HWM values, if it's new, we're only
1263 interested in the RID counter.
1264 *****************************************************************************/
1266 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1270 if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
1271 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1275 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1277 if (version == -1) {
1278 /* No key found, must be a new db */
1279 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1280 IDMAP_VERSION) != 0) {
1281 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1282 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1285 version = IDMAP_VERSION;
1288 if (version != IDMAP_VERSION) {
1289 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1290 "start winbind once\n", IDMAP_VERSION, version));
1291 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1295 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1299 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1305 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1306 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1309 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1313 if (!init_idmap_tdb(tdb)) {
1314 DEBUG(1, ("Could not init idmap\n"));
1318 rid = BASE_RID; /* Default if not set */
1320 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1321 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1329 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1330 smb_panic("tdb_close(idmap_tdb) failed\n");
1336 /*********************************************************************
1337 Initialize the tdb sam backend. Setup the dispath table of methods,
1338 open the tdb, etc...
1339 *********************************************************************/
1341 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1345 const char *pfile = location;
1347 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1351 (*pdb_method)->name = "tdbsam";
1353 (*pdb_method)->setsampwent = tdbsam_setsampwent;
1354 (*pdb_method)->endsampwent = tdbsam_endsampwent;
1355 (*pdb_method)->getsampwent = tdbsam_getsampwent;
1356 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1357 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1358 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1359 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1360 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1361 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1363 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1364 (*pdb_method)->new_rid = tdbsam_new_rid;
1366 /* save the path for later */
1369 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1372 pstrcpy( tdbsam_filename, pfile );
1374 /* no private data */
1376 (*pdb_method)->private_data = NULL;
1377 (*pdb_method)->free_private_data = NULL;
1379 return NT_STATUS_OK;
1382 NTSTATUS pdb_tdbsam_init(void)
1384 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);