ldap_ruleval.c revision 36e852a172cba914383d7341c988128b2c667fbd
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <lber.h>
#include <ldap.h>
#include <strings.h>
#include "nisdb_mt.h"
#include "ldap_util.h"
#include "ldap_val.h"
#include "ldap_attr.h"
#include "ldap_ldap.h"
#include "ldap_ruleval.h"
/*
* Free an array of 'count' rule-value elements.
*/
void
int n, i, j;
if (rv == 0)
return;
for (n = 0; n < count; n++) {
for (i = 0; i < rv[n].numColumns; i++) {
}
}
for (i = 0; i < rv[n].numColumns; i++) {
}
}
}
}
}
j++) {
}
}
}
}
}
/*
* Return an array of 'count' __nis_rule_value_t elements, initialized
* to be copies of 'rvIn' if supplied; empty otherwise.
*/
}
static const __nis_rule_value_t rvZero = {0};
/*
* Grow 'old' from 'oldCount' to 'newCount' elements, initialize the
* new portion to 'rvIn' (empty if not supplied), and return a pointer
* to the result. Following a call to this function, the caller must
* refer only to the returned array, not to 'old'.
*/
int i, j;
char *myself = "growRuleValue";
return (old);
if (oldCount <= 0) {
oldCount = 0;
old = 0;
}
if (rvIn == 0)
if (rv == 0) {
"%s: realloc(%d ((%d+%d)*%d)) => 0",
return (0);
}
if (rv[i].numColumns > 0) {
rv[i].numColumns);
rv[i].numColumns);
}
if (rv[i].numColumns > 0 &&
freeRuleValue(rv, i);
return (0);
}
freeRuleValue(rv, i);
return (0);
}
}
return (rv);
}
/*
* Merge the source rule-value 's' into the target rule-value 't'.
* If successful, unless 's' is a sub-set of 't', 't' will be changed
* on exit, and will contain the values from 's' as well.
*/
int
int i, j;
if (s == 0)
return (0);
else if (t == 0)
return (-1);
for (i = 0; i < s->numColumns; i++) {
t))
return (-1);
}
}
for (i = 0; i < s->numAttrs; i++) {
s->attrName[i],
t))
return (-1);
}
}
return (0);
}
static int
char *myself = "addVal2RuleValue";
/* Internal function, so assume arguments OK */
if (msg == 0)
/* Should we match the 'inName' value case sensitive or not ? */
if (caseSens)
else
comp = strcasecmp;
/*
* String-valued NIS+ entries count the concluding NUL in the
* length, while LDAP entries don't. In order to support this,
* we implement the following for vt_string value types:
*
* If the last byte of the value isn't a NUL, add one to the
* allocated length, so that there always is a NUL after the
* value, making it safe to pass to strcmp() etc.
*
* If 'snipNul' is set (presumably meaning we're inserting a
* value derived from a NIS+ entry), and the last byte of the
* value already is a NUL, decrement the length to be copied by
* one. This (a) doesn't count the NUL in the value length, but
* (b) still leaves a NUL following the value.
*
* In N2L, for all cases we set 'copyLen' to the number of non-0
* characters in 'value'.
*/
valueLen += 1;
copyLen -= 1;
} else if (valueLen == 0) {
/*
* If the 'value' pointer is non-NULL, we create a zero-
* length value with one byte allocated. This takes care
* of empty strings.
*/
valueLen += 1;
}
/* If we already have values for this attribute, add another one */
for (i = 0; i < num; i++) {
/*
* Our caller often doesn't know the type of the
* value; this happens because the type (vt_string
* or vt_ber) is determined by the format in the
* rule sets, and we may be invoked as a preparation
* for evaluating the rules. Hence, we only use the
* supplied 'type' if we need to create a value.
* Otherwise, we accept mixed types.
*
* Strings are OK in any case, since we always make
* sure to have a zero byte at the end of any value,
* whatever the type.
*/
/*
* Used to indicate deletion of attribute,
* so we honor that and don't add a value.
*/
return (0);
}
/*
* If 'value' is NULL, we should delete, so
* remove any existing values, and set the
* 'numVals' field to -1.
*/
if (value == 0) {
}
return (0);
}
/* Is the value a duplicate ? */
copyLen) == 0) {
break;
}
}
return (0);
if (v == 0)
return (-1);
value != 0) {
sfree(v);
return (-1);
}
return (0);
}
}
/* No previous value for this attribute */
/*
* value == 0 means deletion, in which case we create a
* __nis_value_t with the numVals field set to -1.
*/
if (value != 0) {
return (-1);
sfree(v);
return (-1);
}
}
if (inVal == 0) {
if (value != 0) {
sfree(v);
}
return (-1);
}
sfree(v);
return (-1);
}
if (value != 0) {
} else {
}
*numP += 1;
return (0);
}
int
char *myself = "addAttr2RuleValue";
return (-1);
}
int
}
int
char *myself = "addCol2RuleValue";
return (-1);
}
int
}
/*
* Given a table mapping, a NIS+ DB query, and (optionally) an existing
* and compatible __nis_rule_value_t, return a new __nis_rule_value_t
* with the values from the query added.
*/
__nis_rule_value_t *rv) {
int i;
char *myself = "buildNisPlusRuleValue";
if (t == 0 || q == 0)
return (0);
if (rv == 0)
return (0);
for (i = 0; i < q->components.components_len; i++) {
int ic;
int len;
/* Ignore out-of-range column index */
t->numColumns)
continue;
/*
* Add the query value. A NULL value indicates deletion,
* but addCol2RuleValue() takes care of that for us.
*/
rv = 0;
break;
}
}
return (rv);
}
/*
* Given a LHS rule 'rl', return an array containing the item names,
* and the number of elements in the array in '*numItems'.
*
* If there are 'me_match' __nis_mapping_element_t's, we use the
* supplied '*rval' (if any) to derive values for the items in
* the 'me_match', and add the values thus derived to '*rval' (in
* which case the '*rval' pointer will change; the old '*rval'
* is deleted).
*/
__nis_value_t *val, *r;
__nis_mapping_item_t *item = 0;
int repeat = 0;
if (rl == 0)
return (0);
if (rval != 0) {
r = *rval;
} else
r = 0;
/* If there is more than one element, we concatenate the items */
for (i = 0; i < rl->numElements; i++) {
__nis_value_t **tmp;
switch (e->type) {
case me_item:
break;
case me_match:
/*
* Obtain values for the items in the 'me_match'
* element.
*/
0, 0);
if (tmp != 0) {
freeValue(r, 1);
val = 0;
for (n = 0; n < nv; n++) {
val = r;
if (val == 0) {
for (n++; n < nv; n++) {
}
break;
}
}
if (rval != 0) {
}
n++) {
if (item == 0) {
ni = 0;
break;
}
ni++;
}
}
break;
case me_print:
case me_split:
case me_extract:
default:
/* These shouldn't show up on the LHS; ignore */
break;
}
if (tmpitem != 0) {
ni++;
if (item == 0) {
ni = 0;
break;
}
}
}
if (numItems != 0)
return (item);
}
int i;
char *myself = "buildRvalue";
/*
* No RHS indicates deletion, as does a __nis_value_t
* with numVals == -1, so we return such a creature.
*/
if (val != 0) {
}
return (val);
}
/* If there is more than one element, we concatenate the values */
for (i = 0; i < rl->numElements; i++) {
}
return (val);
}
/*
* Derive values for the LDAP attributes specified by the rule 'r',
* and add them to the rule-value 'rv'.
*
* If 'doAssign' is set, out-of-context assignments are performed,
* otherwise not.
*/
int i, j;
char **new;
__nis_buffer_t b = {0, 0};
int numItems;
char **dn = 0;
int numDN = 0;
char *myself = "addLdapRuleValue";
/* Do we have the required values ? */
if (rv == 0)
return (0);
/*
* Establish appropriate search base. For rnative == mit_nisplus,
* we're deriving LDAP attribute values from NIS+ columns; in other
* words, we're writing to LDAP, and should use the write.base value.
*/
/* Set escapeFlag if LHS is "dn" to escape special chars */
}
/* Build the RHS value */
/* Reset escapeFlag */
if (rval == 0)
return (rv);
/*
* Special case: If we got no value for the RHS (presumably because
* we're missing one or more item values), we don't produce an lval.
* Note that this isn't the same thing as an empty value, which we
* faithfully try to transmit to LDAP.
*/
return (rv);
}
/* Obtain the LHS item names */
if (litem == 0) {
return (rv);
}
/* Get string representations of the LHS item names */
lval = 0;
for (i = 0; i < numItems; i++) {
/*
* If the LHS item is out-of-context, we do the
* assignment right here.
*/
int stat;
if (dn == 0)
&numDN);
if (stat != LDAP_SUCCESS) {
char *iname = "<unknown>";
if (tmpval != 0 &&
"%s: LDAP store \"%s\": %s",
}
continue;
}
}
/* Don't need the LHS items themselves anymore */
/*
* If we don't have an 'lval' (probably because all litem[i]:s
* were out-of-context assignments), we're done.
*/
return (rv);
}
/* Special case: rval->numVals < 0 means deletion */
continue;
}
/* If we're out of values, repeat the last one */
/*
* If this is the 'dn', and the value ends in a
* comma, append the appropriate search base.
*/
void *nval;
int nlen = -1;
&nlen);
}
}
/*
* If the lval is multi-valued, go on to the
* other values; otherwise, quit (but increment
* the 'rval' value index).
*/
j++;
break;
}
}
}
/* Clean up */
return (rv);
}
/*
* Remove the indicated attribute, and any values for it, from the
* rule-value.
*/
void
int i;
return;
int j;
}
break;
}
}
}
/*
* Remove the indicated column, and any values for it, from the
* rule-value.
*/
void
int i;
return;
for (i = 0; i < rv->numColumns; i++) {
int j;
}
break;
}
}
}
/*
* Add the write-mode object classes specified by 'objClassAttrs' to the
* rule-value 'rv'.
* If there's an error, 'rv' is deleted, and NULL returned.
*/
int i, nfc = 0;
/*
* Expect to only use this for existing rule-values, so rv == 0 is
* an error.
*/
if (rv == 0)
return (0);
/*
* If 'objClassAttrs' is NULL, we trivially have nothing to do.
* Assume the caller knows what it's doing, and return success.
*/
if (objClassAttrs == 0)
return (rv);
/*
* Make an AND-filter of the object classes, and split into
* components. (Yes, this is a bit round-about, but leverages
* existing functions.)
*/
if (filter == 0) {
return (0);
}
return (0);
}
/* Add the objectClass attributes to the rule-value */
for (i = 0; i < nfc; i++) {
/* Skip if not of the "name=value" form */
continue;
*value = '\0';
value++;
/* Skip if the attribute name isn't "objectClass" */
continue;
return (0);
}
}
return (rv);
}
static char *
int i;
return (0);
/* Look for a non-NULL, non-zero length value */
/*
* Check that there's a NUL at the end. True,
* if there isn't, we may be looking beyond
* allocated memory. However, we would have done
* so in any case when the supposed string was
* traversed (printed, etc.), very possibly by
* a lot more than one byte. So, it's better to
* take a small risk here than a large one later.
*/
return (v);
}
}
return (0);
}
char *
int i;
if (type == mit_nisplus) {
for (i = 0; i < rv->numColumns; i++) {
continue;
}
}
continue;
}
}
}
return (0);
}
static char *norv = "<NIL>";
static char *unknown = "<unknown>";
/*
* Attempt to derive a string identifying the rule-value 'rv'. The
* returned string is a pointer, either into 'rv', or to static
* storage, and must not be freed.
*/
char *
char *v;
if (rv == 0)
return (norv);
/*
* Look for a column called "cname" or "name".
* If that fails, try "key" or "alias".
*/
return (v);
return (v);
return (v);
return (v);
/*
* Look for "dn", or "cn".
*/
return (v);
return (v);
}
return (unknown);
}
/*
* Merge the rule-values with the same DN into one. Each rule-value
* in the returned array will have unique 'dn'. On entry, *numVals
* contains the number of rule-values in 'rv'. On exit, it contains
* the number of rule-values in the returned array or -1 on error.
*/
__nis_rule_value_t *rvq = 0;
int count = 0;
int i, j;
if (numVals == 0)
return (0);
for (i = 0; i < *numVals; i++) {
for (j = 0; j < count; j++) {
mit_ldap)) != 0) {
/* case sensitive compare */
continue;
if (mergeRuleValue(&rvq[j],
&rv[i]) == -1) {
*numVals = -1;
return (0);
}
break;
} else {
*numVals = -1;
return (0);
}
}
/* if no match, then add it to the rulevalue array */
if (j == count) {
&rv[i]);
if (rvq == 0) {
*numVals = -1;
return (0);
}
count++;
}
}
}
return (rvq);
}