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 USERPREFIX_LEN 5
45 #define RIDPREFIX "RID_"
46 #define PRIVPREFIX "PRIV_"
48 /* GLOBAL TDB SAM CONTEXT */
50 static struct db_context
*db_sam
;
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 struct tdbsam_convert_state
{
698 static int tdbsam_convert_one(struct db_record
*rec
, void *priv
)
700 struct tdbsam_convert_state
*state
=
701 (struct tdbsam_convert_state
*)priv
;
707 if (rec
->key
.dsize
< USERPREFIX_LEN
) {
710 if (strncmp((char *)rec
->key
.dptr
, USERPREFIX
, USERPREFIX_LEN
) != 0) {
714 user
= samu_new(talloc_tos());
716 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
717 state
->success
= false;
721 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
722 "(version:%d)\n", rec
->key
.dptr
, state
->from
));
724 switch (state
->from
) {
726 ret
= init_sam_from_buffer_v0(user
, (uint8
*)rec
->value
.dptr
,
730 ret
= init_sam_from_buffer_v1(user
, (uint8
*)rec
->value
.dptr
,
734 ret
= init_sam_from_buffer_v2(user
, (uint8
*)rec
->value
.dptr
,
738 ret
= init_sam_from_buffer_v3(user
, (uint8
*)rec
->value
.dptr
,
742 /* unknown tdbsam version */
746 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
747 "from TDB (key:%s) (version:%d)\n", rec
->key
.dptr
,
750 state
->success
= false;
754 data
.dsize
= init_buffer_from_sam(&data
.dptr
, user
, false);
757 if (data
.dsize
== -1) {
758 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
759 "the new format\n"));
760 state
->success
= false;
764 status
= rec
->store(rec
, data
, TDB_MODIFY
);
765 if (!NT_STATUS_IS_OK(status
)) {
766 DEBUG(0, ("Could not store the new record: %s\n",
768 state
->success
= false;
775 static bool tdbsam_convert(struct db_context
*db
, int32 from
)
777 struct tdbsam_convert_state state
;
780 state
.success
= true;
782 if (db
->transaction_start(db
) != 0) {
783 DEBUG(0, ("Could not start transaction\n"));
787 if (db
->traverse(db
, tdbsam_convert_one
, &state
) != 0) {
788 DEBUG(0, ("traverse failed\n"));
792 if (!state
.success
) {
793 DEBUG(0, ("Converting records failed\n"));
797 if (dbwrap_store_int32(db
, TDBSAM_VERSION_STRING
,
798 TDBSAM_VERSION
) != 0) {
799 DEBUG(0, ("Could not store tdbsam version\n"));
803 if (db
->transaction_commit(db
) != 0) {
804 DEBUG(0, ("Could not commit transaction\n"));
811 if (db
->transaction_cancel(db
) != 0) {
812 smb_panic("transaction_cancel failed");
818 /*********************************************************************
819 Open the tdbsam file based on the absolute path specified.
820 Uses a reference count to allow multiple open calls.
821 *********************************************************************/
823 static bool tdbsam_open( const char *name
)
827 /* check if we are already open */
833 /* Try to open tdb passwd. Create a new one if necessary */
835 db_sam
= db_open(NULL
, name
, 0, TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
836 if (db_sam
== NULL
) {
837 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
842 /* Check the version */
843 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
845 version
= 0; /* Version not found, assume version 0 */
848 /* Compare the version */
849 if (version
> TDBSAM_VERSION
) {
850 /* Version more recent than the latest known */
851 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
856 if ( version
< TDBSAM_VERSION
) {
857 DEBUG(1, ("tdbsam_open: Converting version %d database to "
858 "version %d.\n", version
, TDBSAM_VERSION
));
860 if ( !tdbsam_convert(db_sam
, version
) ) {
861 DEBUG(0, ("tdbsam_open: Error when trying to convert "
862 "tdbsam [%s]\n",name
));
867 DEBUG(3, ("TDBSAM converted successfully.\n"));
870 DEBUG(4,("tdbsam_open: successfully opened %s\n", name
));
875 /******************************************************************
876 Lookup a name in the SAM TDB
877 ******************************************************************/
879 static NTSTATUS
tdbsam_getsampwnam (struct pdb_methods
*my_methods
,
880 struct samu
*user
, const char *sname
)
887 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
888 return NT_STATUS_NO_MEMORY
;
891 /* Data is stored in all lower-case */
892 fstrcpy(name
, sname
);
896 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
898 /* open the database */
900 if ( !tdbsam_open( tdbsam_filename
) ) {
901 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
902 return NT_STATUS_ACCESS_DENIED
;
907 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
909 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
910 DEBUGADD(5, (" Key: %s\n", keystr
));
911 return NT_STATUS_NO_SUCH_USER
;
914 /* unpack the buffer */
916 if (!init_sam_from_buffer(user
, data
.dptr
, data
.dsize
)) {
917 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
918 SAFE_FREE(data
.dptr
);
919 return NT_STATUS_NO_MEMORY
;
924 TALLOC_FREE(data
.dptr
);
929 /***************************************************************************
931 **************************************************************************/
933 static NTSTATUS
tdbsam_getsampwrid (struct pdb_methods
*my_methods
,
934 struct samu
*user
, uint32 rid
)
936 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
942 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
948 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
950 /* open the database */
952 if ( !tdbsam_open( tdbsam_filename
) ) {
953 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
954 return NT_STATUS_ACCESS_DENIED
;
959 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
961 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid
, keystr
));
962 return NT_STATUS_UNSUCCESSFUL
;
965 fstrcpy(name
, (const char *)data
.dptr
);
966 TALLOC_FREE(data
.dptr
);
968 return tdbsam_getsampwnam (my_methods
, user
, name
);
971 static NTSTATUS
tdbsam_getsampwsid(struct pdb_methods
*my_methods
,
972 struct samu
* user
, const DOM_SID
*sid
)
976 if ( !sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
) )
977 return NT_STATUS_UNSUCCESSFUL
;
979 return tdbsam_getsampwrid(my_methods
, user
, rid
);
982 static bool tdb_delete_samacct_only( struct samu
*sam_pass
)
988 fstrcpy(name
, pdb_get_username(sam_pass
));
991 /* set the search key */
993 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
995 /* it's outaa here! 8^) */
997 status
= dbwrap_delete_bystring(db_sam
, keystr
);
998 if (!NT_STATUS_IS_OK(status
)) {
999 DEBUG(5, ("Error deleting entry from tdb passwd "
1000 "database: %s!\n", nt_errstr(status
)));
1007 /***************************************************************************
1008 Delete a struct samu records for the username and RID key
1009 ****************************************************************************/
1011 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
1012 struct samu
*sam_pass
)
1014 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1019 /* open the database */
1021 if ( !tdbsam_open( tdbsam_filename
) ) {
1022 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1024 return NT_STATUS_ACCESS_DENIED
;
1027 fstrcpy(name
, pdb_get_username(sam_pass
));
1030 /* set the search key */
1032 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
1034 rid
= pdb_get_user_rid(sam_pass
);
1036 /* it's outaa here! 8^) */
1038 if (db_sam
->transaction_start(db_sam
) != 0) {
1039 DEBUG(0, ("Could not start transaction\n"));
1040 return NT_STATUS_UNSUCCESSFUL
;
1043 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
1044 if (!NT_STATUS_IS_OK(nt_status
)) {
1045 DEBUG(5, ("Error deleting entry from tdb passwd "
1046 "database: %s!\n", nt_errstr(nt_status
)));
1050 /* set the search key */
1052 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
1054 /* it's outaa here! 8^) */
1056 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
1057 if (!NT_STATUS_IS_OK(nt_status
)) {
1058 DEBUG(5, ("Error deleting entry from tdb rid "
1059 "database: %s!\n", nt_errstr(nt_status
)));
1063 if (db_sam
->transaction_commit(db_sam
) != 0) {
1064 DEBUG(0, ("Could not commit transaction\n"));
1068 return NT_STATUS_OK
;
1071 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1072 smb_panic("transaction_cancel failed");
1079 /***************************************************************************
1080 Update the TDB SAM account record only
1081 Assumes that the tdbsam is already open
1082 ****************************************************************************/
1083 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
1092 /* copy the struct samu struct into a BYTE buffer for storage */
1094 if ( (data
.dsize
=init_buffer_from_sam (&buf
, newpwd
, False
)) == -1 ) {
1095 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1100 fstrcpy(name
, pdb_get_username(newpwd
));
1103 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1104 flag
== TDB_INSERT
? "(new) " : "", name
,
1105 pdb_get_user_rid(newpwd
)));
1107 /* setup the USER index key */
1108 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
1110 /* add the account */
1112 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
1113 if (!NT_STATUS_IS_OK(status
)) {
1114 DEBUG(0, ("Unable to modify passwd TDB: %s!",
1115 nt_errstr(status
)));
1127 /***************************************************************************
1128 Update the TDB SAM RID record only
1129 Assumes that the tdbsam is already open
1130 ****************************************************************************/
1131 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
1138 fstrcpy(name
, pdb_get_username(newpwd
));
1141 /* setup RID data */
1142 data
= string_term_tdb_data(name
);
1144 /* setup the RID index key */
1145 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
,
1146 pdb_get_user_rid(newpwd
));
1148 /* add the reference */
1149 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
1150 if (!NT_STATUS_IS_OK(status
)) {
1151 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
1152 nt_errstr(status
)));
1160 /***************************************************************************
1162 ****************************************************************************/
1164 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
1167 if (!pdb_get_user_rid(newpwd
)) {
1168 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
1169 pdb_get_username(newpwd
)));
1173 /* open the database */
1175 if ( !tdbsam_open( tdbsam_filename
) ) {
1176 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
1180 if (db_sam
->transaction_start(db_sam
) != 0) {
1181 DEBUG(0, ("Could not start transaction\n"));
1185 if (!tdb_update_samacct_only(newpwd
, flag
)
1186 || !tdb_update_ridrec_only(newpwd
, flag
)) {
1190 if (db_sam
->transaction_commit(db_sam
) != 0) {
1191 DEBUG(0, ("Could not commit transaction\n"));
1198 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1199 smb_panic("transaction_cancel failed");
1204 /***************************************************************************
1205 Modifies an existing struct samu
1206 ****************************************************************************/
1208 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
1210 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
1211 return NT_STATUS_UNSUCCESSFUL
;
1213 return NT_STATUS_OK
;
1216 /***************************************************************************
1217 Adds an existing struct samu
1218 ****************************************************************************/
1220 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
1222 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
1223 return NT_STATUS_UNSUCCESSFUL
;
1225 return NT_STATUS_OK
;
1228 /***************************************************************************
1229 Renames a struct samu
1230 - check for the posix user/rename user script
1231 - Add and lock the new user record
1232 - rename the posix user
1233 - rewrite the rid->username record
1234 - delete the old user
1235 - unlock the new user record
1236 ***************************************************************************/
1237 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
1238 struct samu
*old_acct
,
1239 const char *newname
)
1241 struct samu
*new_acct
= NULL
;
1242 char *rename_script
= NULL
;
1244 fstring oldname_lower
;
1245 fstring newname_lower
;
1247 /* can't do anything without an external script */
1249 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
1250 return NT_STATUS_NO_MEMORY
;
1253 rename_script
= talloc_strdup(new_acct
, lp_renameuser_script());
1254 if (!rename_script
) {
1255 TALLOC_FREE(new_acct
);
1256 return NT_STATUS_NO_MEMORY
;
1258 if (!*rename_script
) {
1259 TALLOC_FREE(new_acct
);
1260 return NT_STATUS_ACCESS_DENIED
;
1263 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
1264 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
1266 TALLOC_FREE(new_acct
);
1267 return NT_STATUS_NO_MEMORY
;
1270 /* open the database */
1271 if ( !tdbsam_open( tdbsam_filename
) ) {
1272 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1274 TALLOC_FREE(new_acct
);
1275 return NT_STATUS_ACCESS_DENIED
;
1278 if (db_sam
->transaction_start(db_sam
) != 0) {
1279 DEBUG(0, ("Could not start transaction\n"));
1280 TALLOC_FREE(new_acct
);
1281 return NT_STATUS_ACCESS_DENIED
;
1285 /* add the new account and lock it */
1286 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
1290 /* Rename the posix user. Follow the semantics of _samr_create_user()
1291 so that we lower case the posix name but preserve the case in passdb */
1293 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
1294 strlower_m( oldname_lower
);
1296 fstrcpy( newname_lower
, newname
);
1297 strlower_m( newname_lower
);
1299 rename_script
= talloc_string_sub2(new_acct
,
1306 if (!rename_script
) {
1309 rename_script
= talloc_string_sub2(new_acct
,
1316 if (!rename_script
) {
1319 rename_ret
= smbrun(rename_script
, NULL
);
1321 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
1322 rename_script
, rename_ret
));
1324 if (rename_ret
!= 0) {
1328 smb_nscd_flush_user_cache();
1330 /* rewrite the rid->username record */
1332 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
1336 tdb_delete_samacct_only( old_acct
);
1338 if (db_sam
->transaction_commit(db_sam
) == -1) {
1340 * Ok, we're screwed. We've changed the posix account, but
1341 * could not adapt passdb.tdb. Shall we change the posix
1344 DEBUG(0, ("transaction_commit failed\n"));
1348 TALLOC_FREE(new_acct
);
1349 return NT_STATUS_OK
;
1352 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1353 smb_panic("transaction_cancel failed");
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(struct db_record
*rec
, void *private_data
)
1464 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1465 private_data
, struct tdbsam_search_state
);
1466 size_t prefixlen
= strlen(RIDPREFIX
);
1469 if ((rec
->key
.dsize
< prefixlen
)
1470 || (strncmp((char *)rec
->key
.dptr
, RIDPREFIX
, prefixlen
))) {
1474 rid
= strtoul((char *)rec
->key
.dptr
+prefixlen
, NULL
, 16);
1476 ADD_TO_LARGE_ARRAY(state
, uint32
, rid
, &state
->rids
, &state
->num_rids
,
1477 &state
->array_size
);
1482 static void tdbsam_search_end(struct pdb_search
*search
)
1484 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1485 search
->private_data
, struct tdbsam_search_state
);
1489 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
1490 struct samr_displayentry
*entry
)
1492 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1493 search
->private_data
, struct tdbsam_search_state
);
1494 struct samu
*user
= NULL
;
1500 user
= samu_new(talloc_tos());
1502 DEBUG(0, ("samu_new failed\n"));
1506 if (state
->current
== state
->num_rids
) {
1510 rid
= state
->rids
[state
->current
++];
1512 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
1514 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1516 * Someone has deleted that user since we listed the RIDs
1521 if (!NT_STATUS_IS_OK(status
)) {
1522 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1523 nt_errstr(status
)));
1528 if ((state
->acct_flags
!= 0) &&
1529 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
1533 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
1535 entry
->account_name
= talloc_strdup(
1536 search
->mem_ctx
, pdb_get_username(user
));
1537 entry
->fullname
= talloc_strdup(
1538 search
->mem_ctx
, pdb_get_fullname(user
));
1539 entry
->description
= talloc_strdup(
1540 search
->mem_ctx
, pdb_get_acct_desc(user
));
1544 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
1545 || (entry
->description
== NULL
)) {
1546 DEBUG(0, ("talloc_strdup failed\n"));
1553 static bool tdbsam_search_users(struct pdb_methods
*methods
,
1554 struct pdb_search
*search
,
1557 struct tdbsam_search_state
*state
;
1559 if (!tdbsam_open(tdbsam_filename
)) {
1560 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1565 state
= TALLOC_ZERO_P(search
->mem_ctx
, struct tdbsam_search_state
);
1566 if (state
== NULL
) {
1567 DEBUG(0, ("talloc failed\n"));
1570 state
->acct_flags
= acct_flags
;
1571 state
->methods
= methods
;
1573 db_sam
->traverse_read(db_sam
, tdbsam_collect_rids
, state
);
1575 search
->private_data
= state
;
1576 search
->next_entry
= tdbsam_search_next_entry
;
1577 search
->search_end
= tdbsam_search_end
;
1582 /*********************************************************************
1583 Initialize the tdb sam backend. Setup the dispath table of methods,
1584 open the tdb, etc...
1585 *********************************************************************/
1587 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
1590 char *tdbfile
= NULL
;
1591 const char *pfile
= location
;
1593 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
1597 (*pdb_method
)->name
= "tdbsam";
1599 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
1600 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
1601 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
1602 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
1603 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
1604 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
1605 (*pdb_method
)->search_users
= tdbsam_search_users
;
1607 (*pdb_method
)->rid_algorithm
= tdbsam_rid_algorithm
;
1608 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
1610 /* save the path for later */
1613 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
1614 PASSDB_FILE_NAME
) < 0) {
1615 return NT_STATUS_NO_MEMORY
;
1619 tdbsam_filename
= SMB_STRDUP(pfile
);
1620 if (!tdbsam_filename
) {
1621 return NT_STATUS_NO_MEMORY
;
1625 /* no private data */
1627 (*pdb_method
)->private_data
= NULL
;
1628 (*pdb_method
)->free_private_data
= NULL
;
1630 return NT_STATUS_OK
;
1633 NTSTATUS
pdb_tdbsam_init(void)
1635 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);