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 ((char *)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, lp_logon_home()),
177 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
179 pdb_set_dir_drive(sampass,
180 talloc_sub_basic(sampass, username, lp_logon_drive()),
185 pdb_set_logon_script(sampass, logon_script, PDB_SET);
187 pdb_set_logon_script(sampass,
188 talloc_sub_basic(sampass, username, lp_logon_script()),
193 pdb_set_profile_path(sampass, profile_path, PDB_SET);
195 pdb_set_profile_path(sampass,
196 talloc_sub_basic(sampass, username, lp_logon_path()),
200 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
201 pdb_set_workstations(sampass, workstations, PDB_SET);
202 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
204 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
205 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
211 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
212 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
218 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
219 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
220 pdb_set_hours_len(sampass, hours_len, PDB_SET);
221 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
222 pdb_set_logon_count(sampass, logon_count, PDB_SET);
223 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
224 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
225 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
226 pdb_set_hours(sampass, hours, PDB_SET);
232 SAFE_FREE(nt_username);
235 SAFE_FREE(dir_drive);
236 SAFE_FREE(logon_script);
237 SAFE_FREE(profile_path);
238 SAFE_FREE(acct_desc);
239 SAFE_FREE(workstations);
240 SAFE_FREE(munged_dial);
241 SAFE_FREE(unknown_str);
242 SAFE_FREE(lm_pw_ptr);
243 SAFE_FREE(nt_pw_ptr);
249 /*********************************************************************
250 *********************************************************************/
252 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
255 /* times are stored as 32bit integer
256 take care on system with 64bit wide time_t
263 pass_can_change_time,
264 pass_must_change_time;
265 char *username = NULL;
267 char *nt_username = NULL;
268 char *dir_drive = NULL;
269 char *unknown_str = NULL;
270 char *munged_dial = NULL;
271 char *fullname = NULL;
272 char *homedir = NULL;
273 char *logon_script = NULL;
274 char *profile_path = NULL;
275 char *acct_desc = NULL;
276 char *workstations = NULL;
277 uint32 username_len, domain_len, nt_username_len,
278 dir_drive_len, unknown_str_len, munged_dial_len,
279 fullname_len, homedir_len, logon_script_len,
280 profile_path_len, acct_desc_len, workstations_len;
282 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
283 uint16 acct_ctrl, logon_divs;
284 uint16 bad_password_count, logon_count;
286 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
288 uint32 lm_pw_len, nt_pw_len, hourslen;
291 if(sampass == NULL || buf == NULL) {
292 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
296 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
298 /* unpack the buffer into variables */
299 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
301 &logoff_time, /* d */
302 &kickoff_time, /* d */
303 /* Change from V0 is addition of bad_password_time field. */
304 &bad_password_time, /* d */
305 &pass_last_set_time, /* d */
306 &pass_can_change_time, /* d */
307 &pass_must_change_time, /* d */
308 &username_len, &username, /* B */
309 &domain_len, &domain, /* B */
310 &nt_username_len, &nt_username, /* B */
311 &fullname_len, &fullname, /* B */
312 &homedir_len, &homedir, /* B */
313 &dir_drive_len, &dir_drive, /* B */
314 &logon_script_len, &logon_script, /* B */
315 &profile_path_len, &profile_path, /* B */
316 &acct_desc_len, &acct_desc, /* B */
317 &workstations_len, &workstations, /* B */
318 &unknown_str_len, &unknown_str, /* B */
319 &munged_dial_len, &munged_dial, /* B */
322 &lm_pw_len, &lm_pw_ptr, /* B */
323 &nt_pw_len, &nt_pw_ptr, /* B */
328 &hourslen, &hours, /* B */
329 &bad_password_count, /* w */
330 &logon_count, /* w */
333 if (len == (uint32) -1) {
338 pdb_set_logon_time(sampass, logon_time, PDB_SET);
339 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
340 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
342 /* Change from V0 is addition of bad_password_time field. */
343 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
344 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
345 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
346 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
348 pdb_set_username(sampass, username, PDB_SET);
349 pdb_set_domain(sampass, domain, PDB_SET);
350 pdb_set_nt_username(sampass, nt_username, PDB_SET);
351 pdb_set_fullname(sampass, fullname, PDB_SET);
354 pdb_set_homedir(sampass, homedir, PDB_SET);
357 pdb_set_homedir(sampass,
358 talloc_sub_basic(sampass, username, lp_logon_home()),
363 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
365 pdb_set_dir_drive(sampass,
366 talloc_sub_basic(sampass, username, lp_logon_drive()),
371 pdb_set_logon_script(sampass, logon_script, PDB_SET);
373 pdb_set_logon_script(sampass,
374 talloc_sub_basic(sampass, username, lp_logon_script()),
379 pdb_set_profile_path(sampass, profile_path, PDB_SET);
381 pdb_set_profile_path(sampass,
382 talloc_sub_basic(sampass, username, lp_logon_path()),
386 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
387 pdb_set_workstations(sampass, workstations, PDB_SET);
388 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
390 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
391 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
397 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
398 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
404 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
406 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
407 pdb_set_hours_len(sampass, hours_len, PDB_SET);
408 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
409 pdb_set_logon_count(sampass, logon_count, PDB_SET);
410 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
411 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
412 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
413 pdb_set_hours(sampass, hours, PDB_SET);
419 SAFE_FREE(nt_username);
422 SAFE_FREE(dir_drive);
423 SAFE_FREE(logon_script);
424 SAFE_FREE(profile_path);
425 SAFE_FREE(acct_desc);
426 SAFE_FREE(workstations);
427 SAFE_FREE(munged_dial);
428 SAFE_FREE(unknown_str);
429 SAFE_FREE(lm_pw_ptr);
430 SAFE_FREE(nt_pw_ptr);
436 BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
439 /* times are stored as 32bit integer
440 take care on system with 64bit wide time_t
447 pass_can_change_time,
448 pass_must_change_time;
449 char *username = NULL;
451 char *nt_username = NULL;
452 char *dir_drive = NULL;
453 char *unknown_str = NULL;
454 char *munged_dial = NULL;
455 char *fullname = NULL;
456 char *homedir = NULL;
457 char *logon_script = NULL;
458 char *profile_path = NULL;
459 char *acct_desc = NULL;
460 char *workstations = NULL;
461 uint32 username_len, domain_len, nt_username_len,
462 dir_drive_len, unknown_str_len, munged_dial_len,
463 fullname_len, homedir_len, logon_script_len,
464 profile_path_len, acct_desc_len, workstations_len;
466 uint32 user_rid, group_rid, hours_len, unknown_6;
467 uint16 acct_ctrl, logon_divs;
468 uint16 bad_password_count, logon_count;
470 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
472 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
473 uint32 pwHistLen = 0;
476 BOOL expand_explicit = lp_passdb_expand_explicit();
478 if(sampass == NULL || buf == NULL) {
479 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
483 /* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
485 /* unpack the buffer into variables */
486 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
488 &logoff_time, /* d */
489 &kickoff_time, /* d */
490 &bad_password_time, /* d */
491 &pass_last_set_time, /* d */
492 &pass_can_change_time, /* d */
493 &pass_must_change_time, /* d */
494 &username_len, &username, /* B */
495 &domain_len, &domain, /* B */
496 &nt_username_len, &nt_username, /* B */
497 &fullname_len, &fullname, /* B */
498 &homedir_len, &homedir, /* B */
499 &dir_drive_len, &dir_drive, /* B */
500 &logon_script_len, &logon_script, /* B */
501 &profile_path_len, &profile_path, /* B */
502 &acct_desc_len, &acct_desc, /* B */
503 &workstations_len, &workstations, /* B */
504 &unknown_str_len, &unknown_str, /* B */
505 &munged_dial_len, &munged_dial, /* B */
508 &lm_pw_len, &lm_pw_ptr, /* B */
509 &nt_pw_len, &nt_pw_ptr, /* B */
510 /* Change from V1 is addition of password history field. */
511 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
513 /* Also "remove_me" field was removed. */
516 &hourslen, &hours, /* B */
517 &bad_password_count, /* w */
518 &logon_count, /* w */
521 if (len == (uint32) -1) {
526 pdb_set_logon_time(sampass, logon_time, PDB_SET);
527 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
528 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
529 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
530 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
531 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
532 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
534 pdb_set_username(sampass, username, PDB_SET);
535 pdb_set_domain(sampass, domain, PDB_SET);
536 pdb_set_nt_username(sampass, nt_username, PDB_SET);
537 pdb_set_fullname(sampass, fullname, PDB_SET);
540 fstrcpy( tmpstring, homedir );
541 if (expand_explicit) {
542 standard_sub_basic( username, tmpstring,
545 pdb_set_homedir(sampass, tmpstring, PDB_SET);
548 pdb_set_homedir(sampass,
549 talloc_sub_basic(sampass, username, lp_logon_home()),
554 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
556 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
559 fstrcpy( tmpstring, logon_script );
560 if (expand_explicit) {
561 standard_sub_basic( username, tmpstring,
564 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
567 pdb_set_logon_script(sampass,
568 talloc_sub_basic(sampass, username, lp_logon_script()),
573 fstrcpy( tmpstring, profile_path );
574 if (expand_explicit) {
575 standard_sub_basic( username, tmpstring,
578 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
581 pdb_set_profile_path(sampass,
582 talloc_sub_basic(sampass, username, lp_logon_path()),
586 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
587 pdb_set_workstations(sampass, workstations, PDB_SET);
588 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
590 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
591 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
597 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
598 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
604 /* Change from V1 is addition of password history field. */
605 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
607 uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
612 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
613 if (nt_pw_hist_ptr && nt_pw_hist_len) {
615 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
616 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
617 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
618 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
619 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
620 PW_HISTORY_ENTRY_LEN);
623 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
630 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
633 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
634 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
635 pdb_set_hours_len(sampass, hours_len, PDB_SET);
636 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
637 pdb_set_logon_count(sampass, logon_count, PDB_SET);
638 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
639 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
640 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
641 pdb_set_hours(sampass, hours, PDB_SET);
647 SAFE_FREE(nt_username);
650 SAFE_FREE(dir_drive);
651 SAFE_FREE(logon_script);
652 SAFE_FREE(profile_path);
653 SAFE_FREE(acct_desc);
654 SAFE_FREE(workstations);
655 SAFE_FREE(munged_dial);
656 SAFE_FREE(unknown_str);
657 SAFE_FREE(lm_pw_ptr);
658 SAFE_FREE(nt_pw_ptr);
659 SAFE_FREE(nt_pw_hist_ptr);
666 /**********************************************************************
667 Intialize a struct samu struct from a BYTE buffer of size len
668 *********************************************************************/
670 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
672 return init_sam_from_buffer_v3(sampass, buf, buflen);
675 /**********************************************************************
676 Intialize a BYTE buffer from a struct samu struct
677 *********************************************************************/
679 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
681 return init_buffer_from_sam_v3(buf, sampass, size_only);
684 /**********************************************************************
685 Intialize a BYTE buffer from a struct samu struct
686 *********************************************************************/
688 static BOOL tdbsam_convert(int32 from)
690 const char *vstring = TDBSAM_VERSION_STRING;
691 const char *prefix = USERPREFIX;
692 TDB_DATA data, key, old_key;
696 /* handle a Samba upgrade */
697 tdb_lock_bystring(tdbsam, vstring, 0);
699 /* Enumerate all records and convert them */
700 key = tdb_firstkey(tdbsam);
704 /* skip all non-USER entries (eg. RIDs) */
705 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
707 /* increment to next in line */
708 key = tdb_nextkey(tdbsam, key);
709 SAFE_FREE(old_key.dptr);
713 struct samu *user = NULL;
715 /* read from tdbsam */
716 data = tdb_fetch(tdbsam, key);
718 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
722 /* unpack the buffer from the former format */
723 if ( !(user = samu_new( NULL )) ) {
724 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
725 SAFE_FREE( data.dptr );
728 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
731 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
734 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
737 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
740 ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
743 /* unknown tdbsam version */
747 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
748 SAFE_FREE(data.dptr);
753 /* We're finished with the old data. */
754 SAFE_FREE(data.dptr);
756 /* pack from the buffer into the new format */
758 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
759 data.dsize = init_buffer_from_sam (&buf, user, False);
762 if ( data.dsize == -1 ) {
763 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
766 data.dptr = (char *)buf;
768 /* Store the buffer inside the TDBSAM */
769 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
770 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
771 SAFE_FREE(data.dptr);
775 SAFE_FREE(data.dptr);
777 /* increment to next in line */
779 key = tdb_nextkey(tdbsam, key);
780 SAFE_FREE(old_key.dptr);
786 /* upgrade finished */
787 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
788 tdb_unlock_bystring(tdbsam, vstring);
793 /*********************************************************************
794 Open the tdbsam file based on the absolute path specified.
795 Uses a reference count to allow multiple open calls.
796 *********************************************************************/
798 static BOOL tdbsam_open( const char *name )
802 /* check if we are already open */
806 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
811 SMB_ASSERT( ref_count == 0 );
813 /* Try to open tdb passwd. Create a new one if necessary */
815 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
816 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
820 /* Check the version */
821 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
824 version = 0; /* Version not found, assume version 0 */
826 /* Compare the version */
827 if (version > TDBSAM_VERSION) {
828 /* Version more recent than the latest known */
829 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
835 if ( version < TDBSAM_VERSION ) {
836 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
837 version, TDBSAM_VERSION));
839 if ( !tdbsam_convert(version) ) {
840 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
845 DEBUG(3, ("TDBSAM converted successfully.\n"));
848 /* set the initial reference count */
852 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
857 /****************************************************************************
858 wrapper atound tdb_close() to handle the reference count
859 ****************************************************************************/
861 void tdbsam_close( void )
865 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
867 SMB_ASSERT(ref_count >= 0 );
869 if ( ref_count == 0 ) {
877 /****************************************************************************
878 creates a list of user keys
879 ****************************************************************************/
881 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
883 const char *prefix = USERPREFIX;
884 int prefixlen = strlen (prefix);
885 struct pwent_list *ptr;
887 if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
888 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
889 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
891 /* just return 0 and let the traversal continue */
896 /* save a copy of the key */
898 ptr->key.dptr = memdup( key.dptr, key.dsize );
899 ptr->key.dsize = key.dsize;
901 DLIST_ADD( tdbsam_pwent_list, ptr );
909 /***************************************************************
910 Open the TDB passwd database for SAM account enumeration.
911 Save a list of user keys for iteration.
912 ****************************************************************/
914 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
916 if ( !tdbsam_open( tdbsam_filename ) ) {
917 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
918 return NT_STATUS_ACCESS_DENIED;
921 tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
922 pwent_initialized = True;
928 /***************************************************************
929 End enumeration of the TDB passwd list.
930 ****************************************************************/
932 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
934 struct pwent_list *ptr, *ptr_next;
936 /* close the tdb only if we have a valid pwent state */
938 if ( pwent_initialized ) {
939 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
943 /* clear out any remaining entries in the list */
945 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
946 ptr_next = ptr->next;
947 DLIST_REMOVE( tdbsam_pwent_list, ptr );
948 SAFE_FREE( ptr->key.dptr);
952 pwent_initialized = False;
955 /*****************************************************************
956 Get one struct samu from the TDB (next in line)
957 *****************************************************************/
959 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
961 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
963 struct pwent_list *pkey;
966 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
970 if ( !tdbsam_pwent_list ) {
971 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
975 /* pull the next entry */
977 pkey = tdbsam_pwent_list;
978 DLIST_REMOVE( tdbsam_pwent_list, pkey );
980 data = tdb_fetch(tdbsam, pkey->key);
982 SAFE_FREE( pkey->key.dptr);
986 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
990 if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
991 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
994 SAFE_FREE( data.dptr );
999 /******************************************************************
1000 Lookup a name in the SAM TDB
1001 ******************************************************************/
1003 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
1011 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
1012 return NT_STATUS_NO_MEMORY;
1015 /* Data is stored in all lower-case */
1016 fstrcpy(name, sname);
1019 /* set search key */
1020 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1022 key.dsize = strlen(keystr) + 1;
1024 /* open the database */
1026 if ( !tdbsam_open( tdbsam_filename ) ) {
1027 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1028 return NT_STATUS_ACCESS_DENIED;
1031 /* get the record */
1033 data = tdb_fetch(tdbsam, key);
1035 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
1036 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1037 DEBUGADD(5, (" Key: %s\n", keystr));
1038 result = NT_STATUS_NO_SUCH_USER;
1042 /* unpack the buffer */
1044 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
1045 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1046 SAFE_FREE(data.dptr);
1047 result = NT_STATUS_NO_MEMORY;
1051 result = NT_STATUS_OK;
1054 SAFE_FREE(data.dptr);
1060 /***************************************************************************
1062 **************************************************************************/
1064 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
1066 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1072 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
1076 /* set search key */
1078 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1080 key.dsize = strlen (keystr) + 1;
1082 /* open the database */
1084 if ( !tdbsam_open( tdbsam_filename ) ) {
1085 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1086 return NT_STATUS_ACCESS_DENIED;
1089 /* get the record */
1091 data = tdb_fetch (tdbsam, key);
1093 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
1094 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1095 nt_status = NT_STATUS_UNSUCCESSFUL;
1099 fstrcpy(name, data.dptr);
1100 SAFE_FREE(data.dptr);
1102 nt_status = tdbsam_getsampwnam (my_methods, user, name);
1112 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
1116 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
1117 return NT_STATUS_UNSUCCESSFUL;
1119 return tdbsam_getsampwrid(my_methods, user, rid);
1122 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
1128 fstrcpy(name, pdb_get_username(sam_pass));
1131 /* set the search key */
1133 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1135 key.dsize = strlen (keystr) + 1;
1137 /* it's outaa here! 8^) */
1139 if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
1140 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1141 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1148 /***************************************************************************
1149 Delete a struct samu records for the username and RID key
1150 ****************************************************************************/
1152 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
1154 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1160 /* make sure we have an open handle to the tdb. Should have happened
1161 at module initialization time */
1164 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
1165 return NT_STATUS_NO_SUCH_USER;
1168 fstrcpy(name, pdb_get_username(sam_pass));
1171 /* set the search key */
1173 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1175 key.dsize = strlen (keystr) + 1;
1177 rid = pdb_get_user_rid(sam_pass);
1179 /* open the database */
1181 if ( !tdbsam_open( tdbsam_filename ) ) {
1182 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1183 return NT_STATUS_ACCESS_DENIED;
1186 /* it's outaa here! 8^) */
1188 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1189 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1190 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1191 nt_status = NT_STATUS_UNSUCCESSFUL;
1195 /* set the search key */
1197 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1199 key.dsize = strlen (keystr) + 1;
1201 /* it's outaa here! 8^) */
1203 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1204 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
1205 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1206 nt_status = NT_STATUS_UNSUCCESSFUL;
1210 nt_status = NT_STATUS_OK;
1219 /***************************************************************************
1220 Update the TDB SAM account record only
1221 Assumes that the tdbsam is already open
1222 ****************************************************************************/
1223 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
1231 /* copy the struct samu struct into a BYTE buffer for storage */
1233 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1234 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1238 data.dptr = (char *)buf;
1240 fstrcpy(name, pdb_get_username(newpwd));
1243 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1244 flag == TDB_INSERT ? "(new) " : "", name,
1245 pdb_get_user_rid(newpwd)));
1247 /* setup the USER index key */
1248 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1250 key.dsize = strlen(keystr) + 1;
1252 /* add the account */
1254 if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
1255 DEBUG(0, ("Unable to modify passwd TDB!"));
1256 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1257 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1270 /***************************************************************************
1271 Update the TDB SAM RID record only
1272 Assumes that the tdbsam is already open
1273 ****************************************************************************/
1274 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1280 fstrcpy(name, pdb_get_username(newpwd));
1283 /* setup RID data */
1284 data.dsize = strlen(name) + 1;
1287 /* setup the RID index key */
1288 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1290 key.dsize = strlen (keystr) + 1;
1292 /* add the reference */
1293 if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
1294 DEBUG(0, ("Unable to modify TDB passwd !"));
1295 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1296 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1304 /***************************************************************************
1306 ****************************************************************************/
1308 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1313 /* invalidate the existing TDB iterator if it is open */
1315 tdbsam_endsampwent( my_methods );
1317 if ( !pdb_get_group_rid(newpwd) ) {
1318 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1319 "without a primary group RID\n", pdb_get_username(newpwd)));
1323 if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
1324 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1328 /* open the database */
1330 if ( !tdbsam_open( tdbsam_filename ) ) {
1331 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1335 if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1346 /***************************************************************************
1347 Modifies an existing struct samu
1348 ****************************************************************************/
1350 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1352 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1353 return NT_STATUS_UNSUCCESSFUL;
1355 return NT_STATUS_OK;
1358 /***************************************************************************
1359 Adds an existing struct samu
1360 ****************************************************************************/
1362 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1364 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1365 return NT_STATUS_UNSUCCESSFUL;
1367 return NT_STATUS_OK;
1370 /***************************************************************************
1371 Renames a struct samu
1372 - check for the posix user/rename user script
1373 - Add and lock the new user record
1374 - rename the posix user
1375 - rewrite the rid->username record
1376 - delete the old user
1377 - unlock the new user record
1378 ***************************************************************************/
1379 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1380 struct samu *old_acct,
1381 const char *newname)
1383 struct samu *new_acct = NULL;
1384 pstring rename_script;
1385 BOOL interim_account = False;
1388 /* make sure we have an open handle to the tdb. Should have happened
1389 at module initialization time */
1392 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
1393 return NT_STATUS_NO_SUCH_USER;
1396 /* can't do anything without an external script */
1398 pstrcpy(rename_script, lp_renameuser_script() );
1399 if ( ! *rename_script )
1400 return NT_STATUS_ACCESS_DENIED;
1402 /* invalidate the existing TDB iterator if it is open */
1404 tdbsam_endsampwent( my_methods );
1406 if ( !(new_acct = samu_new( NULL )) ) {
1407 return NT_STATUS_NO_MEMORY;
1410 if ( !pdb_copy_sam_account(new_acct, old_acct)
1411 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1413 TALLOC_FREE(new_acct );
1414 return NT_STATUS_NO_MEMORY;
1417 /* open the database */
1419 if ( !tdbsam_open( tdbsam_filename ) ) {
1420 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1421 TALLOC_FREE(new_acct );
1422 return NT_STATUS_ACCESS_DENIED;
1425 /* add the new account and lock it */
1427 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) )
1432 interim_account = True;
1434 if ( tdb_lock_bystring(tdbsam, newname, 30) == -1 ) {
1438 /* rename the posix user */
1439 string_sub2(rename_script, "%unew", newname, sizeof(pstring),
1441 string_sub2(rename_script, "%uold", pdb_get_username(old_acct),
1442 sizeof(pstring), True, False, True);
1443 rename_ret = smbrun(rename_script, NULL);
1445 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1450 /* rewrite the rid->username record */
1452 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) )
1454 interim_account = False;
1455 tdb_unlock_bystring( tdbsam, newname );
1457 tdb_delete_samacct_only( old_acct );
1461 TALLOC_FREE(new_acct );
1462 return NT_STATUS_OK;
1466 if (interim_account) {
1467 tdb_unlock_bystring(tdbsam, newname);
1468 tdb_delete_samacct_only(new_acct);
1474 TALLOC_FREE(new_acct);
1476 return NT_STATUS_ACCESS_DENIED;
1479 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1485 * Historically, winbind was responsible for allocating RIDs, so the next RID
1486 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1487 * but for compatibility reasons we still keep the the next RID counter in
1488 * winbindd_idmap.tdb.
1491 /*****************************************************************************
1492 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1493 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1494 winbind completely and store the RID counter in passdb.tdb.
1496 Dont' fully initialize with the HWM values, if it's new, we're only
1497 interested in the RID counter.
1498 *****************************************************************************/
1500 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1504 if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
1505 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1509 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1511 if (version == -1) {
1512 /* No key found, must be a new db */
1513 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1514 IDMAP_VERSION) != 0) {
1515 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1516 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1519 version = IDMAP_VERSION;
1522 if (version != IDMAP_VERSION) {
1523 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1524 "start winbind once\n", IDMAP_VERSION, version));
1525 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1529 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1533 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1539 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1540 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1543 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1547 if (!init_idmap_tdb(tdb)) {
1548 DEBUG(1, ("Could not init idmap\n"));
1552 rid = BASE_RID; /* Default if not set */
1554 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1555 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1563 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1564 smb_panic("tdb_close(idmap_tdb) failed\n");
1570 /*********************************************************************
1571 Initialize the tdb sam backend. Setup the dispath table of methods,
1572 open the tdb, etc...
1573 *********************************************************************/
1575 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1579 const char *pfile = location;
1581 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1585 (*pdb_method)->name = "tdbsam";
1587 (*pdb_method)->setsampwent = tdbsam_setsampwent;
1588 (*pdb_method)->endsampwent = tdbsam_endsampwent;
1589 (*pdb_method)->getsampwent = tdbsam_getsampwent;
1590 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1591 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1592 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1593 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1594 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1595 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1597 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1598 (*pdb_method)->new_rid = tdbsam_new_rid;
1600 /* save the path for later */
1603 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1606 pstrcpy( tdbsam_filename, pfile );
1608 /* no private data */
1610 (*pdb_method)->private_data = NULL;
1611 (*pdb_method)->free_private_data = NULL;
1613 return NT_STATUS_OK;
1616 NTSTATUS pdb_tdbsam_init(void)
1618 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);