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_group_sid_from_rid(sampass, group_rid, PDB_SET);
221 pdb_set_hours_len(sampass, hours_len, PDB_SET);
222 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
223 pdb_set_logon_count(sampass, logon_count, PDB_SET);
224 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
225 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
226 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
227 pdb_set_hours(sampass, hours, PDB_SET);
233 SAFE_FREE(nt_username);
236 SAFE_FREE(dir_drive);
237 SAFE_FREE(logon_script);
238 SAFE_FREE(profile_path);
239 SAFE_FREE(acct_desc);
240 SAFE_FREE(workstations);
241 SAFE_FREE(munged_dial);
242 SAFE_FREE(unknown_str);
243 SAFE_FREE(lm_pw_ptr);
244 SAFE_FREE(nt_pw_ptr);
250 /*********************************************************************
251 *********************************************************************/
253 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
256 /* times are stored as 32bit integer
257 take care on system with 64bit wide time_t
264 pass_can_change_time,
265 pass_must_change_time;
266 char *username = NULL;
268 char *nt_username = NULL;
269 char *dir_drive = NULL;
270 char *unknown_str = NULL;
271 char *munged_dial = NULL;
272 char *fullname = NULL;
273 char *homedir = NULL;
274 char *logon_script = NULL;
275 char *profile_path = NULL;
276 char *acct_desc = NULL;
277 char *workstations = NULL;
278 uint32 username_len, domain_len, nt_username_len,
279 dir_drive_len, unknown_str_len, munged_dial_len,
280 fullname_len, homedir_len, logon_script_len,
281 profile_path_len, acct_desc_len, workstations_len;
283 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
284 uint16 acct_ctrl, logon_divs;
285 uint16 bad_password_count, logon_count;
287 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
289 uint32 lm_pw_len, nt_pw_len, hourslen;
292 if(sampass == NULL || buf == NULL) {
293 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
297 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
299 /* unpack the buffer into variables */
300 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
302 &logoff_time, /* d */
303 &kickoff_time, /* d */
304 /* Change from V0 is addition of bad_password_time field. */
305 &bad_password_time, /* d */
306 &pass_last_set_time, /* d */
307 &pass_can_change_time, /* d */
308 &pass_must_change_time, /* d */
309 &username_len, &username, /* B */
310 &domain_len, &domain, /* B */
311 &nt_username_len, &nt_username, /* B */
312 &fullname_len, &fullname, /* B */
313 &homedir_len, &homedir, /* B */
314 &dir_drive_len, &dir_drive, /* B */
315 &logon_script_len, &logon_script, /* B */
316 &profile_path_len, &profile_path, /* B */
317 &acct_desc_len, &acct_desc, /* B */
318 &workstations_len, &workstations, /* B */
319 &unknown_str_len, &unknown_str, /* B */
320 &munged_dial_len, &munged_dial, /* B */
323 &lm_pw_len, &lm_pw_ptr, /* B */
324 &nt_pw_len, &nt_pw_ptr, /* B */
329 &hourslen, &hours, /* B */
330 &bad_password_count, /* w */
331 &logon_count, /* w */
334 if (len == (uint32) -1) {
339 pdb_set_logon_time(sampass, logon_time, PDB_SET);
340 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
341 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
343 /* Change from V0 is addition of bad_password_time field. */
344 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
345 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
346 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
347 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
349 pdb_set_username(sampass, username, PDB_SET);
350 pdb_set_domain(sampass, domain, PDB_SET);
351 pdb_set_nt_username(sampass, nt_username, PDB_SET);
352 pdb_set_fullname(sampass, fullname, PDB_SET);
355 pdb_set_homedir(sampass, homedir, PDB_SET);
358 pdb_set_homedir(sampass,
359 talloc_sub_basic(sampass, username, lp_logon_home()),
364 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
366 pdb_set_dir_drive(sampass,
367 talloc_sub_basic(sampass, username, lp_logon_drive()),
372 pdb_set_logon_script(sampass, logon_script, PDB_SET);
374 pdb_set_logon_script(sampass,
375 talloc_sub_basic(sampass, username, lp_logon_script()),
380 pdb_set_profile_path(sampass, profile_path, PDB_SET);
382 pdb_set_profile_path(sampass,
383 talloc_sub_basic(sampass, username, lp_logon_path()),
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 ((char *)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( tmpstring, homedir );
543 if (expand_explicit) {
544 standard_sub_basic( username, tmpstring,
547 pdb_set_homedir(sampass, tmpstring, PDB_SET);
550 pdb_set_homedir(sampass,
551 talloc_sub_basic(sampass, username, lp_logon_home()),
556 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
558 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
561 fstrcpy( tmpstring, logon_script );
562 if (expand_explicit) {
563 standard_sub_basic( username, tmpstring,
566 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
569 pdb_set_logon_script(sampass,
570 talloc_sub_basic(sampass, username, lp_logon_script()),
575 fstrcpy( tmpstring, profile_path );
576 if (expand_explicit) {
577 standard_sub_basic( username, tmpstring,
580 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
583 pdb_set_profile_path(sampass,
584 talloc_sub_basic(sampass, username, lp_logon_path()),
588 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
589 pdb_set_workstations(sampass, workstations, PDB_SET);
590 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
592 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
593 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
599 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
600 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
606 /* Change from V1 is addition of password history field. */
607 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
609 uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
614 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
615 if (nt_pw_hist_ptr && nt_pw_hist_len) {
617 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
618 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
619 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
620 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
621 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
622 PW_HISTORY_ENTRY_LEN);
625 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
632 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
635 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
636 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
637 pdb_set_hours_len(sampass, hours_len, PDB_SET);
638 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
639 pdb_set_logon_count(sampass, logon_count, PDB_SET);
640 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
641 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
642 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
643 pdb_set_hours(sampass, hours, PDB_SET);
649 SAFE_FREE(nt_username);
652 SAFE_FREE(dir_drive);
653 SAFE_FREE(logon_script);
654 SAFE_FREE(profile_path);
655 SAFE_FREE(acct_desc);
656 SAFE_FREE(workstations);
657 SAFE_FREE(munged_dial);
658 SAFE_FREE(unknown_str);
659 SAFE_FREE(lm_pw_ptr);
660 SAFE_FREE(nt_pw_ptr);
661 SAFE_FREE(nt_pw_hist_ptr);
668 /**********************************************************************
669 Intialize a struct samu struct from a BYTE buffer of size len
670 *********************************************************************/
672 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
674 return init_sam_from_buffer_v3(sampass, buf, buflen);
677 /**********************************************************************
678 Intialize a BYTE buffer from a struct samu struct
679 *********************************************************************/
681 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
683 return init_buffer_from_sam_v3(buf, sampass, size_only);
686 /**********************************************************************
687 Intialize a BYTE buffer from a struct samu struct
688 *********************************************************************/
690 static BOOL tdbsam_convert(int32 from)
692 const char *vstring = TDBSAM_VERSION_STRING;
693 const char *prefix = USERPREFIX;
694 TDB_DATA data, key, old_key;
698 /* handle a Samba upgrade */
699 tdb_lock_bystring(tdbsam, vstring);
701 /* Enumerate all records and convert them */
702 key = tdb_firstkey(tdbsam);
706 /* skip all non-USER entries (eg. RIDs) */
707 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
709 /* increment to next in line */
710 key = tdb_nextkey(tdbsam, key);
711 SAFE_FREE(old_key.dptr);
715 struct samu *user = NULL;
717 /* read from tdbsam */
718 data = tdb_fetch(tdbsam, key);
720 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
724 /* unpack the buffer from the former format */
725 if ( !(user = samu_new( NULL )) ) {
726 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
727 SAFE_FREE( data.dptr );
730 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
733 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
736 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
739 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
742 ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
745 /* unknown tdbsam version */
749 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
750 SAFE_FREE(data.dptr);
755 /* We're finished with the old data. */
756 SAFE_FREE(data.dptr);
758 /* pack from the buffer into the new format */
760 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
761 data.dsize = init_buffer_from_sam (&buf, user, False);
764 if ( data.dsize == -1 ) {
765 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
768 data.dptr = (char *)buf;
770 /* Store the buffer inside the TDBSAM */
771 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
772 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
773 SAFE_FREE(data.dptr);
777 SAFE_FREE(data.dptr);
779 /* increment to next in line */
781 key = tdb_nextkey(tdbsam, key);
782 SAFE_FREE(old_key.dptr);
788 /* upgrade finished */
789 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
790 tdb_unlock_bystring(tdbsam, vstring);
795 /*********************************************************************
796 Open the tdbsam file based on the absolute path specified.
797 Uses a reference count to allow multiple open calls.
798 *********************************************************************/
800 static BOOL tdbsam_open( const char *name )
804 /* check if we are already open */
808 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
813 SMB_ASSERT( ref_count == 0 );
815 /* Try to open tdb passwd. Create a new one if necessary */
817 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
818 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
822 /* set the initial reference count - must be done before tdbsam_convert
823 as that calls tdbsam_open()/tdbsam_close(). */
827 /* Check the version */
828 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
831 version = 0; /* Version not found, assume version 0 */
834 /* Compare the version */
835 if (version > TDBSAM_VERSION) {
836 /* Version more recent than the latest known */
837 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
844 if ( version < TDBSAM_VERSION ) {
845 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
846 version, TDBSAM_VERSION));
848 if ( !tdbsam_convert(version) ) {
849 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
855 DEBUG(3, ("TDBSAM converted successfully.\n"));
858 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
863 /****************************************************************************
864 wrapper atound tdb_close() to handle the reference count
865 ****************************************************************************/
867 void tdbsam_close( void )
871 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
873 SMB_ASSERT(ref_count >= 0 );
875 if ( ref_count == 0 ) {
883 /****************************************************************************
884 creates a list of user keys
885 ****************************************************************************/
887 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
889 const char *prefix = USERPREFIX;
890 int prefixlen = strlen (prefix);
891 struct pwent_list *ptr;
893 if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
894 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
895 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
897 /* just return 0 and let the traversal continue */
902 /* save a copy of the key */
904 ptr->key.dptr = memdup( key.dptr, key.dsize );
905 ptr->key.dsize = key.dsize;
907 DLIST_ADD( tdbsam_pwent_list, ptr );
915 /***************************************************************
916 Open the TDB passwd database for SAM account enumeration.
917 Save a list of user keys for iteration.
918 ****************************************************************/
920 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
922 if ( !tdbsam_open( tdbsam_filename ) ) {
923 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
924 return NT_STATUS_ACCESS_DENIED;
927 tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
928 pwent_initialized = True;
934 /***************************************************************
935 End enumeration of the TDB passwd list.
936 ****************************************************************/
938 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
940 struct pwent_list *ptr, *ptr_next;
942 /* close the tdb only if we have a valid pwent state */
944 if ( pwent_initialized ) {
945 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
949 /* clear out any remaining entries in the list */
951 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
952 ptr_next = ptr->next;
953 DLIST_REMOVE( tdbsam_pwent_list, ptr );
954 SAFE_FREE( ptr->key.dptr);
958 pwent_initialized = False;
961 /*****************************************************************
962 Get one struct samu from the TDB (next in line)
963 *****************************************************************/
965 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
967 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
969 struct pwent_list *pkey;
972 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
976 if ( !tdbsam_pwent_list ) {
977 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
981 /* pull the next entry */
983 pkey = tdbsam_pwent_list;
984 DLIST_REMOVE( tdbsam_pwent_list, pkey );
986 data = tdb_fetch(tdbsam, pkey->key);
988 SAFE_FREE( pkey->key.dptr);
992 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
996 if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
997 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1000 SAFE_FREE( data.dptr );
1002 return NT_STATUS_OK;
1005 /******************************************************************
1006 Lookup a name in the SAM TDB
1007 ******************************************************************/
1009 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
1016 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
1017 return NT_STATUS_NO_MEMORY;
1020 /* Data is stored in all lower-case */
1021 fstrcpy(name, sname);
1024 /* set search key */
1025 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1027 key.dsize = strlen(keystr) + 1;
1029 /* open the database */
1031 if ( !tdbsam_open( tdbsam_filename ) ) {
1032 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1033 return NT_STATUS_ACCESS_DENIED;
1036 /* get the record */
1038 data = tdb_fetch(tdbsam, key);
1040 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
1041 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1042 DEBUGADD(5, (" Key: %s\n", keystr));
1044 return NT_STATUS_NO_SUCH_USER;
1047 /* unpack the buffer */
1049 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
1050 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1051 SAFE_FREE(data.dptr);
1053 return NT_STATUS_NO_MEMORY;
1058 SAFE_FREE(data.dptr);
1061 return NT_STATUS_OK;
1064 /***************************************************************************
1066 **************************************************************************/
1068 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
1070 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1076 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
1080 /* set search key */
1082 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1084 key.dsize = strlen (keystr) + 1;
1086 /* open the database */
1088 if ( !tdbsam_open( tdbsam_filename ) ) {
1089 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1090 return NT_STATUS_ACCESS_DENIED;
1093 /* get the record */
1095 data = tdb_fetch (tdbsam, key);
1097 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
1098 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1099 nt_status = NT_STATUS_UNSUCCESSFUL;
1103 fstrcpy(name, data.dptr);
1104 SAFE_FREE(data.dptr);
1106 nt_status = tdbsam_getsampwnam (my_methods, user, name);
1116 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
1120 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
1121 return NT_STATUS_UNSUCCESSFUL;
1123 return tdbsam_getsampwrid(my_methods, user, rid);
1126 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
1132 fstrcpy(name, pdb_get_username(sam_pass));
1135 /* set the search key */
1137 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1139 key.dsize = strlen (keystr) + 1;
1141 /* it's outaa here! 8^) */
1143 if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
1144 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1145 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1152 /***************************************************************************
1153 Delete a struct samu records for the username and RID key
1154 ****************************************************************************/
1156 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
1158 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1164 /* open the database */
1166 if ( !tdbsam_open( tdbsam_filename ) ) {
1167 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1169 return NT_STATUS_ACCESS_DENIED;
1172 fstrcpy(name, pdb_get_username(sam_pass));
1175 /* set the search key */
1177 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1179 key.dsize = strlen (keystr) + 1;
1181 rid = pdb_get_user_rid(sam_pass);
1183 /* it's outaa here! 8^) */
1185 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1186 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1187 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1188 nt_status = NT_STATUS_UNSUCCESSFUL;
1192 /* set the search key */
1194 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1196 key.dsize = strlen (keystr) + 1;
1198 /* it's outaa here! 8^) */
1200 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1201 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
1202 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1203 nt_status = NT_STATUS_UNSUCCESSFUL;
1207 nt_status = NT_STATUS_OK;
1216 /***************************************************************************
1217 Update the TDB SAM account record only
1218 Assumes that the tdbsam is already open
1219 ****************************************************************************/
1220 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
1228 /* copy the struct samu struct into a BYTE buffer for storage */
1230 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1231 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1235 data.dptr = (char *)buf;
1237 fstrcpy(name, pdb_get_username(newpwd));
1240 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1241 flag == TDB_INSERT ? "(new) " : "", name,
1242 pdb_get_user_rid(newpwd)));
1244 /* setup the USER index key */
1245 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1247 key.dsize = strlen(keystr) + 1;
1249 /* add the account */
1251 if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
1252 DEBUG(0, ("Unable to modify passwd TDB!"));
1253 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1254 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1267 /***************************************************************************
1268 Update the TDB SAM RID record only
1269 Assumes that the tdbsam is already open
1270 ****************************************************************************/
1271 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1277 fstrcpy(name, pdb_get_username(newpwd));
1280 /* setup RID data */
1281 data.dsize = strlen(name) + 1;
1284 /* setup the RID index key */
1285 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1287 key.dsize = strlen (keystr) + 1;
1289 /* add the reference */
1290 if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
1291 DEBUG(0, ("Unable to modify TDB passwd !"));
1292 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1293 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1301 /***************************************************************************
1303 ****************************************************************************/
1305 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 ( !(user_rid = 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;
1387 /* can't do anything without an external script */
1389 pstrcpy(rename_script, lp_renameuser_script() );
1390 if ( ! *rename_script ) {
1391 return NT_STATUS_ACCESS_DENIED;
1394 /* invalidate the existing TDB iterator if it is open */
1396 tdbsam_endsampwent( my_methods );
1398 if ( !(new_acct = samu_new( NULL )) ) {
1399 return NT_STATUS_NO_MEMORY;
1402 if ( !pdb_copy_sam_account(new_acct, old_acct)
1403 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1405 TALLOC_FREE(new_acct );
1406 return NT_STATUS_NO_MEMORY;
1409 /* open the database */
1411 if ( !tdbsam_open( tdbsam_filename ) ) {
1412 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1413 TALLOC_FREE(new_acct );
1414 return NT_STATUS_ACCESS_DENIED;
1417 /* add the new account and lock it */
1419 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1423 interim_account = True;
1425 if ( tdb_lock_bystring_with_timeout(tdbsam, newname, 30) == -1 ) {
1429 /* rename the posix user */
1430 string_sub2(rename_script, "%unew", newname, sizeof(pstring),
1432 string_sub2(rename_script, "%uold", pdb_get_username(old_acct),
1433 sizeof(pstring), True, False, True);
1434 rename_ret = smbrun(rename_script, NULL);
1436 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1442 /* rewrite the rid->username record */
1444 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1447 interim_account = False;
1448 tdb_unlock_bystring( tdbsam, newname );
1450 tdb_delete_samacct_only( old_acct );
1454 TALLOC_FREE(new_acct );
1455 return NT_STATUS_OK;
1459 if (interim_account) {
1460 tdb_unlock_bystring(tdbsam, newname);
1461 tdb_delete_samacct_only(new_acct);
1467 TALLOC_FREE(new_acct);
1469 return NT_STATUS_ACCESS_DENIED;
1472 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1478 * Historically, winbind was responsible for allocating RIDs, so the next RID
1479 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1480 * but for compatibility reasons we still keep the the next RID counter in
1481 * winbindd_idmap.tdb.
1484 /*****************************************************************************
1485 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1486 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1487 winbind completely and store the RID counter in passdb.tdb.
1489 Dont' fully initialize with the HWM values, if it's new, we're only
1490 interested in the RID counter.
1491 *****************************************************************************/
1493 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1497 if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
1498 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1502 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1504 if (version == -1) {
1505 /* No key found, must be a new db */
1506 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1507 IDMAP_VERSION) != 0) {
1508 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1509 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1512 version = IDMAP_VERSION;
1515 if (version != IDMAP_VERSION) {
1516 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1517 "start winbind once\n", IDMAP_VERSION, version));
1518 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1522 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1526 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1532 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1533 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1536 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1540 if (!init_idmap_tdb(tdb)) {
1541 DEBUG(1, ("Could not init idmap\n"));
1545 rid = BASE_RID; /* Default if not set */
1547 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1548 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1556 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1557 smb_panic("tdb_close(idmap_tdb) failed\n");
1563 /*********************************************************************
1564 Initialize the tdb sam backend. Setup the dispath table of methods,
1565 open the tdb, etc...
1566 *********************************************************************/
1568 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1572 const char *pfile = location;
1574 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1578 (*pdb_method)->name = "tdbsam";
1580 (*pdb_method)->setsampwent = tdbsam_setsampwent;
1581 (*pdb_method)->endsampwent = tdbsam_endsampwent;
1582 (*pdb_method)->getsampwent = tdbsam_getsampwent;
1583 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1584 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1585 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1586 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1587 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1588 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1590 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1591 (*pdb_method)->new_rid = tdbsam_new_rid;
1593 /* save the path for later */
1596 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1599 pstrcpy( tdbsam_filename, pfile );
1601 /* no private data */
1603 (*pdb_method)->private_data = NULL;
1604 (*pdb_method)->free_private_data = NULL;
1606 return NT_STATUS_OK;
1609 NTSTATUS pdb_tdbsam_init(void)
1611 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);