s3-libads: use ldap_init_fd() to initialize a ldap session if possible
[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-2009
8  * Copyright (C) Andrew Bartlett   2002
9  * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
10  * 
11  * This program is free software; you can redistribute it and/or modify it under
12  * the terms of the GNU General Public License as published by the Free
13  * Software Foundation; either version 3 of the License, or (at your option)
14  * any later version.
15  * 
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19  * more details.
20  * 
21  * You should have received a copy of the GNU General Public License along with
22  * this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 #include "includes.h"
26 #include "system/filesys.h"
27 #include "passdb.h"
28 #include "dbwrap/dbwrap.h"
29 #include "dbwrap/dbwrap_open.h"
30 #include "../libcli/security/security.h"
31 #include "util_tdb.h"
32 #include "passdb/pdb_tdb.h"
33
34 #if 0 /* when made a module use this */
35
36 static int tdbsam_debug_level = DBGC_ALL;
37 #undef DBGC_CLASS
38 #define DBGC_CLASS tdbsam_debug_level
39
40 #else
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_PASSDB
44
45 #endif
46
47 #define TDBSAM_VERSION  4       /* Most recent TDBSAM version */
48 #define TDBSAM_MINOR_VERSION    0       /* Most recent TDBSAM minor version */
49 #define TDBSAM_VERSION_STRING   "INFO/version"
50 #define TDBSAM_MINOR_VERSION_STRING     "INFO/minor_version"
51 #define PASSDB_FILE_NAME        "passdb.tdb"
52 #define USERPREFIX              "USER_"
53 #define USERPREFIX_LEN          5
54 #define RIDPREFIX               "RID_"
55 #define PRIVPREFIX              "PRIV_"
56 #define NEXT_RID_STRING         "NEXT_RID"
57
58 /* GLOBAL TDB SAM CONTEXT */
59
60 static struct db_context *db_sam;
61 static char *tdbsam_filename;
62 static bool map_builtin;
63
64 struct tdbsam_convert_state {
65         int32_t from;
66         bool success;
67 };
68
69 static int tdbsam_convert_one(struct db_record *rec, void *priv)
70 {
71         struct tdbsam_convert_state *state =
72                 (struct tdbsam_convert_state *)priv;
73         struct samu *user;
74         TDB_DATA data;
75         NTSTATUS status;
76         bool ret;
77         TDB_DATA key;
78         TDB_DATA value;
79
80         key = dbwrap_record_get_key(rec);
81
82         if (key.dsize < USERPREFIX_LEN) {
83                 return 0;
84         }
85         if (strncmp((char *)key.dptr, USERPREFIX, USERPREFIX_LEN) != 0) {
86                 return 0;
87         }
88
89         user = samu_new(talloc_tos());
90         if (user == NULL) {
91                 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
92                 state->success = false;
93                 return -1;
94         }
95
96         DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) "
97                   "(version:%d)\n", (char *)key.dptr, state->from));
98
99         value = dbwrap_record_get_value(rec);
100
101         switch (state->from) {
102         case 0:
103                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V0,
104                                             (uint8_t *)value.dptr,
105                                             value.dsize);
106                 break;
107         case 1:
108                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V1,
109                                             (uint8_t *)value.dptr,
110                                             value.dsize);
111                 break;
112         case 2:
113                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V2,
114                                             (uint8_t *)value.dptr,
115                                             value.dsize);
116                 break;
117         case 3:
118                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V3,
119                                             (uint8_t *)value.dptr,
120                                             value.dsize);
121                 break;
122         case 4:
123                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V4,
124                                             (uint8_t *)value.dptr,
125                                             value.dsize);
126                 break;
127         default:
128                 /* unknown tdbsam version */
129                 ret = False;
130         }
131         if (!ret) {
132                 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned "
133                          "from TDB (key:%s) (version:%d)\n", (char *)key.dptr,
134                          state->from));
135                 TALLOC_FREE(user);
136                 state->success = false;
137                 return -1;
138         }
139
140         data.dsize = init_buffer_from_samu(&data.dptr, user, false);
141         TALLOC_FREE(user);
142
143         if (data.dsize == -1) {
144                 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into "
145                          "the new format\n"));
146                 state->success = false;
147                 return -1;
148         }
149
150         status = dbwrap_record_store(rec, data, TDB_MODIFY);
151         if (!NT_STATUS_IS_OK(status)) {
152                 DEBUG(0, ("Could not store the new record: %s\n",
153                           nt_errstr(status)));
154                 state->success = false;
155                 return -1;
156         }
157
158         return 0;
159 }
160
161 /**********************************************************************
162  Struct and function to backup an old record.
163  *********************************************************************/
164
165 struct tdbsam_backup_state {
166         struct db_context *new_db;
167         bool success;
168 };
169
170 static int backup_copy_fn(struct db_record *orig_rec, void *state)
171 {
172         struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state;
173         struct db_record *new_rec;
174         NTSTATUS status;
175         TDB_DATA key;
176         TDB_DATA value;
177
178         key = dbwrap_record_get_key(orig_rec);
179
180         new_rec = dbwrap_fetch_locked(bs->new_db, talloc_tos(), key);
181         if (new_rec == NULL) {
182                 bs->success = false;
183                 return 1;
184         }
185
186         value = dbwrap_record_get_value(orig_rec);
187
188         status = dbwrap_record_store(new_rec, value, TDB_INSERT);
189
190         TALLOC_FREE(new_rec);
191
192         if (!NT_STATUS_IS_OK(status)) {
193                 bs->success = false;
194                 return 1;
195         }
196         return 0;
197 }
198
199 /**********************************************************************
200  Make a backup of an old passdb and replace the new one with it. We
201  have to do this as between 3.0.x and 3.2.x the hash function changed
202  by mistake (used unsigned char * instead of char *). This means the
203  previous simple update code will fail due to not being able to find
204  existing records to replace in the tdbsam_convert_one() function. JRA.
205  *********************************************************************/
206
207 static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db)
208 {
209         TALLOC_CTX *frame = talloc_stackframe();
210         const char *tmp_fname = NULL;
211         struct db_context *tmp_db = NULL;
212         struct db_context *orig_db = *pp_db;
213         struct tdbsam_backup_state bs;
214         NTSTATUS status;
215
216         tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname);
217         if (!tmp_fname) {
218                 TALLOC_FREE(frame);
219                 return false;
220         }
221
222         unlink(tmp_fname);
223
224         /* Remember to open this on the NULL context. We need
225          * it to stay around after we return from here. */
226
227         tmp_db = db_open(NULL, tmp_fname, 0,
228                          TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
229                          DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
230         if (tmp_db == NULL) {
231                 DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd "
232                           "[%s]\n", tmp_fname));
233                 TALLOC_FREE(frame);
234                 return false;
235         }
236
237         if (dbwrap_transaction_start(orig_db) != 0) {
238                 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n"));
239                 unlink(tmp_fname);
240                 TALLOC_FREE(tmp_db);
241                 TALLOC_FREE(frame);
242                 return false;
243         }
244         if (dbwrap_transaction_start(tmp_db) != 0) {
245                 DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n"));
246                 dbwrap_transaction_cancel(orig_db);
247                 unlink(tmp_fname);
248                 TALLOC_FREE(tmp_db);
249                 TALLOC_FREE(frame);
250                 return false;
251         }
252
253         bs.new_db = tmp_db;
254         bs.success = true;
255
256         status = dbwrap_traverse(orig_db, backup_copy_fn, (void *)&bs, NULL);
257         if (!NT_STATUS_IS_OK(status)) {
258                 DEBUG(0, ("tdbsam_convert_backup: traverse failed\n"));
259                 goto cancel;
260         }
261
262         if (!bs.success) {
263                 DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n"));
264                 goto cancel;
265         }
266
267         if (dbwrap_transaction_commit(orig_db) != 0) {
268                 smb_panic("tdbsam_convert_backup: orig commit failed\n");
269         }
270         if (dbwrap_transaction_commit(tmp_db) != 0) {
271                 smb_panic("tdbsam_convert_backup: orig commit failed\n");
272         }
273
274         /* be sure to close the DBs _before_ renaming the file */
275
276         TALLOC_FREE(orig_db);
277         TALLOC_FREE(tmp_db);
278
279         /* This is safe from other users as we know we're
280          * under a mutex here. */
281
282         if (rename(tmp_fname, dbname) == -1) {
283                 DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n",
284                         tmp_fname,
285                         dbname,
286                         strerror(errno)));
287                 smb_panic("tdbsam_convert_backup: replace passdb failed\n");
288         }
289
290         TALLOC_FREE(frame);
291
292         /* re-open the converted TDB */
293
294         orig_db = db_open(NULL, dbname, 0,
295                           TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
296                           DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
297         if (orig_db == NULL) {
298                 DEBUG(0, ("tdbsam_convert_backup: Failed to re-open "
299                           "converted passdb TDB [%s]\n", dbname));
300                 return false;
301         }
302
303         DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n",
304                 dbname ));
305
306         /* Replace the global db pointer. */
307         *pp_db = orig_db;
308         return true;
309
310   cancel:
311
312         if (dbwrap_transaction_cancel(orig_db) != 0) {
313                 smb_panic("tdbsam_convert: transaction_cancel failed");
314         }
315
316         if (dbwrap_transaction_cancel(tmp_db) != 0) {
317                 smb_panic("tdbsam_convert: transaction_cancel failed");
318         }
319
320         unlink(tmp_fname);
321         TALLOC_FREE(tmp_db);
322         TALLOC_FREE(frame);
323         return false;
324 }
325
326 static bool tdbsam_upgrade_next_rid(struct db_context *db)
327 {
328         TDB_CONTEXT *tdb;
329         uint32_t rid;
330         bool ok = false;
331         NTSTATUS status;
332         char *db_path;
333
334         status = dbwrap_fetch_uint32_bystring(db, NEXT_RID_STRING, &rid);
335         if (NT_STATUS_IS_OK(status)) {
336                 return true;
337         }
338
339         db_path = state_path(talloc_tos(), "winbindd_idmap.tdb");
340         if (db_path == NULL) {
341                 return false;
342         }
343
344         tdb = tdb_open_log(db_path, 0,
345                            TDB_DEFAULT, O_RDONLY, 0644);
346         TALLOC_FREE(db_path);
347         if (tdb) {
348                 ok = tdb_fetch_uint32(tdb, "RID_COUNTER", &rid);
349                 if (!ok) {
350                         rid = BASE_RID;
351                 }
352                 tdb_close(tdb);
353         } else {
354                 rid = BASE_RID;
355         }
356
357         status = dbwrap_store_uint32_bystring(db, NEXT_RID_STRING, rid);
358         if (!NT_STATUS_IS_OK(status)) {
359                 return false;
360         }
361
362         return true;
363 }
364
365 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32_t from)
366 {
367         struct tdbsam_convert_state state;
368         struct db_context *db = NULL;
369         NTSTATUS status;
370
371         /* We only need the update backup for local db's. */
372         if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) {
373                 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name));
374                 return false;
375         }
376
377         db = *pp_db;
378         state.from = from;
379         state.success = true;
380
381         if (dbwrap_transaction_start(db) != 0) {
382                 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
383                 return false;
384         }
385
386         if (!tdbsam_upgrade_next_rid(db)) {
387                 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
388                 goto cancel;
389         }
390
391         status = dbwrap_traverse(db, tdbsam_convert_one, &state, NULL);
392         if (!NT_STATUS_IS_OK(status)) {
393                 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
394                 goto cancel;
395         }
396
397         if (!state.success) {
398                 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
399                 goto cancel;
400         }
401
402         status = dbwrap_store_int32_bystring(db, TDBSAM_VERSION_STRING,
403                                              TDBSAM_VERSION);
404         if (!NT_STATUS_IS_OK(status)) {
405                 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version: "
406                           "%s\n", nt_errstr(status)));
407                 goto cancel;
408         }
409
410         status = dbwrap_store_int32_bystring(db, TDBSAM_MINOR_VERSION_STRING,
411                                              TDBSAM_MINOR_VERSION);
412         if (!NT_STATUS_IS_OK(status)) {
413                 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor "
414                           "version: %s\n", nt_errstr(status)));
415                 goto cancel;
416         }
417
418         if (dbwrap_transaction_commit(db) != 0) {
419                 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
420                 return false;
421         }
422
423         return true;
424
425  cancel:
426         if (dbwrap_transaction_cancel(db) != 0) {
427                 smb_panic("tdbsam_convert: transaction_cancel failed");
428         }
429
430         return false;
431 }
432
433 /*********************************************************************
434  Open the tdbsam file based on the absolute path specified.
435  Uses a reference count to allow multiple open calls.
436 *********************************************************************/
437
438 static bool tdbsam_open( const char *name )
439 {
440         int32_t version;
441         int32_t minor_version;
442         NTSTATUS status;
443
444         /* check if we are already open */
445
446         if ( db_sam ) {
447                 return true;
448         }
449
450         /* Try to open tdb passwd.  Create a new one if necessary */
451
452         db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
453                          DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
454         if (db_sam == NULL) {
455                 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
456                           "[%s]\n", name));
457                 return false;
458         }
459
460         /* Check the version */
461         status = dbwrap_fetch_int32_bystring(db_sam, TDBSAM_VERSION_STRING,
462                                              &version);
463         if (!NT_STATUS_IS_OK(status)) {
464                 version = 0;    /* Version not found, assume version 0 */
465         }
466
467         /* Get the minor version */
468         status = dbwrap_fetch_int32_bystring(
469                 db_sam, TDBSAM_MINOR_VERSION_STRING, &minor_version);
470         if (!NT_STATUS_IS_OK(status)) {
471                 minor_version = 0; /* Minor version not found, assume 0 */
472         }
473
474         /* Compare the version */
475         if (version > TDBSAM_VERSION) {
476                 /* Version more recent than the latest known */
477                 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
478                 TALLOC_FREE(db_sam);
479                 return false;
480         }
481
482         if ( version < TDBSAM_VERSION ||
483                         (version == TDBSAM_VERSION &&
484                          minor_version < TDBSAM_MINOR_VERSION) ) {
485                 /*
486                  * Ok - we think we're going to have to convert.
487                  * Due to the backup process we now must do to
488                  * upgrade we have to get a mutex and re-check
489                  * the version. Someone else may have upgraded
490                  * whilst we were checking.
491                  */
492
493                 struct named_mutex *mtx = grab_named_mutex(NULL,
494                                                 "tdbsam_upgrade_mutex",
495                                                 600);
496
497                 if (!mtx) {
498                         DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
499                         TALLOC_FREE(db_sam);
500                         return false;
501                 }
502
503                 /* Re-check the version */
504                 status = dbwrap_fetch_int32_bystring(
505                         db_sam, TDBSAM_VERSION_STRING, &version);
506                 if (!NT_STATUS_IS_OK(status)) {
507                         version = 0;    /* Version not found, assume version 0 */
508                 }
509
510                 /* Re-check the minor version */
511                 status = dbwrap_fetch_int32_bystring(
512                         db_sam, TDBSAM_MINOR_VERSION_STRING, &minor_version);
513                 if (!NT_STATUS_IS_OK(status)) {
514                         minor_version = 0; /* Minor version not found, assume 0 */
515                 }
516
517                 /* Compare the version */
518                 if (version > TDBSAM_VERSION) {
519                         /* Version more recent than the latest known */
520                         DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
521                         TALLOC_FREE(db_sam);
522                         TALLOC_FREE(mtx);
523                         return false;
524                 }
525
526                 if ( version < TDBSAM_VERSION ||
527                                 (version == TDBSAM_VERSION &&
528                                  minor_version < TDBSAM_MINOR_VERSION) ) {
529                         /*
530                          * Note that minor versions we read that are greater
531                          * than the current minor version we have hard coded
532                          * are assumed to be compatible if they have the same
533                          * major version. That allows previous versions of the
534                          * passdb code that don't know about minor versions to
535                          * still use this database. JRA.
536                          */
537
538                         DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
539                                   "version %d.%d.\n",
540                                         version,
541                                         minor_version,
542                                         TDBSAM_VERSION,
543                                         TDBSAM_MINOR_VERSION));
544
545                         if ( !tdbsam_convert(&db_sam, name, version) ) {
546                                 DEBUG(0, ("tdbsam_open: Error when trying to convert "
547                                           "tdbsam [%s]\n",name));
548                                 TALLOC_FREE(db_sam);
549                                 TALLOC_FREE(mtx);
550                                 return false;
551                         }
552
553                         DEBUG(3, ("TDBSAM converted successfully.\n"));
554                 }
555                 TALLOC_FREE(mtx);
556         }
557
558         DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
559
560         return true;
561 }
562
563 /******************************************************************
564  Lookup a name in the SAM TDB
565 ******************************************************************/
566
567 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
568                                     struct samu *user, const char *sname)
569 {
570         TDB_DATA        data;
571         fstring         keystr;
572         fstring         name;
573         NTSTATUS status;
574
575         if ( !user ) {
576                 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
577                 return NT_STATUS_NO_MEMORY;
578         }
579
580         /* Data is stored in all lower-case */
581         fstrcpy(name, sname);
582         if (!strlower_m(name)) {
583                 return NT_STATUS_INVALID_PARAMETER;
584         }
585
586         /* set search key */
587         fstr_sprintf(keystr, "%s%s", USERPREFIX, name);
588
589         /* open the database */
590
591         if ( !tdbsam_open( tdbsam_filename ) ) {
592                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
593                 return NT_STATUS_ACCESS_DENIED;
594         }
595
596         /* get the record */
597
598         status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
599         if (!NT_STATUS_IS_OK(status)) {
600                 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
601                 DEBUGADD(5, (" Key: %s\n", keystr));
602                 return NT_STATUS_NO_SUCH_USER;
603         }
604
605         if (data.dsize == 0) {
606                 DEBUG(5, ("%s: Got 0-sized record for key %s\n", __func__,
607                           keystr));
608                 return NT_STATUS_NO_SUCH_USER;
609         }
610
611         /* unpack the buffer */
612
613         if (!init_samu_from_buffer(user, SAMU_BUFFER_LATEST, data.dptr, data.dsize)) {
614                 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
615                 TALLOC_FREE(data.dptr);
616                 return NT_STATUS_NO_MEMORY;
617         }
618
619         /* success */
620
621         TALLOC_FREE(data.dptr);
622
623         return NT_STATUS_OK;
624 }
625
626 /***************************************************************************
627  Search by rid
628  **************************************************************************/
629
630 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
631                                     struct samu *user, uint32_t rid)
632 {
633         NTSTATUS                nt_status = NT_STATUS_UNSUCCESSFUL;
634         TDB_DATA                data;
635         fstring                 keystr;
636         fstring                 name;
637
638         if ( !user ) {
639                 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
640                 return nt_status;
641         }
642
643         /* set search key */
644
645         fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, rid);
646
647         /* open the database */
648
649         if ( !tdbsam_open( tdbsam_filename ) ) {
650                 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename));
651                 return NT_STATUS_ACCESS_DENIED;
652         }
653
654         /* get the record */
655
656         nt_status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
657         if (!NT_STATUS_IS_OK(nt_status)) {
658                 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
659                 return nt_status;
660         }
661
662         fstrcpy(name, (const char *)data.dptr);
663         TALLOC_FREE(data.dptr);
664
665         return tdbsam_getsampwnam (my_methods, user, name);
666 }
667
668 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
669                                    struct samu * user, const struct dom_sid *sid)
670 {
671         uint32_t rid;
672
673         if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
674                 return NT_STATUS_UNSUCCESSFUL;
675
676         return tdbsam_getsampwrid(my_methods, user, rid);
677 }
678
679 static bool tdb_delete_samacct_only( struct samu *sam_pass )
680 {
681         fstring         keystr;
682         fstring         name;
683         NTSTATUS status;
684
685         fstrcpy(name, pdb_get_username(sam_pass));
686         if (!strlower_m(name)) {
687                 return false;
688         }
689
690         /* set the search key */
691
692         fstr_sprintf(keystr, "%s%s", USERPREFIX, name);
693
694         /* it's outaa here!  8^) */
695         if ( !tdbsam_open( tdbsam_filename ) ) {
696                 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
697                          tdbsam_filename));
698                 return false;
699         }
700
701         status = dbwrap_delete_bystring(db_sam, keystr);
702         if (!NT_STATUS_IS_OK(status)) {
703                 DEBUG(5, ("Error deleting entry from tdb passwd "
704                           "database: %s!\n", nt_errstr(status)));
705                 return false;
706         }
707
708         return true;
709 }
710
711 /***************************************************************************
712  Delete a struct samu records for the username and RID key
713 ****************************************************************************/
714
715 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
716                                           struct samu *sam_pass)
717 {
718         NTSTATUS        nt_status;
719         fstring         keystr;
720         uint32_t        rid;
721         fstring         name;
722
723         /* open the database */
724
725         if ( !tdbsam_open( tdbsam_filename ) ) {
726                 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
727                          tdbsam_filename));
728                 return NT_STATUS_ACCESS_DENIED;
729         }
730
731         fstrcpy(name, pdb_get_username(sam_pass));
732         if (!strlower_m(name)) {
733                 return NT_STATUS_INVALID_PARAMETER;
734         }
735
736         /* set the search key */
737
738         fstr_sprintf(keystr, "%s%s", USERPREFIX, name);
739
740         rid = pdb_get_user_rid(sam_pass);
741
742         /* it's outaa here!  8^) */
743
744         if (dbwrap_transaction_start(db_sam) != 0) {
745                 DEBUG(0, ("Could not start transaction\n"));
746                 return NT_STATUS_UNSUCCESSFUL;
747         }
748
749         nt_status = dbwrap_delete_bystring(db_sam, keystr);
750         if (!NT_STATUS_IS_OK(nt_status)) {
751                 DEBUG(5, ("Error deleting entry from tdb passwd "
752                           "database: %s!\n", nt_errstr(nt_status)));
753                 goto cancel;
754         }
755
756         /* set the search key */
757
758         fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, rid);
759
760         /* it's outaa here!  8^) */
761
762         nt_status = dbwrap_delete_bystring(db_sam, keystr);
763         if (!NT_STATUS_IS_OK(nt_status)) {
764                 DEBUG(5, ("Error deleting entry from tdb rid "
765                           "database: %s!\n", nt_errstr(nt_status)));
766                 goto cancel;
767         }
768
769         if (dbwrap_transaction_commit(db_sam) != 0) {
770                 DEBUG(0, ("Could not commit transaction\n"));
771                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
772         }
773
774         return NT_STATUS_OK;
775
776  cancel:
777         if (dbwrap_transaction_cancel(db_sam) != 0) {
778                 smb_panic("transaction_cancel failed");
779         }
780
781         return nt_status;
782 }
783
784
785 /***************************************************************************
786  Update the TDB SAM account record only
787  Assumes that the tdbsam is already open 
788 ****************************************************************************/
789 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
790 {
791         TDB_DATA        data;
792         uint8_t         *buf = NULL;
793         fstring         keystr;
794         fstring         name;
795         bool            ret = false;
796         NTSTATUS status;
797
798         /* copy the struct samu struct into a BYTE buffer for storage */
799
800         if ( (data.dsize=init_buffer_from_samu(&buf, newpwd, False)) == -1 ) {
801                 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
802                 goto done;
803         }
804         data.dptr = buf;
805
806         fstrcpy(name, pdb_get_username(newpwd));
807         if (!strlower_m(name)) {
808                 goto done;
809         }
810
811         DEBUG(5, ("Storing %saccount %s with RID %d\n",
812                   flag == TDB_INSERT ? "(new) " : "", name,
813                   pdb_get_user_rid(newpwd)));
814
815         /* setup the USER index key */
816         fstr_sprintf(keystr, "%s%s", USERPREFIX, name);
817
818         /* add the account */
819
820         status = dbwrap_store_bystring(db_sam, keystr, data, flag);
821         if (!NT_STATUS_IS_OK(status)) {
822                 DEBUG(0, ("Unable to modify passwd TDB: %s!",
823                           nt_errstr(status)));
824                 goto done;
825         }
826
827         ret = true;
828
829 done:
830         /* cleanup */
831         SAFE_FREE(buf);
832         return ret;
833 }
834
835 /***************************************************************************
836  Update the TDB SAM RID record only
837  Assumes that the tdbsam is already open
838 ****************************************************************************/
839 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
840 {
841         TDB_DATA        data;
842         fstring         keystr;
843         fstring         name;
844         NTSTATUS status;
845
846         fstrcpy(name, pdb_get_username(newpwd));
847         if (!strlower_m(name)) {
848                 return false;
849         }
850
851         /* setup RID data */
852         data = string_term_tdb_data(name);
853
854         /* setup the RID index key */
855         fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
856
857         /* add the reference */
858         status = dbwrap_store_bystring(db_sam, keystr, data, flag);
859         if (!NT_STATUS_IS_OK(status)) {
860                 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
861                           nt_errstr(status)));
862                 return false;
863         }
864
865         return true;
866
867 }
868
869 /***************************************************************************
870  Update the TDB SAM
871 ****************************************************************************/
872
873 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
874                            int flag)
875 {
876         uint32_t oldrid;
877         uint32_t newrid;
878
879         if (!(newrid = pdb_get_user_rid(newpwd))) {
880                 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
881                          pdb_get_username(newpwd)));
882                 return False;
883         }
884
885         oldrid = newrid;
886
887         /* open the database */
888
889         if ( !tdbsam_open( tdbsam_filename ) ) {
890                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
891                 return False;
892         }
893
894         if (dbwrap_transaction_start(db_sam) != 0) {
895                 DEBUG(0, ("Could not start transaction\n"));
896                 return false;
897         }
898
899         /* If we are updating, we may be changing this users RID. Retrieve the old RID
900            so we can check. */
901
902         if (flag == TDB_MODIFY) {
903                 struct samu *account = samu_new(talloc_tos());
904                 if (account == NULL) {
905                         DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
906                         goto cancel;
907                 }
908                 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods, account, pdb_get_username(newpwd)))) {
909                         DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
910                                 pdb_get_username(newpwd)));
911                         TALLOC_FREE(account);
912                         goto cancel;
913                 }
914                 if (!(oldrid = pdb_get_user_rid(account))) {
915                         DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
916                         TALLOC_FREE(account);
917                         goto cancel;
918                 }
919                 TALLOC_FREE(account);
920         }
921
922         /* Update the new samu entry. */
923         if (!tdb_update_samacct_only(newpwd, flag)) {
924                 goto cancel;
925         }
926
927         /* Now take care of the case where the RID changed. We need
928          * to delete the old RID key and add the new. */
929
930         if (flag == TDB_MODIFY && newrid != oldrid) { 
931                 fstring keystr;
932
933                 /* Delete old RID key */
934                 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid));
935                 fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, oldrid);
936                 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam, keystr))) {
937                         DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr));
938                         goto cancel;
939                 }
940                 /* Insert new RID key */
941                 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid));
942                 if (!tdb_update_ridrec_only(newpwd, TDB_INSERT)) {
943                         goto cancel;
944                 }
945         } else {
946                 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
947                         flag == TDB_MODIFY ? "Updating" : "Inserting", newrid));
948                 if (!tdb_update_ridrec_only(newpwd, flag)) {
949                         goto cancel;
950                 }
951         }
952
953         if (dbwrap_transaction_commit(db_sam) != 0) {
954                 DEBUG(0, ("Could not commit transaction\n"));
955                 return false;
956         }
957
958         return true;
959
960  cancel:
961         if (dbwrap_transaction_cancel(db_sam) != 0) {
962                 smb_panic("transaction_cancel failed");
963         }
964         return false;
965 }
966
967 /***************************************************************************
968  Modifies an existing struct samu
969 ****************************************************************************/
970
971 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
972 {
973         if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
974                 return NT_STATUS_UNSUCCESSFUL;
975         
976         return NT_STATUS_OK;
977 }
978
979 /***************************************************************************
980  Adds an existing struct samu
981 ****************************************************************************/
982
983 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
984 {
985         if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
986                 return NT_STATUS_UNSUCCESSFUL;
987                 
988         return NT_STATUS_OK;
989 }
990
991 /***************************************************************************
992  Renames a struct samu
993  - check for the posix user/rename user script
994  - Add and lock the new user record
995  - rename the posix user
996  - rewrite the rid->username record
997  - delete the old user
998  - unlock the new user record
999 ***************************************************************************/
1000 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
1001                                           struct samu *old_acct,
1002                                           const char *newname)
1003 {
1004         const struct loadparm_substitution *lp_sub =
1005                 loadparm_s3_global_substitution();
1006         struct samu      *new_acct = NULL;
1007         char *rename_script = NULL;
1008         int              rename_ret;
1009         fstring          oldname_lower;
1010         fstring          newname_lower;
1011
1012         /* can't do anything without an external script */
1013
1014         if ( !(new_acct = samu_new( talloc_tos() )) ) {
1015                 return NT_STATUS_NO_MEMORY;
1016         }
1017
1018         rename_script = lp_rename_user_script(new_acct, lp_sub);
1019         if (!rename_script) {
1020                 TALLOC_FREE(new_acct);
1021                 return NT_STATUS_NO_MEMORY;
1022         }
1023         if (!*rename_script) {
1024                 TALLOC_FREE(new_acct);
1025                 return NT_STATUS_ACCESS_DENIED;
1026         }
1027
1028         if ( !pdb_copy_sam_account(new_acct, old_acct)
1029                 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1030         {
1031                 TALLOC_FREE(new_acct);
1032                 return NT_STATUS_NO_MEMORY;
1033         }
1034
1035         /* open the database */
1036         if ( !tdbsam_open( tdbsam_filename ) ) {
1037                 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1038                           tdbsam_filename));
1039                 TALLOC_FREE(new_acct);
1040                 return NT_STATUS_ACCESS_DENIED;
1041         }
1042
1043         if (dbwrap_transaction_start(db_sam) != 0) {
1044                 DEBUG(0, ("Could not start transaction\n"));
1045                 TALLOC_FREE(new_acct);
1046                 return NT_STATUS_ACCESS_DENIED;
1047
1048         }
1049
1050         /* add the new account and lock it */
1051         if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1052                 goto cancel;
1053         }
1054
1055         /* Rename the posix user.  Follow the semantics of _samr_create_user()
1056            so that we lower case the posix name but preserve the case in passdb */
1057
1058         fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1059         if (!strlower_m( oldname_lower )) {
1060                 goto cancel;
1061         }
1062
1063         fstrcpy( newname_lower, newname );
1064         if (!strlower_m( newname_lower )) {
1065                 goto cancel;
1066         }
1067
1068         rename_script = talloc_string_sub2(new_acct,
1069                                 rename_script,
1070                                 "%unew",
1071                                 newname_lower,
1072                                 true,
1073                                 false,
1074                                 true);
1075         if (!rename_script) {
1076                 goto cancel;
1077         }
1078         rename_script = talloc_string_sub2(new_acct,
1079                                 rename_script,
1080                                 "%uold",
1081                                 oldname_lower,
1082                                 true,
1083                                 false,
1084                                 true);
1085         if (!rename_script) {
1086                 goto cancel;
1087         }
1088         rename_ret = smbrun(rename_script, NULL, NULL);
1089
1090         DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
1091                                 rename_script, rename_ret));
1092
1093         if (rename_ret != 0) {
1094                 goto cancel;
1095         }
1096
1097         smb_nscd_flush_user_cache();
1098
1099         /* rewrite the rid->username record */
1100
1101         if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1102                 goto cancel;
1103         }
1104
1105         tdb_delete_samacct_only( old_acct );
1106
1107         if (dbwrap_transaction_commit(db_sam) != 0) {
1108                 /*
1109                  * Ok, we're screwed. We've changed the posix account, but
1110                  * could not adapt passdb.tdb. Shall we change the posix
1111                  * account back?
1112                  */
1113                 DEBUG(0, ("transaction_commit failed\n"));
1114                 TALLOC_FREE(new_acct);
1115                 return NT_STATUS_INTERNAL_DB_CORRUPTION;        
1116         }
1117
1118         TALLOC_FREE(new_acct );
1119         return NT_STATUS_OK;
1120
1121  cancel:
1122         if (dbwrap_transaction_cancel(db_sam) != 0) {
1123                 smb_panic("transaction_cancel failed");
1124         }
1125
1126         TALLOC_FREE(new_acct);
1127
1128         return NT_STATUS_ACCESS_DENIED; 
1129 }
1130
1131 static uint32_t tdbsam_capabilities(struct pdb_methods *methods)
1132 {
1133         return PDB_CAP_STORE_RIDS;
1134 }
1135
1136 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32_t *prid)
1137 {
1138         uint32_t rid;
1139         NTSTATUS status;
1140
1141         rid = BASE_RID;         /* Default if not set */
1142
1143         if (!tdbsam_open(tdbsam_filename)) {
1144                 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1145                         tdbsam_filename));
1146                 return false;
1147         }
1148
1149         status = dbwrap_trans_change_uint32_atomic_bystring(
1150                 db_sam, NEXT_RID_STRING, &rid, 1);
1151         if (!NT_STATUS_IS_OK(status)) {
1152                 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1153                         NEXT_RID_STRING, nt_errstr(status)));
1154                 return false;
1155         }
1156
1157         *prid = rid;
1158
1159         return true;
1160 }
1161
1162 struct tdbsam_search_state {
1163         struct pdb_methods *methods;
1164         uint32_t acct_flags;
1165
1166         uint32_t *rids;
1167         uint32_t num_rids;
1168         ssize_t array_size;
1169         uint32_t current;
1170 };
1171
1172 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1173 {
1174         struct tdbsam_search_state *state = talloc_get_type_abort(
1175                 private_data, struct tdbsam_search_state);
1176         size_t prefixlen = strlen(RIDPREFIX);
1177         uint32_t rid;
1178         int error = 0;
1179         TDB_DATA key;
1180
1181         key = dbwrap_record_get_key(rec);
1182
1183         if ((key.dsize < prefixlen)
1184             || (strncmp((char *)key.dptr, RIDPREFIX, prefixlen))) {
1185                 return 0;
1186         }
1187
1188         rid = smb_strtoul((char *)key.dptr+prefixlen,
1189                           NULL,
1190                           16,
1191                           &error,
1192                           SMB_STR_STANDARD);
1193         if (error != 0) {
1194                 return 0;
1195         }
1196
1197         ADD_TO_LARGE_ARRAY(state, uint32_t, rid, &state->rids, &state->num_rids,
1198                            &state->array_size);
1199
1200         return 0;
1201 }
1202
1203 static void tdbsam_search_end(struct pdb_search *search)
1204 {
1205         struct tdbsam_search_state *state = talloc_get_type_abort(
1206                 search->private_data, struct tdbsam_search_state);
1207         TALLOC_FREE(state);
1208 }
1209
1210 static bool tdbsam_search_next_entry(struct pdb_search *search,
1211                                      struct samr_displayentry *entry)
1212 {
1213         struct tdbsam_search_state *state = talloc_get_type_abort(
1214                 search->private_data, struct tdbsam_search_state);
1215         struct samu *user = NULL;
1216         NTSTATUS status;
1217         uint32_t rid;
1218
1219  again:
1220         TALLOC_FREE(user);
1221         user = samu_new(talloc_tos());
1222         if (user == NULL) {
1223                 DEBUG(0, ("samu_new failed\n"));
1224                 return false;
1225         }
1226
1227         if (state->current == state->num_rids) {
1228                 TALLOC_FREE(user);
1229                 return false;
1230         }
1231
1232         rid = state->rids[state->current++];
1233
1234         status = tdbsam_getsampwrid(state->methods, user, rid);
1235
1236         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1237                 /*
1238                  * Someone has deleted that user since we listed the RIDs
1239                  */
1240                 goto again;
1241         }
1242
1243         if (!NT_STATUS_IS_OK(status)) {
1244                 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1245                            nt_errstr(status)));
1246                 TALLOC_FREE(user);
1247                 return false;
1248         }
1249
1250         if ((state->acct_flags != 0) &&
1251             ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1252                 goto again;
1253         }
1254
1255         entry->acct_flags = pdb_get_acct_ctrl(user);
1256         entry->rid = rid;
1257         entry->account_name = talloc_strdup(search, pdb_get_username(user));
1258         entry->fullname = talloc_strdup(search, pdb_get_fullname(user));
1259         entry->description = talloc_strdup(search, pdb_get_acct_desc(user));
1260
1261         TALLOC_FREE(user);
1262
1263         if ((entry->account_name == NULL) || (entry->fullname == NULL)
1264             || (entry->description == NULL)) {
1265                 DEBUG(0, ("talloc_strdup failed\n"));
1266                 return false;
1267         }
1268
1269         return true;
1270 }
1271
1272 static bool tdbsam_search_users(struct pdb_methods *methods,
1273                                 struct pdb_search *search,
1274                                 uint32_t acct_flags)
1275 {
1276         struct tdbsam_search_state *state;
1277
1278         if (!tdbsam_open(tdbsam_filename)) {
1279                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1280                          tdbsam_filename));
1281                 return false;
1282         }
1283
1284         state = talloc_zero(search, struct tdbsam_search_state);
1285         if (state == NULL) {
1286                 DEBUG(0, ("talloc failed\n"));
1287                 return false;
1288         }
1289         state->acct_flags = acct_flags;
1290         state->methods = methods;
1291
1292         dbwrap_traverse_read(db_sam, tdbsam_collect_rids, state, NULL);
1293
1294         search->private_data = state;
1295         search->next_entry = tdbsam_search_next_entry;
1296         search->search_end = tdbsam_search_end;
1297
1298         return true;
1299 }
1300
1301 static bool tdbsam_is_responsible_for_builtin(struct pdb_methods *m)
1302 {
1303         return map_builtin;
1304 }
1305
1306 /*********************************************************************
1307  Initialize the tdb sam backend.  Setup the dispath table of methods,
1308  open the tdb, etc...
1309 *********************************************************************/
1310
1311 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1312 {
1313         NTSTATUS nt_status;
1314         char *tdbfile = NULL;
1315         const char *pfile = location;
1316
1317         if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1318                 return nt_status;
1319         }
1320
1321         (*pdb_method)->name = "tdbsam";
1322
1323         (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1324         (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1325         (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1326         (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1327         (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1328         (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1329         (*pdb_method)->search_users = tdbsam_search_users;
1330
1331         (*pdb_method)->capabilities = tdbsam_capabilities;
1332         (*pdb_method)->new_rid = tdbsam_new_rid;
1333
1334         (*pdb_method)->is_responsible_for_builtin =
1335                                         tdbsam_is_responsible_for_builtin;
1336         map_builtin = lp_parm_bool(-1, "tdbsam", "map builtin", true);
1337
1338         /* save the path for later */
1339
1340         if (!location) {
1341                 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1342                              PASSDB_FILE_NAME) < 0) {
1343                         return NT_STATUS_NO_MEMORY;
1344                 }
1345                 pfile = tdbfile;
1346         }
1347         tdbsam_filename = SMB_STRDUP(pfile);
1348         if (!tdbsam_filename) {
1349                 return NT_STATUS_NO_MEMORY;
1350         }
1351         SAFE_FREE(tdbfile);
1352
1353         /* no private data */
1354
1355         (*pdb_method)->private_data      = NULL;
1356         (*pdb_method)->free_private_data = NULL;
1357
1358         return NT_STATUS_OK;
1359 }
1360
1361 NTSTATUS pdb_tdbsam_init(TALLOC_CTX *ctx)
1362 {
1363         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
1364 }