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