Print this page
    
5910 libnisdb won't build with modern GCC
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libnisdb/ldap_ruleval.c
          +++ new/usr/src/lib/libnisdb/ldap_ruleval.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  
    | ↓ open down ↓ | 11 lines elided | ↑ open up ↑ | 
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
       22 + * Copyright 2015 Gary Mills
  22   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   24   * Use is subject to license terms.
  24   25   */
  25   26  
  26   27  
  27   28  #include <lber.h>
  28   29  #include <ldap.h>
  29   30  #include <strings.h>
  30   31  
  31   32  #include "nisdb_mt.h"
  32   33  
  33   34  #include "ldap_util.h"
  34   35  #include "ldap_val.h"
  35   36  #include "ldap_attr.h"
  36   37  #include "ldap_ldap.h"
  37   38  #include "ldap_ruleval.h"
  38   39  
  39   40  
  40   41  /*
  41   42   * Free an array of 'count' rule-value elements.
  42   43   */
  43   44  void
  44   45  freeRuleValue(__nis_rule_value_t *rv, int count) {
  45   46          int     n, i, j;
  46   47  
  47   48          if (rv == 0)
  48   49                  return;
  49   50  
  50   51          for (n = 0; n < count; n++) {
  51   52  
  52   53                  if (rv[n].colName != 0) {
  53   54                          for (i = 0; i < rv[n].numColumns; i++) {
  54   55                                  sfree(rv[n].colName[i]);
  55   56                          }
  56   57                          free(rv[n].colName);
  57   58                  }
  58   59                  if (rv[n].colVal != 0) {
  59   60                          for (i = 0; i < rv[n].numColumns; i++) {
  60   61                                  for (j = 0; j < rv[n].colVal[i].numVals; j++) {
  61   62                                          sfree(rv[n].colVal[i].val[j].value);
  62   63                                  }
  63   64                                  if (rv[n].colVal[i].numVals > 0)
  64   65                                          sfree(rv[n].colVal[i].val);
  65   66                          }
  66   67                          free(rv[n].colVal);
  67   68                  }
  68   69  
  69   70                  if (rv[n].attrName != 0) {
  70   71                          for (i = 0; i < rv[n].numAttrs; i++) {
  71   72                                  sfree(rv[n].attrName[i]);
  72   73                          }
  73   74                          free(rv[n].attrName);
  74   75                  }
  75   76                  if (rv[n].attrVal != 0) {
  76   77                          for (i = 0; i < rv[n].numAttrs; i++) {
  77   78                                  for (j = 0; j < rv[n].attrVal[i].numVals;
  78   79                                                  j++) {
  79   80                                          sfree(rv[n].attrVal[i].val[j].value);
  80   81                                  }
  81   82                                  if (rv[n].attrVal[i].numVals > 0)
  82   83                                          sfree(rv[n].attrVal[i].val);
  83   84                          }
  84   85                          free(rv[n].attrVal);
  85   86                  }
  86   87  
  87   88          }
  88   89          sfree(rv);
  89   90  }
  90   91  
  91   92  /*
  92   93   * Return an array of 'count' __nis_rule_value_t elements, initialized
  93   94   * to be copies of 'rvIn' if supplied; empty otherwise.
  94   95   */
  95   96  __nis_rule_value_t *
  96   97  initRuleValue(int count, __nis_rule_value_t *rvIn) {
  97   98          return (growRuleValue(0, count, 0, rvIn));
  98   99  }
  99  100  
 100  101  static const __nis_rule_value_t rvZero = {0};
 101  102  
  
    | ↓ open down ↓ | 70 lines elided | ↑ open up ↑ | 
 102  103  /*
 103  104   * Grow 'old' from 'oldCount' to 'newCount' elements, initialize the
 104  105   * new portion to 'rvIn' (empty if not supplied), and return a pointer
 105  106   * to the result. Following a call to this function, the caller must
 106  107   * refer only to the returned array, not to 'old'.
 107  108   */
 108  109  __nis_rule_value_t *
 109  110  growRuleValue(int oldCount, int newCount, __nis_rule_value_t *old,
 110  111                  __nis_rule_value_t *rvIn) {
 111  112          __nis_rule_value_t      *rv;
 112      -        int                     i, j;
      113 +        int                     i;
 113  114          char                    *myself = "growRuleValue";
 114  115  
 115  116          if (newCount <= 0 || newCount <= oldCount)
 116  117                  return (old);
 117  118  
 118  119          if (oldCount <= 0) {
 119  120                  oldCount = 0;
 120  121                  old = 0;
 121  122          }
 122  123  
 123  124          if (rvIn == 0)
 124  125                  rvIn = (__nis_rule_value_t *)&rvZero;
 125  126  
 126  127          rv = realloc(old, newCount * sizeof (rv[0]));
 127  128          if (rv == 0) {
 128  129                  logmsg(MSG_NOMEM, LOG_ERR,
 129  130                          "%s: realloc(%d ((%d+%d)*%d)) => 0",
 130  131                          myself, (oldCount+newCount) * sizeof (rv[0]),
 131  132                          oldCount, newCount, sizeof (rv[0]));
 132  133                  freeRuleValue(old, oldCount);
 133  134                  return (0);
 134  135          }
 135  136  
 136  137          (void) memset(&rv[oldCount], 0, (newCount-oldCount)*sizeof (rv[0]));
 137  138  
 138  139          for (i = oldCount; i < newCount; i++) {
 139  140                  rv[i].numColumns = rvIn->numColumns;
 140  141                  if (rv[i].numColumns > 0) {
 141  142                          rv[i].colName = cloneName(rvIn->colName,
 142  143                                          rv[i].numColumns);
 143  144                          rv[i].colVal = cloneValue(rvIn->colVal,
 144  145                                          rv[i].numColumns);
 145  146                  }
 146  147                  if (rv[i].numColumns > 0 &&
 147  148                                  (rv[i].colName == 0 || rv[i].colVal == 0)) {
 148  149                          freeRuleValue(rv, i);
 149  150                          return (0);
 150  151                  }
 151  152                  rv[i].numAttrs = rvIn->numAttrs;
 152  153                  rv[i].attrName = cloneName(rvIn->attrName, rv[i].numAttrs);
 153  154                  rv[i].attrVal = cloneValue(rvIn->attrVal, rv[i].numAttrs);
 154  155                  if (rv[i].numAttrs > 0 &&
 155  156                          (rv[i].attrName == 0 || rv[i].attrVal == 0)) {
 156  157                          freeRuleValue(rv, i);
 157  158                          return (0);
 158  159                  }
 159  160          }
 160  161  
 161  162          return (rv);
 162  163  }
 163  164  
 164  165  /*
 165  166   * Merge the source rule-value 's' into the target rule-value 't'.
 166  167   * If successful, unless 's' is a sub-set of 't', 't' will be changed
 167  168   * on exit, and will contain the values from 's' as well.
 168  169   */
 169  170  int
 170  171  mergeRuleValue(__nis_rule_value_t *t, __nis_rule_value_t *s) {
 171  172          int     i, j;
 172  173  
 173  174          if (s == 0)
 174  175                  return (0);
 175  176          else if (t == 0)
 176  177                  return (-1);
 177  178  
 178  179          for (i = 0; i < s->numColumns; i++) {
 179  180                  for (j = 0; j < s->colVal[i].numVals; j++) {
 180  181                          if (addCol2RuleValue(s->colVal[i].type, s->colName[i],
 181  182                                          s->colVal[i].val[j].value,
 182  183                                          s->colVal[i].val[j].length,
 183  184                                          t))
 184  185                                  return (-1);
 185  186                  }
 186  187          }
 187  188  
 188  189          for (i = 0; i < s->numAttrs; i++) {
 189  190                  for (j = 0; j < s->attrVal[i].numVals; j++) {
 190  191                          if (addAttr2RuleValue(s->attrVal[i].type,
 191  192                                          s->attrName[i],
 192  193                                          s->attrVal[i].val[j].value,
 193  194                                          s->attrVal[i].val[j].length,
 194  195                                          t))
 195  196                                  return (-1);
 196  197                  }
 197  198          }
 198  199  
 199  200          return (0);
 200  201  }
 201  202  
 202  203  static int
 203  204  addVal2RuleValue(char *msg, int caseSens, int snipNul, __nis_value_type_t type,
 204  205                  char *name, void *value, int valueLen,
 205  206                  int *numP, char ***inNameP, __nis_value_t **inValP) {
 206  207          int                     i, j, copyLen = valueLen;
 207  208          __nis_single_value_t    *v;
 208  209          char                    **inName = *inNameP;
 209  210          __nis_value_t           *inVal = *inValP;
 210  211          int                     num = *numP;
 211  212          int                     (*comp)(const char *s1, const char *s2);
 212  213          char                    *myself = "addVal2RuleValue";
 213  214  
 214  215          /* Internal function, so assume arguments OK */
 215  216  
 216  217          if (msg == 0)
 217  218                  msg = myself;
 218  219  
 219  220          /* Should we match the 'inName' value case sensitive or not ? */
 220  221          if (caseSens)
 221  222                  comp = strcmp;
 222  223          else
 223  224                  comp = strcasecmp;
 224  225  
 225  226          /*
 226  227           * String-valued NIS+ entries count the concluding NUL in the
 227  228           * length, while LDAP entries don't. In order to support this,
 228  229           * we implement the following for vt_string value types:
 229  230           *
 230  231           * If the last byte of the value isn't a NUL, add one to the
 231  232           * allocated length, so that there always is a NUL after the
 232  233           * value, making it safe to pass to strcmp() etc.
 233  234           *
 234  235           * If 'snipNul' is set (presumably meaning we're inserting a
 235  236           * value derived from a NIS+ entry), and the last byte of the
 236  237           * value already is a NUL, decrement the length to be copied by
 237  238           * one. This (a) doesn't count the NUL in the value length, but
 238  239           * (b) still leaves a NUL following the value.
 239  240           *
 240  241           * In N2L, for all cases we set 'copyLen' to the number of non-0
 241  242           * characters in 'value'.
 242  243           */
 243  244          if (type == vt_string && valueLen > 0) {
 244  245                  char    *charval = value;
 245  246  
 246  247                  if (charval[valueLen-1] != '\0')
 247  248                          valueLen += 1;
 248  249                  else if (yp2ldap || snipNul)
 249  250                          copyLen -= 1;
 250  251          } else if (valueLen == 0) {
 251  252                  /*
 252  253                   * If the 'value' pointer is non-NULL, we create a zero-
 253  254                   * length value with one byte allocated. This takes care
 254  255                   * of empty strings.
 255  256                   */
 256  257                  valueLen += 1;
 257  258          }
 258  259  
 259  260          /* If we already have values for this attribute, add another one */
 260  261          for (i = 0; i < num; i++) {
 261  262                  if ((*comp)(inName[i], name) == 0) {
 262  263  
 263  264                          /*
 264  265                           * Our caller often doesn't know the type of the
 265  266                           * value; this happens because the type (vt_string
 266  267                           * or vt_ber) is determined by the format in the
 267  268                           * rule sets, and we may be invoked as a preparation
 268  269                           * for evaluating the rules. Hence, we only use the
 269  270                           * supplied 'type' if we need to create a value.
 270  271                           * Otherwise, we accept mixed types.
 271  272                           *
 272  273                           * Strings are OK in any case, since we always make
 273  274                           * sure to have a zero byte at the end of any value,
 274  275                           * whatever the type.
 275  276                           */
 276  277  
 277  278                          if (inVal[i].numVals < 0) {
 278  279                                  /*
 279  280                                   * Used to indicate deletion of attribute,
 280  281                                   * so we honor that and don't add a value.
 281  282                                   */
 282  283                                  return (0);
 283  284                          }
 284  285  
 285  286                          /*
 286  287                           * If 'value' is NULL, we should delete, so
 287  288                           * remove any existing values, and set the
 288  289                           * 'numVals' field to -1.
 289  290                           */
 290  291                          if (value == 0) {
 291  292                                  for (j = 0; j < inVal[i].numVals; j++) {
 292  293                                          sfree(inVal[i].val[j].value);
 293  294                                  }
 294  295                                  sfree(inVal[i].val);
 295  296                                  inVal[i].val = 0;
 296  297                                  inVal[i].numVals = -1;
 297  298                                  return (0);
 298  299                          }
 299  300  
 300  301                          /* Is the value a duplicate ? */
 301  302                          for (j = 0; j < inVal[i].numVals; j++) {
 302  303                                  if (copyLen == inVal[i].val[j].length &&
 303  304                                          memcmp(value, inVal[i].val[j].value,
 304  305                                                  copyLen) == 0) {
 305  306                                          break;
 306  307                                  }
 307  308                          }
 308  309                          if (j < inVal[i].numVals)
 309  310                                  return (0);
 310  311  
 311  312                          /* Not a duplicate, so add the name/value pair */
 312  313                          v = realloc(inVal[i].val,
 313  314                                          (inVal[i].numVals+1) *
 314  315                                          sizeof (inVal[i].val[0]));
 315  316                          if (v == 0)
 316  317                                  return (-1);
 317  318                          inVal[i].val = v;
 318  319                          v[inVal[i].numVals].length = copyLen;
 319  320                          v[inVal[i].numVals].value = am(msg, valueLen);
 320  321                          if (v[inVal[i].numVals].value == 0 &&
 321  322                                          value != 0) {
 322  323                                  sfree(v);
 323  324                                  return (-1);
 324  325                          }
 325  326                          memcpy(v[inVal[i].numVals].value, value, copyLen);
 326  327                          inVal[i].numVals++;
 327  328  
 328  329                          return (0);
 329  330                  }
 330  331          }
 331  332  
 332  333          /* No previous value for this attribute */
 333  334  
 334  335          /*
 335  336           * value == 0 means deletion, in which case we create a
 336  337           * __nis_value_t with the numVals field set to -1.
 337  338           */
 338  339          if (value != 0) {
 339  340                  if ((v = am(msg, sizeof (*v))) == 0)
 340  341                          return (-1);
 341  342                  v->length = copyLen;
 342  343                  v->value = am(msg, valueLen);
 343  344                  if (v->value == 0 && value != 0) {
 344  345                          sfree(v);
 345  346                          return (-1);
 346  347                  }
 347  348                  memcpy(v->value, value, copyLen);
 348  349          }
 349  350  
 350  351          inVal = realloc(inVal, (num+1)*sizeof (inVal[0]));
 351  352          if (inVal == 0) {
 352  353                  if (value != 0) {
 353  354                          sfree(v->value);
 354  355                          sfree(v);
 355  356                  }
 356  357                  return (-1);
 357  358          }
 358  359          *inValP = inVal;
 359  360  
 360  361          inName = realloc(inName,
 361  362                  (num+1)*sizeof (inName[0]));
 362  363          if (inName == 0 || (inName[num] =
 363  364                          sdup(msg, T, name)) == 0) {
 364  365                  sfree(v->value);
 365  366                  sfree(v);
 366  367                  return (-1);
 367  368          }
 368  369          *inNameP = inName;
 369  370  
 370  371          inVal[num].type = type;
 371  372          inVal[num].repeat = 0;
 372  373          if (value != 0) {
 373  374                  inVal[num].numVals = 1;
 374  375                  inVal[num].val = v;
 375  376          } else {
 376  377                  inVal[num].numVals = -1;
 377  378                  inVal[num].val = 0;
 378  379          }
 379  380  
 380  381          *numP += 1;
 381  382  
 382  383          return (0);
 383  384  }
 384  385  
 385  386  int
 386  387  addAttr2RuleValue(__nis_value_type_t type, char *name, void *value,
 387  388                  int valueLen, __nis_rule_value_t *rv) {
 388  389          char                    *myself = "addAttr2RuleValue";
 389  390  
 390  391          if (name == 0 || rv == 0)
 391  392                  return (-1);
 392  393  
 393  394          return (addVal2RuleValue(myself, 0, 0, type, name, value, valueLen,
 394  395                                  &rv->numAttrs, &rv->attrName, &rv->attrVal));
 395  396  }
 396  397  
 397  398  int
 398  399  addSAttr2RuleValue(char *name, char *value, __nis_rule_value_t *rv) {
 399  400          return (addAttr2RuleValue(vt_string, name, value, slen(value), rv));
 400  401  }
 401  402  
 402  403  int
 403  404  addCol2RuleValue(__nis_value_type_t type, char *name, void *value,
 404  405                  int valueLen, __nis_rule_value_t *rv) {
 405  406          char *myself = "addCol2RuleValue";
 406  407  
 407  408          if (name == 0 || rv == 0)
 408  409                  return (-1);
 409  410  
 410  411          return (addVal2RuleValue(myself, 1, 1, type, name, value, valueLen,
 411  412                                  &rv->numColumns, &rv->colName, &rv->colVal));
 412  413  }
 413  414  
 414  415  int
 415  416  addSCol2RuleValue(char *name, char *value, __nis_rule_value_t *rv) {
 416  417          return (addCol2RuleValue(vt_string, name, value, slen(value), rv));
 417  418  }
  
    | ↓ open down ↓ | 295 lines elided | ↑ open up ↑ | 
 418  419  
 419  420  /*
 420  421   * Given a table mapping, a NIS+ DB query, and (optionally) an existing
 421  422   * and compatible __nis_rule_value_t, return a new __nis_rule_value_t
 422  423   * with the values from the query added.
 423  424   */
 424  425  __nis_rule_value_t *
 425  426  buildNisPlusRuleValue(__nis_table_mapping_t *t, db_query *q,
 426  427                          __nis_rule_value_t *rv) {
 427  428          int                     i;
 428      -        __nis_single_value_t    *sv;
 429      -        char                    *myself = "buildNisPlusRuleValue";
 430  429  
 431  430          if (t == 0 || q == 0)
 432  431                  return (0);
 433  432  
 434  433          rv = initRuleValue(1, rv);
 435  434          if (rv == 0)
 436  435                  return (0);
 437  436  
 438  437          for (i = 0; i < q->components.components_len; i++) {
 439      -                int     ic;
 440      -                int     iv, v, dup;
 441      -                int     len;
 442  438  
 443  439                  /* Ignore out-of-range column index */
 444  440                  if (q->components.components_val[i].which_index >=
 445  441                                  t->numColumns)
 446  442                          continue;
 447  443  
 448  444                  /*
 449  445                   * Add the query value. A NULL value indicates deletion,
 450  446                   * but addCol2RuleValue() takes care of that for us.
 451  447                   */
 452  448                  if (addCol2RuleValue(vt_string,
 453  449                                  t->column[q->components.components_val[i].
 454  450                                                  which_index],
 455  451                                  q->components.components_val[i].index_value->
 456  452                                          itemvalue.itemvalue_val,
 457  453                                  q->components.components_val[i].index_value->
 458  454                                          itemvalue.itemvalue_len, rv) != 0) {
 459  455                          freeRuleValue(rv, 1);
 460  456                          rv = 0;
 461  457                          break;
 462  458                  }
 463  459          }
 464  460  
 465  461          return (rv);
 466  462  }
 467  463  
 468  464  
 469  465  /*
 470  466   * Given a LHS rule 'rl', return an array containing the item names,
 471  467   * and the number of elements in the array in '*numItems'.
 472  468   *
 473  469   * If there are 'me_match' __nis_mapping_element_t's, we use the
 474  470   * supplied '*rval' (if any) to derive values for the items in
 475  471   * the 'me_match', and add the values thus derived to '*rval' (in
 476  472   * which case the '*rval' pointer will change; the old '*rval'
 477  473   * is deleted).
 478  474   */
 479  475  __nis_mapping_item_t *
 480  476  buildLvalue(__nis_mapping_rlhs_t *rl, __nis_value_t **rval, int *numItems) {
 481  477          __nis_value_t           *val, *r;
 482  478          __nis_mapping_item_t    *item = 0;
 483  479          int                     i, n, ni = 0, nv = 0;
 484  480          int                     repeat = 0;
 485  481  
 486  482          if (rl == 0)
 487  483                  return (0);
 488  484  
 489  485          if (rval != 0) {
 490  486                  r = *rval;
 491  487                  repeat = r->repeat;
 492  488          } else
 493  489                  r = 0;
 494  490  
 495  491          /* If there is more than one element, we concatenate the items */
 496  492          for (i = 0; i < rl->numElements; i++) {
 497  493                  __nis_mapping_element_t *e = &rl->element[i];
 498  494                  __nis_mapping_item_t    *olditem, *tmpitem = 0;
 499  495                  __nis_value_t           **tmp;
 500  496  
 501  497                  switch (e->type) {
 502  498                  case me_item:
 503  499                          tmpitem = cloneItem(&e->element.item);
 504  500                          break;
 505  501                  case me_match:
 506  502                          /*
 507  503                           * Obtain values for the items in the 'me_match'
 508  504                           * element.
 509  505                           */
 510  506                          tmp = matchMappingItem(e->element.match.fmt, r, &nv,
 511  507                                  0, 0);
 512  508                          if (tmp != 0) {
 513  509                                  freeValue(r, 1);
 514  510                                  val = 0;
 515  511                                  for (n = 0; n < nv; n++) {
 516  512                                          r = concatenateValues(val, tmp[n]);
 517  513                                          freeValue(val, 1);
 518  514                                          freeValue(tmp[n], 1);
 519  515                                          val = r;
 520  516                                          if (val == 0) {
 521  517                                                  for (n++; n < nv; n++) {
 522  518                                                          freeValue(tmp[n], 1);
 523  519                                                  }
 524  520                                                  break;
 525  521                                          }
 526  522                                  }
 527  523                                  free(tmp);
 528  524                                  if (rval != 0) {
 529  525                                          if (repeat && val != 0)
 530  526                                                  val->repeat = repeat;
 531  527                                          *rval = val;
 532  528                                  }
 533  529                                  for (n = 0; n < e->element.match.numItems;
 534  530                                                  n++) {
 535  531                                          olditem = item;
 536  532                                          item = concatenateMappingItem(item, ni,
 537  533                                                  &e->element.match.item[n]);
 538  534                                          freeMappingItem(olditem, ni);
 539  535                                          if (item == 0) {
 540  536                                                  ni = 0;
 541  537                                                  break;
 542  538                                          }
 543  539                                          ni++;
 544  540                                  }
 545  541                          }
 546  542                          break;
 547  543                  case me_print:
 548  544                  case me_split:
 549  545                  case me_extract:
 550  546                  default:
 551  547                          /* These shouldn't show up on the LHS; ignore */
 552  548                          break;
 553  549                  }
 554  550  
 555  551                  if (tmpitem != 0) {
 556  552                          olditem = item;
 557  553                          item = concatenateMappingItem(item, ni, tmpitem);
 558  554                          freeMappingItem(olditem, ni);
 559  555                          freeMappingItem(tmpitem, 1);
 560  556                          ni++;
 561  557                          if (item == 0) {
 562  558                                  ni = 0;
 563  559                                  break;
 564  560                          }
 565  561                  }
 566  562          }
 567  563  
 568  564          if (numItems != 0)
 569  565                  *numItems = ni;
 570  566  
 571  567          return (item);
 572  568  }
 573  569  
 574  570  __nis_value_t *
 575  571  buildRvalue(__nis_mapping_rlhs_t *rl, __nis_mapping_item_type_t native,
 576  572                  __nis_rule_value_t *rv, int *stat) {
 577  573          __nis_value_t   *val, *vold = 0, *vnew;
 578  574          int             i;
 579  575          char            *myself = "buildRvalue";
 580  576  
 581  577          if (rl == 0 || rl->numElements <= 0) {
 582  578                  /*
 583  579                   * No RHS indicates deletion, as does a __nis_value_t
 584  580                   * with numVals == -1, so we return such a creature.
 585  581                   */
 586  582                  val = am(myself, sizeof (*val));
 587  583                  if (val != 0) {
 588  584                          val->type = vt_string;
 589  585                          val->numVals = -1;
 590  586                  }
 591  587                  return (val);
 592  588          }
 593  589  
 594  590          /* If there is more than one element, we concatenate the values */
 595  591          for (i = 0; i < rl->numElements; i++) {
 596  592                  vnew = getMappingElement(&rl->element[i], native, rv, stat);
 597  593                  val = concatenateValues(vold, vnew);
 598  594                  freeValue(vnew, 1);
 599  595                  freeValue(vold, 1);
 600  596                  vold = val;
 601  597          }
 602  598          return (val);
 603  599  }
 604  600  
 605  601  /*
 606  602   * Derive values for the LDAP attributes specified by the rule 'r',
 607  603   * and add them to the rule-value 'rv'.
 608  604   *
 609  605   * If 'doAssign' is set, out-of-context assignments are performed,
  
    | ↓ open down ↓ | 158 lines elided | ↑ open up ↑ | 
 610  606   * otherwise not.
 611  607   */
 612  608  __nis_rule_value_t *
 613  609  addLdapRuleValue(__nis_table_mapping_t *t,
 614  610                          __nis_mapping_rule_t *r,
 615  611                          __nis_mapping_item_type_t lnative,
 616  612                          __nis_mapping_item_type_t rnative,
 617  613                          __nis_rule_value_t *rv,
 618  614                          int doAssign, int *stat) {
 619  615          int                     i, j;
 620      -        char                    **new;
 621  616          __nis_value_t           *rval, *lval;
 622      -        __nis_buffer_t          b = {0, 0};
 623  617          __nis_mapping_item_t    *litem;
 624  618          int                     numItems;
 625  619          char                    **dn = 0;
 626  620          int                     numDN = 0;
 627  621          char                    *myself = "addLdapRuleValue";
 628  622  
 629  623  
 630  624          /* Do we have the required values ? */
 631  625          if (rv == 0)
 632  626                  return (0);
 633  627  
 634  628          /*
 635  629           * Establish appropriate search base. For rnative == mit_nisplus,
 636  630           * we're deriving LDAP attribute values from NIS+ columns; in other
 637  631           * words, we're writing to LDAP, and should use the write.base value.
 638  632           */
 639  633          __nisdb_get_tsd()->searchBase = (rnative == mit_nisplus) ?
 640  634                  t->objectDN->write.base : t->objectDN->read.base;
 641  635  
 642  636          /* Set escapeFlag if LHS is "dn" to escape special chars */
 643  637          if (yp2ldap && r->lhs.numElements == 1 &&
 644  638                  r->lhs.element->type == me_item &&
 645  639                  r->lhs.element->element.item.type == mit_ldap &&
 646  640                  strcasecmp(r->lhs.element->element.item.name, "dn") == 0) {
 647  641                          __nisdb_get_tsd()->escapeFlag = '1';
 648  642          }
 649  643  
 650  644          /* Build the RHS value */
 651  645          rval = buildRvalue(&r->rhs, rnative, rv, stat);
 652  646  
 653  647          /* Reset escapeFlag */
 654  648          __nisdb_get_tsd()->escapeFlag = '\0';
 655  649  
 656  650          if (rval == 0)
 657  651                  return (rv);
 658  652  
 659  653          /*
 660  654           * Special case: If we got no value for the RHS (presumably because
 661  655           * we're missing one or more item values), we don't produce an lval.
 662  656           * Note that this isn't the same thing as an empty value, which we
 663  657           * faithfully try to transmit to LDAP.
 664  658           */
 665  659          if (rval->numVals == 1 && rval->val[0].value == 0) {
 666  660                  freeValue(rval, 1);
 667  661                  return (rv);
 668  662          }
 669  663  
 670  664          /* Obtain the LHS item names */
 671  665          litem = buildLvalue(&r->lhs, &rval, &numItems);
 672  666          if (litem == 0) {
 673  667                  freeValue(rval, 1);
 674  668                  return (rv);
 675  669          }
 676  670  
 677  671          /* Get string representations of the LHS item names */
 678  672          lval = 0;
 679  673          for (i = 0; i < numItems; i++) {
 680  674                  __nis_value_t   *tmpval, *old;
 681  675  
 682  676                  tmpval = getMappingItem(&litem[i], lnative, 0, 0, NULL);
 683  677  
 684  678                  /*
 685  679                   * If the LHS item is out-of-context, we do the
 686  680                   * assignment right here.
 687  681                   */
 688  682                  if (doAssign && litem[i].type == mit_ldap &&
 689  683                                  litem[i].searchSpec.triple.scope !=
 690  684                                          LDAP_SCOPE_UNKNOWN &&
 691  685                                  slen(litem[i].searchSpec.triple.base) > 0 &&
 692  686                                  (slen(litem[i].searchSpec.triple.attrs) > 0 ||
 693  687                                  litem[i].searchSpec.triple.element != 0)) {
 694  688                          int     stat;
 695  689  
 696  690                          if (dn == 0)
 697  691                                  dn = findDNs(myself, rv, 1,
 698  692                                          t->objectDN->write.base,
 699  693                                          &numDN);
 700  694  
 701  695                          stat = storeLDAP(&litem[i], i, numItems, rval,
 702  696                                  t->objectDN, dn, numDN);
 703  697                          if (stat != LDAP_SUCCESS) {
 704  698                                  char    *iname = "<unknown>";
 705  699  
 706  700                                  if (tmpval != 0 &&
 707  701                                                  tmpval->numVals == 1)
 708  702                                          iname = tmpval->val[0].value;
 709  703                                  logmsg(MSG_NOTIMECHECK, LOG_ERR,
 710  704                                          "%s: LDAP store \"%s\": %s",
 711  705                                          myself, iname,
 712  706                                          ldap_err2string(stat));
 713  707                          }
 714  708  
 715  709                          freeValue(tmpval, 1);
 716  710                          continue;
 717  711                  }
 718  712  
 719  713                  old = lval;
 720  714                  lval = concatenateValues(old, tmpval);
 721  715                  freeValue(tmpval, 1);
 722  716                  freeValue(old, 1);
 723  717          }
 724  718  
 725  719          /* Don't need the LHS items themselves anymore */
 726  720          freeMappingItem(litem, numItems);
 727  721  
 728  722          /*
 729  723           * If we don't have an 'lval' (probably because all litem[i]:s
 730  724           * were out-of-context assignments), we're done.
 731  725           */
 732  726          if (lval == 0 || lval->numVals <= 0) {
 733  727                  freeValue(lval, 1);
 734  728                  freeValue(rval, 1);
 735  729                  return (rv);
 736  730          }
 737  731  
  
    | ↓ open down ↓ | 105 lines elided | ↑ open up ↑ | 
 738  732          for (i = 0, j = 0; i < lval->numVals; i++) {
 739  733                  /* Special case: rval->numVals < 0 means deletion */
 740  734                  if (rval->numVals < 0) {
 741  735                          (void) addAttr2RuleValue(rval->type,
 742  736                                  lval->val[i].value, 0, 0, rv);
 743  737                          continue;
 744  738                  }
 745  739                  /* If we're out of values, repeat the last one */
 746  740                  if (j >= rval->numVals)
 747  741                          j = (rval->numVals > 0) ? rval->numVals-1 : 0;
 748      -                for (0; j < rval->numVals; j++) {
      742 +                for (; j < rval->numVals; j++) {
 749  743                          /*
 750  744                           * If this is the 'dn', and the value ends in a
 751  745                           * comma, append the appropriate search base.
 752  746                           */
 753  747                          if (strcasecmp("dn", lval->val[i].value) == 0 &&
 754  748                                          lastChar(&rval->val[j]) == ',' &&
 755  749                                          t->objectDN->write.scope !=
 756  750                                                  LDAP_SCOPE_UNKNOWN) {
 757  751                                  void    *nval;
 758  752                                  int     nlen = -1;
 759  753  
 760  754                                  nval = appendString2SingleVal(
 761  755                                          t->objectDN->write.base, &rval->val[j],
 762  756                                          &nlen);
 763  757                                  if (nval != 0 && nlen >= 0) {
 764  758                                          sfree(rval->val[j].value);
 765  759                                          rval->val[j].value = nval;
 766  760                                          rval->val[j].length = nlen;
 767  761                                  }
 768  762                          }
 769  763                          (void) addAttr2RuleValue(rval->type,
 770  764                                  lval->val[i].value, rval->val[j].value,
 771  765                                  rval->val[j].length, rv);
 772  766                          /*
 773  767                           * If the lval is multi-valued, go on to the
 774  768                           * other values; otherwise, quit (but increment
 775  769                           * the 'rval' value index).
 776  770                           */
 777  771                          if (!lval->repeat) {
 778  772                                  j++;
 779  773                                  break;
 780  774                          }
 781  775                  }
 782  776          }
 783  777  
 784  778          /* Clean up */
 785  779          freeValue(lval, 1);
 786  780          freeValue(rval, 1);
 787  781  
 788  782          return (rv);
 789  783  }
 790  784  
 791  785  /*
 792  786   * Remove the indicated attribute, and any values for it, from the
 793  787   * rule-value.
 794  788   */
 795  789  void
 796  790  delAttrFromRuleValue(__nis_rule_value_t *rv, char *attrName) {
 797  791          int     i;
 798  792  
 799  793          if (rv == 0 || attrName == 0)
 800  794                  return;
 801  795  
 802  796          for (i = 0; i < rv->numAttrs; i++) {
 803  797                  if (strcasecmp(attrName, rv->attrName[i]) == 0) {
 804  798                          int     j;
 805  799  
 806  800                          for (j = 0; j < rv->attrVal[i].numVals; j++)
 807  801                                  sfree(rv->attrVal[i].val[j].value);
 808  802                          if (rv->attrVal[i].numVals > 0)
 809  803                                  sfree(rv->attrVal[i].val);
 810  804  
 811  805                          sfree(rv->attrName[i]);
 812  806  
 813  807                          /* Move up the rest of the attribute names/values */
 814  808                          for (j = i+1; j < rv->numAttrs; j++) {
 815  809                                  rv->attrName[j-1] = rv->attrName[j];
 816  810                                  rv->attrVal[j-1] = rv->attrVal[j];
 817  811                          }
 818  812  
 819  813                          rv->numAttrs -= 1;
 820  814  
 821  815                          break;
 822  816                  }
 823  817          }
 824  818  }
 825  819  
 826  820  /*
 827  821   * Remove the indicated column, and any values for it, from the
 828  822   * rule-value.
 829  823   */
 830  824  void
 831  825  delColFromRuleValue(__nis_rule_value_t *rv, char *colName) {
 832  826          int     i;
 833  827  
 834  828          if (rv == 0 || colName == 0)
 835  829                  return;
 836  830  
 837  831          for (i = 0; i < rv->numColumns; i++) {
 838  832                  if (strcmp(colName, rv->colName[i]) == 0) {
 839  833                          int     j;
 840  834  
 841  835                          for (j = 0; j < rv->colVal[i].numVals; j++)
 842  836                                  sfree(rv->colVal[i].val[j].value);
 843  837                          if (rv->colVal[i].numVals > 0)
 844  838                                  sfree(rv->colVal[i].val);
 845  839  
 846  840                          sfree(rv->colName[i]);
 847  841  
 848  842                          /* Move up the rest of the column names/values */
 849  843                          for (j = i+1; j < rv->numColumns; j++) {
 850  844                                  rv->colName[j-1] = rv->colName[j];
 851  845                                  rv->colVal[j-1] = rv->colVal[j];
 852  846                          }
 853  847  
 854  848                          rv->numColumns -= 1;
 855  849  
 856  850                          break;
 857  851                  }
 858  852          }
 859  853  }
 860  854  
 861  855  /*
 862  856   * Add the write-mode object classes specified by 'objClassAttrs' to the
 863  857   * rule-value 'rv'.
 864  858   * If there's an error, 'rv' is deleted, and NULL returned.
 865  859   */
 866  860  __nis_rule_value_t *
 867  861  addObjectClasses(__nis_rule_value_t *rv, char *objClassAttrs) {
 868  862          char    *filter = 0, **fc = 0;
 869  863          int     i, nfc = 0;
 870  864  
 871  865          /*
 872  866           * Expect to only use this for existing rule-values, so rv == 0 is
 873  867           * an error.
 874  868           */
 875  869          if (rv == 0)
 876  870                  return (0);
 877  871  
 878  872          /*
 879  873           * If 'objClassAttrs' is NULL, we trivially have nothing to do.
 880  874           * Assume the caller knows what it's doing, and return success.
 881  875           */
 882  876          if (objClassAttrs == 0)
 883  877                  return (rv);
 884  878  
 885  879          /*
 886  880           * Make an AND-filter of the object classes, and split into
 887  881           * components. (Yes, this is a bit round-about, but leverages
 888  882           * existing functions.)
 889  883           */
 890  884          filter = makeFilter(objClassAttrs);
 891  885          if (filter == 0) {
 892  886                  freeRuleValue(rv, 1);
 893  887                  return (0);
 894  888          }
 895  889  
 896  890          fc = makeFilterComp(filter, &nfc);
 897  891          if (fc == 0 || nfc <= 0) {
 898  892                  free(filter);
 899  893                  freeRuleValue(rv, 1);
 900  894                  return (0);
 901  895          }
 902  896  
 903  897          /* Add the objectClass attributes to the rule-value */
 904  898          for (i = 0; i < nfc; i++) {
 905  899                  char    *name, *value;
 906  900  
 907  901                  name = fc[i];
 908  902                  /* Skip if not of the "name=value" form */
 909  903                  if ((value = strchr(name, '=')) == 0)
 910  904                          continue;
 911  905  
 912  906                  *value = '\0';
 913  907                  value++;
 914  908  
 915  909                  /* Skip if the attribute name isn't "objectClass" */
 916  910                  if (strcasecmp("objectClass", name) != 0)
 917  911                          continue;
 918  912  
 919  913                  if (addSAttr2RuleValue(name, value, rv) != 0) {
 920  914                          free(filter);
 921  915                          freeFilterComp(fc, nfc);
 922  916                          freeRuleValue(rv, 1);
 923  917                          return (0);
 924  918                  }
 925  919          }
 926  920  
 927  921          free(filter);
 928  922          freeFilterComp(fc, nfc);
 929  923  
 930  924          return (rv);
 931  925  }
 932  926  
 933  927  
 934  928  static char *
 935  929  valString(__nis_value_t *val) {
 936  930          int     i;
 937  931  
 938  932          if (val == 0 || val->type != vt_string)
 939  933                  return (0);
 940  934  
 941  935          for (i = 0; i < val->numVals; i++) {
 942  936                  /* Look for a non-NULL, non-zero length value */
 943  937                  if (val->val[i].value != 0 && val->val[i].length > 0) {
 944  938                          char    *v = val->val[i].value;
 945  939  
 946  940                          /*
 947  941                           * Check that there's a NUL at the end. True,
 948  942                           * if there isn't, we may be looking beyond
 949  943                           * allocated memory. However, we would have done
 950  944                           * so in any case when the supposed string was
 951  945                           * traversed (printed, etc.), very possibly by
 952  946                           * a lot more than one byte. So, it's better to
 953  947                           * take a small risk here than a large one later.
 954  948                           */
 955  949                          if (v[val->val[i].length-1] == '\0' ||
 956  950                                          v[val->val[i].length] == '\0')
 957  951                                  return (v);
 958  952                  }
 959  953          }
 960  954  
 961  955          return (0);
 962  956  }
 963  957  
 964  958  char *
 965  959  findVal(char *name, __nis_rule_value_t *rv, __nis_mapping_item_type_t type) {
 966  960          int     i;
 967  961  
 968  962          if (type == mit_nisplus) {
 969  963                  for (i = 0; i < rv->numColumns; i++) {
 970  964                          if (rv->colName[i] == 0)
 971  965                                  continue;
 972  966                          if (strcmp(name, rv->colName[i]) == 0) {
 973  967                                  return (valString(&rv->colVal[i]));
 974  968                          }
 975  969                  }
 976  970          } else if (type == mit_ldap) {
 977  971                  for (i = 0; i < rv->numAttrs; i++) {
 978  972                          if (rv->attrName[i] == 0)
 979  973                                  continue;
 980  974                          if (strcasecmp(name, rv->attrName[i]) == 0) {
 981  975                                  return (valString(&rv->attrVal[i]));
 982  976                          }
 983  977                  }
 984  978          }
 985  979  
 986  980          return (0);
 987  981  }
 988  982  
 989  983  static char     *norv = "<NIL>";
 990  984  static char     *unknown = "<unknown>";
 991  985  
 992  986  /*
 993  987   * Attempt to derive a string identifying the rule-value 'rv'. The
 994  988   * returned string is a pointer, either into 'rv', or to static
 995  989   * storage, and must not be freed.
 996  990   */
 997  991  char *
 998  992  rvId(__nis_rule_value_t *rv, __nis_mapping_item_type_t type) {
 999  993          char    *v;
1000  994  
1001  995          if (rv == 0)
1002  996                  return (norv);
1003  997  
1004  998          if (rv->numColumns > 0 && type == mit_nisplus) {
1005  999                  /*
1006 1000                   * Look for a column called "cname" or "name".
1007 1001                   * If that fails, try "key" or "alias".
1008 1002                   */
1009 1003                  if ((v = findVal("cname", rv, type)) != 0)
1010 1004                          return (v);
1011 1005                  else if ((v = findVal("name", rv, type)) != 0)
1012 1006                          return (v);
1013 1007                  else if ((v = findVal("key", rv, type)) != 0)
1014 1008                          return (v);
1015 1009                  else if ((v = findVal("alias", rv, type)) != 0)
1016 1010                          return (v);
1017 1011          } else if (rv->numAttrs > 0 && type == mit_ldap) {
1018 1012                  /*
1019 1013                   * Look for "dn", or "cn".
1020 1014                   */
1021 1015                  if ((v = findVal("dn", rv, type)) != 0)
1022 1016                          return (v);
1023 1017                  else if ((v = findVal("cn", rv, type)) != 0)
1024 1018                          return (v);
1025 1019          }
1026 1020  
1027 1021          return (unknown);
1028 1022  }
1029 1023  
1030 1024  /*
1031 1025   * Merge the rule-values with the same DN into one. Each rule-value
1032 1026   * in the returned array will have unique 'dn'. On entry, *numVals
1033 1027   * contains the number of rule-values in 'rv'. On exit, it contains
1034 1028   * the number of rule-values in the returned array or -1 on error.
1035 1029   */
1036 1030  __nis_rule_value_t *
1037 1031  mergeRuleValueWithSameDN(__nis_rule_value_t *rv, int *numVals) {
1038 1032          __nis_rule_value_t      *rvq = 0;
1039 1033          char                    *dn, *odn;
1040 1034          int                     count = 0;
1041 1035          int                     i, j;
1042 1036  
1043 1037          if (numVals == 0)
1044 1038                  return (0);
1045 1039  
1046 1040          for (i = 0; i < *numVals; i++) {
1047 1041                  if ((dn = findVal("dn", &rv[i], mit_ldap)) != 0) {
1048 1042                          for (j = 0; j < count; j++) {
1049 1043                                  if ((odn = findVal("dn", &rvq[j],
1050 1044                                                  mit_ldap)) != 0) {
1051 1045                                          /* case sensitive compare */
1052 1046                                          if (strcmp(dn, odn) != 0)
1053 1047                                                  continue;
1054 1048                                          if (mergeRuleValue(&rvq[j],
1055 1049                                                          &rv[i]) == -1) {
1056 1050                                                  freeRuleValue(rvq, count);
1057 1051                                                  *numVals = -1;
1058 1052                                                  return (0);
1059 1053                                          }
1060 1054                                          break;
1061 1055                                  } else {
1062 1056                                          freeRuleValue(rvq, count);
1063 1057                                          *numVals = -1;
1064 1058                                          return (0);
1065 1059                                  }
1066 1060                          }
1067 1061                          /* if no match, then add it to the rulevalue array */
1068 1062                          if (j == count) {
1069 1063                                  rvq = growRuleValue(count, count + 1, rvq,
1070 1064                                                                          &rv[i]);
1071 1065                                  if (rvq == 0) {
1072 1066                                          *numVals = -1;
1073 1067                                          return (0);
1074 1068                                  }
1075 1069                                  count++;
1076 1070                          }
1077 1071                  }
1078 1072          }
1079 1073  
1080 1074          *numVals = count;
1081 1075          return (rvq);
1082 1076  }
  
    | ↓ open down ↓ | 324 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX