Exemplo n.º 1
0
int
rwm_map_config(
		struct ldapmap	*oc_map,
		struct ldapmap	*at_map,
		const char	*fname,
		int		lineno,
		int		argc,
		char		**argv )
{
	struct ldapmap		*map;
	struct ldapmapping	*mapping;
	char			*src, *dst;
	int			is_oc = 0;
	int			rc = 0;

	if ( argc < 3 || argc > 4 ) {
		Debug( LDAP_DEBUG_ANY,
	"%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n",
			fname, lineno, 0 );
		return 1;
	}

	if ( strcasecmp( argv[1], "objectclass" ) == 0 ) {
		map = oc_map;
		is_oc = 1;

	} else if ( strcasecmp( argv[1], "attribute" ) == 0 ) {
		map = at_map;

	} else {
		Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is "
			"\"map {objectclass | attribute} [<local> | *] "
			"{<foreign> | *}\"\n",
			fname, lineno, 0 );
		return 1;
	}

	if ( !is_oc && map->map == NULL ) {
		/* only init if required */
		if ( rwm_map_init( map, &mapping ) != LDAP_SUCCESS ) {
			return 1;
		}
	}

	if ( strcmp( argv[2], "*" ) == 0 ) {
		if ( argc < 4 || strcmp( argv[3], "*" ) == 0 ) {
			map->drop_missing = ( argc < 4 );
			goto success_return;
		}
		src = dst = argv[3];

	} else if ( argc < 4 ) {
		src = "";
		dst = argv[2];

	} else {
		src = argv[2];
		dst = ( strcmp( argv[3], "*" ) == 0 ? src : argv[3] );
	}

	if ( ( map == at_map )
			&& ( strcasecmp( src, "objectclass" ) == 0
			|| strcasecmp( dst, "objectclass" ) == 0 ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"%s: line %d: objectclass attribute cannot be mapped\n",
			fname, lineno, 0 );
		return 1;
	}

	mapping = (struct ldapmapping *)ch_calloc( 2,
		sizeof(struct ldapmapping) );
	if ( mapping == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"%s: line %d: out of memory\n",
			fname, lineno, 0 );
		return 1;
	}
	ber_str2bv( src, 0, 1, &mapping[0].m_src );
	ber_str2bv( dst, 0, 1, &mapping[0].m_dst );
	mapping[1].m_src = mapping[0].m_dst;
	mapping[1].m_dst = mapping[0].m_src;

	mapping[0].m_flags = RWMMAP_F_NONE;
	mapping[1].m_flags = RWMMAP_F_NONE;

	/*
	 * schema check
	 */
	if ( is_oc ) {
		if ( src[0] != '\0' ) {
			mapping[0].m_src_oc = oc_bvfind( &mapping[0].m_src );
			if ( mapping[0].m_src_oc == NULL ) {
				Debug( LDAP_DEBUG_ANY,
	"%s: line %d: warning, source objectClass '%s' "
	"should be defined in schema\n",
					fname, lineno, src );

				/*
				 * FIXME: this should become an err
				 */
				mapping[0].m_src_oc = ch_malloc( sizeof( ObjectClass ) );
				memset( mapping[0].m_src_oc, 0, sizeof( ObjectClass ) );
				mapping[0].m_src_oc->soc_cname = mapping[0].m_src;
				mapping[0].m_flags |= RWMMAP_F_FREE_SRC;
			}
			mapping[1].m_dst_oc = mapping[0].m_src_oc;
		}

		mapping[0].m_dst_oc = oc_bvfind( &mapping[0].m_dst );
		if ( mapping[0].m_dst_oc == NULL ) {
			Debug( LDAP_DEBUG_ANY,
	"%s: line %d: warning, destination objectClass '%s' "
	"is not defined in schema\n",
				fname, lineno, dst );

			mapping[0].m_dst_oc = oc_bvfind_undef( &mapping[0].m_dst );
			if ( mapping[0].m_dst_oc == NULL ) {
				Debug( LDAP_DEBUG_ANY, "%s: line %d: unable to mimic destination objectClass '%s'\n",
					fname, lineno, dst );
				goto error_return;
			}
		}
		mapping[1].m_src_oc = mapping[0].m_dst_oc;

		mapping[0].m_flags |= RWMMAP_F_IS_OC;
		mapping[1].m_flags |= RWMMAP_F_IS_OC;

	} else {
		int			rc;
		const char		*text = NULL;

		if ( src[0] != '\0' ) {
			rc = slap_bv2ad( &mapping[0].m_src,
					&mapping[0].m_src_ad, &text );
			if ( rc != LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_ANY,
	"%s: line %d: warning, source attributeType '%s' "
	"should be defined in schema\n",
					fname, lineno, src );

				/*
				 * we create a fake "proxied" ad 
				 * and add it here.
				 */

				rc = slap_bv2undef_ad( &mapping[0].m_src,
						&mapping[0].m_src_ad, &text,
						SLAP_AD_PROXIED );
				if ( rc != LDAP_SUCCESS ) {
					char prefix[1024];
					snprintf( prefix, sizeof(prefix),
	"%s: line %d: source attributeType '%s': %d",
						fname, lineno, src, rc );
					Debug( LDAP_DEBUG_ANY, "%s (%s)\n",
						prefix, text ? text : "null", 0 );
					goto error_return;
				}

			}
			mapping[1].m_dst_ad = mapping[0].m_src_ad;
		}

		rc = slap_bv2ad( &mapping[0].m_dst, &mapping[0].m_dst_ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
	"%s: line %d: warning, destination attributeType '%s' "
	"is not defined in schema\n",
				fname, lineno, dst );

			rc = slap_bv2undef_ad( &mapping[0].m_dst,
					&mapping[0].m_dst_ad, &text,
					SLAP_AD_PROXIED );
			if ( rc != LDAP_SUCCESS ) {
				char prefix[1024];
				snprintf( prefix, sizeof(prefix), 
	"%s: line %d: destination attributeType '%s': %d",
					fname, lineno, dst, rc );
				Debug( LDAP_DEBUG_ANY, "%s (%s)\n",
					prefix, text ? text : "null", 0 );
				goto error_return;
			}
		}
		mapping[1].m_src_ad = mapping[0].m_dst_ad;
	}

	if ( ( src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, rwm_mapping_cmp ) != NULL)
			|| avl_find( map->remap, (caddr_t)&mapping[1], rwm_mapping_cmp ) != NULL)
	{
		Debug( LDAP_DEBUG_ANY,
			"%s: line %d: duplicate mapping found.\n",
			fname, lineno, 0 );
		/* FIXME: free stuff */
		goto error_return;
	}

	if ( src[0] != '\0' ) {
		avl_insert( &map->map, (caddr_t)&mapping[0],
					rwm_mapping_cmp, rwm_mapping_dup );
	}
	avl_insert( &map->remap, (caddr_t)&mapping[1],
				rwm_mapping_cmp, rwm_mapping_dup );

success_return:;
	return rc;

error_return:;
	if ( mapping ) {
		rwm_mapping_free( mapping );
	}

	return 1;
}
Exemplo n.º 2
0
static int
ldap_build_entry(
		Operation	*op,
		LDAPMessage	*e,
		Entry		*ent,
		struct berval	*bdn )
{
	struct berval	a;
	BerElement	ber = *ldap_get_message_ber( e );
	Attribute	*attr, **attrp;
	const char	*text;
	int		last;
	char *lastb;
	ber_len_t len;

	/* safe assumptions ... */
	assert( ent != NULL );
	BER_BVZERO( &ent->e_bv );

	if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) {
		return LDAP_DECODING_ERROR;
	}

	/*
	 * Note: this may fail if the target host(s) schema differs
	 * from the one known to the meta, and a DN with unknown
	 * attributes is returned.
	 * 
	 * FIXME: should we log anything, or delegate to dnNormalize?
	 */
	/* Note: if the distinguished values or the naming attributes
	 * change, should we massage them as well?
	 */
	if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname,
		op->o_tmpmemctx ) != LDAP_SUCCESS )
	{
		return LDAP_INVALID_DN_SYNTAX;
	}

	ent->e_attrs = NULL;
	if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) {
		return LDAP_SUCCESS;
	}

	attrp = &ent->e_attrs;
	while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE &&
		ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
		int				i;
		slap_syntax_validate_func	*validate;
		slap_syntax_transform_func	*pretty;

		attr = attr_alloc( NULL );
		if ( attr == NULL ) {
			return LDAP_OTHER;
		}
		if ( slap_bv2ad( &a, &attr->a_desc, &text ) 
				!= LDAP_SUCCESS )
		{
			if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
				SLAP_AD_PROXIED ) != LDAP_SUCCESS )
			{
				Debug( LDAP_DEBUG_ANY, 
					"%s ldap_build_entry: "
					"slap_bv2undef_ad(%s): %s\n",
					op->o_log_prefix, a.bv_val, text );

				( void )ber_scanf( &ber, "x" /* [W] */ );
				attr_free( attr );
				continue;
			}
		}

		/* no subschemaSubentry */
		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
			|| attr->a_desc == slap_schema.si_ad_entryDN )
		{

			/* 
			 * We eat target's subschemaSubentry because
			 * a search for this value is likely not
			 * to resolve to the appropriate backend;
			 * later, the local subschemaSubentry is
			 * added.
			 *
			 * We also eat entryDN because the frontend
			 * will reattach it without checking if already
			 * present...
			 */
			( void )ber_scanf( &ber, "x" /* [W] */ );
			attr_free( attr );
			continue;
		}
		
		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
				|| attr->a_vals == NULL )
		{
			/*
			 * Note: attr->a_vals can be null when using
			 * values result filter
			 */
			attr->a_vals = (struct berval *)&slap_dummy_bv;
		}

		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;

		if ( !validate && !pretty ) {
			attr->a_nvals = NULL;
			attr_free( attr );
			goto next_attr;
		}

		for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ;
		last = i;

		/*
		 * check that each value is valid per syntax
		 * and pretty if appropriate
		 */
		for ( i = 0; i<last; i++ ) {
			struct berval	pval;
			int		rc;

			if ( pretty ) {
				rc = ordered_value_pretty( attr->a_desc,
					&attr->a_vals[i], &pval, NULL );

			} else {
				rc = ordered_value_validate( attr->a_desc,
					&attr->a_vals[i], 0 );
			}

			if ( rc != LDAP_SUCCESS ) {
				ObjectClass *oc;

				/* check if, by chance, it's an undefined objectClass */
				if ( attr->a_desc == slap_schema.si_ad_objectClass &&
						( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL )
				{
					ber_dupbv( &pval, &oc->soc_cname );
					rc = LDAP_SUCCESS;

				} else {
					ber_memfree( attr->a_vals[i].bv_val );
					if ( --last == i ) {
						BER_BVZERO( &attr->a_vals[i] );
						break;
					}
					attr->a_vals[i] = attr->a_vals[last];
					BER_BVZERO( &attr->a_vals[last] );
					i--;
				}
			}

			if ( rc == LDAP_SUCCESS && pretty ) {
				ber_memfree( attr->a_vals[i].bv_val );
				attr->a_vals[i] = pval;
			}
		}
		attr->a_numvals = last = i;
		if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
			attr->a_nvals = NULL;
			attr_free( attr );
			goto next_attr;
		}

		if ( last && attr->a_desc->ad_type->sat_equality &&
				attr->a_desc->ad_type->sat_equality->smr_normalize )
		{
			attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) );
			for ( i = 0; i < last; i++ ) {
				int		rc;

				rc = ordered_value_normalize(
					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
					attr->a_desc,
					attr->a_desc->ad_type->sat_equality,
					&attr->a_vals[i], &attr->a_nvals[i],
					NULL );

				if ( rc != LDAP_SUCCESS ) {
					ber_memfree( attr->a_vals[i].bv_val );
					if ( --last == i ) {
						BER_BVZERO( &attr->a_vals[i] );
						break;
					}
					attr->a_vals[i] = attr->a_vals[last];
					BER_BVZERO( &attr->a_vals[last] );
					i--;
				}
			}
			BER_BVZERO( &attr->a_nvals[i] );
			if ( last == 0 ) {
				attr_free( attr );
				goto next_attr;
			}

		} else {
			attr->a_nvals = attr->a_vals;
		}

		attr->a_numvals = last;

		/* Handle sorted vals, strip dups but keep the attr */
		if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
			while ( attr->a_numvals > 1 ) {
				int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
				if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
					break;

				/* Strip duplicate values */
				if ( attr->a_nvals != attr->a_vals )
					ber_memfree( attr->a_nvals[i].bv_val );
				ber_memfree( attr->a_vals[i].bv_val );
				attr->a_numvals--;

				assert( i >= 0 );
				if ( (unsigned)i < attr->a_numvals ) {
					attr->a_vals[i] = attr->a_vals[attr->a_numvals];
					if ( attr->a_nvals != attr->a_vals )
						attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
				}
				BER_BVZERO(&attr->a_vals[attr->a_numvals]);
				if ( attr->a_nvals != attr->a_vals )
					BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
			}
			attr->a_flags |= SLAP_ATTR_SORTED_VALS;
		}

		*attrp = attr;
		attrp = &attr->a_next;

next_attr:;
	}

	return LDAP_SUCCESS;
}