r13711: * Correctly handle acb_info/acct_flags as uint32 not as uint16.
[ira/wip.git] / source3 / passdb / pdb_tdb.c
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
10  * 
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.
15  * 
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.
20  * 
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.
24  */
25
26 #include "includes.h"
27
28 #if 0 /* when made a module use this */
29
30 static int tdbsam_debug_level = DBGC_ALL;
31 #undef DBGC_CLASS
32 #define DBGC_CLASS tdbsam_debug_level
33
34 #else
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_PASSDB
38
39 #endif
40
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_"
47
48 struct pwent_list {
49         struct pwent_list *prev, *next;
50         TDB_DATA key;
51 };
52 static struct pwent_list *tdbsam_pwent_list;
53 static BOOL pwent_initialized;
54
55 /* GLOBAL TDB SAM CONTEXT */
56
57 static TDB_CONTEXT *tdbsam;
58 static int ref_count = 0;
59 static pstring tdbsam_filename;
60
61 /**********************************************************************
62  Marshall/unmarshall struct samu structs.
63  *********************************************************************/
64
65 #define TDB_FORMAT_STRING_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
66 #define TDB_FORMAT_STRING_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
67 #define TDB_FORMAT_STRING_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
68
69 /*********************************************************************
70 *********************************************************************/
71
72 static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
73 {
74
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;
100                 
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;
109         
110         if(sampass == NULL || buf == NULL) {
111                 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
112                 return False;
113         }
114
115 /* TDB_FORMAT_STRING_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
116
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 */
149                 
150         if (len == (uint32) -1)  {
151                 ret = False;
152                 goto done;
153         }
154
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);
161
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);
166
167         if (homedir) {
168                 pdb_set_homedir(sampass, homedir, PDB_SET);
169         }
170         else {
171                 pdb_set_homedir(sampass, 
172                         talloc_sub_basic(sampass, username, lp_logon_home()),
173                         PDB_DEFAULT);
174         }
175
176         if (dir_drive)  
177                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
178         else {
179                 pdb_set_dir_drive(sampass, 
180                         talloc_sub_basic(sampass,  username, lp_logon_drive()),
181                         PDB_DEFAULT);
182         }
183
184         if (logon_script) 
185                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
186         else {
187                 pdb_set_logon_script(sampass, 
188                         talloc_sub_basic(sampass, username, lp_logon_script()),
189                         PDB_DEFAULT);
190         }
191         
192         if (profile_path) {     
193                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
194         } else {
195                 pdb_set_profile_path(sampass, 
196                         talloc_sub_basic(sampass, username, lp_logon_path()),
197                         PDB_DEFAULT);
198         }
199
200         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
201         pdb_set_workstations(sampass, workstations, PDB_SET);
202         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
203
204         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
205                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
206                         ret = False;
207                         goto done;
208                 }
209         }
210
211         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
212                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
213                         ret = False;
214                         goto done;
215                 }
216         }
217
218         pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
219         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
220         pdb_set_hours_len(sampass, hours_len, PDB_SET);
221         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
222         pdb_set_logon_count(sampass, logon_count, PDB_SET);
223         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
224         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
225         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
226         pdb_set_hours(sampass, hours, PDB_SET);
227
228 done:
229
230         SAFE_FREE(username);
231         SAFE_FREE(domain);
232         SAFE_FREE(nt_username);
233         SAFE_FREE(fullname);
234         SAFE_FREE(homedir);
235         SAFE_FREE(dir_drive);
236         SAFE_FREE(logon_script);
237         SAFE_FREE(profile_path);
238         SAFE_FREE(acct_desc);
239         SAFE_FREE(workstations);
240         SAFE_FREE(munged_dial);
241         SAFE_FREE(unknown_str);
242         SAFE_FREE(lm_pw_ptr);
243         SAFE_FREE(nt_pw_ptr);
244         SAFE_FREE(hours);
245
246         return ret;
247 }
248
249 /*********************************************************************
250 *********************************************************************/
251
252 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
253 {
254
255         /* times are stored as 32bit integer
256            take care on system with 64bit wide time_t
257            --SSS */
258         uint32  logon_time,
259                 logoff_time,
260                 kickoff_time,
261                 bad_password_time,
262                 pass_last_set_time,
263                 pass_can_change_time,
264                 pass_must_change_time;
265         char *username = NULL;
266         char *domain = NULL;
267         char *nt_username = NULL;
268         char *dir_drive = NULL;
269         char *unknown_str = NULL;
270         char *munged_dial = NULL;
271         char *fullname = NULL;
272         char *homedir = NULL;
273         char *logon_script = NULL;
274         char *profile_path = NULL;
275         char *acct_desc = NULL;
276         char *workstations = NULL;
277         uint32  username_len, domain_len, nt_username_len,
278                 dir_drive_len, unknown_str_len, munged_dial_len,
279                 fullname_len, homedir_len, logon_script_len,
280                 profile_path_len, acct_desc_len, workstations_len;
281                 
282         uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
283         uint16  acct_ctrl, logon_divs;
284         uint16  bad_password_count, logon_count;
285         uint8   *hours = NULL;
286         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
287         uint32          len = 0;
288         uint32          lm_pw_len, nt_pw_len, hourslen;
289         BOOL ret = True;
290         
291         if(sampass == NULL || buf == NULL) {
292                 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
293                 return False;
294         }
295
296 /* TDB_FORMAT_STRING_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
297
298         /* unpack the buffer into variables */
299         len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
300                 &logon_time,                                            /* d */
301                 &logoff_time,                                           /* d */
302                 &kickoff_time,                                          /* d */
303                 /* Change from V0 is addition of bad_password_time field. */
304                 &bad_password_time,                                     /* d */
305                 &pass_last_set_time,                                    /* d */
306                 &pass_can_change_time,                                  /* d */
307                 &pass_must_change_time,                                 /* d */
308                 &username_len, &username,                               /* B */
309                 &domain_len, &domain,                                   /* B */
310                 &nt_username_len, &nt_username,                         /* B */
311                 &fullname_len, &fullname,                               /* B */
312                 &homedir_len, &homedir,                                 /* B */
313                 &dir_drive_len, &dir_drive,                             /* B */
314                 &logon_script_len, &logon_script,                       /* B */
315                 &profile_path_len, &profile_path,                       /* B */
316                 &acct_desc_len, &acct_desc,                             /* B */
317                 &workstations_len, &workstations,                       /* B */
318                 &unknown_str_len, &unknown_str,                         /* B */
319                 &munged_dial_len, &munged_dial,                         /* B */
320                 &user_rid,                                              /* d */
321                 &group_rid,                                             /* d */
322                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
323                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
324                 &acct_ctrl,                                             /* w */
325                 &remove_me,                                             /* d */
326                 &logon_divs,                                            /* w */
327                 &hours_len,                                             /* d */
328                 &hourslen, &hours,                                      /* B */
329                 &bad_password_count,                                    /* w */
330                 &logon_count,                                           /* w */
331                 &unknown_6);                                            /* d */
332                 
333         if (len == (uint32) -1)  {
334                 ret = False;
335                 goto done;
336         }
337
338         pdb_set_logon_time(sampass, logon_time, PDB_SET);
339         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
340         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
341
342         /* Change from V0 is addition of bad_password_time field. */
343         pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
344         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
345         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
346         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
347
348         pdb_set_username(sampass, username, PDB_SET); 
349         pdb_set_domain(sampass, domain, PDB_SET);
350         pdb_set_nt_username(sampass, nt_username, PDB_SET);
351         pdb_set_fullname(sampass, fullname, PDB_SET);
352
353         if (homedir) {
354                 pdb_set_homedir(sampass, homedir, PDB_SET);
355         }
356         else {
357                 pdb_set_homedir(sampass, 
358                         talloc_sub_basic(sampass, username, lp_logon_home()),
359                         PDB_DEFAULT);
360         }
361
362         if (dir_drive)  
363                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
364         else {
365                 pdb_set_dir_drive(sampass, 
366                         talloc_sub_basic(sampass,  username, lp_logon_drive()),
367                         PDB_DEFAULT);
368         }
369
370         if (logon_script) 
371                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
372         else {
373                 pdb_set_logon_script(sampass, 
374                         talloc_sub_basic(sampass, username, lp_logon_script()),
375                         PDB_DEFAULT);
376         }
377         
378         if (profile_path) {     
379                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
380         } else {
381                 pdb_set_profile_path(sampass, 
382                         talloc_sub_basic(sampass, username, lp_logon_path()),
383                         PDB_DEFAULT);
384         }
385
386         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
387         pdb_set_workstations(sampass, workstations, PDB_SET);
388         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
389
390         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
391                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
392                         ret = False;
393                         goto done;
394                 }
395         }
396
397         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
398                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
399                         ret = False;
400                         goto done;
401                 }
402         }
403
404         pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
405
406         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
407         pdb_set_hours_len(sampass, hours_len, PDB_SET);
408         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
409         pdb_set_logon_count(sampass, logon_count, PDB_SET);
410         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
411         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
412         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
413         pdb_set_hours(sampass, hours, PDB_SET);
414
415 done:
416
417         SAFE_FREE(username);
418         SAFE_FREE(domain);
419         SAFE_FREE(nt_username);
420         SAFE_FREE(fullname);
421         SAFE_FREE(homedir);
422         SAFE_FREE(dir_drive);
423         SAFE_FREE(logon_script);
424         SAFE_FREE(profile_path);
425         SAFE_FREE(acct_desc);
426         SAFE_FREE(workstations);
427         SAFE_FREE(munged_dial);
428         SAFE_FREE(unknown_str);
429         SAFE_FREE(lm_pw_ptr);
430         SAFE_FREE(nt_pw_ptr);
431         SAFE_FREE(hours);
432
433         return ret;
434 }
435
436 BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
437 {
438
439         /* times are stored as 32bit integer
440            take care on system with 64bit wide time_t
441            --SSS */
442         uint32  logon_time,
443                 logoff_time,
444                 kickoff_time,
445                 bad_password_time,
446                 pass_last_set_time,
447                 pass_can_change_time,
448                 pass_must_change_time;
449         char *username = NULL;
450         char *domain = NULL;
451         char *nt_username = NULL;
452         char *dir_drive = NULL;
453         char *unknown_str = NULL;
454         char *munged_dial = NULL;
455         char *fullname = NULL;
456         char *homedir = NULL;
457         char *logon_script = NULL;
458         char *profile_path = NULL;
459         char *acct_desc = NULL;
460         char *workstations = NULL;
461         uint32  username_len, domain_len, nt_username_len,
462                 dir_drive_len, unknown_str_len, munged_dial_len,
463                 fullname_len, homedir_len, logon_script_len,
464                 profile_path_len, acct_desc_len, workstations_len;
465                 
466         uint32  user_rid, group_rid, hours_len, unknown_6;
467         uint16  acct_ctrl, logon_divs;
468         uint16  bad_password_count, logon_count;
469         uint8   *hours = NULL;
470         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
471         uint32          len = 0;
472         uint32          lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
473         uint32 pwHistLen = 0;
474         BOOL ret = True;
475         fstring tmpstring;
476         BOOL expand_explicit = lp_passdb_expand_explicit();
477         
478         if(sampass == NULL || buf == NULL) {
479                 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
480                 return False;
481         }
482                                                                         
483 /* TDB_FORMAT_STRING_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
484
485         /* unpack the buffer into variables */
486         len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
487                 &logon_time,                                            /* d */
488                 &logoff_time,                                           /* d */
489                 &kickoff_time,                                          /* d */
490                 &bad_password_time,                                     /* d */
491                 &pass_last_set_time,                                    /* d */
492                 &pass_can_change_time,                                  /* d */
493                 &pass_must_change_time,                                 /* d */
494                 &username_len, &username,                               /* B */
495                 &domain_len, &domain,                                   /* B */
496                 &nt_username_len, &nt_username,                         /* B */
497                 &fullname_len, &fullname,                               /* B */
498                 &homedir_len, &homedir,                                 /* B */
499                 &dir_drive_len, &dir_drive,                             /* B */
500                 &logon_script_len, &logon_script,                       /* B */
501                 &profile_path_len, &profile_path,                       /* B */
502                 &acct_desc_len, &acct_desc,                             /* B */
503                 &workstations_len, &workstations,                       /* B */
504                 &unknown_str_len, &unknown_str,                         /* B */
505                 &munged_dial_len, &munged_dial,                         /* B */
506                 &user_rid,                                              /* d */
507                 &group_rid,                                             /* d */
508                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
509                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
510                 /* Change from V1 is addition of password history field. */
511                 &nt_pw_hist_len, &nt_pw_hist_ptr,                       /* B */
512                 &acct_ctrl,                                             /* w */
513                 /* Also "remove_me" field was removed. */
514                 &logon_divs,                                            /* w */
515                 &hours_len,                                             /* d */
516                 &hourslen, &hours,                                      /* B */
517                 &bad_password_count,                                    /* w */
518                 &logon_count,                                           /* w */
519                 &unknown_6);                                            /* d */
520                 
521         if (len == (uint32) -1)  {
522                 ret = False;
523                 goto done;
524         }
525
526         pdb_set_logon_time(sampass, logon_time, PDB_SET);
527         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
528         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
529         pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
530         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
531         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
532         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
533
534         pdb_set_username(sampass, username, PDB_SET); 
535         pdb_set_domain(sampass, domain, PDB_SET);
536         pdb_set_nt_username(sampass, nt_username, PDB_SET);
537         pdb_set_fullname(sampass, fullname, PDB_SET);
538
539         if (homedir) {
540                 fstrcpy( tmpstring, homedir );
541                 if (expand_explicit) {
542                         standard_sub_basic( username, tmpstring,
543                                             sizeof(tmpstring) );
544                 }
545                 pdb_set_homedir(sampass, tmpstring, PDB_SET);
546         }
547         else {
548                 pdb_set_homedir(sampass, 
549                         talloc_sub_basic(sampass, username, lp_logon_home()),
550                         PDB_DEFAULT);
551         }
552
553         if (dir_drive)  
554                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
555         else
556                 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
557
558         if (logon_script) {
559                 fstrcpy( tmpstring, logon_script );
560                 if (expand_explicit) {
561                         standard_sub_basic( username, tmpstring,
562                                             sizeof(tmpstring) );
563                 }
564                 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
565         }
566         else {
567                 pdb_set_logon_script(sampass, 
568                         talloc_sub_basic(sampass, username, lp_logon_script()),
569                         PDB_DEFAULT);
570         }
571         
572         if (profile_path) {     
573                 fstrcpy( tmpstring, profile_path );
574                 if (expand_explicit) {
575                         standard_sub_basic( username, tmpstring,
576                                             sizeof(tmpstring) );
577                 }
578                 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
579         } 
580         else {
581                 pdb_set_profile_path(sampass, 
582                         talloc_sub_basic(sampass, username, lp_logon_path()),
583                         PDB_DEFAULT);
584         }
585
586         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
587         pdb_set_workstations(sampass, workstations, PDB_SET);
588         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
589
590         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
591                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
592                         ret = False;
593                         goto done;
594                 }
595         }
596
597         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
598                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
599                         ret = False;
600                         goto done;
601                 }
602         }
603
604         /* Change from V1 is addition of password history field. */
605         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
606         if (pwHistLen) {
607                 uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
608                 if (!pw_hist) {
609                         ret = False;
610                         goto done;
611                 }
612                 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
613                 if (nt_pw_hist_ptr && nt_pw_hist_len) {
614                         int i;
615                         SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
616                         nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
617                         for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
618                                 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
619                                         &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
620                                         PW_HISTORY_ENTRY_LEN);
621                         }
622                 }
623                 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
624                         SAFE_FREE(pw_hist);
625                         ret = False;
626                         goto done;
627                 }
628                 SAFE_FREE(pw_hist);
629         } else {
630                 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
631         }
632
633         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
634         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
635         pdb_set_hours_len(sampass, hours_len, PDB_SET);
636         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
637         pdb_set_logon_count(sampass, logon_count, PDB_SET);
638         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
639         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
640         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
641         pdb_set_hours(sampass, hours, PDB_SET);
642
643 done:
644
645         SAFE_FREE(username);
646         SAFE_FREE(domain);
647         SAFE_FREE(nt_username);
648         SAFE_FREE(fullname);
649         SAFE_FREE(homedir);
650         SAFE_FREE(dir_drive);
651         SAFE_FREE(logon_script);
652         SAFE_FREE(profile_path);
653         SAFE_FREE(acct_desc);
654         SAFE_FREE(workstations);
655         SAFE_FREE(munged_dial);
656         SAFE_FREE(unknown_str);
657         SAFE_FREE(lm_pw_ptr);
658         SAFE_FREE(nt_pw_ptr);
659         SAFE_FREE(nt_pw_hist_ptr);
660         SAFE_FREE(hours);
661
662         return ret;
663 }
664
665
666 /**********************************************************************
667  Intialize a struct samu struct from a BYTE buffer of size len
668  *********************************************************************/
669
670 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
671 {
672         return init_sam_from_buffer_v3(sampass, buf, buflen);
673 }
674
675 /**********************************************************************
676  Intialize a BYTE buffer from a struct samu struct
677  *********************************************************************/
678
679 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
680 {
681         return init_buffer_from_sam_v3(buf, sampass, size_only);
682 }
683
684 /**********************************************************************
685  Intialize a BYTE buffer from a struct samu struct
686  *********************************************************************/
687
688 static BOOL tdbsam_convert(int32 from) 
689 {
690         const char      *vstring = TDBSAM_VERSION_STRING;
691         const char      *prefix = USERPREFIX;
692         TDB_DATA        data, key, old_key;
693         uint8           *buf = NULL;
694         BOOL            ret;
695
696         /* handle a Samba upgrade */
697         tdb_lock_bystring(tdbsam, vstring, 0);
698         
699         /* Enumerate all records and convert them */
700         key = tdb_firstkey(tdbsam);
701
702         while (key.dptr) {
703         
704                 /* skip all non-USER entries (eg. RIDs) */
705                 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
706                         old_key = key;
707                         /* increment to next in line */
708                         key = tdb_nextkey(tdbsam, key);
709                         SAFE_FREE(old_key.dptr);
710                 }
711         
712                 if (key.dptr) {
713                         struct samu *user = NULL;
714
715                         /* read from tdbsam */
716                         data = tdb_fetch(tdbsam, key);
717                         if (!data.dptr) {
718                                 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
719                                 return False;
720                         }
721         
722                         /* unpack the buffer from the former format */
723                         if ( !(user = samu_new( NULL )) ) {
724                                 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
725                                 SAFE_FREE( data.dptr );
726                                 return False;
727                         }
728                         DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
729                         switch (from) {
730                                 case 0:
731                                         ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
732                                         break;
733                                 case 1:
734                                         ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
735                                         break;
736                                 case 2:
737                                         ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
738                                         break;
739                                 case 3:
740                                         ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
741                                         break;
742                                 default:
743                                         /* unknown tdbsam version */
744                                         ret = False;
745                         }
746                         if (!ret) {
747                                 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
748                                 SAFE_FREE(data.dptr);
749                                 TALLOC_FREE(user );
750                                 return False;
751                         }
752         
753                         /* We're finished with the old data. */
754                         SAFE_FREE(data.dptr);
755
756                         /* pack from the buffer into the new format */
757                         
758                         DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
759                         data.dsize = init_buffer_from_sam (&buf, user, False);
760                         TALLOC_FREE(user );
761                         
762                         if ( data.dsize == -1 ) {
763                                 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
764                                 return False;
765                         }
766                         data.dptr = (char *)buf;
767                         
768                         /* Store the buffer inside the TDBSAM */
769                         if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
770                                 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
771                                 SAFE_FREE(data.dptr);
772                                 return False;
773                         }
774                         
775                         SAFE_FREE(data.dptr);
776                         
777                         /* increment to next in line */
778                         old_key = key;
779                         key = tdb_nextkey(tdbsam, key);
780                         SAFE_FREE(old_key.dptr);
781                 }
782                 
783         }
784
785         
786         /* upgrade finished */
787         tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
788         tdb_unlock_bystring(tdbsam, vstring);
789
790         return(True);   
791 }
792
793 /*********************************************************************
794  Open the tdbsam file based on the absolute path specified.
795  Uses a reference count to allow multiple open calls.
796 *********************************************************************/
797
798 static BOOL tdbsam_open( const char *name )
799 {
800         int32   version;
801         
802         /* check if we are already open */
803         
804         if ( tdbsam ) {
805                 ref_count++;
806                 DEBUG(8,("tdbsam_open: Incrementing open reference count.  Ref count is now %d\n", 
807                         ref_count));
808                 return True;
809         }
810         
811         SMB_ASSERT( ref_count == 0 );
812         
813         /* Try to open tdb passwd.  Create a new one if necessary */
814         
815         if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
816                 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
817                 return False;
818         }
819
820         /* Check the version */
821         version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
822         
823         if (version == -1)
824                 version = 0;    /* Version not found, assume version 0 */
825         
826         /* Compare the version */
827         if (version > TDBSAM_VERSION) {
828                 /* Version more recent than the latest known */ 
829                 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
830                 tdb_close( tdbsam );
831                 return False;
832         } 
833         
834         
835         if ( version < TDBSAM_VERSION ) {       
836                 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n", 
837                         version, TDBSAM_VERSION));
838                 
839                 if ( !tdbsam_convert(version) ) {
840                         DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
841                         tdb_close(tdbsam);
842                         return False;
843                 }
844                         
845                 DEBUG(3, ("TDBSAM converted successfully.\n"));
846         }
847         
848         /* set the initial reference count */
849
850         ref_count = 1;
851
852         DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));      
853         
854         return True;
855 }
856
857 /****************************************************************************
858  wrapper atound tdb_close() to handle the reference count
859 ****************************************************************************/
860
861 void tdbsam_close( void )
862 {
863         ref_count--;
864         
865         DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
866
867         SMB_ASSERT(ref_count >= 0 );
868         
869         if ( ref_count == 0 ) {
870                 tdb_close( tdbsam );
871                 tdbsam = NULL;
872         }
873         
874         return;
875 }
876
877 /****************************************************************************
878  creates a list of user keys
879 ****************************************************************************/
880
881 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
882 {
883         const char *prefix = USERPREFIX;
884         int  prefixlen = strlen (prefix);
885         struct pwent_list *ptr;
886         
887         if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
888                 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
889                         DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
890                         
891                         /* just return 0 and let the traversal continue */
892                         return 0;
893                 }
894                 ZERO_STRUCTP(ptr);
895                 
896                 /* save a copy of the key */
897                 
898                 ptr->key.dptr = memdup( key.dptr, key.dsize );
899                 ptr->key.dsize = key.dsize;
900                 
901                 DLIST_ADD( tdbsam_pwent_list, ptr );
902         
903         }
904         
905         
906         return 0;
907 }
908
909 /***************************************************************
910  Open the TDB passwd database for SAM account enumeration.
911  Save a list of user keys for iteration.
912 ****************************************************************/
913
914 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
915 {
916         if ( !tdbsam_open( tdbsam_filename ) ) {
917                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
918                 return NT_STATUS_ACCESS_DENIED;
919         }
920
921         tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
922         pwent_initialized = True;
923
924         return NT_STATUS_OK;
925 }
926
927
928 /***************************************************************
929  End enumeration of the TDB passwd list.
930 ****************************************************************/
931
932 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
933 {
934         struct pwent_list *ptr, *ptr_next;
935         
936         /* close the tdb only if we have a valid pwent state */
937         
938         if ( pwent_initialized ) {
939                 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
940                 tdbsam_close();
941         }
942         
943         /* clear out any remaining entries in the list */
944         
945         for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
946                 ptr_next = ptr->next;
947                 DLIST_REMOVE( tdbsam_pwent_list, ptr );
948                 SAFE_FREE( ptr->key.dptr);
949                 SAFE_FREE( ptr );
950         }       
951         
952         pwent_initialized = False;
953 }
954
955 /*****************************************************************
956  Get one struct samu from the TDB (next in line)
957 *****************************************************************/
958
959 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
960 {
961         NTSTATUS                nt_status = NT_STATUS_UNSUCCESSFUL;
962         TDB_DATA                data;
963         struct pwent_list       *pkey;
964
965         if ( !user ) {
966                 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
967                 return nt_status;
968         }
969
970         if ( !tdbsam_pwent_list ) {
971                 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
972                 return nt_status;
973         }
974         
975         /* pull the next entry */
976                 
977         pkey = tdbsam_pwent_list;
978         DLIST_REMOVE( tdbsam_pwent_list, pkey );
979         
980         data = tdb_fetch(tdbsam, pkey->key);
981
982         SAFE_FREE( pkey->key.dptr);
983         SAFE_FREE( pkey);
984         
985         if ( !data.dptr ) {
986                 DEBUG(5,("pdb_getsampwent: database entry not found.  Was the user deleted?\n"));
987                 return nt_status;
988         }
989   
990         if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
991                 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
992         }
993         
994         SAFE_FREE( data.dptr );
995
996         return NT_STATUS_OK;
997 }
998
999 /******************************************************************
1000  Lookup a name in the SAM TDB
1001 ******************************************************************/
1002
1003 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
1004 {
1005         NTSTATUS        result;
1006         TDB_DATA        data, key;
1007         fstring         keystr;
1008         fstring         name;
1009
1010         if ( !user ) {
1011                 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
1012                 return NT_STATUS_NO_MEMORY;
1013         }
1014
1015         /* Data is stored in all lower-case */
1016         fstrcpy(name, sname);
1017         strlower_m(name);
1018
1019         /* set search key */
1020         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1021         key.dptr = keystr;
1022         key.dsize = strlen(keystr) + 1;
1023
1024         /* open the database */
1025                 
1026         if ( !tdbsam_open( tdbsam_filename ) ) {
1027                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1028                 return NT_STATUS_ACCESS_DENIED;
1029         }
1030         
1031         /* get the record */
1032         
1033         data = tdb_fetch(tdbsam, key);
1034         if (!data.dptr) {
1035                 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
1036                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1037                 DEBUGADD(5, (" Key: %s\n", keystr));
1038                 result = NT_STATUS_NO_SUCH_USER;
1039                 goto done;
1040         }
1041   
1042         /* unpack the buffer */
1043         
1044         if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
1045                 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
1046                 SAFE_FREE(data.dptr);
1047                 result = NT_STATUS_NO_MEMORY;
1048                 goto done;
1049         }
1050         
1051         result = NT_STATUS_OK;
1052         
1053  done:
1054         SAFE_FREE(data.dptr);
1055         tdbsam_close();
1056         
1057         return result;
1058 }
1059
1060 /***************************************************************************
1061  Search by rid
1062  **************************************************************************/
1063
1064 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
1065 {
1066         NTSTATUS                nt_status = NT_STATUS_UNSUCCESSFUL;
1067         TDB_DATA                data, key;
1068         fstring                 keystr;
1069         fstring                 name;
1070
1071         if ( !user ) {
1072                 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
1073                 return nt_status;
1074         }
1075         
1076         /* set search key */
1077         
1078         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1079         key.dptr = keystr;
1080         key.dsize = strlen (keystr) + 1;
1081
1082         /* open the database */
1083                 
1084         if ( !tdbsam_open( tdbsam_filename ) ) {
1085                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1086                 return NT_STATUS_ACCESS_DENIED;
1087         }
1088
1089         /* get the record */
1090         
1091         data = tdb_fetch (tdbsam, key);
1092         if (!data.dptr) {
1093                 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
1094                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1095                 nt_status = NT_STATUS_UNSUCCESSFUL;
1096                 goto done;
1097         }
1098
1099         fstrcpy(name, data.dptr);
1100         SAFE_FREE(data.dptr);
1101         
1102         nt_status = tdbsam_getsampwnam (my_methods, user, name);
1103
1104  done:
1105         /* cleanup */
1106         
1107         tdbsam_close();
1108                 
1109         return nt_status;
1110 }
1111
1112 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
1113 {
1114         uint32 rid;
1115         
1116         if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
1117                 return NT_STATUS_UNSUCCESSFUL;
1118
1119         return tdbsam_getsampwrid(my_methods, user, rid);
1120 }
1121
1122 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
1123 {
1124         TDB_DATA        key;
1125         fstring         keystr;
1126         fstring         name;
1127
1128         fstrcpy(name, pdb_get_username(sam_pass));
1129         strlower_m(name);
1130         
1131         /* set the search key */
1132         
1133         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1134         key.dptr = keystr;
1135         key.dsize = strlen (keystr) + 1;
1136         
1137         /* it's outaa here!  8^) */
1138         
1139         if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
1140                 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1141                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1142                 return False;
1143         }
1144         
1145         return True;
1146 }
1147
1148 /***************************************************************************
1149  Delete a struct samu records for the username and RID key
1150 ****************************************************************************/
1151
1152 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
1153 {
1154         NTSTATUS        nt_status = NT_STATUS_UNSUCCESSFUL;
1155         TDB_DATA        key;
1156         fstring         keystr;
1157         uint32          rid;
1158         fstring         name;
1159         
1160         /* make sure we have an open handle to the tdb.  Should have happened 
1161            at module  initialization time */
1162            
1163         if ( !tdbsam ) {
1164                 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
1165                 return NT_STATUS_NO_SUCH_USER;
1166         }
1167
1168         fstrcpy(name, pdb_get_username(sam_pass));
1169         strlower_m(name);
1170         
1171         /* set the search key */
1172
1173         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1174         key.dptr = keystr;
1175         key.dsize = strlen (keystr) + 1;
1176         
1177         rid = pdb_get_user_rid(sam_pass);
1178
1179         /* open the database */
1180                 
1181         if ( !tdbsam_open( tdbsam_filename ) ) {
1182                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1183                 return NT_STATUS_ACCESS_DENIED;
1184         }
1185         
1186         /* it's outaa here!  8^) */
1187
1188         if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1189                 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
1190                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1191                 nt_status = NT_STATUS_UNSUCCESSFUL;
1192                 goto done;
1193         }
1194
1195         /* set the search key */
1196         
1197         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
1198         key.dptr = keystr;
1199         key.dsize = strlen (keystr) + 1;
1200
1201         /* it's outaa here!  8^) */
1202         
1203         if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
1204                 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
1205                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
1206                 nt_status = NT_STATUS_UNSUCCESSFUL;
1207                 goto done;
1208         }
1209
1210         nt_status = NT_STATUS_OK;
1211         
1212  done:
1213         tdbsam_close();
1214         
1215         return nt_status;
1216 }
1217
1218
1219 /***************************************************************************
1220  Update the TDB SAM account record only
1221  Assumes that the tdbsam is already open 
1222 ****************************************************************************/
1223 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
1224 {
1225         TDB_DATA        key, data;
1226         uint8           *buf = NULL;
1227         fstring         keystr;
1228         fstring         name;
1229         BOOL            ret = True;
1230
1231         /* copy the struct samu struct into a BYTE buffer for storage */
1232         
1233         if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
1234                 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
1235                 ret = False;
1236                 goto done;
1237         }
1238         data.dptr = (char *)buf;
1239
1240         fstrcpy(name, pdb_get_username(newpwd));
1241         strlower_m(name);
1242         
1243         DEBUG(5, ("Storing %saccount %s with RID %d\n", 
1244                   flag == TDB_INSERT ? "(new) " : "", name, 
1245                   pdb_get_user_rid(newpwd)));
1246
1247         /* setup the USER index key */
1248         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
1249         key.dptr = keystr;
1250         key.dsize = strlen(keystr) + 1;
1251
1252         /* add the account */
1253         
1254         if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
1255                 DEBUG(0, ("Unable to modify passwd TDB!"));
1256                 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
1257                 DEBUGADD(0, (" occured while storing the main record (%s)\n",
1258                              keystr));
1259                 ret = False;
1260                 goto done;
1261         }
1262
1263 done:   
1264         /* cleanup */
1265         SAFE_FREE(buf);
1266         
1267         return ret;
1268 }
1269
1270 /***************************************************************************
1271  Update the TDB SAM RID record only
1272  Assumes that the tdbsam is already open 
1273 ****************************************************************************/
1274 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
1275 {
1276         TDB_DATA        key, data;
1277         fstring         keystr;
1278         fstring         name;
1279
1280         fstrcpy(name, pdb_get_username(newpwd));
1281         strlower_m(name);
1282
1283         /* setup RID data */
1284         data.dsize = strlen(name) + 1;
1285         data.dptr = name;
1286
1287         /* setup the RID index key */
1288         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,  pdb_get_user_rid(newpwd));
1289         key.dptr = keystr;
1290         key.dsize = strlen (keystr) + 1;
1291         
1292         /* add the reference */
1293         if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
1294                 DEBUG(0, ("Unable to modify TDB passwd !"));
1295                 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
1296                 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
1297                 return False;
1298         }
1299
1300         return True;
1301
1302 }
1303
1304 /***************************************************************************
1305  Update the TDB SAM
1306 ****************************************************************************/
1307
1308 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
1309 {
1310         uint32          user_rid;
1311         BOOL            result = True;
1312
1313         /* invalidate the existing TDB iterator if it is open */
1314         
1315         tdbsam_endsampwent( my_methods );
1316         
1317         if ( !pdb_get_group_rid(newpwd) ) {
1318                 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
1319                         "without a primary group RID\n", pdb_get_username(newpwd)));
1320                 return False;
1321         }
1322
1323         if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
1324                 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
1325                 return False;
1326         }
1327
1328         /* open the database */
1329                 
1330         if ( !tdbsam_open( tdbsam_filename ) ) {
1331                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1332                 return False;
1333         }
1334         
1335         if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
1336                 result = False;
1337         }
1338
1339         /* cleanup */
1340
1341         tdbsam_close();
1342         
1343         return result;  
1344 }
1345
1346 /***************************************************************************
1347  Modifies an existing struct samu
1348 ****************************************************************************/
1349
1350 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1351 {
1352         if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
1353                 return NT_STATUS_UNSUCCESSFUL;
1354         
1355         return NT_STATUS_OK;
1356 }
1357
1358 /***************************************************************************
1359  Adds an existing struct samu
1360 ****************************************************************************/
1361
1362 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
1363 {
1364         if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
1365                 return NT_STATUS_UNSUCCESSFUL;
1366                 
1367         return NT_STATUS_OK;
1368 }
1369
1370 /***************************************************************************
1371  Renames a struct samu
1372  - check for the posix user/rename user script
1373  - Add and lock the new user record
1374  - rename the posix user
1375  - rewrite the rid->username record
1376  - delete the old user
1377  - unlock the new user record
1378 ***************************************************************************/
1379 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1380                                           struct samu *old_acct, 
1381                                           const char *newname)
1382 {
1383         struct samu      *new_acct = NULL;
1384         pstring          rename_script;
1385         BOOL             interim_account = False;
1386         int              rename_ret;
1387
1388         /* make sure we have an open handle to the tdb.  Should have happened 
1389            at module  initialization time */
1390            
1391         if ( !tdbsam ) {
1392                 DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
1393                 return NT_STATUS_NO_SUCH_USER;
1394         }
1395         
1396         /* can't do anything without an external script */
1397         
1398         pstrcpy(rename_script, lp_renameuser_script() );
1399         if ( ! *rename_script )
1400                 return NT_STATUS_ACCESS_DENIED;
1401
1402         /* invalidate the existing TDB iterator if it is open */
1403         
1404         tdbsam_endsampwent( my_methods );
1405
1406         if ( !(new_acct = samu_new( NULL )) ) {
1407                 return NT_STATUS_NO_MEMORY;
1408         }
1409         
1410         if ( !pdb_copy_sam_account(new_acct, old_acct) 
1411                 || !pdb_set_username(new_acct, newname, PDB_CHANGED)) 
1412         {
1413                 TALLOC_FREE(new_acct );
1414                 return NT_STATUS_NO_MEMORY;
1415         }
1416
1417         /* open the database */
1418                 
1419         if ( !tdbsam_open( tdbsam_filename ) ) {
1420                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
1421                 TALLOC_FREE(new_acct );
1422                 return NT_STATUS_ACCESS_DENIED;
1423         }
1424
1425         /* add the new account and lock it */
1426         
1427         if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) 
1428         {
1429                 goto done;
1430         }
1431         
1432         interim_account = True;
1433
1434         if ( tdb_lock_bystring(tdbsam, newname, 30) == -1 ) {
1435                 goto done;
1436         }
1437
1438         /* rename the posix user */
1439         string_sub2(rename_script, "%unew", newname, sizeof(pstring), 
1440                     True, False, True);
1441         string_sub2(rename_script, "%uold", pdb_get_username(old_acct), 
1442                     sizeof(pstring), True, False, True);
1443         rename_ret = smbrun(rename_script, NULL);
1444
1445         DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
1446
1447         if (rename_ret) 
1448                 goto done; 
1449
1450         /* rewrite the rid->username record */
1451         
1452         if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) )
1453                 goto done;
1454         interim_account = False;
1455         tdb_unlock_bystring( tdbsam, newname );
1456
1457         tdb_delete_samacct_only( old_acct );
1458         
1459         tdbsam_close();
1460         
1461         TALLOC_FREE(new_acct );
1462         return NT_STATUS_OK;
1463
1464 done:   
1465         /* cleanup */
1466         if (interim_account) {
1467                 tdb_unlock_bystring(tdbsam, newname);
1468                 tdb_delete_samacct_only(new_acct);
1469         }
1470         
1471         tdbsam_close();
1472         
1473         if (new_acct)
1474                 TALLOC_FREE(new_acct);
1475         
1476         return NT_STATUS_ACCESS_DENIED; 
1477 }
1478
1479 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
1480 {
1481         return False;
1482 }
1483
1484 /*
1485  * Historically, winbind was responsible for allocating RIDs, so the next RID
1486  * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
1487  * but for compatibility reasons we still keep the the next RID counter in
1488  * winbindd_idmap.tdb.
1489  */
1490
1491 /*****************************************************************************
1492  Initialise idmap database. For now (Dec 2005) this is a copy of the code in
1493  sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
1494  winbind completely and store the RID counter in passdb.tdb.
1495
1496  Dont' fully initialize with the HWM values, if it's new, we're only
1497  interested in the RID counter.
1498 *****************************************************************************/
1499
1500 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
1501 {
1502         int32 version;
1503
1504         if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
1505                 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
1506                 return False;
1507         }
1508
1509         version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
1510
1511         if (version == -1) {
1512                 /* No key found, must be a new db */
1513                 if (tdb_store_int32(tdb, "IDMAP_VERSION",
1514                                     IDMAP_VERSION) != 0) {
1515                         DEBUG(0, ("Could not store IDMAP_VERSION\n"));
1516                         tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1517                         return False;
1518                 }
1519                 version = IDMAP_VERSION;
1520         }
1521
1522         if (version != IDMAP_VERSION) {
1523                 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
1524                           "start winbind once\n", IDMAP_VERSION, version));
1525                 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1526                 return False;
1527         }
1528
1529         tdb_unlock_bystring(tdb, "IDMAP_VERSION");
1530         return True;
1531 }
1532
1533 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1534 {
1535         TDB_CONTEXT *tdb;
1536         uint32 rid;
1537         BOOL ret = False;
1538
1539         tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
1540                            TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
1541
1542         if (tdb == NULL) {
1543                 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
1544                 goto done;
1545         }
1546
1547         if (!init_idmap_tdb(tdb)) {
1548                 DEBUG(1, ("Could not init idmap\n"));
1549                 goto done;
1550         }
1551
1552         rid = BASE_RID;         /* Default if not set */
1553
1554         if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
1555                 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
1556                 goto done;
1557         }
1558
1559         *prid = rid;
1560         ret = True;
1561
1562  done:
1563         if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
1564                 smb_panic("tdb_close(idmap_tdb) failed\n");
1565         }
1566
1567         return ret;
1568 }
1569
1570 /*********************************************************************
1571  Initialize the tdb sam backend.  Setup the dispath table of methods,
1572  open the tdb, etc...
1573 *********************************************************************/
1574
1575 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1576 {
1577         NTSTATUS nt_status;
1578         pstring tdbfile;
1579         const char *pfile = location;
1580
1581         if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1582                 return nt_status;
1583         }
1584
1585         (*pdb_method)->name = "tdbsam";
1586
1587         (*pdb_method)->setsampwent = tdbsam_setsampwent;
1588         (*pdb_method)->endsampwent = tdbsam_endsampwent;
1589         (*pdb_method)->getsampwent = tdbsam_getsampwent;
1590         (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1591         (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1592         (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1593         (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1594         (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1595         (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1596
1597         (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
1598         (*pdb_method)->new_rid = tdbsam_new_rid;
1599
1600         /* save the path for later */
1601                            
1602         if ( !location ) {
1603                 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
1604                 pfile = tdbfile;
1605         }
1606         pstrcpy( tdbsam_filename, pfile );
1607
1608         /* no private data */
1609         
1610         (*pdb_method)->private_data      = NULL;
1611         (*pdb_method)->free_private_data = NULL;
1612
1613         return NT_STATUS_OK;
1614 }
1615
1616 NTSTATUS pdb_tdbsam_init(void)
1617 {
1618         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
1619 }