Change the passdb interface to use allocated strings.
[ira/wip.git] / source3 / passdb / pdb_tdb.c
1 /*
2  * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3  * Copyright (C) Andrew Tridgell 1992-1998
4  * Copyright (C) Simo Sorce 2000
5  * Copyright (C) Gerald Carter 2000
6  * Copyright (C) Jeremy Allison 2001
7  * 
8  * This program is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  * 
18  * You should have received a copy of the GNU General Public License along with
19  * this program; if not, write to the Free Software Foundation, Inc., 675
20  * Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 #ifdef WITH_TDB_SAM
26
27 #define PDB_VERSION             "20010830"
28 #define PASSDB_FILE_NAME        "/passdb.tdb"
29 #define TDB_FORMAT_STRING       "ddddddBBBBBBBBBBBBddBBwdwdBdd"
30 #define USERPREFIX              "USER_"
31 #define RIDPREFIX               "RID_"
32
33 extern int              DEBUGLEVEL;
34
35 struct tdb_enum_info {
36         TDB_CONTEXT     *passwd_tdb;
37         TDB_DATA        key;
38 };
39
40 static struct tdb_enum_info     global_tdb_ent;
41 /*static SAM_ACCOUNT            global_sam_pass;*/
42
43 /**********************************************************************
44  Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
45  *********************************************************************/
46
47 static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
48 {
49
50         /* times are stored as 32bit integer
51            take care on system with 64bit wide time_t
52            --SSS */
53         uint32  logon_time,
54                 logoff_time,
55                 kickoff_time,
56                 pass_last_set_time,
57                 pass_can_change_time,
58                 pass_must_change_time;
59         char *username;
60         char *domain;
61         char *nt_username;
62         char *dir_drive;
63         char *unknown_str;
64         char *munged_dial;
65         char *fullname;
66         char *homedir;
67         char *logon_script;
68         char *profile_path;
69         char *acct_desc;
70         char *workstations;
71         uint32  username_len, domain_len, nt_username_len,
72                 dir_drive_len, unknown_str_len, munged_dial_len,
73                 fullname_len, homedir_len, logon_script_len,
74                 profile_path_len, acct_desc_len, workstations_len;
75                 
76         uint32  /* uid, gid,*/ user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6;
77         uint16  acct_ctrl, logon_divs;
78         uint8   *hours;
79         static uint8    *lm_pw_ptr, *nt_pw_ptr;
80         uint32          len = 0;
81         uint32          lmpwlen, ntpwlen, hourslen;
82         BOOL ret = True;
83         
84         if(sampass == NULL || buf == NULL) {
85                 DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n"));
86                 return False;
87         }
88                                                                         
89         /* unpack the buffer into variables */
90         len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING,
91                 &logon_time,
92                 &logoff_time,
93                 &kickoff_time,
94                 &pass_last_set_time,
95                 &pass_can_change_time,
96                 &pass_must_change_time,
97                 &username_len, &username,
98                 &domain_len, &domain,
99                 &nt_username_len, &nt_username,
100                 &fullname_len, &fullname,
101                 &homedir_len, &homedir,
102                 &dir_drive_len, &dir_drive,
103                 &logon_script_len, &logon_script,
104                 &profile_path_len, &profile_path,
105                 &acct_desc_len, &acct_desc,
106                 &workstations_len, &workstations,
107                 &unknown_str_len, &unknown_str,
108                 &munged_dial_len, &munged_dial,
109                 &user_rid,
110                 &group_rid,
111                 &lmpwlen, &lm_pw_ptr,
112                 &ntpwlen, &nt_pw_ptr,
113                 &acct_ctrl,
114                 &unknown_3,
115                 &logon_divs,
116                 &hours_len,
117                 &hourslen, &hours,
118                 &unknown_5,
119                 &unknown_6);
120                 
121         if (len == -1)  {
122                 ret = False;
123                 goto done;
124         }
125
126         pdb_set_logon_time(sampass, logon_time);
127         pdb_set_logoff_time(sampass, logoff_time);
128         pdb_set_kickoff_time(sampass, kickoff_time);
129         pdb_set_pass_can_change_time(sampass, pass_can_change_time);
130         pdb_set_pass_must_change_time(sampass, pass_must_change_time);
131         pdb_set_pass_last_set_time(sampass, pass_last_set_time);
132
133         pdb_set_username     (sampass, username_len?username:NULL);
134         pdb_set_domain       (sampass, domain_len?domain:NULL);
135         pdb_set_nt_username  (sampass, nt_username_len?nt_username:NULL);
136         pdb_set_fullname     (sampass, fullname_len?fullname:NULL);
137         pdb_set_homedir      (sampass, homedir_len?homedir:NULL, True);
138         pdb_set_dir_drive    (sampass, dir_drive_len?dir_drive:NULL, True);
139         pdb_set_logon_script (sampass, logon_script_len?logon_script:NULL, True);
140         pdb_set_profile_path (sampass, profile_path_len?profile_path:NULL, True);
141         pdb_set_acct_desc    (sampass, acct_desc_len?acct_desc:NULL);
142         pdb_set_workstations (sampass, workstations_len?workstations:NULL);
143         pdb_set_munged_dial  (sampass, munged_dial_len?munged_dial:NULL);
144         if (!pdb_set_lanman_passwd(sampass, lmpwlen?lm_pw_ptr:NULL)) {
145                 ret = False;
146                 goto done;
147         }
148         if (!pdb_set_nt_passwd(sampass, ntpwlen?nt_pw_ptr:NULL)) {
149                 ret = False;
150                 goto done;
151         }
152
153         /*pdb_set_uid(sampass, uid);
154         pdb_set_gid(sampass, gid);*/
155         pdb_set_user_rid(sampass, user_rid);
156         pdb_set_group_rid(sampass, group_rid);
157         pdb_set_unknown_3(sampass, unknown_3);
158         pdb_set_hours_len(sampass, hours_len);
159         pdb_set_unknown_5(sampass, unknown_5);
160         pdb_set_unknown_6(sampass, unknown_6);
161         pdb_set_acct_ctrl(sampass, acct_ctrl);
162         pdb_set_logon_divs(sampass, logon_divs);
163         pdb_set_hours(sampass, hours);
164
165 done:
166
167         SAFE_FREE(username);
168         SAFE_FREE(domain);
169         SAFE_FREE(nt_username);
170         SAFE_FREE(fullname);
171         SAFE_FREE(homedir);
172         SAFE_FREE(dir_drive);
173         SAFE_FREE(logon_script);
174         SAFE_FREE(profile_path);
175         SAFE_FREE(acct_desc);
176         SAFE_FREE(workstations);
177         SAFE_FREE(munged_dial);
178
179         return ret;
180 }
181
182 /**********************************************************************
183  Intialize a BYTE buffer from a SAM_ACCOUNT struct
184  *********************************************************************/
185 static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass)
186 {
187         size_t          len, buflen;
188
189         /* times are stored as 32bit integer
190            take care on system with 64bit wide time_t
191            --SSS */
192         uint32  logon_time,
193                 logoff_time,
194                 kickoff_time,
195                 pass_last_set_time,
196                 pass_can_change_time,
197                 pass_must_change_time;
198         const char *username;
199         const char *domain;
200         const char *nt_username;
201         const char *dir_drive;
202         const char *unknown_str;
203         const char *munged_dial;
204         const char *fullname;
205         const char *homedir;
206         const char *logon_script;
207         const char *profile_path;
208         const char *acct_desc;
209         const char *workstations;
210         uint32  username_len, domain_len, nt_username_len,
211                 dir_drive_len, unknown_str_len, munged_dial_len,
212                 fullname_len, homedir_len, logon_script_len,
213                 profile_path_len, acct_desc_len, workstations_len;
214
215         const uint8 *lm_pw;
216         const uint8 *nt_pw;
217         uint32  lm_pw_len = 16;
218         uint32  nt_pw_len = 16;
219
220         /* do we have a valid SAM_ACCOUNT pointer? */
221         if (sampass == NULL) {
222                 DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n"));
223                 return -1;
224         }
225         
226         *buf = NULL;
227         buflen = 0;
228
229         logon_time = (uint32)pdb_get_logon_time(sampass);
230         logoff_time = (uint32)pdb_get_logoff_time(sampass);
231         kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
232         pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
233         pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
234         pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
235
236
237         username = pdb_get_username(sampass);
238         if (username)
239                 username_len = strlen(username) +1;
240         else
241                 username_len = 0;
242         domain = pdb_get_domain(sampass);
243         if (domain)
244                 domain_len = strlen(domain) +1;
245         else
246                 domain_len = 0;
247         nt_username = pdb_get_nt_username(sampass);
248         if (nt_username)
249                 nt_username_len = strlen(nt_username) +1;
250         else
251                 nt_username_len = 0;
252         dir_drive = pdb_get_dirdrive(sampass);
253         if (dir_drive)
254                 dir_drive_len = strlen(dir_drive) +1;
255         else
256                 dir_drive_len = 0;
257         unknown_str = NULL;
258         unknown_str_len = 0;
259         munged_dial = pdb_get_munged_dial(sampass);
260         if (munged_dial)
261                 munged_dial_len = strlen(munged_dial) +1;
262         else
263                 munged_dial_len = 0;
264                 
265         fullname = pdb_get_fullname(sampass);
266         if (fullname)
267                 fullname_len = strlen(fullname) +1;
268         else
269                 fullname_len = 0;
270         homedir = pdb_get_homedir(sampass);
271         if (homedir)
272                 homedir_len = strlen(homedir) +1;
273         else
274                 homedir_len = 0;
275         logon_script = pdb_get_logon_script(sampass);
276         if (logon_script)
277                 logon_script_len = strlen(logon_script) +1;
278         else
279                 logon_script_len = 0;
280         profile_path = pdb_get_profile_path(sampass);
281         if (profile_path)
282                 profile_path_len = strlen(profile_path) +1;
283         else
284                 profile_path_len = 0;
285         acct_desc = pdb_get_acct_desc(sampass);
286         if (acct_desc)
287                 acct_desc_len = strlen(acct_desc) +1;
288         else
289                 acct_desc_len = 0;
290         workstations = pdb_get_workstations(sampass);
291         if (workstations)
292                 workstations_len = strlen(workstations) +1;
293         else
294                 workstations_len = 0;
295         
296         lm_pw = pdb_get_lanman_passwd(sampass);
297         if (!lm_pw)
298                 lm_pw_len = 0;
299         
300         nt_pw = pdb_get_nt_passwd(sampass);
301         if (!nt_pw)
302                 nt_pw_len = 0;
303                 
304         /* one time to get the size needed */
305         len = tdb_pack(NULL, 0,  TDB_FORMAT_STRING,
306                 logon_time,
307                 logoff_time,
308                 kickoff_time,
309                 pass_last_set_time,
310                 pass_can_change_time,
311                 pass_must_change_time,
312                 username_len, username,
313                 domain_len, domain,
314                 nt_username_len, nt_username,
315                 fullname_len, fullname,
316                 homedir_len, homedir,
317                 dir_drive_len, dir_drive,
318                 logon_script_len, logon_script,
319                 profile_path_len, profile_path,
320                 acct_desc_len, acct_desc,
321                 workstations_len, workstations,
322                 unknown_str_len, unknown_str,
323                 munged_dial_len, munged_dial,
324                 pdb_get_user_rid(sampass),
325                 pdb_get_group_rid(sampass),
326                 lm_pw_len, lm_pw,
327                 nt_pw_len, nt_pw,
328                 pdb_get_acct_ctrl(sampass),
329                 pdb_get_unknown3(sampass),
330                 pdb_get_logon_divs(sampass),
331                 pdb_get_hours_len(sampass),
332                 MAX_HOURS_LEN, pdb_get_hours(sampass),
333                 pdb_get_unknown5(sampass),
334                 pdb_get_unknown6(sampass));
335
336
337         /* malloc the space needed */
338         if ( (*buf=(uint8*)malloc(len)) == NULL) {
339                 DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n"));
340                 return (-1);
341         }
342         
343         /* now for the real call to tdb_pack() */
344         buflen = tdb_pack(*buf, len,  TDB_FORMAT_STRING,
345                 logon_time,
346                 logoff_time,
347                 kickoff_time,
348                 pass_last_set_time,
349                 pass_can_change_time,
350                 pass_must_change_time,
351                 username_len, username,
352                 domain_len, domain,
353                 nt_username_len, nt_username,
354                 fullname_len, fullname,
355                 homedir_len, homedir,
356                 dir_drive_len, dir_drive,
357                 logon_script_len, logon_script,
358                 profile_path_len, profile_path,
359                 acct_desc_len, acct_desc,
360                 workstations_len, workstations,
361                 unknown_str_len, unknown_str,
362                 munged_dial_len, munged_dial,
363                 pdb_get_user_rid(sampass),
364                 pdb_get_group_rid(sampass),
365                 lm_pw_len, lm_pw,
366                 nt_pw_len, nt_pw,
367                 pdb_get_acct_ctrl(sampass),
368                 pdb_get_unknown3(sampass),
369                 pdb_get_logon_divs(sampass),
370                 pdb_get_hours_len(sampass),
371                 MAX_HOURS_LEN, pdb_get_hours(sampass),
372                 pdb_get_unknown5(sampass),
373                 pdb_get_unknown6(sampass));
374         
375         
376         /* check to make sure we got it correct */
377         if (buflen != len) {
378                 /* error */
379                 SAFE_FREE (*buf);
380                 return (-1);
381         }
382
383         return (buflen);
384 }
385
386 /***************************************************************
387  Open the TDB passwd database for SAM account enumeration.
388 ****************************************************************/
389
390 BOOL pdb_setsampwent(BOOL update)
391 {
392         pstring         tdbfile;
393         
394         get_private_directory(tdbfile);
395         pstrcat (tdbfile, PASSDB_FILE_NAME);
396         
397         /* Open tdb passwd */
398         if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
399         {
400                 DEBUG(0, ("Unable to open/create TDB passwd\n"));
401                 return False;
402         }
403         
404         global_tdb_ent.key = tdb_firstkey(global_tdb_ent.passwd_tdb);
405
406         return True;
407 }
408
409 /***************************************************************
410  End enumeration of the TDB passwd list.
411 ****************************************************************/
412
413 void pdb_endsampwent(void)
414 {
415         if (global_tdb_ent.passwd_tdb) {
416                 tdb_close(global_tdb_ent.passwd_tdb);
417                 global_tdb_ent.passwd_tdb = NULL;
418         }
419         
420         DEBUG(7, ("endtdbpwent: closed sam database.\n"));
421 }
422
423 /*****************************************************************
424  Get one SAM_ACCOUNT from the TDB (next in line)
425 *****************************************************************/
426
427 BOOL pdb_getsampwent(SAM_ACCOUNT *user)
428 {
429         TDB_DATA        data;
430         struct passwd   *pw;
431         uid_t           uid;
432         gid_t           gid;
433         char *prefix = USERPREFIX;
434         int  prefixlen = strlen (prefix);
435
436         const char *sam_user;
437         pstring sam_subst;
438
439         if (user==NULL) {
440                 DEBUG(0,("pdb_get_sampwent: SAM_ACCOUNT is NULL.\n"));
441                 return False;
442         }
443
444         /* skip all non-USER entries (eg. RIDs) */
445         while ((global_tdb_ent.key.dsize != 0) && (strncmp(global_tdb_ent.key.dptr, prefix, prefixlen)))
446                 /* increment to next in line */
447                 global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
448
449         /* do we have an valid interation pointer? */
450         if(global_tdb_ent.passwd_tdb == NULL) {
451                 DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
452                 return False;
453         }
454
455         data = tdb_fetch(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
456         if (!data.dptr) {
457                 DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
458                 return False;
459         }
460   
461         /* unpack the buffer */
462         if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
463                 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
464                 SAFE_FREE(data.dptr);
465                 return False;
466         }
467         SAFE_FREE(data.dptr);
468         
469         /* validate the account and fill in UNIX uid and gid.  sys_getpwnam()
470            is used instaed of Get_Pwnam() as we do not need to try case
471            permutations */
472         if ((pw=sys_getpwnam(pdb_get_username(user))) == NULL) {
473                 DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL.  User does not exist!\n", 
474                           pdb_get_username(user)));
475                 return False;
476         }
477
478         uid = pw->pw_uid;
479         gid = pw->pw_gid;
480         pdb_set_uid(user, uid);
481         pdb_set_gid(user, gid);
482
483         /* 21 days from present */
484         pdb_set_pass_must_change_time(user, time(NULL)+1814400);
485
486         sam_user = pdb_get_username(user);
487         pstrcpy(sam_subst, pdb_get_logon_script(user));
488         standard_sub_advanced(-1, sam_user, "", gid, sam_user, sam_subst);
489         pdb_set_logon_script(user, sam_subst, True);
490         pstrcpy(sam_subst, pdb_get_profile_path(user));
491         standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
492         pdb_set_profile_path(user, sam_subst, True);
493         pstrcpy(sam_subst, pdb_get_homedir(user));
494         standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
495         pdb_set_homedir(user, sam_subst, True);
496
497         /* increment to next in line */
498         global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
499
500         return True;
501 }
502
503 /******************************************************************
504  Lookup a name in the SAM TDB
505 ******************************************************************/
506
507 BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
508 {
509         TDB_CONTEXT     *pwd_tdb;
510         TDB_DATA        data, key;
511         fstring         keystr;
512         struct passwd   *pw;
513         pstring         tdbfile;
514         fstring         name;
515         uid_t           uid;
516         gid_t           gid;
517
518         const char *sam_user;
519         pstring sam_subst;
520
521         if (user==NULL) {
522                 DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
523                 return False;
524         }
525
526         /* Data is stored in all lower-case */
527         unix_strlower(sname, -1, name, sizeof(name));
528
529         get_private_directory(tdbfile);
530         pstrcat(tdbfile, PASSDB_FILE_NAME);
531         
532         /* set search key */
533         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
534         key.dptr = keystr;
535         key.dsize = strlen(keystr) + 1;
536
537         /* open the accounts TDB */
538         if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
539                 DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd!\n"));
540                 return False;
541         }
542
543         /* get the record */
544         data = tdb_fetch(pwd_tdb, key);
545         if (!data.dptr) {
546                 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
547                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
548                 tdb_close(pwd_tdb);
549                 return False;
550         }
551   
552         /* unpack the buffer */
553         if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
554                 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
555                 SAFE_FREE(data.dptr);
556                 tdb_close(pwd_tdb);
557                 return False;
558         }
559         SAFE_FREE(data.dptr);
560
561         /* no further use for database, close it now */
562         tdb_close(pwd_tdb);
563         
564         /* validate the account and fill in UNIX uid and gid.  sys_getpwnam()
565            is used instead of Get_Pwnam() as we do not need to try case
566            permutations */
567         if ((pw=sys_getpwnam(pdb_get_username(user)))) {
568                 uid = pw->pw_uid;
569                 gid = pw->pw_gid;
570                 pdb_set_uid(user, uid);
571                 pdb_set_gid(user, gid);
572
573                 /* 21 days from present */
574                 pdb_set_pass_must_change_time(user, time(NULL)+1814400);
575
576                 sam_user = pdb_get_username(user);
577                 pstrcpy(sam_subst, pdb_get_logon_script(user));
578                 standard_sub_advanced(-1, sam_user, "", gid, sam_user, sam_subst);
579                 pdb_set_logon_script(user, sam_subst, True);
580                 pstrcpy(sam_subst, pdb_get_profile_path(user));
581                 standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
582                 pdb_set_profile_path(user, sam_subst, True);
583                 pstrcpy(sam_subst, pdb_get_homedir(user));
584                 standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
585                 pdb_set_homedir(user, sam_subst, True);
586         }
587         else {
588                 DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL.  User does not exist!\n", 
589                           pdb_get_username(user)));
590                 return False;
591         }
592
593         return True;
594 }
595
596 /***************************************************************************
597  Search by rid
598  **************************************************************************/
599
600 BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid)
601 {
602         TDB_CONTEXT             *pwd_tdb;
603         TDB_DATA                data, key;
604         fstring                 keystr;
605         pstring                 tdbfile;
606         fstring                 name;
607         
608         if (user==NULL) {
609                 DEBUG(0,("pdb_getsampwrid: SAM_ACCOUNT is NULL.\n"));
610                 return False;
611         }
612
613         get_private_directory(tdbfile);
614         pstrcat (tdbfile, PASSDB_FILE_NAME);
615         
616         /* set search key */
617         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
618         key.dptr = keystr;
619         key.dsize = strlen (keystr) + 1;
620
621         /* open the accounts TDB */
622         if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
623                 DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
624                 return False;
625         }
626
627         /* get the record */
628         data = tdb_fetch (pwd_tdb, key);
629         if (!data.dptr) {
630                 DEBUG(5,("pdb_getsampwrid (TDB): error fetching database.\n"));
631                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
632                 tdb_close (pwd_tdb);
633                 return False;
634         }
635
636         fstrcpy (name, data.dptr);
637         SAFE_FREE(data.dptr);
638         
639         tdb_close (pwd_tdb);
640         
641         return pdb_getsampwnam (user, name);
642 }
643
644 /***************************************************************************
645  Delete a SAM_ACCOUNT
646 ****************************************************************************/
647
648 BOOL pdb_delete_sam_account(const char *sname)
649 {
650         SAM_ACCOUNT     *sam_pass = NULL;
651         TDB_CONTEXT     *pwd_tdb;
652         TDB_DATA        key, data;
653         fstring         keystr;
654         pstring         tdbfile;
655         uint32          rid;
656         fstring         name;
657         
658         unix_strlower(sname, -1, name, sizeof(name));
659         
660         get_private_directory(tdbfile);
661         pstrcat (tdbfile, PASSDB_FILE_NAME);
662
663         /* open the TDB */
664         if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) {
665                 DEBUG(0, ("Unable to open TDB passwd!"));
666                 return False;
667         }
668   
669         /* set the search key */
670         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
671         key.dptr = keystr;
672         key.dsize = strlen (keystr) + 1;
673         
674         /* get the record */
675         data = tdb_fetch (pwd_tdb, key);
676         if (!data.dptr) {
677                 DEBUG(5,("pdb_delete_sam_account (TDB): error fetching database.\n"));
678                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
679                 tdb_close (pwd_tdb);
680                 return False;
681         }
682   
683         /* unpack the buffer */
684         if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pass))) {
685                 tdb_close (pwd_tdb);
686                 return False;
687         }
688         
689         if (!init_sam_from_buffer (sam_pass, data.dptr, data.dsize)) {
690                 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
691                 tdb_close (pwd_tdb);
692                 SAFE_FREE(data.dptr);
693                 return False;
694         }
695         SAFE_FREE(data.dptr);
696
697         rid = pdb_get_user_rid(sam_pass);
698
699         pdb_free_sam (&sam_pass);
700         
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 False;
707         }       
708
709         /* delete also the RID key */
710
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;
715
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 False;
722         }
723         
724         tdb_close(pwd_tdb);
725         
726         return True;
727 }
728
729 /***************************************************************************
730  Update the TDB SAM
731 ****************************************************************************/
732
733 static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag)
734 {
735         TDB_CONTEXT     *pwd_tdb = NULL;
736         TDB_DATA        key, data;
737         uint8           *buf = NULL;
738         fstring         keystr;
739         pstring         tdbfile;
740         fstring         name;
741         BOOL            ret = True;
742         
743         get_private_directory(tdbfile);
744         pstrcat (tdbfile, PASSDB_FILE_NAME);
745         
746         /* if we don't have a RID, then FAIL */
747         if (!pdb_get_user_rid(newpwd))
748                 DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd)));
749         if (!pdb_get_group_rid(newpwd))
750                 DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd)));
751
752         /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
753         if ((data.dsize=init_buffer_from_sam (&buf, newpwd)) == -1) {
754                 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
755                 ret = False;
756                 goto done;
757         }
758         data.dptr = buf;
759
760         unix_strlower(pdb_get_username(newpwd), -1, name, sizeof(name));
761         
762         /* setup the USER index key */
763         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
764         key.dptr = keystr;
765         key.dsize = strlen (keystr) + 1;
766
767         /* invalidate the existing TDB iterator if it is open */
768         if (global_tdb_ent.passwd_tdb) {
769                 tdb_close(global_tdb_ent.passwd_tdb);
770                 global_tdb_ent.passwd_tdb = NULL;
771         }
772
773         /* open the account TDB passwd*/
774         pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
775         if (!pwd_tdb)
776         {
777                 DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd!\n"));
778                 return False;
779         }
780
781         /* add the account */
782         if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
783                 DEBUG(0, ("Unable to modify passwd TDB!"));
784                 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
785                 ret = False;
786                 goto done;
787         }
788         
789         /* setup RID data */
790         data.dsize = sizeof(fstring);
791         data.dptr = name;
792
793         /* setup the RID index key */
794         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
795         key.dptr = keystr;
796         key.dsize = strlen (keystr) + 1;
797         
798         /* add the reference */
799         if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
800                 DEBUG(0, ("Unable to modify TDB passwd !"));
801                 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
802                 ret = False;
803                 goto done;
804         }
805
806 done:   
807         /* cleanup */
808         tdb_close (pwd_tdb);
809         SAFE_FREE(buf);
810         
811         return (ret);   
812 }
813
814 /***************************************************************************
815  Modifies an existing SAM_ACCOUNT
816 ****************************************************************************/
817
818 BOOL pdb_update_sam_account (const SAM_ACCOUNT *newpwd, BOOL override)
819 {
820         return (tdb_update_sam(newpwd, override, TDB_MODIFY));
821 }
822
823 /***************************************************************************
824  Adds an existing SAM_ACCOUNT
825 ****************************************************************************/
826
827 BOOL pdb_add_sam_account (const SAM_ACCOUNT *newpwd)
828 {
829         return (tdb_update_sam(newpwd, True, TDB_INSERT));
830 }
831
832 #else
833         /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */
834         void samtdb_dummy_function(void) { } /* stop some compilers complaining */
835 #endif /* WITH_TDB_SAM */