Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/lib/smbconf/smbconf_reg.c
Line
Count
Source
1
/*
2
 *  Unix SMB/CIFS implementation.
3
 *  libsmbconf - Samba configuration library, registry backend
4
 *  Copyright (C) Michael Adam 2008
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 3 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
#include "includes.h"
21
#include "lib/smbconf/smbconf_private.h"
22
#include "registry.h"
23
#include "registry/reg_api.h"
24
#include "registry/reg_backend_db.h"
25
#include "registry/reg_util_token.h"
26
#include "registry/reg_api_util.h"
27
#include "registry/reg_init_smbconf.h"
28
#include "lib/smbconf/smbconf_init.h"
29
#include "lib/smbconf/smbconf_reg.h"
30
#include "../libcli/registry/util_reg.h"
31
32
0
#define INCLUDES_VALNAME "includes"
33
34
struct reg_private_data {
35
  struct registry_key *base_key;
36
  bool open;    /* did _we_ open the registry? */
37
};
38
39
/**********************************************************************
40
 *
41
 * helper functions
42
 *
43
 **********************************************************************/
44
45
/**
46
 * a convenience helper to cast the private data structure
47
 */
48
static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
49
0
{
50
0
  return (struct reg_private_data *)(ctx->data);
51
0
}
52
53
/**
54
 * Check whether a given parameter name is valid in the
55
 * smbconf registry backend.
56
 */
57
bool smbconf_reg_parameter_is_valid(const char *param_name)
58
0
{
59
  /* hard code the list of forbidden names here for now */
60
0
  const char *forbidden_names[] = {
61
0
    "state directory",
62
0
    "lock directory",
63
0
    "lock dir",
64
0
    "config backend",
65
0
    "include",
66
    /*
67
     * "includes" has a special meaning internally.
68
     * It is currently not necessary to list it here since it is
69
     * not a valid parameter. But for clarity and safety, we keep
70
     * it for now.
71
     */
72
0
    INCLUDES_VALNAME,
73
0
    NULL
74
0
  };
75
0
  const char **forbidden = NULL;
76
77
0
  if (!lp_parameter_is_valid(param_name)) {
78
0
    return false;
79
0
  }
80
81
0
  for (forbidden = forbidden_names; *forbidden != NULL; forbidden++) {
82
0
    if (strwicmp(param_name, *forbidden) == 0) {
83
0
      return false;
84
0
    }
85
0
  }
86
87
0
  return true;
88
0
}
89
90
/**
91
 * Open a subkey of the base key (i.e a service)
92
 */
93
static sbcErr smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
94
             struct smbconf_ctx *ctx,
95
             const char *servicename,
96
             uint32_t desired_access,
97
             struct registry_key **key)
98
0
{
99
0
  WERROR werr;
100
101
0
  if (servicename == NULL) {
102
0
    *key = rpd(ctx)->base_key;
103
0
    return SBC_ERR_OK;
104
0
  }
105
0
  werr = reg_openkey(mem_ctx, rpd(ctx)->base_key, servicename,
106
0
         desired_access, key);
107
0
  if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
108
0
    return SBC_ERR_NO_SUCH_SERVICE;
109
0
  }
110
0
  if (!W_ERROR_IS_OK(werr)) {
111
0
    return SBC_ERR_NOMEM;
112
0
  }
113
114
0
  return SBC_ERR_OK;
115
0
}
116
117
/**
118
 * check if a value exists in a given registry key
119
 */
120
static bool smbconf_value_exists(struct registry_key *key, const char *param)
121
0
{
122
0
  bool ret = false;
123
0
  WERROR werr;
124
0
  TALLOC_CTX *ctx = talloc_stackframe();
125
0
  struct registry_value *value = NULL;
126
127
0
  werr = reg_queryvalue(ctx, key, param, &value);
128
0
  if (W_ERROR_IS_OK(werr)) {
129
0
    ret = true;
130
0
  }
131
132
0
  talloc_free(ctx);
133
0
  return ret;
134
0
}
135
136
/**
137
 * create a subkey of the base key (i.e. a service...)
138
 */
139
static sbcErr smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
140
               struct smbconf_ctx *ctx,
141
               const char * subkeyname,
142
               struct registry_key **newkey)
143
0
{
144
0
  WERROR werr;
145
0
  sbcErr err = SBC_ERR_OK;
146
0
  TALLOC_CTX *create_ctx;
147
0
  enum winreg_CreateAction action = REG_ACTION_NONE;
148
149
  /* create a new talloc ctx for creation. it will hold
150
   * the intermediate parent key (SMBCONF) for creation
151
   * and will be destroyed when leaving this function... */
152
0
  create_ctx = talloc_stackframe();
153
154
0
  werr = reg_createkey(mem_ctx, rpd(ctx)->base_key, subkeyname,
155
0
           REG_KEY_WRITE, newkey, &action);
156
0
  if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
157
0
    DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
158
0
    err = SBC_ERR_FILE_EXISTS;
159
0
  }
160
0
  if (!W_ERROR_IS_OK(werr)) {
161
0
    DEBUG(5, ("Error creating key %s: %s\n",
162
0
       subkeyname, win_errstr(werr)));
163
0
    err = SBC_ERR_UNKNOWN_FAILURE;
164
0
  }
165
166
0
  talloc_free(create_ctx);
167
0
  return err;
168
0
}
169
170
/**
171
 * add a value to a key.
172
 */
173
static sbcErr smbconf_reg_set_value(struct registry_key *key,
174
            const char *valname,
175
            const char *valstr)
176
0
{
177
0
  struct registry_value val;
178
0
  WERROR werr;
179
0
  sbcErr err;
180
0
  char *subkeyname;
181
0
  const char *canon_valname;
182
0
  const char *canon_valstr;
183
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
184
185
0
  if (!lp_parameter_is_valid(valname)) {
186
0
    DEBUG(5, ("Invalid parameter '%s' given.\n", valname));
187
0
    err = SBC_ERR_INVALID_PARAM;
188
0
    goto done;
189
0
  }
190
191
0
  if (!smbconf_reg_parameter_is_valid(valname)) {
192
0
    DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
193
0
        valname));
194
0
    err = SBC_ERR_INVALID_PARAM;
195
0
    goto done;
196
0
  }
197
198
0
  subkeyname = strrchr_m(key->key->name, '\\');
199
0
  if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
200
0
    DEBUG(5, ("Invalid registry key '%s' given as "
201
0
        "smbconf section.\n", key->key->name));
202
0
    err = SBC_ERR_INVALID_PARAM;
203
0
    goto done;
204
0
  }
205
0
  subkeyname++;
206
0
  if (!strequal(subkeyname, GLOBAL_NAME) &&
207
0
      lp_parameter_is_global(valname))
208
0
  {
209
0
    DEBUG(5, ("Global parameter '%s' not allowed in "
210
0
        "service definition ('%s').\n", valname,
211
0
        subkeyname));
212
0
    err = SBC_ERR_INVALID_PARAM;
213
0
    goto done;
214
0
  }
215
216
0
  if (!lp_canonicalize_parameter_with_value(valname, valstr,
217
0
              &canon_valname,
218
0
              &canon_valstr))
219
0
  {
220
    /*
221
     * We already know the parameter name is valid.
222
     * So the value must be invalid.
223
     */
224
0
    DEBUG(5, ("invalid value '%s' given for parameter '%s'\n",
225
0
        valstr, valname));
226
0
    err = SBC_ERR_INVALID_PARAM;
227
0
    goto done;
228
0
  }
229
230
0
  ZERO_STRUCT(val);
231
232
0
  val.type = REG_SZ;
233
0
  if (!push_reg_sz(tmp_ctx, &val.data, canon_valstr)) {
234
0
    err = SBC_ERR_NOMEM;
235
0
    goto done;
236
0
  }
237
238
0
  werr = reg_setvalue(key, canon_valname, &val);
239
0
  if (!W_ERROR_IS_OK(werr)) {
240
0
    DEBUG(5, ("Error adding value '%s' to "
241
0
        "key '%s': %s\n",
242
0
        canon_valname, key->key->name, win_errstr(werr)));
243
0
    err = SBC_ERR_NOMEM;
244
0
    goto done;
245
0
  }
246
247
0
  err = SBC_ERR_OK;
248
0
done:
249
0
  talloc_free(tmp_ctx);
250
0
  return err;
251
0
}
252
253
static sbcErr smbconf_reg_set_multi_sz_value(struct registry_key *key,
254
               const char *valname,
255
               const uint32_t num_strings,
256
               const char **strings)
257
0
{
258
0
  WERROR werr;
259
0
  sbcErr err = SBC_ERR_OK;
260
0
  struct registry_value *value;
261
0
  uint32_t count;
262
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
263
0
  const char **array;
264
265
0
  if (strings == NULL) {
266
0
    err = SBC_ERR_INVALID_PARAM;
267
0
    goto done;
268
0
  }
269
270
0
  array = talloc_zero_array(tmp_ctx, const char *, num_strings + 1);
271
0
  if (array == NULL) {
272
0
    err = SBC_ERR_NOMEM;
273
0
    goto done;
274
0
  }
275
276
0
  value = talloc_zero(tmp_ctx, struct registry_value);
277
0
  if (value == NULL) {
278
0
    err = SBC_ERR_NOMEM;
279
0
    goto done;
280
0
  }
281
282
0
  value->type = REG_MULTI_SZ;
283
284
0
  for (count = 0; count < num_strings; count++) {
285
0
    array[count] = talloc_strdup(value, strings[count]);
286
0
    if (array[count] == NULL) {
287
0
      err = SBC_ERR_NOMEM;
288
0
      goto done;
289
0
    }
290
0
  }
291
292
0
  if (!push_reg_multi_sz(value, &value->data, array)) {
293
0
    err = SBC_ERR_NOMEM;
294
0
    goto done;
295
0
  }
296
297
0
  werr = reg_setvalue(key, valname, value);
298
0
  if (!W_ERROR_IS_OK(werr)) {
299
0
    DEBUG(5, ("Error adding value '%s' to key '%s': %s\n",
300
0
        valname, key->key->name, win_errstr(werr)));
301
0
    err = SBC_ERR_ACCESS_DENIED;
302
0
  }
303
304
0
done:
305
0
  talloc_free(tmp_ctx);
306
0
  return err;
307
0
}
308
309
/**
310
 * format a registry_value into a string.
311
 *
312
 * This is intended to be used for smbconf registry values,
313
 * which are ar stored as REG_SZ values, so the incomplete
314
 * handling should be ok.
315
 */
316
static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
317
             struct registry_value *value)
318
0
{
319
0
  char *result = NULL;
320
321
  /* alternatively, create a new talloc context? */
322
0
  if (mem_ctx == NULL) {
323
0
    return result;
324
0
  }
325
326
0
  switch (value->type) {
327
0
  case REG_DWORD:
328
0
    if (value->data.length >= 4) {
329
0
      uint32_t v = IVAL(value->data.data, 0);
330
0
      result = talloc_asprintf(mem_ctx, "%d", v);
331
0
    }
332
0
    break;
333
0
  case REG_SZ:
334
0
  case REG_EXPAND_SZ: {
335
0
    const char *s;
336
0
    if (!pull_reg_sz(mem_ctx, &value->data, &s)) {
337
0
      break;
338
0
    }
339
0
    result = talloc_strdup(mem_ctx, s);
340
0
    break;
341
0
  }
342
0
  case REG_MULTI_SZ: {
343
0
    uint32_t j;
344
0
    const char **a = NULL;
345
0
    if (!pull_reg_multi_sz(mem_ctx, &value->data, &a)) {
346
0
      break;
347
0
    }
348
0
    for (j = 0; a[j] != NULL; j++) {
349
0
      result = talloc_asprintf(mem_ctx, "%s\"%s\" ",
350
0
             result ? result : "" ,
351
0
             a[j]);
352
0
      if (result == NULL) {
353
0
        break;
354
0
      }
355
0
    }
356
0
    break;
357
0
  }
358
0
  case REG_BINARY:
359
0
    result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
360
0
           (int)value->data.length);
361
0
    break;
362
0
  default:
363
0
    result = talloc_asprintf(mem_ctx, "<unprintable>");
364
0
    break;
365
0
  }
366
0
  return result;
367
0
}
368
369
static sbcErr smbconf_reg_get_includes_internal(TALLOC_CTX *mem_ctx,
370
            struct registry_key *key,
371
            uint32_t *num_includes,
372
            char ***includes)
373
0
{
374
0
  WERROR werr;
375
0
  sbcErr err;
376
0
  uint32_t count;
377
0
  struct registry_value *value = NULL;
378
0
  char **tmp_includes = NULL;
379
0
  const char **array = NULL;
380
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
381
382
0
  if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
383
    /* no includes */
384
0
    *num_includes = 0;
385
0
    *includes = NULL;
386
0
    err = SBC_ERR_OK;
387
0
    goto done;
388
0
  }
389
390
0
  werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value);
391
0
  if (!W_ERROR_IS_OK(werr)) {
392
0
    err = SBC_ERR_ACCESS_DENIED;
393
0
    goto done;
394
0
  }
395
396
0
  if (value->type != REG_MULTI_SZ) {
397
    /* wrong type -- ignore */
398
0
    err = SBC_ERR_OK;
399
0
    goto done;
400
0
  }
401
402
0
  if (!pull_reg_multi_sz(tmp_ctx, &value->data, &array)) {
403
0
    err = SBC_ERR_NOMEM;
404
0
    goto done;
405
0
  }
406
407
0
  for (count = 0; array[count] != NULL; count++) {
408
0
    err = smbconf_add_string_to_array(tmp_ctx,
409
0
          &tmp_includes,
410
0
          count,
411
0
          array[count]);
412
0
    if (!SBC_ERROR_IS_OK(err)) {
413
0
      goto done;
414
0
    }
415
0
  }
416
417
0
  if (count > 0) {
418
0
    *includes = talloc_move(mem_ctx, &tmp_includes);
419
0
    if (*includes == NULL) {
420
0
      err = SBC_ERR_NOMEM;
421
0
      goto done;
422
0
    }
423
0
    *num_includes = count;
424
0
  } else {
425
0
    *num_includes = 0;
426
0
    *includes = NULL;
427
0
  }
428
429
0
  err = SBC_ERR_OK;
430
0
done:
431
0
  talloc_free(tmp_ctx);
432
0
  return err;
433
0
}
434
435
/**
436
 * Get the values of a key as a list of value names
437
 * and a list of value strings (ordered)
438
 */
439
static sbcErr smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
440
             struct registry_key *key,
441
             uint32_t *num_values,
442
             char ***value_names,
443
             char ***value_strings)
444
0
{
445
0
  TALLOC_CTX *tmp_ctx = NULL;
446
0
  WERROR werr;
447
0
  sbcErr err;
448
0
  uint32_t count;
449
0
  struct registry_value *valvalue = NULL;
450
0
  char *valname = NULL;
451
0
  uint32_t tmp_num_values = 0;
452
0
  char **tmp_valnames = NULL;
453
0
  char **tmp_valstrings = NULL;
454
0
  uint32_t num_includes = 0;
455
0
  char **includes = NULL;
456
457
0
  if ((num_values == NULL) || (value_names == NULL) ||
458
0
      (value_strings == NULL))
459
0
  {
460
0
    err = SBC_ERR_INVALID_PARAM;
461
0
    goto done;
462
0
  }
463
464
0
  tmp_ctx = talloc_stackframe();
465
466
0
  for (count = 0;
467
0
       werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue),
468
0
       W_ERROR_IS_OK(werr);
469
0
       count++)
470
0
  {
471
0
    char *valstring;
472
473
0
    if (!smbconf_reg_parameter_is_valid(valname)) {
474
0
      continue;
475
0
    }
476
477
0
    err = smbconf_add_string_to_array(tmp_ctx,
478
0
              &tmp_valnames,
479
0
              tmp_num_values, valname);
480
0
    if (!SBC_ERROR_IS_OK(err)) {
481
0
      goto done;
482
0
    }
483
484
0
    valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
485
0
    err = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
486
0
              tmp_num_values, valstring);
487
0
    if (!SBC_ERROR_IS_OK(err)) {
488
0
      goto done;
489
0
    }
490
0
    tmp_num_values++;
491
0
  }
492
0
  if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
493
0
    err = SBC_ERR_NOMEM;
494
0
    goto done;
495
0
  }
496
497
  /* now add the includes at the end */
498
0
  err = smbconf_reg_get_includes_internal(tmp_ctx, key, &num_includes,
499
0
             &includes);
500
0
  if (!SBC_ERROR_IS_OK(err)) {
501
0
    goto done;
502
0
  }
503
504
0
  for (count = 0; count < num_includes; count++) {
505
0
    err = smbconf_add_string_to_array(tmp_ctx, &tmp_valnames,
506
0
              tmp_num_values, "include");
507
0
    if (!SBC_ERROR_IS_OK(err)) {
508
0
      goto done;
509
0
    }
510
511
0
    err = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
512
0
              tmp_num_values,
513
0
              includes[count]);
514
0
    if (!SBC_ERROR_IS_OK(err)) {
515
0
      goto done;
516
0
    }
517
518
0
    tmp_num_values++;
519
0
  }
520
521
0
  *num_values = tmp_num_values;
522
0
  if (tmp_num_values > 0) {
523
0
    *value_names = talloc_move(mem_ctx, &tmp_valnames);
524
0
    *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
525
0
  } else {
526
0
    *value_names = NULL;
527
0
    *value_strings = NULL;
528
0
  }
529
530
0
done:
531
0
  talloc_free(tmp_ctx);
532
0
  return err;
533
0
}
534
535
/**
536
 * delete all values from a key
537
 */
538
static sbcErr smbconf_reg_delete_values(struct registry_key *key)
539
0
{
540
0
  WERROR werr;
541
0
  sbcErr err;
542
0
  char *valname;
543
0
  struct registry_value *valvalue;
544
0
  uint32_t count;
545
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
546
547
0
  for (count = 0;
548
0
       werr = reg_enumvalue(mem_ctx, key, count, &valname, &valvalue),
549
0
       W_ERROR_IS_OK(werr);
550
0
       count++)
551
0
  {
552
0
    werr = reg_deletevalue(key, valname);
553
0
    if (!W_ERROR_IS_OK(werr)) {
554
0
      err = SBC_ERR_ACCESS_DENIED;
555
0
      goto done;
556
0
    }
557
0
  }
558
0
  if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
559
0
    DEBUG(1, ("smbconf_reg_delete_values: "
560
0
        "Error enumerating values of %s: %s\n",
561
0
        key->key->name,
562
0
        win_errstr(werr)));
563
0
    err = SBC_ERR_ACCESS_DENIED;
564
0
    goto done;
565
0
  }
566
567
0
  err = SBC_ERR_OK;
568
569
0
done:
570
0
  talloc_free(mem_ctx);
571
0
  return err;
572
0
}
573
574
/**********************************************************************
575
 *
576
 * smbconf operations: registry implementations
577
 *
578
 **********************************************************************/
579
580
/**
581
 * initialize the registry smbconf backend
582
 */
583
static sbcErr smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
584
0
{
585
0
  WERROR werr;
586
0
  sbcErr err;
587
0
  struct security_token *token;
588
589
0
  if (path == NULL) {
590
0
    path = KEY_SMBCONF;
591
0
  }
592
0
  ctx->path = talloc_strdup(ctx, path);
593
0
  if (ctx->path == NULL) {
594
0
    err = SBC_ERR_NOMEM;
595
0
    goto done;
596
0
  }
597
598
0
  ctx->data = talloc_zero(ctx, struct reg_private_data);
599
600
0
  werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
601
0
  if (!W_ERROR_IS_OK(werr)) {
602
0
    DEBUG(1, ("Error creating admin token\n"));
603
0
    err = SBC_ERR_UNKNOWN_FAILURE;
604
0
    goto done;
605
0
  }
606
0
  rpd(ctx)->open = false;
607
608
0
  werr = registry_init_smbconf(path);
609
0
  if (!W_ERROR_IS_OK(werr)) {
610
0
    err = SBC_ERR_BADFILE;
611
0
    goto done;
612
0
  }
613
614
0
  err = ctx->ops->open_conf(ctx);
615
0
  if (!SBC_ERROR_IS_OK(err)) {
616
0
    DEBUG(1, ("Error opening the registry.\n"));
617
0
    goto done;
618
0
  }
619
620
0
  werr = reg_open_path(ctx, ctx->path,
621
0
           KEY_ENUMERATE_SUB_KEYS | REG_KEY_WRITE,
622
0
           token, &rpd(ctx)->base_key);
623
0
  if (!W_ERROR_IS_OK(werr)) {
624
0
    err = SBC_ERR_UNKNOWN_FAILURE;
625
0
    goto done;
626
0
  }
627
628
0
done:
629
0
  return err;
630
0
}
631
632
static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
633
0
{
634
0
  return ctx->ops->close_conf(ctx);
635
0
}
636
637
static bool smbconf_reg_requires_messaging(struct smbconf_ctx *ctx)
638
0
{
639
0
  if (lp_clustering() && lp_parm_bool(-1, "ctdb", "registry.tdb", true)) {
640
0
    return true;
641
0
  }
642
643
0
  return false;
644
0
}
645
646
static bool smbconf_reg_is_writeable(struct smbconf_ctx *ctx)
647
0
{
648
  /*
649
   * The backend has write support.
650
   *
651
   *  TODO: add access checks whether the concrete
652
   *  config source is really writeable by the calling user.
653
   */
654
0
  return true;
655
0
}
656
657
static sbcErr smbconf_reg_open(struct smbconf_ctx *ctx)
658
0
{
659
0
  WERROR werr;
660
661
0
  if (rpd(ctx)->open) {
662
0
    return SBC_ERR_OK;
663
0
  }
664
665
0
  werr = regdb_open();
666
0
  if (!W_ERROR_IS_OK(werr)) {
667
0
    return SBC_ERR_BADFILE;
668
0
  }
669
670
0
  rpd(ctx)->open = true;
671
0
  return SBC_ERR_OK;
672
0
}
673
674
static int smbconf_reg_close(struct smbconf_ctx *ctx)
675
0
{
676
0
  int ret;
677
678
0
  if (!rpd(ctx)->open) {
679
0
    return 0;
680
0
  }
681
682
0
  ret = regdb_close();
683
0
  if (ret == 0) {
684
0
    rpd(ctx)->open = false;
685
0
  }
686
0
  return ret;
687
0
}
688
689
/**
690
 * Get the change sequence number of the given service/parameter.
691
 * service and parameter strings may be NULL.
692
 */
693
static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
694
        struct smbconf_csn *csn,
695
        const char *service, const char *param)
696
0
{
697
0
  if (csn == NULL) {
698
0
    return;
699
0
  }
700
701
0
  if (!SBC_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
702
0
    return;
703
0
  }
704
705
0
  csn->csn = (uint64_t)regdb_get_seqnum();
706
0
}
707
708
/**
709
 * Drop the whole configuration (restarting empty) - registry version
710
 */
711
static sbcErr smbconf_reg_drop(struct smbconf_ctx *ctx)
712
0
{
713
0
  char *path, *p;
714
0
  WERROR werr;
715
0
  sbcErr err = SBC_ERR_OK;
716
0
  struct registry_key *parent_key = NULL;
717
0
  struct registry_key *new_key = NULL;
718
0
  TALLOC_CTX* mem_ctx = talloc_stackframe();
719
0
  enum winreg_CreateAction action;
720
0
  struct security_token *token;
721
722
0
  werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
723
0
  if (!W_ERROR_IS_OK(werr)) {
724
0
    DEBUG(1, ("Error creating admin token\n"));
725
0
    err = SBC_ERR_UNKNOWN_FAILURE;
726
0
    goto done;
727
0
  }
728
729
0
  path = talloc_strdup(mem_ctx, ctx->path);
730
0
  if (path == NULL) {
731
0
    err = SBC_ERR_NOMEM;
732
0
    goto done;
733
0
  }
734
0
  p = strrchr(path, '\\');
735
0
  if (p == NULL) {
736
0
    err = SBC_ERR_INVALID_PARAM;
737
0
    goto done;
738
0
  }
739
0
  *p = '\0';
740
0
  werr = reg_open_path(mem_ctx, path, REG_KEY_WRITE, token,
741
0
           &parent_key);
742
0
  if (!W_ERROR_IS_OK(werr)) {
743
0
    err = SBC_ERR_IO_FAILURE;
744
0
    goto done;
745
0
  }
746
747
0
  werr = reg_deletesubkeys_recursive(parent_key, p+1);
748
0
  if (!W_ERROR_IS_OK(werr)) {
749
0
    err = SBC_ERR_IO_FAILURE;
750
0
    goto done;
751
0
  }
752
753
0
  werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
754
0
           &new_key, &action);
755
0
  if (!W_ERROR_IS_OK(werr)) {
756
0
    err = SBC_ERR_IO_FAILURE;
757
0
    goto done;
758
0
  }
759
760
0
done:
761
0
  talloc_free(mem_ctx);
762
0
  return err;
763
0
}
764
765
/**
766
 * get the list of share names defined in the configuration.
767
 * registry version.
768
 */
769
static sbcErr smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
770
            TALLOC_CTX *mem_ctx,
771
            uint32_t *num_shares,
772
            char ***share_names)
773
0
{
774
0
  uint32_t count;
775
0
  uint32_t added_count = 0;
776
0
  TALLOC_CTX *tmp_ctx = NULL;
777
0
  WERROR werr;
778
0
  sbcErr err = SBC_ERR_OK;
779
0
  char *subkey_name = NULL;
780
0
  char **tmp_share_names = NULL;
781
782
0
  if ((num_shares == NULL) || (share_names == NULL)) {
783
0
    return SBC_ERR_INVALID_PARAM;
784
0
  }
785
786
0
  tmp_ctx = talloc_stackframe();
787
788
  /* make sure "global" is always listed first */
789
0
  if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
790
0
    err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
791
0
              added_count, GLOBAL_NAME);
792
0
    if (!SBC_ERROR_IS_OK(err)) {
793
0
      goto done;
794
0
    }
795
0
    added_count++;
796
0
  }
797
798
0
  for (count = 0;
799
0
       werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
800
0
        &subkey_name, NULL),
801
0
       W_ERROR_IS_OK(werr);
802
0
       count++)
803
0
  {
804
0
    if (strequal(subkey_name, GLOBAL_NAME)) {
805
0
      continue;
806
0
    }
807
808
0
    err = smbconf_add_string_to_array(tmp_ctx,
809
0
               &tmp_share_names,
810
0
               added_count,
811
0
               subkey_name);
812
0
    if (!SBC_ERROR_IS_OK(err)) {
813
0
      goto done;
814
0
    }
815
0
    added_count++;
816
0
  }
817
0
  if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
818
0
    err = SBC_ERR_NO_MORE_ITEMS;
819
0
    goto done;
820
0
  }
821
0
  err = SBC_ERR_OK;
822
823
0
  *num_shares = added_count;
824
0
  if (added_count > 0) {
825
0
    *share_names = talloc_move(mem_ctx, &tmp_share_names);
826
0
  } else {
827
0
    *share_names = NULL;
828
0
  }
829
830
0
done:
831
0
  talloc_free(tmp_ctx);
832
0
  return err;
833
0
}
834
835
/**
836
 * check if a share/service of a given name exists - registry version
837
 */
838
static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
839
             const char *servicename)
840
0
{
841
0
  bool ret = false;
842
0
  sbcErr err;
843
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
844
0
  struct registry_key *key = NULL;
845
846
0
  err = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
847
0
             REG_KEY_READ, &key);
848
0
  if (SBC_ERROR_IS_OK(err)) {
849
0
    ret = true;
850
0
  }
851
852
0
  talloc_free(mem_ctx);
853
0
  return ret;
854
0
}
855
856
/**
857
 * Add a service if it does not already exist - registry version
858
 */
859
static sbcErr smbconf_reg_create_share(struct smbconf_ctx *ctx,
860
               const char *servicename)
861
0
{
862
0
  sbcErr err;
863
0
  struct registry_key *key = NULL;
864
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
865
866
0
  if (servicename == NULL) {
867
0
    return SBC_ERR_OK;
868
0
  }
869
870
0
  err = smbconf_reg_create_service_key(tmp_ctx, ctx,
871
0
               servicename, &key);
872
873
0
  talloc_free(tmp_ctx);
874
0
  return err;
875
0
}
876
877
/**
878
 * get a definition of a share (service) from configuration.
879
 */
880
static sbcErr smbconf_reg_get_share(struct smbconf_ctx *ctx,
881
            TALLOC_CTX *mem_ctx,
882
            const char *servicename,
883
            struct smbconf_service **service)
884
0
{
885
0
  sbcErr err;
886
0
  struct registry_key *key = NULL;
887
0
  struct smbconf_service *tmp_service = NULL;
888
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
889
890
0
  err = smbconf_reg_open_service_key(tmp_ctx, ctx, servicename,
891
0
             REG_KEY_READ, &key);
892
0
  if (!SBC_ERROR_IS_OK(err)) {
893
0
    goto done;
894
0
  }
895
896
0
  tmp_service = talloc_zero(tmp_ctx, struct smbconf_service);
897
0
  if (tmp_service == NULL) {
898
0
    err = SBC_ERR_NOMEM;
899
0
    goto done;
900
0
  }
901
902
0
  if (servicename != NULL) {
903
0
    WERROR werr;
904
0
    uint32_t count = 0;
905
0
    char *name = NULL;
906
907
    /*
908
     * Determine correct upper/lowercase.
909
     */
910
0
    for (count = 0;
911
0
         werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
912
0
          &name, NULL),
913
0
           W_ERROR_IS_OK(werr);
914
0
         count++) {
915
0
      if (!strequal(name, servicename)) {
916
0
        continue;
917
0
      }
918
919
0
      tmp_service->name = talloc_strdup(tmp_service, name);
920
0
      if (tmp_service->name == NULL) {
921
0
        err = SBC_ERR_NOMEM;
922
0
        goto done;
923
0
      }
924
0
      break;
925
0
    }
926
0
  }
927
928
0
  err = smbconf_reg_get_values(tmp_service, key,
929
0
             &(tmp_service->num_params),
930
0
             &(tmp_service->param_names),
931
0
             &(tmp_service->param_values));
932
0
  if (SBC_ERROR_IS_OK(err)) {
933
0
    *service = talloc_move(mem_ctx, &tmp_service);
934
0
  }
935
936
0
done:
937
0
  talloc_free(tmp_ctx);
938
0
  return err;
939
0
}
940
941
/**
942
 * delete a service from configuration
943
 */
944
static sbcErr smbconf_reg_delete_share(struct smbconf_ctx *ctx,
945
               const char *servicename)
946
0
{
947
0
  WERROR werr;
948
0
  sbcErr err = SBC_ERR_OK;
949
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
950
951
0
  if (servicename != NULL) {
952
0
    werr = reg_deletekey_recursive(rpd(ctx)->base_key, servicename);
953
0
    if (!W_ERROR_IS_OK(werr)) {
954
0
      err = SBC_ERR_ACCESS_DENIED;
955
0
    }
956
0
  } else {
957
0
    err = smbconf_reg_delete_values(rpd(ctx)->base_key);
958
0
  }
959
960
0
  talloc_free(mem_ctx);
961
0
  return err;
962
0
}
963
964
/**
965
 * set a configuration parameter to the value provided.
966
 */
967
static sbcErr smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
968
          const char *service,
969
          const char *param,
970
          const char *valstr)
971
0
{
972
0
  sbcErr err;
973
0
  struct registry_key *key = NULL;
974
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
975
976
0
  err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
977
0
             REG_KEY_WRITE, &key);
978
0
  if (!SBC_ERROR_IS_OK(err)) {
979
0
    goto done;
980
0
  }
981
982
0
  err = smbconf_reg_set_value(key, param, valstr);
983
984
0
done:
985
0
  talloc_free(mem_ctx);
986
0
  return err;
987
0
}
988
989
/**
990
 * get the value of a configuration parameter as a string
991
 */
992
static sbcErr smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
993
          TALLOC_CTX *mem_ctx,
994
          const char *service,
995
          const char *param,
996
          char **valstr)
997
0
{
998
0
  WERROR werr;
999
0
  sbcErr err;
1000
0
  struct registry_key *key = NULL;
1001
0
  struct registry_value *value = NULL;
1002
1003
0
  err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1004
0
             REG_KEY_READ, &key);
1005
0
  if (!SBC_ERROR_IS_OK(err)) {
1006
0
    goto done;
1007
0
  }
1008
1009
0
  if (!smbconf_reg_parameter_is_valid(param)) {
1010
0
    err = SBC_ERR_INVALID_PARAM;
1011
0
    goto done;
1012
0
  }
1013
1014
0
  if (!smbconf_value_exists(key, param)) {
1015
0
    err = SBC_ERR_INVALID_PARAM;
1016
0
    goto done;
1017
0
  }
1018
1019
0
  werr = reg_queryvalue(mem_ctx, key, param, &value);
1020
0
  if (!W_ERROR_IS_OK(werr)) {
1021
0
    err = SBC_ERR_NOMEM;
1022
0
    goto done;
1023
0
  }
1024
1025
0
  *valstr = smbconf_format_registry_value(mem_ctx, value);
1026
0
  if (*valstr == NULL) {
1027
0
    err = SBC_ERR_NOMEM;
1028
0
  }
1029
1030
0
done:
1031
0
  talloc_free(key);
1032
0
  talloc_free(value);
1033
0
  return err;
1034
0
}
1035
1036
/**
1037
 * delete a parameter from configuration
1038
 */
1039
static sbcErr smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
1040
             const char *service,
1041
             const char *param)
1042
0
{
1043
0
  struct registry_key *key = NULL;
1044
0
  WERROR werr;
1045
0
  sbcErr err;
1046
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1047
1048
0
  err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1049
0
             REG_KEY_ALL, &key);
1050
0
  if (!SBC_ERROR_IS_OK(err)) {
1051
0
    goto done;
1052
0
  }
1053
1054
0
  if (!smbconf_reg_parameter_is_valid(param)) {
1055
0
    err = SBC_ERR_INVALID_PARAM;
1056
0
    goto done;
1057
0
  }
1058
1059
0
  if (!smbconf_value_exists(key, param)) {
1060
0
    err = SBC_ERR_OK;
1061
0
    goto done;
1062
0
  }
1063
1064
0
  werr = reg_deletevalue(key, param);
1065
0
  if (!W_ERROR_IS_OK(werr)) {
1066
0
    err = SBC_ERR_ACCESS_DENIED;
1067
0
  }
1068
1069
0
done:
1070
0
  talloc_free(mem_ctx);
1071
0
  return err;
1072
0
}
1073
1074
static sbcErr smbconf_reg_get_includes(struct smbconf_ctx *ctx,
1075
               TALLOC_CTX *mem_ctx,
1076
               const char *service,
1077
               uint32_t *num_includes,
1078
               char ***includes)
1079
0
{
1080
0
  sbcErr err;
1081
0
  struct registry_key *key = NULL;
1082
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
1083
1084
0
  err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1085
0
             REG_KEY_READ, &key);
1086
0
  if (!SBC_ERROR_IS_OK(err)) {
1087
0
    goto done;
1088
0
  }
1089
1090
0
  err = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
1091
0
             includes);
1092
0
  if (!SBC_ERROR_IS_OK(err)) {
1093
0
    goto done;
1094
0
  }
1095
1096
0
done:
1097
0
  talloc_free(tmp_ctx);
1098
0
  return err;
1099
0
}
1100
1101
static sbcErr smbconf_reg_set_includes(struct smbconf_ctx *ctx,
1102
               const char *service,
1103
               uint32_t num_includes,
1104
               const char **includes)
1105
0
{
1106
0
  sbcErr err;
1107
0
  struct registry_key *key = NULL;
1108
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
1109
1110
0
  err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1111
0
             REG_KEY_ALL, &key);
1112
0
  if (!SBC_ERROR_IS_OK(err)) {
1113
0
    goto done;
1114
0
  }
1115
1116
0
  if (num_includes == 0) {
1117
0
    WERROR werr;
1118
0
    if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1119
0
      err = SBC_ERR_OK;
1120
0
      goto done;
1121
0
    }
1122
0
    werr = reg_deletevalue(key, INCLUDES_VALNAME);
1123
0
    if (!W_ERROR_IS_OK(werr)) {
1124
0
      err = SBC_ERR_ACCESS_DENIED;
1125
0
      goto done;
1126
0
    }
1127
0
  } else {
1128
0
    err = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
1129
0
                  num_includes, includes);
1130
0
  }
1131
1132
0
done:
1133
0
  talloc_free(tmp_ctx);
1134
0
  return err;
1135
0
}
1136
1137
static sbcErr smbconf_reg_delete_includes(struct smbconf_ctx *ctx,
1138
            const char *service)
1139
0
{
1140
0
  WERROR werr;
1141
0
  sbcErr err;
1142
0
  struct registry_key *key = NULL;
1143
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
1144
1145
0
  err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1146
0
             REG_KEY_ALL, &key);
1147
0
  if (!SBC_ERROR_IS_OK(err)) {
1148
0
    goto done;
1149
0
  }
1150
1151
0
  if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1152
0
    err = SBC_ERR_OK;
1153
0
    goto done;
1154
0
  }
1155
1156
0
  werr = reg_deletevalue(key, INCLUDES_VALNAME);
1157
0
  if (!W_ERROR_IS_OK(werr)) {
1158
0
    err = SBC_ERR_ACCESS_DENIED;
1159
0
    goto done;
1160
0
  }
1161
1162
0
  err = SBC_ERR_OK;
1163
0
done:
1164
0
  talloc_free(tmp_ctx);
1165
0
  return err;
1166
0
}
1167
1168
static sbcErr smbconf_reg_transaction_start(struct smbconf_ctx *ctx)
1169
0
{
1170
0
  WERROR werr;
1171
1172
0
  werr = regdb_transaction_start();
1173
0
  if (!W_ERROR_IS_OK(werr)) {
1174
0
    return SBC_ERR_IO_FAILURE;
1175
0
  }
1176
1177
0
  return SBC_ERR_OK;
1178
0
}
1179
1180
static sbcErr smbconf_reg_transaction_commit(struct smbconf_ctx *ctx)
1181
0
{
1182
0
  WERROR werr;
1183
1184
0
  werr = regdb_transaction_commit();
1185
0
  if (!W_ERROR_IS_OK(werr)) {
1186
0
    return SBC_ERR_IO_FAILURE;
1187
0
  }
1188
1189
0
  return SBC_ERR_OK;
1190
0
}
1191
1192
static sbcErr smbconf_reg_transaction_cancel(struct smbconf_ctx *ctx)
1193
0
{
1194
0
  WERROR werr;
1195
1196
0
  werr = regdb_transaction_cancel();
1197
0
  if (!W_ERROR_IS_OK(werr)) {
1198
0
    return SBC_ERR_IO_FAILURE;
1199
0
  }
1200
1201
0
  return SBC_ERR_OK;
1202
0
}
1203
1204
struct smbconf_ops smbconf_ops_reg = {
1205
  .init     = smbconf_reg_init,
1206
  .shutdown   = smbconf_reg_shutdown,
1207
  .requires_messaging = smbconf_reg_requires_messaging,
1208
  .is_writeable   = smbconf_reg_is_writeable,
1209
  .open_conf    = smbconf_reg_open,
1210
  .close_conf   = smbconf_reg_close,
1211
  .get_csn    = smbconf_reg_get_csn,
1212
  .drop     = smbconf_reg_drop,
1213
  .get_share_names  = smbconf_reg_get_share_names,
1214
  .share_exists   = smbconf_reg_share_exists,
1215
  .create_share   = smbconf_reg_create_share,
1216
  .get_share    = smbconf_reg_get_share,
1217
  .delete_share   = smbconf_reg_delete_share,
1218
  .set_parameter    = smbconf_reg_set_parameter,
1219
  .get_parameter    = smbconf_reg_get_parameter,
1220
  .delete_parameter = smbconf_reg_delete_parameter,
1221
  .get_includes   = smbconf_reg_get_includes,
1222
  .set_includes   = smbconf_reg_set_includes,
1223
  .delete_includes  = smbconf_reg_delete_includes,
1224
  .transaction_start  = smbconf_reg_transaction_start,
1225
  .transaction_commit = smbconf_reg_transaction_commit,
1226
  .transaction_cancel = smbconf_reg_transaction_cancel,
1227
};
1228
1229
1230
/**
1231
 * initialize the smbconf registry backend
1232
 * the only function that is exported from this module
1233
 */
1234
sbcErr smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
1235
      const char *path)
1236
0
{
1237
  /*
1238
   * this tmp_ctx stackframe is required to initialize the registry backend.
1239
   * Without it, the calls panics due to the use of talloc_tos in the
1240
   * source3/registry code.
1241
   */
1242
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
1243
0
  sbcErr err = smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
1244
  talloc_free(tmp_ctx);
1245
0
  return err;
1246
0
}