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 3 /* 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"
67 #define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
69 /*********************************************************************
70 *********************************************************************/
72 static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
75 /* times are stored as 32bit integer
76 take care on system with 64bit wide time_t
83 pass_must_change_time;
84 char *username = NULL;
86 char *nt_username = NULL;
87 char *dir_drive = NULL;
88 char *unknown_str = NULL;
89 char *munged_dial = NULL;
90 char *fullname = NULL;
92 char *logon_script = NULL;
93 char *profile_path = NULL;
94 char *acct_desc = NULL;
95 char *workstations = NULL;
96 uint32 username_len, domain_len, nt_username_len,
97 dir_drive_len, unknown_str_len, munged_dial_len,
98 fullname_len, homedir_len, logon_script_len,
99 profile_path_len, acct_desc_len, workstations_len;
101 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
102 uint16 acct_ctrl, logon_divs;
103 uint16 bad_password_count, logon_count;
105 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
107 uint32 lm_pw_len, nt_pw_len, hourslen;
110 if(sampass == NULL || buf == NULL) {
111 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
115 /* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
117 /* unpack the buffer into variables */
118 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V0,
120 &logoff_time, /* d */
121 &kickoff_time, /* d */
122 &pass_last_set_time, /* d */
123 &pass_can_change_time, /* d */
124 &pass_must_change_time, /* d */
125 &username_len, &username, /* B */
126 &domain_len, &domain, /* B */
127 &nt_username_len, &nt_username, /* B */
128 &fullname_len, &fullname, /* B */
129 &homedir_len, &homedir, /* B */
130 &dir_drive_len, &dir_drive, /* B */
131 &logon_script_len, &logon_script, /* B */
132 &profile_path_len, &profile_path, /* B */
133 &acct_desc_len, &acct_desc, /* B */
134 &workstations_len, &workstations, /* B */
135 &unknown_str_len, &unknown_str, /* B */
136 &munged_dial_len, &munged_dial, /* B */
139 &lm_pw_len, &lm_pw_ptr, /* B */
140 &nt_pw_len, &nt_pw_ptr, /* B */
142 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
145 &hourslen, &hours, /* B */
146 &bad_password_count, /* w */
147 &logon_count, /* w */
150 if (len == (uint32) -1) {
155 pdb_set_logon_time(sampass, logon_time, PDB_SET);
156 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
157 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
158 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
159 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
160 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
162 pdb_set_username(sampass, username, PDB_SET);
163 pdb_set_domain(sampass, domain, PDB_SET);
164 pdb_set_nt_username(sampass, nt_username, PDB_SET);
165 pdb_set_fullname(sampass, fullname, PDB_SET);
168 pdb_set_homedir(sampass, homedir, PDB_SET);
171 pdb_set_homedir(sampass,
172 talloc_sub_basic(sampass, username, domain,
178 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
180 pdb_set_dir_drive(sampass,
181 talloc_sub_basic(sampass, username, domain,
187 pdb_set_logon_script(sampass, logon_script, PDB_SET);
189 pdb_set_logon_script(sampass,
190 talloc_sub_basic(sampass, username, domain,
196 pdb_set_profile_path(sampass, profile_path, PDB_SET);
198 pdb_set_profile_path(sampass,
199 talloc_sub_basic(sampass, username, domain,
204 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
205 pdb_set_workstations(sampass, workstations, PDB_SET);
206 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
208 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
209 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
215 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
216 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
222 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
223 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
224 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
225 pdb_set_hours_len(sampass, hours_len, PDB_SET);
226 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
227 pdb_set_logon_count(sampass, logon_count, PDB_SET);
228 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
229 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
230 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
231 pdb_set_hours(sampass, hours, PDB_SET);
237 SAFE_FREE(nt_username);
240 SAFE_FREE(dir_drive);
241 SAFE_FREE(logon_script);
242 SAFE_FREE(profile_path);
243 SAFE_FREE(acct_desc);
244 SAFE_FREE(workstations);
245 SAFE_FREE(munged_dial);
246 SAFE_FREE(unknown_str);
247 SAFE_FREE(lm_pw_ptr);
248 SAFE_FREE(nt_pw_ptr);
254 /*********************************************************************
255 *********************************************************************/
257 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
260 /* times are stored as 32bit integer
261 take care on system with 64bit wide time_t
268 pass_can_change_time,
269 pass_must_change_time;
270 char *username = NULL;
272 char *nt_username = NULL;
273 char *dir_drive = NULL;
274 char *unknown_str = NULL;
275 char *munged_dial = NULL;
276 char *fullname = NULL;
277 char *homedir = NULL;
278 char *logon_script = NULL;
279 char *profile_path = NULL;
280 char *acct_desc = NULL;
281 char *workstations = NULL;
282 uint32 username_len, domain_len, nt_username_len,
283 dir_drive_len, unknown_str_len, munged_dial_len,
284 fullname_len, homedir_len, logon_script_len,
285 profile_path_len, acct_desc_len, workstations_len;
287 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
288 uint16 acct_ctrl, logon_divs;
289 uint16 bad_password_count, logon_count;
291 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
293 uint32 lm_pw_len, nt_pw_len, hourslen;
296 if(sampass == NULL || buf == NULL) {
297 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
301 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
303 /* unpack the buffer into variables */
304 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V1,
306 &logoff_time, /* d */
307 &kickoff_time, /* d */
308 /* Change from V0 is addition of bad_password_time field. */
309 &bad_password_time, /* d */
310 &pass_last_set_time, /* d */
311 &pass_can_change_time, /* d */
312 &pass_must_change_time, /* d */
313 &username_len, &username, /* B */
314 &domain_len, &domain, /* B */
315 &nt_username_len, &nt_username, /* B */
316 &fullname_len, &fullname, /* B */
317 &homedir_len, &homedir, /* B */
318 &dir_drive_len, &dir_drive, /* B */
319 &logon_script_len, &logon_script, /* B */
320 &profile_path_len, &profile_path, /* B */
321 &acct_desc_len, &acct_desc, /* B */
322 &workstations_len, &workstations, /* B */
323 &unknown_str_len, &unknown_str, /* B */
324 &munged_dial_len, &munged_dial, /* B */
327 &lm_pw_len, &lm_pw_ptr, /* B */
328 &nt_pw_len, &nt_pw_ptr, /* B */
333 &hourslen, &hours, /* B */
334 &bad_password_count, /* w */
335 &logon_count, /* w */
338 if (len == (uint32) -1) {
343 pdb_set_logon_time(sampass, logon_time, PDB_SET);
344 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
345 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
347 /* Change from V0 is addition of bad_password_time field. */
348 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
349 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
350 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
351 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
353 pdb_set_username(sampass, username, PDB_SET);
354 pdb_set_domain(sampass, domain, PDB_SET);
355 pdb_set_nt_username(sampass, nt_username, PDB_SET);
356 pdb_set_fullname(sampass, fullname, PDB_SET);
359 pdb_set_homedir(sampass, homedir, PDB_SET);
362 pdb_set_homedir(sampass,
363 talloc_sub_basic(sampass, username, domain,
369 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
371 pdb_set_dir_drive(sampass,
372 talloc_sub_basic(sampass, username, domain,
378 pdb_set_logon_script(sampass, logon_script, PDB_SET);
380 pdb_set_logon_script(sampass,
381 talloc_sub_basic(sampass, username, domain,
387 pdb_set_profile_path(sampass, profile_path, PDB_SET);
389 pdb_set_profile_path(sampass,
390 talloc_sub_basic(sampass, username, domain,
395 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
396 pdb_set_workstations(sampass, workstations, PDB_SET);
397 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
399 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
400 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
406 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
407 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
413 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
415 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
416 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
417 pdb_set_hours_len(sampass, hours_len, PDB_SET);
418 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
419 pdb_set_logon_count(sampass, logon_count, PDB_SET);
420 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
421 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
422 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
423 pdb_set_hours(sampass, hours, PDB_SET);
429 SAFE_FREE(nt_username);
432 SAFE_FREE(dir_drive);
433 SAFE_FREE(logon_script);
434 SAFE_FREE(profile_path);
435 SAFE_FREE(acct_desc);
436 SAFE_FREE(workstations);
437 SAFE_FREE(munged_dial);
438 SAFE_FREE(unknown_str);
439 SAFE_FREE(lm_pw_ptr);
440 SAFE_FREE(nt_pw_ptr);
446 BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
449 /* times are stored as 32bit integer
450 take care on system with 64bit wide time_t
457 pass_can_change_time,
458 pass_must_change_time;
459 char *username = NULL;
461 char *nt_username = NULL;
462 char *dir_drive = NULL;
463 char *unknown_str = NULL;
464 char *munged_dial = NULL;
465 char *fullname = NULL;
466 char *homedir = NULL;
467 char *logon_script = NULL;
468 char *profile_path = NULL;
469 char *acct_desc = NULL;
470 char *workstations = NULL;
471 uint32 username_len, domain_len, nt_username_len,
472 dir_drive_len, unknown_str_len, munged_dial_len,
473 fullname_len, homedir_len, logon_script_len,
474 profile_path_len, acct_desc_len, workstations_len;
476 uint32 user_rid, group_rid, hours_len, unknown_6;
477 uint16 acct_ctrl, logon_divs;
478 uint16 bad_password_count, logon_count;
480 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
482 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
483 uint32 pwHistLen = 0;
486 BOOL expand_explicit = lp_passdb_expand_explicit();
488 if(sampass == NULL || buf == NULL) {
489 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
493 /* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
495 /* unpack the buffer into variables */
496 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V2,
498 &logoff_time, /* d */
499 &kickoff_time, /* d */
500 &bad_password_time, /* d */
501 &pass_last_set_time, /* d */
502 &pass_can_change_time, /* d */
503 &pass_must_change_time, /* d */
504 &username_len, &username, /* B */
505 &domain_len, &domain, /* B */
506 &nt_username_len, &nt_username, /* B */
507 &fullname_len, &fullname, /* B */
508 &homedir_len, &homedir, /* B */
509 &dir_drive_len, &dir_drive, /* B */
510 &logon_script_len, &logon_script, /* B */
511 &profile_path_len, &profile_path, /* B */
512 &acct_desc_len, &acct_desc, /* B */
513 &workstations_len, &workstations, /* B */
514 &unknown_str_len, &unknown_str, /* B */
515 &munged_dial_len, &munged_dial, /* B */
518 &lm_pw_len, &lm_pw_ptr, /* B */
519 &nt_pw_len, &nt_pw_ptr, /* B */
520 /* Change from V1 is addition of password history field. */
521 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
523 /* Also "remove_me" field was removed. */
526 &hourslen, &hours, /* B */
527 &bad_password_count, /* w */
528 &logon_count, /* w */
531 if (len == (uint32) -1) {
536 pdb_set_logon_time(sampass, logon_time, PDB_SET);
537 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
538 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
539 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
540 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
541 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
542 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
544 pdb_set_username(sampass, username, PDB_SET);
545 pdb_set_domain(sampass, domain, PDB_SET);
546 pdb_set_nt_username(sampass, nt_username, PDB_SET);
547 pdb_set_fullname(sampass, fullname, PDB_SET);
550 fstrcpy( tmpstring, homedir );
551 if (expand_explicit) {
552 standard_sub_basic( username, domain, tmpstring,
555 pdb_set_homedir(sampass, tmpstring, PDB_SET);
558 pdb_set_homedir(sampass,
559 talloc_sub_basic(sampass, username, domain,
565 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
567 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
570 fstrcpy( tmpstring, logon_script );
571 if (expand_explicit) {
572 standard_sub_basic( username, domain, tmpstring,
575 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
578 pdb_set_logon_script(sampass,
579 talloc_sub_basic(sampass, username, domain,
585 fstrcpy( tmpstring, profile_path );
586 if (expand_explicit) {
587 standard_sub_basic( username, domain, tmpstring,
590 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
593 pdb_set_profile_path(sampass,
594 talloc_sub_basic(sampass, username, domain,
599 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
600 pdb_set_workstations(sampass, workstations, PDB_SET);
601 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
603 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
604 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
610 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
611 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
617 /* Change from V1 is addition of password history field. */
618 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
620 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
625 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
626 if (nt_pw_hist_ptr && nt_pw_hist_len) {
628 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
629 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
630 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
631 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
632 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
633 PW_HISTORY_ENTRY_LEN);
636 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
643 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
646 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
647 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
648 pdb_set_hours_len(sampass, hours_len, PDB_SET);
649 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
650 pdb_set_logon_count(sampass, logon_count, PDB_SET);
651 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
652 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
653 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
654 pdb_set_hours(sampass, hours, PDB_SET);
660 SAFE_FREE(nt_username);
663 SAFE_FREE(dir_drive);
664 SAFE_FREE(logon_script);
665 SAFE_FREE(profile_path);
666 SAFE_FREE(acct_desc);
667 SAFE_FREE(workstations);
668 SAFE_FREE(munged_dial);
669 SAFE_FREE(unknown_str);
670 SAFE_FREE(lm_pw_ptr);
671 SAFE_FREE(nt_pw_ptr);
672 SAFE_FREE(nt_pw_hist_ptr);
679 /**********************************************************************
680 Intialize a struct samu struct from a BYTE buffer of size len
681 *********************************************************************/
683 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
685 return init_sam_from_buffer_v3(sampass, buf, buflen);
688 /**********************************************************************
689 Intialize a BYTE buffer from a struct samu struct
690 *********************************************************************/
692 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
694 return init_buffer_from_sam_v3(buf, sampass, size_only);
697 /**********************************************************************
698 Intialize a BYTE buffer from a struct samu struct
699 *********************************************************************/
701 static BOOL tdbsam_convert(int32 from)
703 const char *vstring = TDBSAM_VERSION_STRING;
704 const char *prefix = USERPREFIX;
705 TDB_DATA data, key, old_key;
709 /* handle a Samba upgrade */
710 tdb_lock_bystring(tdbsam, vstring);
712 /* Enumerate all records and convert them */
713 key = tdb_firstkey(tdbsam);
717 /* skip all non-USER entries (eg. RIDs) */
718 while ((key.dsize != 0) && (strncmp((const char *)key.dptr, prefix, strlen (prefix)))) {
720 /* increment to next in line */
721 key = tdb_nextkey(tdbsam, key);
722 SAFE_FREE(old_key.dptr);
726 struct samu *user = NULL;
728 /* read from tdbsam */
729 data = tdb_fetch(tdbsam, key);
731 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
735 /* unpack the buffer from the former format */
736 if ( !(user = samu_new( NULL )) ) {
737 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
738 SAFE_FREE( data.dptr );
741 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
744 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
747 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
750 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
753 ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
756 /* unknown tdbsam version */
760 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
761 SAFE_FREE(data.dptr);
766 /* We're finished with the old data. */
767 SAFE_FREE(data.dptr);
769 /* pack from the buffer into the new format */
771 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n",
772 (const char *)key.dptr, from));
773 data.dsize = init_buffer_from_sam (&buf, user, False);
776 if ( data.dsize == -1 ) {
777 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
782 /* Store the buffer inside the TDBSAM */
783 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
784 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
785 SAFE_FREE(data.dptr);
789 SAFE_FREE(data.dptr);
791 /* increment to next in line */
793 key = tdb_nextkey(tdbsam, key);
794 SAFE_FREE(old_key.dptr);
800 /* upgrade finished */
801 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
802 tdb_unlock_bystring(tdbsam, vstring);
807 /*********************************************************************
808 Open the tdbsam file based on the absolute path specified.
809 Uses a reference count to allow multiple open calls.
810 *********************************************************************/
812 static BOOL tdbsam_open( const char *name )
816 /* check if we are already open */
820 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
825 SMB_ASSERT( ref_count == 0 );
827 /* Try to open tdb passwd. Create a new one if necessary */
829 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
830 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
834 /* set the initial reference count - must be done before tdbsam_convert
835 as that calls tdbsam_open()/tdbsam_close(). */
839 /* Check the version */
840 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
843 version = 0; /* Version not found, assume version 0 */
846 /* Compare the version */
847 if (version > TDBSAM_VERSION) {
848 /* Version more recent than the latest known */
849 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
856 if ( version < TDBSAM_VERSION ) {
857 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
858 version, TDBSAM_VERSION));
860 if ( !tdbsam_convert(version) ) {
861 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
867 DEBUG(3, ("TDBSAM converted successfully.\n"));
870 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
875 /****************************************************************************
876 wrapper atound tdb_close() to handle the reference count
877 ****************************************************************************/
879 void tdbsam_close( void )
883 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
885 SMB_ASSERT(ref_count >= 0 );
887 if ( ref_count == 0 ) {
895 /****************************************************************************
896 creates a list of user keys
897 ****************************************************************************/
899 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
901 const char *prefix = USERPREFIX;
902 int prefixlen = strlen (prefix);
903 struct pwent_list *ptr;
905 if ( strncmp((const char *)key.dptr, prefix, prefixlen) == 0 ) {
906 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
907 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
909 /* just return 0 and let the traversal continue */
914 /* save a copy of the key */
916 ptr->key.dptr = (uint8 *)memdup( key.dptr, key.dsize );
917 if (!ptr->key.dptr) {
918 DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n"));
919 /* just return 0 and let the traversal continue */
924 ptr->key.dsize = key.dsize;
926 DLIST_ADD( tdbsam_pwent_list, ptr );
933 /***************************************************************
934 Open the TDB passwd database for SAM account enumeration.
935 Save a list of user keys for iteration.
936 ****************************************************************/
938 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
940 if ( !tdbsam_open( tdbsam_filename ) ) {
941 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
942 return NT_STATUS_ACCESS_DENIED;
945 tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
946 pwent_initialized = True;
952 /***************************************************************
953 End enumeration of the TDB passwd list.
954 ****************************************************************/
956 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
958 struct pwent_list *ptr, *ptr_next;
960 /* close the tdb only if we have a valid pwent state */
962 if ( pwent_initialized ) {
963 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
967 /* clear out any remaining entries in the list */
969 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
970 ptr_next = ptr->next;
971 DLIST_REMOVE( tdbsam_pwent_list, ptr );
972 SAFE_FREE( ptr->key.dptr);
976 pwent_initialized = False;
979 /*****************************************************************
980 Get one struct samu from the TDB (next in line)
981 *****************************************************************/
983 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
985 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
987 struct pwent_list *pkey;
990 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
994 if ( !tdbsam_pwent_list ) {
995 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
999 /* pull the next entry */
1001 pkey = tdbsam_pwent_list;
1002 DLIST_REMOVE( tdbsam_pwent_list, pkey );
1004 data = tdb_fetch(tdbsam, pkey->key);
1006 SAFE_FREE( pkey->key.dptr);
1010 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
1014 if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
1015 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1018 SAFE_FREE( data.dptr );
1020 return NT_STATUS_OK;
1023 /******************************************************************
1024 Lookup a name in the SAM TDB
1025 ******************************************************************/
1027 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
1034 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
1035 return NT_STATUS_NO_MEMORY;
1038 /* Data is stored in all lower-case */
1039 fstrcpy(name, sname);
1042 /* set search key */
1043 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1045 /* open the database */
1047 if ( !tdbsam_open( tdbsam_filename ) ) {
1048 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1049 return NT_STATUS_ACCESS_DENIED;
1052 /* get the record */
1054 data = tdb_fetch_bystring(tdbsam, keystr);
1056 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
1057 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1058 DEBUGADD(5, (" Key: %s\n", keystr));
1060 return NT_STATUS_NO_SUCH_USER;
1063 /* unpack the buffer */
1065 if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
1066 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1067 SAFE_FREE(data.dptr);
1069 return NT_STATUS_NO_MEMORY;
1074 SAFE_FREE(data.dptr);
1077 return NT_STATUS_OK;
1080 /***************************************************************************
1082 **************************************************************************/
1084 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
1086 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1092 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
1096 /* set search key */
1098 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1100 /* open the database */
1102 if ( !tdbsam_open( tdbsam_filename ) ) {
1103 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1104 return NT_STATUS_ACCESS_DENIED;
1107 /* get the record */
1109 data = tdb_fetch_bystring (tdbsam, keystr);
1111 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
1112 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1113 nt_status = NT_STATUS_UNSUCCESSFUL;
1117 fstrcpy(name, (const char *)data.dptr);
1118 SAFE_FREE(data.dptr);
1120 nt_status = tdbsam_getsampwnam (my_methods, user, name);
1130 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
1134 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
1135 return NT_STATUS_UNSUCCESSFUL;
1137 return tdbsam_getsampwrid(my_methods, user, rid);
1140 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
1145 fstrcpy(name, pdb_get_username(sam_pass));
1148 /* set the search key */
1150 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1152 /* it's outaa here! 8^) */
1154 if (tdb_delete_bystring(tdbsam, keystr) != TDB_SUCCESS) {
1155 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1156 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1163 /***************************************************************************
1164 Delete a struct samu records for the username and RID key
1165 ****************************************************************************/
1167 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
1169 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1174 /* open the database */
1176 if ( !tdbsam_open( tdbsam_filename ) ) {
1177 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1179 return NT_STATUS_ACCESS_DENIED;
1182 fstrcpy(name, pdb_get_username(sam_pass));
1185 /* set the search key */
1187 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1189 rid = pdb_get_user_rid(sam_pass);
1191 /* it's outaa here! 8^) */
1193 if ( tdb_delete_bystring(tdbsam, keystr) != TDB_SUCCESS ) {
1194 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1195 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1196 nt_status = NT_STATUS_UNSUCCESSFUL;
1200 /* set the search key */
1202 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1204 /* it's outaa here! 8^) */
1206 if ( tdb_delete_bystring(tdbsam, keystr) != TDB_SUCCESS ) {
1207 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
1208 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1209 nt_status = NT_STATUS_UNSUCCESSFUL;
1213 nt_status = NT_STATUS_OK;
1222 /***************************************************************************
1223 Update the TDB SAM account record only
1224 Assumes that the tdbsam is already open
1225 ****************************************************************************/
1226 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
1234 /* copy the struct samu struct into a BYTE buffer for storage */
1236 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1237 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1243 fstrcpy(name, pdb_get_username(newpwd));
1246 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1247 flag == TDB_INSERT ? "(new) " : "", name,
1248 pdb_get_user_rid(newpwd)));
1250 /* setup the USER index key */
1251 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1253 /* add the account */
1255 if ( tdb_store_bystring(tdbsam, keystr, data, flag) != TDB_SUCCESS ) {
1256 DEBUG(0, ("Unable to modify passwd TDB!"));
1257 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1258 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1271 /***************************************************************************
1272 Update the TDB SAM RID record only
1273 Assumes that the tdbsam is already open
1274 ****************************************************************************/
1275 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1281 fstrcpy(name, pdb_get_username(newpwd));
1284 /* setup RID data */
1285 data = string_term_tdb_data(name);
1287 /* setup the RID index key */
1288 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1290 /* add the reference */
1291 if (tdb_store_bystring(tdbsam, keystr, data, flag) != TDB_SUCCESS) {
1292 DEBUG(0, ("Unable to modify TDB passwd !"));
1293 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1294 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1302 /***************************************************************************
1304 ****************************************************************************/
1306 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1310 /* invalidate the existing TDB iterator if it is open */
1312 tdbsam_endsampwent( my_methods );
1315 if ( !pdb_get_group_rid(newpwd) ) {
1316 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1317 "without a primary group RID\n", pdb_get_username(newpwd)));
1322 if (!pdb_get_user_rid(newpwd)) {
1323 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1327 /* open the database */
1329 if ( !tdbsam_open( tdbsam_filename ) ) {
1330 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1334 if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1345 /***************************************************************************
1346 Modifies an existing struct samu
1347 ****************************************************************************/
1349 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1351 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1352 return NT_STATUS_UNSUCCESSFUL;
1354 return NT_STATUS_OK;
1357 /***************************************************************************
1358 Adds an existing struct samu
1359 ****************************************************************************/
1361 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1363 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1364 return NT_STATUS_UNSUCCESSFUL;
1366 return NT_STATUS_OK;
1369 /***************************************************************************
1370 Renames a struct samu
1371 - check for the posix user/rename user script
1372 - Add and lock the new user record
1373 - rename the posix user
1374 - rewrite the rid->username record
1375 - delete the old user
1376 - unlock the new user record
1377 ***************************************************************************/
1378 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1379 struct samu *old_acct,
1380 const char *newname)
1382 struct samu *new_acct = NULL;
1383 pstring rename_script;
1384 BOOL interim_account = False;
1386 fstring oldname_lower;
1387 fstring newname_lower;
1389 /* can't do anything without an external script */
1391 pstrcpy(rename_script, lp_renameuser_script() );
1392 if ( ! *rename_script ) {
1393 return NT_STATUS_ACCESS_DENIED;
1396 /* invalidate the existing TDB iterator if it is open */
1398 tdbsam_endsampwent( my_methods );
1400 if ( !(new_acct = samu_new( NULL )) ) {
1401 return NT_STATUS_NO_MEMORY;
1404 if ( !pdb_copy_sam_account(new_acct, old_acct)
1405 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1407 TALLOC_FREE(new_acct );
1408 return NT_STATUS_NO_MEMORY;
1411 /* open the database */
1413 if ( !tdbsam_open( tdbsam_filename ) ) {
1414 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1415 TALLOC_FREE(new_acct );
1416 return NT_STATUS_ACCESS_DENIED;
1419 /* add the new account and lock it */
1421 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1425 interim_account = True;
1427 if ( tdb_lock_bystring_with_timeout(tdbsam, newname, 30) == -1 ) {
1431 /* Rename the posix user. Follow the semantics of _samr_create_user()
1432 so that we lower case the posix name but preserve the case in passdb */
1434 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1435 strlower_m( oldname_lower );
1437 fstrcpy( newname_lower, newname );
1438 strlower_m( newname_lower );
1440 string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring),
1442 string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring),
1444 rename_ret = smbrun(rename_script, NULL);
1446 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1448 if (rename_ret == 0) {
1449 smb_nscd_flush_user_cache();
1456 /* rewrite the rid->username record */
1458 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1461 interim_account = False;
1462 tdb_unlock_bystring( tdbsam, newname );
1464 tdb_delete_samacct_only( old_acct );
1468 TALLOC_FREE(new_acct );
1469 return NT_STATUS_OK;
1473 if (interim_account) {
1474 tdb_unlock_bystring(tdbsam, newname);
1475 tdb_delete_samacct_only(new_acct);
1481 TALLOC_FREE(new_acct);
1483 return NT_STATUS_ACCESS_DENIED;
1486 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1492 * Historically, winbind was responsible for allocating RIDs, so the next RID
1493 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1494 * but for compatibility reasons we still keep the the next RID counter in
1495 * winbindd_idmap.tdb.
1498 /*****************************************************************************
1499 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1500 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1501 winbind completely and store the RID counter in passdb.tdb.
1503 Dont' fully initialize with the HWM values, if it's new, we're only
1504 interested in the RID counter.
1505 *****************************************************************************/
1507 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1511 if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
1512 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1516 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1518 if (version == -1) {
1519 /* No key found, must be a new db */
1520 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1521 IDMAP_VERSION) != 0) {
1522 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1523 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1526 version = IDMAP_VERSION;
1529 if (version != IDMAP_VERSION) {
1530 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1531 "start winbind once\n", IDMAP_VERSION, version));
1532 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1536 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1540 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1546 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1547 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1550 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1554 if (!init_idmap_tdb(tdb)) {
1555 DEBUG(1, ("Could not init idmap\n"));
1559 rid = BASE_RID; /* Default if not set */
1561 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1562 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1570 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1571 smb_panic("tdb_close(idmap_tdb) failed");
1577 /*********************************************************************
1578 Initialize the tdb sam backend. Setup the dispath table of methods,
1579 open the tdb, etc...
1580 *********************************************************************/
1582 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1586 const char *pfile = location;
1588 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1592 (*pdb_method)->name = "tdbsam";
1594 (*pdb_method)->setsampwent = tdbsam_setsampwent;
1595 (*pdb_method)->endsampwent = tdbsam_endsampwent;
1596 (*pdb_method)->getsampwent = tdbsam_getsampwent;
1597 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1598 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1599 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1600 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1601 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1602 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1604 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1605 (*pdb_method)->new_rid = tdbsam_new_rid;
1607 /* save the path for later */
1610 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1613 pstrcpy( tdbsam_filename, pfile );
1615 /* no private data */
1617 (*pdb_method)->private_data = NULL;
1618 (*pdb_method)->free_private_data = NULL;
1620 return NT_STATUS_OK;
1623 NTSTATUS pdb_tdbsam_init(void)
1625 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);