Esempio n. 1
0
/*
 * dnParent - dn's parent, in-place
 * note: the incoming dn is assumed to be normalized/prettyfied,
 * so that escaped rdn/ava separators are in '\'+hexpair form
 *
 * note: "dn" and "pdn" can point to the same berval;
 * beware that, in this case, the pointer to the original buffer
 * will get lost.
 */
void
dnParent( 
	struct berval	*dn, 
	struct berval	*pdn )
{
	char	*p;

	p = ber_bvchr( dn, ',' );

	/* one-level dn */
	if ( p == NULL ) {
		pdn->bv_val = dn->bv_val + dn->bv_len;
		pdn->bv_len = 0;
		return;
	}

	assert( DN_SEPARATOR( p[ 0 ] ) );
	p++;

	assert( ATTR_LEADCHAR( p[ 0 ] ) );
	pdn->bv_len = dn->bv_len - (p - dn->bv_val);
	pdn->bv_val = p;

	return;
}
Esempio n. 2
0
/*
 * We can assume the input is a prettied or normalized DN
 */
ber_len_t
dn_rdnlen(
	Backend		*be,
	struct berval	*dn_in )
{
	const char	*p;

	assert( dn_in != NULL );

	if ( dn_in == NULL ) {
		return 0;
	}

	if ( !dn_in->bv_len ) {
		return 0;
	}

	if ( be != NULL && be_issuffix( be, dn_in ) ) {
		return 0;
	}

	p = ber_bvchr( dn_in, ',' );

	return p ? (ber_len_t) (p - dn_in->bv_val) : dn_in->bv_len;
}
Esempio n. 3
0
/* rdnValidate:
 *
 * LDAP_SUCCESS if rdn is a legal rdn;
 * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns)
 */
int
rdn_validate( struct berval *rdn )
{
#if 1
	/* Major cheat!
	 * input is a pretty or normalized DN
	 * hence, we can just search for ','
	 */
	if( rdn == NULL || rdn->bv_len == 0 ||
		rdn->bv_len > SLAP_LDAPDN_MAXLEN )
	{
		return LDAP_INVALID_SYNTAX;
	}
	return ber_bvchr( rdn, ',' ) == NULL
		? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;

#else
	LDAPRDN		*RDN, **DN[ 2 ] = { &RDN, NULL };
	const char	*p;
	int		rc;

	/*
	 * must be non-empty
	 */
	if ( rdn == NULL || rdn == '\0' ) {
		return 0;
	}

	/*
	 * must be parsable
	 */
	rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	/*
	 * Must be one-level
	 */
	if ( p[ 0 ] != '\0' ) {
		return 0;
	}

	/*
	 * Schema-aware validate
	 */
	if ( rc == LDAP_SUCCESS ) {
		rc = LDAPDN_validate( DN );
	}
	ldap_rdnfree( RDN );

	/*
	 * Must validate (there's a repeated parsing ...)
	 */
	return ( rc == LDAP_SUCCESS );
#endif
}
Esempio n. 4
0
static int
valsort_modify( Operation *op, SlapReply *rs )
{
	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
	valsort_info *vi = on->on_bi.bi_private;

	Modifications *ml;
	int i;
	char *ptr, *end;

	/* See if any weighted sorting applies to this entry */
	for ( ;vi;vi=vi->vi_next ) {
		if ( !dnIsSuffix( &op->o_req_ndn, &vi->vi_dn ))
			continue;
		if ( !(vi->vi_sort & VALSORT_WEIGHTED ))
			continue;
		for (ml = op->orm_modlist; ml; ml=ml->sml_next ) {
			/* Must be a Delete Attr op, so no values to consider */
			if ( !ml->sml_values )
				continue;
			if ( ml->sml_desc == vi->vi_ad )
				break;
		}
		if ( !ml )
			continue;
		for (i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++) {
			ptr = ber_bvchr(&ml->sml_values[i], '{' );
			if ( !ptr ) {
				Debug(LDAP_DEBUG_TRACE, "weight missing from attribute %s\n",
					vi->vi_ad->ad_cname.bv_val, 0, 0);
				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,
					"weight missing from attribute" );
				return rs->sr_err;
			}
			strtol( ptr+1, &end, 0 );
			if ( *end != '}' ) {
				Debug(LDAP_DEBUG_TRACE, "weight is misformatted in %s\n",
					vi->vi_ad->ad_cname.bv_val, 0, 0);
				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,
					"weight is misformatted" );
				return rs->sr_err;
			}
		}
	}
	return SLAP_CB_CONTINUE;
}
Esempio n. 5
0
/*
 * dnRdn - dn's rdn, in-place
 * note: the incoming dn is assumed to be normalized/prettyfied,
 * so that escaped rdn/ava separators are in '\'+hexpair form
 */
void
dnRdn( 
	struct berval	*dn, 
	struct berval	*rdn )
{
	char	*p;

	*rdn = *dn;
	p = ber_bvchr( dn, ',' );

	/* one-level dn */
	if ( p == NULL ) {
		return;
	}

	assert( DN_SEPARATOR( p[ 0 ] ) );
	assert( ATTR_LEADCHAR( p[ 1 ] ) );
	rdn->bv_len = p - dn->bv_val;

	return;
}
Esempio n. 6
0
static int
valsort_add( Operation *op, SlapReply *rs )
{
	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
	valsort_info *vi = on->on_bi.bi_private;

	Attribute *a;
	int i;
	char *ptr, *end;

	/* See if any weighted sorting applies to this entry */
	for ( ;vi;vi=vi->vi_next ) {
		if ( !dnIsSuffix( &op->o_req_ndn, &vi->vi_dn ))
			continue;
		if ( !(vi->vi_sort & VALSORT_WEIGHTED ))
			continue;
		a = attr_find( op->ora_e->e_attrs, vi->vi_ad );
		if ( !a )
			continue;
		for (i=0; !BER_BVISNULL( &a->a_vals[i] ); i++) {
			ptr = ber_bvchr(&a->a_vals[i], '{' );
			if ( !ptr ) {
				Debug(LDAP_DEBUG_TRACE, "weight missing from attribute %s\n",
					vi->vi_ad->ad_cname.bv_val, 0, 0);
				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,
					"weight missing from attribute" );
				return rs->sr_err;
			}
			strtol( ptr+1, &end, 0 );
			if ( *end != '}' ) {
				Debug(LDAP_DEBUG_TRACE, "weight is misformatted in %s\n",
					vi->vi_ad->ad_cname.bv_val, 0, 0);
				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,
					"weight is misformatted" );
				return rs->sr_err;
			}
		}
	}
	return SLAP_CB_CONTINUE;
}
Esempio n. 7
0
/* Find the given attribute's value in the RDN of the DN */
int nssov_find_rdnval(struct berval *dn, AttributeDescription *ad, struct berval *value)
{
	struct berval rdn;
	char *next;

	BER_BVZERO(value);
	dnRdn( dn, &rdn );
	do {
		next = ber_bvchr( &rdn, '+' );
		if ( rdn.bv_val[ad->ad_cname.bv_len] == '=' &&
			!ber_bvcmp( &rdn, &ad->ad_cname )) {
			if ( next )
				rdn.bv_len = next - rdn.bv_val;
			value->bv_val = rdn.bv_val + ad->ad_cname.bv_len + 1;
			value->bv_len = rdn.bv_len - ad->ad_cname.bv_len - 1;
			break;
		}
		if ( !next )
			break;
		next++;
		rdn.bv_len -= next - rdn.bv_val;
		rdn.bv_val = next;
	} while (1);
}
Esempio n. 8
0
static int
OpenLDAPaciPrettyNormal(
	struct berval	*val,
	struct berval	*out,
	void		*ctx,
	int		normalize )
{
	struct berval	oid = BER_BVNULL,
			scope = BER_BVNULL,
			rights = BER_BVNULL,
			nrights = BER_BVNULL,
			type = BER_BVNULL,
			ntype = BER_BVNULL,
			subject = BER_BVNULL,
			nsubject = BER_BVNULL;
	int		idx,
			rc = LDAP_SUCCESS,
			freesubject = 0,
			freetype = 0;
	char		*ptr;

	BER_BVZERO( out );

	if ( BER_BVISEMPTY( val ) ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" );
		return LDAP_INVALID_SYNTAX;
	}

	/* oid: if valid, it's already normalized */
	if ( acl_get_part( val, 0, '#', &oid ) < 0 ||
		numericoidValidate( NULL, &oid ) != LDAP_SUCCESS )
	{
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	/* scope: normalize by replacing with OpenLDAPaciscopes */
	if ( acl_get_part( val, 1, '#', &scope ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	idx = bv_getcaseidx( &scope, OpenLDAPaciscopes );
	if ( idx == -1 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	scope = *OpenLDAPaciscopes[ idx ];

	/* rights */
	if ( acl_get_part( val, 2, '#', &rights ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx )
		!= LDAP_SUCCESS )
	{
		return LDAP_INVALID_SYNTAX;
	}

	/* type */
	if ( acl_get_part( val, 3, '#', &type ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val );
		rc = LDAP_INVALID_SYNTAX;
		goto cleanup;
	}
	idx = bv_getcaseidx( &type, OpenLDAPacitypes );
	if ( idx == -1 ) {
		struct berval	isgr;

		if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) {
		        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		idx = bv_getcaseidx( &isgr, OpenLDAPacitypes );
		if ( idx == -1 || idx >= LAST_OPTIONAL ) {
		        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}
	}
	ntype = *OpenLDAPacitypes[ idx ];

	/* subject */
	bv_get_tail( val, &type, &subject );

	if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) {
	        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val );
		rc = LDAP_INVALID_SYNTAX;
		goto cleanup;
	}

	subject.bv_val++;
	subject.bv_len--;

	if ( idx < LAST_DNVALUED ) {
		/* FIXME: pass DN syntax? */
		if ( normalize ) {
			rc = dnNormalize( 0, NULL, NULL,
				&subject, &nsubject, ctx );
		} else {
			rc = dnPretty( NULL, &subject, &nsubject, ctx );
		}

		if ( rc == LDAP_SUCCESS ) {
			freesubject = 1;

		} else {
	                Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val );
			goto cleanup;
		}

		if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ]
			|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] )
		{
			/* do {group|role}/oc/at check */
			struct berval	ocbv = BER_BVNULL,
					atbv = BER_BVNULL;

			ocbv.bv_val = ber_bvchr( &type, '/' );
			if ( ocbv.bv_val != NULL ) {
				ObjectClass		*oc = NULL;
				AttributeDescription	*ad = NULL;
				const char		*text = NULL;
				int			rc;
				struct berval		bv;

				bv.bv_len = ntype.bv_len;

				ocbv.bv_val++;
				ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val );

				atbv.bv_val = ber_bvchr( &ocbv, '/' );
				if ( atbv.bv_val != NULL ) {
					atbv.bv_val++;
					atbv.bv_len = type.bv_len
						- ( atbv.bv_val - type.bv_val );
					ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1;

					rc = slap_bv2ad( &atbv, &ad, &text );
					if ( rc != LDAP_SUCCESS ) {
	                                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val );
						rc = LDAP_INVALID_SYNTAX;
						goto cleanup;
					}

					bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len;
				}

				oc = oc_bvfind( &ocbv );
				if ( oc == NULL ) {
                                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val );
					rc = LDAP_INVALID_SYNTAX;
					goto cleanup;
				}

				bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len;
				bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx );

				ptr = bv.bv_val;
				ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len );
				ptr[ 0 ] = '/';
				ptr++;
				ptr = lutil_strncopy( ptr,
					oc->soc_cname.bv_val,
					oc->soc_cname.bv_len );
				if ( ad != NULL ) {
					ptr[ 0 ] = '/';
					ptr++;
					ptr = lutil_strncopy( ptr,
						ad->ad_cname.bv_val,
						ad->ad_cname.bv_len );
				}
				ptr[ 0 ] = '\0';

				ntype = bv;
				freetype = 1;
			}
		}

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) {
		AttributeDescription	*ad = NULL;
		const char		*text = NULL;
		int			rc;

		rc = slap_bv2ad( &subject, &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
			/* FIXME: allow nameAndOptionalUID? */
                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		nsubject = ad->ad_cname;

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ]
		|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] )
	{
		/* NOTE: dunno how to normalize it... */
		nsubject = subject;
	}


	out->bv_len =
		oid.bv_len + STRLENOF( "#" )
		+ scope.bv_len + STRLENOF( "#" )
		+ nrights.bv_len + STRLENOF( "#" )
		+ ntype.bv_len + STRLENOF( "#" )
		+ nsubject.bv_len;

	out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx );
	ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	if ( !BER_BVISNULL( &nsubject ) ) {
		ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len );
	}
	ptr[ 0 ] = '\0';

cleanup:;
	if ( freesubject ) {
		ber_memfree_x( nsubject.bv_val, ctx );
	}

	if ( freetype ) {
		ber_memfree_x( ntype.bv_val, ctx );
	}

	if ( !BER_BVISNULL( &nrights ) ) {
		ber_memfree_x( nrights.bv_val, ctx );
	}

	return rc;
}
Esempio n. 9
0
static int
OpenLDAPaciValidate(
	Syntax		*syntax,
	struct berval	*val )
{
	struct berval	oid = BER_BVNULL,
			scope = BER_BVNULL,
			rights = BER_BVNULL,
			type = BER_BVNULL,
			subject = BER_BVNULL;
	int		idx;
	int		rc;

	if ( BER_BVISEMPTY( val ) ) {
		Debug( LDAP_DEBUG_ACL, "aciValidatet: value is empty\n" );
		return LDAP_INVALID_SYNTAX;
	}

	/* oid */
	if ( acl_get_part( val, 0, '#', &oid ) < 0 ||
		numericoidValidate( NULL, &oid ) != LDAP_SUCCESS )
	{
		/* NOTE: the numericoidValidate() is rather pedantic;
		 * I'd replace it with X-ORDERED VALUES so that
		 * it's guaranteed values are maintained and used
		 * in the desired order */
		Debug( LDAP_DEBUG_ACL, "aciValidate: invalid oid '%s'\n", oid.bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	/* scope */
	if ( acl_get_part( val, 1, '#', &scope ) < 0 ||
		bv_getcaseidx( &scope, OpenLDAPaciscopes ) == -1 )
	{
		Debug( LDAP_DEBUG_ACL, "aciValidate: invalid scope '%s'\n", scope.bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	/* rights */
	if ( acl_get_part( val, 2, '#', &rights ) < 0 ||
		OpenLDAPaciValidateRights( &rights ) != LDAP_SUCCESS )
	{
		return LDAP_INVALID_SYNTAX;
	}

	/* type */
	if ( acl_get_part( val, 3, '#', &type ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciValidate: missing type in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	idx = bv_getcaseidx( &type, OpenLDAPacitypes );
	if ( idx == -1 ) {
		struct berval	isgr;

		if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) {
			Debug( LDAP_DEBUG_ACL, "aciValidate: invalid type '%s'\n", type.bv_val );
			return LDAP_INVALID_SYNTAX;
		}

		idx = bv_getcaseidx( &isgr, OpenLDAPacitypes );
		if ( idx == -1 || idx >= LAST_OPTIONAL ) {
			Debug( LDAP_DEBUG_ACL, "aciValidate: invalid type '%s'\n", isgr.bv_val );
			return LDAP_INVALID_SYNTAX;
		}
	}

	/* subject */
	bv_get_tail( val, &type, &subject );
	if ( subject.bv_val[ 0 ] != '#' ) {
		Debug( LDAP_DEBUG_ACL, "aciValidate: missing subject in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	if ( idx >= LAST_DNVALUED ) {
		if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) {
			AttributeDescription	*ad = NULL;
			const char		*text = NULL;

			rc = slap_bv2ad( &subject, &ad, &text );
			if ( rc != LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_ACL, "aciValidate: unknown dn attribute '%s'\n", subject.bv_val );
				return LDAP_INVALID_SYNTAX;
			}

			if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
				/* FIXME: allow nameAndOptionalUID? */
				Debug( LDAP_DEBUG_ACL, "aciValidate: wrong syntax for dn attribute '%s'\n", subject.bv_val );
				return LDAP_INVALID_SYNTAX;
			}
		}

		/* not a DN */
		return LDAP_SUCCESS;

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ]
			|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] )
	{
		/* do {group|role}/oc/at check */
		struct berval	ocbv = BER_BVNULL,
				atbv = BER_BVNULL;

		ocbv.bv_val = ber_bvchr( &type, '/' );
		if ( ocbv.bv_val != NULL ) {
			ocbv.bv_val++;
			ocbv.bv_len = type.bv_len
					- ( ocbv.bv_val - type.bv_val );

			atbv.bv_val = ber_bvchr( &ocbv, '/' );
			if ( atbv.bv_val != NULL ) {
				AttributeDescription	*ad = NULL;
				const char		*text = NULL;
				int			rc;

				atbv.bv_val++;
				atbv.bv_len = type.bv_len
					- ( atbv.bv_val - type.bv_val );
				ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1;

				rc = slap_bv2ad( &atbv, &ad, &text );
				if ( rc != LDAP_SUCCESS ) {
				        Debug( LDAP_DEBUG_ACL, "aciValidate: unknown group attribute '%s'\n", atbv.bv_val );
					return LDAP_INVALID_SYNTAX;
				}
			}

			if ( oc_bvfind( &ocbv ) == NULL ) {
			        Debug( LDAP_DEBUG_ACL, "aciValidate: unknown group '%s'\n", ocbv.bv_val );
				return LDAP_INVALID_SYNTAX;
			}
		}
	}

	if ( BER_BVISEMPTY( &subject ) ) {
		/* empty DN invalid */
	        Debug( LDAP_DEBUG_ACL, "aciValidate: missing dn in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	subject.bv_val++;
	subject.bv_len--;

	/* FIXME: pass DN syntax? */
	rc = dnValidate( NULL, &subject );
	if ( rc != LDAP_SUCCESS ) {
	        Debug( LDAP_DEBUG_ACL, "aciValidate: invalid dn '%s'\n", subject.bv_val );
	}
	return rc;
}
Esempio n. 10
0
static int
do_base( char *uri, char *dn, struct berval *pass, char *base, char *filter, char *pwattr,
	int maxloop, int force, int chaserefs, int noinit, int delay,
	int action_type, void *action )
{
	LDAP	*ld = NULL;
	int  	i = 0;
	int     rc = LDAP_SUCCESS;
	ber_int_t msgid;
	LDAPMessage *res, *msg;
	char **dns = NULL;
	struct berval *creds = NULL;
	char *attrs[] = { LDAP_NO_ATTRS, NULL };
	int ndns = 0;
#ifdef _WIN32
	DWORD beg, end;
#else
	struct timeval beg, end;
#endif
	int version = LDAP_VERSION3;
	char *nullstr = "";

	ldap_initialize( &ld, uri );
	if ( ld == NULL ) {
		tester_perror( "ldap_initialize", NULL );
		exit( EXIT_FAILURE );
	}

	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
		chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );

	rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL );
	if ( rc != LDAP_SUCCESS ) {
		tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
		exit( EXIT_FAILURE );
	}

	fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n",
			(long) pid, maxloop, base, filter, pwattr );

	if ( pwattr != NULL ) {
		attrs[ 0 ] = pwattr;
	}
	rc = ldap_search_ext( ld, base, LDAP_SCOPE_SUBTREE,
			filter, attrs, 0, NULL, NULL, 0, 0, &msgid );
	if ( rc != LDAP_SUCCESS ) {
		tester_ldap_error( ld, "ldap_search_ext", NULL );
		exit( EXIT_FAILURE );
	}

	while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 )
	{
		BerElement *ber;
		struct berval bv;
		int done = 0;

		for ( msg = ldap_first_message( ld, res ); msg;
			msg = ldap_next_message( ld, msg ) )
		{
			switch ( ldap_msgtype( msg ) ) {
			case LDAP_RES_SEARCH_ENTRY:
				rc = ldap_get_dn_ber( ld, msg, &ber, &bv );
				dns = realloc( dns, (ndns + 1)*sizeof(char *) );
				dns[ndns] = ber_strdup( bv.bv_val );
				if ( pwattr != NULL ) {
					struct berval	**values = ldap_get_values_len( ld, msg, pwattr );

					creds = realloc( creds, (ndns + 1)*sizeof(struct berval) );
					if ( values == NULL ) {
novals:;
						creds[ndns].bv_len = 0;
						creds[ndns].bv_val = nullstr;

					} else {
						static struct berval	cleartext = BER_BVC( "{CLEARTEXT} " );
						struct berval		value = *values[ 0 ];

						if ( value.bv_val[ 0 ] == '{' ) {
							char *end = ber_bvchr( &value, '}' );

							if ( end ) {
								if ( ber_bvcmp( &value, &cleartext ) == 0 ) {
									value.bv_val += cleartext.bv_len;
									value.bv_len -= cleartext.bv_len;

								} else {
									ldap_value_free_len( values );
									goto novals;
								}
							}

						}

						ber_dupbv( &creds[ndns], &value );
						ldap_value_free_len( values );
					}
				}
				ndns++;
				ber_free( ber, 0 );
				break;

			case LDAP_RES_SEARCH_RESULT:
				done = 1;
				break;
			}
			if ( done )
				break;
		}
		ldap_msgfree( res );
		if ( done ) break;
	}

#ifdef _WIN32
	beg = GetTickCount();
#else
	gettimeofday( &beg, NULL );
#endif

	if ( ndns == 0 ) {
		tester_error( "No DNs" );
		return 1;
	}

	fprintf( stderr, "  PID=%ld - Bind base=\"%s\" filter=\"%s\" got %d values.\n",
		(long) pid, base, filter, ndns );

	/* Ok, got list of DNs, now start binding to each */
	for ( i = 0; i < maxloop; i++ ) {
		int		j;
		struct berval	cred = { 0, NULL };


#if 0	/* use high-order bits for better randomness (Numerical Recipes in "C") */
		j = rand() % ndns;
#endif
		j = ((double)ndns)*rand()/(RAND_MAX + 1.0);

		if ( creds && !BER_BVISEMPTY( &creds[j] ) ) {
			cred = creds[j];
		}

		if ( do_bind( uri, dns[j], &cred, 1, force, chaserefs, noinit, &ld,
			action_type, action ) && !force )
		{
			break;
		}

		if ( delay ) {
			sleep( delay );
		}
	}

	if ( ld != NULL ) {
		ldap_unbind_ext( ld, NULL, NULL );
		ld = NULL;
	}

#ifdef _WIN32
	end = GetTickCount();
	end -= beg;

	fprintf( stderr, "  PID=%ld - Bind done %d in %d.%03d seconds.\n",
		(long) pid, i, end / 1000, end % 1000 );
#else
	gettimeofday( &end, NULL );
	end.tv_usec -= beg.tv_usec;
	if (end.tv_usec < 0 ) {
		end.tv_usec += 1000000;
		end.tv_sec -= 1;
	}
	end.tv_sec -= beg.tv_sec;

	fprintf( stderr, "  PID=%ld - Bind done %d in %ld.%06ld seconds.\n",
		(long) pid, i, (long) end.tv_sec, (long) end.tv_usec );
#endif

	if ( dns ) {
		for ( i = 0; i < ndns; i++ ) {
			ber_memfree( dns[i] );
		}
		free( dns );
	}

	if ( creds ) {
		for ( i = 0; i < ndns; i++ ) {
			if ( creds[i].bv_val != nullstr ) {
				ber_memfree( creds[i].bv_val );
			}
		}
		free( creds );
	}

	return 0;
}
Esempio n. 11
0
static int
pw2entry( Backend *be, struct passwd *pw, Entry *e )
{
    size_t		pwlen;
    struct berval	val;
    struct berval	bv;

    int		rc;

    /*
     * from pw we get pw_name and make it cn
     * give it an objectclass of person.
     */

    pwlen = strlen( pw->pw_name );
    val.bv_len = STRLENOF("uid=,") + ( pwlen + be->be_suffix[0].bv_len );
    val.bv_val = ch_malloc( val.bv_len + 1 );

    /* rdn attribute type should be a configuratable item */
    sprintf( val.bv_val, "uid=%s,%s",
             pw->pw_name, be->be_suffix[0].bv_val );

    rc = dnNormalize( 0, NULL, NULL, &val, &bv, NULL );
    if( rc != LDAP_SUCCESS ) {
        free( val.bv_val );
        return( -1 );
    }

    e->e_name = val;
    e->e_nname = bv;

    e->e_attrs = NULL;

    /* objectclasses should be configurable items */
    BER_BVSTR( &val, "person" );
    attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL );

    BER_BVSTR( &val, "uidObject" );
    attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL );

    val.bv_val = pw->pw_name;
    val.bv_len = pwlen;
    attr_merge_normalize_one( e, slap_schema.si_ad_uid, &val, NULL );	/* required by uidObject */
    attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );	/* required by person */
    attr_merge_normalize_one( e, ad_sn, &val, NULL );	/* required by person */

#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
    /*
     * if gecos is present, add it as a cn. first process it
     * according to standard BSD usage. If the processed cn has
     * a space, use the tail as the surname.
     */
    if (pw->pw_gecos[0]) {
        char *s;

        ber_str2bv( pw->pw_gecos, 0, 0, &val );
        attr_merge_normalize_one( e, ad_desc, &val, NULL );

        s = ber_bvchr( &val, ',' );
        if ( s ) *s = '\0';

        s = ber_bvchr( &val, '&' );
        if ( s ) {
            char buf[1024];

            if( val.bv_len + pwlen < sizeof(buf) ) {
                int i = s - val.bv_val;
                strncpy( buf, val.bv_val, i );
                s = buf + i;
                strcpy( s, pw->pw_name );
                *s = TOUPPER((unsigned char)*s);
                strcat( s, val.bv_val + i + 1 );
                val.bv_val = buf;
            }
        }
        val.bv_len = strlen( val.bv_val );

        if ( val.bv_len && strcasecmp( val.bv_val, pw->pw_name ) ) {
            attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );
        }

        if ( ( s = strrchr(val.bv_val, ' ' ) ) ) {
            ber_str2bv( s + 1, 0, 0, &val );
            attr_merge_normalize_one( e, ad_sn, &val, NULL );
        }
    }
#endif /* HAVE_STRUCT_PASSWD_PW_GECOS */

    return( 0 );
}
Esempio n. 12
0
int
schema_info( Entry **entry, const char **text )
{
	AttributeDescription *ad_structuralObjectClass
		= slap_schema.si_ad_structuralObjectClass;
	AttributeDescription *ad_objectClass
		= slap_schema.si_ad_objectClass;
	AttributeDescription *ad_createTimestamp
		= slap_schema.si_ad_createTimestamp;
	AttributeDescription *ad_modifyTimestamp
		= slap_schema.si_ad_modifyTimestamp;

	Entry		*e;
	struct berval	vals[5];
	struct berval	nvals[5];

	e = entry_alloc();
	if( e == NULL ) {
		/* Out of memory, do something about it */
		Debug( LDAP_DEBUG_ANY, 
			"schema_info: entry_alloc failed - out of memory.\n", 0, 0, 0 );
		*text = "out of memory";
		return LDAP_OTHER;
	}

	e->e_attrs = NULL;
	/* backend-specific schema info should be created by the
	 * backend itself
	 */
	ber_dupbv( &e->e_name, &frontendDB->be_schemadn );
	ber_dupbv( &e->e_nname, &frontendDB->be_schemandn );
	e->e_private = NULL;

	BER_BVSTR( &vals[0], "subentry" );
	if( attr_merge_one( e, ad_structuralObjectClass, vals, NULL ) ) {
		/* Out of memory, do something about it */
		entry_free( e );
		*text = "out of memory";
		return LDAP_OTHER;
	}

	BER_BVSTR( &vals[0], "top" );
	BER_BVSTR( &vals[1], "subentry" );
	BER_BVSTR( &vals[2], "subschema" );
	BER_BVSTR( &vals[3], "extensibleObject" );
	BER_BVZERO( &vals[4] );
	if ( attr_merge( e, ad_objectClass, vals, NULL ) ) {
		/* Out of memory, do something about it */
		entry_free( e );
		*text = "out of memory";
		return LDAP_OTHER;
	}

	{
		int rc;
		AttributeDescription *desc = NULL;
		struct berval rdn = frontendDB->be_schemadn;
		vals[0].bv_val = ber_bvchr( &rdn, '=' );

		if( vals[0].bv_val == NULL ) {
			*text = "improperly configured subschema subentry";
			return LDAP_OTHER;
		}

		vals[0].bv_val++;
		vals[0].bv_len = rdn.bv_len - (vals[0].bv_val - rdn.bv_val);
		rdn.bv_len -= vals[0].bv_len + 1;

		rc = slap_bv2ad( &rdn, &desc, text );

		if( rc != LDAP_SUCCESS ) {
			entry_free( e );
			*text = "improperly configured subschema subentry";
			return LDAP_OTHER;
		}

		nvals[0].bv_val = ber_bvchr( &frontendDB->be_schemandn, '=' );
		assert( nvals[0].bv_val != NULL );
		nvals[0].bv_val++;
		nvals[0].bv_len = frontendDB->be_schemandn.bv_len -
			(nvals[0].bv_val - frontendDB->be_schemandn.bv_val);

		if ( attr_merge_one( e, desc, vals, nvals ) ) {
			/* Out of memory, do something about it */
			entry_free( e );
			*text = "out of memory";
			return LDAP_OTHER;
		}
	}

	{
		char		timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];

		/*
		 * According to RFC 4512:

   Servers SHOULD maintain the 'creatorsName', 'createTimestamp',       
   'modifiersName', and 'modifyTimestamp' attributes for all entries of 
   the DIT. 

		 * to be conservative, we declare schema created 
		 * AND modified at server startup time ...
		 */

		vals[0].bv_val = timebuf;
		vals[0].bv_len = sizeof( timebuf );

		slap_timestamp( &starttime, vals );

		if( attr_merge_one( e, ad_createTimestamp, vals, NULL ) ) {
			/* Out of memory, do something about it */
			entry_free( e );
			*text = "out of memory";
			return LDAP_OTHER;
		}
		if( attr_merge_one( e, ad_modifyTimestamp, vals, NULL ) ) {
			/* Out of memory, do something about it */
			entry_free( e );
			*text = "out of memory";
			return LDAP_OTHER;
		}
	}

	if ( syn_schema_info( e ) 
		|| mr_schema_info( e )
		|| mru_schema_info( e )
		|| at_schema_info( e )
		|| oc_schema_info( e )
		|| cr_schema_info( e ) )
	{
		/* Out of memory, do something about it */
		entry_free( e );
		*text = "out of memory";
		return LDAP_OTHER;
	}
	
	*entry = e;
	return LDAP_SUCCESS;
}
Esempio n. 13
0
/* Called for all modify and modrdn ops. If the current op was replicated
 * from elsewhere, all of the attrs should already be present.
 */
void slap_mods_opattrs(
	Operation *op,
	Modifications **modsp,
	int manage_ctxcsn )
{
	struct berval name, timestamp, csn = BER_BVNULL;
	struct berval nname;
	char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
	Modifications *mod, **modtail, *modlast;
	int gotcsn = 0, gotmname = 0, gotmtime = 0;

	if ( SLAP_LASTMOD( op->o_bd ) && !op->orm_no_opattrs ) {
		char *ptr;
		timestamp.bv_val = timebuf;
		for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) {
			if ( (*modtail)->sml_op != LDAP_MOD_ADD &&
				(*modtail)->sml_op != SLAP_MOD_SOFTADD &&
				(*modtail)->sml_op != SLAP_MOD_ADD_IF_NOT_PRESENT &&
				(*modtail)->sml_op != LDAP_MOD_REPLACE )
			{
				continue;
			}

			if ( (*modtail)->sml_desc == slap_schema.si_ad_entryCSN )
			{
				csn = (*modtail)->sml_values[0];
				gotcsn = 1;

			} else if ( (*modtail)->sml_desc == slap_schema.si_ad_modifiersName )
			{
				gotmname = 1;

			} else if ( (*modtail)->sml_desc == slap_schema.si_ad_modifyTimestamp )
			{
				gotmtime = 1;
			}
		}

		if ( BER_BVISEMPTY( &op->o_csn )) {
			if ( !gotcsn ) {
				csn.bv_val = csnbuf;
				csn.bv_len = sizeof( csnbuf );
				slap_get_csn( op, &csn, manage_ctxcsn );

			} else {
				if ( manage_ctxcsn ) {
					slap_queue_csn( op, &csn );
				}
			}

		} else {
			csn = op->o_csn;
		}

		ptr = ber_bvchr( &csn, '#' );
		if ( ptr ) {
			timestamp.bv_len = STRLENOF("YYYYMMDDHHMMSSZ");
			AC_MEMCPY( timebuf, csn.bv_val, timestamp.bv_len );
			timebuf[timestamp.bv_len-1] = 'Z';
			timebuf[timestamp.bv_len] = '\0';

		} else {
			time_t now = slap_get_time();

			timestamp.bv_len = sizeof(timebuf);

			slap_timestamp( &now, &timestamp );
		}

		if ( BER_BVISEMPTY( &op->o_dn ) ) {
			BER_BVSTR( &name, SLAPD_ANONYMOUS );
			nname = name;

		} else {
			name = op->o_dn;
			nname = op->o_ndn;
		}

		if ( !gotcsn ) {
			mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
			mod->sml_op = LDAP_MOD_REPLACE;
			mod->sml_flags = SLAP_MOD_INTERNAL;
			mod->sml_next = NULL;
			BER_BVZERO( &mod->sml_type );
			mod->sml_desc = slap_schema.si_ad_entryCSN;
			mod->sml_numvals = 1;
			mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_values[0], &csn );
			BER_BVZERO( &mod->sml_values[1] );
			assert( !BER_BVISNULL( &mod->sml_values[0] ) );
			mod->sml_nvalues = NULL;
			*modtail = mod;
			modlast = mod;
			modtail = &mod->sml_next;
		}

		if ( !gotmname ) {
			mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
			mod->sml_op = LDAP_MOD_REPLACE;
			mod->sml_flags = SLAP_MOD_INTERNAL;
			mod->sml_next = NULL;
			BER_BVZERO( &mod->sml_type );
			mod->sml_desc = slap_schema.si_ad_modifiersName;
			mod->sml_numvals = 1;
			mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_values[0], &name );
			BER_BVZERO( &mod->sml_values[1] );
			assert( !BER_BVISNULL( &mod->sml_values[0] ) );
			mod->sml_nvalues =
				(BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_nvalues[0], &nname );
			BER_BVZERO( &mod->sml_nvalues[1] );
			assert( !BER_BVISNULL( &mod->sml_nvalues[0] ) );
			*modtail = mod;
			modtail = &mod->sml_next;
		}

		if ( !gotmtime ) {
			mod = (Modifications *) ch_malloc( sizeof( Modifications ) );
			mod->sml_op = LDAP_MOD_REPLACE;
			mod->sml_flags = SLAP_MOD_INTERNAL;
			mod->sml_next = NULL;
			BER_BVZERO( &mod->sml_type );
			mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
			mod->sml_numvals = 1;
			mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod->sml_values[0], &timestamp );
			BER_BVZERO( &mod->sml_values[1] );
			assert( !BER_BVISNULL( &mod->sml_values[0] ) );
			mod->sml_nvalues = NULL;
			*modtail = mod;
			modtail = &mod->sml_next;
		}
	}
}
Esempio n. 14
0
static int
valsort_response( Operation *op, SlapReply *rs )
{
	slap_overinst *on;
	valsort_info *vi;
	Attribute *a;

	/* If this is not a search response, or it is a syncrepl response,
	 * or the valsort control wants raw results, pass thru unmodified.
	 */
	if ( rs->sr_type != REP_SEARCH ||
		( _SCM(op->o_sync) > SLAP_CONTROL_IGNORED ) ||
		( op->o_ctrlflag[valsort_cid] & SLAP_CONTROL_DATA0))
		return SLAP_CB_CONTINUE;
		
	on = (slap_overinst *) op->o_bd->bd_info;
	vi = on->on_bi.bi_private;

	/* And we must have something configured */
	if ( !vi ) return SLAP_CB_CONTINUE;

	/* Find a rule whose baseDN matches this entry */
	for (; vi; vi = vi->vi_next ) {
		int i, n;

		if ( !dnIsSuffix( &rs->sr_entry->e_nname, &vi->vi_dn ))
			continue;

		/* Find attr that this rule affects */
		a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad );
		if ( !a ) continue;

		if (( rs->sr_flags & ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) !=
			( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) )
		{
			Entry *e;

			e = entry_dup( rs->sr_entry );
			if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
				overlay_entry_release_ov( op, rs->sr_entry, 0, on );
				rs->sr_flags &= ~REP_ENTRY_MUSTRELEASE;
			} else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
				entry_free( rs->sr_entry );
			}
			rs->sr_entry = e;
			rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED;
			a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad );
		}

		n = a->a_numvals;
		if ( vi->vi_sort & VALSORT_WEIGHTED ) {
			int j, gotnvals;
			long *index = op->o_tmpalloc( n * sizeof(long), op->o_tmpmemctx );

			gotnvals = (a->a_vals != a->a_nvals );

			for (i=0; i<n; i++) {
				char *ptr = ber_bvchr( &a->a_nvals[i], '{' );
				char *end = NULL;
				if ( !ptr ) {
					Debug(LDAP_DEBUG_TRACE, "weights missing from attr %s "
						"in entry %s\n", vi->vi_ad->ad_cname.bv_val,
						rs->sr_entry->e_name.bv_val, 0 );
					break;
				}
				index[i] = strtol( ptr+1, &end, 0 );
				if ( *end != '}' ) {
					Debug(LDAP_DEBUG_TRACE, "weights misformatted "
						"in entry %s\n", 
						rs->sr_entry->e_name.bv_val, 0, 0 );
					break;
				}
				/* Strip out weights */
				ptr = a->a_nvals[i].bv_val;
				end++;
				for (;*end;)
					*ptr++ = *end++;
				*ptr = '\0';
				a->a_nvals[i].bv_len = ptr - a->a_nvals[i].bv_val;

				if ( a->a_vals != a->a_nvals ) {
					ptr = a->a_vals[i].bv_val;
					end = ber_bvchr( &a->a_vals[i], '}' );
					assert( end != NULL );
					end++;
					for (;*end;)
						*ptr++ = *end++;
					*ptr = '\0';
					a->a_vals[i].bv_len = ptr - a->a_vals[i].bv_val;
				}
			}
			/* An attr was missing weights here, ignore it */
			if ( i<n ) {
				op->o_tmpfree( index, op->o_tmpmemctx );
				continue;
			}
			/* Insertion sort */
			for ( i=1; i<n; i++) {
				long idx = index[i];
				struct berval tmp = a->a_vals[i], ntmp;
				if ( gotnvals ) ntmp = a->a_nvals[i];
				j = i;
				while (( j>0 ) && (index[j-1] > idx )) {
					index[j] = index[j-1];
					a->a_vals[j] = a->a_vals[j-1];
					if ( gotnvals ) a->a_nvals[j] = a->a_nvals[j-1];
					j--;
				}
				index[j] = idx;
				a->a_vals[j] = tmp;
				if ( gotnvals ) a->a_nvals[j] = ntmp;
			}
			/* Check for secondary sort */
			if ( vi->vi_sort ^ VALSORT_WEIGHTED ) {
				for ( i=0; i<n;) {
					for (j=i+1; j<n; j++) {
						if (index[i] != index[j])
							break;
					}
					if( j-i > 1 )
						do_sort( op, a, i, j-i, vi->vi_sort );
					i = j;
				}
			}
			op->o_tmpfree( index, op->o_tmpmemctx );
		} else {
			do_sort( op, a, 0, n, vi->vi_sort );
		}
	}
	return SLAP_CB_CONTINUE;
}
Esempio n. 15
0
int slap_bv2ad(
	struct berval *bv,
	AttributeDescription **ad,
	const char **text )
{
	int rtn = LDAP_UNDEFINED_TYPE;
	AttributeDescription desc, *d2;
	char *name, *options, *optn;
	char *opt, *next;
	int ntags;
	int tagslen;

	/* hardcoded limits for speed */
#define MAX_TAGGING_OPTIONS 128
	struct berval tags[MAX_TAGGING_OPTIONS+1];
#define MAX_TAGS_LEN 1024
	char tagbuf[MAX_TAGS_LEN];

	assert( ad != NULL );
	assert( *ad == NULL ); /* temporary */

	if( bv == NULL || BER_BVISNULL( bv ) || BER_BVISEMPTY( bv ) ) {
		*text = "empty AttributeDescription";
		return rtn;
	}

	/* make sure description is IA5 */
	if( ad_keystring( bv ) ) {
		*text = "AttributeDescription contains inappropriate characters";
		return rtn;
	}

	/* find valid base attribute type; parse in place */
	desc.ad_cname = *bv;
	desc.ad_flags = 0;
	BER_BVZERO( &desc.ad_tags );
	name = bv->bv_val;
	options = ber_bvchr( bv, ';' );
	if ( options != NULL && (unsigned) ( options - name ) < bv->bv_len ) {
		/* don't go past the end of the berval! */
		desc.ad_cname.bv_len = options - name;
	} else {
		options = NULL;
	}
	desc.ad_type = at_bvfind( &desc.ad_cname );
	if( desc.ad_type == NULL ) {
		*text = "attribute type undefined";
		return rtn;
	}

	if( is_at_operational( desc.ad_type ) && options != NULL ) {
		*text = "operational attribute with options undefined";
		return rtn;
	}

	/*
	 * parse options in place
	 */
	ntags = 0;
	tagslen = 0;
	optn = bv->bv_val + bv->bv_len;

	for( opt=options; opt != NULL; opt=next ) {
		int optlen;
		opt++; 
		next = strchrlen( opt, optn, ';', &optlen );

		if( optlen == 0 ) {
			*text = "zero length option is invalid";
			return rtn;
		
		} else if ( optlen == STRLENOF("binary") &&
			strncasecmp( opt, "binary", STRLENOF("binary") ) == 0 )
		{
			/* binary option */
			if( slap_ad_is_binary( &desc ) ) {
				*text = "option \"binary\" specified multiple times";
				return rtn;
			}

			if( !slap_syntax_is_binary( desc.ad_type->sat_syntax )) {
				/* not stored in binary, disallow option */
				*text = "option \"binary\" not supported with type";
				return rtn;
			}

			desc.ad_flags |= SLAP_DESC_BINARY;
			continue;

		} else if ( ad_find_option_definition( opt, optlen ) ) {
			int i;

			if( opt[optlen-1] == '-' ||
				( opt[optlen-1] == '=' && msad_range_hack )) {
				desc.ad_flags |= SLAP_DESC_TAG_RANGE;
			}

			if( ntags >= MAX_TAGGING_OPTIONS ) {
				*text = "too many tagging options";
				return rtn;
			}

			/*
			 * tags should be presented in sorted order,
			 * so run the array in reverse.
			 */
			for( i=ntags-1; i>=0; i-- ) {
				int rc;

				rc = strncasecmp( opt, tags[i].bv_val,
					(unsigned) optlen < tags[i].bv_len
						? (unsigned) optlen : tags[i].bv_len );

				if( rc == 0 && (unsigned)optlen == tags[i].bv_len ) {
					/* duplicate (ignore) */
					ntags--;
					goto done;

				} else if ( rc > 0 ||
					( rc == 0 && (unsigned)optlen > tags[i].bv_len ))
				{
					AC_MEMCPY( &tags[i+2], &tags[i+1],
						(ntags-i-1)*sizeof(struct berval) );
					tags[i+1].bv_val = opt;
					tags[i+1].bv_len = optlen;
					goto done;
				}
			}

			if( ntags ) {
				AC_MEMCPY( &tags[1], &tags[0],
					ntags*sizeof(struct berval) );
			}
			tags[0].bv_val = opt;
			tags[0].bv_len = optlen;

done:;
			tagslen += optlen + 1;
			ntags++;

		} else {
			*text = "unrecognized option";
			return rtn;
		}
	}

	if( ntags > 0 ) {
		int i;

		if( tagslen > MAX_TAGS_LEN ) {
			*text = "tagging options too long";
			return rtn;
		}

		desc.ad_tags.bv_val = tagbuf;
		tagslen = 0;

		for( i=0; i<ntags; i++ ) {
			AC_MEMCPY( &desc.ad_tags.bv_val[tagslen],
				tags[i].bv_val, tags[i].bv_len );

			tagslen += tags[i].bv_len;
			desc.ad_tags.bv_val[tagslen++] = ';';
		}

		desc.ad_tags.bv_val[--tagslen] = '\0';
		desc.ad_tags.bv_len = tagslen;
	}

	/* see if a matching description is already cached */
	for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) {
		if( d2->ad_flags != desc.ad_flags ) {
			continue;
		}
		if( d2->ad_tags.bv_len != desc.ad_tags.bv_len ) {
			continue;
		}
		if( d2->ad_tags.bv_len == 0 ) {
			break;
		}
		if( strncasecmp( d2->ad_tags.bv_val, desc.ad_tags.bv_val,
			desc.ad_tags.bv_len ) == 0 )
		{
			break;
		}
	}

	/* Not found, add new one */
	while (d2 == NULL) {
		size_t dlen = 0;
		ldap_pvt_thread_mutex_lock( &desc.ad_type->sat_ad_mutex );
		/* check again now that we've locked */
		for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) {
			if (d2->ad_flags != desc.ad_flags)
				continue;
			if (d2->ad_tags.bv_len != desc.ad_tags.bv_len)
				continue;
			if (d2->ad_tags.bv_len == 0)
				break;
			if (strncasecmp(d2->ad_tags.bv_val, desc.ad_tags.bv_val,
				desc.ad_tags.bv_len) == 0)
				break;
		}
		if (d2) {
			ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex );
			break;
		}

		/* Allocate a single contiguous block. If there are no
		 * options, we just need space for the AttrDesc structure.
		 * Otherwise, we need to tack on the full name length +
		 * options length, + maybe tagging options length again.
		 */
		if (desc.ad_tags.bv_len || desc.ad_flags != SLAP_DESC_NONE) {
			dlen = desc.ad_type->sat_cname.bv_len + 1;
			if (desc.ad_tags.bv_len) {
				dlen += 1 + desc.ad_tags.bv_len;
			}
			if ( slap_ad_is_binary( &desc ) ) {
				dlen += 1 + STRLENOF(";binary") + desc.ad_tags.bv_len;
			}
		}

		d2 = ch_malloc(sizeof(AttributeDescription) + dlen);
		d2->ad_next = NULL;
		d2->ad_type = desc.ad_type;
		d2->ad_flags = desc.ad_flags;
		d2->ad_cname.bv_len = desc.ad_type->sat_cname.bv_len;
		d2->ad_tags.bv_len = desc.ad_tags.bv_len;
		ldap_pvt_thread_mutex_lock( &ad_index_mutex );
		d2->ad_index = ++ad_count;
		ldap_pvt_thread_mutex_unlock( &ad_index_mutex );

		if (dlen == 0) {
			d2->ad_cname.bv_val = d2->ad_type->sat_cname.bv_val;
			d2->ad_tags.bv_val = NULL;
		} else {
			char *cp, *op, *lp;
			int j;
			d2->ad_cname.bv_val = (char *)(d2+1);
			strcpy(d2->ad_cname.bv_val, d2->ad_type->sat_cname.bv_val);
			cp = d2->ad_cname.bv_val + d2->ad_cname.bv_len;
			if( slap_ad_is_binary( &desc ) ) {
				op = cp;
				lp = NULL;
				if( desc.ad_tags.bv_len ) {
					lp = desc.ad_tags.bv_val;
					while( strncasecmp(lp, "binary", STRLENOF("binary")) < 0
					       && (lp = strchr( lp, ';' )) != NULL )
						++lp;
					if( lp != desc.ad_tags.bv_val ) {
						*cp++ = ';';
						j = (lp
						     ? (unsigned) (lp - desc.ad_tags.bv_val - 1)
						     : strlen( desc.ad_tags.bv_val ));
						cp = lutil_strncopy(cp, desc.ad_tags.bv_val, j);
					}
				}
				cp = lutil_strcopy(cp, ";binary");
				if( lp != NULL ) {
					*cp++ = ';';
					cp = lutil_strcopy(cp, lp);
				}
				d2->ad_cname.bv_len = cp - d2->ad_cname.bv_val;
				if( desc.ad_tags.bv_len )
					ldap_pvt_str2lower(op);
				j = 1;
			} else {
				j = 0;
			}
			if( desc.ad_tags.bv_len ) {
				lp = d2->ad_cname.bv_val + d2->ad_cname.bv_len + j;
				if ( j == 0 )
					*lp++ = ';';
				d2->ad_tags.bv_val = lp;
				strcpy(lp, desc.ad_tags.bv_val);
				ldap_pvt_str2lower(lp);
				if( j == 0 )
					d2->ad_cname.bv_len += 1 + desc.ad_tags.bv_len;
			}
		}
		/* Add new desc to list. We always want the bare Desc with
		 * no options to stay at the head of the list, assuming
		 * that one will be used most frequently.
		 */
		if (desc.ad_type->sat_ad == NULL || dlen == 0) {
			d2->ad_next = desc.ad_type->sat_ad;
			desc.ad_type->sat_ad = d2;
		} else {
			d2->ad_next = desc.ad_type->sat_ad->ad_next;
			desc.ad_type->sat_ad->ad_next = d2;
		}
		ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex );
	}

	if( *ad == NULL ) {
		*ad = d2;
	} else {
		**ad = *d2;
	}

	return LDAP_SUCCESS;
}
Esempio n. 16
0
/*
 * call from within ldap_back_db_open()
 */
int
ldap_back_monitor_db_open( BackendDB *be )
{
	ldapinfo_t		*li = (ldapinfo_t *) be->be_private;
	char			buf[ BACKMONITOR_BUFSIZE ];
	Entry			*e = NULL;
	monitor_callback_t	*cb = NULL;
	struct berval		suffix, *filter, *base;
	char			*ptr;
	time_t			now;
	char			timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	struct berval 		timestamp;
	int			rc = 0;
	BackendInfo		*mi;
	monitor_extra_t		*mbe;

	if ( !SLAP_DBMONITORING( be ) ) {
		return 0;
	}

	/* check if monitor is configured and usable */
	mi = backend_info( "monitor" );
	if ( !mi || !mi->bi_extra ) {
		SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
		return 0;
 	}
 	mbe = mi->bi_extra;

	/* don't bother if monitor is not configured */
	if ( !mbe->is_configured() ) {
		static int warning = 0;

		if ( warning++ == 0 ) {
			Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: "
				"monitoring disabled; "
				"configure monitor database to enable\n",
				0, 0, 0 );
		}

		return 0;
	}

	/* set up the fake subsystem that is used to create
	 * the volatile connection entries */
	li->li_monitor_info.lmi_mss.mss_name = "back-ldap";
	li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH;
	li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create;

	li->li_monitor_info.lmi_li = li;
	li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE;
	base = &li->li_monitor_info.lmi_base;
	BER_BVSTR( base, "cn=databases,cn=monitor" );
	filter = &li->li_monitor_info.lmi_filter;
	BER_BVZERO( filter );

	suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
	if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
		suffix = be->be_nsuffix[ 0 ];

	} else {
		ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
	}
	
	filter->bv_len = STRLENOF( "(&" )
		+ li->li_monitor_info.lmi_more_filter.bv_len
		+ STRLENOF( "(monitoredInfo=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( ")(!(monitorOverlay=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( "))(namingContexts:distinguishedNameMatch:=" )
		+ suffix.bv_len + STRLENOF( "))" );
	ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
	ptr = lutil_strcopy( ptr, "(&" );
	ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val,
		li->li_monitor_info.lmi_more_filter.bv_len );
	ptr = lutil_strcopy( ptr, "(monitoredInfo=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" );
	ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
	ptr = lutil_strcopy( ptr, "))" );
	ptr[ 0 ] = '\0';
	assert( ptr == &filter->bv_val[ filter->bv_len ] );

	if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
		ch_free( suffix.bv_val );
	}

	now = slap_get_time();
	timestamp.bv_val = timebuf;
	timestamp.bv_len = sizeof( timebuf );
	slap_timestamp( &now, &timestamp );

	/* caller (e.g. an overlay based on back-ldap) may want to use
	 * a different RDN... */
	if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) {
		ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn );
	}

	ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' );
	assert( ptr != NULL );
	ptr[ 0 ] = '\0';
	ptr++;

	snprintf( buf, sizeof( buf ),
		"dn: %s=%s\n"
		"objectClass: monitorContainer\n"
		"%s: %s\n"
		"creatorsName: %s\n"
		"createTimestamp: %s\n"
		"modifiersName: %s\n"
		"modifyTimestamp: %s\n",
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val );
	e = str2entry( buf );
	if ( e == NULL ) {
		rc = -1;
		goto cleanup;
	}

	ptr[ -1 ] = '=';

	/* add labeledURI and special, modifiable URI value */
	if ( li->li_uri != NULL ) {
		struct berval	bv;
		LDAPURLDesc	*ludlist = NULL;
		int		rc;

		rc = ldap_url_parselist_ext( &ludlist,
			li->li_uri, NULL,
			LDAP_PVT_URL_PARSE_NOEMPTY_HOST
				| LDAP_PVT_URL_PARSE_DEF_PORT );
		if ( rc != LDAP_URL_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
				"ldap_back_monitor_db_open: "
				"unable to parse URI list (ignored)\n",
				0, 0, 0 );
		} else {
			for ( ; ludlist != NULL; ) {
				LDAPURLDesc	*next = ludlist->lud_next;

				bv.bv_val = ldap_url_desc2str( ludlist );
				assert( bv.bv_val != NULL );
				ldap_free_urldesc( ludlist );
				bv.bv_len = strlen( bv.bv_val );
				attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI,
					&bv, NULL );
				ch_free( bv.bv_val );

				ludlist = next;
			}
		}
		
		ber_str2bv( li->li_uri, 0, 0, &bv );
		attr_merge_normalize_one( e, ad_olmDbURIList,
			&bv, NULL );
	}

	ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname );

	cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
	cb->mc_update = ldap_back_monitor_update;
	cb->mc_modify = ldap_back_monitor_modify;
	cb->mc_free = ldap_back_monitor_free;
	cb->mc_private = (void *)li;

	rc = mbe->register_entry_parent( e, cb,
		(monitor_subsys_t *)&li->li_monitor_info,
		MONITOR_F_VOLATILE_CH,
		base, LDAP_SCOPE_SUBORDINATE, filter );

cleanup:;
	if ( rc != 0 ) {
		if ( cb != NULL ) {
			ch_free( cb );
			cb = NULL;
		}

		if ( e != NULL ) {
			entry_free( e );
			e = NULL;
		}

		if ( !BER_BVISNULL( filter ) ) {
			ch_free( filter->bv_val );
			BER_BVZERO( filter );
		}
	}

	/* store for cleanup */
	li->li_monitor_info.lmi_cb = (void *)cb;

	if ( e != NULL ) {
		entry_free( e );
	}

	return rc;
}