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