#include <strings.h>
#include <string.h>
#include <lber.h>
#include <ldap.h>
#include "db_item_c.h"
#include "nisdb_mt.h"
#include "ldap_util.h"
#include "ldap_structs.h"
#include "ldap_val.h"
#include "ldap_ruleval.h"
#include "ldap_op.h"
#include "ldap_nisdbquery.h"
#include "ldap_attr.h"
#include "ldap_xdr.h"
#include "ldap_ldap.h"
item *
buildItem(int len, void *value) {
char *myself = "buildItem";
item *i = am(myself, sizeof (*i));
int mlen = len;
if (i == 0)
return (0);
if (value == 0 || len <= 0) {
i->itemvalue.itemvalue_len = 0;
i->itemvalue.itemvalue_val = 0;
return (i);
}
if (len > 0 && ((char *)value)[len-1] != '\0')
mlen++;
i->itemvalue.itemvalue_len = len;
i->itemvalue.itemvalue_val = am(myself, mlen);
if (mlen > 0 && i->itemvalue.itemvalue_val == 0) {
free(i);
return (0);
}
memcpy(i->itemvalue.itemvalue_val, value, len);
return (i);
}
void
freeItem(item *i) {
if (i != 0) {
sfree(i->itemvalue.itemvalue_val);
free(i);
}
}
void
freeQcomp(db_qcomp *qc, int doFree) {
if (qc == 0)
return;
freeItem(qc->index_value);
if (doFree)
free(qc);
}
db_query *
buildQuery(int num_components, db_qcomp *components) {
char *myself = "buildQuery";
db_query *q = am(myself, sizeof (*q));
if (q == 0)
return (0);
q->components.components_len = num_components;
q->components.components_val = components;
return (q);
}
db_query *
cloneQuery(db_query *old, int numComps) {
db_query *new;
int i;
char *myself = "cloneQuery";
if (old == 0)
return (0);
new = am(myself, sizeof (*new));
if (new == 0)
return (0);
if (old->components.components_len > numComps)
numComps = old->components.components_len;
new->components.components_val = am(myself,
sizeof (new->components.components_val[0]) *
numComps);
if (numComps > 0 && new->components.components_val == 0) {
free(new);
return (0);
}
for (i = 0; i < old->components.components_len; i++) {
item *it;
if (old->components.components_val[i].index_value == 0) {
new->components.components_val[i].index_value = 0;
new->components.components_val[i].which_index =
old->components.components_val[i].which_index;
continue;
}
it = buildItem(old->components.components_val[i].index_value->
itemvalue.itemvalue_len,
old->components.components_val[i].index_value->
itemvalue.itemvalue_val);
if (it == 0) {
new->components.components_len = i + 1;
freeQuery(new);
return (0);
}
new->components.components_val[i].index_value = it;
new->components.components_val[i].which_index =
old->components.components_val[i].which_index;
}
new->components.components_len = old->components.components_len;
return (new);
}
void
freeQuery(db_query *q) {
int i;
if (q == 0)
return;
for (i = 0; i < q->components.components_len; i++) {
freeItem(q->components.components_val[i].index_value);
}
sfree(q->components.components_val);
sfree(q);
}
void
freeQueries(db_query **q, int numQ) {
int i;
if (q == 0)
return;
for (i = 0; i < numQ; i++)
freeQuery(q[i]);
sfree(q);
}
db_query **
createQuery(int num, char **index, __nis_table_mapping_t *t,
__nis_rule_value_t **rvP, int *numVals) {
db_query **q;
db_qcomp *qc;
int i, j, n, a, nv, niv;
__nis_rule_value_t *rvq;
__nis_buffer_t b = {0, 0};
char *table = 0;
char *myself = "createQuery";
rvq = initRuleValue(1, 0);
if (rvq == 0)
return (0);
if (numVals == 0)
numVals = &nv;
*numVals = 0;
if (rvP != 0) {
table = fullObjName(F, t->objName);
if (table == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error converting \"%s\" to FQ object name",
myself, NIL(t->objName));
freeRuleValue(rvq, 1);
return (0);
}
}
for (n = 0; n < num; n++) {
char *value;
if ((value = strchr(index[n], '=')) == 0) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: no '=' in \"%s\"",
myself, index[n]);
continue;
}
*value = '\0';
value++;
for (a = 0; a < t->numColumns; a++) {
if (strcmp(index[n], t->column[a]) == 0) {
if (addSCol2RuleValue(index[n], value, rvq)) {
freeRuleValue(rvq, 1);
sfree(table);
return (0);
}
break;
}
}
if (a >= t->numColumns) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Ignoring unknown column \"%s\"",
myself, NIL(index[n]));
}
}
for (n = 0, niv = 1; n < rvq->numColumns; n++) {
if (rvq->colVal[n].numVals > 1)
niv *= rvq->colVal[n].numVals;
}
*numVals = 1;
sfree(b.buf);
sfree(table);
if (rvq->numColumns <= 0) {
freeRuleValue(rvq, *numVals);
*numVals = 0;
return (0);
}
if (niv > 1 && *numVals == 1) {
__nis_rule_value_t *rv;
int repeat;
rv = initRuleValue(niv, rvq);
if (rv == 0) {
freeRuleValue(rvq, 1);
*numVals = 0;
return (0);
}
for (i = 0, repeat = 1; i < rvq->numColumns; i++) {
int r, k;
for (n = 0, j = 0, r = 0; n < niv; n++) {
for (k = 0; k < rv[n].colVal[i].numVals; k++) {
if (k == j)
continue;
sfree(rv[n].colVal[i].val[k].
value);
}
rv[n].colVal[i].numVals = 1;
if (j != 0)
rv[n].colVal[i].val[0] =
rv[n].colVal[i].val[j];
r += 1;
if (r >= repeat) {
r = 0;
j += 1;
if (j >= rvq->colVal[i].numVals)
j = 0;
}
}
repeat *= rvq->colVal[i].numVals;
}
*numVals = niv;
freeRuleValue(rvq, 1);
rvq = rv;
rv = 0;
}
q = am(myself, *numVals * sizeof (q[0]));
if (q == 0) {
freeRuleValue(rvq, *numVals);
return (0);
}
for (a = 0; a < *numVals; a++) {
int nn, err = 0;
qc = am(myself, rvq[a].numColumns * sizeof (*qc));
if (qc != 0) {
for (nn = 0, i = 0; i < rvq[a].numColumns; i++) {
for (j = 0; j < t->numColumns; j++) {
if (strcmp(rvq[a].colName[i],
t->column[j]) == 0) {
break;
}
}
if (j >= t->numColumns)
continue;
qc[nn].which_index = j;
if (rvq[a].colVal[i].numVals > 0) {
qc[nn].index_value = buildItem(
rvq[a].colVal[i].val[0].length,
rvq[a].colVal[i].val[0].value);
if (qc[nn].index_value == 0)
err++;
} else {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: No values for [%d]%s",
myself, a, rvq[a].colName[i]);
err++;
}
nn++;
}
if (err == 0)
q[a] = buildQuery(nn, qc);
}
if (err > 0 || q[a] == 0) {
freeQueries(q, a);
for (a = 0; a < nn; a++)
freeQcomp(&qc[a], F);
sfree(qc);
freeRuleValue(rvq, *numVals);
return (0);
}
}
if (rvP != 0) {
*rvP = rvq;
} else {
freeRuleValue(rvq, 1);
*numVals = 0;
}
return (q);
}
void
printQuery(db_query *q, __nis_table_mapping_t *t) {
int i, mc = -1;
char *myself = "printQuery";
char *val[NIS_MAXCOLUMNS];
if (q == 0)
return;
(void) memset(val, 0, sizeof (val));
for (i = 0; i < q->components.components_len; i++) {
int ix = q->components.components_val[i].which_index;
if (ix >= NIS_MAXCOLUMNS ||
(t != 0 && ix >= t->numColumns))
continue;
if (ix > mc)
mc = ix;
val[ix] = q->components.components_val[i].index_value->
itemvalue.itemvalue_val;
}
for (i = 0; i <= mc; i++) {
p2buf(myself, "%s%s", (i != 0 ? " " : ""),
(val[i] != 0 ? val[i] : ""));
}
if (mc >= 0)
p2buf(myself, "\n");
}
int
verifyQueryMatch(db_query *q, db_query *fq) {
int i, j, match;
if (fq == 0)
return (1);
if (q == 0)
return ((fq == 0) ? 1 : 0);
for (i = 0, match = 1; match && i < q->components.components_len;
i++) {
for (j = 0; j < fq->components.components_len; j++) {
int len, flen;
if (q->components.components_val[i].which_index !=
fq->components.components_val[j].
which_index)
continue;
if (q->components.components_val[i].index_value == 0) {
if (fq->components.components_val[j].
index_value == 0)
continue;
else {
match = 0;
break;
}
}
if (fq->components.components_val[j].index_value ==
0) {
match = 0;
break;
}
len = q->components.components_val[i].index_value->
itemvalue.itemvalue_len;
flen = fq->components.components_val[j].index_value->
itemvalue.itemvalue_len;
if (len != flen) {
if (!(len > 0 && len == (flen+1) &&
q->components.components_val[i].
index_value->
itemvalue.itemvalue_val[len-1] == 0)) {
match = 0;
break;
}
}
if (memcmp(q->components.components_val[i].index_value->
itemvalue.itemvalue_val,
fq->components.components_val[j].index_value->
itemvalue.itemvalue_val,
flen) != 0) {
match = 0;
break;
}
}
}
return (match);
}
db_query **
filterQuery(__nis_table_mapping_t *t, db_query **q, db_query *qin,
__nis_obj_attr_t ***objAttr, int *numQueries) {
db_query **new;
__nis_obj_attr_t **attr;
int i, nq, nn;
char *myself = "filterQuery";
if ((t == 0 && qin == 0) || q == 0 ||
numQueries == 0 || *numQueries <= 0)
return (q);
nq = *numQueries;
new = am(myself, nq * sizeof (new[0]));
if (objAttr != 0)
attr = am(myself, nq * sizeof (attr[0]));
else
attr = 0;
if (new == 0 || (objAttr != 0 && attr == 0)) {
sfree(new);
freeQueries(q, nq);
sfree(attr);
if (objAttr != 0) {
freeObjAttr(*objAttr, nq);
*objAttr = 0;
}
*numQueries = -1;
return (0);
}
for (i = 0, nn = 0; i < nq; i++) {
int retain = 1;
if (t != 0)
retain = verifyIndexMatch(t, q[i], 0, 0, 0);
if (retain && qin != 0)
retain = verifyQueryMatch(q[i], qin);
if (retain) {
new[nn] = q[i];
if (objAttr != 0)
attr[nn] = (*objAttr)[i];
nn++;
} else {
freeQuery(q[i]);
q[i] = 0;
if (objAttr != 0) {
freeSingleObjAttr((*objAttr)[i]);
(*objAttr)[i] = 0;
}
}
}
free(q);
if (objAttr != 0) {
sfree(*objAttr);
*objAttr = attr;
}
*numQueries = nn;
return (new);
}
db_query **
createNisPlusEntry(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
db_query *qin, __nis_obj_attr_t ***objAttr,
int *numQueries) {
db_query **query = 0;
int r, i, j, ir;
__nis_value_t *rval, *lval;
__nis_mapping_item_t *litem;
int numItems;
int nq;
__nis_obj_attr_t **attr = 0;
char **dn = 0;
int numDN = 0;
char *myself = "createNisPlusEntry";
if (t == 0 || t->objectDN == 0 || rv == 0)
return (0);
__nisdb_get_tsd()->searchBase = t->objectDN->read.base;
for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) {
int nrq, ntq, err;
db_query **newq;
__nis_obj_attr_t **newattr;
rval = buildRvalue(&t->ruleFromLDAP[r]->rhs,
mit_ldap, rv, NULL);
if (rval == 0)
continue;
litem = buildLvalue(&t->ruleFromLDAP[r]->lhs, &rval,
&numItems);
if (litem == 0) {
freeValue(rval, 1);
continue;
}
lval = 0;
for (i = 0; i < numItems; i++) {
__nis_value_t *tmpval, *old;
tmpval = getMappingItem(&litem[i],
mit_nisplus, 0, 0, NULL);
if (litem[i].type == mit_ldap) {
int stat;
if (dn == 0)
dn = findDNs(myself, rv, 1,
t->objectDN->write.base,
&numDN);
stat = storeLDAP(&litem[i], i, numItems, rval,
t->objectDN, dn, numDN);
if (stat != LDAP_SUCCESS) {
char *iname = "<unknown>";
if (tmpval != 0 &&
tmpval->numVals == 1)
iname = tmpval->val[0].value;
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: LDAP store \"%s\": %s",
myself, iname,
ldap_err2string(stat));
}
freeValue(tmpval, 1);
continue;
}
old = lval;
lval = concatenateValues(old, tmpval);
freeValue(tmpval, 1);
freeValue(old, 1);
}
freeMappingItem(litem, numItems);
if (lval == 0 || lval->numVals <= 0 || rval->numVals <= 0) {
freeValue(lval, 1);
freeValue(rval, 1);
continue;
}
if (rval->numVals > 1) {
if (lval->numVals == 1 && lval->repeat)
nrq = rval->numVals;
else if (lval->numVals > 1 && rval->repeat)
nrq = 1 + ((rval->numVals-1)/lval->numVals);
else
nrq = 1;
} else {
nrq = 1;
}
if (nq <= 0)
ntq = nrq;
else
ntq = nq * nrq;
if (ntq > nq) {
newq = realloc(query, ntq * sizeof (query[0]));
newattr = realloc(attr, ntq * sizeof (attr[0]));
if (newq == 0 || newattr == 0) {
logmsg(MSG_NOMEM, LOG_ERR,
"%s: realloc(%d) => NULL",
myself, ntq * sizeof (query[0]));
freeValue(lval, 1);
freeValue(rval, 1);
freeQueries(query, nq);
freeObjAttr(attr, nq);
sfree(newq);
freeDNs(dn, numDN);
return (0);
}
query = newq;
attr = newattr;
}
for (i = 1, err = 0; i < nrq; i++) {
for (j = 0; j < nq; j++) {
query[(nq*i)+j] = cloneQuery(query[j],
t->numColumns);
if (query[(nq*i)+j] == 0 &&
query[j] != 0)
err++;
attr[(nq*i)+j] = cloneObjAttr(attr[j]);
if (attr[(nq*i)+j] == 0 &&
attr[j] != 0)
err++;
}
}
if (err > 0) {
freeValue(lval, 1);
freeValue(rval, 1);
freeQueries(query, ntq);
freeObjAttr(attr, ntq);
freeDNs(dn, numDN);
return (0);
}
if (nq <= 0) {
(void) memset(query, 0, ntq * sizeof (query[0]));
(void) memset(attr, 0, ntq * sizeof (attr[0]));
for (i = 0, err = 0; i < ntq; i++) {
query[i] = am(myself, sizeof (*query[i]));
if (query[i] == 0) {
err++;
break;
}
query[i]->components.components_val =
am(myself, t->numColumns *
sizeof (query[i]->components.components_val[0]));
if (query[i]->components.components_val == 0) {
err++;
break;
}
query[i]->components.components_len = 0;
}
if (err > 0) {
freeValue(lval, 1);
freeValue(rval, 1);
freeQueries(query, ntq);
freeObjAttr(attr, ntq);
freeDNs(dn, numDN);
return (0);
}
}
for (i = 0, ir = 0; i < lval->numVals; i++) {
char *oaName = 0;
int index;
for (index = 0; index < t->numColumns;
index++) {
if (strncmp(t->column[index],
lval->val[i].value,
lval->val[i].length) == 0)
break;
}
if (index >= t->numColumns) {
oaName = isObjAttr(&lval->val[i]);
if (oaName == 0)
continue;
}
for (j = i*nrq; j < (i+1)*nrq; j++) {
int k;
ir = (j < rval->numVals) ?
j : rval->numVals - 1;
for (k = j % nrq, err = 0; k < ntq; k += nrq) {
int ic, c;
if (oaName != 0) {
int fail = setObjAttrField(
oaName,
&rval->val[ir],
&attr[k]);
if (fail) {
err++;
break;
}
continue;
}
ic = query[k]->components.
components_len;
if (ic >= t->numColumns)
continue;
for (c = 0; c < ic; c++) {
if (query[k]->components.
components_val[c].
which_index == index)
break;
}
if (c >= ic) {
int l;
char *v;
query[k]->components.
components_val[ic].
which_index = index;
l = rval->val[ir].length;
v = rval->val[ir].value;
if (rval->type == vt_string &&
l > 0 &&
v[l-1] != '\0' &&
v[l] == '\0')
l++;
query[k]->components.
components_val[ic].
index_value =
buildItem(l, v);
if (query[k]->
components.
components_val[ic].
index_value == 0) {
err++;
break;
}
query[k]->components.
components_len++;
}
}
if (err > 0) {
freeValue(lval, 1);
freeValue(rval, 1);
freeQueries(query, ntq);
freeObjAttr(attr, ntq);
freeDNs(dn, numDN);
return (0);
}
}
}
freeValue(lval, 1);
freeValue(rval, 1);
nq = ntq;
}
freeDNs(dn, numDN);
if (nq <= 0) {
sfree(query);
query = 0;
}
if (query != 0) {
if (t->index.numIndexes > 0)
query = filterQuery(t, query, qin, &attr, &nq);
else if (qin != 0)
query = filterQuery(0, query, qin, &attr, &nq);
}
if (query != 0 && numQueries != 0)
*numQueries = nq;
if (objAttr != 0)
*objAttr = attr;
else
freeObjAttr(attr, nq);
return (query);
}
db_query **
ruleValue2Query(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
db_query *qin, __nis_obj_attr_t ***objAttr, int *numQueries) {
db_query **q = 0, ***qp = 0;
int i, nqp, nq, *nnp = 0, nv;
__nis_obj_attr_t **attr = 0, ***atp = 0;
char *myself = "ruleValue2Query";
if (t == 0 || rv == 0 || numQueries == 0)
return (0);
nv = *numQueries;
if (nv <= 0)
return (0);
qp = am(myself, nv * sizeof (*qp));
nnp = am(myself, nv * sizeof (*nnp));
atp = am(myself, nv * sizeof (*atp));
if (qp == 0 || nnp == 0 || atp == 0) {
sfree(qp);
sfree(nnp);
sfree(atp);
return (0);
}
for (i = 0, nq = 0, nqp = 0; i < nv; i++) {
qp[nqp] = createNisPlusEntry(t, &rv[i], qin, &atp[nqp],
&nnp[nqp]);
if (qp[nqp] == 0)
goto cleanup;
nq += nnp[nqp];
nqp++;
}
if (nqp == 0 || nq <= 0)
goto cleanup;
q = am(myself, nq * sizeof (q[0]));
attr = am(myself, nq * sizeof (attr[0]));
if (q == 0 || attr == 0) {
nq = 0;
goto cleanup;
}
for (i = 0, nq = 0; i < nqp; i++) {
(void) memcpy(&q[nq], qp[i], nnp[i] * sizeof (qp[i][0]));
(void) memcpy(&attr[nq], atp[i], nnp[i] * sizeof (atp[i][0]));
nq += nnp[i];
free(qp[i]);
free(atp[i]);
}
*numQueries = nq;
if (objAttr != 0)
*objAttr = attr;
else
freeObjAttr(attr, nq);
nqp = 0;
cleanup:
for (i = 0; i < nqp; i++) {
freeQueries(qp[i], nnp[i]);
sfree(atp[i]);
}
sfree(qp);
sfree(nnp);
sfree(atp);
return (q);
}
db_query *
pseudoEntryObj2Query(entry_obj *e, nis_object *tobj, __nis_rule_value_t *rv) {
db_query *qbuf;
db_qcomp *qcbuf;
int nc, i;
__nis_rule_value_t *rvt = 0;
char *myself = "pseudoEntryObj2Query";
nc = e->en_cols.en_cols_len - 1;
if (e == 0 || nc < 0 || nc > NIS_MAXCOLUMNS)
return (0);
if (rv != 0) {
nis_object *o;
o = unmakePseudoEntryObj(e, tobj);
if (o == 0)
return (0);
rvt = addObjAttr2RuleValue(o, 0);
nis_destroy_object(o);
if (rvt == 0)
return (0);
}
qbuf = am(myself, sizeof (*qbuf));
if (nc == 0)
return (qbuf);
qcbuf = am(myself, nc * sizeof (*qcbuf));
if (qcbuf == 0) {
sfree(qcbuf);
if (rvt != 0)
freeRuleValue(rvt, 1);
return (0);
}
qbuf->components.components_val = qcbuf;
qbuf->components.components_len = nc;
for (i = 0; i < nc; i++) {
qcbuf[i].which_index = i;
qcbuf[i].index_value = buildItem(
e->en_cols.en_cols_val[i+1].ec_value.ec_value_len,
e->en_cols.en_cols_val[i+1].ec_value.ec_value_val);
if (qcbuf[i].index_value == 0) {
freeQuery(qbuf);
if (rvt != 0)
freeRuleValue(rvt, 1);
return (0);
}
}
if (rvt != 0) {
*rv = *rvt;
sfree(rvt);
}
return (qbuf);
}
db_query *
queryFromComponent(db_query *q, int index, db_query *qbuf) {
if (q == 0 || index < 0 || index >= q->components.components_len ||
qbuf == 0)
return (0);
qbuf->components.components_len = 1;
qbuf->components.components_val = &q->components.components_val[index];
return (qbuf);
}