Fix bug #5533. Winbindd fails to cope correctly with a workgroup name containing...
[Samba.git] / source / passdb / pdb_tdb.c
blobe9beaa053682a1ef95847c9da0edf9ac7fee7109
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 2 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, write to the Free Software Foundation, Inc., 675
23 * Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 #if 0 /* when made a module use this */
30 static int tdbsam_debug_level = DBGC_ALL;
31 #undef DBGC_CLASS
32 #define DBGC_CLASS tdbsam_debug_level
34 #else
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_PASSDB
39 #endif
41 #define TDBSAM_VERSION 3 /* Most recent TDBSAM version */
42 #define TDBSAM_VERSION_STRING "INFO/version"
43 #define PASSDB_FILE_NAME "passdb.tdb"
44 #define USERPREFIX "USER_"
45 #define RIDPREFIX "RID_"
46 #define PRIVPREFIX "PRIV_"
48 struct pwent_list {
49 struct pwent_list *prev, *next;
50 TDB_DATA key;
52 static struct pwent_list *tdbsam_pwent_list;
53 static BOOL pwent_initialized;
55 /* GLOBAL TDB SAM CONTEXT */
57 static TDB_CONTEXT *tdbsam;
58 static int ref_count = 0;
59 static pstring tdbsam_filename;
61 /**********************************************************************
62 Marshall/unmarshall struct samu structs.
63 *********************************************************************/
65 #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
66 #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
67 #define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
69 /*********************************************************************
70 *********************************************************************/
72 static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
75 /* times are stored as 32bit integer
76 take care on system with 64bit wide time_t
77 --SSS */
78 uint32 logon_time,
79 logoff_time,
80 kickoff_time,
81 pass_last_set_time,
82 pass_can_change_time,
83 pass_must_change_time;
84 char *username = NULL;
85 char *domain = NULL;
86 char *nt_username = NULL;
87 char *dir_drive = NULL;
88 char *unknown_str = NULL;
89 char *munged_dial = NULL;
90 char *fullname = NULL;
91 char *homedir = NULL;
92 char *logon_script = NULL;
93 char *profile_path = NULL;
94 char *acct_desc = NULL;
95 char *workstations = NULL;
96 uint32 username_len, domain_len, nt_username_len,
97 dir_drive_len, unknown_str_len, munged_dial_len,
98 fullname_len, homedir_len, logon_script_len,
99 profile_path_len, acct_desc_len, workstations_len;
101 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
102 uint16 acct_ctrl, logon_divs;
103 uint16 bad_password_count, logon_count;
104 uint8 *hours = NULL;
105 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
106 uint32 len = 0;
107 uint32 lm_pw_len, nt_pw_len, hourslen;
108 BOOL ret = True;
110 if(sampass == NULL || buf == NULL) {
111 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
112 return False;
115 /* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
117 /* unpack the buffer into variables */
118 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
119 &logon_time, /* d */
120 &logoff_time, /* d */
121 &kickoff_time, /* d */
122 &pass_last_set_time, /* d */
123 &pass_can_change_time, /* d */
124 &pass_must_change_time, /* d */
125 &username_len, &username, /* B */
126 &domain_len, &domain, /* B */
127 &nt_username_len, &nt_username, /* B */
128 &fullname_len, &fullname, /* B */
129 &homedir_len, &homedir, /* B */
130 &dir_drive_len, &dir_drive, /* B */
131 &logon_script_len, &logon_script, /* B */
132 &profile_path_len, &profile_path, /* B */
133 &acct_desc_len, &acct_desc, /* B */
134 &workstations_len, &workstations, /* B */
135 &unknown_str_len, &unknown_str, /* B */
136 &munged_dial_len, &munged_dial, /* B */
137 &user_rid, /* d */
138 &group_rid, /* d */
139 &lm_pw_len, &lm_pw_ptr, /* B */
140 &nt_pw_len, &nt_pw_ptr, /* B */
141 &acct_ctrl, /* w */
142 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
143 &logon_divs, /* w */
144 &hours_len, /* d */
145 &hourslen, &hours, /* B */
146 &bad_password_count, /* w */
147 &logon_count, /* w */
148 &unknown_6); /* d */
150 if (len == (uint32) -1) {
151 ret = False;
152 goto done;
155 pdb_set_logon_time(sampass, logon_time, PDB_SET);
156 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
157 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
158 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
159 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
160 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
162 pdb_set_username(sampass, username, PDB_SET);
163 pdb_set_domain(sampass, domain, PDB_SET);
164 pdb_set_nt_username(sampass, nt_username, PDB_SET);
165 pdb_set_fullname(sampass, fullname, PDB_SET);
167 if (homedir) {
168 pdb_set_homedir(sampass, homedir, PDB_SET);
170 else {
171 pdb_set_homedir(sampass,
172 talloc_sub_basic(sampass, username, domain,
173 lp_logon_home()),
174 PDB_DEFAULT);
177 if (dir_drive)
178 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
179 else {
180 pdb_set_dir_drive(sampass,
181 talloc_sub_basic(sampass, username, domain,
182 lp_logon_drive()),
183 PDB_DEFAULT);
186 if (logon_script)
187 pdb_set_logon_script(sampass, logon_script, PDB_SET);
188 else {
189 pdb_set_logon_script(sampass,
190 talloc_sub_basic(sampass, username, domain,
191 lp_logon_script()),
192 PDB_DEFAULT);
195 if (profile_path) {
196 pdb_set_profile_path(sampass, profile_path, PDB_SET);
197 } else {
198 pdb_set_profile_path(sampass,
199 talloc_sub_basic(sampass, username, domain,
200 lp_logon_path()),
201 PDB_DEFAULT);
204 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
205 pdb_set_workstations(sampass, workstations, PDB_SET);
206 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
208 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
209 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
210 ret = False;
211 goto done;
215 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
216 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
217 ret = False;
218 goto done;
222 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
223 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
224 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
225 pdb_set_hours_len(sampass, hours_len, PDB_SET);
226 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
227 pdb_set_logon_count(sampass, logon_count, PDB_SET);
228 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
229 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
230 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
231 pdb_set_hours(sampass, hours, PDB_SET);
233 done:
235 SAFE_FREE(username);
236 SAFE_FREE(domain);
237 SAFE_FREE(nt_username);
238 SAFE_FREE(fullname);
239 SAFE_FREE(homedir);
240 SAFE_FREE(dir_drive);
241 SAFE_FREE(logon_script);
242 SAFE_FREE(profile_path);
243 SAFE_FREE(acct_desc);
244 SAFE_FREE(workstations);
245 SAFE_FREE(munged_dial);
246 SAFE_FREE(unknown_str);
247 SAFE_FREE(lm_pw_ptr);
248 SAFE_FREE(nt_pw_ptr);
249 SAFE_FREE(hours);
251 return ret;
254 /*********************************************************************
255 *********************************************************************/
257 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
260 /* times are stored as 32bit integer
261 take care on system with 64bit wide time_t
262 --SSS */
263 uint32 logon_time,
264 logoff_time,
265 kickoff_time,
266 bad_password_time,
267 pass_last_set_time,
268 pass_can_change_time,
269 pass_must_change_time;
270 char *username = NULL;
271 char *domain = NULL;
272 char *nt_username = NULL;
273 char *dir_drive = NULL;
274 char *unknown_str = NULL;
275 char *munged_dial = NULL;
276 char *fullname = NULL;
277 char *homedir = NULL;
278 char *logon_script = NULL;
279 char *profile_path = NULL;
280 char *acct_desc = NULL;
281 char *workstations = NULL;
282 uint32 username_len, domain_len, nt_username_len,
283 dir_drive_len, unknown_str_len, munged_dial_len,
284 fullname_len, homedir_len, logon_script_len,
285 profile_path_len, acct_desc_len, workstations_len;
287 uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
288 uint16 acct_ctrl, logon_divs;
289 uint16 bad_password_count, logon_count;
290 uint8 *hours = NULL;
291 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
292 uint32 len = 0;
293 uint32 lm_pw_len, nt_pw_len, hourslen;
294 BOOL ret = True;
296 if(sampass == NULL || buf == NULL) {
297 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
298 return False;
301 /* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
303 /* unpack the buffer into variables */
304 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
305 &logon_time, /* d */
306 &logoff_time, /* d */
307 &kickoff_time, /* d */
308 /* Change from V0 is addition of bad_password_time field. */
309 &bad_password_time, /* d */
310 &pass_last_set_time, /* d */
311 &pass_can_change_time, /* d */
312 &pass_must_change_time, /* d */
313 &username_len, &username, /* B */
314 &domain_len, &domain, /* B */
315 &nt_username_len, &nt_username, /* B */
316 &fullname_len, &fullname, /* B */
317 &homedir_len, &homedir, /* B */
318 &dir_drive_len, &dir_drive, /* B */
319 &logon_script_len, &logon_script, /* B */
320 &profile_path_len, &profile_path, /* B */
321 &acct_desc_len, &acct_desc, /* B */
322 &workstations_len, &workstations, /* B */
323 &unknown_str_len, &unknown_str, /* B */
324 &munged_dial_len, &munged_dial, /* B */
325 &user_rid, /* d */
326 &group_rid, /* d */
327 &lm_pw_len, &lm_pw_ptr, /* B */
328 &nt_pw_len, &nt_pw_ptr, /* B */
329 &acct_ctrl, /* w */
330 &remove_me, /* d */
331 &logon_divs, /* w */
332 &hours_len, /* d */
333 &hourslen, &hours, /* B */
334 &bad_password_count, /* w */
335 &logon_count, /* w */
336 &unknown_6); /* d */
338 if (len == (uint32) -1) {
339 ret = False;
340 goto done;
343 pdb_set_logon_time(sampass, logon_time, PDB_SET);
344 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
345 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
347 /* Change from V0 is addition of bad_password_time field. */
348 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
349 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
350 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
351 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
353 pdb_set_username(sampass, username, PDB_SET);
354 pdb_set_domain(sampass, domain, PDB_SET);
355 pdb_set_nt_username(sampass, nt_username, PDB_SET);
356 pdb_set_fullname(sampass, fullname, PDB_SET);
358 if (homedir) {
359 pdb_set_homedir(sampass, homedir, PDB_SET);
361 else {
362 pdb_set_homedir(sampass,
363 talloc_sub_basic(sampass, username, domain,
364 lp_logon_home()),
365 PDB_DEFAULT);
368 if (dir_drive)
369 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
370 else {
371 pdb_set_dir_drive(sampass,
372 talloc_sub_basic(sampass, username, domain,
373 lp_logon_drive()),
374 PDB_DEFAULT);
377 if (logon_script)
378 pdb_set_logon_script(sampass, logon_script, PDB_SET);
379 else {
380 pdb_set_logon_script(sampass,
381 talloc_sub_basic(sampass, username, domain,
382 lp_logon_script()),
383 PDB_DEFAULT);
386 if (profile_path) {
387 pdb_set_profile_path(sampass, profile_path, PDB_SET);
388 } else {
389 pdb_set_profile_path(sampass,
390 talloc_sub_basic(sampass, username, domain,
391 lp_logon_path()),
392 PDB_DEFAULT);
395 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
396 pdb_set_workstations(sampass, workstations, PDB_SET);
397 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
399 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
400 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
401 ret = False;
402 goto done;
406 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
407 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
408 ret = False;
409 goto done;
413 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
415 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
416 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
417 pdb_set_hours_len(sampass, hours_len, PDB_SET);
418 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
419 pdb_set_logon_count(sampass, logon_count, PDB_SET);
420 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
421 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
422 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
423 pdb_set_hours(sampass, hours, PDB_SET);
425 done:
427 SAFE_FREE(username);
428 SAFE_FREE(domain);
429 SAFE_FREE(nt_username);
430 SAFE_FREE(fullname);
431 SAFE_FREE(homedir);
432 SAFE_FREE(dir_drive);
433 SAFE_FREE(logon_script);
434 SAFE_FREE(profile_path);
435 SAFE_FREE(acct_desc);
436 SAFE_FREE(workstations);
437 SAFE_FREE(munged_dial);
438 SAFE_FREE(unknown_str);
439 SAFE_FREE(lm_pw_ptr);
440 SAFE_FREE(nt_pw_ptr);
441 SAFE_FREE(hours);
443 return ret;
446 BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
449 /* times are stored as 32bit integer
450 take care on system with 64bit wide time_t
451 --SSS */
452 uint32 logon_time,
453 logoff_time,
454 kickoff_time,
455 bad_password_time,
456 pass_last_set_time,
457 pass_can_change_time,
458 pass_must_change_time;
459 char *username = NULL;
460 char *domain = NULL;
461 char *nt_username = NULL;
462 char *dir_drive = NULL;
463 char *unknown_str = NULL;
464 char *munged_dial = NULL;
465 char *fullname = NULL;
466 char *homedir = NULL;
467 char *logon_script = NULL;
468 char *profile_path = NULL;
469 char *acct_desc = NULL;
470 char *workstations = NULL;
471 uint32 username_len, domain_len, nt_username_len,
472 dir_drive_len, unknown_str_len, munged_dial_len,
473 fullname_len, homedir_len, logon_script_len,
474 profile_path_len, acct_desc_len, workstations_len;
476 uint32 user_rid, group_rid, hours_len, unknown_6;
477 uint16 acct_ctrl, logon_divs;
478 uint16 bad_password_count, logon_count;
479 uint8 *hours = NULL;
480 uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
481 uint32 len = 0;
482 uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
483 uint32 pwHistLen = 0;
484 BOOL ret = True;
485 fstring tmpstring;
486 BOOL expand_explicit = lp_passdb_expand_explicit();
488 if(sampass == NULL || buf == NULL) {
489 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
490 return False;
493 /* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
495 /* unpack the buffer into variables */
496 len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
497 &logon_time, /* d */
498 &logoff_time, /* d */
499 &kickoff_time, /* d */
500 &bad_password_time, /* d */
501 &pass_last_set_time, /* d */
502 &pass_can_change_time, /* d */
503 &pass_must_change_time, /* d */
504 &username_len, &username, /* B */
505 &domain_len, &domain, /* B */
506 &nt_username_len, &nt_username, /* B */
507 &fullname_len, &fullname, /* B */
508 &homedir_len, &homedir, /* B */
509 &dir_drive_len, &dir_drive, /* B */
510 &logon_script_len, &logon_script, /* B */
511 &profile_path_len, &profile_path, /* B */
512 &acct_desc_len, &acct_desc, /* B */
513 &workstations_len, &workstations, /* B */
514 &unknown_str_len, &unknown_str, /* B */
515 &munged_dial_len, &munged_dial, /* B */
516 &user_rid, /* d */
517 &group_rid, /* d */
518 &lm_pw_len, &lm_pw_ptr, /* B */
519 &nt_pw_len, &nt_pw_ptr, /* B */
520 /* Change from V1 is addition of password history field. */
521 &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
522 &acct_ctrl, /* w */
523 /* Also "remove_me" field was removed. */
524 &logon_divs, /* w */
525 &hours_len, /* d */
526 &hourslen, &hours, /* B */
527 &bad_password_count, /* w */
528 &logon_count, /* w */
529 &unknown_6); /* d */
531 if (len == (uint32) -1) {
532 ret = False;
533 goto done;
536 pdb_set_logon_time(sampass, logon_time, PDB_SET);
537 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
538 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
539 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
540 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
541 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
542 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
544 pdb_set_username(sampass, username, PDB_SET);
545 pdb_set_domain(sampass, domain, PDB_SET);
546 pdb_set_nt_username(sampass, nt_username, PDB_SET);
547 pdb_set_fullname(sampass, fullname, PDB_SET);
549 if (homedir) {
550 fstrcpy( tmpstring, homedir );
551 if (expand_explicit) {
552 standard_sub_basic( username, domain, tmpstring,
553 sizeof(tmpstring) );
555 pdb_set_homedir(sampass, tmpstring, PDB_SET);
557 else {
558 pdb_set_homedir(sampass,
559 talloc_sub_basic(sampass, username, domain,
560 lp_logon_home()),
561 PDB_DEFAULT);
564 if (dir_drive)
565 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
566 else
567 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
569 if (logon_script) {
570 fstrcpy( tmpstring, logon_script );
571 if (expand_explicit) {
572 standard_sub_basic( username, domain, tmpstring,
573 sizeof(tmpstring) );
575 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
577 else {
578 pdb_set_logon_script(sampass,
579 talloc_sub_basic(sampass, username, domain,
580 lp_logon_script()),
581 PDB_DEFAULT);
584 if (profile_path) {
585 fstrcpy( tmpstring, profile_path );
586 if (expand_explicit) {
587 standard_sub_basic( username, domain, tmpstring,
588 sizeof(tmpstring) );
590 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
592 else {
593 pdb_set_profile_path(sampass,
594 talloc_sub_basic(sampass, username, domain,
595 lp_logon_path()),
596 PDB_DEFAULT);
599 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
600 pdb_set_workstations(sampass, workstations, PDB_SET);
601 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
603 if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
604 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
605 ret = False;
606 goto done;
610 if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
611 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
612 ret = False;
613 goto done;
617 /* Change from V1 is addition of password history field. */
618 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
619 if (pwHistLen) {
620 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
621 if (!pw_hist) {
622 ret = False;
623 goto done;
625 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
626 if (nt_pw_hist_ptr && nt_pw_hist_len) {
627 int i;
628 SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
629 nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
630 for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
631 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
632 &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
633 PW_HISTORY_ENTRY_LEN);
636 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
637 SAFE_FREE(pw_hist);
638 ret = False;
639 goto done;
641 SAFE_FREE(pw_hist);
642 } else {
643 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
646 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
647 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
648 pdb_set_hours_len(sampass, hours_len, PDB_SET);
649 pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
650 pdb_set_logon_count(sampass, logon_count, PDB_SET);
651 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
652 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
653 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
654 pdb_set_hours(sampass, hours, PDB_SET);
656 done:
658 SAFE_FREE(username);
659 SAFE_FREE(domain);
660 SAFE_FREE(nt_username);
661 SAFE_FREE(fullname);
662 SAFE_FREE(homedir);
663 SAFE_FREE(dir_drive);
664 SAFE_FREE(logon_script);
665 SAFE_FREE(profile_path);
666 SAFE_FREE(acct_desc);
667 SAFE_FREE(workstations);
668 SAFE_FREE(munged_dial);
669 SAFE_FREE(unknown_str);
670 SAFE_FREE(lm_pw_ptr);
671 SAFE_FREE(nt_pw_ptr);
672 SAFE_FREE(nt_pw_hist_ptr);
673 SAFE_FREE(hours);
675 return ret;
679 /**********************************************************************
680 Intialize a struct samu struct from a BYTE buffer of size len
681 *********************************************************************/
683 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
685 return init_sam_from_buffer_v3(sampass, buf, buflen);
688 /**********************************************************************
689 Intialize a BYTE buffer from a struct samu struct
690 *********************************************************************/
692 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
694 return init_buffer_from_sam_v3(buf, sampass, size_only);
697 /**********************************************************************
698 Intialize a BYTE buffer from a struct samu struct
699 *********************************************************************/
701 static BOOL tdbsam_convert(int32 from)
703 const char *vstring = TDBSAM_VERSION_STRING;
704 const char *prefix = USERPREFIX;
705 TDB_DATA data, key, old_key;
706 uint8 *buf = NULL;
707 BOOL ret;
709 /* handle a Samba upgrade */
710 tdb_lock_bystring(tdbsam, vstring);
712 /* Enumerate all records and convert them */
713 key = tdb_firstkey(tdbsam);
715 while (key.dptr) {
717 /* skip all non-USER entries (eg. RIDs) */
718 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
719 old_key = key;
720 /* increment to next in line */
721 key = tdb_nextkey(tdbsam, key);
722 SAFE_FREE(old_key.dptr);
725 if (key.dptr) {
726 struct samu *user = NULL;
728 /* read from tdbsam */
729 data = tdb_fetch(tdbsam, key);
730 if (!data.dptr) {
731 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
732 return False;
735 /* unpack the buffer from the former format */
736 if ( !(user = samu_new( NULL )) ) {
737 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
738 SAFE_FREE( data.dptr );
739 return False;
741 DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
742 switch (from) {
743 case 0:
744 ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
745 break;
746 case 1:
747 ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
748 break;
749 case 2:
750 ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
751 break;
752 case 3:
753 ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
754 break;
755 default:
756 /* unknown tdbsam version */
757 ret = False;
759 if (!ret) {
760 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
761 SAFE_FREE(data.dptr);
762 TALLOC_FREE(user );
763 return False;
766 /* We're finished with the old data. */
767 SAFE_FREE(data.dptr);
769 /* pack from the buffer into the new format */
771 DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
772 data.dsize = init_buffer_from_sam (&buf, user, False);
773 TALLOC_FREE(user );
775 if ( data.dsize == -1 ) {
776 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
777 return False;
779 data.dptr = (char *)buf;
781 /* Store the buffer inside the TDBSAM */
782 if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
783 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
784 SAFE_FREE(data.dptr);
785 return False;
788 SAFE_FREE(data.dptr);
790 /* increment to next in line */
791 old_key = key;
792 key = tdb_nextkey(tdbsam, key);
793 SAFE_FREE(old_key.dptr);
799 /* upgrade finished */
800 tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
801 tdb_unlock_bystring(tdbsam, vstring);
803 return(True);
806 /*********************************************************************
807 Open the tdbsam file based on the absolute path specified.
808 Uses a reference count to allow multiple open calls.
809 *********************************************************************/
811 static BOOL tdbsam_open( const char *name )
813 int32 version;
815 /* check if we are already open */
817 if ( tdbsam ) {
818 ref_count++;
819 DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
820 ref_count));
821 return True;
824 SMB_ASSERT( ref_count == 0 );
826 /* Try to open tdb passwd. Create a new one if necessary */
828 if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
829 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
830 return False;
833 /* set the initial reference count - must be done before tdbsam_convert
834 as that calls tdbsam_open()/tdbsam_close(). */
836 ref_count = 1;
838 /* Check the version */
839 version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
841 if (version == -1) {
842 version = 0; /* Version not found, assume version 0 */
845 /* Compare the version */
846 if (version > TDBSAM_VERSION) {
847 /* Version more recent than the latest known */
848 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
849 tdb_close( tdbsam );
850 ref_count = 0;
851 return False;
855 if ( version < TDBSAM_VERSION ) {
856 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
857 version, TDBSAM_VERSION));
859 if ( !tdbsam_convert(version) ) {
860 DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
861 tdb_close(tdbsam);
862 ref_count = 0;
863 return False;
866 DEBUG(3, ("TDBSAM converted successfully.\n"));
869 DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
871 return True;
874 /****************************************************************************
875 wrapper atound tdb_close() to handle the reference count
876 ****************************************************************************/
878 void tdbsam_close( void )
880 ref_count--;
882 DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
884 SMB_ASSERT(ref_count >= 0 );
886 if ( ref_count == 0 ) {
887 tdb_close( tdbsam );
888 tdbsam = NULL;
891 return;
894 /****************************************************************************
895 creates a list of user keys
896 ****************************************************************************/
898 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
900 const char *prefix = USERPREFIX;
901 int prefixlen = strlen (prefix);
902 struct pwent_list *ptr;
904 if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
905 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
906 DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
908 /* just return 0 and let the traversal continue */
909 return 0;
911 ZERO_STRUCTP(ptr);
913 /* save a copy of the key */
915 ptr->key.dptr = (char *)memdup( key.dptr, key.dsize );
916 if (!ptr->key.dptr) {
917 DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n"));
918 /* just return 0 and let the traversal continue */
919 SAFE_FREE(ptr);
920 return 0;
923 ptr->key.dsize = key.dsize;
925 DLIST_ADD( tdbsam_pwent_list, ptr );
929 return 0;
932 /***************************************************************
933 Open the TDB passwd database for SAM account enumeration.
934 Save a list of user keys for iteration.
935 ****************************************************************/
937 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
939 if ( !tdbsam_open( tdbsam_filename ) ) {
940 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
941 return NT_STATUS_ACCESS_DENIED;
944 tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
945 pwent_initialized = True;
947 return NT_STATUS_OK;
951 /***************************************************************
952 End enumeration of the TDB passwd list.
953 ****************************************************************/
955 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
957 struct pwent_list *ptr, *ptr_next;
959 /* close the tdb only if we have a valid pwent state */
961 if ( pwent_initialized ) {
962 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
963 tdbsam_close();
966 /* clear out any remaining entries in the list */
968 for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
969 ptr_next = ptr->next;
970 DLIST_REMOVE( tdbsam_pwent_list, ptr );
971 SAFE_FREE( ptr->key.dptr);
972 SAFE_FREE( ptr );
975 pwent_initialized = False;
978 /*****************************************************************
979 Get one struct samu from the TDB (next in line)
980 *****************************************************************/
982 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
984 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
985 TDB_DATA data;
986 struct pwent_list *pkey;
988 if ( !user ) {
989 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
990 return nt_status;
993 if ( !tdbsam_pwent_list ) {
994 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
995 return nt_status;
998 /* pull the next entry */
1000 pkey = tdbsam_pwent_list;
1001 DLIST_REMOVE( tdbsam_pwent_list, pkey );
1003 data = tdb_fetch(tdbsam, pkey->key);
1005 SAFE_FREE( pkey->key.dptr);
1006 SAFE_FREE( pkey);
1008 if ( !data.dptr ) {
1009 DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
1010 return nt_status;
1013 if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
1014 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1017 SAFE_FREE( data.dptr );
1019 return NT_STATUS_OK;
1022 /******************************************************************
1023 Lookup a name in the SAM TDB
1024 ******************************************************************/
1026 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
1028 TDB_DATA data, key;
1029 fstring keystr;
1030 fstring name;
1032 if ( !user ) {
1033 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
1034 return NT_STATUS_NO_MEMORY;
1037 /* Data is stored in all lower-case */
1038 fstrcpy(name, sname);
1039 strlower_m(name);
1041 /* set search key */
1042 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1043 key.dptr = keystr;
1044 key.dsize = strlen(keystr) + 1;
1046 /* open the database */
1048 if ( !tdbsam_open( tdbsam_filename ) ) {
1049 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1050 return NT_STATUS_ACCESS_DENIED;
1053 /* get the record */
1055 data = tdb_fetch(tdbsam, key);
1056 if (!data.dptr) {
1057 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
1058 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1059 DEBUGADD(5, (" Key: %s\n", keystr));
1060 tdbsam_close();
1061 return NT_STATUS_NO_SUCH_USER;
1064 /* unpack the buffer */
1066 if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
1067 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1068 SAFE_FREE(data.dptr);
1069 tdbsam_close();
1070 return NT_STATUS_NO_MEMORY;
1073 /* success */
1075 SAFE_FREE(data.dptr);
1076 tdbsam_close();
1078 return NT_STATUS_OK;
1081 /***************************************************************************
1082 Search by rid
1083 **************************************************************************/
1085 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
1087 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1088 TDB_DATA data, key;
1089 fstring keystr;
1090 fstring name;
1092 if ( !user ) {
1093 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
1094 return nt_status;
1097 /* set search key */
1099 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1100 key.dptr = keystr;
1101 key.dsize = strlen (keystr) + 1;
1103 /* open the database */
1105 if ( !tdbsam_open( tdbsam_filename ) ) {
1106 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1107 return NT_STATUS_ACCESS_DENIED;
1110 /* get the record */
1112 data = tdb_fetch (tdbsam, key);
1113 if (!data.dptr) {
1114 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
1115 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1116 nt_status = NT_STATUS_UNSUCCESSFUL;
1117 goto done;
1120 fstrcpy(name, data.dptr);
1121 SAFE_FREE(data.dptr);
1123 nt_status = tdbsam_getsampwnam (my_methods, user, name);
1125 done:
1126 /* cleanup */
1128 tdbsam_close();
1130 return nt_status;
1133 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
1135 uint32 rid;
1137 if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
1138 return NT_STATUS_UNSUCCESSFUL;
1140 return tdbsam_getsampwrid(my_methods, user, rid);
1143 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
1145 TDB_DATA key;
1146 fstring keystr;
1147 fstring name;
1149 fstrcpy(name, pdb_get_username(sam_pass));
1150 strlower_m(name);
1152 /* set the search key */
1154 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1155 key.dptr = keystr;
1156 key.dsize = strlen (keystr) + 1;
1158 /* it's outaa here! 8^) */
1160 if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
1161 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1162 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1163 return False;
1166 return True;
1169 /***************************************************************************
1170 Delete a struct samu records for the username and RID key
1171 ****************************************************************************/
1173 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
1175 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1176 TDB_DATA key;
1177 fstring keystr;
1178 uint32 rid;
1179 fstring name;
1181 /* open the database */
1183 if ( !tdbsam_open( tdbsam_filename ) ) {
1184 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
1185 tdbsam_filename));
1186 return NT_STATUS_ACCESS_DENIED;
1189 fstrcpy(name, pdb_get_username(sam_pass));
1190 strlower_m(name);
1192 /* set the search key */
1194 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1195 key.dptr = keystr;
1196 key.dsize = strlen (keystr) + 1;
1198 rid = pdb_get_user_rid(sam_pass);
1200 /* it's outaa here! 8^) */
1202 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1203 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1204 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1205 nt_status = NT_STATUS_UNSUCCESSFUL;
1206 goto done;
1209 /* set the search key */
1211 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1212 key.dptr = keystr;
1213 key.dsize = strlen (keystr) + 1;
1215 /* it's outaa here! 8^) */
1217 if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1218 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
1219 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1220 nt_status = NT_STATUS_UNSUCCESSFUL;
1221 goto done;
1224 nt_status = NT_STATUS_OK;
1226 done:
1227 tdbsam_close();
1229 return nt_status;
1233 /***************************************************************************
1234 Update the TDB SAM account record only
1235 Assumes that the tdbsam is already open
1236 ****************************************************************************/
1237 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
1239 TDB_DATA key, data;
1240 uint8 *buf = NULL;
1241 fstring keystr;
1242 fstring name;
1243 BOOL ret = True;
1245 /* copy the struct samu struct into a BYTE buffer for storage */
1247 if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1248 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1249 ret = False;
1250 goto done;
1252 data.dptr = (char *)buf;
1254 fstrcpy(name, pdb_get_username(newpwd));
1255 strlower_m(name);
1257 DEBUG(5, ("Storing %saccount %s with RID %d\n",
1258 flag == TDB_INSERT ? "(new) " : "", name,
1259 pdb_get_user_rid(newpwd)));
1261 /* setup the USER index key */
1262 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1263 key.dptr = keystr;
1264 key.dsize = strlen(keystr) + 1;
1266 /* add the account */
1268 if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
1269 DEBUG(0, ("Unable to modify passwd TDB!"));
1270 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1271 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1272 keystr));
1273 ret = False;
1274 goto done;
1277 done:
1278 /* cleanup */
1279 SAFE_FREE(buf);
1281 return ret;
1284 /***************************************************************************
1285 Update the TDB SAM RID record only
1286 Assumes that the tdbsam is already open
1287 ****************************************************************************/
1288 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1290 TDB_DATA key, data;
1291 fstring keystr;
1292 fstring name;
1294 fstrcpy(name, pdb_get_username(newpwd));
1295 strlower_m(name);
1297 /* setup RID data */
1298 data.dsize = strlen(name) + 1;
1299 data.dptr = name;
1301 /* setup the RID index key */
1302 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
1303 key.dptr = keystr;
1304 key.dsize = strlen (keystr) + 1;
1306 /* add the reference */
1307 if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
1308 DEBUG(0, ("Unable to modify TDB passwd !"));
1309 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1310 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1311 return False;
1314 return True;
1318 /***************************************************************************
1319 Update the TDB SAM
1320 ****************************************************************************/
1322 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1324 BOOL result = True;
1326 /* invalidate the existing TDB iterator if it is open */
1328 tdbsam_endsampwent( my_methods );
1330 #if 0
1331 if ( !pdb_get_group_rid(newpwd) ) {
1332 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1333 "without a primary group RID\n", pdb_get_username(newpwd)));
1334 return False;
1336 #endif
1338 if (!pdb_get_user_rid(newpwd)) {
1339 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1340 return False;
1343 /* open the database */
1345 if ( !tdbsam_open( tdbsam_filename ) ) {
1346 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1347 return False;
1350 if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1351 result = False;
1354 /* cleanup */
1356 tdbsam_close();
1358 return result;
1361 /***************************************************************************
1362 Modifies an existing struct samu
1363 ****************************************************************************/
1365 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1367 if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1368 return NT_STATUS_UNSUCCESSFUL;
1370 return NT_STATUS_OK;
1373 /***************************************************************************
1374 Adds an existing struct samu
1375 ****************************************************************************/
1377 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1379 if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1380 return NT_STATUS_UNSUCCESSFUL;
1382 return NT_STATUS_OK;
1385 /***************************************************************************
1386 Renames a struct samu
1387 - check for the posix user/rename user script
1388 - Add and lock the new user record
1389 - rename the posix user
1390 - rewrite the rid->username record
1391 - delete the old user
1392 - unlock the new user record
1393 ***************************************************************************/
1394 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1395 struct samu *old_acct,
1396 const char *newname)
1398 struct samu *new_acct = NULL;
1399 pstring rename_script;
1400 BOOL interim_account = False;
1401 int rename_ret;
1402 fstring oldname_lower;
1403 fstring newname_lower;
1405 /* can't do anything without an external script */
1407 pstrcpy(rename_script, lp_renameuser_script() );
1408 if ( ! *rename_script ) {
1409 return NT_STATUS_ACCESS_DENIED;
1412 /* invalidate the existing TDB iterator if it is open */
1414 tdbsam_endsampwent( my_methods );
1416 if ( !(new_acct = samu_new( NULL )) ) {
1417 return NT_STATUS_NO_MEMORY;
1420 if ( !pdb_copy_sam_account(new_acct, old_acct)
1421 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1423 TALLOC_FREE(new_acct );
1424 return NT_STATUS_NO_MEMORY;
1427 /* open the database */
1429 if ( !tdbsam_open( tdbsam_filename ) ) {
1430 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1431 TALLOC_FREE(new_acct );
1432 return NT_STATUS_ACCESS_DENIED;
1435 /* add the new account and lock it */
1437 if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1438 goto done;
1441 interim_account = True;
1443 if ( tdb_lock_bystring_with_timeout(tdbsam, newname, 30) == -1 ) {
1444 goto done;
1447 /* Rename the posix user. Follow the semantics of _samr_create_user()
1448 so that we lower case the posix name but preserve the case in passdb */
1450 fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1451 strlower_m( oldname_lower );
1453 fstrcpy( newname_lower, newname );
1454 strlower_m( newname_lower );
1456 string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring),
1457 True, False, True);
1458 string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring),
1459 True, False, True);
1460 rename_ret = smbrun(rename_script, NULL);
1462 DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1464 if (rename_ret == 0) {
1465 smb_nscd_flush_user_cache();
1468 if (rename_ret) {
1469 goto done;
1472 /* rewrite the rid->username record */
1474 if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1475 goto done;
1477 interim_account = False;
1478 tdb_unlock_bystring( tdbsam, newname );
1480 tdb_delete_samacct_only( old_acct );
1482 tdbsam_close();
1484 TALLOC_FREE(new_acct );
1485 return NT_STATUS_OK;
1487 done:
1488 /* cleanup */
1489 if (interim_account) {
1490 tdb_unlock_bystring(tdbsam, newname);
1491 tdb_delete_samacct_only(new_acct);
1494 tdbsam_close();
1496 if (new_acct)
1497 TALLOC_FREE(new_acct);
1499 return NT_STATUS_ACCESS_DENIED;
1502 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1504 return False;
1508 * Historically, winbind was responsible for allocating RIDs, so the next RID
1509 * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1510 * but for compatibility reasons we still keep the the next RID counter in
1511 * winbindd_idmap.tdb.
1514 /*****************************************************************************
1515 Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1516 sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1517 winbind completely and store the RID counter in passdb.tdb.
1519 Dont' fully initialize with the HWM values, if it's new, we're only
1520 interested in the RID counter.
1521 *****************************************************************************/
1523 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1525 int32 version;
1527 if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
1528 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1529 return False;
1532 version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1534 if (version == -1) {
1535 /* No key found, must be a new db */
1536 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1537 IDMAP_VERSION) != 0) {
1538 DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1539 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1540 return False;
1542 version = IDMAP_VERSION;
1545 if (version != IDMAP_VERSION) {
1546 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1547 "start winbind once\n", IDMAP_VERSION, version));
1548 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1549 return False;
1552 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1553 return True;
1556 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1558 TDB_CONTEXT *tdb;
1559 uint32 rid;
1560 BOOL ret = False;
1562 tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1563 TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1565 if (tdb == NULL) {
1566 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1567 goto done;
1570 if (!init_idmap_tdb(tdb)) {
1571 DEBUG(1, ("Could not init idmap\n"));
1572 goto done;
1575 rid = BASE_RID; /* Default if not set */
1577 if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1578 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1579 goto done;
1582 *prid = rid;
1583 ret = True;
1585 done:
1586 if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1587 smb_panic("tdb_close(idmap_tdb) failed\n");
1590 return ret;
1593 /*********************************************************************
1594 Initialize the tdb sam backend. Setup the dispath table of methods,
1595 open the tdb, etc...
1596 *********************************************************************/
1598 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1600 NTSTATUS nt_status;
1601 pstring tdbfile;
1602 const char *pfile = location;
1604 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1605 return nt_status;
1608 (*pdb_method)->name = "tdbsam";
1610 (*pdb_method)->setsampwent = tdbsam_setsampwent;
1611 (*pdb_method)->endsampwent = tdbsam_endsampwent;
1612 (*pdb_method)->getsampwent = tdbsam_getsampwent;
1613 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1614 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1615 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1616 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1617 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1618 (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1620 (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1621 (*pdb_method)->new_rid = tdbsam_new_rid;
1623 /* save the path for later */
1625 if ( !location ) {
1626 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1627 pfile = tdbfile;
1629 pstrcpy( tdbsam_filename, pfile );
1631 /* no private data */
1633 (*pdb_method)->private_data = NULL;
1634 (*pdb_method)->free_private_data = NULL;
1636 return NT_STATUS_OK;
1639 NTSTATUS pdb_tdbsam_init(void)
1641 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);