s3:passdb/pdb_tdb add parameter to control handling of BUILTIN
[vlendec/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 *)value.dptr,
105                                             value.dsize);
106                 break;
107         case 1:
108                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V1,
109                                             (uint8 *)value.dptr,
110                                             value.dsize);
111                 break;
112         case 2:
113                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V2,
114                                             (uint8 *)value.dptr,
115                                             value.dsize);
116                 break;
117         case 3:
118                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V3,
119                                             (uint8 *)value.dptr,
120                                             value.dsize);
121                 break;
122         case 4:
123                 ret = init_samu_from_buffer(user, SAMU_BUFFER_V4,
124                                             (uint8 *)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);
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);
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 rid;
330         bool ok = false;
331         NTSTATUS status;
332
333         status = dbwrap_fetch_uint32_bystring(db, NEXT_RID_STRING, &rid);
334         if (NT_STATUS_IS_OK(status)) {
335                 return true;
336         }
337
338         tdb = tdb_open_log(state_path("winbindd_idmap.tdb"), 0,
339                            TDB_DEFAULT, O_RDONLY, 0644);
340
341         if (tdb) {
342                 ok = tdb_fetch_uint32(tdb, "RID_COUNTER", &rid);
343                 if (!ok) {
344                         rid = BASE_RID;
345                 }
346                 tdb_close(tdb);
347         } else {
348                 rid = BASE_RID;
349         }
350
351         status = dbwrap_store_uint32_bystring(db, NEXT_RID_STRING, rid);
352         if (!NT_STATUS_IS_OK(status)) {
353                 return false;
354         }
355
356         return true;
357 }
358
359 static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from)
360 {
361         struct tdbsam_convert_state state;
362         struct db_context *db = NULL;
363         NTSTATUS status;
364
365         /* We only need the update backup for local db's. */
366         if (db_is_local(name) && !tdbsam_convert_backup(name, pp_db)) {
367                 DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name));
368                 return false;
369         }
370
371         db = *pp_db;
372         state.from = from;
373         state.success = true;
374
375         if (dbwrap_transaction_start(db) != 0) {
376                 DEBUG(0, ("tdbsam_convert: Could not start transaction\n"));
377                 return false;
378         }
379
380         if (!tdbsam_upgrade_next_rid(db)) {
381                 DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n"));
382                 goto cancel;
383         }
384
385         status = dbwrap_traverse(db, tdbsam_convert_one, &state, NULL);
386         if (!NT_STATUS_IS_OK(status)) {
387                 DEBUG(0, ("tdbsam_convert: traverse failed\n"));
388                 goto cancel;
389         }
390
391         if (!state.success) {
392                 DEBUG(0, ("tdbsam_convert: Converting records failed\n"));
393                 goto cancel;
394         }
395
396         status = dbwrap_store_int32_bystring(db, TDBSAM_VERSION_STRING,
397                                              TDBSAM_VERSION);
398         if (!NT_STATUS_IS_OK(status)) {
399                 DEBUG(0, ("tdbsam_convert: Could not store tdbsam version: "
400                           "%s\n", nt_errstr(status)));
401                 goto cancel;
402         }
403
404         status = dbwrap_store_int32_bystring(db, TDBSAM_MINOR_VERSION_STRING,
405                                              TDBSAM_MINOR_VERSION);
406         if (!NT_STATUS_IS_OK(status)) {
407                 DEBUG(0, ("tdbsam_convert: Could not store tdbsam minor "
408                           "version: %s\n", nt_errstr(status)));
409                 goto cancel;
410         }
411
412         if (dbwrap_transaction_commit(db) != 0) {
413                 DEBUG(0, ("tdbsam_convert: Could not commit transaction\n"));
414                 return false;
415         }
416
417         return true;
418
419  cancel:
420         if (dbwrap_transaction_cancel(db) != 0) {
421                 smb_panic("tdbsam_convert: transaction_cancel failed");
422         }
423
424         return false;
425 }
426
427 /*********************************************************************
428  Open the tdbsam file based on the absolute path specified.
429  Uses a reference count to allow multiple open calls.
430 *********************************************************************/
431
432 static bool tdbsam_open( const char *name )
433 {
434         int32   version;
435         int32   minor_version;
436         NTSTATUS status;
437
438         /* check if we are already open */
439
440         if ( db_sam ) {
441                 return true;
442         }
443
444         /* Try to open tdb passwd.  Create a new one if necessary */
445
446         db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600,
447                          DBWRAP_LOCK_ORDER_1);
448         if (db_sam == NULL) {
449                 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd "
450                           "[%s]\n", name));
451                 return false;
452         }
453
454         /* Check the version */
455         status = dbwrap_fetch_int32_bystring(db_sam, TDBSAM_VERSION_STRING,
456                                              &version);
457         if (!NT_STATUS_IS_OK(status)) {
458                 version = 0;    /* Version not found, assume version 0 */
459         }
460
461         /* Get the minor version */
462         status = dbwrap_fetch_int32_bystring(
463                 db_sam, TDBSAM_MINOR_VERSION_STRING, &minor_version);
464         if (!NT_STATUS_IS_OK(status)) {
465                 minor_version = 0; /* Minor version not found, assume 0 */
466         }
467
468         /* Compare the version */
469         if (version > TDBSAM_VERSION) {
470                 /* Version more recent than the latest known */
471                 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
472                 TALLOC_FREE(db_sam);
473                 return false;
474         }
475
476         if ( version < TDBSAM_VERSION ||
477                         (version == TDBSAM_VERSION &&
478                          minor_version < TDBSAM_MINOR_VERSION) ) {
479                 /*
480                  * Ok - we think we're going to have to convert.
481                  * Due to the backup process we now must do to
482                  * upgrade we have to get a mutex and re-check
483                  * the version. Someone else may have upgraded
484                  * whilst we were checking.
485                  */
486
487                 struct named_mutex *mtx = grab_named_mutex(NULL,
488                                                 "tdbsam_upgrade_mutex",
489                                                 600);
490
491                 if (!mtx) {
492                         DEBUG(0, ("tdbsam_open: failed to grab mutex.\n"));
493                         TALLOC_FREE(db_sam);
494                         return false;
495                 }
496
497                 /* Re-check the version */
498                 status = dbwrap_fetch_int32_bystring(
499                         db_sam, TDBSAM_VERSION_STRING, &version);
500                 if (!NT_STATUS_IS_OK(status)) {
501                         version = 0;    /* Version not found, assume version 0 */
502                 }
503
504                 /* Re-check the minor version */
505                 status = dbwrap_fetch_int32_bystring(
506                         db_sam, TDBSAM_MINOR_VERSION_STRING, &minor_version);
507                 if (!NT_STATUS_IS_OK(status)) {
508                         minor_version = 0; /* Minor version not found, assume 0 */
509                 }
510
511                 /* Compare the version */
512                 if (version > TDBSAM_VERSION) {
513                         /* Version more recent than the latest known */
514                         DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
515                         TALLOC_FREE(db_sam);
516                         TALLOC_FREE(mtx);
517                         return false;
518                 }
519
520                 if ( version < TDBSAM_VERSION ||
521                                 (version == TDBSAM_VERSION &&
522                                  minor_version < TDBSAM_MINOR_VERSION) ) {
523                         /*
524                          * Note that minor versions we read that are greater
525                          * than the current minor version we have hard coded
526                          * are assumed to be compatible if they have the same
527                          * major version. That allows previous versions of the
528                          * passdb code that don't know about minor versions to
529                          * still use this database. JRA.
530                          */
531
532                         DEBUG(1, ("tdbsam_open: Converting version %d.%d database to "
533                                   "version %d.%d.\n",
534                                         version,
535                                         minor_version,
536                                         TDBSAM_VERSION,
537                                         TDBSAM_MINOR_VERSION));
538
539                         if ( !tdbsam_convert(&db_sam, name, version) ) {
540                                 DEBUG(0, ("tdbsam_open: Error when trying to convert "
541                                           "tdbsam [%s]\n",name));
542                                 TALLOC_FREE(db_sam);
543                                 TALLOC_FREE(mtx);
544                                 return false;
545                         }
546
547                         DEBUG(3, ("TDBSAM converted successfully.\n"));
548                 }
549                 TALLOC_FREE(mtx);
550         }
551
552         DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
553
554         return true;
555 }
556
557 /******************************************************************
558  Lookup a name in the SAM TDB
559 ******************************************************************/
560
561 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods,
562                                     struct samu *user, const char *sname)
563 {
564         TDB_DATA        data;
565         fstring         keystr;
566         fstring         name;
567         NTSTATUS status;
568
569         if ( !user ) {
570                 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
571                 return NT_STATUS_NO_MEMORY;
572         }
573
574         /* Data is stored in all lower-case */
575         fstrcpy(name, sname);
576         if (!strlower_m(name)) {
577                 return NT_STATUS_INVALID_PARAMETER;
578         }
579
580         /* set search key */
581         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
582
583         /* open the database */
584
585         if ( !tdbsam_open( tdbsam_filename ) ) {
586                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
587                 return NT_STATUS_ACCESS_DENIED;
588         }
589
590         /* get the record */
591
592         status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
593         if (!NT_STATUS_IS_OK(status)) {
594                 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
595                 DEBUGADD(5, (" Key: %s\n", keystr));
596                 return NT_STATUS_NO_SUCH_USER;
597         }
598
599         /* unpack the buffer */
600
601         if (!init_samu_from_buffer(user, SAMU_BUFFER_LATEST, data.dptr, data.dsize)) {
602                 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
603                 SAFE_FREE(data.dptr);
604                 return NT_STATUS_NO_MEMORY;
605         }
606
607         /* success */
608
609         TALLOC_FREE(data.dptr);
610
611         return NT_STATUS_OK;
612 }
613
614 /***************************************************************************
615  Search by rid
616  **************************************************************************/
617
618 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods,
619                                     struct samu *user, uint32 rid)
620 {
621         NTSTATUS                nt_status = NT_STATUS_UNSUCCESSFUL;
622         TDB_DATA                data;
623         fstring                 keystr;
624         fstring                 name;
625
626         if ( !user ) {
627                 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
628                 return nt_status;
629         }
630
631         /* set search key */
632
633         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
634
635         /* open the database */
636
637         if ( !tdbsam_open( tdbsam_filename ) ) {
638                 DEBUG(0,("tdbsam_getsampwrid: failed to open %s!\n", tdbsam_filename));
639                 return NT_STATUS_ACCESS_DENIED;
640         }
641
642         /* get the record */
643
644         nt_status = dbwrap_fetch_bystring(db_sam, talloc_tos(), keystr, &data);
645         if (!NT_STATUS_IS_OK(nt_status)) {
646                 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
647                 return nt_status;
648         }
649
650         fstrcpy(name, (const char *)data.dptr);
651         TALLOC_FREE(data.dptr);
652
653         return tdbsam_getsampwnam (my_methods, user, name);
654 }
655
656 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods,
657                                    struct samu * user, const struct dom_sid *sid)
658 {
659         uint32 rid;
660
661         if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
662                 return NT_STATUS_UNSUCCESSFUL;
663
664         return tdbsam_getsampwrid(my_methods, user, rid);
665 }
666
667 static bool tdb_delete_samacct_only( struct samu *sam_pass )
668 {
669         fstring         keystr;
670         fstring         name;
671         NTSTATUS status;
672
673         fstrcpy(name, pdb_get_username(sam_pass));
674         if (!strlower_m(name)) {
675                 return false;
676         }
677
678         /* set the search key */
679
680         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
681
682         /* it's outaa here!  8^) */
683         if ( !tdbsam_open( tdbsam_filename ) ) {
684                 DEBUG(0,("tdb_delete_samacct_only: failed to open %s!\n",
685                          tdbsam_filename));
686                 return false;
687         }
688
689         status = dbwrap_delete_bystring(db_sam, keystr);
690         if (!NT_STATUS_IS_OK(status)) {
691                 DEBUG(5, ("Error deleting entry from tdb passwd "
692                           "database: %s!\n", nt_errstr(status)));
693                 return false;
694         }
695
696         return true;
697 }
698
699 /***************************************************************************
700  Delete a struct samu records for the username and RID key
701 ****************************************************************************/
702
703 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
704                                           struct samu *sam_pass)
705 {
706         NTSTATUS        nt_status = NT_STATUS_UNSUCCESSFUL;
707         fstring         keystr;
708         uint32          rid;
709         fstring         name;
710
711         /* open the database */
712
713         if ( !tdbsam_open( tdbsam_filename ) ) {
714                 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
715                          tdbsam_filename));
716                 return NT_STATUS_ACCESS_DENIED;
717         }
718
719         fstrcpy(name, pdb_get_username(sam_pass));
720         if (!strlower_m(name)) {
721                 return NT_STATUS_INVALID_PARAMETER;
722         }
723
724         /* set the search key */
725
726         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
727
728         rid = pdb_get_user_rid(sam_pass);
729
730         /* it's outaa here!  8^) */
731
732         if (dbwrap_transaction_start(db_sam) != 0) {
733                 DEBUG(0, ("Could not start transaction\n"));
734                 return NT_STATUS_UNSUCCESSFUL;
735         }
736
737         nt_status = dbwrap_delete_bystring(db_sam, keystr);
738         if (!NT_STATUS_IS_OK(nt_status)) {
739                 DEBUG(5, ("Error deleting entry from tdb passwd "
740                           "database: %s!\n", nt_errstr(nt_status)));
741                 goto cancel;
742         }
743
744         /* set the search key */
745
746         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
747
748         /* it's outaa here!  8^) */
749
750         nt_status = dbwrap_delete_bystring(db_sam, keystr);
751         if (!NT_STATUS_IS_OK(nt_status)) {
752                 DEBUG(5, ("Error deleting entry from tdb rid "
753                           "database: %s!\n", nt_errstr(nt_status)));
754                 goto cancel;
755         }
756
757         if (dbwrap_transaction_commit(db_sam) != 0) {
758                 DEBUG(0, ("Could not commit transaction\n"));
759                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
760         }
761
762         return NT_STATUS_OK;
763
764  cancel:
765         if (dbwrap_transaction_cancel(db_sam) != 0) {
766                 smb_panic("transaction_cancel failed");
767         }
768
769         return nt_status;
770 }
771
772
773 /***************************************************************************
774  Update the TDB SAM account record only
775  Assumes that the tdbsam is already open 
776 ****************************************************************************/
777 static bool tdb_update_samacct_only( struct samu* newpwd, int flag )
778 {
779         TDB_DATA        data;
780         uint8           *buf = NULL;
781         fstring         keystr;
782         fstring         name;
783         bool            ret = false;
784         NTSTATUS status;
785
786         /* copy the struct samu struct into a BYTE buffer for storage */
787
788         if ( (data.dsize=init_buffer_from_samu(&buf, newpwd, False)) == -1 ) {
789                 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
790                 goto done;
791         }
792         data.dptr = buf;
793
794         fstrcpy(name, pdb_get_username(newpwd));
795         if (!strlower_m(name)) {
796                 goto done;
797         }
798
799         DEBUG(5, ("Storing %saccount %s with RID %d\n",
800                   flag == TDB_INSERT ? "(new) " : "", name,
801                   pdb_get_user_rid(newpwd)));
802
803         /* setup the USER index key */
804         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
805
806         /* add the account */
807
808         status = dbwrap_store_bystring(db_sam, keystr, data, flag);
809         if (!NT_STATUS_IS_OK(status)) {
810                 DEBUG(0, ("Unable to modify passwd TDB: %s!",
811                           nt_errstr(status)));
812                 goto done;
813         }
814
815         ret = true;
816
817 done:
818         /* cleanup */
819         SAFE_FREE(buf);
820         return ret;
821 }
822
823 /***************************************************************************
824  Update the TDB SAM RID record only
825  Assumes that the tdbsam is already open
826 ****************************************************************************/
827 static bool tdb_update_ridrec_only( struct samu* newpwd, int flag )
828 {
829         TDB_DATA        data;
830         fstring         keystr;
831         fstring         name;
832         NTSTATUS status;
833
834         fstrcpy(name, pdb_get_username(newpwd));
835         if (!strlower_m(name)) {
836                 return false;
837         }
838
839         /* setup RID data */
840         data = string_term_tdb_data(name);
841
842         /* setup the RID index key */
843         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
844                  pdb_get_user_rid(newpwd));
845
846         /* add the reference */
847         status = dbwrap_store_bystring(db_sam, keystr, data, flag);
848         if (!NT_STATUS_IS_OK(status)) {
849                 DEBUG(0, ("Unable to modify TDB passwd: %s!\n",
850                           nt_errstr(status)));
851                 return false;
852         }
853
854         return true;
855
856 }
857
858 /***************************************************************************
859  Update the TDB SAM
860 ****************************************************************************/
861
862 static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
863                            int flag)
864 {
865         uint32_t oldrid;
866         uint32_t newrid;
867
868         if (!(newrid = pdb_get_user_rid(newpwd))) {
869                 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n",
870                          pdb_get_username(newpwd)));
871                 return False;
872         }
873
874         oldrid = newrid;
875
876         /* open the database */
877
878         if ( !tdbsam_open( tdbsam_filename ) ) {
879                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
880                 return False;
881         }
882
883         if (dbwrap_transaction_start(db_sam) != 0) {
884                 DEBUG(0, ("Could not start transaction\n"));
885                 return false;
886         }
887
888         /* If we are updating, we may be changing this users RID. Retrieve the old RID
889            so we can check. */
890
891         if (flag == TDB_MODIFY) {
892                 struct samu *account = samu_new(talloc_tos());
893                 if (account == NULL) {
894                         DEBUG(0,("tdb_update_sam: samu_new() failed\n"));
895                         goto cancel;
896                 }
897                 if (!NT_STATUS_IS_OK(tdbsam_getsampwnam(my_methods, account, pdb_get_username(newpwd)))) {
898                         DEBUG(0,("tdb_update_sam: tdbsam_getsampwnam() for %s failed\n",
899                                 pdb_get_username(newpwd)));
900                         TALLOC_FREE(account);
901                         goto cancel;
902                 }
903                 if (!(oldrid = pdb_get_user_rid(account))) {
904                         DEBUG(0,("tdb_update_sam: pdb_get_user_rid() failed\n"));
905                         TALLOC_FREE(account);
906                         goto cancel;
907                 }
908                 TALLOC_FREE(account);
909         }
910
911         /* Update the new samu entry. */
912         if (!tdb_update_samacct_only(newpwd, flag)) {
913                 goto cancel;
914         }
915
916         /* Now take care of the case where the RID changed. We need
917          * to delete the old RID key and add the new. */
918
919         if (flag == TDB_MODIFY && newrid != oldrid) { 
920                 fstring keystr;
921
922                 /* Delete old RID key */
923                 DEBUG(10, ("tdb_update_sam: Deleting key for RID %u\n", oldrid));
924                 slprintf(keystr, sizeof(keystr) - 1, "%s%.8x", RIDPREFIX, oldrid);
925                 if (!NT_STATUS_IS_OK(dbwrap_delete_bystring(db_sam, keystr))) {
926                         DEBUG(0, ("tdb_update_sam: Can't delete %s\n", keystr));
927                         goto cancel;
928                 }
929                 /* Insert new RID key */
930                 DEBUG(10, ("tdb_update_sam: Inserting key for RID %u\n", newrid));
931                 if (!tdb_update_ridrec_only(newpwd, TDB_INSERT)) {
932                         goto cancel;
933                 }
934         } else {
935                 DEBUG(10, ("tdb_update_sam: %s key for RID %u\n",
936                         flag == TDB_MODIFY ? "Updating" : "Inserting", newrid));
937                 if (!tdb_update_ridrec_only(newpwd, flag)) {
938                         goto cancel;
939                 }
940         }
941
942         if (dbwrap_transaction_commit(db_sam) != 0) {
943                 DEBUG(0, ("Could not commit transaction\n"));
944                 return false;
945         }
946
947         return true;
948
949  cancel:
950         if (dbwrap_transaction_cancel(db_sam) != 0) {
951                 smb_panic("transaction_cancel failed");
952         }
953         return false;
954 }
955
956 /***************************************************************************
957  Modifies an existing struct samu
958 ****************************************************************************/
959
960 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
961 {
962         if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
963                 return NT_STATUS_UNSUCCESSFUL;
964         
965         return NT_STATUS_OK;
966 }
967
968 /***************************************************************************
969  Adds an existing struct samu
970 ****************************************************************************/
971
972 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
973 {
974         if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
975                 return NT_STATUS_UNSUCCESSFUL;
976                 
977         return NT_STATUS_OK;
978 }
979
980 /***************************************************************************
981  Renames a struct samu
982  - check for the posix user/rename user script
983  - Add and lock the new user record
984  - rename the posix user
985  - rewrite the rid->username record
986  - delete the old user
987  - unlock the new user record
988 ***************************************************************************/
989 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
990                                           struct samu *old_acct,
991                                           const char *newname)
992 {
993         struct samu      *new_acct = NULL;
994         char *rename_script = NULL;
995         int              rename_ret;
996         fstring          oldname_lower;
997         fstring          newname_lower;
998
999         /* can't do anything without an external script */
1000
1001         if ( !(new_acct = samu_new( talloc_tos() )) ) {
1002                 return NT_STATUS_NO_MEMORY;
1003         }
1004
1005         rename_script = lp_renameuser_script(new_acct);
1006         if (!rename_script) {
1007                 TALLOC_FREE(new_acct);
1008                 return NT_STATUS_NO_MEMORY;
1009         }
1010         if (!*rename_script) {
1011                 TALLOC_FREE(new_acct);
1012                 return NT_STATUS_ACCESS_DENIED;
1013         }
1014
1015         if ( !pdb_copy_sam_account(new_acct, old_acct)
1016                 || !pdb_set_username(new_acct, newname, PDB_CHANGED))
1017         {
1018                 TALLOC_FREE(new_acct);
1019                 return NT_STATUS_NO_MEMORY;
1020         }
1021
1022         /* open the database */
1023         if ( !tdbsam_open( tdbsam_filename ) ) {
1024                 DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
1025                           tdbsam_filename));
1026                 TALLOC_FREE(new_acct);
1027                 return NT_STATUS_ACCESS_DENIED;
1028         }
1029
1030         if (dbwrap_transaction_start(db_sam) != 0) {
1031                 DEBUG(0, ("Could not start transaction\n"));
1032                 TALLOC_FREE(new_acct);
1033                 return NT_STATUS_ACCESS_DENIED;
1034
1035         }
1036
1037         /* add the new account and lock it */
1038         if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
1039                 goto cancel;
1040         }
1041
1042         /* Rename the posix user.  Follow the semantics of _samr_create_user()
1043            so that we lower case the posix name but preserve the case in passdb */
1044
1045         fstrcpy( oldname_lower, pdb_get_username(old_acct) );
1046         if (!strlower_m( oldname_lower )) {
1047                 goto cancel;
1048         }
1049
1050         fstrcpy( newname_lower, newname );
1051         if (!strlower_m( newname_lower )) {
1052                 goto cancel;
1053         }
1054
1055         rename_script = talloc_string_sub2(new_acct,
1056                                 rename_script,
1057                                 "%unew",
1058                                 newname_lower,
1059                                 true,
1060                                 false,
1061                                 true);
1062         if (!rename_script) {
1063                 goto cancel;
1064         }
1065         rename_script = talloc_string_sub2(new_acct,
1066                                 rename_script,
1067                                 "%uold",
1068                                 oldname_lower,
1069                                 true,
1070                                 false,
1071                                 true);
1072         if (!rename_script) {
1073                 goto cancel;
1074         }
1075         rename_ret = smbrun(rename_script, NULL);
1076
1077         DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
1078                                 rename_script, rename_ret));
1079
1080         if (rename_ret != 0) {
1081                 goto cancel;
1082         }
1083
1084         smb_nscd_flush_user_cache();
1085
1086         /* rewrite the rid->username record */
1087
1088         if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
1089                 goto cancel;
1090         }
1091
1092         tdb_delete_samacct_only( old_acct );
1093
1094         if (dbwrap_transaction_commit(db_sam) != 0) {
1095                 /*
1096                  * Ok, we're screwed. We've changed the posix account, but
1097                  * could not adapt passdb.tdb. Shall we change the posix
1098                  * account back?
1099                  */
1100                 DEBUG(0, ("transaction_commit failed\n"));
1101                 TALLOC_FREE(new_acct);
1102                 return NT_STATUS_INTERNAL_DB_CORRUPTION;        
1103         }
1104
1105         TALLOC_FREE(new_acct );
1106         return NT_STATUS_OK;
1107
1108  cancel:
1109         if (dbwrap_transaction_cancel(db_sam) != 0) {
1110                 smb_panic("transaction_cancel failed");
1111         }
1112
1113         TALLOC_FREE(new_acct);
1114
1115         return NT_STATUS_ACCESS_DENIED; 
1116 }
1117
1118 static uint32_t tdbsam_capabilities(struct pdb_methods *methods)
1119 {
1120         return PDB_CAP_STORE_RIDS;
1121 }
1122
1123 static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
1124 {
1125         uint32 rid;
1126         NTSTATUS status;
1127
1128         rid = BASE_RID;         /* Default if not set */
1129
1130         if (!tdbsam_open(tdbsam_filename)) {
1131                 DEBUG(0,("tdbsam_new_rid: failed to open %s!\n",
1132                         tdbsam_filename));
1133                 return false;
1134         }
1135
1136         status = dbwrap_trans_change_uint32_atomic_bystring(
1137                 db_sam, NEXT_RID_STRING, &rid, 1);
1138         if (!NT_STATUS_IS_OK(status)) {
1139                 DEBUG(3, ("tdbsam_new_rid: Failed to increase %s: %s\n",
1140                         NEXT_RID_STRING, nt_errstr(status)));
1141                 return false;
1142         }
1143
1144         *prid = rid;
1145
1146         return true;
1147 }
1148
1149 struct tdbsam_search_state {
1150         struct pdb_methods *methods;
1151         uint32_t acct_flags;
1152
1153         uint32_t *rids;
1154         uint32_t num_rids;
1155         ssize_t array_size;
1156         uint32_t current;
1157 };
1158
1159 static int tdbsam_collect_rids(struct db_record *rec, void *private_data)
1160 {
1161         struct tdbsam_search_state *state = talloc_get_type_abort(
1162                 private_data, struct tdbsam_search_state);
1163         size_t prefixlen = strlen(RIDPREFIX);
1164         uint32 rid;
1165         TDB_DATA key;
1166
1167         key = dbwrap_record_get_key(rec);
1168
1169         if ((key.dsize < prefixlen)
1170             || (strncmp((char *)key.dptr, RIDPREFIX, prefixlen))) {
1171                 return 0;
1172         }
1173
1174         rid = strtoul((char *)key.dptr+prefixlen, NULL, 16);
1175
1176         ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
1177                            &state->array_size);
1178
1179         return 0;
1180 }
1181
1182 static void tdbsam_search_end(struct pdb_search *search)
1183 {
1184         struct tdbsam_search_state *state = talloc_get_type_abort(
1185                 search->private_data, struct tdbsam_search_state);
1186         TALLOC_FREE(state);
1187 }
1188
1189 static bool tdbsam_search_next_entry(struct pdb_search *search,
1190                                      struct samr_displayentry *entry)
1191 {
1192         struct tdbsam_search_state *state = talloc_get_type_abort(
1193                 search->private_data, struct tdbsam_search_state);
1194         struct samu *user = NULL;
1195         NTSTATUS status;
1196         uint32_t rid;
1197
1198  again:
1199         TALLOC_FREE(user);
1200         user = samu_new(talloc_tos());
1201         if (user == NULL) {
1202                 DEBUG(0, ("samu_new failed\n"));
1203                 return false;
1204         }
1205
1206         if (state->current == state->num_rids) {
1207                 TALLOC_FREE(user);
1208                 return false;
1209         }
1210
1211         rid = state->rids[state->current++];
1212
1213         status = tdbsam_getsampwrid(state->methods, user, rid);
1214
1215         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1216                 /*
1217                  * Someone has deleted that user since we listed the RIDs
1218                  */
1219                 goto again;
1220         }
1221
1222         if (!NT_STATUS_IS_OK(status)) {
1223                 DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
1224                            nt_errstr(status)));
1225                 TALLOC_FREE(user);
1226                 return false;
1227         }
1228
1229         if ((state->acct_flags != 0) &&
1230             ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
1231                 goto again;
1232         }
1233
1234         entry->acct_flags = pdb_get_acct_ctrl(user);
1235         entry->rid = rid;
1236         entry->account_name = talloc_strdup(search, pdb_get_username(user));
1237         entry->fullname = talloc_strdup(search, pdb_get_fullname(user));
1238         entry->description = talloc_strdup(search, pdb_get_acct_desc(user));
1239
1240         TALLOC_FREE(user);
1241
1242         if ((entry->account_name == NULL) || (entry->fullname == NULL)
1243             || (entry->description == NULL)) {
1244                 DEBUG(0, ("talloc_strdup failed\n"));
1245                 return false;
1246         }
1247
1248         return true;
1249 }
1250
1251 static bool tdbsam_search_users(struct pdb_methods *methods,
1252                                 struct pdb_search *search,
1253                                 uint32 acct_flags)
1254 {
1255         struct tdbsam_search_state *state;
1256
1257         if (!tdbsam_open(tdbsam_filename)) {
1258                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
1259                          tdbsam_filename));
1260                 return false;
1261         }
1262
1263         state = talloc_zero(search, struct tdbsam_search_state);
1264         if (state == NULL) {
1265                 DEBUG(0, ("talloc failed\n"));
1266                 return false;
1267         }
1268         state->acct_flags = acct_flags;
1269         state->methods = methods;
1270
1271         dbwrap_traverse_read(db_sam, tdbsam_collect_rids, state, NULL);
1272
1273         search->private_data = state;
1274         search->next_entry = tdbsam_search_next_entry;
1275         search->search_end = tdbsam_search_end;
1276
1277         return true;
1278 }
1279
1280 static bool tdbsam_is_responsible_for_builtin(struct pdb_methods *m)
1281 {
1282         return map_builtin;
1283 }
1284
1285 /*********************************************************************
1286  Initialize the tdb sam backend.  Setup the dispath table of methods,
1287  open the tdb, etc...
1288 *********************************************************************/
1289
1290 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
1291 {
1292         NTSTATUS nt_status;
1293         char *tdbfile = NULL;
1294         const char *pfile = location;
1295
1296         if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
1297                 return nt_status;
1298         }
1299
1300         (*pdb_method)->name = "tdbsam";
1301
1302         (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
1303         (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
1304         (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
1305         (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
1306         (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
1307         (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
1308         (*pdb_method)->search_users = tdbsam_search_users;
1309
1310         (*pdb_method)->capabilities = tdbsam_capabilities;
1311         (*pdb_method)->new_rid = tdbsam_new_rid;
1312
1313         (*pdb_method)->is_responsible_for_builtin =
1314                                         tdbsam_is_responsible_for_builtin;
1315         map_builtin = lp_parm_bool(-1, "tdbsam", "map builtin", true);
1316
1317         /* save the path for later */
1318
1319         if (!location) {
1320                 if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
1321                              PASSDB_FILE_NAME) < 0) {
1322                         return NT_STATUS_NO_MEMORY;
1323                 }
1324                 pfile = tdbfile;
1325         }
1326         tdbsam_filename = SMB_STRDUP(pfile);
1327         if (!tdbsam_filename) {
1328                 return NT_STATUS_NO_MEMORY;
1329         }
1330         SAFE_FREE(tdbfile);
1331
1332         /* no private data */
1333
1334         (*pdb_method)->private_data      = NULL;
1335         (*pdb_method)->free_private_data = NULL;
1336
1337         return NT_STATUS_OK;
1338 }
1339
1340 NTSTATUS pdb_tdbsam_init(void)
1341 {
1342         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
1343 }