Coverage Report

Created: 2026-02-14 07:07

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