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