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
;
781 state
.success
= true;
783 if (db
->transaction_start(db
) != 0) {
784 DEBUG(0, ("Could not start transaction\n"));
788 ret
= db
->traverse(db
, tdbsam_convert_one
, &state
);
790 DEBUG(0, ("traverse failed\n"));
794 if (!state
.success
) {
795 DEBUG(0, ("Converting records failed\n"));
799 if (dbwrap_store_int32(db
, TDBSAM_VERSION_STRING
,
800 TDBSAM_VERSION
) != 0) {
801 DEBUG(0, ("Could not store tdbsam version\n"));
805 if (db
->transaction_commit(db
) != 0) {
806 DEBUG(0, ("Could not commit transaction\n"));
813 if (db
->transaction_cancel(db
) != 0) {
814 smb_panic("transaction_cancel failed");
820 /*********************************************************************
821 Open the tdbsam file based on the absolute path specified.
822 Uses a reference count to allow multiple open calls.
823 *********************************************************************/
825 static bool tdbsam_open( const char *name
)
829 /* check if we are already open */
835 /* Try to open tdb passwd. Create a new one if necessary */
837 db_sam
= db_open(NULL
, name
, 0, TDB_DEFAULT
, O_CREAT
|O_RDWR
, 0600);
838 if (db_sam
== NULL
) {
839 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
844 /* Check the version */
845 version
= dbwrap_fetch_int32(db_sam
, TDBSAM_VERSION_STRING
);
847 version
= 0; /* Version not found, assume version 0 */
850 /* Compare the version */
851 if (version
> TDBSAM_VERSION
) {
852 /* Version more recent than the latest known */
853 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version
));
858 if ( version
< TDBSAM_VERSION
) {
859 DEBUG(1, ("tdbsam_open: Converting version %d database to "
860 "version %d.\n", version
, TDBSAM_VERSION
));
862 if ( !tdbsam_convert(db_sam
, version
) ) {
863 DEBUG(0, ("tdbsam_open: Error when trying to convert "
864 "tdbsam [%s]\n",name
));
869 DEBUG(3, ("TDBSAM converted successfully.\n"));
872 DEBUG(4,("tdbsam_open: successfully opened %s\n", name
));
877 /******************************************************************
878 Lookup a name in the SAM TDB
879 ******************************************************************/
881 static NTSTATUS
tdbsam_getsampwnam (struct pdb_methods
*my_methods
,
882 struct samu
*user
, const char *sname
)
889 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
890 return NT_STATUS_NO_MEMORY
;
893 /* Data is stored in all lower-case */
894 fstrcpy(name
, sname
);
898 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
900 /* open the database */
902 if ( !tdbsam_open( tdbsam_filename
) ) {
903 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
904 return NT_STATUS_ACCESS_DENIED
;
909 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
911 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
912 DEBUGADD(5, (" Key: %s\n", keystr
));
913 return NT_STATUS_NO_SUCH_USER
;
916 /* unpack the buffer */
918 if (!init_sam_from_buffer(user
, data
.dptr
, data
.dsize
)) {
919 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
920 SAFE_FREE(data
.dptr
);
921 return NT_STATUS_NO_MEMORY
;
926 TALLOC_FREE(data
.dptr
);
931 /***************************************************************************
933 **************************************************************************/
935 static NTSTATUS
tdbsam_getsampwrid (struct pdb_methods
*my_methods
,
936 struct samu
*user
, uint32 rid
)
938 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
944 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
950 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
952 /* open the database */
954 if ( !tdbsam_open( tdbsam_filename
) ) {
955 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
956 return NT_STATUS_ACCESS_DENIED
;
961 data
= dbwrap_fetch_bystring(db_sam
, talloc_tos(), keystr
);
963 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid
, keystr
));
964 return NT_STATUS_UNSUCCESSFUL
;
967 fstrcpy(name
, (const char *)data
.dptr
);
968 TALLOC_FREE(data
.dptr
);
970 return tdbsam_getsampwnam (my_methods
, user
, name
);
973 static NTSTATUS
tdbsam_getsampwsid(struct pdb_methods
*my_methods
,
974 struct samu
* user
, const DOM_SID
*sid
)
978 if ( !sid_peek_check_rid(get_global_sam_sid(), sid
, &rid
) )
979 return NT_STATUS_UNSUCCESSFUL
;
981 return tdbsam_getsampwrid(my_methods
, user
, rid
);
984 static bool tdb_delete_samacct_only( struct samu
*sam_pass
)
990 fstrcpy(name
, pdb_get_username(sam_pass
));
993 /* set the search key */
995 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
997 /* it's outaa here! 8^) */
999 status
= dbwrap_delete_bystring(db_sam
, keystr
);
1000 if (!NT_STATUS_IS_OK(status
)) {
1001 DEBUG(5, ("Error deleting entry from tdb passwd "
1002 "database: %s!\n", nt_errstr(status
)));
1009 /***************************************************************************
1010 Delete a struct samu records for the username and RID key
1011 ****************************************************************************/
1013 static NTSTATUS
tdbsam_delete_sam_account(struct pdb_methods
*my_methods
,
1014 struct samu
*sam_pass
)
1016 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1021 /* open the database */
1023 if ( !tdbsam_open( tdbsam_filename
) ) {
1024 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1026 return NT_STATUS_ACCESS_DENIED
;
1029 fstrcpy(name
, pdb_get_username(sam_pass
));
1032 /* set the search key */
1034 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
1036 rid
= pdb_get_user_rid(sam_pass
);
1038 /* it's outaa here! 8^) */
1040 if (db_sam
->transaction_start(db_sam
) != 0) {
1041 DEBUG(0, ("Could not start transaction\n"));
1042 return NT_STATUS_UNSUCCESSFUL
;
1045 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
1046 if (!NT_STATUS_IS_OK(nt_status
)) {
1047 DEBUG(5, ("Error deleting entry from tdb passwd "
1048 "database: %s!\n", nt_errstr(nt_status
)));
1052 /* set the search key */
1054 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
, rid
);
1056 /* it's outaa here! 8^) */
1058 nt_status
= dbwrap_delete_bystring(db_sam
, keystr
);
1059 if (!NT_STATUS_IS_OK(nt_status
)) {
1060 DEBUG(5, ("Error deleting entry from tdb rid "
1061 "database: %s!\n", nt_errstr(nt_status
)));
1065 if (db_sam
->transaction_commit(db_sam
) != 0) {
1066 DEBUG(0, ("Could not commit transaction\n"));
1067 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1070 return NT_STATUS_OK
;
1073 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1074 smb_panic("transaction_cancel failed");
1081 /***************************************************************************
1082 Update the TDB SAM account record only
1083 Assumes that the tdbsam is already open
1084 ****************************************************************************/
1085 static bool tdb_update_samacct_only( struct samu
* newpwd
, int flag
)
1094 /* copy the struct samu struct into a BYTE buffer for storage */
1096 if ( (data
.dsize
=init_buffer_from_sam (&buf
, newpwd
, False
)) == -1 ) {
1097 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1102 fstrcpy(name
, pdb_get_username(newpwd
));
1105 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1106 flag
== TDB_INSERT
? "(new) " : "", name
,
1107 pdb_get_user_rid(newpwd
)));
1109 /* setup the USER index key */
1110 slprintf(keystr
, sizeof(keystr
)-1, "%s%s", USERPREFIX
, name
);
1112 /* add the account */
1114 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 DEBUG(0, ("Unable to modify passwd TDB: %s!",
1117 nt_errstr(status
)));
1129 /***************************************************************************
1130 Update the TDB SAM RID record only
1131 Assumes that the tdbsam is already open
1132 ****************************************************************************/
1133 static bool tdb_update_ridrec_only( struct samu
* newpwd
, int flag
)
1140 fstrcpy(name
, pdb_get_username(newpwd
));
1143 /* setup RID data */
1144 data
= string_term_tdb_data(name
);
1146 /* setup the RID index key */
1147 slprintf(keystr
, sizeof(keystr
)-1, "%s%.8x", RIDPREFIX
,
1148 pdb_get_user_rid(newpwd
));
1150 /* add the reference */
1151 status
= dbwrap_store_bystring(db_sam
, keystr
, data
, flag
);
1152 if (!NT_STATUS_IS_OK(status
)) {
1153 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
1154 nt_errstr(status
)));
1162 /***************************************************************************
1164 ****************************************************************************/
1166 static bool tdb_update_sam(struct pdb_methods
*my_methods
, struct samu
* newpwd
,
1169 if (!pdb_get_user_rid(newpwd
)) {
1170 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
1171 pdb_get_username(newpwd
)));
1175 /* open the database */
1177 if ( !tdbsam_open( tdbsam_filename
) ) {
1178 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename
));
1182 if (db_sam
->transaction_start(db_sam
) != 0) {
1183 DEBUG(0, ("Could not start transaction\n"));
1187 if (!tdb_update_samacct_only(newpwd
, flag
)
1188 || !tdb_update_ridrec_only(newpwd
, flag
)) {
1192 if (db_sam
->transaction_commit(db_sam
) != 0) {
1193 DEBUG(0, ("Could not commit transaction\n"));
1200 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1201 smb_panic("transaction_cancel failed");
1206 /***************************************************************************
1207 Modifies an existing struct samu
1208 ****************************************************************************/
1210 static NTSTATUS
tdbsam_update_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
1212 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_MODIFY
) )
1213 return NT_STATUS_UNSUCCESSFUL
;
1215 return NT_STATUS_OK
;
1218 /***************************************************************************
1219 Adds an existing struct samu
1220 ****************************************************************************/
1222 static NTSTATUS
tdbsam_add_sam_account (struct pdb_methods
*my_methods
, struct samu
*newpwd
)
1224 if ( !tdb_update_sam(my_methods
, newpwd
, TDB_INSERT
) )
1225 return NT_STATUS_UNSUCCESSFUL
;
1227 return NT_STATUS_OK
;
1230 /***************************************************************************
1231 Renames a struct samu
1232 - check for the posix user/rename user script
1233 - Add and lock the new user record
1234 - rename the posix user
1235 - rewrite the rid->username record
1236 - delete the old user
1237 - unlock the new user record
1238 ***************************************************************************/
1239 static NTSTATUS
tdbsam_rename_sam_account(struct pdb_methods
*my_methods
,
1240 struct samu
*old_acct
,
1241 const char *newname
)
1243 struct samu
*new_acct
= NULL
;
1244 char *rename_script
= NULL
;
1246 fstring oldname_lower
;
1247 fstring newname_lower
;
1249 /* can't do anything without an external script */
1251 if ( !(new_acct
= samu_new( talloc_tos() )) ) {
1252 return NT_STATUS_NO_MEMORY
;
1255 rename_script
= talloc_strdup(new_acct
, lp_renameuser_script());
1256 if (!rename_script
) {
1257 TALLOC_FREE(new_acct
);
1258 return NT_STATUS_NO_MEMORY
;
1260 if (!*rename_script
) {
1261 TALLOC_FREE(new_acct
);
1262 return NT_STATUS_ACCESS_DENIED
;
1265 if ( !pdb_copy_sam_account(new_acct
, old_acct
)
1266 || !pdb_set_username(new_acct
, newname
, PDB_CHANGED
))
1268 TALLOC_FREE(new_acct
);
1269 return NT_STATUS_NO_MEMORY
;
1272 /* open the database */
1273 if ( !tdbsam_open( tdbsam_filename
) ) {
1274 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1276 TALLOC_FREE(new_acct
);
1277 return NT_STATUS_ACCESS_DENIED
;
1280 if (db_sam
->transaction_start(db_sam
) != 0) {
1281 DEBUG(0, ("Could not start transaction\n"));
1282 TALLOC_FREE(new_acct
);
1283 return NT_STATUS_ACCESS_DENIED
;
1287 /* add the new account and lock it */
1288 if ( !tdb_update_samacct_only(new_acct
, TDB_INSERT
) ) {
1292 /* Rename the posix user. Follow the semantics of _samr_create_user()
1293 so that we lower case the posix name but preserve the case in passdb */
1295 fstrcpy( oldname_lower
, pdb_get_username(old_acct
) );
1296 strlower_m( oldname_lower
);
1298 fstrcpy( newname_lower
, newname
);
1299 strlower_m( newname_lower
);
1301 rename_script
= talloc_string_sub2(new_acct
,
1308 if (!rename_script
) {
1311 rename_script
= talloc_string_sub2(new_acct
,
1318 if (!rename_script
) {
1321 rename_ret
= smbrun(rename_script
, NULL
);
1323 DEBUG(rename_ret
? 0 : 3,("Running the command `%s' gave %d\n",
1324 rename_script
, rename_ret
));
1326 if (rename_ret
!= 0) {
1330 smb_nscd_flush_user_cache();
1332 /* rewrite the rid->username record */
1334 if ( !tdb_update_ridrec_only( new_acct
, TDB_MODIFY
) ) {
1338 tdb_delete_samacct_only( old_acct
);
1340 if (db_sam
->transaction_commit(db_sam
) != 0) {
1342 * Ok, we're screwed. We've changed the posix account, but
1343 * could not adapt passdb.tdb. Shall we change the posix
1346 DEBUG(0, ("transaction_commit failed\n"));
1347 TALLOC_FREE(new_acct
);
1348 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1351 TALLOC_FREE(new_acct
);
1352 return NT_STATUS_OK
;
1355 if (db_sam
->transaction_cancel(db_sam
) != 0) {
1356 smb_panic("transaction_cancel failed");
1359 TALLOC_FREE(new_acct
);
1361 return NT_STATUS_ACCESS_DENIED
;
1364 static bool tdbsam_rid_algorithm(struct pdb_methods
*methods
)
1370 * Historically, winbind was responsible for allocating RIDs, so the next RID
1371 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1372 * but for compatibility reasons we still keep the the next RID counter in
1373 * winbindd_idmap.tdb.
1376 /*****************************************************************************
1377 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1378 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1379 winbind completely and store the RID counter in passdb.tdb.
1381 Dont' fully initialize with the HWM values, if it's new, we're only
1382 interested in the RID counter.
1383 *****************************************************************************/
1385 static bool init_idmap_tdb(TDB_CONTEXT
*tdb
)
1389 if (tdb_lock_bystring(tdb
, "IDMAP_VERSION") != 0) {
1390 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1394 version
= tdb_fetch_int32(tdb
, "IDMAP_VERSION");
1396 if (version
== -1) {
1397 /* No key found, must be a new db */
1398 if (tdb_store_int32(tdb
, "IDMAP_VERSION",
1399 IDMAP_VERSION
) != 0) {
1400 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1401 tdb_unlock_bystring(tdb
, "IDMAP_VERSION");
1404 version
= IDMAP_VERSION
;
1407 if (version
!= IDMAP_VERSION
) {
1408 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1409 "start winbind once\n", IDMAP_VERSION
, version
));
1410 tdb_unlock_bystring(tdb
, "IDMAP_VERSION");
1414 tdb_unlock_bystring(tdb
, "IDMAP_VERSION");
1418 static bool tdbsam_new_rid(struct pdb_methods
*methods
, uint32
*prid
)
1424 tdb
= tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
1425 TDB_DEFAULT
, O_RDWR
| O_CREAT
, 0644);
1428 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno
)));
1432 if (!init_idmap_tdb(tdb
)) {
1433 DEBUG(1, ("Could not init idmap\n"));
1437 rid
= BASE_RID
; /* Default if not set */
1439 if (!tdb_change_uint32_atomic(tdb
, "RID_COUNTER", &rid
, 1)) {
1440 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1448 if ((tdb
!= NULL
) && (tdb_close(tdb
) != 0)) {
1449 smb_panic("tdb_close(idmap_tdb) failed");
1455 struct tdbsam_search_state
{
1456 struct pdb_methods
*methods
;
1457 uint32_t acct_flags
;
1465 static int tdbsam_collect_rids(struct db_record
*rec
, void *private_data
)
1467 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1468 private_data
, struct tdbsam_search_state
);
1469 size_t prefixlen
= strlen(RIDPREFIX
);
1472 if ((rec
->key
.dsize
< prefixlen
)
1473 || (strncmp((char *)rec
->key
.dptr
, RIDPREFIX
, prefixlen
))) {
1477 rid
= strtoul((char *)rec
->key
.dptr
+prefixlen
, NULL
, 16);
1479 ADD_TO_LARGE_ARRAY(state
, uint32
, rid
, &state
->rids
, &state
->num_rids
,
1480 &state
->array_size
);
1485 static void tdbsam_search_end(struct pdb_search
*search
)
1487 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1488 search
->private_data
, struct tdbsam_search_state
);
1492 static bool tdbsam_search_next_entry(struct pdb_search
*search
,
1493 struct samr_displayentry
*entry
)
1495 struct tdbsam_search_state
*state
= talloc_get_type_abort(
1496 search
->private_data
, struct tdbsam_search_state
);
1497 struct samu
*user
= NULL
;
1503 user
= samu_new(talloc_tos());
1505 DEBUG(0, ("samu_new failed\n"));
1509 if (state
->current
== state
->num_rids
) {
1513 rid
= state
->rids
[state
->current
++];
1515 status
= tdbsam_getsampwrid(state
->methods
, user
, rid
);
1517 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1519 * Someone has deleted that user since we listed the RIDs
1524 if (!NT_STATUS_IS_OK(status
)) {
1525 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1526 nt_errstr(status
)));
1531 if ((state
->acct_flags
!= 0) &&
1532 ((state
->acct_flags
& pdb_get_acct_ctrl(user
)) == 0)) {
1536 entry
->acct_flags
= pdb_get_acct_ctrl(user
);
1538 entry
->account_name
= talloc_strdup(
1539 search
->mem_ctx
, pdb_get_username(user
));
1540 entry
->fullname
= talloc_strdup(
1541 search
->mem_ctx
, pdb_get_fullname(user
));
1542 entry
->description
= talloc_strdup(
1543 search
->mem_ctx
, pdb_get_acct_desc(user
));
1547 if ((entry
->account_name
== NULL
) || (entry
->fullname
== NULL
)
1548 || (entry
->description
== NULL
)) {
1549 DEBUG(0, ("talloc_strdup failed\n"));
1556 static bool tdbsam_search_users(struct pdb_methods
*methods
,
1557 struct pdb_search
*search
,
1560 struct tdbsam_search_state
*state
;
1562 if (!tdbsam_open(tdbsam_filename
)) {
1563 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1568 state
= TALLOC_ZERO_P(search
->mem_ctx
, struct tdbsam_search_state
);
1569 if (state
== NULL
) {
1570 DEBUG(0, ("talloc failed\n"));
1573 state
->acct_flags
= acct_flags
;
1574 state
->methods
= methods
;
1576 db_sam
->traverse_read(db_sam
, tdbsam_collect_rids
, state
);
1578 search
->private_data
= state
;
1579 search
->next_entry
= tdbsam_search_next_entry
;
1580 search
->search_end
= tdbsam_search_end
;
1585 /*********************************************************************
1586 Initialize the tdb sam backend. Setup the dispath table of methods,
1587 open the tdb, etc...
1588 *********************************************************************/
1590 static NTSTATUS
pdb_init_tdbsam(struct pdb_methods
**pdb_method
, const char *location
)
1593 char *tdbfile
= NULL
;
1594 const char *pfile
= location
;
1596 if (!NT_STATUS_IS_OK(nt_status
= make_pdb_method( pdb_method
))) {
1600 (*pdb_method
)->name
= "tdbsam";
1602 (*pdb_method
)->getsampwnam
= tdbsam_getsampwnam
;
1603 (*pdb_method
)->getsampwsid
= tdbsam_getsampwsid
;
1604 (*pdb_method
)->add_sam_account
= tdbsam_add_sam_account
;
1605 (*pdb_method
)->update_sam_account
= tdbsam_update_sam_account
;
1606 (*pdb_method
)->delete_sam_account
= tdbsam_delete_sam_account
;
1607 (*pdb_method
)->rename_sam_account
= tdbsam_rename_sam_account
;
1608 (*pdb_method
)->search_users
= tdbsam_search_users
;
1610 (*pdb_method
)->rid_algorithm
= tdbsam_rid_algorithm
;
1611 (*pdb_method
)->new_rid
= tdbsam_new_rid
;
1613 /* save the path for later */
1616 if (asprintf(&tdbfile
, "%s/%s", lp_private_dir(),
1617 PASSDB_FILE_NAME
) < 0) {
1618 return NT_STATUS_NO_MEMORY
;
1622 tdbsam_filename
= SMB_STRDUP(pfile
);
1623 if (!tdbsam_filename
) {
1624 return NT_STATUS_NO_MEMORY
;
1628 /* no private data */
1630 (*pdb_method
)->private_data
= NULL
;
1631 (*pdb_method
)->free_private_data
= NULL
;
1633 return NT_STATUS_OK
;
1636 NTSTATUS
pdb_tdbsam_init(void)
1638 return smb_register_passdb(PASSDB_INTERFACE_VERSION
, "tdbsam", pdb_init_tdbsam
);