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