When doing a cli_ulogoff don't invalidate the cnum, invalidate the vuid.
[Samba.git] / source / passdb / pdb_tdb.c
blob9b2de1cddd2a78df9a7a26cf1abeba5292bf6b49
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-2009
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_MINOR_VERSION 1 /* Most recent TDBSAM minor version */
42 #define TDBSAM_VERSION_STRING "INFO/version"
43 #define TDBSAM_MINOR_VERSION_STRING "INFO/minor_version"
44 #define PASSDB_FILE_NAME "passdb.tdb"
45 #define USERPREFIX "USER_"
46 #define USERPREFIX_LEN 5
47 #define RIDPREFIX "RID_"
48 #define PRIVPREFIX "PRIV_"
50 /* GLOBAL TDB SAM CONTEXT */
52 static struct db_context *db_sam;
53 static char *tdbsam_filename;
55 /**********************************************************************
56 Marshall/unmarshall struct samu structs.
57 *********************************************************************/
59 #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
60 #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
61 #define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
63 /*********************************************************************
64 *********************************************************************/
66 static bool init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
69 /* times are stored as 32bit integer
70 take care on system with 64bit wide time_t
71 --SSS */
72 uint32 logon_time,
73 logoff_time,
74 kickoff_time,
75 pass_last_set_time,
76 pass_can_change_time,
77 pass_must_change_time;
78 char *username = NULL;
79 char *domain = NULL;
80 char *nt_username = NULL;
81 char *dir_drive = NULL;
82 char *unknown_str = NULL;
83 char *munged_dial = NULL;
84 char *fullname = NULL;
85 char *homedir = NULL;
86 char *logon_script = NULL;
87 char *profile_path = NULL;
88 char *acct_desc = NULL;
89 char *workstations = NULL;
90 uint32 username_len, domain_len, nt_username_len,
91 dir_drive_len, unknown_str_len, munged_dial_len,
92 fullname_len, homedir_len, logon_script_len,
93 profile_path_len, acct_desc_len, workstations_len;
95 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
96 uint16 acct_ctrl, logon_divs;
97 uint16 bad_password_count, logon_count;
98 uint8 *hours = NULL;
99 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
100 uint32 len = 0;
101 uint32 lm_pw_len, nt_pw_len, hourslen;
102 bool ret = True;
104 if(sampass == NULL || buf == NULL) {
105 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
106 return False;
109 /* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
111 /* unpack the buffer into variables */
112 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V0,
113 &logon_time, /* d */
114 &logoff_time, /* d */
115 &kickoff_time, /* d */
116 &pass_last_set_time, /* d */
117 &pass_can_change_time, /* d */
118 &pass_must_change_time, /* d */
119 &username_len, &username, /* B */
120 &domain_len, &domain, /* B */
121 &nt_username_len, &nt_username, /* B */
122 &fullname_len, &fullname, /* B */
123 &homedir_len, &homedir, /* B */
124 &dir_drive_len, &dir_drive, /* B */
125 &logon_script_len, &logon_script, /* B */
126 &profile_path_len, &profile_path, /* B */
127 &acct_desc_len, &acct_desc, /* B */
128 &workstations_len, &workstations, /* B */
129 &unknown_str_len, &unknown_str, /* B */
130 &munged_dial_len, &munged_dial, /* B */
131 &user_rid, /* d */
132 &group_rid, /* d */
133 &lm_pw_len, &lm_pw_ptr, /* B */
134 &nt_pw_len, &nt_pw_ptr, /* B */
135 &acct_ctrl, /* w */
136 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
137 &logon_divs, /* w */
138 &hours_len, /* d */
139 &hourslen, &hours, /* B */
140 &bad_password_count, /* w */
141 &logon_count, /* w */
142 &unknown_6); /* d */
144 if (len == (uint32) -1) {
145 ret = False;
146 goto done;
149 pdb_set_logon_time(sampass, logon_time, PDB_SET);
150 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
151 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
152 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
153 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
154 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
156 pdb_set_username(sampass, username, PDB_SET);
157 pdb_set_domain(sampass, domain, PDB_SET);
158 pdb_set_nt_username(sampass, nt_username, PDB_SET);
159 pdb_set_fullname(sampass, fullname, PDB_SET);
161 if (homedir) {
162 pdb_set_homedir(sampass, homedir, PDB_SET);
164 else {
165 pdb_set_homedir(sampass,
166 talloc_sub_basic(sampass, username, domain,
167 lp_logon_home()),
168 PDB_DEFAULT);
171 if (dir_drive)
172 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
173 else {
174 pdb_set_dir_drive(sampass,
175 talloc_sub_basic(sampass, username, domain,
176 lp_logon_drive()),
177 PDB_DEFAULT);
180 if (logon_script)
181 pdb_set_logon_script(sampass, logon_script, PDB_SET);
182 else {
183 pdb_set_logon_script(sampass,
184 talloc_sub_basic(sampass, username, domain,
185 lp_logon_script()),
186 PDB_DEFAULT);
189 if (profile_path) {
190 pdb_set_profile_path(sampass, profile_path, PDB_SET);
191 } else {
192 pdb_set_profile_path(sampass,
193 talloc_sub_basic(sampass, username, domain,
194 lp_logon_path()),
195 PDB_DEFAULT);
198 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
199 pdb_set_workstations(sampass, workstations, PDB_SET);
200 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
202 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
203 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
204 ret = False;
205 goto done;
209 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
210 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
211 ret = False;
212 goto done;
216 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
217 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
218 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
219 pdb_set_hours_len(sampass, hours_len, PDB_SET);
220 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
221 pdb_set_logon_count(sampass, logon_count, PDB_SET);
222 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
223 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
224 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
225 pdb_set_hours(sampass, hours, PDB_SET);
227 done:
229 SAFE_FREE(username);
230 SAFE_FREE(domain);
231 SAFE_FREE(nt_username);
232 SAFE_FREE(fullname);
233 SAFE_FREE(homedir);
234 SAFE_FREE(dir_drive);
235 SAFE_FREE(logon_script);
236 SAFE_FREE(profile_path);
237 SAFE_FREE(acct_desc);
238 SAFE_FREE(workstations);
239 SAFE_FREE(munged_dial);
240 SAFE_FREE(unknown_str);
241 SAFE_FREE(lm_pw_ptr);
242 SAFE_FREE(nt_pw_ptr);
243 SAFE_FREE(hours);
245 return ret;
248 /*********************************************************************
249 *********************************************************************/
251 static bool init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
254 /* times are stored as 32bit integer
255 take care on system with 64bit wide time_t
256 --SSS */
257 uint32 logon_time,
258 logoff_time,
259 kickoff_time,
260 bad_password_time,
261 pass_last_set_time,
262 pass_can_change_time,
263 pass_must_change_time;
264 char *username = NULL;
265 char *domain = NULL;
266 char *nt_username = NULL;
267 char *dir_drive = NULL;
268 char *unknown_str = NULL;
269 char *munged_dial = NULL;
270 char *fullname = NULL;
271 char *homedir = NULL;
272 char *logon_script = NULL;
273 char *profile_path = NULL;
274 char *acct_desc = NULL;
275 char *workstations = NULL;
276 uint32 username_len, domain_len, nt_username_len,
277 dir_drive_len, unknown_str_len, munged_dial_len,
278 fullname_len, homedir_len, logon_script_len,
279 profile_path_len, acct_desc_len, workstations_len;
281 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
282 uint16 acct_ctrl, logon_divs;
283 uint16 bad_password_count, logon_count;
284 uint8 *hours = NULL;
285 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
286 uint32 len = 0;
287 uint32 lm_pw_len, nt_pw_len, hourslen;
288 bool ret = True;
290 if(sampass == NULL || buf == NULL) {
291 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
292 return False;
295 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
297 /* unpack the buffer into variables */
298 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V1,
299 &logon_time, /* d */
300 &logoff_time, /* d */
301 &kickoff_time, /* d */
302 /* Change from V0 is addition of bad_password_time field. */
303 &bad_password_time, /* d */
304 &pass_last_set_time, /* d */
305 &pass_can_change_time, /* d */
306 &pass_must_change_time, /* d */
307 &username_len, &username, /* B */
308 &domain_len, &domain, /* B */
309 &nt_username_len, &nt_username, /* B */
310 &fullname_len, &fullname, /* B */
311 &homedir_len, &homedir, /* B */
312 &dir_drive_len, &dir_drive, /* B */
313 &logon_script_len, &logon_script, /* B */
314 &profile_path_len, &profile_path, /* B */
315 &acct_desc_len, &acct_desc, /* B */
316 &workstations_len, &workstations, /* B */
317 &unknown_str_len, &unknown_str, /* B */
318 &munged_dial_len, &munged_dial, /* B */
319 &user_rid, /* d */
320 &group_rid, /* d */
321 &lm_pw_len, &lm_pw_ptr, /* B */
322 &nt_pw_len, &nt_pw_ptr, /* B */
323 &acct_ctrl, /* w */
324 &remove_me, /* d */
325 &logon_divs, /* w */
326 &hours_len, /* d */
327 &hourslen, &hours, /* B */
328 &bad_password_count, /* w */
329 &logon_count, /* w */
330 &unknown_6); /* d */
332 if (len == (uint32) -1) {
333 ret = False;
334 goto done;
337 pdb_set_logon_time(sampass, logon_time, PDB_SET);
338 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
339 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
341 /* Change from V0 is addition of bad_password_time field. */
342 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
343 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
344 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
345 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
347 pdb_set_username(sampass, username, PDB_SET);
348 pdb_set_domain(sampass, domain, PDB_SET);
349 pdb_set_nt_username(sampass, nt_username, PDB_SET);
350 pdb_set_fullname(sampass, fullname, PDB_SET);
352 if (homedir) {
353 pdb_set_homedir(sampass, homedir, PDB_SET);
355 else {
356 pdb_set_homedir(sampass,
357 talloc_sub_basic(sampass, username, domain,
358 lp_logon_home()),
359 PDB_DEFAULT);
362 if (dir_drive)
363 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
364 else {
365 pdb_set_dir_drive(sampass,
366 talloc_sub_basic(sampass, username, domain,
367 lp_logon_drive()),
368 PDB_DEFAULT);
371 if (logon_script)
372 pdb_set_logon_script(sampass, logon_script, PDB_SET);
373 else {
374 pdb_set_logon_script(sampass,
375 talloc_sub_basic(sampass, username, domain,
376 lp_logon_script()),
377 PDB_DEFAULT);
380 if (profile_path) {
381 pdb_set_profile_path(sampass, profile_path, PDB_SET);
382 } else {
383 pdb_set_profile_path(sampass,
384 talloc_sub_basic(sampass, username, domain,
385 lp_logon_path()),
386 PDB_DEFAULT);
389 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
390 pdb_set_workstations(sampass, workstations, PDB_SET);
391 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
393 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
394 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
395 ret = False;
396 goto done;
400 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
401 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
402 ret = False;
403 goto done;
407 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
409 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
410 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
411 pdb_set_hours_len(sampass, hours_len, PDB_SET);
412 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
413 pdb_set_logon_count(sampass, logon_count, PDB_SET);
414 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
415 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
416 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
417 pdb_set_hours(sampass, hours, PDB_SET);
419 done:
421 SAFE_FREE(username);
422 SAFE_FREE(domain);
423 SAFE_FREE(nt_username);
424 SAFE_FREE(fullname);
425 SAFE_FREE(homedir);
426 SAFE_FREE(dir_drive);
427 SAFE_FREE(logon_script);
428 SAFE_FREE(profile_path);
429 SAFE_FREE(acct_desc);
430 SAFE_FREE(workstations);
431 SAFE_FREE(munged_dial);
432 SAFE_FREE(unknown_str);
433 SAFE_FREE(lm_pw_ptr);
434 SAFE_FREE(nt_pw_ptr);
435 SAFE_FREE(hours);
437 return ret;
440 bool init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
443 /* times are stored as 32bit integer
444 take care on system with 64bit wide time_t
445 --SSS */
446 uint32 logon_time,
447 logoff_time,
448 kickoff_time,
449 bad_password_time,
450 pass_last_set_time,
451 pass_can_change_time,
452 pass_must_change_time;
453 char *username = NULL;
454 char *domain = NULL;
455 char *nt_username = NULL;
456 char *dir_drive = NULL;
457 char *unknown_str = NULL;
458 char *munged_dial = NULL;
459 char *fullname = NULL;
460 char *homedir = NULL;
461 char *logon_script = NULL;
462 char *profile_path = NULL;
463 char *acct_desc = NULL;
464 char *workstations = NULL;
465 uint32 username_len, domain_len, nt_username_len,
466 dir_drive_len, unknown_str_len, munged_dial_len,
467 fullname_len, homedir_len, logon_script_len,
468 profile_path_len, acct_desc_len, workstations_len;
470 uint32 user_rid, group_rid, hours_len, unknown_6;
471 uint16 acct_ctrl, logon_divs;
472 uint16 bad_password_count, logon_count;
473 uint8 *hours = NULL;
474 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
475 uint32 len = 0;
476 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
477 uint32 pwHistLen = 0;
478 bool ret = True;
479 fstring tmp_string;
480 bool expand_explicit = lp_passdb_expand_explicit();
482 if(sampass == NULL || buf == NULL) {
483 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
484 return False;
487 /* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
489 /* unpack the buffer into variables */
490 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING_V2,
491 &logon_time, /* d */
492 &logoff_time, /* d */
493 &kickoff_time, /* d */
494 &bad_password_time, /* d */
495 &pass_last_set_time, /* d */
496 &pass_can_change_time, /* d */
497 &pass_must_change_time, /* d */
498 &username_len, &username, /* B */
499 &domain_len, &domain, /* B */
500 &nt_username_len, &nt_username, /* B */
501 &fullname_len, &fullname, /* B */
502 &homedir_len, &homedir, /* B */
503 &dir_drive_len, &dir_drive, /* B */
504 &logon_script_len, &logon_script, /* B */
505 &profile_path_len, &profile_path, /* B */
506 &acct_desc_len, &acct_desc, /* B */
507 &workstations_len, &workstations, /* B */
508 &unknown_str_len, &unknown_str, /* B */
509 &munged_dial_len, &munged_dial, /* B */
510 &user_rid, /* d */
511 &group_rid, /* d */
512 &lm_pw_len, &lm_pw_ptr, /* B */
513 &nt_pw_len, &nt_pw_ptr, /* B */
514 /* Change from V1 is addition of password history field. */
515 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
516 &acct_ctrl, /* w */
517 /* Also "remove_me" field was removed. */
518 &logon_divs, /* w */
519 &hours_len, /* d */
520 &hourslen, &hours, /* B */
521 &bad_password_count, /* w */
522 &logon_count, /* w */
523 &unknown_6); /* d */
525 if (len == (uint32) -1) {
526 ret = False;
527 goto done;
530 pdb_set_logon_time(sampass, logon_time, PDB_SET);
531 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
532 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
533 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
534 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
535 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
536 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
538 pdb_set_username(sampass, username, PDB_SET);
539 pdb_set_domain(sampass, domain, PDB_SET);
540 pdb_set_nt_username(sampass, nt_username, PDB_SET);
541 pdb_set_fullname(sampass, fullname, PDB_SET);
543 if (homedir) {
544 fstrcpy( tmp_string, homedir );
545 if (expand_explicit) {
546 standard_sub_basic( username, domain, tmp_string,
547 sizeof(tmp_string) );
549 pdb_set_homedir(sampass, tmp_string, PDB_SET);
551 else {
552 pdb_set_homedir(sampass,
553 talloc_sub_basic(sampass, username, domain,
554 lp_logon_home()),
555 PDB_DEFAULT);
558 if (dir_drive)
559 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
560 else
561 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
563 if (logon_script) {
564 fstrcpy( tmp_string, logon_script );
565 if (expand_explicit) {
566 standard_sub_basic( username, domain, tmp_string,
567 sizeof(tmp_string) );
569 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
571 else {
572 pdb_set_logon_script(sampass,
573 talloc_sub_basic(sampass, username, domain,
574 lp_logon_script()),
575 PDB_DEFAULT);
578 if (profile_path) {
579 fstrcpy( tmp_string, profile_path );
580 if (expand_explicit) {
581 standard_sub_basic( username, domain, tmp_string,
582 sizeof(tmp_string) );
584 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
586 else {
587 pdb_set_profile_path(sampass,
588 talloc_sub_basic(sampass, username, domain,
589 lp_logon_path()),
590 PDB_DEFAULT);
593 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
594 pdb_set_workstations(sampass, workstations, PDB_SET);
595 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
597 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
598 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
599 ret = False;
600 goto done;
604 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
605 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
606 ret = False;
607 goto done;
611 /* Change from V1 is addition of password history field. */
612 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
613 if (pwHistLen) {
614 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
615 if (!pw_hist) {
616 ret = False;
617 goto done;
619 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
620 if (nt_pw_hist_ptr && nt_pw_hist_len) {
621 int i;
622 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
623 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
624 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
625 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
626 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
627 PW_HISTORY_ENTRY_LEN);
630 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
631 SAFE_FREE(pw_hist);
632 ret = False;
633 goto done;
635 SAFE_FREE(pw_hist);
636 } else {
637 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
640 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
641 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
642 pdb_set_hours_len(sampass, hours_len, PDB_SET);
643 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
644 pdb_set_logon_count(sampass, logon_count, PDB_SET);
645 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
646 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
647 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
648 pdb_set_hours(sampass, hours, PDB_SET);
650 done:
652 SAFE_FREE(username);
653 SAFE_FREE(domain);
654 SAFE_FREE(nt_username);
655 SAFE_FREE(fullname);
656 SAFE_FREE(homedir);
657 SAFE_FREE(dir_drive);
658 SAFE_FREE(logon_script);
659 SAFE_FREE(profile_path);
660 SAFE_FREE(acct_desc);
661 SAFE_FREE(workstations);
662 SAFE_FREE(munged_dial);
663 SAFE_FREE(unknown_str);
664 SAFE_FREE(lm_pw_ptr);
665 SAFE_FREE(nt_pw_ptr);
666 SAFE_FREE(nt_pw_hist_ptr);
667 SAFE_FREE(hours);
669 return ret;
673 /**********************************************************************
674 Intialize a struct samu struct from a BYTE buffer of size len
675 *********************************************************************/
677 static bool init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
679 return init_sam_from_buffer_v3(sampass, buf, buflen);
682 /**********************************************************************
683 Intialize a BYTE buffer from a struct samu struct
684 *********************************************************************/
686 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, bool size_only)
688 return init_buffer_from_sam_v3(buf, sampass, size_only);
691 /**********************************************************************
692 Struct and function to update an old record.
693 *********************************************************************/
695 struct tdbsam_convert_state {
696 int32_t from;
697 bool success;
700 static int tdbsam_convert_one(struct db_record *rec, void *priv)
702 struct tdbsam_convert_state *state =
703 (struct tdbsam_convert_state *)priv;
704 struct samu *user;
705 TDB_DATA data;
706 NTSTATUS status;
707 bool ret;
709 if (rec->key.dsize < USERPREFIX_LEN) {
710 return 0;
712 if (strncmp((char *)rec->key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
713 return 0;
716 user = samu_new(talloc_tos());
717 if (user == NULL) {
718 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
719 state->success = false;
720 return -1;
723 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
724 "(version:%d)\n", rec->key.dptr, state->from));
726 switch (state->from) {
727 case 0:
728 ret = init_sam_from_buffer_v0(user, (uint8 *)rec->value.dptr,
729 rec->value.dsize);
730 break;
731 case 1:
732 ret = init_sam_from_buffer_v1(user, (uint8 *)rec->value.dptr,
733 rec->value.dsize);
734 break;
735 case 2:
736 ret = init_sam_from_buffer_v2(user, (uint8 *)rec->value.dptr,
737 rec->value.dsize);
738 break;
739 case 3:
740 ret = init_sam_from_buffer_v3(user, (uint8 *)rec->value.dptr,
741 rec->value.dsize);
742 break;
743 default:
744 /* unknown tdbsam version */
745 ret = False;
747 if (!ret) {
748 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
749 "from TDB (key:%s) (version:%d)\n", rec->key.dptr,
750 state->from));
751 TALLOC_FREE(user);
752 state->success = false;
753 return -1;
756 data.dsize = init_buffer_from_sam(&data.dptr, user, false);
757 TALLOC_FREE(user);
759 if (data.dsize == -1) {
760 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
761 "the new format\n"));
762 state->success = false;
763 return -1;
766 status = rec->store(rec, data, TDB_MODIFY);
767 if (!NT_STATUS_IS_OK(status)) {
768 DEBUG(0, ("Could not store the new record: %s\n",
769 nt_errstr(status)));
770 state->success = false;
771 return -1;
774 return 0;
777 /**********************************************************************
778 Struct and function to backup an old record.
779 *********************************************************************/
781 struct tdbsam_backup_state {
782 struct db_context *new_db;
783 bool success;
786 static int backup_copy_fn(struct db_record *orig_rec, void *state)
788 struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state;
789 struct db_record *new_rec;
790 NTSTATUS status;
792 new_rec = bs->new_db->fetch_locked(bs->new_db, talloc_tos(), orig_rec->key);
793 if (new_rec == NULL) {
794 bs->success = false;
795 return 1;
798 status = new_rec->store(new_rec, orig_rec->value, TDB_INSERT);
800 TALLOC_FREE(new_rec);
802 if (!NT_STATUS_IS_OK(status)) {
803 bs->success = false;
804 return 1;
806 return 0;
809 /**********************************************************************
810 Make a backup of an old passdb and replace the new one with it. We
811 have to do this as between 3.0.x and 3.2.x the hash function changed
812 by mistake (used unsigned char * instead of char *). This means the
813 previous simple update code will fail due to not being able to find
814 existing records to replace in the tdbsam_convert_one() function. JRA.
815 *********************************************************************/
817 static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db)
819 TALLOC_CTX *frame = talloc_stackframe();
820 const char *tmp_fname = NULL;
821 struct db_context *tmp_db = NULL;
822 struct db_context *orig_db = *pp_db;
823 struct tdbsam_backup_state bs;
824 int ret;
826 tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname);
827 if (!tmp_fname) {
828 TALLOC_FREE(frame);
829 return false;
832 unlink(tmp_fname);
834 /* Remember to open this on the NULL context. We need
835 * it to stay around after we return from here. */
837 tmp_db = db_open_trans(NULL, tmp_fname, 0,
838 TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
839 if (tmp_db == NULL) {
840 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
841 "[%s]\n", tmp_fname));
842 TALLOC_FREE(frame);
843 return false;
846 if (orig_db->transaction_start(orig_db) != 0) {
847 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
848 unlink(tmp_fname);
849 TALLOC_FREE(tmp_db);
850 TALLOC_FREE(frame);
851 return false;
853 if (tmp_db->transaction_start(tmp_db) != 0) {
854 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
855 orig_db->transaction_cancel(orig_db);
856 unlink(tmp_fname);
857 TALLOC_FREE(tmp_db);
858 TALLOC_FREE(frame);
859 return false;
862 bs.new_db = tmp_db;
863 bs.success = true;
865 ret = orig_db->traverse(orig_db, backup_copy_fn, (void *)&bs);
866 if (ret < 0) {
867 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
868 goto cancel;
871 if (!bs.success) {
872 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
873 goto cancel;
876 if (orig_db->transaction_commit(orig_db) != 0) {
877 smb_panic("tdbsam_convert_backup: orig commit failed\n");
879 if (tmp_db->transaction_commit(tmp_db) != 0) {
880 smb_panic("tdbsam_convert_backup: orig commit failed\n");
883 /* be sure to close the DBs _before_ renaming the file */
885 TALLOC_FREE(orig_db);
886 TALLOC_FREE(tmp_db);
888 /* This is safe from other users as we know we're
889 * under a mutex here. */
891 if (rename(tmp_fname, dbname) == -1) {
892 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
893 tmp_fname,
894 dbname,
895 strerror(errno)));
896 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
899 TALLOC_FREE(frame);
901 /* re-open the converted TDB */
903 orig_db = db_open_trans(NULL, dbname, 0,
904 TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
905 if (orig_db == NULL) {
906 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
907 "converted passdb TDB [%s]\n", dbname));
908 return false;
911 DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
912 dbname ));
914 /* Replace the global db pointer. */
915 *pp_db = orig_db;
916 return true;
918 cancel:
920 if (orig_db->transaction_cancel(orig_db) != 0) {
921 smb_panic("tdbsam_convert: transaction_cancel failed");
924 if (tmp_db->transaction_cancel(tmp_db) != 0) {
925 smb_panic("tdbsam_convert: transaction_cancel failed");
928 unlink(tmp_fname);
929 TALLOC_FREE(tmp_db);
930 TALLOC_FREE(frame);
931 return false;
934 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from)
936 struct tdbsam_convert_state state;
937 struct db_context *db = NULL;
938 int ret;
940 /* We only need the update backup for local db's. */
941 if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) {
942 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name));
943 return false;
946 db = *pp_db;
947 state.from = from;
948 state.success = true;
950 if (db->transaction_start(db) != 0) {
951 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
952 return false;
955 ret = db->traverse(db, tdbsam_convert_one, &state);
956 if (ret < 0) {
957 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
958 goto cancel;
961 if (!state.success) {
962 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
963 goto cancel;
966 if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING,
967 TDBSAM_VERSION) != 0) {
968 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n"));
969 goto cancel;
972 if (dbwrap_store_int32(db, TDBSAM_MINOR_VERSION_STRING,
973 TDBSAM_MINOR_VERSION) != 0) {
974 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor version\n"));
975 goto cancel;
978 if (db->transaction_commit(db) != 0) {
979 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
980 goto cancel;
983 return true;
985 cancel:
986 if (db->transaction_cancel(db) != 0) {
987 smb_panic("tdbsam_convert: transaction_cancel failed");
990 return false;
993 /*********************************************************************
994 Open the tdbsam file based on the absolute path specified.
995 Uses a reference count to allow multiple open calls.
996 *********************************************************************/
998 static bool tdbsam_open( const char *name )
1000 int32 version;
1001 int32 minor_version;
1003 /* check if we are already open */
1005 if ( db_sam ) {
1006 return true;
1009 /* Try to open tdb passwd. Create a new one if necessary */
1011 db_sam = db_open_trans(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600);
1012 if (db_sam == NULL) {
1013 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
1014 "[%s]\n", name));
1015 return false;
1018 /* Check the version */
1019 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
1020 if (version == -1) {
1021 version = 0; /* Version not found, assume version 0 */
1024 /* Get the minor version */
1025 minor_version = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING);
1026 if (minor_version == -1) {
1027 minor_version = 0; /* Minor version not found, assume 0 */
1030 /* Compare the version */
1031 if (version > TDBSAM_VERSION) {
1032 /* Version more recent than the latest known */
1033 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
1034 TALLOC_FREE(db_sam);
1035 return false;
1038 if ( version < TDBSAM_VERSION ||
1039 (version == TDBSAM_VERSION &&
1040 minor_version < TDBSAM_MINOR_VERSION) ) {
1042 * Ok - we think we're going to have to convert.
1043 * Due to the backup process we now must do to
1044 * upgrade we have to get a mutex and re-check
1045 * the version. Someone else may have upgraded
1046 * whilst we were checking.
1049 struct named_mutex *mtx = grab_named_mutex(NULL,
1050 "tdbsam_upgrade_mutex",
1051 600);
1053 if (!mtx) {
1054 DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
1055 TALLOC_FREE(db_sam);
1056 return false;
1059 /* Re-check the version */
1060 version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING);
1061 if (version == -1) {
1062 version = 0; /* Version not found, assume version 0 */
1065 /* Re-check the minor version */
1066 minor_version = dbwrap_fetch_int32(db_sam, TDBSAM_MINOR_VERSION_STRING);
1067 if (minor_version == -1) {
1068 minor_version = 0; /* Minor version not found, assume 0 */
1071 /* Compare the version */
1072 if (version > TDBSAM_VERSION) {
1073 /* Version more recent than the latest known */
1074 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
1075 TALLOC_FREE(db_sam);
1076 TALLOC_FREE(mtx);
1077 return false;
1080 if ( version < TDBSAM_VERSION ||
1081 (version == TDBSAM_VERSION &&
1082 minor_version < TDBSAM_MINOR_VERSION) ) {
1084 * Note that minor versions we read that are greater
1085 * than the current minor version we have hard coded
1086 * are assumed to be compatible if they have the same
1087 * major version. That allows previous versions of the
1088 * passdb code that don't know about minor versions to
1089 * still use this database. JRA.
1092 DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
1093 "version %d.%d.\n",
1094 version,
1095 minor_version,
1096 TDBSAM_VERSION,
1097 TDBSAM_MINOR_VERSION));
1099 if ( !tdbsam_convert(&db_sam, name, version) ) {
1100 DEBUG(0, ("tdbsam_open: Error when trying to convert "
1101 "tdbsam [%s]\n",name));
1102 TALLOC_FREE(db_sam);
1103 TALLOC_FREE(mtx);
1104 return false;
1107 DEBUG(3, ("TDBSAM converted successfully.\n"));
1109 TALLOC_FREE(mtx);
1112 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
1114 return true;
1117 /******************************************************************
1118 Lookup a name in the SAM TDB
1119 ******************************************************************/
1121 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
1122 struct samu *user, const char *sname)
1124 TDB_DATA data;
1125 fstring keystr;
1126 fstring name;
1128 if ( !user ) {
1129 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
1130 return NT_STATUS_NO_MEMORY;
1133 /* Data is stored in all lower-case */
1134 fstrcpy(name, sname);
1135 strlower_m(name);
1137 /* set search key */
1138 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1140 /* open the database */
1142 if ( !tdbsam_open( tdbsam_filename ) ) {
1143 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1144 return NT_STATUS_ACCESS_DENIED;
1147 /* get the record */
1149 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
1150 if (!data.dptr) {
1151 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
1152 DEBUGADD(5, (" Key: %s\n", keystr));
1153 return NT_STATUS_NO_SUCH_USER;
1156 /* unpack the buffer */
1158 if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
1159 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1160 SAFE_FREE(data.dptr);
1161 return NT_STATUS_NO_MEMORY;
1164 /* success */
1166 TALLOC_FREE(data.dptr);
1168 return NT_STATUS_OK;
1171 /***************************************************************************
1172 Search by rid
1173 **************************************************************************/
1175 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
1176 struct samu *user, uint32 rid)
1178 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1179 TDB_DATA data;
1180 fstring keystr;
1181 fstring name;
1183 if ( !user ) {
1184 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
1185 return nt_status;
1188 /* set search key */
1190 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1192 /* open the database */
1194 if ( !tdbsam_open( tdbsam_filename ) ) {
1195 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1196 return NT_STATUS_ACCESS_DENIED;
1199 /* get the record */
1201 data = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr);
1202 if (!data.dptr) {
1203 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
1204 return NT_STATUS_UNSUCCESSFUL;
1207 fstrcpy(name, (const char *)data.dptr);
1208 TALLOC_FREE(data.dptr);
1210 return tdbsam_getsampwnam (my_methods, user, name);
1213 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
1214 struct samu * user, const DOM_SID *sid)
1216 uint32 rid;
1218 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
1219 return NT_STATUS_UNSUCCESSFUL;
1221 return tdbsam_getsampwrid(my_methods, user, rid);
1224 static bool tdb_delete_samacct_only( struct samu *sam_pass )
1226 fstring keystr;
1227 fstring name;
1228 NTSTATUS status;
1230 fstrcpy(name, pdb_get_username(sam_pass));
1231 strlower_m(name);
1233 /* set the search key */
1235 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1237 /* it's outaa here! 8^) */
1239 status = dbwrap_delete_bystring(db_sam, keystr);
1240 if (!NT_STATUS_IS_OK(status)) {
1241 DEBUG(5, ("Error deleting entry from tdb passwd "
1242 "database: %s!\n", nt_errstr(status)));
1243 return false;
1246 return true;
1249 /***************************************************************************
1250 Delete a struct samu records for the username and RID key
1251 ****************************************************************************/
1253 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
1254 struct samu *sam_pass)
1256 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1257 fstring keystr;
1258 uint32 rid;
1259 fstring name;
1261 /* open the database */
1263 if ( !tdbsam_open( tdbsam_filename ) ) {
1264 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1265 tdbsam_filename));
1266 return NT_STATUS_ACCESS_DENIED;
1269 fstrcpy(name, pdb_get_username(sam_pass));
1270 strlower_m(name);
1272 /* set the search key */
1274 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1276 rid = pdb_get_user_rid(sam_pass);
1278 /* it's outaa here! 8^) */
1280 if (db_sam->transaction_start(db_sam) != 0) {
1281 DEBUG(0, ("Could not start transaction\n"));
1282 return NT_STATUS_UNSUCCESSFUL;
1285 nt_status = dbwrap_delete_bystring(db_sam, keystr);
1286 if (!NT_STATUS_IS_OK(nt_status)) {
1287 DEBUG(5, ("Error deleting entry from tdb passwd "
1288 "database: %s!\n", nt_errstr(nt_status)));
1289 goto cancel;
1292 /* set the search key */
1294 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1296 /* it's outaa here! 8^) */
1298 nt_status = dbwrap_delete_bystring(db_sam, keystr);
1299 if (!NT_STATUS_IS_OK(nt_status)) {
1300 DEBUG(5, ("Error deleting entry from tdb rid "
1301 "database: %s!\n", nt_errstr(nt_status)));
1302 goto cancel;
1305 if (db_sam->transaction_commit(db_sam) != 0) {
1306 DEBUG(0, ("Could not commit transaction\n"));
1307 goto cancel;
1310 return NT_STATUS_OK;
1312 cancel:
1313 if (db_sam->transaction_cancel(db_sam) != 0) {
1314 smb_panic("transaction_cancel failed");
1317 return nt_status;
1321 /***************************************************************************
1322 Update the TDB SAM account record only
1323 Assumes that the tdbsam is already open
1324 ****************************************************************************/
1325 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
1327 TDB_DATA data;
1328 uint8 *buf = NULL;
1329 fstring keystr;
1330 fstring name;
1331 bool ret = false;
1332 NTSTATUS status;
1334 /* copy the struct samu struct into a BYTE buffer for storage */
1336 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1337 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1338 goto done;
1340 data.dptr = buf;
1342 fstrcpy(name, pdb_get_username(newpwd));
1343 strlower_m(name);
1345 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1346 flag == TDB_INSERT ? "(new) " : "", name,
1347 pdb_get_user_rid(newpwd)));
1349 /* setup the USER index key */
1350 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1352 /* add the account */
1354 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 DEBUG(0, ("Unable to modify passwd TDB: %s!",
1357 nt_errstr(status)));
1358 goto done;
1361 ret = true;
1363 done:
1364 /* cleanup */
1365 SAFE_FREE(buf);
1366 return ret;
1369 /***************************************************************************
1370 Update the TDB SAM RID record only
1371 Assumes that the tdbsam is already open
1372 ****************************************************************************/
1373 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
1375 TDB_DATA data;
1376 fstring keystr;
1377 fstring name;
1378 NTSTATUS status;
1380 fstrcpy(name, pdb_get_username(newpwd));
1381 strlower_m(name);
1383 /* setup RID data */
1384 data = string_term_tdb_data(name);
1386 /* setup the RID index key */
1387 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
1388 pdb_get_user_rid(newpwd));
1390 /* add the reference */
1391 status = dbwrap_store_bystring(db_sam, keystr, data, flag);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
1394 nt_errstr(status)));
1395 return false;
1398 return true;
1402 /***************************************************************************
1403 Update the TDB SAM
1404 ****************************************************************************/
1406 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
1407 int flag)
1409 uint32_t oldrid;
1410 uint32_t newrid;
1412 if (!(newrid = pdb_get_user_rid(newpwd))) {
1413 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
1414 pdb_get_username(newpwd)));
1415 return False;
1418 oldrid = newrid;
1420 /* open the database */
1422 if ( !tdbsam_open( tdbsam_filename ) ) {
1423 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1424 return False;
1427 if (db_sam->transaction_start(db_sam) != 0) {
1428 DEBUG(0, ("Could not start transaction\n"));
1429 return false;
1432 /* If we are updating, we may be changing this users RID. Retrieve the old RID
1433 so we can check. */
1435 if (flag == TDB_MODIFY) {
1436 struct samu *account = samu_new(talloc_tos());
1437 if (account == NULL) {
1438 DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
1439 goto cancel;
1441 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods, account, pdb_get_username(newpwd)))) {
1442 DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
1443 pdb_get_username(newpwd)));
1444 TALLOC_FREE(account);
1445 goto cancel;
1447 if (!(oldrid = pdb_get_user_rid(account))) {
1448 DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
1449 TALLOC_FREE(account);
1450 goto cancel;
1452 TALLOC_FREE(account);
1455 /* Update the new samu entry. */
1456 if (!tdb_update_samacct_only(newpwd, flag)) {
1457 goto cancel;
1460 /* Now take care of the case where the RID changed. We need
1461 * to delete the old RID key and add the new. */
1463 if (flag == TDB_MODIFY && newrid != oldrid) {
1464 fstring keystr;
1466 /* Delete old RID key */
1467 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid));
1468 slprintf(keystr, sizeof(keystr) - 1, "%s%.8x", RIDPREFIX, oldrid);
1469 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam, keystr))) {
1470 DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr));
1471 goto cancel;
1473 /* Insert new RID key */
1474 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid));
1475 if (!tdb_update_ridrec_only(newpwd, TDB_INSERT)) {
1476 goto cancel;
1478 } else {
1479 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
1480 flag == TDB_MODIFY ? "Updating" : "Inserting", newrid));
1481 if (!tdb_update_ridrec_only(newpwd, flag)) {
1482 goto cancel;
1486 if (db_sam->transaction_commit(db_sam) != 0) {
1487 DEBUG(0, ("Could not commit transaction\n"));
1488 goto cancel;
1491 return true;
1493 cancel:
1494 if (db_sam->transaction_cancel(db_sam) != 0) {
1495 smb_panic("transaction_cancel failed");
1497 return false;
1500 /***************************************************************************
1501 Modifies an existing struct samu
1502 ****************************************************************************/
1504 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1506 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1507 return NT_STATUS_UNSUCCESSFUL;
1509 return NT_STATUS_OK;
1512 /***************************************************************************
1513 Adds an existing struct samu
1514 ****************************************************************************/
1516 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1518 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1519 return NT_STATUS_UNSUCCESSFUL;
1521 return NT_STATUS_OK;
1524 /***************************************************************************
1525 Renames a struct samu
1526 - check for the posix user/rename user script
1527 - Add and lock the new user record
1528 - rename the posix user
1529 - rewrite the rid->username record
1530 - delete the old user
1531 - unlock the new user record
1532 ***************************************************************************/
1533 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1534 struct samu *old_acct,
1535 const char *newname)
1537 struct samu *new_acct = NULL;
1538 char *rename_script = NULL;
1539 int rename_ret;
1540 fstring oldname_lower;
1541 fstring newname_lower;
1543 /* can't do anything without an external script */
1545 if ( !(new_acct = samu_new( talloc_tos() )) ) {
1546 return NT_STATUS_NO_MEMORY;
1549 rename_script = talloc_strdup(new_acct, lp_renameuser_script());
1550 if (!rename_script) {
1551 TALLOC_FREE(new_acct);
1552 return NT_STATUS_NO_MEMORY;
1554 if (!*rename_script) {
1555 TALLOC_FREE(new_acct);
1556 return NT_STATUS_ACCESS_DENIED;
1559 if ( !pdb_copy_sam_account(new_acct, old_acct)
1560 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1562 TALLOC_FREE(new_acct);
1563 return NT_STATUS_NO_MEMORY;
1566 /* open the database */
1567 if ( !tdbsam_open( tdbsam_filename ) ) {
1568 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1569 tdbsam_filename));
1570 TALLOC_FREE(new_acct);
1571 return NT_STATUS_ACCESS_DENIED;
1574 if (db_sam->transaction_start(db_sam) != 0) {
1575 DEBUG(0, ("Could not start transaction\n"));
1576 TALLOC_FREE(new_acct);
1577 return NT_STATUS_ACCESS_DENIED;
1581 /* add the new account and lock it */
1582 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1583 goto cancel;
1586 /* Rename the posix user. Follow the semantics of _samr_create_user()
1587 so that we lower case the posix name but preserve the case in passdb */
1589 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1590 strlower_m( oldname_lower );
1592 fstrcpy( newname_lower, newname );
1593 strlower_m( newname_lower );
1595 rename_script = talloc_string_sub2(new_acct,
1596 rename_script,
1597 "%unew",
1598 newname_lower,
1599 true,
1600 false,
1601 true);
1602 if (!rename_script) {
1603 goto cancel;
1605 rename_script = talloc_string_sub2(new_acct,
1606 rename_script,
1607 "%uold",
1608 oldname_lower,
1609 true,
1610 false,
1611 true);
1612 if (!rename_script) {
1613 goto cancel;
1615 rename_ret = smbrun(rename_script, NULL);
1617 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
1618 rename_script, rename_ret));
1620 if (rename_ret != 0) {
1621 goto cancel;
1624 smb_nscd_flush_user_cache();
1626 /* rewrite the rid->username record */
1628 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1629 goto cancel;
1632 tdb_delete_samacct_only( old_acct );
1634 if (db_sam->transaction_commit(db_sam) != 0) {
1636 * Ok, we're screwed. We've changed the posix account, but
1637 * could not adapt passdb.tdb. Shall we change the posix
1638 * account back?
1640 DEBUG(0, ("transaction_commit failed\n"));
1641 goto cancel;
1644 TALLOC_FREE(new_acct );
1645 return NT_STATUS_OK;
1647 cancel:
1648 if (db_sam->transaction_cancel(db_sam) != 0) {
1649 smb_panic("transaction_cancel failed");
1652 TALLOC_FREE(new_acct);
1654 return NT_STATUS_ACCESS_DENIED;
1657 static bool tdbsam_rid_algorithm(struct pdb_methods *methods)
1659 return False;
1663 * Historically, winbind was responsible for allocating RIDs, so the next RID
1664 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1665 * but for compatibility reasons we still keep the the next RID counter in
1666 * winbindd_idmap.tdb.
1669 /*****************************************************************************
1670 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1671 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1672 winbind completely and store the RID counter in passdb.tdb.
1674 Dont' fully initialize with the HWM values, if it's new, we're only
1675 interested in the RID counter.
1676 *****************************************************************************/
1678 static bool init_idmap_tdb(TDB_CONTEXT *tdb)
1680 int32 version;
1682 if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
1683 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1684 return False;
1687 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1689 if (version == -1) {
1690 /* No key found, must be a new db */
1691 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1692 IDMAP_VERSION) != 0) {
1693 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1694 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1695 return False;
1697 version = IDMAP_VERSION;
1700 if (version != IDMAP_VERSION) {
1701 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1702 "start winbind once\n", IDMAP_VERSION, version));
1703 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1704 return False;
1707 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1708 return True;
1711 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1713 TDB_CONTEXT *tdb;
1714 uint32 rid;
1715 bool ret = False;
1717 tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
1718 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1720 if (tdb == NULL) {
1721 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1722 goto done;
1725 if (!init_idmap_tdb(tdb)) {
1726 DEBUG(1, ("Could not init idmap\n"));
1727 goto done;
1730 rid = BASE_RID; /* Default if not set */
1732 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1733 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1734 goto done;
1737 *prid = rid;
1738 ret = True;
1740 done:
1741 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1742 smb_panic("tdb_close(idmap_tdb) failed");
1745 return ret;
1748 struct tdbsam_search_state {
1749 struct pdb_methods *methods;
1750 uint32_t acct_flags;
1752 uint32_t *rids;
1753 uint32_t num_rids;
1754 ssize_t array_size;
1755 uint32_t current;
1758 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1760 struct tdbsam_search_state *state = talloc_get_type_abort(
1761 private_data, struct tdbsam_search_state);
1762 size_t prefixlen = strlen(RIDPREFIX);
1763 uint32 rid;
1765 if ((rec->key.dsize < prefixlen)
1766 || (strncmp((char *)rec->key.dptr, RIDPREFIX, prefixlen))) {
1767 return 0;
1770 rid = strtoul((char *)rec->key.dptr+prefixlen, NULL, 16);
1772 ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1773 &state->array_size);
1775 return 0;
1778 static void tdbsam_search_end(struct pdb_search *search)
1780 struct tdbsam_search_state *state = talloc_get_type_abort(
1781 search->private_data, struct tdbsam_search_state);
1782 TALLOC_FREE(state);
1785 static bool tdbsam_search_next_entry(struct pdb_search *search,
1786 struct samr_displayentry *entry)
1788 struct tdbsam_search_state *state = talloc_get_type_abort(
1789 search->private_data, struct tdbsam_search_state);
1790 struct samu *user = NULL;
1791 NTSTATUS status;
1792 uint32_t rid;
1794 again:
1795 TALLOC_FREE(user);
1796 user = samu_new(talloc_tos());
1797 if (user == NULL) {
1798 DEBUG(0, ("samu_new failed\n"));
1799 return false;
1802 if (state->current == state->num_rids) {
1803 return false;
1806 rid = state->rids[state->current++];
1808 status = tdbsam_getsampwrid(state->methods, user, rid);
1810 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1812 * Someone has deleted that user since we listed the RIDs
1814 goto again;
1817 if (!NT_STATUS_IS_OK(status)) {
1818 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1819 nt_errstr(status)));
1820 TALLOC_FREE(user);
1821 return false;
1824 if ((state->acct_flags != 0) &&
1825 ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1826 goto again;
1829 entry->acct_flags = pdb_get_acct_ctrl(user);
1830 entry->rid = rid;
1831 entry->account_name = talloc_strdup(
1832 search->mem_ctx, pdb_get_username(user));
1833 entry->fullname = talloc_strdup(
1834 search->mem_ctx, pdb_get_fullname(user));
1835 entry->description = talloc_strdup(
1836 search->mem_ctx, pdb_get_acct_desc(user));
1838 TALLOC_FREE(user);
1840 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1841 || (entry->description == NULL)) {
1842 DEBUG(0, ("talloc_strdup failed\n"));
1843 return false;
1846 return true;
1849 static bool tdbsam_search_users(struct pdb_methods *methods,
1850 struct pdb_search *search,
1851 uint32 acct_flags)
1853 struct tdbsam_search_state *state;
1855 if (!tdbsam_open(tdbsam_filename)) {
1856 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1857 tdbsam_filename));
1858 return false;
1861 state = TALLOC_ZERO_P(search->mem_ctx, struct tdbsam_search_state);
1862 if (state == NULL) {
1863 DEBUG(0, ("talloc failed\n"));
1864 return false;
1866 state->acct_flags = acct_flags;
1867 state->methods = methods;
1869 db_sam->traverse_read(db_sam, tdbsam_collect_rids, state);
1871 search->private_data = state;
1872 search->next_entry = tdbsam_search_next_entry;
1873 search->search_end = tdbsam_search_end;
1875 return true;
1878 /*********************************************************************
1879 Initialize the tdb sam backend. Setup the dispath table of methods,
1880 open the tdb, etc...
1881 *********************************************************************/
1883 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1885 NTSTATUS nt_status;
1886 char *tdbfile = NULL;
1887 const char *pfile = location;
1889 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1890 return nt_status;
1893 (*pdb_method)->name = "tdbsam";
1895 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1896 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1897 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1898 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1899 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1900 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1901 (*pdb_method)->search_users = tdbsam_search_users;
1903 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1904 (*pdb_method)->new_rid = tdbsam_new_rid;
1906 /* save the path for later */
1908 if (!location) {
1909 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1910 PASSDB_FILE_NAME) < 0) {
1911 return NT_STATUS_NO_MEMORY;
1913 pfile = tdbfile;
1915 tdbsam_filename = SMB_STRDUP(pfile);
1916 if (!tdbsam_filename) {
1917 return NT_STATUS_NO_MEMORY;
1919 SAFE_FREE(tdbfile);
1921 /* no private data */
1923 (*pdb_method)->private_data = NULL;
1924 (*pdb_method)->free_private_data = NULL;
1926 return NT_STATUS_OK;
1929 NTSTATUS pdb_tdbsam_init(void)
1931 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);