/* * ldap_compare_ext - perform an ldap extended compare operation. The dn * of the entry to compare to and the attribute and value to compare (in * attr and value) are supplied. The msgid of the response is returned. * * Example: * struct berval bvalue = { "secret", sizeof("secret")-1 }; * rc = ldap_compare( ld, "c=us@cn=bob", * "userPassword", &bvalue, * sctrl, cctrl, &msgid ) */ int ldap_compare_ext( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, struct berval *bvalue, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_compare\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( attr != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; ber = ldap_build_compare_req( ld, dn, attr, bvalue, sctrls, cctrls, &id ); if( !ber ) return ld->ld_errno; /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber, id ); return ( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
/* * ldap_compare - perform an ldap (and X.500) compare operation. The dn * of the entry to compare to and the attribute and value to compare (in * attr and value) are supplied. The msgid of the response is returned. * * Example: * ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" ) */ int ldap_compare( LDAP *ld, char *dn, char *attr, char *value ) { BerElement *ber; struct berval bv; int rv; /* The compare request looks like this: * CompareRequest ::= SEQUENCE { * entry DistinguishedName, * ava SEQUENCE { * type AttributeType, * value AttributeValue * } * } * and must be wrapped in an LDAPMessage. */ #ifdef _REENTRANT LOCK_LDAP(ld); #endif Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 ); bv.bv_val = value; bv.bv_len = strlen(value); if ((ber = ldap_build_compare_req(ld, dn, attr, &bv, NULL)) == NULLBER) { #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return (-1); } #ifndef NO_CACHE if ( ld->ld_cache != NULL ) { if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) { ber_free( ber, 1 ); ld->ld_errno = LDAP_SUCCESS; #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return( ld->ld_msgid ); } add_request_to_cache( ld, LDAP_REQ_COMPARE, ber ); } #endif /* NO_CACHE */ /* send the message */ rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber ); #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return (rv); }
meta_search_candidate_t asyncmeta_back_compare_start(Operation *op, SlapReply *rs, a_metaconn_t *mc, bm_context_t *bc, int candidate) { a_dncookie dc; a_metainfo_t *mi = mc->mc_info; a_metatarget_t *mt = mi->mi_targets[ candidate ]; struct berval mdn = BER_BVNULL; struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname; struct berval mapped_value = op->orc_ava->aa_value; int rc = 0, nretries = 1; LDAPControl **ctrls = NULL; meta_search_candidate_t retcode = META_SEARCH_CANDIDATE; BerElement *ber = NULL; a_metasingleconn_t *msc = &mc->mc_conns[ candidate ]; SlapReply *candidates = bc->candidates; ber_int_t msgid; dc.target = mt; dc.conn = op->o_conn; dc.rs = rs; dc.ctx = "compareDN"; switch ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) { case LDAP_UNWILLING_TO_PERFORM: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; retcode = META_SEARCH_ERR; goto doreturn; default: break; } /* * if attr is objectClass, try to remap the value */ if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) { asyncmeta_map( &mt->mt_rwmap.rwm_oc, &op->orc_ava->aa_value, &mapped_value, BACKLDAP_MAP ); if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) { rs->sr_err = LDAP_OTHER; retcode = META_SEARCH_ERR; goto done; } /* * else try to remap the attribute */ } else { asyncmeta_map( &mt->mt_rwmap.rwm_at, &op->orc_ava->aa_desc->ad_cname, &mapped_attr, BACKLDAP_MAP ); if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) { rs->sr_err = LDAP_OTHER; retcode = META_SEARCH_ERR; goto done; } if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { dc.ctx = "compareAttrDN"; switch ( asyncmeta_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) ) { case LDAP_UNWILLING_TO_PERFORM: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; retcode = META_SEARCH_ERR; goto done; default: break; } } } retry:; ctrls = op->o_ctrls; if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS ) { candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_ERR; goto done; } ber = ldap_build_compare_req( msc->msc_ld, mdn.bv_val, mapped_attr.bv_val, &mapped_value, ctrls, NULL, &msgid); if (ber) { candidates[ candidate ].sr_msgid = msgid; rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_COMPARE, mdn.bv_val, ber, msgid ); if (rc == msgid) rc = LDAP_SUCCESS; else rc = LDAP_SERVER_DOWN; switch ( rc ) { case LDAP_SUCCESS: retcode = META_SEARCH_CANDIDATE; asyncmeta_set_msc_time(msc); break; case LDAP_SERVER_DOWN: ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex); asyncmeta_clear_one_msc(NULL, mc, candidate); ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex); if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) { nretries = 0; /* if the identity changed, there might be need to re-authz */ (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); goto retry; } default: candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_ERR; } } done: (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); } if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) { free( mapped_value.bv_val ); } doreturn:; Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_compare_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid ); return retcode; }
/* LDAPv3 API extensions */ int ldap_compare_ext(LDAP *ld, char *dn, char *attr, struct berval *bvalue, LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp) { BerElement *ber; struct berval bv; int rv; /* The compare request looks like this: * CompareRequest ::= SEQUENCE { * entry DistinguishedName, * ava SEQUENCE { * type AttributeType, * value AttributeValue * } * } * and must be wrapped in an LDAPMessage. */ #ifdef _REENTRANT LOCK_LDAP(ld); #endif Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 ); if ((ber = ldap_build_compare_req(ld, dn, attr, bvalue, NULL)) == NULLBER) { rv = ld->ld_errno; if (rv == LDAP_SUCCESS) rv = LDAP_OTHER; #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return (rv); } #ifndef NO_CACHE if ( ld->ld_cache != NULL ) { if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) { ber_free( ber, 1 ); ld->ld_errno = LDAP_SUCCESS; *msgidp = ld->ld_msgid; #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return( LDAP_SUCCESS ); } add_request_to_cache( ld, LDAP_REQ_COMPARE, ber ); } #endif /* NO_CACHE */ /* send the message */ rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber ); if (rv == -1) { rv = ld->ld_errno; if (rv == LDAP_SUCCESS){ rv = LDAP_OTHER; } #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return (rv); } *msgidp = rv; #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return (LDAP_SUCCESS); }