datum * getKeyFromRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *nv, int *statP) { int i, j; datum *key = 0; char *str; char *myself = "getKeyFromRuleValue"; /* No error yet */ *statP = 0; if (rv == 0 || nv == 0) return (0); for (i = 0; i < rv->numColumns; i++) { if (rv->colName[i] == 0) continue; if (strcasecmp(N2LKEY, rv->colName[i]) == 0 || strcasecmp(N2LIPKEY, rv->colName[i]) == 0) { if ((*nv = rv->colVal[i].numVals) == 0) return (0); if ((key = am(myself, sizeof (key[0]) * *nv)) == 0) { *statP = MAP_NO_MEMORY; return (0); } for (j = 0; j < *nv; j++) { if ((str = rv->colVal[i].val[j].value) == 0) { key[j].dsize = 0; key[j].dptr = 0; } else { if (verifyIndexMatch(t, 0, 0, rv->colName[i], str) == 0) { key[j].dsize = 0; key[j].dptr = 0; continue; } key[j].dsize = strlen(str); key[j].dptr = am(myself, key[j].dsize + 1); if (key[j].dptr == 0) { *statP = MAP_NO_MEMORY; for (--j; j >= 0; j--) sfree(key[j].dptr); sfree(key); return (0); } bcopy(str, key[j].dptr, key[j].dsize); } } return (key); } } return (0); }
datum * getKeyFromRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, int *nv, int *statP, bool_t xlate_to_lcase) { int i, j, k; datum *key = 0; char *str; char *myself = "getKeyFromRuleValue"; /* No error yet */ *statP = 0; if (rv == 0 || nv == 0) return (0); for (i = 0; i < rv->numColumns; i++) { if (rv->colName[i] == 0) continue; if (strcasecmp(N2LKEY, rv->colName[i]) == 0 || strcasecmp(N2LIPKEY, rv->colName[i]) == 0) { if ((*nv = rv->colVal[i].numVals) == 0) return (0); if ((key = am(myself, sizeof (key[0]) * *nv)) == 0) { *statP = MAP_NO_MEMORY; return (0); } for (j = 0; j < *nv; j++) { if ((str = rv->colVal[i].val[j].value) == 0) { key[j].dsize = 0; key[j].dptr = 0; } else { if (verifyIndexMatch(t, 0, 0, rv->colName[i], str) == 0) { key[j].dsize = 0; key[j].dptr = 0; continue; } key[j].dsize = strlen(str); key[j].dptr = am(myself, key[j].dsize + 1); if (key[j].dptr == 0) { *statP = MAP_NO_MEMORY; for (--j; j >= 0; j--) sfree(key[j].dptr); sfree(key); return (0); } /* transliterate key to lowercase */ if (xlate_to_lcase == TRUE) { /* * For multi-homed * entries, skip over * "YP_MULTI_" prefix. */ k = 0; if (strncmp(YPMULTI, str, YPMULTISZ) == 0) { k = YPMULTISZ; bcopy(str, key[j].dptr, YPMULTISZ); } while (k < key[j].dsize) { key[j].dptr[k] = (char)tolower( (int)(uchar_t) str[k]); k++; } } else { bcopy(str, key[j].dptr, key[j].dsize); } } } return (key); } } return (0); }
/* * Updates 'rv' with NIS name=value pairs suitable to * construct datum from namefield information. * Some part based on createNisPlusEntry (from ldap_nisdbquery.c) * This code assumes that from a given LDAP entry, applying the * mapping rules, would give us one or more NIS entries, differing * only in key. */ suc_code buildNISRuleValue(__nis_table_mapping_t *t, __nis_rule_value_t *rv, char *domain) { int r, i, j, k, l, nrq, res, len; int numItems, splitname, count, statP; __nis_value_t *rval; __nis_mapping_item_t *litem; __nis_mapping_rule_t *rl; __nis_rule_value_t *rvq; char *value, *emptystr = ""; statP = SUCCESS; /* Initialize default base */ __nisdb_get_tsd()->searchBase = t->objectDN->read.base; /* Initialize rule-value rvq */ rvq = 0; count = 0; /* Add domainname to rule-value */ if (addCol2RuleValue(vt_string, N2LDOMAIN, domain, strlen(domain), rv)) { return (MAP_INTERNAL_ERROR); } for (r = 0; r < t->numRulesFromLDAP; r++) { rl = t->ruleFromLDAP[r]; /* Set escapeFlag if RHS is "dn" to remove escape chars */ if (rl->rhs.numElements == 1 && rl->rhs.element->type == me_item && rl->rhs.element->element.item.type == mit_ldap && strcasecmp(rl->rhs.element->element.item.name, "dn") == 0) { __nisdb_get_tsd()->escapeFlag = '2'; } rval = buildRvalue(&rl->rhs, mit_ldap, rv, NULL); /* Reset escapeFlag */ __nisdb_get_tsd()->escapeFlag = '\0'; if (rval == 0) { continue; } if (rval->numVals <= 0) { /* Treat as invalid */ freeValue(rval, 1); continue; } litem = buildLvalue(&rl->lhs, &rval, &numItems); if (litem == 0) { /* This will take care of numItems == 0 */ freeValue(rval, 1); continue; } if (rval->numVals > 1) { if (numItems == 1 && litem->repeat) nrq = rval->numVals; else if (numItems > 1 && rval->repeat) nrq = 1 + ((rval->numVals-1)/numItems); else nrq = 1; } else nrq = 1; /* Set splitname if splitfield names are specified */ for (i = 0; i < numItems; i++) { if (strcasecmp(litem[i].name, N2LKEY) == 0 || strcasecmp(litem[i].name, N2LIPKEY) == 0 || strcasecmp(litem[i].name, N2LCOMMENT) == 0) continue; for (j = 0; j < t->numColumns; j++) { if (strcmp(litem[i].name, t->column[j]) == 0) break; } if (j == t->numColumns) break; } splitname = (i < numItems)?1:0; for (j = 0; j < nrq; j++) { if (splitname == 1) { /* * Put every value of splitfieldname in a new * rule-value. Helps generating splitfields. */ rvq = growRuleValue(count, count + 1, rvq, 0); if (rvq == 0) { freeRuleValue(rvq, count); freeValue(rval, 1); freeMappingItem(litem, numItems); return (MAP_INTERNAL_ERROR); } count++; } for (k = j % nrq, l = 0; l < numItems; k += nrq, l++) { /* If we run out of values, use empty strings */ if (k >= rval->numVals) { value = emptystr; len = 0; } else { value = rval->val[k].value; len = rval->val[k].length; } res = (splitname == 1)?addCol2RuleValue( vt_string, litem[l].name, value, len, &rvq[count - 1]):0; if (res != -1) res = addCol2RuleValue(vt_string, litem[l].name, value, len, rv); if (res == -1) { freeRuleValue(rvq, count); freeValue(rval, 1); freeMappingItem(litem, numItems); return (MAP_INTERNAL_ERROR); } } } freeValue(rval, 1); rval = 0; freeMappingItem(litem, numItems); litem = 0; numItems = 0; } /* for r < t->numRulesFromLDAP */ statP = addSplitFieldValues(t, rvq, rv, count, domain); if (rvq) freeRuleValue(rvq, count); if (verifyIndexMatch(t, 0, rv, 0, 0) == 0) return (MAP_INDEXLIST_ERROR); return (statP); } /* end of buildNISRuleValue */
/* * Maps and writes a single NIS entry to the LDAP DIT */ int singleWriteToDIT(char *map, char *domain, datum *key, datum *value, bool_t replace) { __nis_table_mapping_t *t; __nis_rule_value_t *rv, *frv; __nis_ldap_search_t *ls; int statP = SUCCESS, flag; int nv, nr, i, rc, collapse; char *dn = 0, *skey, *svalue, *str; char *myself = "singleWriteToDIT"; if (!map || !domain || !key || !value) { return (MAP_PARAM_ERROR); } /* Return SUCCESS for empty or whitespace key */ for (i = 0; i < key->dsize && (key->dptr[i] == 0 || key->dptr[i] == ' ' || key->dptr[i] == '\t'); i++); if (i >= key->dsize) return (SUCCESS); /* Get the mapping information for the map */ if ((t = mappingFromMap(map, domain, &statP)) == 0) { /* * No problem. We don't handle this map and domain. Maybe it's * handled by a service other than NIS. */ return (statP); } /* NULL-terminated version of key and value for logging */ if ((skey = am(myself, key->dsize + 1)) == 0) return (MAP_NO_MEMORY); (void) memcpy(skey, key->dptr, key->dsize); if ((svalue = am(myself, value->dsize + 1)) == 0) { sfree(skey); return (MAP_NO_MEMORY); } (void) memcpy(svalue, value->dptr, value->dsize); if ((str = getFullMapName(map, domain)) == 0) { sfree(skey); sfree(svalue); return (MAP_NO_MEMORY); } /* For each alternate mapping */ for (flag = 0; t != 0; t = t->next) { /* Verify objName */ if (strcmp(str, t->objName) != 0) { continue; } /* Verify if key matches the index */ if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 || verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0) continue; /* Check the writespecs */ if (t->objectDN->write.base == 0) { logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: No baseDN in writespec. Write disabled " "for %s (%s)", myself, t->dbId, map); continue; } /* Check if rulesToLDAP are provided */ if (t->numRulesToLDAP == 0) { logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: No rulesToLDAP. Write disabled for " "%s (%s)", myself, t->dbId, map); continue; } /* Set flag to indicate write is enabled */ flag = 1; /* Convert key and value into an array of rule-values */ if ((rv = datumToRuleValue(key, value, t, &nv, domain, FALSE, &statP)) == 0) { logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Conversion error %d (NIS to name=value " "pairs) for NIS data (key=%s, value=%s) " "for %s (%s)", myself, statP, skey, svalue, t->dbId, map); sfree(skey); sfree(svalue); /* Free full map name */ sfree(str); return (statP); } /* Convert NIS data to LDAP equivalents for each rule-value */ for (i = 0; i < nv; i++) { /* Verify indexlist with name=value pairs */ if (verifyIndexMatch(t, 0, &rv[i], 0, 0) == 0) break; /* Create LDAP request and LDAP name=value pairs */ if ((ls = createLdapRequest(t, &rv[i], 0, 0, NULL, NULL)) == 0) { logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Conversion error (name=value pairs" " to LDAP) for NIS data " "(key=%s, value=%s) for %s (%s)", myself, skey, svalue, t->dbId, map); freeRuleValue(rv, nv); sfree(skey); sfree(svalue); /* Free full map name */ sfree(str); return (MAP_CREATE_LDAP_REQUEST_ERROR); } freeLdapSearch(ls); /* printRuleValue(&rv[i]); */ } /* If i < nv then this alternate mapping isn't the one */ if (i < nv) continue; /* * Merge rule-values with the same DN so that we have * one ldap write request for each DN */ nr = nv; frv = mergeRuleValueWithSameDN(rv, &nr); freeRuleValue(rv, nv); if (frv == 0) { if (nr == -1) { logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Unable to merge LDAP write " "requests to same DN for NIS data " "(key=%s, value=%s) for %s (%s)", myself, skey, svalue, t->dbId, map); statP = MAP_INTERNAL_ERROR; } else if (nr == 0) { logmsg(MSG_NOTIMECHECK, LOG_WARNING, "%s: Cannot generate write DN due to " "missing information for NIS data " "(key=%s, value=%s) for %s (%s)", myself, skey, svalue, t->dbId, map); statP = MAP_NO_DN; } sfree(skey); sfree(svalue); /* Free full map name */ sfree(str); return (statP); } /* Write to the LDAP server */ for (collapse = 0, i = 0; i < nr; i++) { if ((dn = findVal("dn", &frv[i], mit_ldap)) != 0) { if (replace == FALSE) { /* ldap add */ rc = ldapAdd(dn, &frv[i], t->objectDN->write.attrs, 0); } else { /* ldap modify with addFirst set */ rc = ldapModify(dn, &frv[i], t->objectDN->write.attrs, 1); } /* if we get err=20, collapse and try again */ if (!collapse && (rc == LDAP_TYPE_OR_VALUE_EXISTS) && (collapseRuleValue(&frv[i]) == 1)) { logmsg(MSG_NOTIMECHECK, LOG_WARNING, "%s: Ignoring values differing " "in case from NIS data (key=%s," " value=%s) for (dn: %s) for " "%s (%s)", myself, skey, svalue, dn, t->dbId, map); collapse = 1; i--; continue; } collapse = 0; if (rc != LDAP_SUCCESS) { /* Log error */ logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: %s error %d (%s) for " "(dn: %s) for NIS data " "(key=%s, value=%s) " "for %s (%s)", myself, (replace == TRUE) ? "ldapModify" : "ldapAdd", rc, ldap_err2string(rc), dn, skey, svalue, t->dbId, map); /* Dumping failed call may be useful */ /* printRuleValue(&frv[i]); */ /* * Return the error code and let wrapper * sort out if mapping should continue * or abort. */ statP = rc; sfree(skey); sfree(svalue); freeRuleValue(frv, nr); /* Free full map name */ sfree(str); return (statP); } } } freeRuleValue(frv, nr); } sfree(skey); sfree(svalue); /* Free full map name */ sfree(str); return ((flag)?SUCCESS:MAP_WRITE_DISABLED); }
/* * Read (i.e get and map) a single NIS entry from the LDAP DIT */ bool_t singleReadFromDIT(char *map, char *domain, datum *key, datum *value, int *statP) { __nis_table_mapping_t *t; __nis_rule_value_t *rv_request = 0, *rv_result = 0; __nis_ldap_search_t *ls; __nis_object_dn_t *objectDN = NULL; int i, rc, nr = 0; datum *datval = 0; char *skey, *str; char *myself = "singleReadFromDIT"; *statP = SUCCESS; if (!map || !domain || !key || !value) { *statP = MAP_PARAM_ERROR; return (FALSE); } /* Get the mapping information for the map */ if ((t = mappingFromMap(map, domain, statP)) == 0) { /* * No problem. We don't handle this map and domain. Maybe it's * handled by a service other than NIS. */ return (FALSE); } /* NULL-terminated version of datum key for logging */ if ((skey = am(myself, key->dsize + 1)) == 0) { *statP = MAP_NO_MEMORY; return (FALSE); } (void) memcpy(skey, key->dptr, key->dsize); if ((str = getFullMapName(map, domain)) == 0) { *statP = MAP_NO_MEMORY; return (FALSE); } /* For each alternate mapping */ for (; t != 0; t = t->next) { /* Verify objName */ if (strcmp(str, t->objName) != 0) { continue; } /* Verify if key matches the index */ if (verifyIndexMatch(t, 0, 0, N2LKEY, skey) == 0 || verifyIndexMatch(t, 0, 0, N2LIPKEY, skey) == 0) continue; /* Check if rulesFromLDAP are provided */ if (t->numRulesFromLDAP == 0) { logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: No rulesFromLDAP information available " "for %s (%s)", myself, t->dbId, map); continue; } /* Convert key into rule-value */ if ((rv_request = datumToRuleValue(key, 0, t, 0, domain, TRUE, statP)) == 0) { logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Conversion error %d (NIS to name=value " "pairs) for NIS key (%s) for %s (%s)", myself, *statP, skey, t->dbId, map); continue; } /* Convert rule-value into ldap request */ for (objectDN = t->objectDN; objectDN && objectDN->read.base; objectDN = objectDN->next) { ls = createLdapRequest(t, rv_request, 0, 1, NULL, objectDN); if (ls == 0) { *statP = MAP_CREATE_LDAP_REQUEST_ERROR; logmsg(MSG_NOTIMECHECK, LOG_ERR, "%s: Failed to create ldapSearch " "request for " "NIS key (%s) for %s (%s) " "for base %s", myself, skey, t->dbId, map, objectDN->read.base); continue; } ls->timeout.tv_sec = SINGLE_ACCESS_TIMEOUT_SEC; ls->timeout.tv_usec = SINGLE_ACCESS_TIMEOUT_USEC; /* Query LDAP */ nr = (ls->isDN)?0:-1; rv_result = ldapSearch(ls, &nr, 0, statP); freeLdapSearch(ls); if (rv_result == 0) { if (*statP == LDAP_NO_SUCH_OBJECT) { /* Entry does not exist in */ /* the ldap server */ } continue; } freeRuleValue(rv_request, 1); rv_request = 0; /* if result > 1, first match will be returned */ if (nr > 1) { logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: %d ldapSearch results " "for NIS key (%s) " "for %s (%s) for base %s. " "First match will be returned ", myself, nr, skey, t->dbId, map, objectDN->read.base); } for (i = 0; i < nr; i++) { /* Convert LDAP data to NIS equivalents */ *statP = buildNISRuleValue(t, &rv_result[i], domain); if (*statP == MAP_INDEXLIST_ERROR) continue; if (*statP != SUCCESS) { logmsg(MSG_NOTIMECHECK, LOG_WARNING, "%s: Conversion error %d (LDAP to " "name=value pairs) for NIS key (%s) " "for %s (%s) for base %s", myself, *statP, skey, t->dbId, map, objectDN->read.base); continue; } /* * Check if 'key' from the ldap result matches the key * provided by our caller */ if ((rc = verifyKey(skey, &rv_result[i])) == -1) { logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: Cannot verify key from ldap " "result for NIS key (%s) for %s (%s) " "for base %s", myself, skey, t->dbId, map, objectDN->read.base); continue; } if (rc == 1) { datval = ruleValueToDatum(t, &rv_result[i], statP); if (datval == 0) { logmsg(MSG_NOTIMECHECK, LOG_WARNING, "%s: Conversion error %d " "(name=value pairs to NIS) " "for NIS key (%s) for %s (%s)" " for base %s", myself, *statP, skey, t->dbId, map, objectDN->read.base); continue; } if (value) { value->dptr = datval->dptr; value->dsize = datval->dsize; } sfree(datval); sfree(skey); freeRuleValue(rv_result, nr); rv_result = 0; *statP = SUCCESS; /* Free full map name */ sfree(str); return (TRUE); } } freeRuleValue(rv_result, nr); rv_result = 0; } /* end of for over objectDN */ if (rv_request != 0) { freeRuleValue(rv_request, 1); rv_request = 0; } if (rv_result != 0) { freeRuleValue(rv_result, nr); rv_result = 0; } } sfree(skey); *statP = MAP_NO_MATCHING_KEY; /* Free full map name */ sfree(str); return (FALSE); }