Print this page
    
NEX-19665 Several door servers don't properly handle exiting threads
Review by: Gordon Ross <gordon.ross@nexenta.com>
Review by: Evan Layton <evan.layton@nexenta.com>
NEX-2225 Unable to join NexentaStor to 2008 AD
NEX-1638 Updated DC Locator
 Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com
re #13190 rb4312 idmapd error -9961 (No AD servers)
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/idmap/idmapd/init.c
          +++ new/usr/src/cmd/idmap/idmapd/init.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Initialization routines
  28   28   */
  29   29  
  30   30  #include "idmapd.h"
  31   31  #include <signal.h>
  32   32  #include <thread.h>
  33   33  #include <string.h>
  34   34  #include <errno.h>
  35   35  #include <assert.h>
  36   36  #include <unistd.h>
  37   37  #include <sys/types.h>
  38   38  #include <sys/stat.h>
  39   39  #include <rpcsvc/daemon_utils.h>
  40   40  
  41   41  
  42   42  int
  43   43  init_mapping_system()
  44   44  {
  45   45          int rc = 0;
  46   46  
  47   47          if ((rc = load_config()) < 0)
  48   48                  return (rc);
  49   49  
  50   50          (void) setegid(DAEMON_GID);
  51   51          (void) seteuid(DAEMON_UID);
  52   52          if (init_dbs() < 0) {
  53   53                  rc = -1;
  54   54                  fini_mapping_system();
  55   55          }
  56   56          (void) seteuid(0);
  57   57          (void) setegid(0);
  58   58  
  59   59          return (rc);
  60   60  }
  61   61  
  62   62  void
  63   63  fini_mapping_system()
  64   64  {
  65   65          fini_dbs();
  66   66  }
  67   67  
  68   68  int
  69   69  load_config()
  70   70  {
  71   71          int rc;
  72   72          if ((_idmapdstate.cfg = idmap_cfg_init()) == NULL) {
  73   73                  degrade_svc(0, "failed to initialize config");
  74   74                  return (-1);
  75   75          }
  76   76  
  77   77          rc = idmap_cfg_upgrade(_idmapdstate.cfg);
  78   78          if (rc != 0) {
  79   79                  degrade_svc(0, "fatal error while upgrading configuration");
  80   80                  return (rc);
  81   81          }
  82   82  
  83   83          rc = idmap_cfg_load(_idmapdstate.cfg, 0);
  84   84          if (rc < -1) {
  85   85                  /* Total failure */
  86   86                  degrade_svc(0, "fatal error while loading configuration");
  87   87                  return (rc);
  88   88          }
  89   89  
  90   90          if (rc != 0)
  91   91                  /* Partial failure */
  92   92                  idmapdlog(LOG_ERR, "Various errors occurred while loading "
  93   93                      "the configuration; check the logs");
  94   94  
  95   95          if ((rc = idmap_cfg_start_updates()) < 0) {
  96   96                  /* Total failure */
  97   97                  degrade_svc(0, "could not start config updater");
  98   98                  return (rc);
  99   99          }
 100  100  
 101  101          if (DBG(CONFIG, 1))
 102  102                  idmapdlog(LOG_DEBUG, "Initial configuration loaded");
 103  103  
 104  104          return (0);
 105  105  }
 106  106  
 107  107  
 108  108  void
 109  109  reload_gcs()
 110  110  {
 111  111          int             i, j;
 112  112          adutils_ad_t    **new_gcs;
 113  113          adutils_ad_t    **old_gcs = _idmapdstate.gcs;
 114  114          int             new_num_gcs;
 115  115          int             old_num_gcs = _idmapdstate.num_gcs;
 116  116          idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
 117  117          idmap_trustedforest_t *trustfor = pgcfg->trusted_forests;
 118  118          int             num_trustfor = pgcfg->num_trusted_forests;
 119  119          ad_disc_domainsinforest_t *domain_in_forest;
 120  120  
 121  121          if (pgcfg->use_ads == B_FALSE ||
 122  122              pgcfg->domain_name == NULL) {
 123  123                  /*
 124  124                   * ADS disabled, or no domain name specified.
 125  125                   * Not using adutils. (but still can use lsa)
 126  126                   */
 127  127                  new_gcs = NULL;
 128  128                  new_num_gcs = 0;
 129  129                  goto out;
 130  130          }
 131  131  
 132  132          if (pgcfg->global_catalog == NULL ||
 133  133              pgcfg->global_catalog[0].host[0] == '\0') {
 134  134                  /*
 135  135                   * No GCs.  Continue to use the previous AD config in case
 136  136                   * that's still good but auto-discovery had a transient failure.
 137  137                   * If that stops working we'll go into degraded mode anyways
 138  138                   * when it does.
 139  139                   */
 140  140                  idmapdlog(LOG_INFO,
 141  141                      "Global Catalog servers not configured/discoverable");
 142  142                  return;
 143  143          }
 144  144  
 145  145          new_num_gcs = 1 + num_trustfor;
 146  146          new_gcs = calloc(new_num_gcs, sizeof (adutils_ad_t *));
 147  147          if (new_gcs == NULL) {
 148  148                  degrade_svc(0, "could not allocate AD context array "
 149  149                      "(out of memory)");
 150  150                  return;
 151  151          }
 152  152  
 153  153          if (adutils_ad_alloc(&new_gcs[0], NULL, ADUTILS_AD_GLOBAL_CATALOG) !=
 154  154              ADUTILS_SUCCESS) {
 155  155                  free(new_gcs);
 156  156                  degrade_svc(0, "could not initialize AD context "
 157  157                      "(out of memory)");
 158  158                  return;
 159  159          }
 160  160  
 161  161          for (i = 0; pgcfg->global_catalog[i].host[0] != '\0'; i++) {
 162  162                  if (idmap_add_ds(new_gcs[0],
 163  163                      pgcfg->global_catalog[i].host,
 164  164                      pgcfg->global_catalog[i].port) != 0) {
 165  165                          adutils_ad_free(&new_gcs[0]);
 166  166                          free(new_gcs);
 167  167                          degrade_svc(0, "could not set AD hosts "
 168  168                              "(out of memory)");
 169  169                          return;
 170  170                  }
 171  171          }
 172  172  
 173  173          if (pgcfg->domains_in_forest != NULL) {
 174  174                  for (i = 0; pgcfg->domains_in_forest[i].domain[0] != '\0';
 175  175                      i++) {
 176  176                          if (adutils_add_domain(new_gcs[0],
 177  177                              pgcfg->domains_in_forest[i].domain,
 178  178                              pgcfg->domains_in_forest[i].sid) != 0) {
 179  179                                  adutils_ad_free(&new_gcs[0]);
 180  180                                  free(new_gcs);
 181  181                                  degrade_svc(0, "could not set AD domains "
 182  182                                      "(out of memory)");
 183  183                                  return;
 184  184                          }
 185  185                  }
 186  186          }
 187  187  
 188  188          for (i = 0; i < num_trustfor; i++) {
 189  189                  if (adutils_ad_alloc(&new_gcs[i + 1], NULL,
 190  190                      ADUTILS_AD_GLOBAL_CATALOG) != ADUTILS_SUCCESS) {
 191  191                          degrade_svc(0, "could not initialize trusted AD "
 192  192                              "context (out of memory)");
 193  193                                  new_num_gcs = i + 1;
 194  194                                  goto out;
 195  195                  }
 196  196                  for (j = 0; trustfor[i].global_catalog[j].host[0] != '\0';
 197  197                      j++) {
 198  198                          if (idmap_add_ds(new_gcs[i + 1],
 199  199                              trustfor[i].global_catalog[j].host,
 200  200                              trustfor[i].global_catalog[j].port) != 0) {
 201  201                                  adutils_ad_free(&new_gcs[i + 1]);
 202  202                                  degrade_svc(0, "could not set trusted "
 203  203                                      "AD hosts (out of memory)");
 204  204                                  new_num_gcs = i + 1;
 205  205                                  goto out;
 206  206                          }
 207  207                  }
 208  208                  for (j = 0; trustfor[i].domains_in_forest[j].domain[0] != '\0';
 209  209                      j++) {
 210  210                          domain_in_forest = &trustfor[i].domains_in_forest[j];
 211  211                          /* Only add domains which are marked */
 212  212                          if (domain_in_forest->trusted) {
 213  213                                  if (adutils_add_domain(new_gcs[i + 1],
 214  214                                      domain_in_forest->domain,
 215  215                                      domain_in_forest->sid) != 0) {
 216  216                                          adutils_ad_free(&new_gcs[i + 1]);
 217  217                                          degrade_svc(0, "could not set trusted "
 218  218                                              "AD domains (out of memory)");
 219  219                                          new_num_gcs = i + 1;
 220  220                                          goto out;
 221  221                                  }
 222  222                          }
 223  223                  }
 224  224          }
 225  225  
 226  226  out:
 227  227          _idmapdstate.gcs = new_gcs;
 228  228          _idmapdstate.num_gcs = new_num_gcs;
 229  229  
 230  230          if (old_gcs != NULL) {
 231  231                  for (i = 0; i < old_num_gcs; i++)
 232  232                          adutils_ad_free(&old_gcs[i]);
 233  233                  free(old_gcs);
 234  234          }
 235  235  }
 236  236  
 237  237  /*
 238  238   * NEEDSWORK:  This should load entries for domain servers for all known
 239  239   * domains - the joined domain, other domains in the forest, and trusted
 240  240   * domains in other forests.  However, we don't yet discover any DCs other
 241  241   * than the DCs for the joined domain.
 242  242   */
 243  243  static
 244  244  void
 245  245  reload_dcs(void)
 246  246  {
 247  247          int             i;
 248  248          adutils_ad_t    **new_dcs;
 249  249          adutils_ad_t    **old_dcs = _idmapdstate.dcs;
 250  250          int             new_num_dcs;
 251  251          int             old_num_dcs = _idmapdstate.num_dcs;
 252  252          idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg;
 253  253  
 254  254          if (pgcfg->use_ads == B_FALSE ||
 255  255              pgcfg->domain_name == NULL) {
 256  256                  /*
 257  257                   * ADS disabled, or no domain name specified.
 258  258                   * Not using adutils. (but still can use lsa)
 259  259                   */
 260  260                  new_dcs = NULL;
 261  261                  new_num_dcs = 0;
 262  262                  goto out;
 263  263          }
 264  264  
 265  265          if (pgcfg->domain_controller == NULL ||
 266  266              pgcfg->domain_controller[0].host[0] == '\0') {
 267  267                  /*
 268  268                   * No DCs.  Continue to use the previous AD config in case
 269  269                   * that's still good but auto-discovery had a transient failure.
 270  270                   * If that stops working we'll go into degraded mode anyways
 271  271                   * when it does.
 272  272                   */
 273  273                  idmapdlog(LOG_INFO,
 274  274                      "Domain controller servers not configured/discoverable");
 275  275                  return;
 276  276          }
 277  277  
 278  278          new_num_dcs = 1;
 279  279          new_dcs = calloc(new_num_dcs, sizeof (adutils_ad_t *));
 280  280          if (new_dcs == NULL)
 281  281                  goto nomem;
 282  282  
 283  283          if (adutils_ad_alloc(&new_dcs[0], pgcfg->domain_name,
 284  284              ADUTILS_AD_DATA) != ADUTILS_SUCCESS)
 285  285                  goto nomem;
 286  286  
 287  287          for (i = 0; pgcfg->domain_controller[i].host[0] != '\0'; i++) {
 288  288                  if (idmap_add_ds(new_dcs[0],
 289  289                      pgcfg->domain_controller[i].host,
 290  290                      pgcfg->domain_controller[i].port) != 0)
 291  291                          goto nomem;
 292  292          }
 293  293  
 294  294          /*
 295  295           * NEEDSWORK:  All we need here is to add the domain and SID for
 296  296           * this DC to the list of domains supported by this entry.  Isn't
 297  297           * there an easier way to find the SID than to walk through the list
 298  298           * of all of the domains in the forest?
 299  299           */
 300  300          ad_disc_domainsinforest_t *dif = pgcfg->domains_in_forest;
 301  301          if (dif != NULL) {
 302  302                  for (; dif->domain[0] != '\0'; dif++) {
 303  303                          if (domain_eq(pgcfg->domain_name, dif->domain)) {
 304  304                                  if (adutils_add_domain(new_dcs[0],
 305  305                                      dif->domain, dif->sid) != 0)
 306  306                                          goto nomem;
 307  307                                  break;
 308  308                          }
 309  309                  }
 310  310          }
 311  311  
 312  312  out:
 313  313          _idmapdstate.dcs = new_dcs;
 314  314          _idmapdstate.num_dcs = new_num_dcs;
 315  315  
 316  316          if (old_dcs != NULL) {
 317  317                  for (i = 0; i < old_num_dcs; i++)
 318  318                          adutils_ad_free(&old_dcs[i]);
 319  319                  free(old_dcs);
 320  320          }
 321  321  
 322  322          return;
 323  323  
 324  324  nomem:
 325  325          degrade_svc(0, "out of memory");
 326  326  
 327  327          if (new_dcs != NULL) {
 328  328                  if (new_dcs[0] != NULL)
 329  329                          adutils_ad_free(&new_dcs[0]);
 330  330                  free(new_dcs);
 331  331          }
 332  332  }
 333  333  
 334  334  
 335  335  void
 336  336  reload_ad(void)
 337  337  {
 338  338          reload_gcs();
 339  339          reload_dcs();
 340  340  }
 341  341  
 342  342  void
 343  343  print_idmapdstate(void)
 344  344  {
 345  345          int i, j;
 346  346          idmap_pg_config_t *pgcfg;
 347  347          idmap_trustedforest_t *tf;
 348  348  
 349  349          RDLOCK_CONFIG();
  
    | 
      ↓ open down ↓ | 
    316 lines elided | 
    
      ↑ open up ↑ | 
  
 350  350  
 351  351          if (_idmapdstate.cfg == NULL) {
 352  352                  idmapdlog(LOG_INFO, "Null configuration");
 353  353                  UNLOCK_CONFIG();
 354  354                  return;
 355  355          }
 356  356  
 357  357          pgcfg = &_idmapdstate.cfg->pgcfg;
 358  358  
 359  359          idmapdlog(LOG_DEBUG, "list_size_limit=%llu", pgcfg->list_size_limit);
      360 +        idmapdlog(LOG_DEBUG, "max_threads=%llu", pgcfg->max_threads);
 360  361          idmapdlog(LOG_DEBUG, "default_domain=%s",
 361  362              CHECK_NULL(pgcfg->default_domain));
 362  363          idmapdlog(LOG_DEBUG, "domain_name=%s", CHECK_NULL(pgcfg->domain_name));
 363  364          idmapdlog(LOG_DEBUG, "machine_sid=%s", CHECK_NULL(pgcfg->machine_sid));
 364  365          if (pgcfg->domain_controller == NULL ||
 365  366              pgcfg->domain_controller[0].host[0] == '\0') {
 366  367                  idmapdlog(LOG_DEBUG, "No domain controllers known");
 367  368          } else {
 368  369                  for (i = 0; pgcfg->domain_controller[i].host[0] != '\0'; i++)
 369  370                          idmapdlog(LOG_DEBUG, "domain_controller=%s port=%d",
 370  371                              pgcfg->domain_controller[i].host,
 371  372                              pgcfg->domain_controller[i].port);
 372  373          }
 373  374          idmapdlog(LOG_DEBUG, "forest_name=%s", CHECK_NULL(pgcfg->forest_name));
 374  375          idmapdlog(LOG_DEBUG, "site_name=%s", CHECK_NULL(pgcfg->site_name));
 375  376          if (pgcfg->global_catalog == NULL ||
 376  377              pgcfg->global_catalog[0].host[0] == '\0') {
 377  378                  idmapdlog(LOG_DEBUG, "No global catalog servers known");
 378  379          } else {
 379  380                  for (i = 0; pgcfg->global_catalog[i].host[0] != '\0'; i++)
 380  381                          idmapdlog(LOG_DEBUG, "global_catalog=%s port=%d",
 381  382                              pgcfg->global_catalog[i].host,
 382  383                              pgcfg->global_catalog[i].port);
 383  384          }
 384  385          if (pgcfg->domains_in_forest == NULL ||
 385  386              pgcfg->domains_in_forest[0].domain[0] == '\0') {
 386  387                  idmapdlog(LOG_DEBUG, "No domains in forest %s known",
 387  388                      CHECK_NULL(pgcfg->forest_name));
 388  389          } else {
 389  390                  for (i = 0; pgcfg->domains_in_forest[i].domain[0] != '\0'; i++)
 390  391                          idmapdlog(LOG_DEBUG, "domains in forest %s = %s",
 391  392                              CHECK_NULL(pgcfg->forest_name),
 392  393                              pgcfg->domains_in_forest[i].domain);
 393  394          }
 394  395          if (pgcfg->trusted_domains == NULL ||
 395  396              pgcfg->trusted_domains[0].domain[0] == '\0') {
 396  397                  idmapdlog(LOG_DEBUG, "No trusted domains known");
 397  398          } else {
 398  399                  for (i = 0; pgcfg->trusted_domains[i].domain[0] != '\0'; i++)
 399  400                          idmapdlog(LOG_DEBUG, "trusted domain = %s",
 400  401                              pgcfg->trusted_domains[i].domain);
 401  402          }
 402  403  
 403  404          for (i = 0; i < pgcfg->num_trusted_forests; i++) {
 404  405                  tf = &pgcfg->trusted_forests[i];
 405  406                  for (j = 0; tf->global_catalog[j].host[0] != '\0'; j++)
 406  407                          idmapdlog(LOG_DEBUG,
 407  408                              "trusted forest %s global_catalog=%s port=%d",
 408  409                              tf->forest_name,
 409  410                              tf->global_catalog[j].host,
 410  411                              tf->global_catalog[j].port);
 411  412                  for (j = 0; tf->domains_in_forest[j].domain[0] != '\0'; j++) {
 412  413                          if (tf->domains_in_forest[j].trusted) {
 413  414                                  idmapdlog(LOG_DEBUG,
 414  415                                      "trusted forest %s domain=%s",
 415  416                                      tf->forest_name,
 416  417                                      tf->domains_in_forest[j].domain);
 417  418                          }
 418  419                  }
 419  420          }
 420  421  
 421  422          idmapdlog(LOG_DEBUG, "directory_based_mapping=%s",
 422  423              enum_lookup(pgcfg->directory_based_mapping, directory_mapping_map));
 423  424          idmapdlog(LOG_DEBUG, "ad_unixuser_attr=%s",
 424  425              CHECK_NULL(pgcfg->ad_unixuser_attr));
 425  426          idmapdlog(LOG_DEBUG, "ad_unixgroup_attr=%s",
 426  427              CHECK_NULL(pgcfg->ad_unixgroup_attr));
 427  428          idmapdlog(LOG_DEBUG, "nldap_winname_attr=%s",
 428  429              CHECK_NULL(pgcfg->nldap_winname_attr));
 429  430  
 430  431          UNLOCK_CONFIG();
 431  432  }
 432  433  
 433  434  int
 434  435  create_directory(const char *path, uid_t uid, gid_t gid)
 435  436  {
 436  437          int     rc;
 437  438  
 438  439          if ((rc = mkdir(path, 0700)) < 0 && errno != EEXIST) {
 439  440                  idmapdlog(LOG_ERR, "Error creating directory %s (%s)",
 440  441                      path, strerror(errno));
 441  442                  return (-1);
 442  443          }
 443  444  
 444  445          if (lchown(path, uid, gid) < 0) {
 445  446                  idmapdlog(LOG_ERR, "Error creating directory %s (%s)",
 446  447                      path, strerror(errno));
 447  448                  if (rc == 0)
 448  449                          (void) rmdir(path);
 449  450                  return (-1);
 450  451          }
 451  452          return (0);
 452  453  }
  
    | 
      ↓ open down ↓ | 
    83 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX