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