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