/* * ldap_search - initiate an ldap search operation. * * Parameters: * * ld LDAP descriptor * base DN of the base object * scope the search scope - one of LDAP_SCOPE_BASE, * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE * filter a string containing the search filter * (e.g., "(|(cn=bob)(sn=bob))") * attrs list of attribute types to return for matches * attrsonly 1 => attributes only 0 => attributes and values * * Example: * char *attrs[] = { "mail", "title", 0 }; * msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", * attrs, attrsonly ); */ int ldap_search( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly ) { BerElement *ber; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "ldap_search\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); #endif assert( ld != NULL ); assert( LDAP_VALID( ld ) ); ber = ldap_build_search_req( ld, base, scope, filter, attrs, attrsonly, NULL, NULL, -1, -1 ); if ( ber == NULL ) { return( -1 ); } /* send the message */ return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber )); }
/* * ldap_modify_ext - initiate an ldap extended modify operation. * * Parameters: * * ld LDAP descriptor * dn DN of the object to modify * mods List of modifications to make. This is null-terminated * array of struct ldapmod's, specifying the modifications * to perform. * sctrls Server Controls * cctrls Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *mods[] = { * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_DELETE, "ou", 0 }, * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } * 0 * } * rc= ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid ); */ int ldap_modify_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; ber = ldap_build_modify_req( ld, dn, mods, sctrls, cctrls, &id ); if( !ber ) return ld->ld_errno; /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
/* * 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 ); }
int ldap_rename( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_rename\n" ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; ber = ldap_build_moddn_req( ld, dn, newrdn, newSuperior, deleteoldrdn, sctrls, cctrls, &id ); if( !ber ) return ld->ld_errno; /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id ); if( *msgidp < 0 ) { return( ld->ld_errno ); } return LDAP_SUCCESS; }
/* * ldap_delete_ext - initiate an ldap extended delete operation. Parameters: * * ld LDAP descriptor * dn DN of the object to delete * sctrls Server Controls * cctrls Client Controls * msgidp Message Id Pointer * * Example: * rc = ldap_delete( ld, dn, sctrls, cctrls, msgidp ); */ int ldap_delete_ext( LDAP *ld, LDAP_CONST char* dn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { int rc; BerElement *ber; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "ldap_delete_ext\n", 0,0,0 ); #else Debug( LDAP_DEBUG_TRACE, "ldap_delete_ext\n", 0, 0, 0 ); #endif assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } if ( ber_printf( ber, "{its", /* '}' */ ++ld->ld_msgid, LDAP_REQ_DELETE, dn ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_DELETE, dn, ber ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; }
/* * 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; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID(ld, id); rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */ id, LDAP_REQ_COMPARE, dn, attr, bvalue ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); 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_kerberos_bind1 - initiate a bind to the ldap server using * kerberos authentication. The dn is supplied. It is assumed the user * already has a valid ticket granting ticket. The msgid of the * request is returned on success (suitable for passing to ldap_result()), * -1 is returned if there's trouble. * * Example: * ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" ) */ int ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn ) { BerElement *ber; char *cred; int rc; ber_len_t credlen; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 ); if( ld->ld_version > LDAP_VERSION2 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return -1; } if ( dn == NULL ) dn = ""; if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver", &credlen )) == NULL ) { return( -1 ); /* ld_errno should already be set */ } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { LDAP_FREE( cred ); return( -1 ); } LDAP_NEXT_MSGID( ld, id ); /* fill it in */ rc = ber_printf( ber, "{it{istoN}N}", id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen ); if ( rc == -1 ) { LDAP_FREE( cred ); ber_free( ber, 1 ); ld->ld_errno = LDAP_ENCODING_ERROR; return( -1 ); } LDAP_FREE( cred ); /* send the message */ return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id )); }
/* * ldap_search - initiate an ldap search operation. * * Parameters: * * ld LDAP descriptor * base DN of the base object * scope the search scope - one of * LDAP_SCOPE_BASE (baseObject), * LDAP_SCOPE_ONELEVEL (oneLevel), * LDAP_SCOPE_SUBTREE (subtree), or * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension * filter a string containing the search filter * (e.g., "(|(cn=bob)(sn=bob))") * attrs list of attribute types to return for matches * attrsonly 1 => attributes only 0 => attributes and values * * Example: * char *attrs[] = { "mail", "title", 0 }; * msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", * attrs, attrsonly ); */ int ldap_search( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly ) { BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); ber = ldap_build_search_req( ld, base, scope, filter, attrs, attrsonly, NULL, NULL, -1, -1, -1, &id ); if ( ber == NULL ) { return( -1 ); } /* send the message */ return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id )); }
int ldap_sasl_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; ber = ldap_build_bind_req( ld, dn, mechanism, cred, sctrls, cctrls, &id ); if( !ber ) return ld->ld_errno; /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; }
/* * ldap_modify_ext - initiate an ldap extended modify operation. * * Parameters: * * ld LDAP descriptor * dn DN of the object to modify * mods List of modifications to make. This is null-terminated * array of struct ldapmod's, specifying the modifications * to perform. * sctrls Server Controls * cctrls Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *mods[] = { * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_DELETE, "ou", 0 }, * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } * 0 * } * rc= ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid ); */ int ldap_modify_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID( ld, id ); rc = ber_printf( ber, "{it{s{" /*}}}*/, id, LDAP_REQ_MODIFY, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* allow mods to be NULL ("touch") */ if ( mods ) { /* for each modification to be performed... */ for ( i = 0; mods[i] != NULL; i++ ) { if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { rc = ber_printf( ber, "{e{s[V]N}N}", (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ), mods[i]->mod_type, mods[i]->mod_bvalues ); } else { rc = ber_printf( ber, "{e{s[v]N}N}", (ber_int_t) mods[i]->mod_op, mods[i]->mod_type, mods[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
int ldap_extended_operation( LDAP *ld, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( reqoid != NULL && *reqoid != '\0' ); assert( msgidp != NULL ); /* must be version 3 (or greater) */ if ( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return( ld->ld_errno ); } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } LDAP_NEXT_MSGID( ld, id ); if ( reqdata != NULL ) { rc = ber_printf( ber, "{it{tstON}", /* '}' */ id, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, reqoid, LDAP_TAG_EXOP_REQ_VALUE, reqdata ); } else { rc = ber_printf( ber, "{it{tsN}", /* '}' */ id, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, reqoid ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
/* * ldap_modify_ext - initiate an ldap extended modify operation. * * Parameters: * * ld LDAP descriptor * dn DN of the object to modify * mods List of modifications to make. This is null-terminated * array of struct ldapmod's, specifying the modifications * to perform. * sctrls Server Controls * cctrls Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *mods[] = { * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_REPLACE, "sn", { "jensen", 0 } }, * 0 * } * rc= ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid ); */ int ldap_modify_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; /* * A modify request looks like this: * ModifyRequet ::= SEQUENCE { * object DistinguishedName, * modifications SEQUENCE OF SEQUENCE { * operation ENUMERATED { * add (0), * delete (1), * replace (2) * }, * modification SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } * } */ #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "ldap_modify_ext\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); #endif /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } if ( ber_printf( ber, "{it{s{" /*}}}*/, ++ld->ld_msgid, LDAP_REQ_MODIFY, dn ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* for each modification to be performed... */ for ( i = 0; mods[i] != NULL; i++ ) { if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { rc = ber_printf( ber, "{e{s[V]N}N}", (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ), mods[i]->mod_type, mods[i]->mod_bvalues ); } else { rc = ber_printf( ber, "{e{s[v]N}N}", (ber_int_t) mods[i]->mod_op, mods[i]->mod_type, mods[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
meta_search_candidate_t asyncmeta_back_modrdn_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, mnewSuperior = BER_BVNULL, newrdn = BER_BVNULL; 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; if ( op->orr_newSup ) { /* * NOTE: the newParent, if defined, must be on the * same target as the entry to be renamed. This check * has been anticipated in meta_back_getconn() */ /* * FIXME: one possibility is to delete the entry * from one target and add it to the other; * unfortunately we'd need write access to both, * which is nearly impossible; for administration * needs, the rootdn of the metadirectory could * be mapped to an administrative account on each * target (the binddn?); we'll see. */ /* * NOTE: we need to port the identity assertion * feature from back-ldap */ /* needs LDAPv3 */ switch ( mt->mt_version ) { case LDAP_VERSION3: break; case 0: if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { break; } /* fall thru */ default: /* op->o_protocol cannot be anything but LDAPv3, * otherwise wouldn't be here */ rs->sr_err = LDAP_UNWILLING_TO_PERFORM; retcode = META_SEARCH_ERR; goto done; } /* * Rewrite the new superior, if defined and required */ dc.ctx = "newSuperiorDN"; if ( asyncmeta_dn_massage( &dc, op->orr_newSup, &mnewSuperior ) ) { rs->sr_err = LDAP_OTHER; retcode = META_SEARCH_ERR; goto done; } } /* * Rewrite the modrdn dn, if required */ dc.ctx = "modrDN"; if ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) { rs->sr_err = LDAP_OTHER; retcode = META_SEARCH_ERR; goto done; } /* NOTE: we need to copy the newRDN in case it was formed * from a DN by simply changing the length (ITS#5397) */ newrdn = op->orr_newrdn; if ( newrdn.bv_val[ newrdn.bv_len ] != '\0' ) { ber_dupbv_x( &newrdn, &op->orr_newrdn, op->o_tmpmemctx ); } 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_moddn_req( msc->msc_ld, mdn.bv_val, newrdn.bv_val, mnewSuperior.bv_val, op->orr_deleteoldrdn, ctrls, NULL, &msgid); if (ber) { candidates[ candidate ].sr_msgid = msgid; rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_MODRDN, 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 ); BER_BVZERO( &mdn ); } if ( !BER_BVISNULL( &mnewSuperior ) && mnewSuperior.bv_val != op->orr_newSup->bv_val ) { free( mnewSuperior.bv_val ); BER_BVZERO( &mnewSuperior ); } if ( newrdn.bv_val != op->orr_newrdn.bv_val ) { op->o_tmpfree( newrdn.bv_val, op->o_tmpmemctx ); } doreturn:; Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_modrdn_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid ); return retcode; }
meta_search_candidate_t asyncmeta_back_add_start(Operation *op, SlapReply *rs, a_metaconn_t *mc, bm_context_t *bc, int candidate) { int isupdate; Attribute *a; int i; LDAPMod **attrs; struct berval mapped; a_dncookie dc; a_metainfo_t *mi = mc->mc_info; a_metatarget_t *mt = mi->mi_targets[ candidate ]; struct berval mdn; 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; LDAPControl **ctrls = NULL; int rc, nretries = 1; dc.target = mt; dc.conn = op->o_conn; dc.rs = rs; dc.ctx = "addDN"; mdn.bv_len = 0; switch (asyncmeta_dn_massage( &dc, &bc->op->o_req_dn, &mdn ) ) { case LDAP_SUCCESS: break; case LDAP_UNWILLING_TO_PERFORM: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "Operation not allowed"; retcode = META_SEARCH_ERR; goto doreturn; default: rs->sr_err = LDAP_NO_SUCH_OBJECT; retcode = META_SEARCH_NOT_CANDIDATE; goto doreturn; } /* Count number of attributes in entry ( +1 ) */ for ( i = 1, a = op->ora_e->e_attrs; a; i++, a = a->a_next ); /* Create array of LDAPMods for ldap_add() */ attrs = ch_malloc( sizeof( LDAPMod * )*i ); dc.ctx = "addAttrDN"; isupdate = be_shadow_update( op ); for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) { int j, is_oc = 0; if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod ) { continue; } if ( a->a_desc == slap_schema.si_ad_objectClass || a->a_desc == slap_schema.si_ad_structuralObjectClass ) { is_oc = 1; mapped = a->a_desc->ad_cname; } else { asyncmeta_map( &mt->mt_rwmap.rwm_at, &a->a_desc->ad_cname, &mapped, BACKLDAP_MAP ); if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) { continue; } } attrs[ i ] = ch_malloc( sizeof( LDAPMod ) ); if ( attrs[ i ] == NULL ) { continue; } attrs[ i ]->mod_op = LDAP_MOD_BVALUES; attrs[ i ]->mod_type = mapped.bv_val; if ( is_oc ) { for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ); attrs[ i ]->mod_bvalues = (struct berval **)ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) { struct ldapmapping *mapping; asyncmeta_mapping( &mt->mt_rwmap.rwm_oc, &a->a_vals[ j ], &mapping, BACKLDAP_MAP ); if ( mapping == NULL ) { if ( mt->mt_rwmap.rwm_oc.drop_missing ) { continue; } attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ]; } else { attrs[ i ]->mod_bvalues[ j ] = &mapping->dst; } j++; } attrs[ i ]->mod_bvalues[ j ] = NULL; } else { /* * FIXME: dn-valued attrs should be rewritten * to allow their use in ACLs at the back-ldap * level. */ if ( a->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { (void)asyncmeta_dnattr_rewrite( &dc, a->a_vals ); if ( a->a_vals == NULL ) { continue; } } for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) ; attrs[ i ]->mod_bvalues = ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) { attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ]; } attrs[ i ]->mod_bvalues[ j ] = NULL; } i++; } attrs[ i ] = NULL; 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_add_req( msc->msc_ld, mdn.bv_val, attrs, ctrls, NULL, &msgid); if (ber) { candidates[ candidate ].sr_msgid = msgid; rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_ADD, 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 ); for ( --i; i >= 0; --i ) { free( attrs[ i ]->mod_bvalues ); free( attrs[ i ] ); } free( attrs ); if ( mdn.bv_val != op->ora_e->e_dn ) { free( mdn.bv_val ); BER_BVZERO( &mdn ); } doreturn:; Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_add_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid ); return retcode; }
/* * ldap_search_ext - initiate an ldap search operation. * * Parameters: * * ld LDAP descriptor * base DN of the base object * scope the search scope - one of LDAP_SCOPE_BASE, * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE * filter a string containing the search filter * (e.g., "(|(cn=bob)(sn=bob))") * attrs list of attribute types to return for matches * attrsonly 1 => attributes only 0 => attributes and values * * Example: * char *attrs[] = { "mail", "title", 0 }; * ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit, * &msgid ); */ int ldap_search_ext( LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, struct timeval *timeout, int sizelimit, int *msgidp ) { int rc; BerElement *ber; int timelimit; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "ldap_search_ext\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); #endif assert( ld != NULL ); assert( LDAP_VALID( ld ) ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* * if timeout is provided, both tv_sec and tv_usec must * be non-zero */ if( timeout != NULL ) { if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) { return LDAP_PARAM_ERROR; } /* timelimit must be non-zero if timeout is provided */ timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1; } else { /* no timeout, no timelimit */ timelimit = -1; } ber = ldap_build_search_req( ld, base, scope, filter, attrs, attrsonly, sctrls, cctrls, timelimit, sizelimit ); if ( ber == NULL ) { return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ); if( *msgidp < 0 ) return ld->ld_errno; return LDAP_SUCCESS; }
/* * ldap_add_ext - initiate an ldap extended add operation. Parameters: * * ld LDAP descriptor * dn DN of the entry to add * mods List of attributes for the entry. This is a null- * terminated array of pointers to LDAPMod structures. * only the type and values in the structures need be * filled in. * sctrl Server Controls * cctrl Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *attrs[] = { * { 0, "cn", { "babs jensen", "babs", 0 } }, * { 0, "sn", { "jensen", 0 } }, * { 0, "objectClass", { "person", 0 } }, * 0 * } * rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ); */ int ldap_add_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_NEXT_MSGID(ld, id); rc = ber_printf( ber, "{it{s{", /* '}}}' */ id, LDAP_REQ_ADD, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* allow attrs to be NULL ("touch"; should fail...) */ if ( attrs ) { /* for each attribute in the entry... */ for ( i = 0; attrs[i] != NULL; i++ ) { if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { int j; if ( attrs[i]->mod_bvalues == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) { if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } } rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type, attrs[i]->mod_bvalues ); } else { if ( attrs[i]->mod_values == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type, attrs[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; }
int ldap_rename( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID( ld, id ); if( newSuperior != NULL ) { /* must be version 3 (or greater) */ if ( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; ber_free( ber, 1 ); return( ld->ld_errno ); } rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */ id, LDAP_REQ_MODDN, dn, newrdn, (ber_int_t) deleteoldrdn, LDAP_TAG_NEWSUPERIOR, newSuperior ); } else { rc = ber_printf( ber, "{it{ssbN}", /* '}' */ id, LDAP_REQ_MODDN, dn, newrdn, (ber_int_t) deleteoldrdn ); } if ( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } rc = ber_printf( ber, /*{*/ "N}" ); if ( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id ); if( *msgidp < 0 ) { return( ld->ld_errno ); } return LDAP_SUCCESS; }
int ldap_sasl_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; #ifdef NEW_LOGGING LDAP_LOG ( TRANSPORT, ENTRY, "ldap_sasl_bind\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); #endif assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; if( mechanism == LDAP_SASL_SIMPLE ) { if( dn == NULL && cred != NULL && cred->bv_len ) { /* use default binddn */ dn = ld->ld_defbinddn; } } else if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } if ( dn == NULL ) { dn = ""; } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } assert( LBER_VALID( ber ) ); if( mechanism == LDAP_SASL_SIMPLE ) { /* simple bind */ rc = ber_printf( ber, "{it{istON}" /*}*/, ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SIMPLE, cred ); } else if ( cred == NULL || cred->bv_val == NULL ) { /* SASL bind w/o creditials */ rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/, ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism ); } else { /* SASL bind w/ creditials */ rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/, ++ld->ld_msgid, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism, cred ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( -1 ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; }
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; }
meta_search_candidate_t asyncmeta_back_search_start( Operation *op, SlapReply *rs, a_metaconn_t *mc, bm_context_t *bc, int candidate, struct berval *prcookie, ber_int_t prsize ) { SlapReply *candidates = bc->candidates; a_metainfo_t *mi = ( a_metainfo_t * )mc->mc_info; a_metatarget_t *mt = mi->mi_targets[ candidate ]; a_metasingleconn_t *msc = &mc->mc_conns[ candidate ]; a_dncookie dc; struct berval realbase = op->o_req_dn; int realscope = op->ors_scope; struct berval mbase = BER_BVNULL; struct berval mfilter = BER_BVNULL; char **mapped_attrs = NULL; int rc; meta_search_candidate_t retcode; int timelimit; int nretries = 1; LDAPControl **ctrls = NULL; BerElement *ber; ber_int_t msgid; #ifdef SLAPD_META_CLIENT_PR LDAPControl **save_ctrls = NULL; #endif /* SLAPD_META_CLIENT_PR */ /* this should not happen; just in case... */ if ( msc->msc_ld == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: asyncmeta_back_search_start candidate=%d ld=NULL%s.\n", op->o_log_prefix, candidate, META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" ); candidates[ candidate ].sr_err = LDAP_OTHER; if ( META_BACK_ONERR_STOP( mi ) ) { return META_SEARCH_ERR; } candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; return META_SEARCH_NOT_CANDIDATE; } Debug( LDAP_DEBUG_TRACE, "%s >>> asyncmeta_back_search_start[%d]\n", op->o_log_prefix, candidate, 0 ); /* * modifies the base according to the scope, if required */ if ( mt->mt_nsuffix.bv_len > op->o_req_ndn.bv_len ) { switch ( op->ors_scope ) { case LDAP_SCOPE_SUBTREE: /* * make the target suffix the new base * FIXME: this is very forgiving, because * "illegal" searchBases may be turned * into the suffix of the target; however, * the requested searchBase already passed * thru the candidate analyzer... */ if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) { realbase = mt->mt_nsuffix; if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) { realscope = LDAP_SCOPE_SUBORDINATE; } } else { /* * this target is no longer candidate */ retcode = META_SEARCH_NOT_CANDIDATE; goto doreturn; } break; case LDAP_SCOPE_SUBORDINATE: case LDAP_SCOPE_ONELEVEL: { struct berval rdn = mt->mt_nsuffix; rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," ); if ( dnIsOneLevelRDN( &rdn ) && dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) { /* * if there is exactly one level, * make the target suffix the new * base, and make scope "base" */ realbase = mt->mt_nsuffix; if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) { if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) { realscope = LDAP_SCOPE_SUBORDINATE; } else { realscope = LDAP_SCOPE_SUBTREE; } } else { realscope = LDAP_SCOPE_BASE; } break; } /* else continue with the next case */ } case LDAP_SCOPE_BASE: /* * this target is no longer candidate */ retcode = META_SEARCH_NOT_CANDIDATE; goto doreturn; } } /* check filter expression */ if ( mt->mt_filter ) { metafilter_t *mf; for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) { if ( regexec( &mf->mf_regex, op->ors_filterstr.bv_val, 0, NULL, 0 ) == 0 ) break; } /* nothing matched, this target is no longer a candidate */ if ( !mf ) { retcode = META_SEARCH_NOT_CANDIDATE; goto doreturn; } } /* * Rewrite the search base, if required */ dc.target = mt; dc.ctx = "searchBase"; dc.conn = op->o_conn; dc.rs = rs; switch ( asyncmeta_dn_massage( &dc, &realbase, &mbase ) ) { case LDAP_SUCCESS: break; case LDAP_UNWILLING_TO_PERFORM: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "Operation not allowed"; retcode = META_SEARCH_ERR; goto doreturn; default: /* * this target is no longer candidate */ retcode = META_SEARCH_NOT_CANDIDATE; goto doreturn; } /* * Maps filter */ rc = asyncmeta_filter_map_rewrite( &dc, op->ors_filter, &mfilter, BACKLDAP_MAP, NULL ); switch ( rc ) { case LDAP_SUCCESS: break; case LDAP_COMPARE_FALSE: default: /* * this target is no longer candidate */ retcode = META_SEARCH_NOT_CANDIDATE; goto done; } /* * Maps required attributes */ rc = asyncmeta_map_attrs( op, &mt->mt_rwmap.rwm_at, op->ors_attrs, BACKLDAP_MAP, &mapped_attrs ); if ( rc != LDAP_SUCCESS ) { /* * this target is no longer candidate */ retcode = META_SEARCH_NOT_CANDIDATE; goto done; } if ( op->ors_tlimit != SLAP_NO_LIMIT ) { timelimit = op->ors_tlimit > 0 ? op->ors_tlimit : 1; } else { timelimit = -1; /* no limit */ } #ifdef SLAPD_META_CLIENT_PR save_ctrls = op->o_ctrls; { LDAPControl *pr_c = NULL; int i = 0, nc = 0; if ( save_ctrls ) { for ( ; save_ctrls[i] != NULL; i++ ); nc = i; pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, save_ctrls, NULL ); } if ( pr_c != NULL ) nc--; if ( mt->mt_ps > 0 || prcookie != NULL ) nc++; if ( mt->mt_ps > 0 || prcookie != NULL || pr_c != NULL ) { int src = 0, dst = 0; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval val = BER_BVNULL; ber_len_t len; len = sizeof( LDAPControl * )*( nc + 1 ) + sizeof( LDAPControl ); if ( mt->mt_ps > 0 || prcookie != NULL ) { struct berval nullcookie = BER_BVNULL; ber_tag_t tag; if ( prsize == 0 && mt->mt_ps > 0 ) prsize = mt->mt_ps; if ( prcookie == NULL ) prcookie = &nullcookie; ber_init2( ber, NULL, LBER_USE_DER ); tag = ber_printf( ber, "{iO}", prsize, prcookie ); if ( tag == LBER_ERROR ) { /* error */ (void) ber_free_buf( ber ); goto done_pr; } tag = ber_flatten2( ber, &val, 0 ); if ( tag == LBER_ERROR ) { /* error */ (void) ber_free_buf( ber ); goto done_pr; } len += val.bv_len + 1; } op->o_ctrls = op->o_tmpalloc( len, op->o_tmpmemctx ); if ( save_ctrls ) { for ( ; save_ctrls[ src ] != NULL; src++ ) { if ( save_ctrls[ src ] != pr_c ) { op->o_ctrls[ dst ] = save_ctrls[ src ]; dst++; } } } if ( mt->mt_ps > 0 || prcookie != NULL ) { op->o_ctrls[ dst ] = (LDAPControl *)&op->o_ctrls[ nc + 1 ]; op->o_ctrls[ dst ]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; op->o_ctrls[ dst ]->ldctl_iscritical = 1; op->o_ctrls[ dst ]->ldctl_value.bv_val = (char *)&op->o_ctrls[ dst ][ 1 ]; AC_MEMCPY( op->o_ctrls[ dst ]->ldctl_value.bv_val, val.bv_val, val.bv_len + 1 ); op->o_ctrls[ dst ]->ldctl_value.bv_len = val.bv_len; dst++; (void)ber_free_buf( ber ); } op->o_ctrls[ dst ] = NULL; } done_pr:; } #endif /* SLAPD_META_CLIENT_PR */ retry:; asyncmeta_set_msc_time(msc); ctrls = op->o_ctrls; if (nretries == 0) { if (rc != LDAP_SUCCESS) { rs->sr_err = LDAP_BUSY; retcode = META_SEARCH_ERR; candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; goto done; } } if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS ) { candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_NOT_CANDIDATE; goto done; } /* * Starts the search */ ber = ldap_build_search_req( msc->msc_ld, mbase.bv_val, realscope, mfilter.bv_val, mapped_attrs, op->ors_attrsonly, ctrls, NULL, timelimit, op->ors_slimit, op->ors_deref, &msgid ); if (ber) { candidates[ candidate ].sr_msgid = msgid; rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_SEARCH, mbase.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); if (mc->mc_active < 1) { 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; } rs->sr_err = LDAP_UNAVAILABLE; retcode = META_SEARCH_ERR; break; default: candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_NOT_CANDIDATE; } } done:; (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); #ifdef SLAPD_META_CLIENT_PR if ( save_ctrls != op->o_ctrls ) { op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx ); op->o_ctrls = save_ctrls; } #endif /* SLAPD_META_CLIENT_PR */ if ( mapped_attrs ) { ber_memfree_x( mapped_attrs, op->o_tmpmemctx ); } if ( mfilter.bv_val != op->ors_filterstr.bv_val ) { ber_memfree_x( mfilter.bv_val, NULL ); } if ( mbase.bv_val != realbase.bv_val ) { free( mbase.bv_val ); } doreturn:; Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_search_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid ); return retcode; }