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 3 of the License, or (at your option)
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License along with
22 * this program; if not, see <http://www.gnu.org/licenses/>.
27 #if 0 /* when made a module use this */
29 static int tdbsam_debug_level = DBGC_ALL;
31 #define DBGC_CLASS tdbsam_debug_level
36 #define DBGC_CLASS DBGC_PASSDB
40 #define TDBSAM_VERSION 3 /* Most recent TDBSAM version */
41 #define TDBSAM_VERSION_STRING "INFO/version"
42 #define PASSDB_FILE_NAME "passdb.tdb"
43 #define USERPREFIX "USER_"
44 #define RIDPREFIX "RID_"
45 #define PRIVPREFIX "PRIV_"
47 /* GLOBAL TDB SAM CONTEXT */
49 static TDB_CONTEXT *tdbsam;
50 static int ref_count = 0;
51 static char *tdbsam_filename;
53 /**********************************************************************
54 Marshall/unmarshall struct samu structs.
55 *********************************************************************/
57 #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
58 #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
59 #define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
61 /*********************************************************************
62 *********************************************************************/
64 static bool init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
67 /* times are stored as 32bit integer
68 take care on system with 64bit wide time_t
75 pass_must_change_time;
76 char *username = NULL;
78 char *nt_username = NULL;
79 char *dir_drive = NULL;
80 char *unknown_str = NULL;
81 char *munged_dial = NULL;
82 char *fullname = NULL;
84 char *logon_script = NULL;
85 char *profile_path = NULL;
86 char *acct_desc = NULL;
87 char *workstations = NULL;
88 uint32 username_len, domain_len, nt_username_len,
89 dir_drive_len, unknown_str_len, munged_dial_len,
90 fullname_len, homedir_len, logon_script_len,
91 profile_path_len, acct_desc_len, workstations_len;
93 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
94 uint16 acct_ctrl, logon_divs;
95 uint16 bad_password_count, logon_count;
97 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
99 uint32 lm_pw_len, nt_pw_len, hourslen;
102 if(sampass == NULL || buf == NULL) {
103 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
107 /* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
109 /* unpack the buffer into variables */
110 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V0,
112 &logoff_time, /* d */
113 &kickoff_time, /* d */
114 &pass_last_set_time, /* d */
115 &pass_can_change_time, /* d */
116 &pass_must_change_time, /* d */
117 &username_len, &username, /* B */
118 &domain_len, &domain, /* B */
119 &nt_username_len, &nt_username, /* B */
120 &fullname_len, &fullname, /* B */
121 &homedir_len, &homedir, /* B */
122 &dir_drive_len, &dir_drive, /* B */
123 &logon_script_len, &logon_script, /* B */
124 &profile_path_len, &profile_path, /* B */
125 &acct_desc_len, &acct_desc, /* B */
126 &workstations_len, &workstations, /* B */
127 &unknown_str_len, &unknown_str, /* B */
128 &munged_dial_len, &munged_dial, /* B */
131 &lm_pw_len, &lm_pw_ptr, /* B */
132 &nt_pw_len, &nt_pw_ptr, /* B */
134 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
137 &hourslen, &hours, /* B */
138 &bad_password_count, /* w */
139 &logon_count, /* w */
142 if (len == (uint32) -1) {
147 pdb_set_logon_time(sampass, logon_time, PDB_SET);
148 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
149 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
150 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
151 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
152 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
154 pdb_set_username(sampass, username, PDB_SET);
155 pdb_set_domain(sampass, domain, PDB_SET);
156 pdb_set_nt_username(sampass, nt_username, PDB_SET);
157 pdb_set_fullname(sampass, fullname, PDB_SET);
160 pdb_set_homedir(sampass, homedir, PDB_SET);
163 pdb_set_homedir(sampass,
164 talloc_sub_basic(sampass, username, domain,
170 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
172 pdb_set_dir_drive(sampass,
173 talloc_sub_basic(sampass, username, domain,
179 pdb_set_logon_script(sampass, logon_script, PDB_SET);
181 pdb_set_logon_script(sampass,
182 talloc_sub_basic(sampass, username, domain,
188 pdb_set_profile_path(sampass, profile_path, PDB_SET);
190 pdb_set_profile_path(sampass,
191 talloc_sub_basic(sampass, username, domain,
196 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
197 pdb_set_workstations(sampass, workstations, PDB_SET);
198 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
200 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
201 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
207 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
208 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
214 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
215 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
216 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
217 pdb_set_hours_len(sampass, hours_len, PDB_SET);
218 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
219 pdb_set_logon_count(sampass, logon_count, PDB_SET);
220 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
221 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
222 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
223 pdb_set_hours(sampass, hours, PDB_SET);
229 SAFE_FREE(nt_username);
232 SAFE_FREE(dir_drive);
233 SAFE_FREE(logon_script);
234 SAFE_FREE(profile_path);
235 SAFE_FREE(acct_desc);
236 SAFE_FREE(workstations);
237 SAFE_FREE(munged_dial);
238 SAFE_FREE(unknown_str);
239 SAFE_FREE(lm_pw_ptr);
240 SAFE_FREE(nt_pw_ptr);
246 /*********************************************************************
247 *********************************************************************/
249 static bool init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
252 /* times are stored as 32bit integer
253 take care on system with 64bit wide time_t
260 pass_can_change_time,
261 pass_must_change_time;
262 char *username = NULL;
264 char *nt_username = NULL;
265 char *dir_drive = NULL;
266 char *unknown_str = NULL;
267 char *munged_dial = NULL;
268 char *fullname = NULL;
269 char *homedir = NULL;
270 char *logon_script = NULL;
271 char *profile_path = NULL;
272 char *acct_desc = NULL;
273 char *workstations = NULL;
274 uint32 username_len, domain_len, nt_username_len,
275 dir_drive_len, unknown_str_len, munged_dial_len,
276 fullname_len, homedir_len, logon_script_len,
277 profile_path_len, acct_desc_len, workstations_len;
279 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
280 uint16 acct_ctrl, logon_divs;
281 uint16 bad_password_count, logon_count;
283 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
285 uint32 lm_pw_len, nt_pw_len, hourslen;
288 if(sampass == NULL || buf == NULL) {
289 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
293 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
295 /* unpack the buffer into variables */
296 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V1,
298 &logoff_time, /* d */
299 &kickoff_time, /* d */
300 /* Change from V0 is addition of bad_password_time field. */
301 &bad_password_time, /* d */
302 &pass_last_set_time, /* d */
303 &pass_can_change_time, /* d */
304 &pass_must_change_time, /* d */
305 &username_len, &username, /* B */
306 &domain_len, &domain, /* B */
307 &nt_username_len, &nt_username, /* B */
308 &fullname_len, &fullname, /* B */
309 &homedir_len, &homedir, /* B */
310 &dir_drive_len, &dir_drive, /* B */
311 &logon_script_len, &logon_script, /* B */
312 &profile_path_len, &profile_path, /* B */
313 &acct_desc_len, &acct_desc, /* B */
314 &workstations_len, &workstations, /* B */
315 &unknown_str_len, &unknown_str, /* B */
316 &munged_dial_len, &munged_dial, /* B */
319 &lm_pw_len, &lm_pw_ptr, /* B */
320 &nt_pw_len, &nt_pw_ptr, /* B */
325 &hourslen, &hours, /* B */
326 &bad_password_count, /* w */
327 &logon_count, /* w */
330 if (len == (uint32) -1) {
335 pdb_set_logon_time(sampass, logon_time, PDB_SET);
336 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
337 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
339 /* Change from V0 is addition of bad_password_time field. */
340 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
341 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
342 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
343 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
345 pdb_set_username(sampass, username, PDB_SET);
346 pdb_set_domain(sampass, domain, PDB_SET);
347 pdb_set_nt_username(sampass, nt_username, PDB_SET);
348 pdb_set_fullname(sampass, fullname, PDB_SET);
351 pdb_set_homedir(sampass, homedir, PDB_SET);
354 pdb_set_homedir(sampass,
355 talloc_sub_basic(sampass, username, domain,
361 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
363 pdb_set_dir_drive(sampass,
364 talloc_sub_basic(sampass, username, domain,
370 pdb_set_logon_script(sampass, logon_script, PDB_SET);
372 pdb_set_logon_script(sampass,
373 talloc_sub_basic(sampass, username, domain,
379 pdb_set_profile_path(sampass, profile_path, PDB_SET);
381 pdb_set_profile_path(sampass,
382 talloc_sub_basic(sampass, username, domain,
387 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
388 pdb_set_workstations(sampass, workstations, PDB_SET);
389 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
391 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
392 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
398 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
399 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
405 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
407 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
408 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
409 pdb_set_hours_len(sampass, hours_len, PDB_SET);
410 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
411 pdb_set_logon_count(sampass, logon_count, PDB_SET);
412 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
413 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
414 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
415 pdb_set_hours(sampass, hours, PDB_SET);
421 SAFE_FREE(nt_username);
424 SAFE_FREE(dir_drive);
425 SAFE_FREE(logon_script);
426 SAFE_FREE(profile_path);
427 SAFE_FREE(acct_desc);
428 SAFE_FREE(workstations);
429 SAFE_FREE(munged_dial);
430 SAFE_FREE(unknown_str);
431 SAFE_FREE(lm_pw_ptr);
432 SAFE_FREE(nt_pw_ptr);
438 bool init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
441 /* times are stored as 32bit integer
442 take care on system with 64bit wide time_t
449 pass_can_change_time,
450 pass_must_change_time;
451 char *username = NULL;
453 char *nt_username = NULL;
454 char *dir_drive = NULL;
455 char *unknown_str = NULL;
456 char *munged_dial = NULL;
457 char *fullname = NULL;
458 char *homedir = NULL;
459 char *logon_script = NULL;
460 char *profile_path = NULL;
461 char *acct_desc = NULL;
462 char *workstations = NULL;
463 uint32 username_len, domain_len, nt_username_len,
464 dir_drive_len, unknown_str_len, munged_dial_len,
465 fullname_len, homedir_len, logon_script_len,
466 profile_path_len, acct_desc_len, workstations_len;
468 uint32 user_rid, group_rid, hours_len, unknown_6;
469 uint16 acct_ctrl, logon_divs;
470 uint16 bad_password_count, logon_count;
472 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
474 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
475 uint32 pwHistLen = 0;
478 bool expand_explicit = lp_passdb_expand_explicit();
480 if(sampass == NULL || buf == NULL) {
481 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
485 /* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
487 /* unpack the buffer into variables */
488 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V2,
490 &logoff_time, /* d */
491 &kickoff_time, /* d */
492 &bad_password_time, /* d */
493 &pass_last_set_time, /* d */
494 &pass_can_change_time, /* d */
495 &pass_must_change_time, /* d */
496 &username_len, &username, /* B */
497 &domain_len, &domain, /* B */
498 &nt_username_len, &nt_username, /* B */
499 &fullname_len, &fullname, /* B */
500 &homedir_len, &homedir, /* B */
501 &dir_drive_len, &dir_drive, /* B */
502 &logon_script_len, &logon_script, /* B */
503 &profile_path_len, &profile_path, /* B */
504 &acct_desc_len, &acct_desc, /* B */
505 &workstations_len, &workstations, /* B */
506 &unknown_str_len, &unknown_str, /* B */
507 &munged_dial_len, &munged_dial, /* B */
510 &lm_pw_len, &lm_pw_ptr, /* B */
511 &nt_pw_len, &nt_pw_ptr, /* B */
512 /* Change from V1 is addition of password history field. */
513 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
515 /* Also "remove_me" field was removed. */
518 &hourslen, &hours, /* B */
519 &bad_password_count, /* w */
520 &logon_count, /* w */
523 if (len == (uint32) -1) {
528 pdb_set_logon_time(sampass, logon_time, PDB_SET);
529 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
530 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
531 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
532 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
533 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
534 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
536 pdb_set_username(sampass, username, PDB_SET);
537 pdb_set_domain(sampass, domain, PDB_SET);
538 pdb_set_nt_username(sampass, nt_username, PDB_SET);
539 pdb_set_fullname(sampass, fullname, PDB_SET);
542 fstrcpy( tmp_string, homedir );
543 if (expand_explicit) {
544 standard_sub_basic( username, domain, tmp_string,
545 sizeof(tmp_string) );
547 pdb_set_homedir(sampass, tmp_string, PDB_SET);
550 pdb_set_homedir(sampass,
551 talloc_sub_basic(sampass, username, domain,
557 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
559 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
562 fstrcpy( tmp_string, logon_script );
563 if (expand_explicit) {
564 standard_sub_basic( username, domain, tmp_string,
565 sizeof(tmp_string) );
567 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
570 pdb_set_logon_script(sampass,
571 talloc_sub_basic(sampass, username, domain,
577 fstrcpy( tmp_string, profile_path );
578 if (expand_explicit) {
579 standard_sub_basic( username, domain, tmp_string,
580 sizeof(tmp_string) );
582 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
585 pdb_set_profile_path(sampass,
586 talloc_sub_basic(sampass, username, domain,
591 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
592 pdb_set_workstations(sampass, workstations, PDB_SET);
593 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
595 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
596 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
602 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
603 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
609 /* Change from V1 is addition of password history field. */
610 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
612 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
617 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
618 if (nt_pw_hist_ptr && nt_pw_hist_len) {
620 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
621 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
622 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
623 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
624 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
625 PW_HISTORY_ENTRY_LEN);
628 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
635 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
638 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
639 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
640 pdb_set_hours_len(sampass, hours_len, PDB_SET);
641 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
642 pdb_set_logon_count(sampass, logon_count, PDB_SET);
643 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
644 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
645 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
646 pdb_set_hours(sampass, hours, PDB_SET);
652 SAFE_FREE(nt_username);
655 SAFE_FREE(dir_drive);
656 SAFE_FREE(logon_script);
657 SAFE_FREE(profile_path);
658 SAFE_FREE(acct_desc);
659 SAFE_FREE(workstations);
660 SAFE_FREE(munged_dial);
661 SAFE_FREE(unknown_str);
662 SAFE_FREE(lm_pw_ptr);
663 SAFE_FREE(nt_pw_ptr);
664 SAFE_FREE(nt_pw_hist_ptr);
671 /**********************************************************************
672 Intialize a struct samu struct from a BYTE buffer of size len
673 *********************************************************************/
675 static bool init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
677 return init_sam_from_buffer_v3(sampass, buf, buflen);
680 /**********************************************************************
681 Intialize a BYTE buffer from a struct samu struct
682 *********************************************************************/
684 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, bool size_only)
686 return init_buffer_from_sam_v3(buf, sampass, size_only);
689 /**********************************************************************
690 Intialize a BYTE buffer from a struct samu struct
691 *********************************************************************/
693 static bool tdbsam_convert(int32 from)
695 const char *vstring = TDBSAM_VERSION_STRING;
696 const char *prefix = USERPREFIX;
697 TDB_DATA data, key, old_key;
701 /* handle a Samba upgrade */
702 tdb_lock_bystring(tdbsam, vstring);
704 /* Enumerate all records and convert them */
705 key = tdb_firstkey(tdbsam);
709 /* skip all non-USER entries (eg. RIDs) */
710 while ((key.dsize != 0) && (strncmp((const char *)key.dptr, prefix, strlen (prefix)))) {
712 /* increment to next in line */
713 key = tdb_nextkey(tdbsam, key);
714 SAFE_FREE(old_key.dptr);
718 struct samu *user = NULL;
720 /* read from tdbsam */
721 data = tdb_fetch(tdbsam, key);
723 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
727 /* unpack the buffer from the former format */
728 if ( !(user = samu_new( NULL )) ) {
729 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
730 SAFE_FREE( data.dptr );
733 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
736 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
739 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
742 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
745 ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
748 /* unknown tdbsam version */
752 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
753 SAFE_FREE(data.dptr);
758 /* We're finished with the old data. */
759 SAFE_FREE(data.dptr);
761 /* pack from the buffer into the new format */
763 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n",
764 (const char *)key.dptr, from));
765 data.dsize = init_buffer_from_sam (&buf, user, False);
768 if ( data.dsize == -1 ) {
769 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
774 /* Store the buffer inside the TDBSAM */
775 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
776 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
777 SAFE_FREE(data.dptr);
781 SAFE_FREE(data.dptr);
783 /* increment to next in line */
785 key = tdb_nextkey(tdbsam, key);
786 SAFE_FREE(old_key.dptr);
792 /* upgrade finished */
793 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
794 tdb_unlock_bystring(tdbsam, vstring);
799 /*********************************************************************
800 Open the tdbsam file based on the absolute path specified.
801 Uses a reference count to allow multiple open calls.
802 *********************************************************************/
804 static bool tdbsam_open( const char *name )
808 /* check if we are already open */
812 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
817 SMB_ASSERT( ref_count == 0 );
819 /* Try to open tdb passwd. Create a new one if necessary */
821 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
822 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
826 /* set the initial reference count - must be done before tdbsam_convert
827 as that calls tdbsam_open()/tdbsam_close(). */
831 /* Check the version */
832 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
835 version = 0; /* Version not found, assume version 0 */
838 /* Compare the version */
839 if (version > TDBSAM_VERSION) {
840 /* Version more recent than the latest known */
841 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
848 if ( version < TDBSAM_VERSION ) {
849 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
850 version, TDBSAM_VERSION));
852 if ( !tdbsam_convert(version) ) {
853 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
859 DEBUG(3, ("TDBSAM converted successfully.\n"));
862 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
867 /****************************************************************************
868 wrapper atound tdb_close() to handle the reference count
869 ****************************************************************************/
871 void tdbsam_close( void )
875 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
877 SMB_ASSERT(ref_count >= 0 );
879 if ( ref_count == 0 ) {
887 /******************************************************************
888 Lookup a name in the SAM TDB
889 ******************************************************************/
891 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
898 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
899 return NT_STATUS_NO_MEMORY;
902 /* Data is stored in all lower-case */
903 fstrcpy(name, sname);
907 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
909 /* open the database */
911 if ( !tdbsam_open( tdbsam_filename ) ) {
912 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
913 return NT_STATUS_ACCESS_DENIED;
918 data = tdb_fetch_bystring(tdbsam, keystr);
920 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
921 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
922 DEBUGADD(5, (" Key: %s\n", keystr));
924 return NT_STATUS_NO_SUCH_USER;
927 /* unpack the buffer */
929 if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
930 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
931 SAFE_FREE(data.dptr);
933 return NT_STATUS_NO_MEMORY;
938 SAFE_FREE(data.dptr);
944 /***************************************************************************
946 **************************************************************************/
948 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
950 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
956 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
962 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
964 /* open the database */
966 if ( !tdbsam_open( tdbsam_filename ) ) {
967 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
968 return NT_STATUS_ACCESS_DENIED;
973 data = tdb_fetch_bystring (tdbsam, keystr);
975 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
976 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
977 nt_status = NT_STATUS_UNSUCCESSFUL;
981 fstrcpy(name, (const char *)data.dptr);
982 SAFE_FREE(data.dptr);
984 nt_status = tdbsam_getsampwnam (my_methods, user, name);
994 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
998 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
999 return NT_STATUS_UNSUCCESSFUL;
1001 return tdbsam_getsampwrid(my_methods, user, rid);
1004 static bool tdb_delete_samacct_only( struct samu *sam_pass )
1009 fstrcpy(name, pdb_get_username(sam_pass));
1012 /* set the search key */
1014 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1016 /* it's outaa here! 8^) */
1018 if (tdb_delete_bystring(tdbsam, keystr) != TDB_SUCCESS) {
1019 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1020 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1027 /***************************************************************************
1028 Delete a struct samu records for the username and RID key
1029 ****************************************************************************/
1031 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
1033 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1038 /* open the database */
1040 if ( !tdbsam_open( tdbsam_filename ) ) {
1041 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1043 return NT_STATUS_ACCESS_DENIED;
1046 fstrcpy(name, pdb_get_username(sam_pass));
1049 /* set the search key */
1051 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1053 rid = pdb_get_user_rid(sam_pass);
1055 /* it's outaa here! 8^) */
1057 if ( tdb_delete_bystring(tdbsam, keystr) != TDB_SUCCESS ) {
1058 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1059 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1060 nt_status = NT_STATUS_UNSUCCESSFUL;
1064 /* set the search key */
1066 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1068 /* it's outaa here! 8^) */
1070 if ( tdb_delete_bystring(tdbsam, keystr) != TDB_SUCCESS ) {
1071 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
1072 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1073 nt_status = NT_STATUS_UNSUCCESSFUL;
1077 nt_status = NT_STATUS_OK;
1086 /***************************************************************************
1087 Update the TDB SAM account record only
1088 Assumes that the tdbsam is already open
1089 ****************************************************************************/
1090 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
1098 /* copy the struct samu struct into a BYTE buffer for storage */
1100 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1101 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1107 fstrcpy(name, pdb_get_username(newpwd));
1110 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1111 flag == TDB_INSERT ? "(new) " : "", name,
1112 pdb_get_user_rid(newpwd)));
1114 /* setup the USER index key */
1115 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1117 /* add the account */
1119 if ( tdb_store_bystring(tdbsam, keystr, data, flag) != TDB_SUCCESS ) {
1120 DEBUG(0, ("Unable to modify passwd TDB!"));
1121 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1122 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1135 /***************************************************************************
1136 Update the TDB SAM RID record only
1137 Assumes that the tdbsam is already open
1138 ****************************************************************************/
1139 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
1145 fstrcpy(name, pdb_get_username(newpwd));
1148 /* setup RID data */
1149 data = string_term_tdb_data(name);
1151 /* setup the RID index key */
1152 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1154 /* add the reference */
1155 if (tdb_store_bystring(tdbsam, keystr, data, flag) != TDB_SUCCESS) {
1156 DEBUG(0, ("Unable to modify TDB passwd !"));
1157 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1158 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1166 /***************************************************************************
1168 ****************************************************************************/
1170 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1175 if ( !pdb_get_group_rid(newpwd) ) {
1176 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1177 "without a primary group RID\n", pdb_get_username(newpwd)));
1182 if (!pdb_get_user_rid(newpwd)) {
1183 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1187 /* open the database */
1189 if ( !tdbsam_open( tdbsam_filename ) ) {
1190 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1194 if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1205 /***************************************************************************
1206 Modifies an existing struct samu
1207 ****************************************************************************/
1209 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1211 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1212 return NT_STATUS_UNSUCCESSFUL;
1214 return NT_STATUS_OK;
1217 /***************************************************************************
1218 Adds an existing struct samu
1219 ****************************************************************************/
1221 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1223 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1224 return NT_STATUS_UNSUCCESSFUL;
1226 return NT_STATUS_OK;
1229 /***************************************************************************
1230 Renames a struct samu
1231 - check for the posix user/rename user script
1232 - Add and lock the new user record
1233 - rename the posix user
1234 - rewrite the rid->username record
1235 - delete the old user
1236 - unlock the new user record
1237 ***************************************************************************/
1238 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1239 struct samu *old_acct,
1240 const char *newname)
1242 TALLOC_CTX *ctx = talloc_tos();
1243 struct samu *new_acct = NULL;
1244 char *rename_script = NULL;
1245 bool interim_account = False;
1247 fstring oldname_lower;
1248 fstring newname_lower;
1250 /* can't do anything without an external script */
1252 rename_script = talloc_strdup(ctx, lp_renameuser_script());
1253 if (!rename_script) {
1254 return NT_STATUS_NO_MEMORY;
1256 if (!*rename_script) {
1257 return NT_STATUS_ACCESS_DENIED;
1260 if ( !(new_acct = samu_new( NULL )) ) {
1261 return NT_STATUS_NO_MEMORY;
1264 if ( !pdb_copy_sam_account(new_acct, old_acct)
1265 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1267 TALLOC_FREE(new_acct );
1268 return NT_STATUS_NO_MEMORY;
1271 /* open the database */
1272 if ( !tdbsam_open( tdbsam_filename ) ) {
1273 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1274 TALLOC_FREE(new_acct );
1275 return NT_STATUS_ACCESS_DENIED;
1278 /* add the new account and lock it */
1279 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1283 interim_account = True;
1285 if ( tdb_lock_bystring_with_timeout(tdbsam, newname, 30) == -1 ) {
1289 /* Rename the posix user. Follow the semantics of _samr_create_user()
1290 so that we lower case the posix name but preserve the case in passdb */
1292 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1293 strlower_m( oldname_lower );
1295 fstrcpy( newname_lower, newname );
1296 strlower_m( newname_lower );
1298 rename_script = talloc_string_sub2(ctx,
1305 if (!rename_script) {
1308 rename_script = talloc_string_sub2(ctx,
1315 if (!rename_script) {
1318 rename_ret = smbrun(rename_script, NULL);
1320 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
1321 rename_script, rename_ret));
1323 if (rename_ret == 0) {
1324 smb_nscd_flush_user_cache();
1331 /* rewrite the rid->username record */
1333 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1336 interim_account = False;
1337 tdb_unlock_bystring( tdbsam, newname );
1339 tdb_delete_samacct_only( old_acct );
1343 TALLOC_FREE(new_acct );
1344 return NT_STATUS_OK;
1348 if (interim_account) {
1349 tdb_unlock_bystring(tdbsam, newname);
1350 tdb_delete_samacct_only(new_acct);
1356 TALLOC_FREE(new_acct);
1358 return NT_STATUS_ACCESS_DENIED;
1361 static bool tdbsam_rid_algorithm(struct pdb_methods *methods)
1367 * Historically, winbind was responsible for allocating RIDs, so the next RID
1368 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1369 * but for compatibility reasons we still keep the the next RID counter in
1370 * winbindd_idmap.tdb.
1373 /*****************************************************************************
1374 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1375 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1376 winbind completely and store the RID counter in passdb.tdb.
1378 Dont' fully initialize with the HWM values, if it's new, we're only
1379 interested in the RID counter.
1380 *****************************************************************************/
1382 static bool init_idmap_tdb(TDB_CONTEXT *tdb)
1386 if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
1387 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1391 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1393 if (version == -1) {
1394 /* No key found, must be a new db */
1395 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1396 IDMAP_VERSION) != 0) {
1397 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1398 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1401 version = IDMAP_VERSION;
1404 if (version != IDMAP_VERSION) {
1405 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1406 "start winbind once\n", IDMAP_VERSION, version));
1407 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1411 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1415 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1421 tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
1422 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1425 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1429 if (!init_idmap_tdb(tdb)) {
1430 DEBUG(1, ("Could not init idmap\n"));
1434 rid = BASE_RID; /* Default if not set */
1436 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1437 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1445 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1446 smb_panic("tdb_close(idmap_tdb) failed");
1452 struct tdbsam_search_state {
1453 struct pdb_methods *methods;
1454 uint32_t acct_flags;
1462 static int tdbsam_collect_rids(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data,
1465 struct tdbsam_search_state *state = talloc_get_type_abort(
1466 private_data, struct tdbsam_search_state);
1467 size_t prefixlen = strlen(RIDPREFIX);
1470 if ((key.dsize < prefixlen)
1471 || (strncmp((char *)key.dptr, RIDPREFIX, prefixlen))) {
1475 rid = strtoul((char *)key.dptr+prefixlen, NULL, 16);
1477 ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1478 &state->array_size);
1483 static void tdbsam_search_end(struct pdb_search *search)
1485 struct tdbsam_search_state *state = talloc_get_type_abort(
1486 search->private_data, struct tdbsam_search_state);
1490 static bool tdbsam_search_next_entry(struct pdb_search *search,
1491 struct samr_displayentry *entry)
1493 struct tdbsam_search_state *state = talloc_get_type_abort(
1494 search->private_data, struct tdbsam_search_state);
1495 struct samu *user = NULL;
1501 user = samu_new(talloc_tos());
1503 DEBUG(0, ("samu_new failed\n"));
1507 if (state->current == state->num_rids) {
1511 rid = state->rids[state->current++];
1513 status = tdbsam_getsampwrid(state->methods, user, rid);
1515 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1517 * Someone has deleted that user since we listed the RIDs
1522 if (!NT_STATUS_IS_OK(status)) {
1523 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1524 nt_errstr(status)));
1529 if ((state->acct_flags != 0) &&
1530 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1534 entry->acct_flags = pdb_get_acct_ctrl(user);
1536 entry->account_name = talloc_strdup(
1537 search->mem_ctx, pdb_get_username(user));
1538 entry->fullname = talloc_strdup(
1539 search->mem_ctx, pdb_get_fullname(user));
1540 entry->description = talloc_strdup(
1541 search->mem_ctx, pdb_get_acct_desc(user));
1545 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1546 || (entry->description == NULL)) {
1547 DEBUG(0, ("talloc_strdup failed\n"));
1554 static bool tdbsam_search_users(struct pdb_methods *methods,
1555 struct pdb_search *search,
1558 struct tdbsam_search_state *state;
1560 if (!tdbsam_open(tdbsam_filename)) {
1561 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1566 state = TALLOC_ZERO_P(search->mem_ctx, struct tdbsam_search_state);
1567 if (state == NULL) {
1568 DEBUG(0, ("talloc failed\n"));
1571 state->acct_flags = acct_flags;
1572 state->methods = methods;
1574 tdb_traverse(tdbsam, tdbsam_collect_rids, state);
1578 search->private_data = state;
1579 search->next_entry = tdbsam_search_next_entry;
1580 search->search_end = tdbsam_search_end;
1585 /*********************************************************************
1586 Initialize the tdb sam backend. Setup the dispath table of methods,
1587 open the tdb, etc...
1588 *********************************************************************/
1590 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1593 char *tdbfile = NULL;
1594 const char *pfile = location;
1596 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1600 (*pdb_method)->name = "tdbsam";
1602 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1603 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1604 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1605 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1606 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1607 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1608 (*pdb_method)->search_users = tdbsam_search_users;
1610 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1611 (*pdb_method)->new_rid = tdbsam_new_rid;
1613 /* save the path for later */
1616 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1617 PASSDB_FILE_NAME) < 0) {
1618 return NT_STATUS_NO_MEMORY;
1622 tdbsam_filename = SMB_STRDUP(pfile);
1623 if (!tdbsam_filename) {
1624 return NT_STATUS_NO_MEMORY;
1628 /* no private data */
1630 (*pdb_method)->private_data = NULL;
1631 (*pdb_method)->free_private_data = NULL;
1633 return NT_STATUS_OK;
1636 NTSTATUS pdb_tdbsam_init(void)
1638 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);