pdb_tdb: use db_open_trans()
[Samba/gbeck.git] / source / passdb / pdb_tdb.c
blobb41a7cc0a48bc03730cb0249982603b20cd90872
1 /*
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)
14 * any later version.
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
19 * more details.
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/>.
25 #include "includes.h"
27 #if 0 /* when made a module use this */
29 static int tdbsam_debug_level = DBGC_ALL;
30 #undef DBGC_CLASS
31 #define DBGC_CLASS tdbsam_debug_level
33 #else
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_PASSDB
38 #endif
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
69 --SSS */
70 uint32 logon_time,
71 logoff_time,
72 kickoff_time,
73 pass_last_set_time,
74 pass_can_change_time,
75 pass_must_change_time;
76 char *username = NULL;
77 char *domain = 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;
83 char *homedir = 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;
96 uint8 *hours = NULL;
97 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
98 uint32 len = 0;
99 uint32 lm_pw_len, nt_pw_len, hourslen;
100 bool ret = True;
102 if(sampass == NULL || buf == NULL) {
103 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
104 return False;
107 /* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
109 /* unpack the buffer into variables */
110 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V0,
111 &logon_time, /* d */
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 */
129 &user_rid, /* d */
130 &group_rid, /* d */
131 &lm_pw_len, &lm_pw_ptr, /* B */
132 &nt_pw_len, &nt_pw_ptr, /* B */
133 &acct_ctrl, /* w */
134 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
135 &logon_divs, /* w */
136 &hours_len, /* d */
137 &hourslen, &hours, /* B */
138 &bad_password_count, /* w */
139 &logon_count, /* w */
140 &unknown_6); /* d */
142 if (len == (uint32) -1) {
143 ret = False;
144 goto done;
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);
159 if (homedir) {
160 pdb_set_homedir(sampass, homedir, PDB_SET);
162 else {
163 pdb_set_homedir(sampass,
164 talloc_sub_basic(sampass, username, domain,
165 lp_logon_home()),
166 PDB_DEFAULT);
169 if (dir_drive)
170 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
171 else {
172 pdb_set_dir_drive(sampass,
173 talloc_sub_basic(sampass, username, domain,
174 lp_logon_drive()),
175 PDB_DEFAULT);
178 if (logon_script)
179 pdb_set_logon_script(sampass, logon_script, PDB_SET);
180 else {
181 pdb_set_logon_script(sampass,
182 talloc_sub_basic(sampass, username, domain,
183 lp_logon_script()),
184 PDB_DEFAULT);
187 if (profile_path) {
188 pdb_set_profile_path(sampass, profile_path, PDB_SET);
189 } else {
190 pdb_set_profile_path(sampass,
191 talloc_sub_basic(sampass, username, domain,
192 lp_logon_path()),
193 PDB_DEFAULT);
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)) {
202 ret = False;
203 goto done;
207 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
208 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
209 ret = False;
210 goto done;
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);
225 done:
227 SAFE_FREE(username);
228 SAFE_FREE(domain);
229 SAFE_FREE(nt_username);
230 SAFE_FREE(fullname);
231 SAFE_FREE(homedir);
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);
241 SAFE_FREE(hours);
243 return ret;
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
254 --SSS */
255 uint32 logon_time,
256 logoff_time,
257 kickoff_time,
258 bad_password_time,
259 pass_last_set_time,
260 pass_can_change_time,
261 pass_must_change_time;
262 char *username = NULL;
263 char *domain = 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;
282 uint8 *hours = NULL;
283 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
284 uint32 len = 0;
285 uint32 lm_pw_len, nt_pw_len, hourslen;
286 bool ret = True;
288 if(sampass == NULL || buf == NULL) {
289 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
290 return False;
293 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
295 /* unpack the buffer into variables */
296 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V1,
297 &logon_time, /* d */
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 */
317 &user_rid, /* d */
318 &group_rid, /* d */
319 &lm_pw_len, &lm_pw_ptr, /* B */
320 &nt_pw_len, &nt_pw_ptr, /* B */
321 &acct_ctrl, /* w */
322 &remove_me, /* d */
323 &logon_divs, /* w */
324 &hours_len, /* d */
325 &hourslen, &hours, /* B */
326 &bad_password_count, /* w */
327 &logon_count, /* w */
328 &unknown_6); /* d */
330 if (len == (uint32) -1) {
331 ret = False;
332 goto done;
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);
350 if (homedir) {
351 pdb_set_homedir(sampass, homedir, PDB_SET);
353 else {
354 pdb_set_homedir(sampass,
355 talloc_sub_basic(sampass, username, domain,
356 lp_logon_home()),
357 PDB_DEFAULT);
360 if (dir_drive)
361 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
362 else {
363 pdb_set_dir_drive(sampass,
364 talloc_sub_basic(sampass, username, domain,
365 lp_logon_drive()),
366 PDB_DEFAULT);
369 if (logon_script)
370 pdb_set_logon_script(sampass, logon_script, PDB_SET);
371 else {
372 pdb_set_logon_script(sampass,
373 talloc_sub_basic(sampass, username, domain,
374 lp_logon_script()),
375 PDB_DEFAULT);
378 if (profile_path) {
379 pdb_set_profile_path(sampass, profile_path, PDB_SET);
380 } else {
381 pdb_set_profile_path(sampass,
382 talloc_sub_basic(sampass, username, domain,
383 lp_logon_path()),
384 PDB_DEFAULT);
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)) {
393 ret = False;
394 goto done;
398 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
399 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
400 ret = False;
401 goto done;
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);
417 done:
419 SAFE_FREE(username);
420 SAFE_FREE(domain);
421 SAFE_FREE(nt_username);
422 SAFE_FREE(fullname);
423 SAFE_FREE(homedir);
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);
433 SAFE_FREE(hours);
435 return ret;
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
443 --SSS */
444 uint32 logon_time,
445 logoff_time,
446 kickoff_time,
447 bad_password_time,
448 pass_last_set_time,
449 pass_can_change_time,
450 pass_must_change_time;
451 char *username = NULL;
452 char *domain = 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;
471 uint8 *hours = NULL;
472 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
473 uint32 len = 0;
474 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
475 uint32 pwHistLen = 0;
476 bool ret = True;
477 fstring tmp_string;
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"));
482 return False;
485 /* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
487 /* unpack the buffer into variables */
488 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V2,
489 &logon_time, /* d */
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 */
508 &user_rid, /* d */
509 &group_rid, /* d */
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 */
514 &acct_ctrl, /* w */
515 /* Also "remove_me" field was removed. */
516 &logon_divs, /* w */
517 &hours_len, /* d */
518 &hourslen, &hours, /* B */
519 &bad_password_count, /* w */
520 &logon_count, /* w */
521 &unknown_6); /* d */
523 if (len == (uint32) -1) {
524 ret = False;
525 goto done;
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);
541 if (homedir) {
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);
549 else {
550 pdb_set_homedir(sampass,
551 talloc_sub_basic(sampass, username, domain,
552 lp_logon_home()),
553 PDB_DEFAULT);
556 if (dir_drive)
557 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
558 else
559 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
561 if (logon_script) {
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);
569 else {
570 pdb_set_logon_script(sampass,
571 talloc_sub_basic(sampass, username, domain,
572 lp_logon_script()),
573 PDB_DEFAULT);
576 if (profile_path) {
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);
584 else {
585 pdb_set_profile_path(sampass,
586 talloc_sub_basic(sampass, username, domain,
587 lp_logon_path()),
588 PDB_DEFAULT);
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)) {
597 ret = False;
598 goto done;
602 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
603 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
604 ret = False;
605 goto done;
609 /* Change from V1 is addition of password history field. */
610 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
611 if (pwHistLen) {
612 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
613 if (!pw_hist) {
614 ret = False;
615 goto done;
617 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
618 if (nt_pw_hist_ptr && nt_pw_hist_len) {
619 int i;
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)) {
629 SAFE_FREE(pw_hist);
630 ret = False;
631 goto done;
633 SAFE_FREE(pw_hist);
634 } else {
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);
648 done:
650 SAFE_FREE(username);
651 SAFE_FREE(domain);
652 SAFE_FREE(nt_username);
653 SAFE_FREE(fullname);
654 SAFE_FREE(homedir);
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);
665 SAFE_FREE(hours);
667 return ret;
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 {
694 int32_t from;
695 bool success;
698 static int tdbsam_convert_one(struct db_record *rec, void *priv)
700 struct tdbsam_convert_state *state =
701 (struct tdbsam_convert_state *)priv;
702 struct samu *user;
703 TDB_DATA data;
704 NTSTATUS status;
705 bool ret;
707 if (rec->key.dsize < USERPREFIX_LEN) {
708 return 0;
710 if (strncmp((char *)rec->key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
711 return 0;
714 user = samu_new(talloc_tos());
715 if (user == NULL) {
716 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
717 state->success = false;
718 return -1;
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) {
725 case 0:
726 ret = init_sam_from_buffer_v0(user, (uint8 *)rec->value.dptr,
727 rec->value.dsize);
728 break;
729 case 1:
730 ret = init_sam_from_buffer_v1(user, (uint8 *)rec->value.dptr,
731 rec->value.dsize);
732 break;
733 case 2:
734 ret = init_sam_from_buffer_v2(user, (uint8 *)rec->value.dptr,
735 rec->value.dsize);
736 break;
737 case 3:
738 ret = init_sam_from_buffer_v3(user, (uint8 *)rec->value.dptr,
739 rec->value.dsize);
740 break;
741 default:
742 /* unknown tdbsam version */
743 ret = False;
745 if (!ret) {
746 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
747 "from TDB (key:%s) (version:%d)\n", rec->key.dptr,
748 state->from));
749 TALLOC_FREE(user);
750 state->success = false;
751 return -1;
754 data.dsize = init_buffer_from_sam(&data.dptr, user, false);
755 TALLOC_FREE(user);
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;
761 return -1;
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",
767 nt_errstr(status)));
768 state->success = false;
769 return -1;
772 return 0;
775 static bool tdbsam_convert(struct db_context *db, int32 from)
777 struct tdbsam_convert_state state;
779 state.from = from;
780 state.success = true;
782 if (db->transaction_start(db) != 0) {
783 DEBUG(0, ("Could not start transaction\n"));
784 return false;
787 if (db->traverse(db, tdbsam_convert_one, &state) != 0) {
788 DEBUG(0, ("traverse failed\n"));
789 goto cancel;
792 if (!state.success) {
793 DEBUG(0, ("Converting records failed\n"));
794 goto cancel;
797 if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING,
798 TDBSAM_VERSION) != 0) {
799 DEBUG(0, ("Could not store tdbsam version\n"));
800 goto cancel;
803 if (db->transaction_commit(db) != 0) {
804 DEBUG(0, ("Could not commit transaction\n"));
805 goto cancel;
808 return true;
810 cancel:
811 if (db->transaction_cancel(db) != 0) {
812 smb_panic("transaction_cancel failed");
815 return false;
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 )
825 int32 version;
827 /* check if we are already open */
829 if ( db_sam ) {
830 return true;
833 /* Try to open tdb passwd. Create a new one if necessary */
835 db_sam = db_open_trans(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 "
838 "[%s]\n", name));
839 return false;
842 /* Check the version */
843 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
844 if (version == -1) {
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));
852 TALLOC_FREE(db_sam);
853 return false;
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));
863 TALLOC_FREE(db_sam);
864 return false;
867 DEBUG(3, ("TDBSAM converted successfully.\n"));
870 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
872 return true;
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)
882 TDB_DATA data;
883 fstring keystr;
884 fstring name;
886 if ( !user ) {
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);
893 strlower_m(name);
895 /* set search key */
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;
905 /* get the record */
907 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
908 if (!data.dptr) {
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;
922 /* success */
924 TALLOC_FREE(data.dptr);
926 return NT_STATUS_OK;
929 /***************************************************************************
930 Search by rid
931 **************************************************************************/
933 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
934 struct samu *user, uint32 rid)
936 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
937 TDB_DATA data;
938 fstring keystr;
939 fstring name;
941 if ( !user ) {
942 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
943 return nt_status;
946 /* set search key */
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;
957 /* get the record */
959 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
960 if (!data.dptr) {
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)
974 uint32 rid;
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 )
984 fstring keystr;
985 fstring name;
986 NTSTATUS status;
988 fstrcpy(name, pdb_get_username(sam_pass));
989 strlower_m(name);
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)));
1001 return false;
1004 return true;
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;
1015 fstring keystr;
1016 uint32 rid;
1017 fstring name;
1019 /* open the database */
1021 if ( !tdbsam_open( tdbsam_filename ) ) {
1022 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1023 tdbsam_filename));
1024 return NT_STATUS_ACCESS_DENIED;
1027 fstrcpy(name, pdb_get_username(sam_pass));
1028 strlower_m(name);
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)));
1047 goto cancel;
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)));
1060 goto cancel;
1063 if (db_sam->transaction_commit(db_sam) != 0) {
1064 DEBUG(0, ("Could not commit transaction\n"));
1065 goto cancel;
1068 return NT_STATUS_OK;
1070 cancel:
1071 if (db_sam->transaction_cancel(db_sam) != 0) {
1072 smb_panic("transaction_cancel failed");
1075 return nt_status;
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 )
1085 TDB_DATA data;
1086 uint8 *buf = NULL;
1087 fstring keystr;
1088 fstring name;
1089 bool ret = false;
1090 NTSTATUS status;
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"));
1096 goto done;
1098 data.dptr = buf;
1100 fstrcpy(name, pdb_get_username(newpwd));
1101 strlower_m(name);
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)));
1116 goto done;
1119 ret = true;
1121 done:
1122 /* cleanup */
1123 SAFE_FREE(buf);
1124 return ret;
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 )
1133 TDB_DATA data;
1134 fstring keystr;
1135 fstring name;
1136 NTSTATUS status;
1138 fstrcpy(name, pdb_get_username(newpwd));
1139 strlower_m(name);
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)));
1153 return false;
1156 return true;
1160 /***************************************************************************
1161 Update the TDB SAM
1162 ****************************************************************************/
1164 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
1165 int flag)
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)));
1170 return False;
1173 /* open the database */
1175 if ( !tdbsam_open( tdbsam_filename ) ) {
1176 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1177 return False;
1180 if (db_sam->transaction_start(db_sam) != 0) {
1181 DEBUG(0, ("Could not start transaction\n"));
1182 return false;
1185 if (!tdb_update_samacct_only(newpwd, flag)
1186 || !tdb_update_ridrec_only(newpwd, flag)) {
1187 goto cancel;
1190 if (db_sam->transaction_commit(db_sam) != 0) {
1191 DEBUG(0, ("Could not commit transaction\n"));
1192 goto cancel;
1195 return true;
1197 cancel:
1198 if (db_sam->transaction_cancel(db_sam) != 0) {
1199 smb_panic("transaction_cancel failed");
1201 return false;
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;
1243 int rename_ret;
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",
1273 tdbsam_filename));
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) ) {
1287 goto cancel;
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,
1300 rename_script,
1301 "%unew",
1302 newname_lower,
1303 true,
1304 false,
1305 true);
1306 if (!rename_script) {
1307 goto cancel;
1309 rename_script = talloc_string_sub2(new_acct,
1310 rename_script,
1311 "%uold",
1312 oldname_lower,
1313 true,
1314 false,
1315 true);
1316 if (!rename_script) {
1317 goto cancel;
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) {
1325 goto cancel;
1328 smb_nscd_flush_user_cache();
1330 /* rewrite the rid->username record */
1332 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1333 goto cancel;
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
1342 * account back?
1344 DEBUG(0, ("transaction_commit failed\n"));
1345 goto cancel;
1348 TALLOC_FREE(new_acct );
1349 return NT_STATUS_OK;
1351 cancel:
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)
1363 return False;
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)
1384 int32 version;
1386 if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
1387 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1388 return False;
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");
1399 return False;
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");
1408 return False;
1411 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1412 return True;
1415 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1417 TDB_CONTEXT *tdb;
1418 uint32 rid;
1419 bool ret = False;
1421 tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
1422 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1424 if (tdb == NULL) {
1425 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1426 goto done;
1429 if (!init_idmap_tdb(tdb)) {
1430 DEBUG(1, ("Could not init idmap\n"));
1431 goto done;
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"));
1438 goto done;
1441 *prid = rid;
1442 ret = True;
1444 done:
1445 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1446 smb_panic("tdb_close(idmap_tdb) failed");
1449 return ret;
1452 struct tdbsam_search_state {
1453 struct pdb_methods *methods;
1454 uint32_t acct_flags;
1456 uint32_t *rids;
1457 uint32_t num_rids;
1458 ssize_t array_size;
1459 uint32_t current;
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);
1467 uint32 rid;
1469 if ((rec->key.dsize < prefixlen)
1470 || (strncmp((char *)rec->key.dptr, RIDPREFIX, prefixlen))) {
1471 return 0;
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);
1479 return 0;
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);
1486 TALLOC_FREE(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;
1495 NTSTATUS status;
1496 uint32_t rid;
1498 again:
1499 TALLOC_FREE(user);
1500 user = samu_new(talloc_tos());
1501 if (user == NULL) {
1502 DEBUG(0, ("samu_new failed\n"));
1503 return false;
1506 if (state->current == state->num_rids) {
1507 return false;
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
1518 goto again;
1521 if (!NT_STATUS_IS_OK(status)) {
1522 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1523 nt_errstr(status)));
1524 TALLOC_FREE(user);
1525 return false;
1528 if ((state->acct_flags != 0) &&
1529 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1530 goto again;
1533 entry->acct_flags = pdb_get_acct_ctrl(user);
1534 entry->rid = rid;
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));
1542 TALLOC_FREE(user);
1544 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1545 || (entry->description == NULL)) {
1546 DEBUG(0, ("talloc_strdup failed\n"));
1547 return false;
1550 return true;
1553 static bool tdbsam_search_users(struct pdb_methods *methods,
1554 struct pdb_search *search,
1555 uint32 acct_flags)
1557 struct tdbsam_search_state *state;
1559 if (!tdbsam_open(tdbsam_filename)) {
1560 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1561 tdbsam_filename));
1562 return false;
1565 state = TALLOC_ZERO_P(search->mem_ctx, struct tdbsam_search_state);
1566 if (state == NULL) {
1567 DEBUG(0, ("talloc failed\n"));
1568 return false;
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;
1579 return true;
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)
1589 NTSTATUS nt_status;
1590 char *tdbfile = NULL;
1591 const char *pfile = location;
1593 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1594 return nt_status;
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 */
1612 if (!location) {
1613 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1614 PASSDB_FILE_NAME) < 0) {
1615 return NT_STATUS_NO_MEMORY;
1617 pfile = tdbfile;
1619 tdbsam_filename = SMB_STRDUP(pfile);
1620 if (!tdbsam_filename) {
1621 return NT_STATUS_NO_MEMORY;
1623 SAFE_FREE(tdbfile);
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);