And some more memory leaks in mapping.c and pdb_tdb.c. tdb_nextkey
[Samba.git] / source / passdb / pdb_tdb.c
blob2cf7a0119f3b072e5e9fb1b9fd2da3da995ecf09
1 /*
2 * Unix SMB/CIFS implementation.
3 * SMB parameters and setup
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Simo Sorce 2000-2002
6 * Copyright (C) Gerald Carter 2000
7 * Copyright (C) Jeremy Allison 2001
8 * Copyright (C) Andrew Bartlett 2002
9 *
10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
20 * You should have received a copy of the GNU General Public License along with
21 * this program; if not, write to the Free Software Foundation, Inc., 675
22 * Mass Ave, Cambridge, MA 02139, USA.
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 PDB_VERSION "20010830"
41 #define PASSDB_FILE_NAME "passdb.tdb"
42 #define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBdd"
43 #define USERPREFIX "USER_"
44 #define RIDPREFIX "RID_"
46 struct tdbsam_privates {
47 TDB_CONTEXT *passwd_tdb;
48 TDB_DATA key;
50 /* retrive-once info */
51 const char *tdbsam_location;
53 BOOL permit_non_unix_accounts;
55 BOOL algorithmic_rids;
57 uint32 low_nua_rid;
58 uint32 high_nua_rid;
61 /**********************************************************************
62 Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
63 *********************************************************************/
65 static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state,
66 SAM_ACCOUNT *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;
79 char *domain;
80 char *nt_username;
81 char *dir_drive;
82 char *unknown_str;
83 char *munged_dial;
84 char *fullname;
85 char *homedir;
86 char *logon_script;
87 char *profile_path;
88 char *acct_desc;
89 char *workstations;
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, unknown_3, hours_len, unknown_5, unknown_6;
96 uint16 acct_ctrl, logon_divs;
97 uint8 *hours;
98 static uint8 *lm_pw_ptr, *nt_pw_ptr;
99 uint32 len = 0;
100 uint32 lm_pw_len, nt_pw_len, hourslen;
101 BOOL ret = True;
102 uid_t uid = -1;
103 gid_t gid = -1;
105 if(sampass == NULL || buf == NULL) {
106 DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n"));
107 return False;
110 /* unpack the buffer into variables */
111 len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING,
112 &logon_time,
113 &logoff_time,
114 &kickoff_time,
115 &pass_last_set_time,
116 &pass_can_change_time,
117 &pass_must_change_time,
118 &username_len, &username,
119 &domain_len, &domain,
120 &nt_username_len, &nt_username,
121 &fullname_len, &fullname,
122 &homedir_len, &homedir,
123 &dir_drive_len, &dir_drive,
124 &logon_script_len, &logon_script,
125 &profile_path_len, &profile_path,
126 &acct_desc_len, &acct_desc,
127 &workstations_len, &workstations,
128 &unknown_str_len, &unknown_str,
129 &munged_dial_len, &munged_dial,
130 &user_rid,
131 &group_rid,
132 &lm_pw_len, &lm_pw_ptr,
133 &nt_pw_len, &nt_pw_ptr,
134 &acct_ctrl,
135 &unknown_3,
136 &logon_divs,
137 &hours_len,
138 &hourslen, &hours,
139 &unknown_5,
140 &unknown_6);
142 if (len == -1) {
143 ret = False;
144 goto done;
147 pdb_set_logon_time(sampass, logon_time, PDB_SET);
148 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
149 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
150 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
151 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
152 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
154 pdb_set_username (sampass, username, PDB_SET);
155 pdb_set_domain (sampass, domain, PDB_SET);
156 pdb_set_nt_username (sampass, nt_username, PDB_SET);
157 pdb_set_fullname (sampass, fullname, PDB_SET);
159 if (homedir) {
160 pdb_set_homedir(sampass, homedir, PDB_SET);
162 else {
163 pdb_set_homedir(sampass,
164 talloc_sub_specified(sampass->mem_ctx,
165 lp_logon_home(),
166 username, domain,
167 uid, gid),
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_specified(sampass->mem_ctx,
176 lp_logon_drive(),
177 username, domain,
178 uid, gid),
179 PDB_DEFAULT);
182 if (logon_script)
183 pdb_set_logon_script(sampass, logon_script, PDB_SET);
184 else {
185 pdb_set_logon_script(sampass,
186 talloc_sub_specified(sampass->mem_ctx,
187 lp_logon_script(),
188 username, domain,
189 uid, gid),
190 PDB_DEFAULT);
193 if (profile_path) {
194 pdb_set_profile_path(sampass, profile_path, PDB_SET);
195 } else {
196 pdb_set_profile_path(sampass,
197 talloc_sub_specified(sampass->mem_ctx,
198 lp_logon_path(),
199 username, domain,
200 uid, gid),
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_user_sid_from_rid(sampass, user_rid, PDB_SET);
223 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
224 pdb_set_unknown_3(sampass, unknown_3, PDB_SET);
225 pdb_set_hours_len(sampass, hours_len, PDB_SET);
226 pdb_set_unknown_5(sampass, unknown_5, PDB_SET);
227 pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
228 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
229 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
230 pdb_set_hours(sampass, hours, PDB_SET);
232 done:
234 SAFE_FREE(username);
235 SAFE_FREE(domain);
236 SAFE_FREE(nt_username);
237 SAFE_FREE(fullname);
238 SAFE_FREE(homedir);
239 SAFE_FREE(dir_drive);
240 SAFE_FREE(logon_script);
241 SAFE_FREE(profile_path);
242 SAFE_FREE(acct_desc);
243 SAFE_FREE(workstations);
244 SAFE_FREE(munged_dial);
245 SAFE_FREE(unknown_str);
246 SAFE_FREE(hours);
248 return ret;
251 /**********************************************************************
252 Intialize a BYTE buffer from a SAM_ACCOUNT struct
253 *********************************************************************/
254 static uint32 init_buffer_from_sam (struct tdbsam_privates *tdb_state,
255 uint8 **buf, const SAM_ACCOUNT *sampass)
257 size_t len, buflen;
259 /* times are stored as 32bit integer
260 take care on system with 64bit wide time_t
261 --SSS */
262 uint32 logon_time,
263 logoff_time,
264 kickoff_time,
265 pass_last_set_time,
266 pass_can_change_time,
267 pass_must_change_time;
269 uint32 user_rid, group_rid;
271 const char *username;
272 const char *domain;
273 const char *nt_username;
274 const char *dir_drive;
275 const char *unknown_str;
276 const char *munged_dial;
277 const char *fullname;
278 const char *homedir;
279 const char *logon_script;
280 const char *profile_path;
281 const char *acct_desc;
282 const char *workstations;
283 uint32 username_len, domain_len, nt_username_len,
284 dir_drive_len, unknown_str_len, munged_dial_len,
285 fullname_len, homedir_len, logon_script_len,
286 profile_path_len, acct_desc_len, workstations_len;
288 const uint8 *lm_pw;
289 const uint8 *nt_pw;
290 uint32 lm_pw_len = 16;
291 uint32 nt_pw_len = 16;
293 /* do we have a valid SAM_ACCOUNT pointer? */
294 if (sampass == NULL) {
295 DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n"));
296 return -1;
299 *buf = NULL;
300 buflen = 0;
302 logon_time = (uint32)pdb_get_logon_time(sampass);
303 logoff_time = (uint32)pdb_get_logoff_time(sampass);
304 kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
305 pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
306 pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
307 pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
309 user_rid = pdb_get_user_rid(sampass);
310 group_rid = pdb_get_group_rid(sampass);
312 username = pdb_get_username(sampass);
313 if (username) username_len = strlen(username) +1;
314 else username_len = 0;
316 domain = pdb_get_domain(sampass);
317 if (domain) domain_len = strlen(domain) +1;
318 else domain_len = 0;
320 nt_username = pdb_get_nt_username(sampass);
321 if (nt_username) nt_username_len = strlen(nt_username) +1;
322 else nt_username_len = 0;
324 fullname = pdb_get_fullname(sampass);
325 if (fullname) fullname_len = strlen(fullname) +1;
326 else fullname_len = 0;
329 * Only updates fields which have been set (not defaults from smb.conf)
332 if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE))
333 dir_drive = pdb_get_dir_drive(sampass);
334 else dir_drive = NULL;
335 if (dir_drive) dir_drive_len = strlen(dir_drive) +1;
336 else dir_drive_len = 0;
338 if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) homedir = pdb_get_homedir(sampass);
339 else homedir = NULL;
340 if (homedir) homedir_len = strlen(homedir) +1;
341 else homedir_len = 0;
343 if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) logon_script = pdb_get_logon_script(sampass);
344 else logon_script = NULL;
345 if (logon_script) logon_script_len = strlen(logon_script) +1;
346 else logon_script_len = 0;
348 if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) profile_path = pdb_get_profile_path(sampass);
349 else profile_path = NULL;
350 if (profile_path) profile_path_len = strlen(profile_path) +1;
351 else profile_path_len = 0;
353 lm_pw = pdb_get_lanman_passwd(sampass);
354 if (!lm_pw) lm_pw_len = 0;
356 nt_pw = pdb_get_nt_passwd(sampass);
357 if (!nt_pw) nt_pw_len = 0;
359 acct_desc = pdb_get_acct_desc(sampass);
360 if (acct_desc) acct_desc_len = strlen(acct_desc) +1;
361 else acct_desc_len = 0;
363 workstations = pdb_get_workstations(sampass);
364 if (workstations) workstations_len = strlen(workstations) +1;
365 else workstations_len = 0;
367 unknown_str = NULL;
368 unknown_str_len = 0;
370 munged_dial = pdb_get_munged_dial(sampass);
371 if (munged_dial) munged_dial_len = strlen(munged_dial) +1;
372 else munged_dial_len = 0;
374 /* one time to get the size needed */
375 len = tdb_pack(NULL, 0, TDB_FORMAT_STRING,
376 logon_time,
377 logoff_time,
378 kickoff_time,
379 pass_last_set_time,
380 pass_can_change_time,
381 pass_must_change_time,
382 username_len, username,
383 domain_len, domain,
384 nt_username_len, nt_username,
385 fullname_len, fullname,
386 homedir_len, homedir,
387 dir_drive_len, dir_drive,
388 logon_script_len, logon_script,
389 profile_path_len, profile_path,
390 acct_desc_len, acct_desc,
391 workstations_len, workstations,
392 unknown_str_len, unknown_str,
393 munged_dial_len, munged_dial,
394 user_rid,
395 group_rid,
396 lm_pw_len, lm_pw,
397 nt_pw_len, nt_pw,
398 pdb_get_acct_ctrl(sampass),
399 pdb_get_unknown_3(sampass),
400 pdb_get_logon_divs(sampass),
401 pdb_get_hours_len(sampass),
402 MAX_HOURS_LEN, pdb_get_hours(sampass),
403 pdb_get_unknown_5(sampass),
404 pdb_get_unknown_6(sampass));
407 /* malloc the space needed */
408 if ( (*buf=(uint8*)malloc(len)) == NULL) {
409 DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n"));
410 return (-1);
413 /* now for the real call to tdb_pack() */
414 buflen = tdb_pack(*buf, len, TDB_FORMAT_STRING,
415 logon_time,
416 logoff_time,
417 kickoff_time,
418 pass_last_set_time,
419 pass_can_change_time,
420 pass_must_change_time,
421 username_len, username,
422 domain_len, domain,
423 nt_username_len, nt_username,
424 fullname_len, fullname,
425 homedir_len, homedir,
426 dir_drive_len, dir_drive,
427 logon_script_len, logon_script,
428 profile_path_len, profile_path,
429 acct_desc_len, acct_desc,
430 workstations_len, workstations,
431 unknown_str_len, unknown_str,
432 munged_dial_len, munged_dial,
433 user_rid,
434 group_rid,
435 lm_pw_len, lm_pw,
436 nt_pw_len, nt_pw,
437 pdb_get_acct_ctrl(sampass),
438 pdb_get_unknown_3(sampass),
439 pdb_get_logon_divs(sampass),
440 pdb_get_hours_len(sampass),
441 MAX_HOURS_LEN, pdb_get_hours(sampass),
442 pdb_get_unknown_5(sampass),
443 pdb_get_unknown_6(sampass));
446 /* check to make sure we got it correct */
447 if (buflen != len) {
448 DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n",
449 buflen, len));
450 /* error */
451 SAFE_FREE (*buf);
452 return (-1);
455 return (buflen);
458 /***************************************************************
459 Open the TDB passwd database for SAM account enumeration.
460 ****************************************************************/
462 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
464 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
466 /* Open tdb passwd */
467 if (!(tdb_state->passwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
469 DEBUG(0, ("Unable to open/create TDB passwd\n"));
470 return NT_STATUS_UNSUCCESSFUL;
473 tdb_state->key = tdb_firstkey(tdb_state->passwd_tdb);
475 return NT_STATUS_OK;
478 static void close_tdb(struct tdbsam_privates *tdb_state)
480 if (tdb_state->passwd_tdb) {
481 tdb_close(tdb_state->passwd_tdb);
482 tdb_state->passwd_tdb = NULL;
486 /***************************************************************
487 End enumeration of the TDB passwd list.
488 ****************************************************************/
490 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
492 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
493 SAFE_FREE(tdb_state->key.dptr);
494 close_tdb(tdb_state);
496 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
499 /*****************************************************************
500 Get one SAM_ACCOUNT from the TDB (next in line)
501 *****************************************************************/
503 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
505 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
506 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
507 TDB_DATA data, old_key;
508 const char *prefix = USERPREFIX;
509 int prefixlen = strlen (prefix);
512 if (user==NULL) {
513 DEBUG(0,("pdb_get_sampwent: SAM_ACCOUNT is NULL.\n"));
514 return nt_status;
517 /* skip all non-USER entries (eg. RIDs) */
518 while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen))) {
520 old_key = tdb_state->key;
522 /* increment to next in line */
523 tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
525 SAFE_FREE(old_key.dptr);
528 /* do we have an valid iteration pointer? */
529 if(tdb_state->passwd_tdb == NULL) {
530 DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
531 return nt_status;
534 data = tdb_fetch(tdb_state->passwd_tdb, tdb_state->key);
535 if (!data.dptr) {
536 DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
537 return nt_status;
540 /* unpack the buffer */
541 if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) {
542 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
543 SAFE_FREE(data.dptr);
544 return nt_status;
546 SAFE_FREE(data.dptr);
548 old_key = tdb_state->key;
550 /* increment to next in line */
551 tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
553 SAFE_FREE(old_key.dptr);
555 return NT_STATUS_OK;
558 /******************************************************************
559 Lookup a name in the SAM TDB
560 ******************************************************************/
562 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
564 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
565 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
566 TDB_CONTEXT *pwd_tdb;
567 TDB_DATA data, key;
568 fstring keystr;
569 fstring name;
571 if (user==NULL) {
572 DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
573 return nt_status;
577 /* Data is stored in all lower-case */
578 fstrcpy(name, sname);
579 strlower(name);
581 /* set search key */
582 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
583 key.dptr = keystr;
584 key.dsize = strlen(keystr) + 1;
586 /* open the accounts TDB */
587 if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
588 DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
589 return nt_status;
592 /* get the record */
593 data = tdb_fetch(pwd_tdb, key);
594 if (!data.dptr) {
595 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
596 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
597 DEBUGADD(5, (" Key: %s\n", keystr));
598 tdb_close(pwd_tdb);
599 return nt_status;
602 /* unpack the buffer */
603 if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) {
604 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
605 SAFE_FREE(data.dptr);
606 tdb_close(pwd_tdb);
607 return nt_status;
609 SAFE_FREE(data.dptr);
611 /* no further use for database, close it now */
612 tdb_close(pwd_tdb);
614 return NT_STATUS_OK;
617 /***************************************************************************
618 Search by rid
619 **************************************************************************/
621 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
623 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
624 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
625 TDB_CONTEXT *pwd_tdb;
626 TDB_DATA data, key;
627 fstring keystr;
628 fstring name;
630 if (user==NULL) {
631 DEBUG(0,("pdb_getsampwrid: SAM_ACCOUNT is NULL.\n"));
632 return nt_status;
635 /* set search key */
636 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
637 key.dptr = keystr;
638 key.dsize = strlen (keystr) + 1;
640 /* open the accounts TDB */
641 if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
642 DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
643 return nt_status;
646 /* get the record */
647 data = tdb_fetch (pwd_tdb, key);
648 if (!data.dptr) {
649 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
650 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
651 tdb_close (pwd_tdb);
652 return nt_status;
655 fstrcpy(name, data.dptr);
656 SAFE_FREE(data.dptr);
658 tdb_close (pwd_tdb);
660 return tdbsam_getsampwnam (my_methods, user, name);
663 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
665 uint32 rid;
666 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
667 return NT_STATUS_UNSUCCESSFUL;
668 return tdbsam_getsampwrid(my_methods, user, rid);
671 /***************************************************************************
672 Delete a SAM_ACCOUNT
673 ****************************************************************************/
675 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_pass)
677 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
678 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
679 TDB_CONTEXT *pwd_tdb;
680 TDB_DATA key;
681 fstring keystr;
682 uint32 rid;
683 fstring name;
685 fstrcpy(name, pdb_get_username(sam_pass));
686 strlower(name);
688 /* open the TDB */
689 if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR, 0600))) {
690 DEBUG(0, ("Unable to open TDB passwd!"));
691 return nt_status;
694 /* set the search key */
695 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
696 key.dptr = keystr;
697 key.dsize = strlen (keystr) + 1;
699 rid = pdb_get_user_rid(sam_pass);
701 /* it's outaa here! 8^) */
702 if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
703 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
704 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
705 tdb_close(pwd_tdb);
706 return nt_status;
709 /* delete also the RID key */
711 /* set the search key */
712 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
713 key.dptr = keystr;
714 key.dsize = strlen (keystr) + 1;
716 /* it's outaa here! 8^) */
717 if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
718 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
719 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
720 tdb_close(pwd_tdb);
721 return nt_status;
724 tdb_close(pwd_tdb);
726 return NT_STATUS_OK;
729 /***************************************************************************
730 Update the TDB SAM
731 ****************************************************************************/
733 static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
735 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
736 TDB_CONTEXT *pwd_tdb = NULL;
737 TDB_DATA key, data;
738 uint8 *buf = NULL;
739 fstring keystr;
740 fstring name;
741 BOOL ret = True;
742 uint32 user_rid;
743 BOOL tdb_ret;
745 /* invalidate the existing TDB iterator if it is open */
746 if (tdb_state->passwd_tdb) {
747 tdb_close(tdb_state->passwd_tdb);
748 tdb_state->passwd_tdb = NULL;
751 /* open the account TDB passwd*/
752 pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
753 if (!pwd_tdb)
755 DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
756 return False;
759 if (!pdb_get_group_rid(newpwd)) {
760 DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd)));
761 ret = False;
762 goto done;
765 /* if flag == TDB_INSERT then make up a new RID else throw an error. */
766 if (!(user_rid = pdb_get_user_rid(newpwd))) {
767 if ((flag & TDB_INSERT) && tdb_state->permit_non_unix_accounts) {
768 uint32 lowrid, highrid;
769 if (!idmap_get_free_rid_range(&lowrid, &highrid)) {
770 /* should never happen */
771 DEBUG(0, ("tdbsam: something messed up, no high/low rids but nua enabled ?!\n"));
772 ret = False;
773 goto done;
775 user_rid = lowrid;
776 tdb_ret = tdb_change_uint32_atomic(pwd_tdb, "RID_COUNTER", &user_rid, RID_MULTIPLIER);
777 if (!tdb_ret) {
778 ret = False;
779 goto done;
781 if (user_rid > highrid) {
782 DEBUG(0, ("tdbsam: no NUA rids available, cannot add user %s!\n", pdb_get_username(newpwd)));
783 ret = False;
784 goto done;
786 if (!pdb_set_user_sid_from_rid(newpwd, user_rid, PDB_CHANGED)) {
787 DEBUG(0, ("tdbsam: not able to set new allocated user RID into sam account!\n"));
788 ret = False;
789 goto done;
791 } else {
792 DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd)));
793 ret = False;
794 goto done;
798 /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
799 if ((data.dsize=init_buffer_from_sam (tdb_state, &buf, newpwd)) == -1) {
800 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
801 ret = False;
802 goto done;
804 data.dptr = buf;
806 fstrcpy(name, pdb_get_username(newpwd));
807 strlower(name);
809 DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid));
811 /* setup the USER index key */
812 slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
813 key.dptr = keystr;
814 key.dsize = strlen(keystr) + 1;
816 /* add the account */
817 if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
818 DEBUG(0, ("Unable to modify passwd TDB!"));
819 DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
820 DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
821 ret = False;
822 goto done;
825 /* setup RID data */
826 data.dsize = strlen(name) + 1;
827 data.dptr = name;
829 /* setup the RID index key */
830 slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, user_rid);
831 key.dptr = keystr;
832 key.dsize = strlen (keystr) + 1;
834 /* add the reference */
835 if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
836 DEBUG(0, ("Unable to modify TDB passwd !"));
837 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
838 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
839 ret = False;
840 goto done;
843 done:
844 /* cleanup */
845 tdb_close (pwd_tdb);
846 SAFE_FREE(buf);
848 return (ret);
851 #if 0
852 /***************************************************************************
853 Allocates a new RID and returns it to the caller as a domain sid
855 NOTE: Use carefullt, do not waste RIDs they are a limited resource!
856 - SSS
857 ***************************************************************************/
859 static NTSTATUS tdbsam_get_next_sid (struct pdb_methods *my_methods, DOM_SID *sid)
861 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
862 struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
863 TDB_CONTEXT *pwd_tdb;
864 uint32 rid;
866 if (sid == NULL) {
867 return NT_STATUS_INVALID_PARAMETER;
870 pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
871 if (!pwd_tdb)
873 DEBUG(0, ("tdbsam_get_next_sid: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
874 return NT_STATUS_UNSUCCESSFUL;
877 rid = BASE_RID;
878 if (tdb_change_uint32_atomic(pwd_tdb, "RID_COUNTER", &rid, 1)) {
880 sid_copy(sid, get_global_sam_sid());
881 if (!sid_append_rid(sid, rid)) {
882 goto done;
885 ret = NT_STATUS_OK;
888 done:
889 tdb_close (pwd_tdb);
890 return ret;
892 #endif
894 /***************************************************************************
895 Modifies an existing SAM_ACCOUNT
896 ****************************************************************************/
898 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
900 if (tdb_update_sam(my_methods, newpwd, TDB_MODIFY))
901 return NT_STATUS_OK;
902 else
903 return NT_STATUS_UNSUCCESSFUL;
906 /***************************************************************************
907 Adds an existing SAM_ACCOUNT
908 ****************************************************************************/
910 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
912 if (tdb_update_sam(my_methods, newpwd, TDB_INSERT))
913 return NT_STATUS_OK;
914 else
915 return NT_STATUS_UNSUCCESSFUL;
918 static void free_private_data(void **vp)
920 struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
921 close_tdb(*tdb_state);
922 *tdb_state = NULL;
924 /* No need to free any further, as it is talloc()ed */
928 static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
930 NTSTATUS nt_status;
931 struct tdbsam_privates *tdb_state;
932 uid_t low_nua_uid, high_nua_uid;
934 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
935 return nt_status;
938 (*pdb_method)->name = "tdbsam";
940 (*pdb_method)->setsampwent = tdbsam_setsampwent;
941 (*pdb_method)->endsampwent = tdbsam_endsampwent;
942 (*pdb_method)->getsampwent = tdbsam_getsampwent;
943 (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
944 (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
945 (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
946 (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
947 (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
949 tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates));
951 if (!tdb_state) {
952 DEBUG(0, ("talloc() failed for tdbsam private_data!\n"));
953 return NT_STATUS_NO_MEMORY;
956 if (location) {
957 tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location);
958 } else {
959 pstring tdbfile;
960 get_private_directory(tdbfile);
961 pstrcat(tdbfile, "/");
962 pstrcat(tdbfile, PASSDB_FILE_NAME);
963 tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
966 (*pdb_method)->private_data = tdb_state;
968 (*pdb_method)->free_private_data = free_private_data;
970 if (lp_idmap_uid(&low_nua_uid, &high_nua_uid)) {
971 DEBUG(3, ("idmap uid range defined, non unix accounts enabled\n"));
973 tdb_state->permit_non_unix_accounts = True;
975 tdb_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
977 tdb_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
979 } else {
980 tdb_state->algorithmic_rids = True;
983 return NT_STATUS_OK;
986 NTSTATUS pdb_tdbsam_init(void)
988 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);