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