nis_parse_ldap_yp_util.c revision a87701e9837f8a9ee9e4c4d3186295c0e29f743f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 Gary Mills
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include "ldap_parse.h"
#include "nis_parse_ldap_conf.h"
#include "nis_parse_ldap_util.h"
#include "ldap_util.h"
/* Forward declarations */
int getfullmapname(char **, const char *);
int checkfullmapname(const char *, const char *, __nis_table_mapping_t **,
int append_domainContext(__nis_table_mapping_t **, char *, char *);
__nis_table_mapping_t *new_merged_mapping(const char *,
/*
* FUNCTION: initialize_table_mapping
*
* Initialize the __nis_table_mapping_t structure.
*
* INPUT: __nis_table_mapping_t
*
*/
void
{
mapping->numColumns = 0;
mapping->usedns_flag = 0;
mapping->securemap_flag = 0;
mapping->numRulesFromLDAP = 0;
mapping->numRulesToLDAP = 0;
}
}
/*
* FUNCTION: initialize_yp_parse_structs
*
* Initialize the __yp_domain_context_t structure.
*
* INPUT: __yp_domain_context_t
*
*/
void
{
ypDomains->numDomains = 0;
ypDomains->numYppasswdd = 0;
}
/*
* FUNCTION: merge_table_mapping
*
* Merges information from one table_mapping struct
* into another
*
* INPUT: Source and Destination table_mapping structs.
* RETURN: 0 on success and > 0 on error.
*/
static int
{
int i;
int orig_num_rules;
int append;
return (1);
return (1);
/*
* If 'in' is generic (non-expanded) and 'out' is domain-specific,
* then rules from 'in' should not be appended to those in 'out'.
*/
append = 0;
else
append = 1;
return (1);
}
/* add_column() increments numColumns, so we don't */
for (i = 0; i < in->numColumns; i++) {
return (1);
}
}
if (out->usedns_flag == 0)
if (out->securemap_flag == 0)
if (!out->separatorStr)
return (2);
}
out->e = (__nis_mapping_element_t *)
sizeof (__nis_mapping_element_t));
if (!out->e)
return (2);
for (; i > 0; i--) {
}
return (1);
}
}
}
if (!out->ruleFromLDAP)
return (1);
for (i = 0; i < in->numRulesFromLDAP; i++) {
for (i = out->numRulesFromLDAP;
i > orig_num_rules; i--) {
}
return (1);
}
}
}
in->numRulesToLDAP);
if (!out->ruleToLDAP)
return (1);
for (i = 0; i < in->numRulesToLDAP; i++) {
for (i = out->numRulesToLDAP;
i > orig_num_rules; i--) {
}
return (1);
}
}
}
return (2);
return (1);
}
}
/* objName has no space- a single map dbIdMapping */
return (2);
}
}
return (2);
}
}
/*
* FUNCTION: copy_object_dn
*
* Copies a __nis_object_dn_t structure.
*
* RETURN: 0 on success, > 0 on failure.
*
* NOTE: The caller MUST free newdn using
* free_object_dn() if return value != 0 (error condition)
*/
static int
{
return (1);
}
} else {
return (2);
}
return (2);
}
} else {
}
return (2);
} else {
}
return (2);
}
} else {
}
return (2);
}
return (1);
}
sizeof (__nis_object_dn_t));
return (1);
} else {
return (0);
}
} /* End of while on in */
return (0);
}
/*
* FUNCTION: free_yp_domain_context
*
* Frees __yp_domain_context_t
*
* INPUT: __yp_domain_context_t
*/
void
{
int i;
for (i = 0; i < domains->numDomains; i++) {
}
}
}
for (i = 0; i < domains->numYppasswdd; i++) {
domains->yppasswddDomainLabels[i] =
NULL;
}
}
domains->numDomains = 0;
}
}
/*
* FUNCTION: second_parser_pass
*
* Prepares the linked list of table_mappings for processing
* by finish_parse(), adding, merging and deleting structures
* as necessary. Also adds dummy objectDN info. for splitField's.
*
* RETURN VALUE: 0 on success, > 0 on failure.
*/
int
{
__nis_table_mapping_t *t, *t2;
char *lasts;
char *myself = "second_parser_pass";
int i = 0, len;
for (t = *table_mapping; t != NULL; ) {
/*
* Temporarily using this field to flag deletion.
* 0 : don't delete
* 1 : delete
* The mapping structure will be deleted in final_parser_pass
*/
t->isMaster = 0;
if (!t->dbId) {
"%s: no dbId field", myself);
return (1);
}
"%s: Cannot allocate memory for objName",
myself);
return (1);
}
/* Get the generic mapping */
}
} else {
if (!t->objName) {
"%s: Cannot allocate memory for "
"t->objName", myself);
return (2);
}
} else {
/* Force relationship for domain specific */
/* Get the generic mapping */
/* If not found, use dbId for objName */
"%s: Cannot allocate memory for t->objName",
myself);
return (2);
}
} else {
dom++;
"%s: Cannot allocate memory for t->objName",
myself);
return (2);
}
&lasts);
/* Loop 'breaks' on errors */
while (alias) {
if (!dupalias)
break;
if (getfullmapname(&dupalias,
dom)) {
i = 1;
break;
}
else {
2;
break;
"%s %s",
t->objName,
dupalias);
}
" ", &lasts);
}
if (tobj)
if (alias ||
== NULL) {
if (i)
"%s: getfullmapname failed for %s for domain \"%s\"",
dom);
else {
p_error =
"%s: Cannot allocate memory",
myself);
}
if (dupalias)
if (t->objName)
return (2);
}
&lasts);
}
}
}
if (merge_table_mapping(tg, t)) {
"Error merging information from the %s to the %s mapping structure",
if (objName)
return (1);
}
}
/*
* If objName is "map1 map2" then do the second pass.
* If it is just "map1" however skip the expansion.
* Also skip it if t->objName is null.
*/
if (t2) {
if (merge_table_mapping(t, t2)) {
"Error merging information from the %s to the %s mapping structure",
if (objName)
return (1);
}
t->isMaster = 1;
} else {
if (t_new) {
t->isMaster = 1;
else
*table_mapping = t_new;
} else {
"Error creating a new mapping structure %s",
objs);
if (objName)
return (1);
}
}
!= NULL) {
if (t2) {
if (merge_table_mapping(t, t2)) {
"Error merging information from the %s to the %s mapping structure",
if (objName)
return (1);
}
t->isMaster = 1;
} else {
/*
* create a new t_map with dbId = objs
* and copy t->* into new t_map
*/
if (t_new) {
t->isMaster = 1;
else
*table_mapping = t_new;
} else {
"Error creating a new mapping structure %s",
objs);
if (objName)
return (1);
}
}
}
} /* if objs!= NULL */
prev = t;
t = t->next;
if (objName) {
}
} /* for t = table_mapping loop */
return (0);
}
new_merged_mapping(const char *match,
{
return (NULL);
return (NULL);
}
}
return (outtable);
}
/*
* FUNCTION: final_parser_pass
*
* completes the final expansion of t_map structures linked list.
* all structures will have a non-null objPath as well as a objName
* in the form of "mapname . domainname ." or "splitfieldname .
* domainname .".
*
* RETURN VALUE: 0 on success, -1 on failure, -2 on fatal error.
*/
int
{
int i;
char *myself = "final_parser_pass";
int nm;
bool_t r;
int del_tbl_flag = 0;
if (ypDomains) {
if (!ypDomains->numDomains) {
"%s:No domains specified.", myself);
return (-1);
}
} else {
"%s:No domain structure supplied.", myself);
return (-1);
}
for (t = *table_mapping; t != NULL; ) {
/* Delete if marked for deletion by second_parser_pass */
if (t->isMaster == 1) {
else
*table_mapping = t->next;
t1 = t;
t = t->next;
continue;
}
if (!t->objName) {
"%s:Could not allocate.", myself);
return (-1);
}
}
i = ypDomains->numDomains;
while (i > 0) {
if (i == 1) {
/* modify existing table_mapping's */
ypDomains->domainLabels[0],
if (nm == 1) {
/* delete this mapping structure */
"Mapping structure %s,%s "
"already exists.",
t->dbId,
ypDomains->domainLabels[0]);
if (merge_table_mapping(t,
returned_map)) {
"Error merging information "
"from the %s to the %s "
"mapping structure.",
t->dbId,
returned_map->dbId);
return (-1);
}
if (del_tbl_flag == 0)
del_tbl_flag = 1;
} else if (nm == -1) {
"Error searching for %s,%s structure",
t->dbId,
ypDomains->domainLabels[0]);
return (-1);
if ((append_domainContext(&t,
ypDomains->domainLabels[0],
"Error appending domainContext %s",
ypDomains->domainLabels[0]);
return (-1);
}
del_tbl_flag = 0;
}
} else { /* if (i > 1) */
/* need to create new table_mapping's */
if (nm == -1) {
"Error searching for %s,%s structure",
t->dbId,
return (-1);
} else if (nm == 0) {
/* we clone ourselves */
if (t1) {
if ((append_domainContext(&t1,
"Error appending domainContext %s",
return (-1);
}
} else {
*table_mapping = t1;
}
} else { /* if !t1 */
"%s:Could not create new table -"
" check all instances of %s for errors",
return (-1);
}
} else if (nm == 1) {
"Mapping structure %s,%s already exists.",
t->dbId,
/*
* We should be deleting this, but can't
* really do it here, because we need to
* match with the domainLabels[0] case
* too. So we will just flag it for now.
*/
if (merge_table_mapping(t,
returned_map)) {
"Error merging information from the %s to the %s mapping structure.",
t->dbId,
returned_map->dbId);
return (-1);
}
del_tbl_flag = 1;
} else if (nm == 2) {
if ((append_domainContext(&t,
"Error appending domainContext %s",
return (-1);
}
} /* end of "if (nm == 0)" */
} /* end of else if (i > 1) */
/*
* 'merge_table_mapping' only copies unexpanded
* objectDN values into returned_map. Hence,
* read.base and write.base in returned_map
* needs to be expanded.
*/
r = make_fqdn(
if (r == TRUE &&
r = make_full_dn(
}
if (r == FALSE) {
"Error appending domainContext "
"%s to %s",
returned_map->dbId);
return (-2);
}
}
i--;
} /* end of while i > 0 loop */
if (del_tbl_flag == 1) {
} else {
*table_mapping = t->next;
t = *table_mapping;
}
del_tbl_flag = 0;
} else {
prev = t;
t = t->next;
}
} /* end of table mapping loop */
if (!t->dbId) {
"%s:Fatal error: structure with no dbId found.",
myself);
return (-2);
}
append_dot(&t->dbId);
if (!t->objectDN) {
return (-1);
}
}
return (0);
}
/*
* FUNCTION: append_mapping_rule
*
* Appends mapping rules to a table_mapping structure
* with previously existing rules. flag controls whether
* the functions works on the rules From or To LDAP.
*
* RETURN VALUE: 0 on success, >= 1 on failure.
*/
static int
{
if (flag == 0) {
return (1);
}
rules = (__nis_mapping_rule_t **)
sizeof (__nis_mapping_rule_t *));
return (2);
return (2);
}
dst->numRulesFromLDAP++;
} else if (flag == 1) {
return (1);
}
rules = (__nis_mapping_rule_t **)
sizeof (__nis_mapping_rule_t *));
return (2);
return (2);
}
dst->numRulesToLDAP++;
} else
return (1);
return (0);
}
/*
* FUNCTION: check_domain_specific_order
*
* Makes sure that an attribute with explicitly specified
* nisLDAPdomainContext is found before its non-domain
* specific counterpart.
*
* RETURN VALUE: 0 normal exit
* 1 if domain specific attribute found
* after non-domain specific one.
* -1 some error condition
*/
int
check_domain_specific_order(const char *sd,
{
char *myself = "check_domain_specific_order";
char *type;
char *dbId = 0;
int i, len;
int match = 0;
if (ypDomains) {
if (!ypDomains->numDomains) {
"%s:No domains specified.", myself);
return (-1);
}
} else {
"%s:No domain structure supplied.", myself);
return (-1);
}
for (i = 0; i < ypDomains->numDomains; i++) {
/* prevent from matching against itself */
continue;
"%s:Memory allocation error.", myself);
return (-1);
}
if (getfullmapname(&dbId,
ypDomains->domainLabels[i])) {
"Error getting fully qualified name for %s",
dbId);
return (-1);
}
match = 0;
switch (attrib_num) {
case key_yp_map_flags:
if (t->usedns_flag != 0 ||
t->securemap_flag != 0)
match = 1;
type = YP_MAP_FLAGS;
break;
case key_yp_comment_char:
if (t->commentChar !=
match = 1;
break;
if (strcmp(t->separatorStr,
DEFAULT_SEP_STRING) != 0)
match = 1;
type =
break;
case key_yp_name_fields:
if (t->e && t->numColumns)
match = 1;
case key_yp_split_field:
if (t->e && t->numColumns)
match = 1;
break;
case key_yp_db_id_map:
if (t->objName)
match = 1;
type = YP_DB_ID_MAP;
break;
case key_yp_entry_ttl:
if (t->initTtlLo !=
match = 1;
type = YP_ENTRY_TTL;
break;
case key_yp_ldap_object_dn:
if (t->objectDN)
match = 1;
break;
case key_nis_to_ldap_map:
if (t->ruleToLDAP)
match = 1;
break;
case key_ldap_to_nis_map:
if (t->ruleFromLDAP)
match = 1;
break;
default:
type = "unknown";
match = 0;
break;
} /* end of switch */
if (match) {
"Relative attribute '%s' of type '%s' found before fully qualified one '%s'",
return (1);
}
} /* end of strncasecmp */
} /* end of t loop */
} /* end of i loop */
if (dbId)
return (0);
}
int
{
return (1);
/* map already has a domain part, do nothing */
return (0);
} else {
append_comma(&maps);
return (1);
return (0);
} else
return (1);
}
}
/*
* FUNCTION: checkfullmapname
*
* Tries to find out if by appending the table mapping structures
* with each of the provided nisLDAPdomainContexts, an already
* existing fqdn table mapping structure results. That would be the
* case when a full qualified domain specific attribute was present.
*
* Note that per NISLDAPmapping(4) such an attribute MUST be listed
* in the mapping file BEFORE its non-fqdn counterpart.
*
* RETURNS: 0 normal exit, 1 if an existing structure found, -1 for all
* errors, 2 if already fqdn. If returning 1 the existing structure is
* in found_map.
*/
int
{
char *map;
/* This function does not alter mapname */
return (-1);
return (2);
return (-1);
return (-1);
}
if (*found_map) {
return (1);
}
return (0);
}
/*
* FUNCTION: append_domainContext
*
* Higher level function to append the domains to the appropriate
* fields in a table mapping structure. Calls either getfullmapname()
* or make_full_dn() to do the actual append.
*
* RETURNS: 0 on success, -1 on any error.
*/
int
char *DomainLabel, char *Domain)
{
char *lasts;
int domain_specific = 0;
char *myself = "append_domainContext";
return (-1);
return (-1);
}
if (!tmp_dbId)
return (-1);
domain_specific = 1;
if (id)
else {
return (-1);
}
if (!id) {
return (-1);
}
return (0);
}
} else {
return (-1);
}
}
if (tmp_dbId)
return (-1);
/*
* If domain specific mapping doesn't have objectDN,
* then don't touch. Most probably, pass for the generic mapping
* will handle this by coping over it's own objectDN
*/
return (0);
/* Allocate memory to objectDN */
"%s: Cannot allocate memory for objectDN",
myself);
return (2);
}
}
return (-1);
return (-1);
}
return (0);
}