root/source3/lib/smbconf/smbconf_reg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rpd
  2. smbconf_reg_valname_forbidden
  3. smbconf_reg_valname_valid
  4. smbconf_reg_open_service_key
  5. smbconf_value_exists
  6. smbconf_reg_create_service_key
  7. smbconf_reg_set_value
  8. smbconf_reg_set_multi_sz_value
  9. smbconf_format_registry_value
  10. smbconf_reg_get_includes_internal
  11. smbconf_reg_get_values
  12. smbconf_reg_key_has_values
  13. smbconf_reg_delete_values
  14. smbconf_reg_init
  15. smbconf_reg_shutdown
  16. smbconf_reg_requires_messaging
  17. smbconf_reg_is_writeable
  18. smbconf_reg_open
  19. smbconf_reg_close
  20. smbconf_reg_get_csn
  21. smbconf_reg_drop
  22. smbconf_reg_get_share_names
  23. smbconf_reg_share_exists
  24. smbconf_reg_create_share
  25. smbconf_reg_get_share
  26. smbconf_reg_delete_share
  27. smbconf_reg_set_parameter
  28. smbconf_reg_get_parameter
  29. smbconf_reg_delete_parameter
  30. smbconf_reg_get_includes
  31. smbconf_reg_set_includes
  32. smbconf_reg_delete_includes
  33. smbconf_reg_transaction_start
  34. smbconf_reg_transaction_commit
  35. smbconf_reg_transaction_cancel
  36. smbconf_init_reg

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

/* [<][>][^][v][top][bottom][index][help] */