1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <stdio.h>
  28 #include <string.h>
  29 #include <stdlib.h>
  30 #include <ctype.h>
  31 #include <fcntl.h>
  32 #include <errno.h>
  33 #include <syslog.h>
  34 
  35 #include "ldap_parse.h"
  36 #include "nis_parse_ldap_conf.h"
  37 #include "nis_parse_ldap_err.h"
  38 #include "ldap_util.h"
  39 
  40 extern __nis_mapping_rule_t **dup_mapping_rules(
  41         __nis_mapping_rule_t **rules, int n_rules);
  42 extern __nis_mapping_rule_t *dup_mapping_rule(
  43         __nis_mapping_rule_t *in);
  44 
  45 static int      merge_table_mapping(__nis_table_mapping_t *in,
  46         __nis_table_mapping_t *out);
  47 __nis_table_mapping_t *new_merged_mapping(const char *,
  48         __nis_table_mapping_t *intbl);
  49 static int append_mapping_rule(__nis_mapping_rule_t *src_rule,
  50         __nis_table_mapping_t *tbl, int flag);
  51 
  52 
  53 static int copy_object_dn(__nis_object_dn_t     *in,
  54                 __nis_object_dn_t       *newdn);
  55 
  56 /*
  57  * FUNCTION:    initialize_table_mapping
  58  *
  59  * Initialize the __nis_table_mapping_t structure.
  60  *
  61  * INPUT:       __nis_table_mapping_t
  62  *
  63  */
  64 void
  65 initialize_table_mapping(
  66         __nis_table_mapping_t *mapping)
  67 {
  68         if (mapping != NULL) {
  69                 mapping->dbId = NULL;
  70 
  71                 mapping->index.numIndexes = 0;
  72                 mapping->index.name = NULL;
  73                 mapping->index.value = NULL;
  74 
  75                 mapping->numColumns = 0;
  76                 mapping->column = NULL;
  77 
  78                 mapping->initTtlLo = (time_t)NO_VALUE_SET;
  79                 mapping->initTtlHi = (time_t)NO_VALUE_SET;
  80                 mapping->ttl = (time_t)NO_VALUE_SET;
  81 
  82                 mapping->usedns_flag = 0;
  83                 mapping->securemap_flag = 0;
  84                 mapping->commentChar = DEFAULT_COMMENT_CHAR;
  85                 mapping->numSplits = 0;
  86 
  87                 mapping->objectDN = NULL;
  88 
  89                 mapping->separatorStr = DEFAULT_SEP_STRING;
  90 
  91                 mapping->numRulesFromLDAP = 0;
  92                 mapping->numRulesToLDAP = 0;
  93 
  94                 mapping->ruleFromLDAP = NULL;
  95                 mapping->ruleToLDAP = NULL;
  96 
  97                 mapping->e = NULL;
  98                 mapping->objName = NULL;
  99                 mapping->objPath = NULL;
 100                 mapping->obj = NULL;
 101                 mapping->isMaster = 0;
 102                 mapping->seq_num = NO_VALUE_SET;
 103         }
 104 }
 105 
 106 /*
 107  * FUNCTION:    initialize_yp_parse_structs
 108  *
 109  * Initialize the __yp_domain_context_t structure.
 110  *
 111  * INPUT:               __yp_domain_context_t
 112  *
 113  */
 114 void
 115 initialize_yp_parse_structs(
 116         __yp_domain_context_t   *ypDomains)
 117 {
 118         ypDomains->numDomains = 0;
 119         ypDomains->domainLabels = NULL;
 120         ypDomains->domains = NULL;
 121         ypDomains->numYppasswdd = 0;
 122         ypDomains->yppasswddDomainLabels = NULL;
 123 }
 124 
 125 /*
 126  * FUNCTION:    merge_table_mapping
 127  *
 128  * Merges information from one table_mapping struct
 129  * into another
 130  *
 131  * INPUT: Source and Destination table_mapping structs.
 132  * RETURN: 0 on success and > 0 on error.
 133  */
 134 
 135 static int
 136 merge_table_mapping(
 137         __nis_table_mapping_t *in,
 138         __nis_table_mapping_t *out)
 139 {
 140         int i;
 141         int len;
 142         int orig_num_rules;
 143         int append;
 144 
 145         if (in == NULL)
 146                 return (1);
 147 
 148         if (in->dbId == NULL)
 149                 return (1);
 150 
 151         /*
 152          * If 'in' is generic (non-expanded) and 'out' is domain-specific,
 153          * then rules from 'in' should not be appended to those in 'out'.
 154          */
 155         if (!strchr(in->dbId, COMMA_CHAR) && strchr(out->dbId, COMMA_CHAR))
 156                 append = 0;
 157         else
 158                 append = 1;
 159 
 160 
 161         if (!out->index.numIndexes && in->index.numIndexes > 0) {
 162                 if (!dup_index(&in->index, &out->index))
 163                         return (1);
 164         }
 165 
 166         /* add_column() increments numColumns, so we don't */
 167         if (!out->numColumns && in->numColumns > 0) {
 168                 for (i = 0; i < in->numColumns; i++) {
 169                         if (!add_column(out, in->column[i]))
 170                                 return (1);
 171                 }
 172         }
 173 
 174         if (out->commentChar == DEFAULT_COMMENT_CHAR &&
 175             in->commentChar != DEFAULT_COMMENT_CHAR)
 176                 out->commentChar = in->commentChar;
 177 
 178         if (out->usedns_flag == 0)
 179                 out->usedns_flag = in->usedns_flag;
 180 
 181         if (out->securemap_flag == 0)
 182                 out->securemap_flag = in->securemap_flag;
 183 
 184         if ((strcmp(out->separatorStr, DEFAULT_SEP_STRING) == 0) &&
 185             (strcmp(in->separatorStr, DEFAULT_SEP_STRING) != 0)) {
 186                 out->separatorStr = s_strdup(in->separatorStr);
 187                 if (!out->separatorStr)
 188                         return (2);
 189         }
 190 
 191         if (!out->numSplits && !out->e && in->e) {
 192                 out->numSplits = in->numSplits;
 193                 out->e = (__nis_mapping_element_t *)
 194                     s_calloc(1, (in->numSplits+1) *
 195                     sizeof (__nis_mapping_element_t));
 196                 if (!out->e)
 197                         return (2);
 198                 for (i = 0; i <= in->numSplits; i++) {
 199                         if (!dup_mapping_element(&in->e[i], &out->e[i])) {
 200                                 for (; i > 0; i--) {
 201                                         free_mapping_element(&out->e[i - 1]);
 202                                 }
 203                                 out->e = NULL;
 204                                 return (1);
 205                         }
 206                 }
 207         }
 208 
 209         if (out->initTtlLo == (time_t)NO_VALUE_SET &&
 210             in->initTtlLo != (time_t)NO_VALUE_SET)
 211                 out->initTtlLo = in->initTtlLo;
 212 
 213         if (out->initTtlHi == (time_t)NO_VALUE_SET &&
 214             in->initTtlHi != (time_t)NO_VALUE_SET)
 215                 out->initTtlHi = in->initTtlHi;
 216 
 217         if (out->ttl == (time_t)NO_VALUE_SET &&
 218             in->ttl != (time_t)NO_VALUE_SET)
 219                 out->ttl = in->ttl;
 220 
 221         if (!out->numRulesFromLDAP && in->numRulesFromLDAP) {
 222                 out->ruleFromLDAP = dup_mapping_rules(in->ruleFromLDAP,
 223                     in->numRulesFromLDAP);
 224                 if (!out->ruleFromLDAP)
 225                         return (1);
 226                 out->numRulesFromLDAP = in->numRulesFromLDAP;
 227         } else if (append && out->numRulesFromLDAP && in->numRulesFromLDAP) {
 228                 orig_num_rules = out->numRulesFromLDAP;
 229                 for (i = 0; i < in->numRulesFromLDAP; i++) {
 230                         if (append_mapping_rule(in->ruleFromLDAP[i], out, 0)) {
 231                                 for (i = out->numRulesFromLDAP;
 232                                     i > orig_num_rules; i--) {
 233                                         free_mapping_rule(out->ruleFromLDAP[i]);
 234                                         out->ruleFromLDAP[i] = NULL;
 235                                 }
 236                                 return (1);
 237 
 238                         }
 239                 }
 240         }
 241 
 242         if (!out->numRulesToLDAP && in->numRulesToLDAP) {
 243                 out->ruleToLDAP = dup_mapping_rules(in->ruleToLDAP,
 244                     in->numRulesToLDAP);
 245                 if (!out->ruleToLDAP)
 246                         return (1);
 247                 out->numRulesToLDAP = in->numRulesToLDAP;
 248         } else if (append && out->numRulesToLDAP && in->numRulesToLDAP) {
 249                 orig_num_rules = out->numRulesToLDAP;
 250                 for (i = 0; i < in->numRulesToLDAP; i++) {
 251                         if (append_mapping_rule(in->ruleToLDAP[i], out, 1)) {
 252                                 for (i = out->numRulesToLDAP;
 253                                     i > orig_num_rules; i--) {
 254                                         free_mapping_rule(out->ruleToLDAP[i]);
 255                                         out->ruleToLDAP[i] = NULL;
 256                                 }
 257                                 return (1);
 258                         }
 259                 }
 260         }
 261         if (!out->objectDN && in->objectDN) {
 262                 out->objectDN = (__nis_object_dn_t *)
 263                     s_calloc(1, sizeof (__nis_object_dn_t));
 264                 if (!out->objectDN)
 265                         return (2);
 266                 if (copy_object_dn(in->objectDN, out->objectDN)) {
 267                         free_object_dn(out->objectDN);
 268                         out->objectDN = NULL;
 269                         return (1);
 270                 }
 271         }
 272 
 273         if (!out->objName && in->objName) {
 274                 if (!strchr(in->objName, SPACE_CHAR)) {
 275                         /* objName has no space- a single map dbIdMapping */
 276                         out->objName = s_strndup(in->objName,
 277                             strlen(in->objName));
 278                         if (!out->objName)
 279                                 return (2);
 280                 }
 281         }
 282 
 283         if (!out->objName && out->dbId) {
 284                 out->objName = s_strndup(out->dbId, strlen(out->dbId));
 285                 if (!out->objName)
 286                         return (2);
 287         }
 288 
 289         if (out->seq_num == NO_VALUE_SET && in->seq_num >= 0)
 290                 out->seq_num = in->seq_num;
 291 
 292         return (p_error == no_parse_error ? 0 : 1);
 293 }
 294 
 295 /*
 296  * FUNCTION:    copy_object_dn
 297  *
 298  * Copies a __nis_object_dn_t structure.
 299  *
 300  * RETURN:      0 on success, > 0 on failure.
 301  *
 302  * NOTE:        The caller MUST free newdn using
 303  *              free_object_dn() if return value != 0 (error condition)
 304  */
 305 
 306 static int
 307 copy_object_dn(__nis_object_dn_t *in, __nis_object_dn_t *newdn)
 308 {
 309         if (in == NULL) {
 310                 p_error = parse_no_object_dn;
 311                 return (1);
 312         }
 313         while (in != NULL) {
 314                 if (in->read.base == NULL) {
 315                         newdn->read.base = NULL;
 316                 } else {
 317                         newdn->read.base = s_strndup(
 318                             in->read.base, strlen(in->read.base));
 319                         if (newdn->read.base == NULL)
 320                                 return (2);
 321                 }
 322                 newdn->read.scope = in->read.scope;
 323                 if (in->read.attrs) {
 324                         newdn->read.attrs = s_strndup(
 325                             in->read.attrs, strlen(in->read.attrs));
 326                         if (newdn->read.attrs == NULL) {
 327                                 return (2);
 328                         }
 329                 } else {
 330                         newdn->read.attrs = NULL;
 331                 }
 332                 newdn->read.element = in->read.element;
 333                 if (in->write.base != NULL) {
 334                         newdn->write.base = s_strndup(
 335                             in->write.base, strlen(in->write.base));
 336                         if (newdn->write.base == NULL)
 337                                 return (2);
 338                 } else {
 339                         newdn->write.base = NULL;
 340                 }
 341                 newdn->write.scope = in->write.scope;
 342                 if (in->write.attrs != NULL) {
 343                         newdn->write.attrs = s_strndup(
 344                             in->write.attrs, strlen(in->write.attrs));
 345                         if (newdn->write.attrs == NULL) {
 346                                 return (2);
 347                         }
 348                 } else {
 349                         newdn->write.attrs = NULL;
 350                 }
 351                 newdn->write.element = in->write.element;
 352                 if (in->dbIdName) {
 353                         newdn->dbIdName = s_strndup(in->dbIdName,
 354                             strlen(in->dbIdName));
 355                         if (newdn->dbIdName == NULL)
 356                                 return (2);
 357                 }
 358 
 359                 if (in->delDisp)
 360                         newdn->delDisp = in->delDisp;
 361 
 362                 if (in->dbId && in->numDbIds > 0) {
 363                         newdn->dbId = dup_mapping_rules(in->dbId,
 364                             in->numDbIds);
 365                         if (!newdn->dbId)
 366                                 return (1);
 367                         newdn->numDbIds = in->numDbIds;
 368                 }
 369                 if (in->next != NULL) {
 370                         newdn->next = (__nis_object_dn_t *)s_calloc(1,
 371                             sizeof (__nis_object_dn_t));
 372                         if (newdn->next == NULL)
 373                                 return (1);
 374                         newdn = newdn->next;
 375                         in = in->next;
 376                 } else {
 377                         return (0);
 378                 }
 379         } /* End of while on in */
 380 
 381         return (0);
 382 }
 383 
 384 /*
 385  * FUNCTION:    free_yp_domain_context
 386  *
 387  * Frees __yp_domain_context_t
 388  *
 389  * INPUT:               __yp_domain_context_t
 390  */
 391 void
 392 free_yp_domain_context(__yp_domain_context_t *domains)
 393 {
 394         int i;
 395 
 396         if (domains != NULL) {
 397                 for (i = 0; i < domains->numDomains; i++) {
 398                         if (domains->domains[i] != NULL) {
 399                                 free(domains->domains[i]);
 400                                 domains->domains[i] = NULL;
 401                         }
 402                         if (domains->domainLabels[i] != NULL) {
 403                                 free(domains->domainLabels[i]);
 404                                 domains->domainLabels[i] = NULL;
 405                         }
 406                 }
 407                 domains->domains = NULL;
 408                 domains->domainLabels = NULL;
 409                 for (i = 0; i < domains->numYppasswdd; i++) {
 410                         if (domains->yppasswddDomainLabels[i] != NULL) {
 411                                 free(domains->yppasswddDomainLabels[i]);
 412                                 domains->yppasswddDomainLabels[i] =
 413                                     NULL;
 414                         }
 415                 }
 416                 domains->yppasswddDomainLabels = NULL;
 417                 domains->numDomains = 0;
 418                 domains = NULL;
 419         }
 420 }
 421 
 422 /*
 423  * FUNCTION:    second_parser_pass
 424  *
 425  * Prepares the linked list of table_mappings for processing
 426  * by finish_parse(), adding, merging and deleting structures
 427  * as necessary. Also adds dummy objectDN info. for splitField's.
 428  *
 429  * RETURN VALUE: 0 on success, > 0 on failure.
 430  */
 431 int
 432 second_parser_pass(__nis_table_mapping_t **table_mapping)
 433 {
 434         __nis_table_mapping_t   *t, *t2;
 435         __nis_table_mapping_t   *t_new = NULL, *tg;
 436         __nis_table_mapping_t   *prev = NULL;
 437         __nis_object_dn_t   *objectDN;
 438         char    *objs, *dom;
 439         char    *objName = NULL;
 440         char    *lasts;
 441         char    *tobj, *alias, *dupalias, *tmp;
 442         char    *myself = "second_parser_pass";
 443         int     i = 0, len;
 444         int     remove_t = 0;
 445         int     add_t = 0;
 446 
 447         prev = NULL;
 448         for (t = *table_mapping; t != NULL; ) {
 449                 /*
 450                  * Temporarily using this field to flag deletion.
 451                  * 0 : don't delete
 452                  * 1 : delete
 453                  * The mapping structure will be deleted in final_parser_pass
 454                  */
 455                 t->isMaster = 0;
 456 
 457                 if (!t->dbId) {
 458                         p_error = parse_bad_map_error;
 459                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 460                             "%s: no dbId field", myself);
 461                         return (1);
 462                 }
 463                 tg = NULL;
 464                 dom = strchr(t->dbId, COMMA_CHAR);
 465                 if (t->objName != NULL) {
 466                         objName = strdup(t->objName);
 467                         if (objName == NULL) {
 468                                 p_error = parse_no_mem_error;
 469                                 logmsg(MSG_NOMEM, LOG_ERR,
 470                                     "%s: Cannot allocate memory for objName",
 471                                     myself);
 472                                 return (1);
 473                         }
 474                         objs = (char *)strtok_r(objName, " ", &lasts);
 475                         /* Get the generic mapping */
 476                         if (dom != NULL) {
 477                                 tg = find_table_mapping(t->dbId, dom - t->dbId,
 478                                     *table_mapping);
 479                         }
 480                 } else {
 481                         objs = NULL;
 482                         if (dom == NULL) {
 483                                 t->objName = s_strndup(t->dbId,
 484                                     strlen(t->dbId));
 485                                 if (!t->objName) {
 486                                         logmsg(MSG_NOMEM, LOG_ERR,
 487                                             "%s: Cannot allocate memory for "
 488                                             "t->objName", myself);
 489                                         objs = NULL;
 490                                         return (2);
 491                                 }
 492                         } else {
 493                                 /* Force relationship for domain specific */
 494 
 495                                 /* Get the generic mapping */
 496                                 tg = find_table_mapping(t->dbId, dom - t->dbId,
 497                                     *table_mapping);
 498                                 if (tg == NULL || tg->objName == NULL) {
 499                                         /* If not found, use dbId for objName */
 500                                         t->objName = s_strndup(t->dbId,
 501                                             strlen(t->dbId));
 502                                         if (t->objName == NULL) {
 503                                                 logmsg(MSG_NOMEM, LOG_ERR,
 504                                     "%s: Cannot allocate memory for t->objName",
 505                                                     myself);
 506                                                 return (2);
 507                                         }
 508                                 } else {
 509                                         dom++;
 510                                         tobj = s_strndup(tg->objName,
 511                                             strlen(tg->objName));
 512                                         if (tobj == NULL) {
 513                                                 logmsg(MSG_NOMEM, LOG_ERR,
 514                                     "%s: Cannot allocate memory for t->objName",
 515                                                     myself);
 516                                                 return (2);
 517                                         }
 518                                         alias = (char *)strtok_r(tobj, " ",
 519                                             &lasts);
 520 
 521                                         /* Loop 'breaks' on errors */
 522                                         while (alias) {
 523                                                 tmp = NULL;
 524                                                 dupalias = s_strndup(alias,
 525                                                     strlen(alias));
 526                                                 if (!dupalias)
 527                                                         break;
 528                                                 if (getfullmapname(&dupalias,
 529                                                     dom)) {
 530                                                         i = 1;
 531                                                         break;
 532                                                 }
 533                                                 if (t->objName == NULL)
 534                                                         t->objName = dupalias;
 535                                                 else {
 536                                                         len = strlen(t->objName)
 537                                                             + strlen(dupalias) +
 538                                                             2;
 539                                                         tmp = s_calloc(1, len);
 540                                                         if (tmp == NULL)
 541                                                                 break;
 542                                                         snprintf(tmp, len,
 543                                                             "%s %s",
 544                                                             t->objName,
 545                                                             dupalias);
 546                                                         free(dupalias);
 547                                                         dupalias = NULL;
 548                                                         free(t->objName);
 549                                                         t->objName = tmp;
 550                                                 }
 551                                                 alias = (char *)strtok_r(NULL,
 552                                                     " ", &lasts);
 553                                         }
 554 
 555                                         if (tobj)
 556                                                 free(tobj);
 557 
 558                                         if (alias ||
 559                                             (objName = s_strdup(t->objName))
 560                                             == NULL) {
 561                                                 if (i)
 562                                                         logmsg(MSG_NOTIMECHECK,
 563                                                             LOG_ERR,
 564                     "%s: getfullmapname failed for %s for domain \"%s\"",
 565                                                             myself, dupalias,
 566                                                             dom);
 567                                                 else {
 568                                                         p_error =
 569                                                             parse_no_mem_error;
 570                                                         logmsg(MSG_NOMEM,
 571                                                             LOG_ERR,
 572                                             "%s: Cannot allocate memory",
 573                                                             myself);
 574                                                 }
 575                                                 if (dupalias)
 576                                                         free(dupalias);
 577                                                 if (t->objName)
 578                                                         free(t->objName);
 579                                                 return (2);
 580 
 581                                         }
 582                                         objs = (char *)strtok_r(objName, " ",
 583                                             &lasts);
 584                                 }
 585                         }
 586                 }
 587 
 588                 if (tg != NULL) {
 589                         if (merge_table_mapping(tg, t)) {
 590                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 591             "Error merging information from the %s to the %s mapping structure",
 592                                     tg->dbId, t->dbId);
 593                                 objs = NULL;
 594                                 if (objName)
 595                                         free(objName);
 596                                 return (1);
 597                         }
 598                 }
 599 
 600                 /*
 601                  * If objName is "map1 map2" then do the second pass.
 602                  * If it is just "map1" however skip the expansion.
 603                  * Also skip it if t->objName is null.
 604                  */
 605                 if (objs && strncasecmp(objs, t->objName,
 606                     strlen(t->objName))) {
 607                         t2 = find_table_mapping(objs, strlen(objs),
 608                             *table_mapping);
 609                         if (t2) {
 610                                 if (merge_table_mapping(t, t2)) {
 611                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 612             "Error merging information from the %s to the %s mapping structure",
 613                                             t->dbId, t2->dbId);
 614                                         objs = NULL;
 615                                         if (objName)
 616                                                 free(objName);
 617                                         return (1);
 618                                 }
 619                                 t->isMaster = 1;
 620                         } else {
 621                                 t_new = new_merged_mapping(objs, t);
 622                                 if (t_new) {
 623                                         t->isMaster = 1;
 624                                         if (prev != NULL)
 625                                                 prev->next = t_new;
 626                                         else
 627                                                 *table_mapping = t_new;
 628                                         prev = t_new;
 629                                         prev->next = t;
 630                                 } else {
 631                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 632                                     "Error creating a new mapping structure %s",
 633                                             objs);
 634                                         objs = NULL;
 635                                         if (objName)
 636                                                 free(objName);
 637                                         return (1);
 638                                 }
 639                         }
 640                         while ((objs = (char *)strtok_r(NULL, " ", &lasts))
 641                             != NULL) {
 642                                 t2 = find_table_mapping(objs, strlen(objs),
 643                                     *table_mapping);
 644                                 if (t2) {
 645                                         if (merge_table_mapping(t, t2)) {
 646                                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 647             "Error merging information from the %s to the %s mapping structure",
 648                                                     t->dbId, t2->dbId);
 649                                                 objs = NULL;
 650                                                 if (objName)
 651                                                         free(objName);
 652                                                 return (1);
 653                                         }
 654                                         t->isMaster = 1;
 655                                 } else {
 656                                         /*
 657                                          * create a new t_map with dbId = objs
 658                                          * and copy t->* into new t_map
 659                                          */
 660                                         t_new = new_merged_mapping(objs, t);
 661                                         if (t_new) {
 662                                                 t->isMaster = 1;
 663                                                 if (prev != NULL)
 664                                                         prev->next = t_new;
 665                                                 else
 666                                                         *table_mapping = t_new;
 667                                                 prev = t_new;
 668                                                 prev->next = t;
 669                                         } else {
 670                                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 671                                     "Error creating a new mapping structure %s",
 672                                                     objs);
 673                                                 objs = NULL;
 674                                                 if (objName)
 675                                                         free(objName);
 676                                                 return (1);
 677                                         }
 678                                 }
 679                         }
 680                 } /* if objs!= NULL */
 681 
 682                 prev = t;
 683                 t = t->next;
 684 
 685                 if (objName) {
 686                         free(objName);
 687                         objName = NULL;
 688                         objs = NULL;
 689                 }
 690         } /* for t = table_mapping loop */
 691         return (0);
 692 }
 693 
 694 __nis_table_mapping_t *
 695 new_merged_mapping(const char *match,
 696         __nis_table_mapping_t   *intbl)
 697 {
 698 
 699         __nis_table_mapping_t   *outtable = NULL;
 700 
 701         outtable = (__nis_table_mapping_t *)
 702             s_calloc(1, sizeof (__nis_table_mapping_t));
 703         if (outtable == NULL)
 704                 return (NULL);
 705         initialize_table_mapping(outtable);
 706         outtable->dbId = s_strndup(match, strlen(match));
 707         if (outtable->dbId == NULL) {
 708                 free_table_mapping(outtable);
 709                 outtable = NULL;
 710                 return (NULL);
 711         }
 712         if (merge_table_mapping(intbl, outtable)) {
 713                 free_table_mapping(outtable);
 714                 outtable = NULL;
 715         }
 716         return (outtable);
 717 }
 718 
 719 /*
 720  * FUNCTION:    final_parser_pass
 721  *
 722  * completes the final expansion of t_map structures linked list.
 723  * all structures will have a non-null objPath as well as a objName
 724  * in the form of "mapname . domainname ." or "splitfieldname .
 725  * domainname .".
 726  *
 727  * RETURN VALUE:        0 on success, -1 on failure, -2 on fatal error.
 728  */
 729 int
 730 final_parser_pass(
 731         __nis_table_mapping_t   **table_mapping,
 732         __yp_domain_context_t   *ypDomains)
 733 {
 734         __nis_table_mapping_t   *t;
 735         __nis_table_mapping_t   *t1, *returned_map;
 736         __nis_table_mapping_t   *prev = NULL;
 737         int                     i;
 738         char                    *myself = "final_parser_pass";
 739         int                     nm;
 740         bool_t                  r;
 741         int                     del_tbl_flag = 0;
 742 
 743         if (ypDomains) {
 744                 if (!ypDomains->numDomains) {
 745                         p_error = parse_internal_error;
 746                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 747                             "%s:No domains specified.", myself);
 748                         return (-1);
 749                 }
 750         } else {
 751                 p_error = parse_internal_error;
 752                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 753                     "%s:No domain structure supplied.", myself);
 754                 return (-1);
 755         }
 756         prev = NULL;
 757 
 758         for (t = *table_mapping; t != NULL; ) {
 759 
 760                 /* Delete if marked for deletion by second_parser_pass */
 761                 if (t->isMaster == 1) {
 762                         if (prev != NULL)
 763                                 prev->next = t->next;
 764                         else
 765                                 *table_mapping = t->next;
 766                         t1 = t;
 767                         t = t->next;
 768                         free_table_mapping(t1);
 769                         continue;
 770                 }
 771 
 772                 if (!t->objName && t->dbId) {
 773                         t->objName = s_strndup(t->dbId, strlen(t->dbId));
 774                         if (!t->objName) {
 775                                 logmsg(MSG_NOMEM, LOG_ERR,
 776                                     "%s:Could not allocate.", myself);
 777                                 return (-1);
 778                         }
 779                 }
 780                 i = ypDomains->numDomains;
 781                 while (i > 0) {
 782                         if (i == 1) {
 783                         /* modify existing table_mapping's */
 784                                 nm = checkfullmapname(t->dbId,
 785                                     ypDomains->domainLabels[0],
 786                                     table_mapping, &returned_map);
 787                                 if (nm == 1) {
 788                                         /* delete this mapping structure */
 789                                         logmsg(MSG_NOTIMECHECK,
 790                                             LOG_WARNING,
 791                                             "Mapping structure %s,%s "
 792                                             "already exists.",
 793                                             t->dbId,
 794                                             ypDomains->domainLabels[0]);
 795                                         if (merge_table_mapping(t,
 796                                             returned_map)) {
 797                                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 798                                                     "Error merging information "
 799                                                     "from the %s to the %s "
 800                                                     "mapping structure.",
 801                                                     t->dbId,
 802                                                     returned_map->dbId);
 803                                                 return (-1);
 804                                         }
 805                                         if (del_tbl_flag == 0)
 806                                                 del_tbl_flag = 1;
 807                                 } else if (nm == -1) {
 808                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 809                         "Error searching for %s,%s structure",
 810                                             t->dbId,
 811                                             ypDomains->domainLabels[0]);
 812                                         return (-1);
 813                                 } else if (nm == 0 || nm == 2) {
 814                                         if ((append_domainContext(&t,
 815                                             ypDomains->domainLabels[0],
 816                                             ypDomains->domains[0])) != 0) {
 817                                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 818                                         "Error appending domainContext %s",
 819                                                     ypDomains->domainLabels[0]);
 820                                                 return (-1);
 821                                         }
 822                                         del_tbl_flag = 0;
 823                                 }
 824                         } else { /* if (i > 1) */
 825                                 /* need to create new table_mapping's */
 826                                 nm = checkfullmapname(t->dbId,
 827                                     ypDomains->domainLabels[i - 1],
 828                                     table_mapping, &returned_map);
 829                                 if (nm == -1) {
 830                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 831                                 "Error searching for %s,%s structure",
 832                                             t->dbId,
 833                                             ypDomains->domainLabels[i - 1]);
 834                                         return (-1);
 835                                 } else if (nm == 0) {
 836                                         t1 = new_merged_mapping(t->dbId, t);
 837                                         /* we clone ourselves */
 838                                         if (t1) {
 839                                                 if ((append_domainContext(&t1,
 840                                         ypDomains->domainLabels[i - 1],
 841                                         ypDomains->domains[i - 1])) != 0) {
 842                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 843                                         "Error appending domainContext %s",
 844                                         ypDomains->domainLabels[i - 1]);
 845                                                         free(t1);
 846                                                         return (-1);
 847                                                 }
 848                                                 if (prev != NULL) {
 849                                                         t1->next = prev->next;
 850                                                         prev->next = t1;
 851                                                         prev = prev->next;
 852                                                 } else {
 853                                                         t1->next =
 854                                                             *table_mapping;
 855                                                         *table_mapping = t1;
 856                                                         prev = t1;
 857                                                 }
 858                                         } else { /* if !t1 */
 859                                                 p_error = parse_internal_error;
 860                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 861                                         "%s:Could not create new table -"
 862                                         " check all instances of %s for errors",
 863                                             myself, t->dbId);
 864                                                 return (-1);
 865                                         }
 866                                 } else if (nm == 1) {
 867                                         logmsg(MSG_NOTIMECHECK, LOG_WARNING,
 868                                 "Mapping structure %s,%s already exists.",
 869                                             t->dbId,
 870                                             ypDomains->domainLabels[i - 1]);
 871                                         /*
 872                                          * We should be deleting this, but can't
 873                                          * really do it here, because we need to
 874                                          * match with the domainLabels[0] case
 875                                          * too. So we will just flag it for now.
 876                                          */
 877                                         if (merge_table_mapping(t,
 878                                             returned_map)) {
 879                                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 880         "Error merging information from the %s to the %s mapping structure.",
 881                                                     t->dbId,
 882                                                     returned_map->dbId);
 883                                                 return (-1);
 884                                         }
 885                                         del_tbl_flag = 1;
 886                                 } else if (nm == 2) {
 887                                         if ((append_domainContext(&t,
 888                                             ypDomains->domainLabels[i - 1],
 889                                             ypDomains->domains[i - 1])) != 0) {
 890                                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
 891                                         "Error appending domainContext %s",
 892                                                 ypDomains->domainLabels[i - 1]);
 893                                                 return (-1);
 894                                         }
 895                                 } /* end of "if (nm == 0)" */
 896                         } /* end of else if (i > 1) */
 897 
 898 
 899                         /*
 900                          * 'merge_table_mapping' only copies unexpanded
 901                          * objectDN values into returned_map. Hence,
 902                          * read.base and write.base in returned_map
 903                          * needs to be expanded.
 904                          */
 905                         if (nm == 1 && returned_map && returned_map->objectDN) {
 906                                 r = make_fqdn(
 907                                     returned_map->objectDN,
 908                                     ypDomains->domains[i - 1]);
 909                                 if (r == TRUE &&
 910                                     returned_map->objectDN->write.base) {
 911                                         r = make_full_dn(
 912                                             &returned_map->objectDN->write.base,
 913                                             ypDomains->domains[i - 1]);
 914                                 }
 915 
 916                                 if (r == FALSE) {
 917                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 918                                             "Error appending domainContext "
 919                                             "%s to %s",
 920                                             ypDomains->domainLabels[i - 1],
 921                                             returned_map->dbId);
 922                                         return (-2);
 923                                 }
 924                         }
 925                         i--;
 926                 } /* end of while i > 0 loop */
 927 
 928                 if (del_tbl_flag == 1) {
 929                         if (prev != NULL) {
 930                                 prev->next = t->next;
 931                                 free_table_mapping(t);
 932                                 t = prev->next;
 933                         } else {
 934                                 *table_mapping = t->next;
 935                                 free_table_mapping(t);
 936                                 t = *table_mapping;
 937                         }
 938                         del_tbl_flag = 0;
 939                 } else {
 940                         prev = t;
 941                         t = t->next;
 942                 }
 943         } /* end of table mapping loop */
 944 
 945         for (t = *table_mapping; t != NULL; t = t->next) {
 946                 if (!t->dbId) {
 947                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 948                             "%s:Fatal error: structure with no dbId found.",
 949                             myself);
 950                         return (-2);
 951                 }
 952                 append_dot(&t->dbId);
 953                 if (!t->objectDN) {
 954                         p_error = parse_internal_error;
 955                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
 956                             "%s:No objectDN for %s.", myself, t->dbId);
 957                         return (-1);
 958                 }
 959         }
 960 
 961         return (0);
 962 }
 963 
 964 /*
 965  * FUNCTION: append_mapping_rule
 966  *
 967  * Appends mapping rules to a table_mapping structure
 968  * with previously existing rules. flag controls whether
 969  * the functions works on the rules From or To LDAP.
 970  *
 971  * RETURN VALUE: 0 on success, >= 1 on failure.
 972  */
 973 
 974 static int
 975 append_mapping_rule(__nis_mapping_rule_t *src_rule,
 976         __nis_table_mapping_t *dst, int flag)
 977 {
 978         __nis_mapping_rule_t **rules = NULL;
 979 
 980         if (flag == 0) {
 981                 if (dst->ruleFromLDAP == NULL) {
 982                         p_error = parse_internal_error;
 983                         return (1);
 984                 }
 985                 rules = (__nis_mapping_rule_t **)
 986                     s_realloc(dst->ruleFromLDAP,
 987                     (dst->numRulesFromLDAP + 1) *
 988                     sizeof (__nis_mapping_rule_t *));
 989                 if (rules == NULL)
 990                         return (2);
 991                 dst->ruleFromLDAP = rules;
 992                 rules[dst->numRulesFromLDAP] = dup_mapping_rule(src_rule);
 993                 if (rules[dst->numRulesFromLDAP] == NULL) {
 994                         p_error = parse_no_mem_error;
 995                         return (2);
 996                 }
 997                 dst->numRulesFromLDAP++;
 998         } else if (flag == 1) {
 999                 if (dst->ruleToLDAP == NULL) {
1000                         p_error = parse_internal_error;
1001                         return (1);
1002                 }
1003                 rules = (__nis_mapping_rule_t **)
1004                     s_realloc(dst->ruleToLDAP,
1005                     (dst->numRulesToLDAP + 1) *
1006                     sizeof (__nis_mapping_rule_t *));
1007                 if (rules == NULL)
1008                         return (2);
1009                 dst->ruleToLDAP = rules;
1010                 rules[dst->numRulesToLDAP] = dup_mapping_rule(src_rule);
1011                 if (rules[dst->numRulesToLDAP] == NULL) {
1012                         p_error = parse_no_mem_error;
1013                         return (2);
1014                 }
1015                 dst->numRulesToLDAP++;
1016         } else
1017                 return (1);
1018 
1019         return (0);
1020 }
1021 
1022 /*
1023  * FUNCTION: check_domain_specific_order
1024  *
1025  * Makes sure that an attribute with explicitly specified
1026  * nisLDAPdomainContext is found before its non-domain
1027  * specific counterpart.
1028  *
1029  * RETURN VALUE: 0 normal exit
1030  *               1 if domain specific attribute found
1031  *                 after non-domain specific one.
1032  *                               -1 some error condition
1033  */
1034 
1035 int
1036 check_domain_specific_order(const char *sd,
1037         config_key      attrib_num,
1038         __nis_table_mapping_t *table_mapping,
1039         __yp_domain_context_t   *ypDomains)
1040 {
1041         __nis_table_mapping_t *t;
1042         char    *myself = "check_domain_specific_order";
1043         char    *type;
1044         char    *dbId = 0;
1045         int     i, len;
1046         int             match = 0;
1047 
1048         if (ypDomains) {
1049                 if (!ypDomains->numDomains) {
1050                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
1051                             "%s:No domains specified.", myself);
1052                         return (-1);
1053                 }
1054         } else {
1055                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1056                     "%s:No domain structure supplied.", myself);
1057                 return (-1);
1058         }
1059 
1060         for (i = 0; i < ypDomains->numDomains; i++) {
1061                 for (t = table_mapping; t != NULL; t = t->next) {
1062                         len = strlen(sd);
1063                         if ((strcasecmp(t->dbId, sd) == 0) && (len ==
1064                             strlen(t->dbId)))
1065                                 /* prevent from matching against itself */
1066                                 continue;
1067                         dbId = s_strndup(t->dbId, strlen(t->dbId));
1068                         if (dbId == NULL) {
1069                                 logmsg(MSG_NOMEM, LOG_ERR,
1070                                     "%s:Memory allocation error.", myself);
1071                                 return (-1);
1072                         }
1073 
1074                         if (getfullmapname(&dbId,
1075                             ypDomains->domainLabels[i])) {
1076                                 logmsg(MSG_NOTIMECHECK, LOG_ERR,
1077                                 "Error getting fully qualified name for %s",
1078                                     dbId);
1079                                 free(dbId);
1080                                 return (-1);
1081                         }
1082                         if ((strcasecmp(dbId, sd) == 0) && (len ==
1083                             strlen(dbId))) {
1084                                 match = 0;
1085                                 switch (attrib_num) {
1086                                         case key_yp_map_flags:
1087                                                 if (t->usedns_flag != 0 ||
1088                                                     t->securemap_flag != 0)
1089                                                         match = 1;
1090                                                 type = YP_MAP_FLAGS;
1091                                                 break;
1092                                         case key_yp_comment_char:
1093                                                 if (t->commentChar !=
1094                                                     DEFAULT_COMMENT_CHAR)
1095                                                         match = 1;
1096                                                 type = YP_COMMENT_CHAR;
1097                                                 break;
1098                                         case key_yp_repeated_field_separators:
1099                                                 if (strcmp(t->separatorStr,
1100                                                     DEFAULT_SEP_STRING) != 0)
1101                                                         match = 1;
1102                                                 type =
1103                                         YP_REPEATED_FIELD_SEPARATORS;
1104                                                 break;
1105                                         case key_yp_name_fields:
1106                                                 if (t->e && t->numColumns)
1107                                                         match = 1;
1108                                                 type = YP_NAME_FIELDS;
1109                                         case key_yp_split_field:
1110                                                 if (t->e && t->numColumns)
1111                                                         match = 1;
1112                                                 type = YP_SPLIT_FIELD;
1113                                                 break;
1114                                         case key_yp_db_id_map:
1115                                                 if (t->objName)
1116                                                         match = 1;
1117                                                 type = YP_DB_ID_MAP;
1118                                                 break;
1119                                         case key_yp_entry_ttl:
1120                                                 if (t->initTtlLo !=
1121                                                     (time_t)NO_VALUE_SET)
1122                                                         match = 1;
1123                                                 type = YP_ENTRY_TTL;
1124                                                 break;
1125                                         case key_yp_ldap_object_dn:
1126                                                 if (t->objectDN)
1127                                                         match = 1;
1128                                                 type = YP_LDAP_OBJECT_DN;
1129                                                 break;
1130                                         case key_nis_to_ldap_map:
1131                                                 if (t->ruleToLDAP)
1132                                                         match = 1;
1133                                                 type = NIS_TO_LDAP_MAP;
1134                                                 break;
1135                                         case key_ldap_to_nis_map:
1136                                                 if (t->ruleFromLDAP)
1137                                                         match = 1;
1138                                                 type = LDAP_TO_NIS_MAP;
1139                                                 break;
1140                                         default:
1141                                                 type = "unknown";
1142                                                 match = 0;
1143                                                 break;
1144                                 }       /* end of switch */
1145                                 if (match) {
1146                                         logmsg(MSG_NOTIMECHECK, LOG_ERR,
1147 "Relative attribute '%s' of type '%s' found before fully qualified one '%s'",
1148                                             t->dbId, type, sd);
1149                                         free(dbId);
1150                                         dbId = NULL;
1151                                         return (1);
1152                                 }
1153                         } /* end of strncasecmp */
1154                         free(dbId);
1155                         dbId = NULL;
1156                 } /* end of t loop */
1157         } /* end of i loop */
1158         if (dbId)
1159                 free(dbId);
1160         dbId = NULL;
1161         return (0);
1162 }
1163 
1164 int
1165 getfullmapname(char **mapname, const char *domainname)
1166 {
1167         char *maps = *mapname;
1168         int maplen = strlen(maps);
1169         int domainlen = strlen(domainname);
1170 
1171         if (!maplen || !domainlen ||
1172             maps[maplen - 1] == PERIOD_CHAR)
1173                 return (1);
1174         else if (strchr(maps, COMMA_CHAR)) {
1175                 /* map already has a domain part, do nothing */
1176                 return (0);
1177         } else {
1178                 append_comma(&maps);
1179                 maplen = strlen(maps);
1180                 maps = realloc(maps, (maplen + domainlen + 1));
1181                 if (maps != NULL) {
1182                         if (strlcat(maps, domainname, (maplen + domainlen + 1))
1183                             >= (maplen + domainlen + 1))
1184                                 return (1);
1185                         *mapname = maps;
1186                         return (0);
1187                 } else
1188                         return (1);
1189         }
1190 }
1191 
1192 /*
1193  * FUNCTION: checkfullmapname
1194  *
1195  * Tries to find out if by appending the table mapping structures
1196  * with each of the provided nisLDAPdomainContexts, an already
1197  * existing fqdn table mapping structure results. That would be the
1198  * case when a full qualified domain specific attribute was present.
1199  *
1200  * Note that per NISLDAPmapping(4) such an attribute MUST be listed
1201  * in the mapping file BEFORE its non-fqdn counterpart.
1202  *
1203  * RETURNS:     0 normal exit, 1 if an existing structure found, -1 for all
1204  * errors, 2 if already fqdn. If returning 1 the existing structure is
1205  * in found_map.
1206  */
1207 
1208 int
1209 checkfullmapname(const char *mapname, const char *domainname,
1210 __nis_table_mapping_t **table_mapping,
1211 __nis_table_mapping_t **found_map)
1212 {
1213         char *map;
1214 
1215         *found_map = NULL;
1216 
1217         /* This function does not alter mapname */
1218 
1219         if (!mapname || !domainname || *table_mapping == NULL)
1220                 return (-1);
1221 
1222         if (strchr(mapname, COMMA_CHAR))
1223                 return (2);
1224 
1225         if ((map = s_strndup(mapname, strlen(mapname))) == 0)
1226                 return (-1);
1227 
1228         if (getfullmapname(&map, domainname)) {
1229                 free(map);
1230                 return (-1);
1231         }
1232 
1233         *found_map = find_table_mapping(map, strlen(map), *table_mapping);
1234         if (*found_map) {
1235                 free(map);
1236                 return (1);
1237         }
1238 
1239         free(map);
1240         return (0);
1241 }
1242 
1243 /*
1244  * FUNCTION:    append_domainContext
1245  *
1246  * Higher level function to append the domains to the appropriate
1247  * fields in a table mapping structure. Calls either getfullmapname()
1248  * or make_full_dn() to do the actual append.
1249  *
1250  * RETURNS: 0 on success, -1 on any error.
1251  */
1252 
1253 int
1254 append_domainContext(__nis_table_mapping_t **table_map,
1255 char   *DomainLabel, char *Domain)
1256 {
1257         __nis_table_mapping_t *tmp_map = *table_map;
1258         char *lasts;
1259         char *tmp_dbId = NULL;
1260         char *id = NULL;
1261         int  domain_specific = 0;
1262         char *myself = "append_domainContext";
1263 
1264         if (!DomainLabel || !Domain || !tmp_map)
1265                 return (-1);
1266         if (tmp_map->dbId == NULL || tmp_map->objName == NULL) {
1267                 p_error = parse_bad_map_error;
1268                 return (-1);
1269         }
1270         tmp_dbId = s_strndup(tmp_map->dbId, strlen(tmp_map->dbId));
1271         if (!tmp_dbId)
1272                 return (-1);
1273         if (strchr(tmp_map->dbId, COMMA_CHAR)) {
1274                 domain_specific = 1;
1275                 id = (char *)strtok_r(tmp_dbId, COMMA_STRING, &lasts);
1276                 if (id)
1277                         id = (char *)strtok_r(NULL, COMMA_STRING, &lasts);
1278                 else {
1279                         free(tmp_dbId);
1280                         return (-1);
1281                 }
1282                 if (!id) {
1283                         free(tmp_dbId);
1284                         return (-1);
1285                 }
1286                 if (strcasecmp(id, DomainLabel)) {
1287                         free(tmp_dbId);
1288                         return (0);
1289                 }
1290         } else {
1291                 if (getfullmapname(&tmp_map->dbId, DomainLabel)) {
1292                         free(tmp_dbId);
1293                         return (-1);
1294                 }
1295                 append_dot(&tmp_map->dbId);
1296         }
1297         if (tmp_dbId)
1298                 free(tmp_dbId);
1299         tmp_dbId = NULL;
1300 
1301         if (getfullmapname(&tmp_map->objName, DomainLabel))
1302                 return (-1);
1303         append_dot(&tmp_map->objName);
1304 
1305         /*
1306          * If domain specific mapping doesn't have objectDN,
1307          * then don't touch. Most probably, pass for the generic mapping
1308          * will handle this by coping over it's own objectDN
1309          */
1310         if (domain_specific && tmp_map->objectDN == NULL)
1311                 return (0);
1312 
1313         if (tmp_map->objectDN == NULL) {
1314                 /* Allocate memory to objectDN */
1315                 tmp_map->objectDN = (__nis_object_dn_t *)
1316                     s_calloc(1, sizeof (__nis_object_dn_t));
1317                 if (tmp_map->objectDN == NULL) {
1318                         logmsg(MSG_NOMEM, LOG_ERR,
1319 "%s: Cannot allocate memory for objectDN",
1320                             myself);
1321                         return (2);
1322                 }
1323                 tmp_map->objectDN->read.base = NULL;
1324                 tmp_map->objectDN->write.base = NULL;
1325                 tmp_map->objectDN->read.attrs = NULL;
1326                 tmp_map->objectDN->write.attrs = NULL;
1327                 tmp_map->objectDN->read.scope = LDAP_SCOPE_ONELEVEL;
1328                 tmp_map->objectDN->write.scope = LDAP_SCOPE_UNKNOWN;
1329         }
1330 
1331         if (!make_fqdn(tmp_map->objectDN, Domain))
1332                 return (-1);
1333         if (tmp_map->objectDN->write.base) {
1334                 if (!make_full_dn(&tmp_map->objectDN->write.base, Domain))
1335                         return (-1);
1336         }
1337 
1338         return (0);
1339 }