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