10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*13143SBenjamin.Chang@Oracle.COM * Common Development and Distribution License (the "License").
6*13143SBenjamin.Chang@Oracle.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*13143SBenjamin.Chang@Oracle.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * DESCRIPTION: Contains dit_access interface support functions.
270Sstevel@tonic-gate */
280Sstevel@tonic-gate #include <sys/systeminfo.h>
290Sstevel@tonic-gate #include <unistd.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <sys/stat.h>
330Sstevel@tonic-gate #include <sys/systeminfo.h>
340Sstevel@tonic-gate #include <unistd.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <syslog.h>
370Sstevel@tonic-gate #include <ndbm.h>
380Sstevel@tonic-gate #include <strings.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include "../ldap_util.h"
410Sstevel@tonic-gate #include "../ldap_map.h"
420Sstevel@tonic-gate #include "../ldap_parse.h"
430Sstevel@tonic-gate #include "../ldap_structs.h"
440Sstevel@tonic-gate #include "../ldap_val.h"
450Sstevel@tonic-gate #include "../ldap_ruleval.h"
460Sstevel@tonic-gate #include "../ldap_op.h"
470Sstevel@tonic-gate #include "../ldap_attr.h"
480Sstevel@tonic-gate #include "../ldap_nisdbquery.h"
490Sstevel@tonic-gate #include "../nisdb_mt.h"
500Sstevel@tonic-gate #include "shim.h"
510Sstevel@tonic-gate #include "yptol.h"
520Sstevel@tonic-gate #include "dit_access_utils.h"
530Sstevel@tonic-gate
54*13143SBenjamin.Chang@Oracle.COM #define YPMULTI "YP_MULTI_"
55*13143SBenjamin.Chang@Oracle.COM #define YPMULTISZ 9 /* == strlen(YPMULTI) */
56*13143SBenjamin.Chang@Oracle.COM
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate * Returns 'map,domain.'
590Sstevel@tonic-gate */
600Sstevel@tonic-gate char *
getFullMapName(char * map,char * domain)610Sstevel@tonic-gate getFullMapName(char *map, char *domain) {
620Sstevel@tonic-gate char *myself = "getFullMapName";
630Sstevel@tonic-gate char *objPath;
640Sstevel@tonic-gate if (map == 0 || domain == 0) {
650Sstevel@tonic-gate return (0);
660Sstevel@tonic-gate }
670Sstevel@tonic-gate objPath = scat(myself, T, scat(myself, F, map, ","),
680Sstevel@tonic-gate scat(myself, F, domain, "."));
690Sstevel@tonic-gate
700Sstevel@tonic-gate return (objPath);
710Sstevel@tonic-gate }
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * Convert string to __nis_value_t
750Sstevel@tonic-gate */
stringToValue(char * dptr,int dsize)760Sstevel@tonic-gate __nis_value_t *stringToValue(char *dptr, int dsize) {
770Sstevel@tonic-gate char *myself = "stringToValue";
780Sstevel@tonic-gate char *emptystr = "";
790Sstevel@tonic-gate __nis_value_t *val;
800Sstevel@tonic-gate
810Sstevel@tonic-gate if ((val = am(myself, sizeof (*val))) == 0) {
820Sstevel@tonic-gate return (0);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate
850Sstevel@tonic-gate val->type = vt_string;
860Sstevel@tonic-gate val->repeat = 0;
870Sstevel@tonic-gate val->numVals = 1;
880Sstevel@tonic-gate if ((val->val = am(myself, sizeof (val->val[0]))) == 0) {
890Sstevel@tonic-gate sfree(val);
900Sstevel@tonic-gate return (0);
910Sstevel@tonic-gate }
920Sstevel@tonic-gate
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate * Null strings or strings with length 0 are treated
950Sstevel@tonic-gate * as empty strings with length 1
960Sstevel@tonic-gate */
970Sstevel@tonic-gate if (dptr == 0 || dsize <= 0) {
980Sstevel@tonic-gate dptr = emptystr;
990Sstevel@tonic-gate dsize = 1;
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate val->val->length = dsize;
1030Sstevel@tonic-gate if (dptr[dsize - 1] != '\0') {
1040Sstevel@tonic-gate val->val->length = dsize + 1;
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate val->val->value = am(myself, val->val->length);
1080Sstevel@tonic-gate if (val->val->value == 0) {
1090Sstevel@tonic-gate freeValue(val, 1);
1100Sstevel@tonic-gate return (0);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate (void) memcpy(val->val->value, dptr, dsize);
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate return (val);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate * Returns an array of rule-values corresponding to the
1190Sstevel@tonic-gate * splitfields.
1200Sstevel@tonic-gate */
1210Sstevel@tonic-gate __nis_rule_value_t *
processSplitField(__nis_table_mapping_t * sf,__nis_value_t * inVal,int * nv,int * statP)1220Sstevel@tonic-gate processSplitField(__nis_table_mapping_t *sf, __nis_value_t *inVal,
1230Sstevel@tonic-gate int *nv, int *statP) {
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate char *sepset;
1260Sstevel@tonic-gate __nis_rule_value_t *rvq;
1270Sstevel@tonic-gate __nis_mapping_format_t *ftmp;
1280Sstevel@tonic-gate __nis_value_t **valA, *tempVal;
1290Sstevel@tonic-gate int i, j, res, numVals, oldlen, count;
1300Sstevel@tonic-gate char *str, *oldstr;
1310Sstevel@tonic-gate char *myself = "processSplitField";
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /* sf will be non NULL */
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate if (inVal == 0 || inVal->type != vt_string) {
1360Sstevel@tonic-gate *statP = MAP_PARAM_ERROR;
1370Sstevel@tonic-gate return (0);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate /* Get the separator list */
1410Sstevel@tonic-gate sepset = sf->separatorStr;
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* Initialize rule-value */
1440Sstevel@tonic-gate rvq = 0;
1450Sstevel@tonic-gate count = 0;
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate if ((tempVal = stringToValue(inVal->val->value,
1480Sstevel@tonic-gate inVal->val->length)) == 0) {
1490Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
1500Sstevel@tonic-gate return (0);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate str = oldstr = tempVal->val->value;
1540Sstevel@tonic-gate oldlen = tempVal->val->length;
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate while (str) {
1570Sstevel@tonic-gate tempVal->val->value = str;
1580Sstevel@tonic-gate tempVal->val->length = strlen(str) + 1;
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate /* Loop to check which format matches str */
1610Sstevel@tonic-gate for (i = 0; i <= sf->numSplits; i++) {
1620Sstevel@tonic-gate valA = matchMappingItem(sf->e[i].element.match.fmt,
1630Sstevel@tonic-gate tempVal, &numVals, sepset, &str);
1640Sstevel@tonic-gate if (valA == 0) {
1650Sstevel@tonic-gate /* The format didn't match. Try the next one */
1660Sstevel@tonic-gate continue;
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate * If we are here means we had a match.
1710Sstevel@tonic-gate * Each new set of values obtained from the match is
1720Sstevel@tonic-gate * added to a new rule-value. This is to preserve the
1730Sstevel@tonic-gate * the distinction between each set.
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 0);
1760Sstevel@tonic-gate if (rvq == 0) {
1770Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
1780Sstevel@tonic-gate for (j = 0; j < numVals; j++)
1790Sstevel@tonic-gate freeValue(valA[j], 1);
1800Sstevel@tonic-gate sfree(valA);
1810Sstevel@tonic-gate tempVal->val->value = oldstr;
1820Sstevel@tonic-gate tempVal->val->length = oldlen;
1830Sstevel@tonic-gate freeValue(tempVal, 1);
1840Sstevel@tonic-gate return (0);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate count++;
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate for (j = 0; j < numVals; j++) {
1890Sstevel@tonic-gate res = addCol2RuleValue(vt_string,
1900Sstevel@tonic-gate sf->e[i].element.match.item[j].name,
1910Sstevel@tonic-gate valA[j]->val->value,
1920Sstevel@tonic-gate valA[j]->val->length,
1930Sstevel@tonic-gate &rvq[count - 1]);
1940Sstevel@tonic-gate if (res == -1) {
1950Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
1960Sstevel@tonic-gate for (; j < numVals; j++)
1970Sstevel@tonic-gate freeValue(valA[j], 1);
1980Sstevel@tonic-gate sfree(valA);
1990Sstevel@tonic-gate tempVal->val->value = oldstr;
2000Sstevel@tonic-gate tempVal->val->length = oldlen;
2010Sstevel@tonic-gate freeValue(tempVal, 1);
2020Sstevel@tonic-gate freeRuleValue(rvq, count);
2030Sstevel@tonic-gate return (0);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate freeValue(valA[j], 1);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate sfree(valA);
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate * Since we had a match, break out of this loop
2110Sstevel@tonic-gate * to parse remainder of str
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate break;
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /* Didn't find any match, so get out of the loop */
2170Sstevel@tonic-gate if (i > sf->numSplits) {
2180Sstevel@tonic-gate str = 0;
2190Sstevel@tonic-gate break;
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate /* Skip the separators before looping back */
2230Sstevel@tonic-gate if (str) {
2240Sstevel@tonic-gate str = str + strspn(str, sepset);
2250Sstevel@tonic-gate if (*str == '\0')
2260Sstevel@tonic-gate break;
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate tempVal->val->value = oldstr;
2310Sstevel@tonic-gate tempVal->val->length = oldlen;
2320Sstevel@tonic-gate freeValue(tempVal, 1);
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate if (str == 0) {
2350Sstevel@tonic-gate freeRuleValue(rvq, count);
2360Sstevel@tonic-gate return (0);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (nv != 0)
2400Sstevel@tonic-gate *nv = count;
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate return (rvq);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate * Convert the datum to an array of RuleValues
2470Sstevel@tonic-gate */
2480Sstevel@tonic-gate __nis_rule_value_t *
datumToRuleValue(datum * key,datum * value,__nis_table_mapping_t * t,int * nv,char * domain,bool_t readonly,int * statP)2490Sstevel@tonic-gate datumToRuleValue(datum *key, datum *value, __nis_table_mapping_t *t,
2500Sstevel@tonic-gate int *nv, char *domain, bool_t readonly, int *statP) {
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate __nis_rule_value_t *rvq, *subrvq, *newrvq;
2530Sstevel@tonic-gate __nis_value_t *val;
2540Sstevel@tonic-gate __nis_value_t **valA;
2550Sstevel@tonic-gate __nis_table_mapping_t *sf;
2560Sstevel@tonic-gate int valueLen, comLen, numVals, nr, count = 1;
2570Sstevel@tonic-gate int i, j, k, l, af;
2580Sstevel@tonic-gate char *ipaddr, *ipvalue;
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate /* At this point, 't' is always non NULL */
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate /* Initialize rule-value */
2630Sstevel@tonic-gate if ((rvq = initRuleValue(1, 0)) == 0) {
2640Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
2650Sstevel@tonic-gate return (0);
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate /* Add domainname to rule-value */
2690Sstevel@tonic-gate if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain),
2700Sstevel@tonic-gate rvq)) {
2710Sstevel@tonic-gate freeRuleValue(rvq, 1);
2720Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
2730Sstevel@tonic-gate return (0);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /* Handle key */
2770Sstevel@tonic-gate if (key != 0) {
2780Sstevel@tonic-gate /* Add field=value pair for N2LKEY */
2790Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LKEY, key->dptr, key->dsize,
2800Sstevel@tonic-gate rvq);
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate /* For readonly, add field=value pair for N2LSEARCHKEY */
2830Sstevel@tonic-gate if (readonly == TRUE && i == 0) {
2840Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LSEARCHKEY, key->dptr,
2850Sstevel@tonic-gate key->dsize, rvq);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate if (i) {
2880Sstevel@tonic-gate freeRuleValue(rvq, 1);
2890Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
2900Sstevel@tonic-gate return (0);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate /* Add field=value pairs for IP addresses */
2940Sstevel@tonic-gate if (checkIPaddress(key->dptr, key->dsize, &ipaddr) > 0) {
2950Sstevel@tonic-gate /* If key is IPaddress, use preferred format */
2960Sstevel@tonic-gate ipvalue = ipaddr;
2970Sstevel@tonic-gate valueLen = strlen(ipaddr);
2980Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LIPKEY, ipvalue,
2990Sstevel@tonic-gate valueLen, rvq);
3000Sstevel@tonic-gate } else {
3010Sstevel@tonic-gate /* If not, use original value for N2LSEARCHIPKEY */
3020Sstevel@tonic-gate ipaddr = 0;
3030Sstevel@tonic-gate ipvalue = key->dptr;
3040Sstevel@tonic-gate valueLen = key->dsize;
3050Sstevel@tonic-gate i = 0;
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate if (readonly == TRUE && i == 0) {
3090Sstevel@tonic-gate i = addCol2RuleValue(vt_string, N2LSEARCHIPKEY, ipvalue,
3100Sstevel@tonic-gate valueLen, rvq);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate sfree(ipaddr);
3130Sstevel@tonic-gate if (i) {
3140Sstevel@tonic-gate freeRuleValue(rvq, 1);
3150Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
3160Sstevel@tonic-gate return (0);
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /* Handle datum value */
3210Sstevel@tonic-gate if (value != 0 && t->e) {
3220Sstevel@tonic-gate valueLen = value->dsize;
3230Sstevel@tonic-gate /*
3240Sstevel@tonic-gate * Extract the comment, if any, and add it to
3250Sstevel@tonic-gate * the rule-value.
3260Sstevel@tonic-gate */
3270Sstevel@tonic-gate if (t->commentChar != '\0') {
3280Sstevel@tonic-gate /*
3290Sstevel@tonic-gate * We loop on value->dsize because value->dptr
3300Sstevel@tonic-gate * may not be NULL-terminated.
3310Sstevel@tonic-gate */
3320Sstevel@tonic-gate for (i = 0; i < value->dsize; i++) {
3330Sstevel@tonic-gate if (value->dptr[i] == t->commentChar) {
3340Sstevel@tonic-gate valueLen = i;
3350Sstevel@tonic-gate comLen = value->dsize - i - 1;
3360Sstevel@tonic-gate if (comLen == 0)
3370Sstevel@tonic-gate break;
3380Sstevel@tonic-gate if (addCol2RuleValue(vt_string,
3390Sstevel@tonic-gate N2LCOMMENT, value->dptr + i + 1,
3400Sstevel@tonic-gate comLen, rvq)) {
3410Sstevel@tonic-gate freeRuleValue(rvq, 1);
3420Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
3430Sstevel@tonic-gate return (0);
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate break;
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate /* Skip trailing whitespaces */
3510Sstevel@tonic-gate for (; valueLen > 0 && (value->dptr[valueLen - 1] == ' ' ||
3520Sstevel@tonic-gate value->dptr[valueLen - 1] == '\t'); valueLen--);
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate /*
3550Sstevel@tonic-gate * At this point valueLen is the effective length of
3560Sstevel@tonic-gate * the data. Convert value into __nis_value_t so that
3570Sstevel@tonic-gate * we can use the matchMappingItem function to break it
3580Sstevel@tonic-gate * into fields.
3590Sstevel@tonic-gate */
3600Sstevel@tonic-gate if ((val = stringToValue(value->dptr, valueLen)) == 0) {
3610Sstevel@tonic-gate freeRuleValue(rvq, 1);
3620Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
3630Sstevel@tonic-gate return (0);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate /* Perform namefield match */
3670Sstevel@tonic-gate valA = matchMappingItem(t->e->element.match.fmt, val,
3680Sstevel@tonic-gate &numVals, 0, 0);
3690Sstevel@tonic-gate if (valA == 0) {
3700Sstevel@tonic-gate freeValue(val, 1);
3710Sstevel@tonic-gate freeRuleValue(rvq, 1);
3720Sstevel@tonic-gate *statP = MAP_NAMEFIELD_MATCH_ERROR;
3730Sstevel@tonic-gate return (0);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate /* We don't need val anymore, so free it */
3770Sstevel@tonic-gate freeValue(val, 1);
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate /*
3800Sstevel@tonic-gate * Since matchMappingItem only returns us an array of
3810Sstevel@tonic-gate * __nis_value_t's, we need to associate each value
3820Sstevel@tonic-gate * in the array with the corresponding item name.
3830Sstevel@tonic-gate * This code assumes that numVals will be less than or
3840Sstevel@tonic-gate * equal to the number of item names associated with
3850Sstevel@tonic-gate * the format.
3860Sstevel@tonic-gate * These name=value pairs are added to rvq.
3870Sstevel@tonic-gate */
3880Sstevel@tonic-gate for (i = 0, *statP = SUCCESS; i < numVals; i++) {
3890Sstevel@tonic-gate for (j = 0; j < count; j++) {
3900Sstevel@tonic-gate if (addCol2RuleValue(vt_string,
3910Sstevel@tonic-gate t->e->element.match.item[i].name,
3920Sstevel@tonic-gate valA[i]->val->value,
3930Sstevel@tonic-gate valA[i]->val->length, &rvq[j])) {
3940Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
3950Sstevel@tonic-gate break;
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate if (*statP == MAP_INTERNAL_ERROR)
3990Sstevel@tonic-gate break;
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate /*
4020Sstevel@tonic-gate * Check if splitField exists for the field.
4030Sstevel@tonic-gate * Since splitfields are also stored as mapping
4040Sstevel@tonic-gate * structures, we need to get the hash table entry
4050Sstevel@tonic-gate * corresponding to the splitfield name
4060Sstevel@tonic-gate */
4070Sstevel@tonic-gate sf = mappingFromMap(t->e->element.match.item[i].name,
4080Sstevel@tonic-gate domain, statP);
4090Sstevel@tonic-gate if (*statP == MAP_NO_MEMORY)
4100Sstevel@tonic-gate break;
4110Sstevel@tonic-gate *statP = SUCCESS;
4120Sstevel@tonic-gate if (sf == 0)
4130Sstevel@tonic-gate continue;
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate /*
4160Sstevel@tonic-gate * Process and add splitFields to rule-value rvq
4170Sstevel@tonic-gate */
4180Sstevel@tonic-gate subrvq = processSplitField(sf, valA[i], &nr, statP);
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate if (subrvq == 0) {
4210Sstevel@tonic-gate /* statP would have been set */
4220Sstevel@tonic-gate break;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate /*
4260Sstevel@tonic-gate * We merge 'count' rule-values in rvq with 'nr'
4270Sstevel@tonic-gate * rule-values from subrvq to give us a whopping
4280Sstevel@tonic-gate * 'count * nr' rule-values
4290Sstevel@tonic-gate */
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate /* Initialize the new rule-value array */
4320Sstevel@tonic-gate if ((newrvq = initRuleValue(count * nr, 0)) == 0) {
4330Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
4340Sstevel@tonic-gate freeRuleValue(subrvq, nr);
4350Sstevel@tonic-gate break;
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate for (j = 0, l = 0; j < nr; j++) {
4390Sstevel@tonic-gate for (k = 0; k < count; k++, l++) {
4400Sstevel@tonic-gate if ((mergeRuleValue(&newrvq[l],
4410Sstevel@tonic-gate &rvq[k]) == -1) ||
4420Sstevel@tonic-gate (mergeRuleValue(
4430Sstevel@tonic-gate &newrvq[l],
4440Sstevel@tonic-gate &subrvq[j]) == -1)) {
4450Sstevel@tonic-gate *statP = MAP_INTERNAL_ERROR;
4460Sstevel@tonic-gate for (i = 0; i < numVals; i++)
4470Sstevel@tonic-gate freeValue(valA[i], 1);
4480Sstevel@tonic-gate sfree(valA);
4490Sstevel@tonic-gate freeRuleValue(rvq, count);
4500Sstevel@tonic-gate freeRuleValue(newrvq,
4510Sstevel@tonic-gate count * nr);
4520Sstevel@tonic-gate freeRuleValue(subrvq, nr);
4530Sstevel@tonic-gate return (0);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate freeRuleValue(rvq, count);
4590Sstevel@tonic-gate rvq = newrvq;
4600Sstevel@tonic-gate count = l;
4610Sstevel@tonic-gate freeRuleValue(subrvq, nr);
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate /* We don't need valA anymore, so free it */
4660Sstevel@tonic-gate for (i = 0; i < numVals; i++)
4670Sstevel@tonic-gate freeValue(valA[i], 1);
4680Sstevel@tonic-gate sfree(valA);
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate if (*statP != SUCCESS) {
4710Sstevel@tonic-gate freeRuleValue(rvq, count);
4720Sstevel@tonic-gate return (0);
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate } /* if value */
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate if (nv != 0)
4780Sstevel@tonic-gate *nv = count;
4790Sstevel@tonic-gate return (rvq);
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate * Generate name=values pairs for splitfield names
4850Sstevel@tonic-gate *
4860Sstevel@tonic-gate * Consider Example:
4870Sstevel@tonic-gate * nisLDAPnameFields club:
4880Sstevel@tonic-gate * ("%s %s %s", name, code, members)
4890Sstevel@tonic-gate * nisLDAPsplitField members:
4900Sstevel@tonic-gate * ("(%s,%s,%s)", host, user, domain),
4910Sstevel@tonic-gate * ("%s", group)
4920Sstevel@tonic-gate * On entry,
4930Sstevel@tonic-gate * - rv is an array of numVals rule-values each containing
4940Sstevel@tonic-gate * name=value pairs for names occuring in nisLDAPsplitField.
4950Sstevel@tonic-gate * (i.e host, user, domain, group)
4960Sstevel@tonic-gate * - trv contains name=value pairs for names occuring in
4970Sstevel@tonic-gate * nisLDAPnameFields. (i.e name, code but not members)
4980Sstevel@tonic-gate *
4990Sstevel@tonic-gate * For every name in nisLDAPnamefields that is a splitfield,
5000Sstevel@tonic-gate * this function applies the data in rv to the corresponding
5010Sstevel@tonic-gate * splitfield formats (accessed thru t), to generate a single
5020Sstevel@tonic-gate * string value for the corresponding splitfield (members).
5030Sstevel@tonic-gate * This new name=value pair is then added to trv.
5040Sstevel@tonic-gate * Besides, any uninitialized namefield names are set to empty strings.
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate suc_code
addSplitFieldValues(__nis_table_mapping_t * t,__nis_rule_value_t * rv,__nis_rule_value_t * trv,int numVals,char * domain)5070Sstevel@tonic-gate addSplitFieldValues(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
5080Sstevel@tonic-gate __nis_rule_value_t *trv, int numVals, char *domain) {
5090Sstevel@tonic-gate __nis_table_mapping_t *sf;
5100Sstevel@tonic-gate __nis_value_t *val;
5110Sstevel@tonic-gate int i, j, k, nitems, res, statP;
5120Sstevel@tonic-gate char *str, *tempstr;
5130Sstevel@tonic-gate char delim[2] = {0, 0};
5140Sstevel@tonic-gate char *emptystr = "";
5150Sstevel@tonic-gate char *myself = "addSplitFieldValues";
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate if (trv == 0)
5180Sstevel@tonic-gate return (MAP_INTERNAL_ERROR);
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate if (t->e == 0)
5210Sstevel@tonic-gate return (SUCCESS);
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate nitems = t->e->element.match.numItems;
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate /*
5260Sstevel@tonic-gate * Procedure:
5270Sstevel@tonic-gate * - Check each name in nisLDAPnamefield
5280Sstevel@tonic-gate * - if it's a splifield, construct its value and add it to trv
5290Sstevel@tonic-gate * - if not, check if it has a value
5300Sstevel@tonic-gate * - if not, add empty string
5310Sstevel@tonic-gate */
5320Sstevel@tonic-gate for (i = 0, sf = 0; i < nitems; i++) {
5330Sstevel@tonic-gate if (rv) {
5340Sstevel@tonic-gate /*
5350Sstevel@tonic-gate * str will eventually contain the single string
5360Sstevel@tonic-gate * value for the corresponding splitfield.
5370Sstevel@tonic-gate * No point initializing str if rv == 0 because
5380Sstevel@tonic-gate * splitfield cannot be constructed without rv.
5390Sstevel@tonic-gate * So, only initialized here.
5400Sstevel@tonic-gate */
5410Sstevel@tonic-gate str = 0;
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate /* Check if it's a splitfield name */
5440Sstevel@tonic-gate sf = mappingFromMap(t->e->element.match.item[i].name,
5450Sstevel@tonic-gate domain, &statP);
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * Return only incase of memory allocation failure.
5490Sstevel@tonic-gate * The other error case (MAP_NO_MAPPING_EXISTS),
5500Sstevel@tonic-gate * indicates that the item name is not a splitfieldname
5510Sstevel@tonic-gate * i.e it's a namefieldname. This case is handled by
5520Sstevel@tonic-gate * the following if (sf == 0)
5530Sstevel@tonic-gate */
5540Sstevel@tonic-gate if (statP == MAP_NO_MEMORY)
5550Sstevel@tonic-gate return (statP);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate if (sf == 0) {
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate * Not a splitfield name. Verify if it has a value
5610Sstevel@tonic-gate */
5620Sstevel@tonic-gate if (findVal(t->e->element.match.item[i].name,
5630Sstevel@tonic-gate trv, mit_nisplus) == 0) {
5640Sstevel@tonic-gate /* if not, use empty string */
5650Sstevel@tonic-gate res = addCol2RuleValue(vt_string,
5660Sstevel@tonic-gate t->e->element.match.item[i].name,
5670Sstevel@tonic-gate emptystr, 0, trv);
5680Sstevel@tonic-gate if (res == -1) {
5690Sstevel@tonic-gate return (MAP_INTERNAL_ERROR);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * If rv == 0 then sf == 0 so we will continue here
5740Sstevel@tonic-gate * i.e. does not matter that str is not yet set up.
5750Sstevel@tonic-gate */
5760Sstevel@tonic-gate continue;
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate /* Code to construct a single value */
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate /* Use the first separator character as the delimiter */
5820Sstevel@tonic-gate delim[0] = sf->separatorStr[0];
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate for (j = 0; j < numVals; j++) {
5850Sstevel@tonic-gate /* sf->numSplits is zero-based */
5860Sstevel@tonic-gate for (k = 0; k <= sf->numSplits; k++) {
5870Sstevel@tonic-gate val = getMappingFormatArray(
5880Sstevel@tonic-gate sf->e[k].element.match.fmt, &rv[j],
5890Sstevel@tonic-gate fa_item,
5900Sstevel@tonic-gate sf->e[k].element.match.numItems,
5910Sstevel@tonic-gate sf->e[k].element.match.item);
5920Sstevel@tonic-gate if (val == 0)
5930Sstevel@tonic-gate continue;
5940Sstevel@tonic-gate if (val->numVals > 0) {
5950Sstevel@tonic-gate if (str) {
5960Sstevel@tonic-gate tempstr = scat(myself,
5970Sstevel@tonic-gate 0, str, delim);
5980Sstevel@tonic-gate sfree(str);
5990Sstevel@tonic-gate if (tempstr)
6000Sstevel@tonic-gate str = tempstr;
6010Sstevel@tonic-gate else {
6020Sstevel@tonic-gate freeValue(val, 1);
6030Sstevel@tonic-gate return (MAP_NO_MEMORY);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate tempstr = scat(myself, 0, str,
6070Sstevel@tonic-gate val->val->value);
6080Sstevel@tonic-gate sfree(str);
6090Sstevel@tonic-gate if (tempstr)
6100Sstevel@tonic-gate str = tempstr;
6110Sstevel@tonic-gate else {
6120Sstevel@tonic-gate freeValue(val, 1);
6130Sstevel@tonic-gate return (MAP_NO_MEMORY);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate freeValue(val, 1);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate if (str == 0)
6200Sstevel@tonic-gate str = emptystr;
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate res = addCol2RuleValue(vt_string,
6230Sstevel@tonic-gate t->e->element.match.item[i].name,
6240Sstevel@tonic-gate str, strlen(str), trv);
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate if (str != emptystr)
6270Sstevel@tonic-gate sfree(str);
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate if (res == -1) {
6300Sstevel@tonic-gate return (MAP_INTERNAL_ERROR);
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate return (SUCCESS);
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate /*
6380Sstevel@tonic-gate * Updates 'rv' with NIS name=value pairs suitable to
6390Sstevel@tonic-gate * construct datum from namefield information.
6400Sstevel@tonic-gate * Some part based on createNisPlusEntry (from ldap_nisdbquery.c)
6410Sstevel@tonic-gate * This code assumes that from a given LDAP entry, applying the
6420Sstevel@tonic-gate * mapping rules, would give us one or more NIS entries, differing
6430Sstevel@tonic-gate * only in key.
6440Sstevel@tonic-gate */
6450Sstevel@tonic-gate suc_code
buildNISRuleValue(__nis_table_mapping_t * t,__nis_rule_value_t * rv,char * domain)6460Sstevel@tonic-gate buildNISRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
6470Sstevel@tonic-gate char *domain) {
6480Sstevel@tonic-gate int r, i, j, k, l, index, nrq, res, len;
6490Sstevel@tonic-gate int numItems, splitname, count, statP;
6500Sstevel@tonic-gate __nis_value_t *rval;
6510Sstevel@tonic-gate __nis_mapping_item_t *litem;
6520Sstevel@tonic-gate __nis_mapping_rule_t *rl;
6530Sstevel@tonic-gate __nis_rule_value_t *rvq;
6540Sstevel@tonic-gate char *value, *emptystr = "";
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate statP = SUCCESS;
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate /* Initialize default base */
6590Sstevel@tonic-gate __nisdb_get_tsd()->searchBase = t->objectDN->read.base;
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate /* Initialize rule-value rvq */
6620Sstevel@tonic-gate rvq = 0;
6630Sstevel@tonic-gate count = 0;
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate /* Add domainname to rule-value */
6660Sstevel@tonic-gate if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain),
6670Sstevel@tonic-gate rv)) {
6680Sstevel@tonic-gate return (MAP_INTERNAL_ERROR);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate for (r = 0; r < t->numRulesFromLDAP; r++) {
6720Sstevel@tonic-gate rl = t->ruleFromLDAP[r];
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate /* Set escapeFlag if RHS is "dn" to remove escape chars */
6750Sstevel@tonic-gate if (rl->rhs.numElements == 1 &&
6760Sstevel@tonic-gate rl->rhs.element->type == me_item &&
6770Sstevel@tonic-gate rl->rhs.element->element.item.type == mit_ldap &&
6780Sstevel@tonic-gate strcasecmp(rl->rhs.element->element.item.name, "dn")
6790Sstevel@tonic-gate == 0) {
6800Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '2';
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate rval = buildRvalue(&rl->rhs, mit_ldap, rv, NULL);
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate /* Reset escapeFlag */
6860Sstevel@tonic-gate __nisdb_get_tsd()->escapeFlag = '\0';
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate if (rval == 0) {
6890Sstevel@tonic-gate continue;
6900Sstevel@tonic-gate }
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate if (rval->numVals <= 0) {
6930Sstevel@tonic-gate /* Treat as invalid */
6940Sstevel@tonic-gate freeValue(rval, 1);
6950Sstevel@tonic-gate continue;
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate litem = buildLvalue(&rl->lhs, &rval, &numItems);
6990Sstevel@tonic-gate if (litem == 0) {
7000Sstevel@tonic-gate /* This will take care of numItems == 0 */
7010Sstevel@tonic-gate freeValue(rval, 1);
7020Sstevel@tonic-gate continue;
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate
7050Sstevel@tonic-gate if (rval->numVals > 1) {
7060Sstevel@tonic-gate if (numItems == 1 && litem->repeat)
7070Sstevel@tonic-gate nrq = rval->numVals;
7080Sstevel@tonic-gate else if (numItems > 1 && rval->repeat)
7090Sstevel@tonic-gate nrq = 1 + ((rval->numVals-1)/numItems);
7100Sstevel@tonic-gate else
7110Sstevel@tonic-gate nrq = 1;
7120Sstevel@tonic-gate } else
7130Sstevel@tonic-gate nrq = 1;
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /* Set splitname if splitfield names are specified */
7160Sstevel@tonic-gate for (i = 0; i < numItems; i++) {
7170Sstevel@tonic-gate if (strcasecmp(litem[i].name, N2LKEY) == 0 ||
7180Sstevel@tonic-gate strcasecmp(litem[i].name, N2LIPKEY) == 0 ||
7190Sstevel@tonic-gate strcasecmp(litem[i].name, N2LCOMMENT) == 0)
7200Sstevel@tonic-gate continue;
7210Sstevel@tonic-gate for (j = 0; j < t->numColumns; j++) {
7220Sstevel@tonic-gate if (strcmp(litem[i].name, t->column[j]) == 0)
7230Sstevel@tonic-gate break;
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate if (j == t->numColumns)
7260Sstevel@tonic-gate break;
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate splitname = (i < numItems)?1:0;
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate for (j = 0; j < nrq; j++) {
7320Sstevel@tonic-gate if (splitname == 1) {
7330Sstevel@tonic-gate /*
7340Sstevel@tonic-gate * Put every value of splitfieldname in a new
7350Sstevel@tonic-gate * rule-value. Helps generating splitfields.
7360Sstevel@tonic-gate */
7370Sstevel@tonic-gate rvq = growRuleValue(count, count + 1, rvq, 0);
7380Sstevel@tonic-gate if (rvq == 0) {
7390Sstevel@tonic-gate freeRuleValue(rvq, count);
7400Sstevel@tonic-gate freeValue(rval, 1);
7410Sstevel@tonic-gate freeMappingItem(litem, numItems);
7420Sstevel@tonic-gate return (MAP_INTERNAL_ERROR);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate count++;
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate for (k = j % nrq, l = 0; l < numItems; k += nrq, l++) {
7480Sstevel@tonic-gate /* If we run out of values, use empty strings */
7490Sstevel@tonic-gate if (k >= rval->numVals) {
7500Sstevel@tonic-gate value = emptystr;
7510Sstevel@tonic-gate len = 0;
7520Sstevel@tonic-gate } else {
7530Sstevel@tonic-gate value = rval->val[k].value;
7540Sstevel@tonic-gate len = rval->val[k].length;
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate res = (splitname == 1)?addCol2RuleValue(
7570Sstevel@tonic-gate vt_string, litem[l].name, value,
7580Sstevel@tonic-gate len, &rvq[count - 1]):0;
7590Sstevel@tonic-gate if (res != -1)
7600Sstevel@tonic-gate res = addCol2RuleValue(vt_string,
7610Sstevel@tonic-gate litem[l].name, value, len, rv);
7620Sstevel@tonic-gate if (res == -1) {
7630Sstevel@tonic-gate freeRuleValue(rvq, count);
7640Sstevel@tonic-gate freeValue(rval, 1);
7650Sstevel@tonic-gate freeMappingItem(litem, numItems);
7660Sstevel@tonic-gate return (MAP_INTERNAL_ERROR);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate freeValue(rval, 1);
7710Sstevel@tonic-gate rval = 0;
7720Sstevel@tonic-gate freeMappingItem(litem, numItems);
7730Sstevel@tonic-gate litem = 0;
7740Sstevel@tonic-gate numItems = 0;
7750Sstevel@tonic-gate } /* for r < t->numRulesFromLDAP */
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate statP = addSplitFieldValues(t, rvq, rv, count, domain);
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate if (rvq)
7800Sstevel@tonic-gate freeRuleValue(rvq, count);
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate if (verifyIndexMatch(t, 0, rv, 0, 0) == 0)
7830Sstevel@tonic-gate return (MAP_INDEXLIST_ERROR);
7840Sstevel@tonic-gate return (statP);
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate } /* end of buildNISRuleValue */
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate /*
7890Sstevel@tonic-gate * Convert rule-value to datum using namefield information
7900Sstevel@tonic-gate */
7910Sstevel@tonic-gate datum *
ruleValueToDatum(__nis_table_mapping_t * t,__nis_rule_value_t * rv,int * statP)7920Sstevel@tonic-gate ruleValueToDatum(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *statP) {
7930Sstevel@tonic-gate __nis_value_t *val;
7940Sstevel@tonic-gate datum *value;
7950Sstevel@tonic-gate char *str, *cstr, commentSep[3] = {' ', 0, 0};
7960Sstevel@tonic-gate char *myself = "ruleValueToDatum";
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate /* No error yet */
7990Sstevel@tonic-gate *statP = 0;
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate /* Return empty datum if no namefield information available */
8020Sstevel@tonic-gate if (t->e == 0) {
8030Sstevel@tonic-gate if ((value = am(myself, sizeof (*value))) == 0)
8040Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
8050Sstevel@tonic-gate return (value);
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate val = getMappingFormatArray(t->e->element.match.fmt, rv,
8090Sstevel@tonic-gate fa_item, t->e->element.match.numItems,
8100Sstevel@tonic-gate t->e->element.match.item);
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate if (val && val->val && val->val->value) {
8130Sstevel@tonic-gate if ((value = am(myself, sizeof (*value))) == 0) {
8140Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
8150Sstevel@tonic-gate freeValue(val, 1);
8160Sstevel@tonic-gate return (0);
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate /* Strip trailing whitespaces */
8200Sstevel@tonic-gate cstr = (char *)val->val->value + val->val->length;
8210Sstevel@tonic-gate for (; cstr >= (char *)val->val->value &&
8220Sstevel@tonic-gate (*cstr == ' ' || *cstr == '\t'); *cstr-- = '\0');
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate if (t->commentChar != '\0' &&
8250Sstevel@tonic-gate (str = findVal(N2LCOMMENT, rv, mit_nisplus)) != 0 &&
8260Sstevel@tonic-gate *str != '\0') {
8270Sstevel@tonic-gate commentSep[1] = t->commentChar;
8280Sstevel@tonic-gate cstr = scat(myself, F, commentSep, str);
8290Sstevel@tonic-gate if (cstr) {
8300Sstevel@tonic-gate value->dptr = scat(myself, F,
8310Sstevel@tonic-gate val->val->value, cstr);
8320Sstevel@tonic-gate sfree(cstr);
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate } else {
8350Sstevel@tonic-gate value->dptr = sdup(myself, T, val->val->value);
8360Sstevel@tonic-gate }
8370Sstevel@tonic-gate freeValue(val, 1);
8380Sstevel@tonic-gate if (value->dptr) {
8390Sstevel@tonic-gate value->dsize = strlen(value->dptr);
8400Sstevel@tonic-gate return (value);
8410Sstevel@tonic-gate } else {
8420Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
8430Sstevel@tonic-gate sfree(value);
8440Sstevel@tonic-gate return (0);
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate *statP = MAP_NAMEFIELD_MATCH_ERROR;
8490Sstevel@tonic-gate return (0);
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate datum *
getKeyFromRuleValue(__nis_table_mapping_t * t,__nis_rule_value_t * rv,int * nv,int * statP,bool_t xlate_to_lcase)8530Sstevel@tonic-gate getKeyFromRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *nv,
854*13143SBenjamin.Chang@Oracle.COM int *statP, bool_t xlate_to_lcase)
855*13143SBenjamin.Chang@Oracle.COM {
856*13143SBenjamin.Chang@Oracle.COM int i, j, k;
8570Sstevel@tonic-gate datum *key = 0;
8580Sstevel@tonic-gate char *str;
8590Sstevel@tonic-gate char *myself = "getKeyFromRuleValue";
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate /* No error yet */
8620Sstevel@tonic-gate *statP = 0;
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate if (rv == 0 || nv == 0)
8650Sstevel@tonic-gate return (0);
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) {
8680Sstevel@tonic-gate if (rv->colName[i] == 0)
8690Sstevel@tonic-gate continue;
8700Sstevel@tonic-gate if (strcasecmp(N2LKEY, rv->colName[i]) == 0 ||
871*13143SBenjamin.Chang@Oracle.COM strcasecmp(N2LIPKEY, rv->colName[i]) == 0) {
8720Sstevel@tonic-gate if ((*nv = rv->colVal[i].numVals) == 0)
8730Sstevel@tonic-gate return (0);
8740Sstevel@tonic-gate if ((key = am(myself, sizeof (key[0]) * *nv)) == 0) {
8750Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
8760Sstevel@tonic-gate return (0);
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate for (j = 0; j < *nv; j++) {
8790Sstevel@tonic-gate if ((str = rv->colVal[i].val[j].value) == 0) {
8800Sstevel@tonic-gate key[j].dsize = 0;
8810Sstevel@tonic-gate key[j].dptr = 0;
8820Sstevel@tonic-gate } else {
8830Sstevel@tonic-gate if (verifyIndexMatch(t, 0, 0,
884*13143SBenjamin.Chang@Oracle.COM rv->colName[i], str) == 0) {
8850Sstevel@tonic-gate key[j].dsize = 0;
8860Sstevel@tonic-gate key[j].dptr = 0;
8870Sstevel@tonic-gate continue;
8880Sstevel@tonic-gate }
889*13143SBenjamin.Chang@Oracle.COM
8900Sstevel@tonic-gate key[j].dsize = strlen(str);
8910Sstevel@tonic-gate key[j].dptr = am(myself,
892*13143SBenjamin.Chang@Oracle.COM key[j].dsize + 1);
8930Sstevel@tonic-gate if (key[j].dptr == 0) {
8940Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
8950Sstevel@tonic-gate for (--j; j >= 0; j--)
8960Sstevel@tonic-gate sfree(key[j].dptr);
8970Sstevel@tonic-gate sfree(key);
8980Sstevel@tonic-gate return (0);
8990Sstevel@tonic-gate }
900*13143SBenjamin.Chang@Oracle.COM
901*13143SBenjamin.Chang@Oracle.COM /* transliterate key to lowercase */
902*13143SBenjamin.Chang@Oracle.COM if (xlate_to_lcase == TRUE) {
903*13143SBenjamin.Chang@Oracle.COM
904*13143SBenjamin.Chang@Oracle.COM /*
905*13143SBenjamin.Chang@Oracle.COM * For multi-homed
906*13143SBenjamin.Chang@Oracle.COM * entries, skip over
907*13143SBenjamin.Chang@Oracle.COM * "YP_MULTI_" prefix.
908*13143SBenjamin.Chang@Oracle.COM */
909*13143SBenjamin.Chang@Oracle.COM k = 0;
910*13143SBenjamin.Chang@Oracle.COM if (strncmp(YPMULTI, str,
911*13143SBenjamin.Chang@Oracle.COM YPMULTISZ) == 0) {
912*13143SBenjamin.Chang@Oracle.COM k = YPMULTISZ;
913*13143SBenjamin.Chang@Oracle.COM bcopy(str, key[j].dptr,
914*13143SBenjamin.Chang@Oracle.COM YPMULTISZ);
915*13143SBenjamin.Chang@Oracle.COM }
916*13143SBenjamin.Chang@Oracle.COM while (k < key[j].dsize) {
917*13143SBenjamin.Chang@Oracle.COM key[j].dptr[k] =
918*13143SBenjamin.Chang@Oracle.COM (char)tolower(
919*13143SBenjamin.Chang@Oracle.COM (int)(uchar_t)
920*13143SBenjamin.Chang@Oracle.COM str[k]);
921*13143SBenjamin.Chang@Oracle.COM k++;
922*13143SBenjamin.Chang@Oracle.COM }
923*13143SBenjamin.Chang@Oracle.COM } else {
924*13143SBenjamin.Chang@Oracle.COM bcopy(str, key[j].dptr,
925*13143SBenjamin.Chang@Oracle.COM key[j].dsize);
926*13143SBenjamin.Chang@Oracle.COM }
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate }
9290Sstevel@tonic-gate return (key);
9300Sstevel@tonic-gate }
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate return (0);
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate /*
9360Sstevel@tonic-gate * Get the mapping structure corresponding to `map,domain.'
9370Sstevel@tonic-gate */
9380Sstevel@tonic-gate __nis_table_mapping_t *
mappingFromMap(char * map,char * domain,int * statP)9390Sstevel@tonic-gate mappingFromMap(char *map, char *domain, int *statP) {
9400Sstevel@tonic-gate char *mapPath;
9410Sstevel@tonic-gate __nis_table_mapping_t *t;
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate /* No error yet */
9440Sstevel@tonic-gate *statP = 0;
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate /* Construct map,domain. */
9470Sstevel@tonic-gate if ((mapPath = getFullMapName(map, domain)) == 0) {
9480Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
9490Sstevel@tonic-gate return (0);
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate
9520Sstevel@tonic-gate /* Get the hash table entry for the mapPath */
9530Sstevel@tonic-gate if ((t = __nis_find_item_mt(mapPath, &ldapMappingList, 1, 0))
9540Sstevel@tonic-gate == 0) {
9550Sstevel@tonic-gate *statP = MAP_NO_MAPPING_EXISTS;
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate sfree(mapPath);
9580Sstevel@tonic-gate return (t);
9590Sstevel@tonic-gate }
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate /*
9620Sstevel@tonic-gate * Verify at least one key value obtained from DIT matches the search key
9630Sstevel@tonic-gate * RETURNS: 1 MATCH
9640Sstevel@tonic-gate * 0 NO MATCH
9650Sstevel@tonic-gate * -1 NO KEY FOUND
9660Sstevel@tonic-gate */
9670Sstevel@tonic-gate static int
verifyKey(char * key,__nis_rule_value_t * rv)9680Sstevel@tonic-gate verifyKey(char *key, __nis_rule_value_t *rv) {
9690Sstevel@tonic-gate int i, j;
9700Sstevel@tonic-gate char *sipkey, *str;
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate for (i = 0; i < rv->numColumns; i++) {
9730Sstevel@tonic-gate if (rv->colName[i] == 0)
9740Sstevel@tonic-gate continue;
9750Sstevel@tonic-gate if (strcasecmp(N2LKEY, rv->colName[i]) == 0) {
9760Sstevel@tonic-gate if (rv->colVal[i].val == 0)
9770Sstevel@tonic-gate return (0);
9780Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) {
9790Sstevel@tonic-gate str = (char *)rv->colVal[i].val[j].value;
9800Sstevel@tonic-gate if (str && strcmp(str, key) == 0)
9810Sstevel@tonic-gate return (1);
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate return (0);
9840Sstevel@tonic-gate } else if (strcasecmp(N2LIPKEY, rv->colName[i]) == 0) {
9850Sstevel@tonic-gate if (checkIPaddress(key, strlen(key), &sipkey) > 0) {
9860Sstevel@tonic-gate if (rv->colVal[i].val == 0)
9870Sstevel@tonic-gate return (0);
9880Sstevel@tonic-gate for (j = 0; j < rv->colVal[i].numVals; j++) {
9890Sstevel@tonic-gate str = rv->colVal[i].val[j].value;
9900Sstevel@tonic-gate if (str && strcmp(str, sipkey) == 0) {
9910Sstevel@tonic-gate sfree(sipkey);
9920Sstevel@tonic-gate return (1);
9930Sstevel@tonic-gate }
9940Sstevel@tonic-gate }
9950Sstevel@tonic-gate sfree(sipkey);
9960Sstevel@tonic-gate }
9970Sstevel@tonic-gate return (0);
9980Sstevel@tonic-gate }
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate return (-1);
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate /*
10040Sstevel@tonic-gate * Read (i.e get and map) a single NIS entry from the LDAP DIT
10050Sstevel@tonic-gate */
10060Sstevel@tonic-gate bool_t
singleReadFromDIT(char * map,char * domain,datum * key,datum * value,int * statP)10070Sstevel@tonic-gate singleReadFromDIT(char *map, char *domain, datum *key, datum *value,
10080Sstevel@tonic-gate int *statP) {
10090Sstevel@tonic-gate __nis_table_mapping_t *t;
10100Sstevel@tonic-gate __nis_rule_value_t *rv_request = 0, *rv_result = 0;
10110Sstevel@tonic-gate __nis_ldap_search_t *ls;
10120Sstevel@tonic-gate __nis_object_dn_t *objectDN = NULL;
10130Sstevel@tonic-gate int i, rc, nr = 0, nv = 0;
10140Sstevel@tonic-gate datum *datval = 0;
10150Sstevel@tonic-gate char *skey, *str, *sipkey;
10160Sstevel@tonic-gate char *myself = "singleReadFromDIT";
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate *statP = SUCCESS;
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate if (!map || !domain || !key || !value) {
10210Sstevel@tonic-gate *statP = MAP_PARAM_ERROR;
10220Sstevel@tonic-gate return (FALSE);
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate /* Get the mapping information for the map */
10270Sstevel@tonic-gate if ((t = mappingFromMap(map, domain, statP)) == 0) {
10280Sstevel@tonic-gate /*
10290Sstevel@tonic-gate * No problem. We don't handle this map and domain. Maybe it's
10300Sstevel@tonic-gate * handled by a service other than NIS.
10310Sstevel@tonic-gate */
10320Sstevel@tonic-gate return (FALSE);
10330Sstevel@tonic-gate }
10340Sstevel@tonic-gate
10350Sstevel@tonic-gate /* NULL-terminated version of datum key for logging */
10360Sstevel@tonic-gate if ((skey = am(myself, key->dsize + 1)) == 0) {
10370Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
10380Sstevel@tonic-gate return (FALSE);
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate (void) memcpy(skey, key->dptr, key->dsize);
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate if ((str = getFullMapName(map, domain)) == 0) {
10430Sstevel@tonic-gate *statP = MAP_NO_MEMORY;
10440Sstevel@tonic-gate return (FALSE);
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate /* For each alternate mapping */
10480Sstevel@tonic-gate for (; t != 0; t = t->next) {
10490Sstevel@tonic-gate /* Verify objName */
10500Sstevel@tonic-gate if (strcmp(str, t->objName) != 0) {
10510Sstevel@tonic-gate continue;
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /* Verify if key matches the index */
10550Sstevel@tonic-gate if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 ||
10560Sstevel@tonic-gate verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0)
10570Sstevel@tonic-gate continue;
10580Sstevel@tonic-gate
10590Sstevel@tonic-gate /* Check if rulesFromLDAP are provided */
10600Sstevel@tonic-gate if (t->numRulesFromLDAP == 0) {
10610Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO,
10620Sstevel@tonic-gate "%s: No rulesFromLDAP information available "
10630Sstevel@tonic-gate "for %s (%s)", myself, t->dbId, map);
10640Sstevel@tonic-gate continue;
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate /* Convert key into rule-value */
10680Sstevel@tonic-gate if ((rv_request = datumToRuleValue(key, 0, t, 0, domain, TRUE,
10690Sstevel@tonic-gate statP)) == 0) {
10700Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
10710Sstevel@tonic-gate "%s: Conversion error %d (NIS to name=value "
10720Sstevel@tonic-gate "pairs) for NIS key (%s) for %s (%s)",
10730Sstevel@tonic-gate myself, *statP, skey, t->dbId, map);
10740Sstevel@tonic-gate continue;
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate /* Convert rule-value into ldap request */
10770Sstevel@tonic-gate for (objectDN = t->objectDN; objectDN &&
10780Sstevel@tonic-gate objectDN->read.base;
10790Sstevel@tonic-gate objectDN = objectDN->next) {
10800Sstevel@tonic-gate ls = createLdapRequest(t, rv_request, 0, 1, NULL,
10810Sstevel@tonic-gate objectDN);
10820Sstevel@tonic-gate if (ls == 0) {
10830Sstevel@tonic-gate *statP = MAP_CREATE_LDAP_REQUEST_ERROR;
10840Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
10850Sstevel@tonic-gate "%s: Failed to create ldapSearch "
10860Sstevel@tonic-gate "request for "
10870Sstevel@tonic-gate "NIS key (%s) for %s (%s) "
10880Sstevel@tonic-gate "for base %s",
10890Sstevel@tonic-gate myself, skey, t->dbId, map,
10900Sstevel@tonic-gate objectDN->read.base);
10910Sstevel@tonic-gate continue;
10920Sstevel@tonic-gate }
10930Sstevel@tonic-gate ls->timeout.tv_sec = SINGLE_ACCESS_TIMEOUT_SEC;
10940Sstevel@tonic-gate ls->timeout.tv_usec = SINGLE_ACCESS_TIMEOUT_USEC;
10950Sstevel@tonic-gate /* Query LDAP */
10960Sstevel@tonic-gate nr = (ls->isDN)?0:-1;
10970Sstevel@tonic-gate rv_result = ldapSearch(ls, &nr, 0, statP);
10980Sstevel@tonic-gate freeLdapSearch(ls);
10990Sstevel@tonic-gate if (rv_result == 0) {
11000Sstevel@tonic-gate if (*statP == LDAP_NO_SUCH_OBJECT) {
11010Sstevel@tonic-gate /* Entry does not exist in */
11020Sstevel@tonic-gate /* the ldap server */
11030Sstevel@tonic-gate }
11040Sstevel@tonic-gate continue;
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate freeRuleValue(rv_request, 1);
11070Sstevel@tonic-gate rv_request = 0;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate /* if result > 1, first match will be returned */
11100Sstevel@tonic-gate if (nr > 1) {
11110Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO,
11120Sstevel@tonic-gate "%s: %d ldapSearch results "
11130Sstevel@tonic-gate "for NIS key (%s) "
11140Sstevel@tonic-gate "for %s (%s) for base %s. "
11150Sstevel@tonic-gate "First match will be returned ",
11160Sstevel@tonic-gate myself, nr, skey, t->dbId, map,
11170Sstevel@tonic-gate objectDN->read.base);
11180Sstevel@tonic-gate }
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate for (i = 0; i < nr; i++) {
11210Sstevel@tonic-gate /* Convert LDAP data to NIS equivalents */
11220Sstevel@tonic-gate *statP = buildNISRuleValue(t, &rv_result[i],
11230Sstevel@tonic-gate domain);
11240Sstevel@tonic-gate if (*statP == MAP_INDEXLIST_ERROR)
11250Sstevel@tonic-gate continue;
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate if (*statP != SUCCESS) {
11280Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING,
11290Sstevel@tonic-gate "%s: Conversion error %d (LDAP to "
11300Sstevel@tonic-gate "name=value pairs) for NIS key (%s) "
11310Sstevel@tonic-gate "for %s (%s) for base %s", myself,
11320Sstevel@tonic-gate *statP, skey,
11330Sstevel@tonic-gate t->dbId, map, objectDN->read.base);
11340Sstevel@tonic-gate continue;
11350Sstevel@tonic-gate }
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate /*
11380Sstevel@tonic-gate * Check if 'key' from the ldap result matches the key
11390Sstevel@tonic-gate * provided by our caller
11400Sstevel@tonic-gate */
11410Sstevel@tonic-gate if ((rc = verifyKey(skey, &rv_result[i]))
11420Sstevel@tonic-gate == -1) {
11430Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO,
11440Sstevel@tonic-gate "%s: Cannot verify key from ldap "
11450Sstevel@tonic-gate "result for NIS key (%s) for %s (%s) "
11460Sstevel@tonic-gate "for base %s",
11470Sstevel@tonic-gate myself, skey, t->dbId, map,
11480Sstevel@tonic-gate objectDN->read.base);
11490Sstevel@tonic-gate continue;
11500Sstevel@tonic-gate }
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate if (rc == 1) {
11530Sstevel@tonic-gate datval = ruleValueToDatum(t,
11540Sstevel@tonic-gate &rv_result[i], statP);
11550Sstevel@tonic-gate if (datval == 0) {
11560Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK,
11570Sstevel@tonic-gate LOG_WARNING,
11580Sstevel@tonic-gate "%s: Conversion error %d "
11590Sstevel@tonic-gate "(name=value pairs to NIS) "
11600Sstevel@tonic-gate "for NIS key (%s) for %s (%s)"
11610Sstevel@tonic-gate " for base %s",
11620Sstevel@tonic-gate myself,
11630Sstevel@tonic-gate *statP, skey, t->dbId, map,
11640Sstevel@tonic-gate objectDN->read.base);
11650Sstevel@tonic-gate continue;
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate if (value) {
11680Sstevel@tonic-gate value->dptr = datval->dptr;
11690Sstevel@tonic-gate value->dsize = datval->dsize;
11700Sstevel@tonic-gate }
11710Sstevel@tonic-gate sfree(datval);
11720Sstevel@tonic-gate sfree(skey);
11730Sstevel@tonic-gate freeRuleValue(rv_result, nr);
11740Sstevel@tonic-gate rv_result = 0;
11750Sstevel@tonic-gate *statP = SUCCESS;
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate /* Free full map name */
11780Sstevel@tonic-gate sfree(str);
11790Sstevel@tonic-gate
11800Sstevel@tonic-gate return (TRUE);
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate }
11830Sstevel@tonic-gate freeRuleValue(rv_result, nr);
11840Sstevel@tonic-gate rv_result = 0;
11850Sstevel@tonic-gate } /* end of for over objectDN */
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate if (rv_request != 0) {
11880Sstevel@tonic-gate freeRuleValue(rv_request, 1);
11890Sstevel@tonic-gate rv_request = 0;
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate if (rv_result != 0) {
11920Sstevel@tonic-gate freeRuleValue(rv_result, nr);
11930Sstevel@tonic-gate rv_result = 0;
11940Sstevel@tonic-gate }
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate sfree(skey);
11970Sstevel@tonic-gate *statP = MAP_NO_MATCHING_KEY;
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate /* Free full map name */
12000Sstevel@tonic-gate sfree(str);
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate return (FALSE);
12030Sstevel@tonic-gate }
12040Sstevel@tonic-gate
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate /*
12070Sstevel@tonic-gate * Maps and writes a single NIS entry to the LDAP DIT
12080Sstevel@tonic-gate */
12090Sstevel@tonic-gate int
singleWriteToDIT(char * map,char * domain,datum * key,datum * value,bool_t replace)12100Sstevel@tonic-gate singleWriteToDIT(char *map, char *domain, datum *key, datum *value,
12110Sstevel@tonic-gate bool_t replace) {
12120Sstevel@tonic-gate __nis_table_mapping_t *t;
12130Sstevel@tonic-gate __nis_rule_value_t *rv, *frv;
12140Sstevel@tonic-gate __nis_ldap_search_t *ls;
12150Sstevel@tonic-gate int statP = SUCCESS, flag;
12160Sstevel@tonic-gate int nv, nr, i, rc, collapse;
12170Sstevel@tonic-gate char *dn = 0, *skey, *svalue, *str;
12180Sstevel@tonic-gate char *myself = "singleWriteToDIT";
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate if (!map || !domain || !key || !value) {
12210Sstevel@tonic-gate return (MAP_PARAM_ERROR);
12220Sstevel@tonic-gate }
12230Sstevel@tonic-gate
12240Sstevel@tonic-gate /* Return SUCCESS for empty or whitespace key */
12250Sstevel@tonic-gate for (i = 0; i < key->dsize && (key->dptr[i] == 0 ||
12260Sstevel@tonic-gate key->dptr[i] == ' ' || key->dptr[i] == '\t'); i++);
12270Sstevel@tonic-gate if (i >= key->dsize)
12280Sstevel@tonic-gate return (SUCCESS);
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate /* Get the mapping information for the map */
12310Sstevel@tonic-gate if ((t = mappingFromMap(map, domain, &statP)) == 0) {
12320Sstevel@tonic-gate /*
12330Sstevel@tonic-gate * No problem. We don't handle this map and domain. Maybe it's
12340Sstevel@tonic-gate * handled by a service other than NIS.
12350Sstevel@tonic-gate */
12360Sstevel@tonic-gate return (statP);
12370Sstevel@tonic-gate }
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate /* NULL-terminated version of key and value for logging */
12400Sstevel@tonic-gate if ((skey = am(myself, key->dsize + 1)) == 0)
12410Sstevel@tonic-gate return (MAP_NO_MEMORY);
12420Sstevel@tonic-gate (void) memcpy(skey, key->dptr, key->dsize);
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate if ((svalue = am(myself, value->dsize + 1)) == 0) {
12450Sstevel@tonic-gate sfree(skey);
12460Sstevel@tonic-gate return (MAP_NO_MEMORY);
12470Sstevel@tonic-gate }
12480Sstevel@tonic-gate (void) memcpy(svalue, value->dptr, value->dsize);
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate if ((str = getFullMapName(map, domain)) == 0) {
12510Sstevel@tonic-gate sfree(skey);
12520Sstevel@tonic-gate sfree(svalue);
12530Sstevel@tonic-gate return (MAP_NO_MEMORY);
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate /* For each alternate mapping */
12570Sstevel@tonic-gate for (flag = 0; t != 0; t = t->next) {
12580Sstevel@tonic-gate /* Verify objName */
12590Sstevel@tonic-gate if (strcmp(str, t->objName) != 0) {
12600Sstevel@tonic-gate continue;
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate /* Verify if key matches the index */
12640Sstevel@tonic-gate if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 ||
12650Sstevel@tonic-gate verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0)
12660Sstevel@tonic-gate continue;
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate /* Check the writespecs */
12690Sstevel@tonic-gate if (t->objectDN->write.base == 0) {
12700Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO,
12710Sstevel@tonic-gate "%s: No baseDN in writespec. Write disabled "
12720Sstevel@tonic-gate "for %s (%s)", myself, t->dbId, map);
12730Sstevel@tonic-gate continue;
12740Sstevel@tonic-gate }
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate /* Check if rulesToLDAP are provided */
12770Sstevel@tonic-gate if (t->numRulesToLDAP == 0) {
12780Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO,
12790Sstevel@tonic-gate "%s: No rulesToLDAP. Write disabled for "
12800Sstevel@tonic-gate "%s (%s)", myself, t->dbId, map);
12810Sstevel@tonic-gate continue;
12820Sstevel@tonic-gate }
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate /* Set flag to indicate write is enabled */
12850Sstevel@tonic-gate flag = 1;
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate /* Convert key and value into an array of rule-values */
12880Sstevel@tonic-gate if ((rv = datumToRuleValue(key, value, t, &nv, domain, FALSE,
12890Sstevel@tonic-gate &statP)) == 0) {
12900Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
12910Sstevel@tonic-gate "%s: Conversion error %d (NIS to name=value "
12920Sstevel@tonic-gate "pairs) for NIS data (key=%s, value=%s) "
12930Sstevel@tonic-gate "for %s (%s)",
12940Sstevel@tonic-gate myself, statP, skey, svalue, t->dbId, map);
12950Sstevel@tonic-gate sfree(skey);
12960Sstevel@tonic-gate sfree(svalue);
12970Sstevel@tonic-gate
12980Sstevel@tonic-gate /* Free full map name */
12990Sstevel@tonic-gate sfree(str);
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate return (statP);
13020Sstevel@tonic-gate }
13030Sstevel@tonic-gate
13040Sstevel@tonic-gate /* Convert NIS data to LDAP equivalents for each rule-value */
13050Sstevel@tonic-gate for (i = 0; i < nv; i++) {
13060Sstevel@tonic-gate /* Verify indexlist with name=value pairs */
13070Sstevel@tonic-gate if (verifyIndexMatch(t, 0, &rv[i], 0, 0) == 0)
13080Sstevel@tonic-gate break;
13090Sstevel@tonic-gate
13100Sstevel@tonic-gate /* Create LDAP request and LDAP name=value pairs */
13110Sstevel@tonic-gate if ((ls = createLdapRequest(t, &rv[i],
13120Sstevel@tonic-gate 0, 0, NULL, NULL)) == 0) {
13130Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
13140Sstevel@tonic-gate "%s: Conversion error (name=value pairs"
13150Sstevel@tonic-gate " to LDAP) for NIS data "
13160Sstevel@tonic-gate "(key=%s, value=%s) for %s (%s)",
13170Sstevel@tonic-gate myself, skey, svalue, t->dbId, map);
13180Sstevel@tonic-gate freeRuleValue(rv, nv);
13190Sstevel@tonic-gate sfree(skey);
13200Sstevel@tonic-gate sfree(svalue);
13210Sstevel@tonic-gate
13220Sstevel@tonic-gate /* Free full map name */
13230Sstevel@tonic-gate sfree(str);
13240Sstevel@tonic-gate
13250Sstevel@tonic-gate return (MAP_CREATE_LDAP_REQUEST_ERROR);
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate freeLdapSearch(ls);
13280Sstevel@tonic-gate /* printRuleValue(&rv[i]); */
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate /* If i < nv then this alternate mapping isn't the one */
13320Sstevel@tonic-gate if (i < nv)
13330Sstevel@tonic-gate continue;
13340Sstevel@tonic-gate
13350Sstevel@tonic-gate /*
13360Sstevel@tonic-gate * Merge rule-values with the same DN so that we have
13370Sstevel@tonic-gate * one ldap write request for each DN
13380Sstevel@tonic-gate */
13390Sstevel@tonic-gate nr = nv;
13400Sstevel@tonic-gate frv = mergeRuleValueWithSameDN(rv, &nr);
13410Sstevel@tonic-gate freeRuleValue(rv, nv);
13420Sstevel@tonic-gate if (frv == 0) {
13430Sstevel@tonic-gate if (nr == -1) {
13440Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
13450Sstevel@tonic-gate "%s: Unable to merge LDAP write "
13460Sstevel@tonic-gate "requests to same DN for NIS data "
13470Sstevel@tonic-gate "(key=%s, value=%s) for %s (%s)",
13480Sstevel@tonic-gate myself, skey, svalue, t->dbId, map);
13490Sstevel@tonic-gate statP = MAP_INTERNAL_ERROR;
13500Sstevel@tonic-gate } else if (nr == 0) {
13510Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING,
13520Sstevel@tonic-gate "%s: Cannot generate write DN due to "
13530Sstevel@tonic-gate "missing information for NIS data "
13540Sstevel@tonic-gate "(key=%s, value=%s) for %s (%s)",
13550Sstevel@tonic-gate myself, skey, svalue, t->dbId, map);
13560Sstevel@tonic-gate statP = MAP_NO_DN;
13570Sstevel@tonic-gate }
13580Sstevel@tonic-gate sfree(skey);
13590Sstevel@tonic-gate sfree(svalue);
13600Sstevel@tonic-gate
13610Sstevel@tonic-gate /* Free full map name */
13620Sstevel@tonic-gate sfree(str);
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate return (statP);
13650Sstevel@tonic-gate }
13660Sstevel@tonic-gate
13670Sstevel@tonic-gate /* Write to the LDAP server */
13680Sstevel@tonic-gate for (collapse = 0, i = 0; i < nr; i++) {
13690Sstevel@tonic-gate if ((dn = findVal("dn", &frv[i], mit_ldap)) != 0) {
13700Sstevel@tonic-gate if (replace == FALSE) {
13710Sstevel@tonic-gate /* ldap add */
13720Sstevel@tonic-gate rc = ldapAdd(dn, &frv[i],
13730Sstevel@tonic-gate t->objectDN->write.attrs, 0);
13740Sstevel@tonic-gate } else {
13750Sstevel@tonic-gate /* ldap modify with addFirst set */
13760Sstevel@tonic-gate rc = ldapModify(dn, &frv[i],
13770Sstevel@tonic-gate t->objectDN->write.attrs, 1);
13780Sstevel@tonic-gate }
13790Sstevel@tonic-gate
13800Sstevel@tonic-gate /* if we get err=20, collapse and try again */
13810Sstevel@tonic-gate if (!collapse &&
13820Sstevel@tonic-gate (rc == LDAP_TYPE_OR_VALUE_EXISTS) &&
13830Sstevel@tonic-gate (collapseRuleValue(&frv[i]) == 1)) {
13840Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING,
13850Sstevel@tonic-gate "%s: Ignoring values differing "
13860Sstevel@tonic-gate "in case from NIS data (key=%s,"
13870Sstevel@tonic-gate " value=%s) for (dn: %s) for "
13880Sstevel@tonic-gate "%s (%s)", myself, skey,
13890Sstevel@tonic-gate svalue, dn, t->dbId, map);
13900Sstevel@tonic-gate collapse = 1;
13910Sstevel@tonic-gate i--;
13920Sstevel@tonic-gate continue;
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate collapse = 0;
13960Sstevel@tonic-gate if (rc != LDAP_SUCCESS) {
13970Sstevel@tonic-gate /* Log error */
13980Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
13990Sstevel@tonic-gate "%s: %s error %d (%s) for "
14000Sstevel@tonic-gate "(dn: %s) for NIS data "
14010Sstevel@tonic-gate "(key=%s, value=%s) "
14020Sstevel@tonic-gate "for %s (%s)",
14030Sstevel@tonic-gate myself, (replace == TRUE) ?
14040Sstevel@tonic-gate "ldapModify" : "ldapAdd", rc,
14050Sstevel@tonic-gate ldap_err2string(rc), dn, skey,
14060Sstevel@tonic-gate svalue, t->dbId, map);
14070Sstevel@tonic-gate
14080Sstevel@tonic-gate /* Dumping failed call may be useful */
14090Sstevel@tonic-gate /* printRuleValue(&frv[i]); */
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate /*
14120Sstevel@tonic-gate * Return the error code and let wrapper
14130Sstevel@tonic-gate * sort out if mapping should continue
14140Sstevel@tonic-gate * or abort.
14150Sstevel@tonic-gate */
14160Sstevel@tonic-gate statP = rc;
14170Sstevel@tonic-gate sfree(skey);
14180Sstevel@tonic-gate sfree(svalue);
14190Sstevel@tonic-gate freeRuleValue(frv, nr);
14200Sstevel@tonic-gate
14210Sstevel@tonic-gate /* Free full map name */
14220Sstevel@tonic-gate sfree(str);
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate return (statP);
14250Sstevel@tonic-gate }
14260Sstevel@tonic-gate }
14270Sstevel@tonic-gate }
14280Sstevel@tonic-gate
14290Sstevel@tonic-gate freeRuleValue(frv, nr);
14300Sstevel@tonic-gate }
14310Sstevel@tonic-gate
14320Sstevel@tonic-gate sfree(skey);
14330Sstevel@tonic-gate sfree(svalue);
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate /* Free full map name */
14360Sstevel@tonic-gate sfree(str);
14370Sstevel@tonic-gate
14380Sstevel@tonic-gate return ((flag)?SUCCESS:MAP_WRITE_DISABLED);
14390Sstevel@tonic-gate }
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate suc_code
collapseRuleValue(__nis_rule_value_t * rv)14420Sstevel@tonic-gate collapseRuleValue(__nis_rule_value_t *rv) {
14430Sstevel@tonic-gate int i, j, k, flag;
14440Sstevel@tonic-gate
14450Sstevel@tonic-gate /* Using 'val' to appease cstyle's 80 chars/line limit */
14460Sstevel@tonic-gate __nis_value_t *val;
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate for (i = 0, flag = 0; i < rv->numAttrs; i++) {
14490Sstevel@tonic-gate val = &rv->attrVal[i];
14500Sstevel@tonic-gate for (j = 1; j < val->numVals; j++) {
14510Sstevel@tonic-gate for (k = 0; k < j; k++) {
14520Sstevel@tonic-gate if (val->val[j].length != val->val[k].length)
14530Sstevel@tonic-gate continue;
14540Sstevel@tonic-gate if (val->val[k].length == 0)
14550Sstevel@tonic-gate continue;
14560Sstevel@tonic-gate if (strncasecmp(val->val[j].value,
14570Sstevel@tonic-gate val->val[k].value,
14580Sstevel@tonic-gate val->val[j].length) != 0)
14590Sstevel@tonic-gate continue;
14600Sstevel@tonic-gate flag = 1;
14610Sstevel@tonic-gate sfree(val->val[j].value);
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate #ifdef ORDER_NOT_IMPORTANT
14640Sstevel@tonic-gate val->val[j--] = val->val[--val->numVals];
14650Sstevel@tonic-gate #else
14660Sstevel@tonic-gate /* Order needs to be maintained */
14670Sstevel@tonic-gate for (k = j + 1; k < val->numVals; k++)
14680Sstevel@tonic-gate val->val[k - 1] = val->val[k];
14690Sstevel@tonic-gate j--;
14700Sstevel@tonic-gate val->numVals--;
14710Sstevel@tonic-gate #endif
14720Sstevel@tonic-gate break;
14730Sstevel@tonic-gate }
14740Sstevel@tonic-gate }
14750Sstevel@tonic-gate }
14760Sstevel@tonic-gate return (flag);
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate /* ObjectClass lookup table */
14800Sstevel@tonic-gate static struct {
14810Sstevel@tonic-gate const char *attrType;
14820Sstevel@tonic-gate const char *objectClass;
14830Sstevel@tonic-gate } oc_lookup[] = {
14840Sstevel@tonic-gate { "o", "objectclass=organization"},
14850Sstevel@tonic-gate { "organizationname", "objectclass=organization"},
14860Sstevel@tonic-gate { "2.5.4.10", "objectclass=organization"},
14870Sstevel@tonic-gate { "ou", "objectclass=organizationalunit"},
14880Sstevel@tonic-gate { "organizationalunitname", "objectclass=organizationalunit"},
14890Sstevel@tonic-gate { "2.5.4.11", "objectclass=organizationalunit"},
14900Sstevel@tonic-gate { "c", "objectclass=country"},
14910Sstevel@tonic-gate { "countryname", "objectclass=country"},
14920Sstevel@tonic-gate { "2.5.4.6", "objectclass=country"},
14930Sstevel@tonic-gate { "dc", "objectclass=domain"},
14940Sstevel@tonic-gate { "domaincomponent", "objectclass=domain"},
14950Sstevel@tonic-gate { "0.9.2342.19200300.100.1.25", "objectclass=domain"},
14960Sstevel@tonic-gate { "nismapname", "objectclass=nismap"},
14970Sstevel@tonic-gate { "1.3.6.1.1.1.1.26", "objectclass=nismap"},
14980Sstevel@tonic-gate { "automountmapname", "objectclass=automountmap"},
14990Sstevel@tonic-gate { "1.3.6.1.1.1.1.31", "objectclass=automountmap"},
15000Sstevel@tonic-gate { 0, 0}
15010Sstevel@tonic-gate };
15020Sstevel@tonic-gate
15030Sstevel@tonic-gate /*
15040Sstevel@tonic-gate * Returns the name of the objectclass to which the object
15050Sstevel@tonic-gate * represented by the given 'rdn' will most likely belong to.
15060Sstevel@tonic-gate * The return value is in static memory so it should not be
15070Sstevel@tonic-gate * freed
15080Sstevel@tonic-gate */
15090Sstevel@tonic-gate const char *
getObjectClass(char * rdn)15100Sstevel@tonic-gate getObjectClass(char *rdn) {
15110Sstevel@tonic-gate
15120Sstevel@tonic-gate char *attrtype, *p;
15130Sstevel@tonic-gate int len, i;
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate /* Skip leading whitespaces */
15160Sstevel@tonic-gate for (p = rdn; *p == ' ' || *p == '\t'; p++);
15170Sstevel@tonic-gate if (*p == '\0')
15180Sstevel@tonic-gate return (0);
15190Sstevel@tonic-gate attrtype = p;
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate /* Find '=' */
15220Sstevel@tonic-gate if ((p = strchr(attrtype, '=')) == 0 || p == attrtype ||
15230Sstevel@tonic-gate *(p - 1) == '\\')
15240Sstevel@tonic-gate return (0);
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate /*
15270Sstevel@tonic-gate * Skip trailing whitespaces in attrtype
15280Sstevel@tonic-gate * Don't worry, p won't decrease beyond attrtype
15290Sstevel@tonic-gate */
15300Sstevel@tonic-gate for (--p; *p == ' ' || *p == '\t'; p--);
15310Sstevel@tonic-gate len = p - attrtype + 1;
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate for (i = 0; oc_lookup[i].attrType; i++)
15340Sstevel@tonic-gate if (!strncasecmp(oc_lookup[i].attrType, attrtype, len))
15350Sstevel@tonic-gate /* Check length is right */
15360Sstevel@tonic-gate if (len == strlen(oc_lookup[i].attrType))
15370Sstevel@tonic-gate return (oc_lookup[i].objectClass);
15380Sstevel@tonic-gate
15390Sstevel@tonic-gate return (0);
15400Sstevel@tonic-gate }
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate /*
15430Sstevel@tonic-gate * Split 'dn' into rdn and parentdn based on the first
15440Sstevel@tonic-gate * occurrence of unescaped 'comma' or 'semicolon'. rdn
15450Sstevel@tonic-gate * lies on the LHS while parentdn lies on the RHS of the
15460Sstevel@tonic-gate * split. If none found, then an empty string ("") is
15470Sstevel@tonic-gate * assigned to parentdn
15480Sstevel@tonic-gate */
15490Sstevel@tonic-gate int
splitDN(char * dn,char ** rdn,char ** parentdn)15500Sstevel@tonic-gate splitDN(char *dn, char **rdn, char **parentdn) {
15510Sstevel@tonic-gate char *value, *name;
15520Sstevel@tonic-gate char *myself = "splitDN";
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate if ((name = sdup(myself, T, dn)) == 0)
15550Sstevel@tonic-gate return (-1);
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate for (value = name; *value != '\0'; value++) {
15580Sstevel@tonic-gate if (*value == ',' || *value == ';')
15590Sstevel@tonic-gate if (value == name || *(value - 1) != '\\')
15600Sstevel@tonic-gate break;
15610Sstevel@tonic-gate }
15620Sstevel@tonic-gate
15630Sstevel@tonic-gate if (*value != '\0') {
15640Sstevel@tonic-gate *value = '\0';
15650Sstevel@tonic-gate value++;
15660Sstevel@tonic-gate } else
15670Sstevel@tonic-gate value = 0;
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate if (parentdn) {
15700Sstevel@tonic-gate if ((*parentdn = sdup(myself, T, value)) == 0) {
15710Sstevel@tonic-gate sfree(name);
15720Sstevel@tonic-gate return (-1);
15730Sstevel@tonic-gate }
15740Sstevel@tonic-gate }
15750Sstevel@tonic-gate if (rdn)
15760Sstevel@tonic-gate *rdn = name;
15770Sstevel@tonic-gate else
15780Sstevel@tonic-gate sfree(name);
15790Sstevel@tonic-gate
15800Sstevel@tonic-gate return (1);
15810Sstevel@tonic-gate }
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate /*
15840Sstevel@tonic-gate * FUNCTION : makeNISObject()
15850Sstevel@tonic-gate *
15860Sstevel@tonic-gate * DESCRIPTION: Sets up a nis Object in the DIT.
15870Sstevel@tonic-gate *
15880Sstevel@tonic-gate * GIVEN :
15890Sstevel@tonic-gate * Case 1: Both 'domain' and 'dn' are non-NULL
15900Sstevel@tonic-gate * Create nisDomainObject with the given information
15910Sstevel@tonic-gate * Case 2: Only 'domain' is non-NULL
15920Sstevel@tonic-gate * Obtain the 'dn' from the nisLDAPdomainContext list
15930Sstevel@tonic-gate * Create nisDomainObject with the above information
15940Sstevel@tonic-gate * Case 3: Only 'dn' is non-NULL
15950Sstevel@tonic-gate * Create an object with the 'dn'
15960Sstevel@tonic-gate * Here we guess the objectclass attribute, based on
15970Sstevel@tonic-gate * oc_lookup table
15980Sstevel@tonic-gate * Case 4: Both 'domain' and 'dn' are NULL
15990Sstevel@tonic-gate * Error
16000Sstevel@tonic-gate *
16010Sstevel@tonic-gate * RETURNS : SUCCESS = It worked
16020Sstevel@tonic-gate * FAILURE = There was a problem.
16030Sstevel@tonic-gate */
16040Sstevel@tonic-gate suc_code
makeNISObject(char * domain,char * dn)16050Sstevel@tonic-gate makeNISObject(char *domain, char *dn) {
16060Sstevel@tonic-gate __nis_rule_value_t *rv;
16070Sstevel@tonic-gate __nis_ldap_search_t *ls;
16080Sstevel@tonic-gate int i, rc, nr, add_rc;
16090Sstevel@tonic-gate char *val;
16100Sstevel@tonic-gate char *myself = "makeNISObject";
16110Sstevel@tonic-gate
16120Sstevel@tonic-gate if (!dn && !domain)
16130Sstevel@tonic-gate return (FAILURE);
16140Sstevel@tonic-gate
16150Sstevel@tonic-gate /*
16160Sstevel@tonic-gate * If only 'domain' name is provided, then
16170Sstevel@tonic-gate * try to find dn from the nisLDAPdomainContext
16180Sstevel@tonic-gate * list generated by the parser
16190Sstevel@tonic-gate */
16200Sstevel@tonic-gate if (!dn) {
16210Sstevel@tonic-gate for (i = 0; i < ypDomains.numDomains; i++) {
16220Sstevel@tonic-gate if (ypDomains.domainLabels[i] == 0)
16230Sstevel@tonic-gate continue;
16240Sstevel@tonic-gate if (strcasecmp(domain, ypDomains.domainLabels[i])
16250Sstevel@tonic-gate == 0) {
16260Sstevel@tonic-gate dn = ypDomains.domains[i];
16270Sstevel@tonic-gate break;
16280Sstevel@tonic-gate }
16290Sstevel@tonic-gate }
16300Sstevel@tonic-gate if (!dn)
16310Sstevel@tonic-gate return (FAILURE);
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate
16340Sstevel@tonic-gate /*
16350Sstevel@tonic-gate * If only 'dn' is given, then it means that the
16360Sstevel@tonic-gate * caller simply wants to a create an entry for
16370Sstevel@tonic-gate * that 'dn'.
16380Sstevel@tonic-gate *
16390Sstevel@tonic-gate * If 'domain' is given, then check if the 'dn'
16400Sstevel@tonic-gate * has already been set up as a nis domain object.
16410Sstevel@tonic-gate * If not, see if we can make it become one.
16420Sstevel@tonic-gate */
16430Sstevel@tonic-gate if (domain) {
16440Sstevel@tonic-gate /*
16450Sstevel@tonic-gate * Check to see if the nis domain object has
16460Sstevel@tonic-gate * already been set up
16470Sstevel@tonic-gate */
16480Sstevel@tonic-gate ls = buildLdapSearch(dn, LDAP_SCOPE_BASE, 0, 0,
16490Sstevel@tonic-gate "objectclass=*", 0, 0, 0);
16500Sstevel@tonic-gate if (ls == 0) {
16510Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
16520Sstevel@tonic-gate "%s: Unable to create ldapSearch "
16530Sstevel@tonic-gate "request for dn: %s", myself, dn);
16540Sstevel@tonic-gate return (FAILURE);
16550Sstevel@tonic-gate }
16560Sstevel@tonic-gate nr = -1;
16570Sstevel@tonic-gate rv = ldapSearch(ls, &nr, 0, &rc);
16580Sstevel@tonic-gate freeLdapSearch(ls);
16590Sstevel@tonic-gate if (rc == LDAP_SUCCESS) {
16600Sstevel@tonic-gate val = findVal("nisDomain", rv, mit_ldap);
16610Sstevel@tonic-gate if (val != NULL) {
16620Sstevel@tonic-gate /*
16630Sstevel@tonic-gate * Yes, nis domain object found. Check
16640Sstevel@tonic-gate * to see if the domain names match.
16650Sstevel@tonic-gate * If so, we are done. If not, log
16660Sstevel@tonic-gate * a warning message, and return SUCCESS.
16670Sstevel@tonic-gate */
16680Sstevel@tonic-gate if (strcasecmp(val, domain) == 0) {
16690Sstevel@tonic-gate freeRuleValue(rv, nr);
16700Sstevel@tonic-gate return (SUCCESS);
16710Sstevel@tonic-gate } else {
16720Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK,
16730Sstevel@tonic-gate LOG_WARNING,
16740Sstevel@tonic-gate "%s: Entry (dn: %s) already "
16750Sstevel@tonic-gate "contains a nis domain name "
16760Sstevel@tonic-gate "(%s). The domain name (%s) "
16770Sstevel@tonic-gate "is not added.",
16780Sstevel@tonic-gate myself, dn, val, domain);
16790Sstevel@tonic-gate freeRuleValue(rv, nr);
16800Sstevel@tonic-gate return (SUCCESS);
16810Sstevel@tonic-gate }
16820Sstevel@tonic-gate } else {
16830Sstevel@tonic-gate freeRuleValue(rv, nr);
16840Sstevel@tonic-gate /*
16850Sstevel@tonic-gate * Entry for the 'dn' exists, but it
16860Sstevel@tonic-gate * is not a nis domain object yet.
16870Sstevel@tonic-gate * Add the nisDoamin attribute and
16880Sstevel@tonic-gate * the nisDomainObject objectclass to
16890Sstevel@tonic-gate * the entry.
16900Sstevel@tonic-gate */
16910Sstevel@tonic-gate if ((rv = initRuleValue(1, 0)) == 0)
16920Sstevel@tonic-gate return (FAILURE);
16930Sstevel@tonic-gate
16940Sstevel@tonic-gate if (addSAttr2RuleValue("nisDomain",
16950Sstevel@tonic-gate domain, rv) == -1) {
16960Sstevel@tonic-gate freeRuleValue(rv, 1);
16970Sstevel@tonic-gate return (FAILURE);
16980Sstevel@tonic-gate }
16990Sstevel@tonic-gate rc = ldapModify(dn, rv,
17000Sstevel@tonic-gate "objectclass=nisDomainObject",
17010Sstevel@tonic-gate 0);
17020Sstevel@tonic-gate freeRuleValue(rv, 1);
17030Sstevel@tonic-gate if (rc == LDAP_SUCCESS) {
17040Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK,
17050Sstevel@tonic-gate LOG_INFO,
17060Sstevel@tonic-gate "%s: entry (dn: %s) "
17070Sstevel@tonic-gate "modified to be an "
17080Sstevel@tonic-gate "nis domain object",
17090Sstevel@tonic-gate myself, dn);
17100Sstevel@tonic-gate return (SUCCESS);
17110Sstevel@tonic-gate } else {
17120Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK,
17130Sstevel@tonic-gate LOG_ERR,
17140Sstevel@tonic-gate "%s: unable to modify "
17150Sstevel@tonic-gate "entry (dn: %s) to be "
17160Sstevel@tonic-gate "a nis domain object: "
17170Sstevel@tonic-gate "ldapModify error %d (%s)",
17180Sstevel@tonic-gate myself, dn, rc,
17190Sstevel@tonic-gate ldap_err2string(rc));
17200Sstevel@tonic-gate return (FAILURE);
17210Sstevel@tonic-gate }
17220Sstevel@tonic-gate }
17230Sstevel@tonic-gate } else { /* search for 'dn' failed */
17240Sstevel@tonic-gate freeRuleValue(rv, nr);
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate /*
17270Sstevel@tonic-gate * It is OK if no such object, otherwise
17280Sstevel@tonic-gate * log an error.
17290Sstevel@tonic-gate */
17300Sstevel@tonic-gate if (rc != LDAP_NO_SUCH_OBJECT) {
17310Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
17320Sstevel@tonic-gate "%s: unable to retrieve "
17330Sstevel@tonic-gate "entry (dn: %s): "
17340Sstevel@tonic-gate "ldapSearch error %d (%s)",
17350Sstevel@tonic-gate myself, dn, rc,
17360Sstevel@tonic-gate ldap_err2string(rc));
17370Sstevel@tonic-gate return (FAILURE);
17380Sstevel@tonic-gate }
17390Sstevel@tonic-gate }
17400Sstevel@tonic-gate
17410Sstevel@tonic-gate /*
17420Sstevel@tonic-gate * If the 'dn' is actually the naming context of
17430Sstevel@tonic-gate * the DIT, we should be able to make it a nis domain
17440Sstevel@tonic-gate * object without worrying about missing parent
17450Sstevel@tonic-gate * entries. If unable to add the entry for the 'dn'
17460Sstevel@tonic-gate * due to missing parent entries, fall through
17470Sstevel@tonic-gate * to create them and then add the nis domain object.
17480Sstevel@tonic-gate */
17490Sstevel@tonic-gate if (addNISObject(domain, dn, &add_rc) == SUCCESS)
17500Sstevel@tonic-gate return (SUCCESS);
17510Sstevel@tonic-gate else if (add_rc != LDAP_NO_SUCH_OBJECT)
17520Sstevel@tonic-gate return (FAILURE);
17530Sstevel@tonic-gate }
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate /* Create parent */
17560Sstevel@tonic-gate if (addParent(dn, NULL) == FAILURE)
17570Sstevel@tonic-gate return (FAILURE);
17580Sstevel@tonic-gate
17590Sstevel@tonic-gate if (addNISObject(domain, dn, NULL) == FAILURE)
17600Sstevel@tonic-gate return (FAILURE);
17610Sstevel@tonic-gate
17620Sstevel@tonic-gate return (SUCCESS);
17630Sstevel@tonic-gate }
17640Sstevel@tonic-gate
17650Sstevel@tonic-gate suc_code
addParent(char * dn,char ** attr)17660Sstevel@tonic-gate addParent(char *dn, char **attr) {
17670Sstevel@tonic-gate __nis_rule_value_t *rv;
17680Sstevel@tonic-gate __nis_ldap_search_t *ls;
17690Sstevel@tonic-gate int rc, nr;
17700Sstevel@tonic-gate char *parentdn = 0, *rdn = 0;
17710Sstevel@tonic-gate char *myself = "addParent";
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate /* Obtain parentdn */
17740Sstevel@tonic-gate if (splitDN(dn, &rdn, &parentdn) == -1)
17750Sstevel@tonic-gate return (FAILURE);
17760Sstevel@tonic-gate if (!parentdn) {
17770Sstevel@tonic-gate sfree(rdn);
17780Sstevel@tonic-gate return (FAILURE);
17790Sstevel@tonic-gate }
17800Sstevel@tonic-gate
17810Sstevel@tonic-gate /* Check if parentdn exists */
17820Sstevel@tonic-gate ls = buildLdapSearch(parentdn, LDAP_SCOPE_BASE, 0, 0,
17830Sstevel@tonic-gate "objectclass=*", 0, 0, 0);
17840Sstevel@tonic-gate if (ls == 0) {
17850Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
17860Sstevel@tonic-gate "%s: Unable to create ldapSearch request for "
17870Sstevel@tonic-gate "parent (dn: %s) of (dn: %s)",
17880Sstevel@tonic-gate myself, parentdn, dn);
17890Sstevel@tonic-gate sfree(parentdn);
17900Sstevel@tonic-gate sfree(rdn);
17910Sstevel@tonic-gate return (FAILURE);
17920Sstevel@tonic-gate }
17930Sstevel@tonic-gate nr = -1;
17940Sstevel@tonic-gate rv = ldapSearch(ls, &nr, 0, &rc);
17950Sstevel@tonic-gate freeLdapSearch(ls);
17960Sstevel@tonic-gate freeRuleValue(rv, nr);
17970Sstevel@tonic-gate
17980Sstevel@tonic-gate /* Create parent if it doesn't exists */
17990Sstevel@tonic-gate if (rc == LDAP_NO_SUCH_OBJECT) {
18000Sstevel@tonic-gate if (makeNISObject(0, parentdn) == FAILURE) {
18010Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
18020Sstevel@tonic-gate "%s: Unable to create parent (dn: %s) of "
18030Sstevel@tonic-gate "(dn: %s) in the DIT", myself, parentdn, dn);
18040Sstevel@tonic-gate sfree(parentdn);
18050Sstevel@tonic-gate sfree(rdn);
18060Sstevel@tonic-gate return (FAILURE);
18070Sstevel@tonic-gate }
18080Sstevel@tonic-gate }
18090Sstevel@tonic-gate sfree(parentdn);
18100Sstevel@tonic-gate
18110Sstevel@tonic-gate if (attr && rdn)
18120Sstevel@tonic-gate *attr = (char *)getObjectClass(rdn);
18130Sstevel@tonic-gate sfree(rdn);
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate return (SUCCESS);
18160Sstevel@tonic-gate }
18170Sstevel@tonic-gate
18180Sstevel@tonic-gate
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate /*
18210Sstevel@tonic-gate * FUNCTION : is_fatal_error()
18220Sstevel@tonic-gate *
18230Sstevel@tonic-gate * DESCRIPTION: Works out if a failed mapping operation should be retried.
18240Sstevel@tonic-gate *
18250Sstevel@tonic-gate * INPUTS : Result code from operation
18260Sstevel@tonic-gate *
18270Sstevel@tonic-gate * OUTPUTS : TRUE = Fatal error, don't retry.
18280Sstevel@tonic-gate * FALSE = Temporary error, retry.
18290Sstevel@tonic-gate */
18300Sstevel@tonic-gate bool_t
is_fatal_error(int res)18310Sstevel@tonic-gate is_fatal_error(int res)
18320Sstevel@tonic-gate {
18330Sstevel@tonic-gate
18340Sstevel@tonic-gate if (0 > res)
18350Sstevel@tonic-gate /* An internal mapping error. Not going to go away. */
18360Sstevel@tonic-gate return (TRUE);
18370Sstevel@tonic-gate
18380Sstevel@tonic-gate switch (res) {
18390Sstevel@tonic-gate case (LDAP_PROTOCOL_ERROR):
18400Sstevel@tonic-gate case (LDAP_TIMELIMIT_EXCEEDED):
18410Sstevel@tonic-gate case (LDAP_PARTIAL_RESULTS):
18420Sstevel@tonic-gate case (LDAP_BUSY):
18430Sstevel@tonic-gate case (LDAP_UNAVAILABLE):
18440Sstevel@tonic-gate case (LDAP_UNWILLING_TO_PERFORM):
18450Sstevel@tonic-gate case (LDAP_OTHER):
18460Sstevel@tonic-gate case (LDAP_SERVER_DOWN):
18470Sstevel@tonic-gate case (LDAP_LOCAL_ERROR):
18480Sstevel@tonic-gate case (LDAP_TIMEOUT):
18490Sstevel@tonic-gate case (LDAP_NO_MEMORY):
18500Sstevel@tonic-gate /* Probably worth a retry */
18510Sstevel@tonic-gate return (FALSE);
18520Sstevel@tonic-gate
18530Sstevel@tonic-gate default:
18540Sstevel@tonic-gate return (TRUE);
18550Sstevel@tonic-gate }
18560Sstevel@tonic-gate }
18570Sstevel@tonic-gate
18580Sstevel@tonic-gate /*
18590Sstevel@tonic-gate * FUNCTION : addNISObject()
18600Sstevel@tonic-gate *
18610Sstevel@tonic-gate * DESCRIPTION: Add a nis Object in the DIT.
18620Sstevel@tonic-gate *
18630Sstevel@tonic-gate * GIVEN :
18640Sstevel@tonic-gate * Case 1: 'dn' is NULL
18650Sstevel@tonic-gate * Error
18660Sstevel@tonic-gate * Case 2: 'domain' is non-NULL
18670Sstevel@tonic-gate * Create nisDomainObject with the given information
18680Sstevel@tonic-gate * Case 3: 'domain' is NULL
18690Sstevel@tonic-gate * Create an object with the 'dn'
18700Sstevel@tonic-gate * Here we guess the objectclass attribute, based on
18710Sstevel@tonic-gate * oc_lookup table
18720Sstevel@tonic-gate *
18730Sstevel@tonic-gate * RETURNS : SUCCESS = It worked
18740Sstevel@tonic-gate * FAILURE = There was a problem. If the ldap add
18750Sstevel@tonic-gate * operation failed, ldap_rc will be set
18760Sstevel@tonic-gate * to the ldap error code.
18770Sstevel@tonic-gate */
18780Sstevel@tonic-gate suc_code
addNISObject(char * domain,char * dn,int * ldap_rc)18790Sstevel@tonic-gate addNISObject(char *domain, char *dn, int *ldap_rc) {
18800Sstevel@tonic-gate __nis_rule_value_t *rv;
18810Sstevel@tonic-gate int rc;
18820Sstevel@tonic-gate char *objClassAttrs = NULL, *attrs;
18830Sstevel@tonic-gate char *value, *svalue, *rdn = NULL;
18840Sstevel@tonic-gate char *myself = "addNISObject";
18850Sstevel@tonic-gate
18860Sstevel@tonic-gate if (!dn)
18870Sstevel@tonic-gate return (FAILURE);
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate if ((rv = initRuleValue(1, 0)) == 0)
18900Sstevel@tonic-gate return (FAILURE);
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate if (ldap_rc)
18930Sstevel@tonic-gate *ldap_rc = -1;
18940Sstevel@tonic-gate
18950Sstevel@tonic-gate /*
18960Sstevel@tonic-gate * Add name=value pairs from RDN. Although this is not required
18970Sstevel@tonic-gate * for SunOne Directory Server, during openldap interoperabilty
18980Sstevel@tonic-gate * tests, it was found out that openldap server returned object
18990Sstevel@tonic-gate * class violation errors if MUST attributes were not specified
19000Sstevel@tonic-gate * explicitly.
19010Sstevel@tonic-gate */
19020Sstevel@tonic-gate if (splitDN(dn, &rdn, 0) == -1)
19030Sstevel@tonic-gate return (FAILURE);
19040Sstevel@tonic-gate if (rdn != NULL) {
19050Sstevel@tonic-gate objClassAttrs = (char *)getObjectClass(rdn);
19060Sstevel@tonic-gate if (objClassAttrs == NULL) {
19070Sstevel@tonic-gate sfree(rdn);
19080Sstevel@tonic-gate return (FAILURE);
19090Sstevel@tonic-gate }
19100Sstevel@tonic-gate
19110Sstevel@tonic-gate /*
19120Sstevel@tonic-gate * RDN can be composed of multiple name=value pairs
19130Sstevel@tonic-gate * concatenated by '+'. Hence, we need to determine each
19140Sstevel@tonic-gate * pair and add it to 'rv'
19150Sstevel@tonic-gate */
19160Sstevel@tonic-gate for (value = rdn, svalue = NULL; *value != '\0'; value++) {
19170Sstevel@tonic-gate if (*value == '+') {
19180Sstevel@tonic-gate /* Make sure it's not escaped */
19190Sstevel@tonic-gate if (value == rdn || *(value - 1) != '\\') {
19200Sstevel@tonic-gate /*
19210Sstevel@tonic-gate * We are at the start of the new
19220Sstevel@tonic-gate * pair. 'svalue' now contains the
19230Sstevel@tonic-gate * value for the previous pair. Add
19240Sstevel@tonic-gate * the previous pair to 'rv'
19250Sstevel@tonic-gate */
19260Sstevel@tonic-gate *value = '\0';
19270Sstevel@tonic-gate if (svalue &&
19280Sstevel@tonic-gate addSAttr2RuleValue(rdn, svalue, rv)
19290Sstevel@tonic-gate == -1) {
19300Sstevel@tonic-gate sfree(rdn);
19310Sstevel@tonic-gate freeRuleValue(rv, 1);
19320Sstevel@tonic-gate return (FAILURE);
19330Sstevel@tonic-gate }
19340Sstevel@tonic-gate svalue = NULL;
19350Sstevel@tonic-gate rdn = value + 1;
19360Sstevel@tonic-gate continue;
19370Sstevel@tonic-gate }
19380Sstevel@tonic-gate }
19390Sstevel@tonic-gate
19400Sstevel@tonic-gate if (*value == '=') {
19410Sstevel@tonic-gate if (value == rdn || *(value - 1) != '\\') {
19420Sstevel@tonic-gate /*
19430Sstevel@tonic-gate * 'rdn' now contains the name.
19440Sstevel@tonic-gate * Whatever follows till the next
19450Sstevel@tonic-gate * unescaped '+' or '\0' is the
19460Sstevel@tonic-gate * value for this pair.
19470Sstevel@tonic-gate */
19480Sstevel@tonic-gate *value = '\0';
19490Sstevel@tonic-gate svalue = value + 1;
19500Sstevel@tonic-gate continue;
19510Sstevel@tonic-gate }
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate }
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate /*
19560Sstevel@tonic-gate * End of String. Add the previous name=value pair to 'rv'
19570Sstevel@tonic-gate */
19580Sstevel@tonic-gate if (svalue && addSAttr2RuleValue(rdn, svalue, rv) == -1) {
19590Sstevel@tonic-gate sfree(rdn);
19600Sstevel@tonic-gate freeRuleValue(rv, 1);
19610Sstevel@tonic-gate return (FAILURE);
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate sfree(rdn);
19640Sstevel@tonic-gate } else /* rdn == NULL */
19650Sstevel@tonic-gate return (FAILURE);
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate /* Create the entry */
19680Sstevel@tonic-gate if (domain) {
19690Sstevel@tonic-gate if (addSAttr2RuleValue("nisDomain", domain, rv) == -1) {
19700Sstevel@tonic-gate freeRuleValue(rv, 1);
19710Sstevel@tonic-gate return (FAILURE);
19720Sstevel@tonic-gate }
19730Sstevel@tonic-gate attrs = scat(myself, F, "objectclass=nisdomainobject,",
19740Sstevel@tonic-gate objClassAttrs);
19750Sstevel@tonic-gate if (!attrs) {
19760Sstevel@tonic-gate freeRuleValue(rv, 1);
19770Sstevel@tonic-gate return (FAILURE);
19780Sstevel@tonic-gate }
19790Sstevel@tonic-gate rc = ldapAdd(dn, rv, attrs, 0);
19800Sstevel@tonic-gate sfree(attrs);
19810Sstevel@tonic-gate } else {
19820Sstevel@tonic-gate rc = ldapAdd(dn, rv, objClassAttrs, 0);
19830Sstevel@tonic-gate }
19840Sstevel@tonic-gate
19850Sstevel@tonic-gate if (rc == LDAP_SUCCESS)
19860Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO,
19870Sstevel@tonic-gate "%s: Entry (dn: %s) added to DIT",
19880Sstevel@tonic-gate myself, dn);
19890Sstevel@tonic-gate else if (rc == LDAP_ALREADY_EXISTS)
19900Sstevel@tonic-gate /* Treat this as success */
19910Sstevel@tonic-gate rc = LDAP_SUCCESS;
19920Sstevel@tonic-gate else
19930Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR,
19940Sstevel@tonic-gate "%s: ldapAdd error %d (%s) for (dn: %s)",
19950Sstevel@tonic-gate myself, rc, ldap_err2string(rc), dn);
19960Sstevel@tonic-gate
19970Sstevel@tonic-gate freeRuleValue(rv, 1);
19980Sstevel@tonic-gate if (ldap_rc)
19990Sstevel@tonic-gate *ldap_rc = rc;
20000Sstevel@tonic-gate return ((rc == LDAP_SUCCESS)?SUCCESS:FAILURE);
20010Sstevel@tonic-gate }
2002