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