struct berval * slap_passwd_return( struct berval *cred ) { int rc; struct berval *bv = NULL; char berbuf[LBER_ELEMENT_SIZEOF]; /* opaque structure, size unknown but smaller than berbuf */ BerElement *ber = (BerElement *)berbuf; assert( cred != NULL ); #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "slap_passwd_return: %ld\n",(long)cred->bv_len, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n", (long) cred->bv_len, 0, 0 ); #endif ber_init_w_nullc( ber, LBER_USE_DER ); rc = ber_printf( ber, "{tON}", LDAP_TAG_EXOP_MODIFY_PASSWD_GEN, cred ); if( rc >= 0 ) { (void) ber_flatten( ber, &bv ); } ber_free_buf( ber ); return bv; }
Filter * str2filter_x( Operation *op, const char *str ) { int rc; Filter *f = NULL; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; const char *text = NULL; Debug( LDAP_DEBUG_FILTER, "str2filter \"%s\"\n", str, 0, 0 ); if ( str == NULL || *str == '\0' ) { return NULL; } ber_init2( ber, NULL, LBER_USE_DER ); if ( op->o_tmpmemctx ) { ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } rc = ldap_pvt_put_filter( ber, str ); if( rc < 0 ) { goto done; } ber_reset( ber, 1 ); rc = get_filter( op, ber, &f, &text ); done: ber_free_buf( ber ); return f; }
struct berval * slap_passwd_return( struct berval *cred ) { int rc; struct berval *bv = NULL; BerElementBuffer berbuf; /* opaque structure, size unknown but smaller than berbuf */ BerElement *ber = (BerElement *)&berbuf; assert( cred != NULL ); Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n", (long) cred->bv_len, 0, 0 ); ber_init_w_nullc( ber, LBER_USE_DER ); rc = ber_printf( ber, "{tON}", LDAP_TAG_EXOP_MODIFY_PASSWD_GEN, cred ); if( rc >= 0 ) { (void) ber_flatten( ber, &bv ); } ber_free_buf( ber ); return bv; }
static int dupent_response_done( Operation *op, SlapReply *rs ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; struct berval ctrlval; LDAPControl *ctrl, *ctrlsp[2]; ber_init2( ber, NULL, LBER_USE_DER ); /* DuplicateEntryResponseDone ::= SEQUENCE { resultCode, -- From [RFC2251] errorMessage [0] LDAPString OPTIONAL, attribute [1] AttributeDescription OPTIONAL } */ ber_printf( ber, "{i}", rs->sr_err ); if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) { ber_free_buf( ber ); if ( op->o_dupent == SLAP_CONTROL_CRITICAL ) { return LDAP_CONSTRAINT_VIOLATION; } return SLAP_CB_CONTINUE; } ctrl = op->o_tmpcalloc( 1, sizeof( LDAPControl ) + ctrlval.bv_len + 1, op->o_tmpmemctx ); ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ]; ctrl->ldctl_oid = LDAP_CONTROL_DUPENT_RESPONSE; ctrl->ldctl_iscritical = 0; ctrl->ldctl_value.bv_len = ctrlval.bv_len; AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0'; ber_free_buf( ber ); ctrlsp[0] = ctrl; ctrlsp[1] = NULL; slap_add_ctrls( op, rs, ctrlsp ); return SLAP_CB_CONTINUE; }
/* 4.2.2. Bind Response The Bind response is defined as follows. BindResponse ::= [APPLICATION 1] SEQUENCE { COMPONENTS OF LDAPResult, serverSaslCreds [7] OCTET STRING OPTIONAL } */ VOID VmDirSendSASLBindResponse( PVDIR_OPERATION pOperation ) { DWORD dwError = 0; BerElementBuffer berbuf; BerElement * ber = (BerElement *) &berbuf; PVDIR_LDAP_RESULT pResult = &(pOperation->ldapResult); ber_tag_t respType = GetResultTag(pOperation->reqCode); (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer )); ber_init2( ber, NULL, LBER_USE_DER ); VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "VmDirSendLdapResponse: code (%d), Error (%d)(%s)", respType, pResult->errCode, VDIR_SAFE_STRING(pResult->pszErrMsg)); dwError = ber_printf( ber, "{it{ess" /*"}}"*/, pOperation->msgId, // message sequence id GetResultTag(pOperation->reqCode), // ldap response type pResult->errCode, // ldap return code e.g. LDAP_SASL_CONNTINUE pResult->matchedDn.lberbv.bv_len > 0 ? pResult->matchedDn.lberbv.bv_val : "", VDIR_SAFE_STRING(pResult->pszErrMsg)); // error text detail BAIL_ON_LBER_ERROR(dwError); // Send back TAG and SASL reply blob // NOTE, not exactly sure if we ever need to send Tag but WITHOUT blob reply if blob is empty. // but this should NOT happen in GSSAPI scenario. if ( pResult->replyInfo.type == REP_SASL && pResult->replyInfo.replyData.bvSaslReply.lberbv.bv_len > 0 ) { dwError = ber_printf( ber, "tO", LDAP_TAG_SASL_RES_CREDS, &pResult->replyInfo.replyData.bvSaslReply.lberbv ); BAIL_ON_LBER_ERROR(dwError); } dwError = ber_printf( ber, "N}N}" ); BAIL_ON_LBER_ERROR(dwError); dwError = WriteBerOnSocket( pOperation->conn, ber ); BAIL_ON_VMDIR_ERROR(dwError); cleanup: ber_free_buf( ber ); return; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "lber error (%d)", dwError); goto cleanup; }
int WritePagedSearchDoneControl( VDIR_OPERATION * op, BerElement * ber ) { int retVal = LDAP_OPERATIONS_ERROR; BerElementBuffer ctrlValBerbuf; BerElement * ctrlValBer = (BerElement *) &ctrlValBerbuf; VDIR_BERVALUE bvCtrlVal = VDIR_BERVALUE_INIT; if (!op || !op->showPagedResultsCtrl) { retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } if ( op->showPagedResultsCtrl) { VDIR_PAGED_RESULT_CONTROL_VALUE* prCtrlVal = &op->showPagedResultsCtrl->value.pagedResultCtrlVal; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WritePagedSearchDoneControl: Paged Search Done Control Value: pageSize[%d] cookie[%s]", prCtrlVal->pageSize, prCtrlVal->cookie ); (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer )); ber_init2( ctrlValBer, NULL, LBER_USE_DER ); if (ber_printf( ctrlValBer, "{is}", 0, prCtrlVal->cookie) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Paged Search Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf; bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf; if (ber_printf(ber, "t{{sO}}", LDAP_TAG_CONTROLS, LDAP_CONTROL_PAGEDRESULTS, &bvCtrlVal.lberbv ) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WritePagedSearchDoneControl: ber_printf (to print Search Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } } retVal = LDAP_SUCCESS; cleanup: ber_free_buf( ctrlValBer ); return retVal; error: goto cleanup; }
static void send_paged_response( Operation *op, SlapReply *rs, ID *lastid, int tentries ) { LDAPControl *ctrls[2]; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; PagedResultsCookie respcookie; struct berval cookie; Debug(LDAP_DEBUG_ARGS, "send_paged_response: lastid=0x%08lx nentries=%d\n", lastid ? *lastid : 0, rs->sr_nentries, NULL ); ctrls[1] = NULL; ber_init2( ber, NULL, LBER_USE_DER ); if ( lastid ) { respcookie = ( PagedResultsCookie )(*lastid); cookie.bv_len = sizeof( respcookie ); cookie.bv_val = (char *)&respcookie; } else { respcookie = ( PagedResultsCookie )0; BER_BVSTR( &cookie, "" ); } op->o_conn->c_pagedresults_state.ps_cookie = respcookie; op->o_conn->c_pagedresults_state.ps_count = ((PagedResultsState *)op->o_pagedresults_state)->ps_count + rs->sr_nentries; /* return size of 0 -- no estimate */ ber_printf( ber, "{iO}", 0, &cookie ); ctrls[0] = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx ); if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) { goto done; } ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ctrls[0]->ldctl_iscritical = 0; slap_add_ctrls( op, rs, ctrls ); rs->sr_err = LDAP_SUCCESS; send_ldap_result( op, rs ); done: (void) ber_free_buf( ber ); }
void ber_free( BerElement *ber, int freebuf ) { if( ber == NULL ) { LDAP_MEMORY_DEBUG_ASSERT( ber != NULL ); return; } if( freebuf ) ber_free_buf( ber ); ber_memfree_x( (char *) ber, ber->ber_memctx ); }
static int pack_pagedresult_response_control( Operation *op, SlapReply *rs, sort_op *so, LDAPControl **ctrlsp ) { LDAPControl *ctrl; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; PagedResultsCookie resp_cookie; struct berval cookie, bv; int rc; ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); if ( so->so_nentries > 0 ) { resp_cookie = ( PagedResultsCookie )so->so_tree; cookie.bv_len = sizeof( PagedResultsCookie ); cookie.bv_val = (char *)&resp_cookie; } else { resp_cookie = ( PagedResultsCookie )0; BER_BVZERO( &cookie ); } op->o_conn->c_pagedresults_state.ps_cookie = resp_cookie; op->o_conn->c_pagedresults_state.ps_count = ((PagedResultsState *)op->o_pagedresults_state)->ps_count + rs->sr_nentries; rc = ber_printf( ber, "{iO}", so->so_nentries, &cookie ); if ( rc != -1 ) { rc = ber_flatten2( ber, &bv, 0 ); } if ( rc != -1 ) { ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+ bv.bv_len, op->o_tmpmemctx ); ctrl->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ctrl->ldctl_iscritical = 0; ctrl->ldctl_value.bv_val = (char *)(ctrl+1); ctrl->ldctl_value.bv_len = bv.bv_len; memcpy( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len ); ctrlsp[0] = ctrl; } else { ctrlsp[0] = NULL; rs->sr_err = LDAP_OTHER; } ber_free_buf( ber ); return rs->sr_err; }
/* Generates the LdapControl to be communicated to the client in the case of Strong Consistency Write task */ int WriteConsistencyWriteDoneControl( VDIR_OPERATION * pOp, BerElement * pBer ) { int retVal = LDAP_OPERATIONS_ERROR; BerElementBuffer ctrlValBerbuf; BerElement * pCtrlValBer = (BerElement *) &ctrlValBerbuf; VDIR_BERVALUE bvCtrlVal = VDIR_BERVALUE_INIT; DWORD dwStatus = 0; PSTR pControlsString = NULL; if (pOp == NULL || pBer == NULL) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: VDIR_OPERATION or BerElement is NULL failed"); BAIL_ON_VMDIR_ERROR(retVal); } (void) memset((char *)&ctrlValBerbuf, '\0', sizeof(BerElementBuffer)); ber_init2(pCtrlValBer, NULL, LBER_USE_DER); dwStatus = pOp->strongConsistencyWriteCtrl->value.scwDoneCtrlVal.status; pControlsString = pOp->strongConsistencyWriteCtrl->type; if (ber_printf(pCtrlValBer, "{i}", dwStatus) == -1) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: ber_printf (to print status...) failed"); BAIL_ON_VMDIR_ERROR(retVal); } bvCtrlVal.lberbv.bv_val = pCtrlValBer->ber_buf; bvCtrlVal.lberbv.bv_len = pCtrlValBer->ber_ptr - pCtrlValBer->ber_buf; if (ber_printf(pBer, "t{{sO}}", LDAP_TAG_CONTROLS, pControlsString, &bvCtrlVal.lberbv) == -1) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: ber_printf (to print ldapControl...) failed"); BAIL_ON_VMDIR_ERROR(retVal); } retVal = LDAP_SUCCESS; cleanup: ber_free_buf(pCtrlValBer); return retVal; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: failed"); goto cleanup; }
static int pack_vlv_response_control( Operation *op, SlapReply *rs, sort_op *so, LDAPControl **ctrlsp ) { LDAPControl *ctrl; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval cookie, bv; int rc; ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); rc = ber_printf( ber, "{iie", so->so_vlv_target, so->so_nentries, so->so_vlv_rc ); if ( rc != -1 && so->so_vcontext ) { cookie.bv_val = (char *)&so->so_vcontext; cookie.bv_len = sizeof(so->so_vcontext); rc = ber_printf( ber, "tO", LDAP_VLVCONTEXT_IDENTIFIER, &cookie ); } if ( rc != -1 ) { rc = ber_printf( ber, "}" ); } if ( rc != -1 ) { rc = ber_flatten2( ber, &bv, 0 ); } if ( rc != -1 ) { ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+ bv.bv_len, op->o_tmpmemctx ); ctrl->ldctl_oid = LDAP_CONTROL_VLVRESPONSE; ctrl->ldctl_iscritical = 0; ctrl->ldctl_value.bv_val = (char *)(ctrl+1); ctrl->ldctl_value.bv_len = bv.bv_len; memcpy( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len ); ctrlsp[0] = ctrl; } else { ctrlsp[0] = NULL; rs->sr_err = LDAP_OTHER; } ber_free_buf( ber ); return rs->sr_err; }
static int send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c ) { int rc; if( c == NULL ) return 0; rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ); if( rc == -1 ) return rc; for( ; *c != NULL; c++) { rc = send_ldap_control( ber, *c ); if( rc == -1 ) return rc; } #ifdef SLAP_CONTROL_X_SORTEDRESULTS /* this is a hack to avoid having to modify op->s_ctrls */ if( o->o_sortedresults ) { BerElementBuffer berbuf; BerElement *sber = (BerElement *) &berbuf; LDAPControl sorted; BER_BVZERO( &sorted.ldctl_value ); sorted.ldctl_oid = LDAP_CONTROL_SORTRESPONSE; sorted.ldctl_iscritical = 0; ber_init2( sber, NULL, LBER_USE_DER ); ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM ); if( ber_flatten2( sber, &sorted.ldctl_value, 0 ) == -1 ) { return -1; } (void) ber_free_buf( sber ); rc = send_ldap_control( ber, &sorted ); if( rc == -1 ) return rc; } #endif rc = ber_printf( ber, /*{*/"N}" ); return rc; }
static int pack_sss_response_control( Operation *op, SlapReply *rs, LDAPControl **ctrlsp ) { LDAPControl *ctrl; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval bv; int rc; ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); /* Pack error code */ rc = ber_printf(ber, "{e}", rs->sr_err); if ( rc != -1) rc = ber_flatten2( ber, &bv, 0 ); if ( rc != -1 ) { ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+ bv.bv_len, op->o_tmpmemctx ); ctrl->ldctl_oid = LDAP_CONTROL_SORTRESPONSE; ctrl->ldctl_iscritical = 0; ctrl->ldctl_value.bv_val = (char *)(ctrl+1); ctrl->ldctl_value.bv_len = bv.bv_len; memcpy( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len ); ctrlsp[0] = ctrl; } else { ctrlsp[0] = NULL; rs->sr_err = LDAP_OTHER; } ber_free_buf( ber ); return rs->sr_err; }
static int deref_response( Operation *op, SlapReply *rs ) { int rc = SLAP_CB_CONTINUE; if ( rs->sr_type == REP_SEARCH ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; deref_cb_t *dc = (deref_cb_t *)op->o_callback->sc_private; DerefSpec *ds; DerefRes *dr, *drhead = NULL, **drp = &drhead; struct berval bv = BER_BVNULL; int nDerefRes = 0, nDerefVals = 0, nAttrs = 0, nVals = 0; struct berval ctrlval; LDAPControl *ctrl, *ctrlsp[2]; AccessControlState acl_state = ACL_STATE_INIT; static char dummy = '\0'; Entry *ebase; int i; rc = overlay_entry_get_ov( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &ebase, dc->dc_on ); if ( rc != LDAP_SUCCESS || ebase == NULL ) { return SLAP_CB_CONTINUE; } for ( ds = dc->dc_ds; ds; ds = ds->ds_next ) { Attribute *a = attr_find( ebase->e_attrs, ds->ds_derefAttr ); if ( a != NULL ) { DerefVal *dv; BerVarray *bva; if ( !access_allowed( op, rs->sr_entry, a->a_desc, NULL, ACL_READ, &acl_state ) ) { continue; } dr = op->o_tmpcalloc( 1, sizeof( DerefRes ) + ( sizeof( DerefVal ) + sizeof( BerVarray * ) * ds->ds_nattrs ) * ( a->a_numvals + 1 ), op->o_tmpmemctx ); dr->dr_spec = *ds; dv = dr->dr_vals = (DerefVal *)&dr[ 1 ]; bva = (BerVarray *)&dv[ a->a_numvals + 1 ]; bv.bv_len += ds->ds_derefAttr->ad_cname.bv_len; nAttrs++; nDerefRes++; for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) { Entry *e = NULL; dv[ i ].dv_attrVals = bva; bva += ds->ds_nattrs; if ( !access_allowed( op, rs->sr_entry, a->a_desc, &a->a_nvals[ i ], ACL_READ, &acl_state ) ) { dv[ i ].dv_derefSpecVal.bv_val = &dummy; continue; } ber_dupbv_x( &dv[ i ].dv_derefSpecVal, &a->a_vals[ i ], op->o_tmpmemctx ); bv.bv_len += dv[ i ].dv_derefSpecVal.bv_len; nVals++; nDerefVals++; rc = overlay_entry_get_ov( op, &a->a_nvals[ i ], NULL, NULL, 0, &e, dc->dc_on ); if ( rc == LDAP_SUCCESS && e != NULL ) { int j; if ( access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_READ, NULL ) ) { for ( j = 0; j < ds->ds_nattrs; j++ ) { Attribute *aa; if ( !access_allowed( op, e, ds->ds_attributes[ j ], NULL, ACL_READ, &acl_state ) ) { continue; } aa = attr_find( e->e_attrs, ds->ds_attributes[ j ] ); if ( aa != NULL ) { unsigned k, h, last = aa->a_numvals; ber_bvarray_dup_x( &dv[ i ].dv_attrVals[ j ], aa->a_vals, op->o_tmpmemctx ); bv.bv_len += ds->ds_attributes[ j ]->ad_cname.bv_len; for ( k = 0, h = 0; k < aa->a_numvals; k++ ) { if ( !access_allowed( op, e, aa->a_desc, &aa->a_nvals[ k ], ACL_READ, &acl_state ) ) { op->o_tmpfree( dv[ i ].dv_attrVals[ j ][ h ].bv_val, op->o_tmpmemctx ); dv[ i ].dv_attrVals[ j ][ h ] = dv[ i ].dv_attrVals[ j ][ --last ]; BER_BVZERO( &dv[ i ].dv_attrVals[ j ][ last ] ); continue; } bv.bv_len += dv[ i ].dv_attrVals[ j ][ h ].bv_len; nVals++; h++; } nAttrs++; } } } overlay_entry_release_ov( op, e, 0, dc->dc_on ); } } *drp = dr; drp = &dr->dr_next; } } overlay_entry_release_ov( op, ebase, 0, dc->dc_on ); if ( drhead == NULL ) { return SLAP_CB_CONTINUE; } /* cook the control value */ bv.bv_len += nVals * sizeof(struct berval) + nAttrs * sizeof(struct berval) + nDerefVals * sizeof(DerefVal) + nDerefRes * sizeof(DerefRes); bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx ); ber_init2( ber, &bv, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); rc = ber_printf( ber, "{" /*}*/ ); for ( dr = drhead; dr != NULL; dr = dr->dr_next ) { for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) { int j, first = 1; if ( dr->dr_vals[ i ].dv_derefSpecVal.bv_val == &dummy ) { continue; } rc = ber_printf( ber, "{OO" /*}*/, &dr->dr_spec.ds_derefAttr->ad_cname, &dr->dr_vals[ i ].dv_derefSpecVal ); op->o_tmpfree( dr->dr_vals[ i ].dv_derefSpecVal.bv_val, op->o_tmpmemctx ); for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) { if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) { if ( first ) { rc = ber_printf( ber, "t{" /*}*/, (LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) ); first = 0; } rc = ber_printf( ber, "{O[W]}", &dr->dr_spec.ds_attributes[ j ]->ad_cname, dr->dr_vals[ i ].dv_attrVals[ j ] ); op->o_tmpfree( dr->dr_vals[ i ].dv_attrVals[ j ], op->o_tmpmemctx ); } } if ( !first ) { rc = ber_printf( ber, /*{{*/ "}N}" ); } else { rc = ber_printf( ber, /*{*/ "}" ); } } } rc = ber_printf( ber, /*{*/ "}" ); if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) { if ( op->o_deref == SLAP_CONTROL_CRITICAL ) { rc = LDAP_CONSTRAINT_VIOLATION; } else { rc = SLAP_CB_CONTINUE; } goto cleanup; } ctrl = op->o_tmpcalloc( 1, sizeof( LDAPControl ) + ctrlval.bv_len + 1, op->o_tmpmemctx ); ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ]; ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF; ctrl->ldctl_iscritical = 0; ctrl->ldctl_value.bv_len = ctrlval.bv_len; memcpy( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0'; ber_free_buf( ber ); ctrlsp[0] = ctrl; ctrlsp[1] = NULL; slap_add_ctrls( op, rs, ctrlsp ); rc = SLAP_CB_CONTINUE; cleanup:; /* release all */ for ( ; drhead != NULL; ) { DerefRes *drnext = drhead->dr_next; op->o_tmpfree( drhead, op->o_tmpmemctx ); drhead = drnext; } } else if ( rs->sr_type == REP_RESULT ) { rc = deref_cleanup( op, rs ); } return rc; }
static int dds_op_extended( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = on->on_bi.bi_private; if ( DDS_OFF( di ) ) { return SLAP_CB_CONTINUE; } if ( bvmatch( &op->ore_reqoid, &slap_EXOP_REFRESH ) ) { Entry *e = NULL; time_t ttl; BackendDB db = *op->o_bd; SlapReply rs2 = { REP_RESULT }; Operation op2 = *op; slap_callback sc = { 0 }; Modifications ttlmod = { { 0 } }; struct berval ttlvalues[ 2 ]; char ttlbuf[STRLENOF("31557600") + 1]; rs->sr_err = slap_parse_refresh( op->ore_reqdata, NULL, &ttl, &rs->sr_text, NULL ); assert( rs->sr_err == LDAP_SUCCESS ); if ( ttl <= 0 || ttl > DDS_RF2589_MAX_TTL ) { rs->sr_err = LDAP_PROTOCOL_ERROR; rs->sr_text = "invalid time-to-live for dynamicObject"; return rs->sr_err; } if ( ttl > di->di_max_ttl ) { /* FIXME: I don't understand if this has to be an error, * or an indication that the requested Ttl has been * shortened to di->di_max_ttl >= 1 day */ rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; rs->sr_text = "time-to-live for dynamicObject exceeds limit"; return rs->sr_err; } if ( di->di_min_ttl && ttl < di->di_min_ttl ) { ttl = di->di_min_ttl; } /* This does not apply to multi-master case */ if ( !( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ) ) ) { /* we SHOULD return a referral in this case */ BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if ( defref != NULL ) { rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs, NULL, NULL, LDAP_SCOPE_DEFAULT ); if ( rs->sr_ref ) { rs->sr_flags |= REP_REF_MUSTBEFREED; } else { rs->sr_ref = defref; } rs->sr_err = LDAP_REFERRAL; } else { rs->sr_text = "shadow context; no update referral"; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; } return rs->sr_err; } assert( !BER_BVISNULL( &op->o_req_ndn ) ); /* check if exists but not dynamicObject */ op->o_bd->bd_info = (BackendInfo *)on->on_info; rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) { /* return referral only if "disclose" * is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; rs->sr_text = "refresh operation only applies to dynamic objects"; } be_entry_release_r( op, e ); } else { rs->sr_err = LDAP_NO_SUCH_OBJECT; } return rs->sr_err; } else if ( e != NULL ) { be_entry_release_r( op, e ); } /* we require manage privileges on the entryTtl, * and fake a Relax control */ op2.o_tag = LDAP_REQ_MODIFY; op2.o_bd = &db; db.bd_info = (BackendInfo *)on->on_info; op2.o_callback = ≻ sc.sc_response = slap_null_cb; op2.o_relax = SLAP_CONTROL_CRITICAL; op2.orm_modlist = &ttlmod; ttlmod.sml_op = LDAP_MOD_REPLACE; ttlmod.sml_flags = SLAP_MOD_MANAGING; ttlmod.sml_desc = slap_schema.si_ad_entryTtl; ttlmod.sml_values = ttlvalues; ttlmod.sml_numvals = 1; ttlvalues[ 0 ].bv_val = ttlbuf; ttlvalues[ 0 ].bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl ); BER_BVZERO( &ttlvalues[ 1 ] ); /* the entryExpireTimestamp is added by modify */ rs->sr_err = slap_biglock_call_be( op_modify, &op2, &rs2 ); if ( ttlmod.sml_next != NULL ) { slap_mods_free( ttlmod.sml_next, 1 ); } if ( rs->sr_err == LDAP_SUCCESS ) { int rc; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_init_w_nullc( ber, LBER_USE_DER ); rc = ber_printf( ber, "{tiN}", LDAP_TAG_EXOP_REFRESH_RES_TTL, (int)ttl ); if ( rc < 0 ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; } else { (void)ber_flatten( ber, &rs->sr_rspdata ); rs->sr_rspoid = ch_strdup( slap_EXOP_REFRESH.bv_val ); Log3( LDAP_DEBUG_TRACE, LDAP_LEVEL_INFO, "%s REFRESH dn=\"%s\" TTL=%ld\n", op->o_log_prefix, op->o_req_ndn.bv_val, ttl ); } ber_free_buf( ber ); } return rs->sr_err; } return SLAP_CB_CONTINUE; }
int VmDirSendSearchEntry( PVDIR_OPERATION pOperation, PVDIR_ENTRY pSrEntry ) { int retVal = LDAP_SUCCESS; BerElementBuffer berbuf; BerElement * ber = (BerElement *) &berbuf; BOOLEAN bFreeBer = FALSE; ber_len_t iBlobSize = 0; BerValue lberBervEntryBlob = {0}; int nAttrs = 0; int nVals = 0; BOOLEAN attrMetaDataReqd = FALSE; SearchReq * sr = &(pOperation->request.searchReq); int i = 0; BOOLEAN nonTrivialAttrsInReplScope = FALSE; uint32_t iSearchReqSpecialChars = 0; PATTRIBUTE_META_DATA_NODE pAttrMetaData = NULL; int numAttrMetaData = 0; PVDIR_ATTRIBUTE pAttr = NULL; USN usnChanged = 0; PSTR pszLocalErrorMsg = NULL; if ( !pOperation || !pSrEntry ) { retVal = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(retVal); } pSrEntry->bSearchEntrySent = FALSE; // see if client request has "*" and/or "+" ("-" for userpassword internal to vmdir) // WEI TODO: when we have attribute level ACL check, this information will be useful // return result will depend on ACL each on each attribute client is asking before // generating a final result to send back SetSpecialReturnChar(&pOperation->request.searchReq, &iSearchReqSpecialChars); if ( pSrEntry->eId == DSE_ROOT_ENTRY_ID && pOperation->request.searchReq.attrs == NULL ) { // For ADSI, if no specific attributes requested of DSE ROOT search, // return ALL (include operational) attributes. iSearchReqSpecialChars |= LDAP_SEARCH_REQUEST_CHAR_OP; } // ACL check before processing/sending the current srEntry back retVal = VmDirSrvAccessCheck( pOperation, &pOperation->conn->AccessInfo, pSrEntry, VMDIR_RIGHT_DS_READ_PROP ); BAIL_ON_VMDIR_ERROR( retVal ); if ( pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL ) { ; // no op in INTERNAL case } else { // If not replication, and showDeletedObjectsCtrl not present, => don't send back Deleted objects (tombstones). if (pOperation->syncReqCtrl == NULL && pOperation->showDeletedObjectsCtrl == NULL) { pAttr = VmDirEntryFindAttribute(ATTR_IS_DELETED, pSrEntry); if (pAttr) { if (VmDirStringCompareA((PSTR)pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE) == 0) { goto cleanup; // Don't send this entry } } } // In case of replication request, skip certain updates if (pOperation->syncReqCtrl != NULL) { PVDIR_ATTRIBUTE pAttrUsnCreated = NULL; USN usnCreated = 0; USN limitUsn = 0; VMDIR_REPLICATION_AGREEMENT * replAgr = NULL; pAttr = VmDirEntryFindAttribute(ATTR_USN_CHANGED, pSrEntry); assert( pAttr != NULL ); usnChanged = VmDirStringToLA( pAttr->vals[0].lberbv.bv_val, NULL, 10); // Check if usnChanged is beyond successful replication update state limitUsn = VmDirdGetLimitLocalUsnToBeSupplied(); if (limitUsn != 0 && usnChanged >= limitUsn) { VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "SendSearchEntry: bug# 863244 RACE CONDITION encountered., " "usnChanged = %ld, limitLocalUsnToBeSupplied = %ld, skipping entry: %s", usnChanged, limitUsn, pSrEntry->dn.lberbv.bv_val ); goto cleanup; // Don't send this entry } // Check if usnChanged is beyond lowestPendingUncommittedUsn recorded at the beginning of replication search if (pOperation->lowestPendingUncommittedUsn != 0 && usnChanged >= pOperation->lowestPendingUncommittedUsn) { VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: usnChanged = %ld, lowestPendingUncommittedUsn = %ld, " "skipping entry: %s", usnChanged, pOperation->lowestPendingUncommittedUsn, pSrEntry->dn.lberbv.bv_val ); goto cleanup; // Don't send this entry } // Don't send (skip) modifications to my server object, and my RAs pAttrUsnCreated = VmDirEntryFindAttribute(ATTR_USN_CREATED, pSrEntry); assert( pAttrUsnCreated != NULL ); usnCreated = VmDirStringToLA( pAttrUsnCreated->vals[0].lberbv.bv_val, NULL, 10); // Only send back creation of certain objects, and not their modifications. // Check if consumer has already seen the creation. If yes, we are dealing with mods, which should be skipped // for my server object, and my RAs // Note: Skipping mods for RAs and Server Objects will cause inconsistencies with replicas. But these // two types only have local scope regarding functional effects. But if we are looking up / processing // information for these two types of objects on a replica, we need to watch out for potential // inconsistencies against the original source. if (pOperation->syncReqCtrl->value.syncReqCtrlVal.intLastLocalUsnProcessed > usnCreated) { if (strcmp(pSrEntry->dn.bvnorm_val, gVmdirServerGlobals.serverObjDN.bvnorm_val) == 0) { VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my server object, DN: %s", gVmdirServerGlobals.serverObjDN.lberbv.bv_val ); goto cleanup; // Don't send this entry } for (replAgr = gVmdirReplAgrs; replAgr != NULL; replAgr = replAgr->next ) { if (strcmp(pSrEntry->dn.bvnorm_val, replAgr->dn.bvnorm_val) == 0) { VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my RA object, DN: %s", replAgr->dn.bvnorm_val ); goto cleanup; // Don't send this entry } } } // do not replicate DSE Root entry, because it is a "local" entry. if (pSrEntry->eId == DSE_ROOT_ENTRY_ID) { VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to DSE Root entry, DN: %s", pSrEntry->dn.bvnorm_val ); goto cleanup; // Don't send this entry } } // Approximate calculation for the required ber size, because apart from lengths and strings, ber also includes // tags. if ( VmDirComputeEncodedEntrySize(pSrEntry, &nAttrs, &nVals, &iBlobSize) != 0 || VmDirAllocateMemory(iBlobSize, (PVOID*)&lberBervEntryBlob.bv_val) != 0 ) { retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "no memory"); } lberBervEntryBlob.bv_len = iBlobSize; ber_init2( ber, &lberBervEntryBlob, LBER_USE_DER ); // ber takes over lberBervEntryBlob.lberbv.bv_val ownership bFreeBer = TRUE; if ( ber_printf( ber, "{it{O{", pOperation->msgId, LDAP_RES_SEARCH_ENTRY, &pSrEntry->dn ) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: ber_printf (to print msgId ...) failed" ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding msgId, RES_SEARCH_ENTRY, DN failed"); } // Determine if we need to send back the attribute metaData if ( pOperation->syncReqCtrl != NULL ) // Replication { attrMetaDataReqd = TRUE; } else // check if attrMetaData attribute has been requested explicitly. { if (sr->attrs != NULL) { for (i = 0; sr->attrs[i].lberbv.bv_val != NULL; i++) { if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, ATTR_ATTR_META_DATA, FALSE) == 0) { attrMetaDataReqd = TRUE; break; } } } } if (attrMetaDataReqd) { if ((pOperation->pBEIF->pfnBEGetAllAttrsMetaData( pOperation->pBECtx, pSrEntry->eId, &pAttrMetaData, &numAttrMetaData )) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: pfnBEGetAllAttrsMetaData failed for entryId: %ld", pSrEntry->eId); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "pfnBEGetAllAttrsMetaData failed."); } // SJ-TBD: Following double for loop to be optimized // Copy attrMetaData to corresponding attributes for (i=0; i<numAttrMetaData; i++) { for ( pAttr = pSrEntry->attrs; pAttr != NULL; pAttr = pAttr->next) { if (pAttr->pATDesc->usAttrID == pAttrMetaData[i].attrID) { VmDirStringCpyA( pAttr->metaData, VMDIR_MAX_ATTR_META_DATA_LEN, pAttrMetaData[i].metaData ); pAttrMetaData[i].metaData[0] = '\0'; } } } } retVal = WriteAttributes( pOperation, pSrEntry, iSearchReqSpecialChars , ber, &pszLocalErrorMsg ); BAIL_ON_VMDIR_ERROR( retVal ); if (attrMetaDataReqd) { retVal = WriteMetaDataAttribute( pOperation, pSrEntry->attrs, numAttrMetaData, pAttrMetaData, ber, &nonTrivialAttrsInReplScope, &pszLocalErrorMsg ); BAIL_ON_VMDIR_ERROR( retVal ); } if (ber_printf( ber, "N}N}" ) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ber_printf (to terminate the entry and the complete search result entry message ...) failed" ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding terminating the entry failed."); } if ( pOperation->syncReqCtrl != NULL ) // Replication, => write Sync State Control { retVal = WriteSyncStateControl( pOperation, pSrEntry->attrs, ber, &pszLocalErrorMsg ); BAIL_ON_VMDIR_ERROR( retVal ); } if (ber_printf( ber, "N}" ) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );; retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding terminating the entry failed."); } if ((pOperation->syncReqCtrl == NULL) || (pOperation->syncReqCtrl != NULL && nonTrivialAttrsInReplScope )) { if (WriteBerOnSocket( pOperation->conn, ber ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: WriteBerOnSocket failed." ); retVal = LDAP_UNAVAILABLE; BAIL_ON_VMDIR_ERROR( retVal ); } pSrEntry->bSearchEntrySent = TRUE; sr->iNumEntrySent++; VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Send entry: %s", pSrEntry->dn.lberbv.bv_val); } else { VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: NOT Sending entry: %s %p %d", pSrEntry->dn.lberbv.bv_val, pOperation->syncReqCtrl, nonTrivialAttrsInReplScope); } // record max local usnChanged in syncControlDone if (pOperation->syncReqCtrl != NULL) { if (usnChanged > pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed) { pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed = usnChanged; } } retVal = LDAP_SUCCESS; } cleanup: if (bFreeBer) { ber_free_buf( ber ); } VMDIR_SAFE_FREE_MEMORY( pAttrMetaData ); VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return( retVal ); error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry failed DN=(%s), (%u)(%s)", (pSrEntry && pSrEntry->dn.lberbv.bv_val) ? pSrEntry->dn.lberbv.bv_val : "", retVal, VDIR_SAFE_STRING( pszLocalErrorMsg)); if ( !pOperation->ldapResult.pszErrMsg && pszLocalErrorMsg ) { pOperation->ldapResult.pszErrMsg = pszLocalErrorMsg; pszLocalErrorMsg = NULL; } goto cleanup; }
void VmDirSendLdapResult( VDIR_OPERATION * op ) { BerElementBuffer berbuf; BerElement * ber = (BerElement *) &berbuf; ber_int_t msgId = 0; ber_tag_t resCode = 0; size_t iNumSearchEntrySent = 0; PCSTR pszSocketInfo = NULL; (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer )); resCode = GetResultTag( op->reqCode ); msgId = (resCode != LBER_SEQUENCE) ? op->msgId : 0; if ( resCode == LDAP_RES_SEARCH_RESULT ) { iNumSearchEntrySent = op->request.searchReq.iNumEntrySent; } ber_init2( ber, NULL, LBER_USE_DER ); if (op->conn) { pszSocketInfo = op->conn->szClientIP; } if (op->ldapResult.errCode && op->ldapResult.errCode != LDAP_SASL_BIND_IN_PROGRESS) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)", op->reqCode, op->ldapResult.errCode, VDIR_SAFE_STRING(op->ldapResult.pszErrMsg), iNumSearchEntrySent, VDIR_SAFE_STRING(pszSocketInfo)); } else if ( op->reqCode == LDAP_REQ_SEARCH ) { VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)", op->reqCode, op->ldapResult.errCode, VDIR_SAFE_STRING(op->ldapResult.pszErrMsg), iNumSearchEntrySent, VDIR_SAFE_STRING(pszSocketInfo)); } if (ber_printf( ber, "{it{essN}", msgId, resCode, op->ldapResult.errCode, "", VDIR_SAFE_STRING(op->ldapResult.pszErrMsg)) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" ); goto done; } // If Search, Replication, and one or more entries were sent back => Send back Sync Done Control if ( op->reqCode == LDAP_REQ_SEARCH && op->syncReqCtrl != NULL && op->syncDoneCtrl != NULL) { if (WriteSyncDoneControl( op, ber ) != LDAP_SUCCESS) { goto done; } } if ( op->reqCode == LDAP_REQ_SEARCH && op->showPagedResultsCtrl != NULL) { if (WritePagedSearchDoneControl( op, ber ) != LDAP_SUCCESS) { goto done; } } if (ber_printf( ber, "N}" ) == -1) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" ); goto done; } if (WriteBerOnSocket( op->conn, ber ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: WriteBerOnSocket failed" ); goto done; } done: ber_free_buf( ber ); }
int WriteSyncStateControl( VDIR_OPERATION * op, VDIR_ATTRIBUTE * pAttr, BerElement * ber, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; VDIR_BERVALUE syncStateCtrlType = { {VmDirStringLenA( LDAP_CONTROL_SYNC_STATE ), LDAP_CONTROL_SYNC_STATE}, 0, 0, NULL }; int entryState = LDAP_SYNC_MODIFY; BerElementBuffer ctrlValBerbuf; BerElement * ctrlValBer = (BerElement *) &ctrlValBerbuf; VDIR_BERVALUE bvCtrlVal = VDIR_BERVALUE_INIT; PSTR pszLocalErrorMsg = NULL; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: Begin" ); /* Logic to determine the entry state is: * Default entry state is LDAP_SYNC_MODIFY * * If ATTR_USN_CREATED value is greater than the last local USN that the consumer has seen so far, * entry state is LDAP_SYNC_ADD. * Otherwise, if isDeleted=TRUE is in the replication scope, entry state is LDAP_SYNC_DELETE. * * NOTE: The logic is based on the things (entry state + what has the consumer seen so far) seen by the supplier * at this point in time. Things/state could be different at the time when consumer tries to apply this change. * => may lead to various conflict resolution scenarios. */ for ( ; pAttr != NULL; pAttr = pAttr->next) { if (pAttr->metaData[0] != '\0') // We are sending back this attribute's meta data. => Attribute is in // replication scope. SJ-TBD: we are overloading pAttr->metaData // field. Should we have another field (e.g. inReplScope) in Attribute { if ( VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_IS_DELETED, FALSE ) == 0 && VmDirStringCompareA( pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE ) == 0) { entryState = LDAP_SYNC_DELETE; continue; // Look if it is LDAP_SYNC_ADD case } if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CREATED, FALSE ) == 0) { entryState = LDAP_SYNC_ADD; break; } } } if (ber_printf( ber, "t{{O", LDAP_TAG_CONTROLS, &(syncStateCtrlType.lberbv) ) == -1 ) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteSyncStateControl: ber_printf (to print attribute name ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } ////////// Build ber for the control value (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer )); ber_init2( ctrlValBer, NULL, LBER_USE_DER ); if (ber_printf( ctrlValBer, "{i}", entryState ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } ////////////// Building ber for the control value done bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf; bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf; if (ber_printf( ber, "O", &bvCtrlVal.lberbv ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } if (ber_printf( ber, "}}" ) == -1 ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg), "Encoding sync state control failed."); } cleanup: ber_free_buf( ctrlValBer ); if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: End" ); return( retVal ); error: goto cleanup; }
static int null_back_respond( Operation *op, SlapReply *rs, int rc ) { LDAPControl ctrl[SLAP_MAX_RESPONSE_CONTROLS], *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int c = 0; BerElementBuffer ps_berbuf; BerElement *ps_ber = NULL; LDAPControl **preread_ctrl = NULL, **postread_ctrl = NULL; rs->sr_err = LDAP_OTHER; /* this comes first, as in case of assertion failure * any further processing must stop */ if ( get_assert( op ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; goto respond; } if ( op->o_preread ) { Entry e = { 0 }; switch ( op->o_tag ) { case LDAP_REQ_MODIFY: case LDAP_REQ_RENAME: case LDAP_REQ_DELETE: e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; preread_ctrl = &ctrls[c]; *preread_ctrl = NULL; if ( slap_read_controls( op, rs, &e, &slap_pre_read_bv, preread_ctrl ) ) { preread_ctrl = NULL; Debug( LDAP_DEBUG_TRACE, "<=- null_back_respond: pre-read " "failed!\n", 0, 0, 0 ); if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto respond; } } else { c++; } break; } } if ( op->o_postread ) { Entry e = { 0 }; switch ( op->o_tag ) { case LDAP_REQ_ADD: case LDAP_REQ_MODIFY: case LDAP_REQ_RENAME: if ( op->o_tag == LDAP_REQ_ADD ) { e.e_name = op->ora_e->e_name; e.e_nname = op->ora_e->e_nname; } else { e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; } postread_ctrl = &ctrls[c]; *postread_ctrl = NULL; if ( slap_read_controls( op, rs, &e, &slap_post_read_bv, postread_ctrl ) ) { postread_ctrl = NULL; Debug( LDAP_DEBUG_TRACE, "<=- null_back_respond: post-read " "failed!\n", 0, 0, 0 ); if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto respond; } } else { c++; } break; } } if ( op->o_noop ) { switch ( op->o_tag ) { case LDAP_REQ_ADD: case LDAP_REQ_MODIFY: case LDAP_REQ_RENAME: case LDAP_REQ_DELETE: case LDAP_REQ_EXTENDED: rc = LDAP_X_NO_OPERATION; break; } } if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { struct berval cookie = BER_BVC( "" ); /* should not be here... */ assert( op->o_tag == LDAP_REQ_SEARCH ); ctrl[c].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ctrl[c].ldctl_iscritical = 0; ps_ber = (BerElement *)&ps_berbuf; ber_init2( ps_ber, NULL, LBER_USE_DER ); /* return size of 0 -- no estimate */ ber_printf( ps_ber, "{iO}", 0, &cookie ); if ( ber_flatten2( ps_ber, &ctrl[c].ldctl_value, 0 ) == -1 ) { goto done; } ctrls[c] = &ctrl[c]; c++; } /* terminate controls array */ ctrls[c] = NULL; rs->sr_ctrls = ctrls; rs->sr_err = rc; respond:; send_ldap_result( op, rs ); rs->sr_ctrls = NULL; done:; if ( ps_ber != NULL ) { (void) ber_free_buf( ps_ber ); } if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } return rs->sr_err; }
int slap_send_search_entry( Operation *op, SlapReply *rs ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; Attribute *a; int i, j, rc = LDAP_UNAVAILABLE, bytes; int userattrs; AccessControlState acl_state = ACL_STATE_INIT; int attrsonly; AttributeDescription *ad_entry = slap_schema.si_ad_entry; /* a_flags: array of flags telling if the i-th element will be * returned or filtered out * e_flags: array of a_flags */ char **e_flags = NULL; rs->sr_type = REP_SEARCH; if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) { rc = LDAP_SIZELIMIT_EXCEEDED; goto error_return; } /* Every 64 entries, check for thread pool pause */ if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) && ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 ) { rc = LDAP_BUSY; goto error_return; } /* eventually will loop through generated operational attribute types * currently implemented types include: * entryDN, subschemaSubentry, and hasSubordinates */ /* NOTE: moved before overlays callback circling because * they may modify entry and other stuff in rs */ /* check for special all operational attributes ("+") type */ /* FIXME: maybe we could set this flag at the operation level; * however, in principle the caller of send_search_entry() may * change the attribute list at each call */ rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs ); rc = backend_operational( op, rs ); if ( rc ) { goto error_return; } if ( op->o_callback ) { rc = slap_response_play( op, rs ); if ( rc != SLAP_CB_CONTINUE ) { goto error_return; } } Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: conn %lu dn=\"%s\"%s\n", op->o_connid, rs->sr_entry->e_name.bv_val, op->ors_attrsonly ? " (attrsOnly)" : "" ); attrsonly = op->ors_attrsonly; if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu access to entry (%s) not allowed\n", op->o_connid, rs->sr_entry->e_name.bv_val ); rc = LDAP_INSUFFICIENT_ACCESS; goto error_return; } if ( op->o_res_ber ) { /* read back control or LDAP_CONNECTIONLESS */ ber = op->o_res_ber; } else { struct berval bv; bv.bv_len = entry_flatsize( rs->sr_entry, 0 ); bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx ); ber_init2( ber, &bv, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } #ifdef LDAP_CONNECTIONLESS if ( op->o_conn && op->o_conn->c_is_udp ) { /* CONNECTIONLESS */ if ( op->o_protocol == LDAP_VERSION2 ) { rc = ber_printf(ber, "t{O{" /*}}*/, LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } else { rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } } else #endif if ( op->o_res_ber ) { /* read back control */ rc = ber_printf( ber, "t{O{" /*}}*/, LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } else { rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encoding DN error" ); rc = rs->sr_err; goto error_return; } /* check for special all user attributes ("*") type */ userattrs = SLAP_USERATTRS( rs->sr_attr_flags ); /* create an array of arrays of flags. Each flag corresponds * to particular value of attribute and equals 1 if value matches * to ValuesReturnFilter or 0 if not */ if ( op->o_vrFilter != NULL ) { int k = 0; size_t size; for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) { for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++; } size = i * sizeof(char *) + k; if ( size > 0 ) { char *a_flags; e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx ); if( e_flags == NULL ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu slap_sl_calloc failed\n", op->o_connid ); ber_free( ber, 1 ); set_ldap_error( rs, LDAP_OTHER, "out of memory" ); goto error_return; } a_flags = (char *)(e_flags + i); memset( a_flags, 0, k ); for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) { for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); e_flags[i] = a_flags; a_flags += j; } rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: " "conn %lu matched values filtering failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "matched values filtering error" ); rc = rs->sr_err; goto error_return; } } } for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) { AttributeDescription *desc = a->a_desc; int finish = 0; if ( rs->sr_attrs == NULL ) { /* all user attrs request, skip operational attributes */ if( is_at_operational( desc->ad_type ) ) { continue; } } else { /* specific attrs requested */ if ( is_at_operational( desc->ad_type ) ) { /* if not explicitly requested */ if ( !ad_inlist( desc, rs->sr_attrs )) { /* if not all op attrs requested, skip */ if ( !SLAP_OPATTRS( rs->sr_attr_flags )) continue; /* if DSA-specific and replicating, skip */ if ( op->o_sync != SLAP_CONTROL_NONE && desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION ) continue; } } else { if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } } } if ( attrsonly ) { if ( ! access_allowed( op, rs->sr_entry, desc, NULL, ACL_READ, &acl_state ) ) { Debug( LDAP_DEBUG_ACL, "send_search_entry: " "conn %lu access to attribute %s not allowed\n", op->o_connid, desc->ad_cname.bv_val ); continue; } if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encoding description error"); rc = rs->sr_err; goto error_return; } finish = 1; } else { int first = 1; for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) { if ( ! access_allowed( op, rs->sr_entry, desc, &a->a_nvals[i], ACL_READ, &acl_state ) ) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu " "access to attribute %s, value #%d not allowed\n", op->o_connid, desc->ad_cname.bv_val, i ); continue; } if ( op->o_vrFilter && e_flags[j][i] == 0 ){ continue; } if ( first ) { first = 0; finish = 1; if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encoding description error"); rc = rs->sr_err; goto error_return; } } if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu " "ber_printf failed.\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encoding values error" ); rc = rs->sr_err; goto error_return; } } } if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encode end error" ); rc = rs->sr_err; goto error_return; } } /* NOTE: moved before overlays callback circling because * they may modify entry and other stuff in rs */ if ( rs->sr_operational_attrs != NULL && op->o_vrFilter != NULL ) { int k = 0; size_t size; for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) { for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++; } size = i * sizeof(char *) + k; if ( size > 0 ) { char *a_flags, **tmp; /* * Reuse previous memory - we likely need less space * for operational attributes */ tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k, op->o_tmpmemctx ); if ( tmp == NULL ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu " "not enough memory " "for matched values filtering\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "not enough memory for matched values filtering" ); goto error_return; } e_flags = tmp; a_flags = (char *)(e_flags + i); memset( a_flags, 0, k ); for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) { for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); e_flags[i] = a_flags; a_flags += j; } rc = filter_matched_values(op, rs->sr_operational_attrs, &e_flags) ; if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu " "matched values filtering failed\n", op->o_connid); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "matched values filtering error" ); rc = rs->sr_err; goto error_return; } } } for (a = rs->sr_operational_attrs, j=0; a != NULL; a = a->a_next, j++ ) { AttributeDescription *desc = a->a_desc; if ( rs->sr_attrs == NULL ) { /* all user attrs request, skip operational attributes */ if( is_at_operational( desc->ad_type ) ) { continue; } } else { /* specific attrs requested */ if( is_at_operational( desc->ad_type ) ) { if ( !SLAP_OPATTRS( rs->sr_attr_flags ) && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } /* if DSA-specific and replicating, skip */ if ( op->o_sync != SLAP_CONTROL_NONE && desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION ) continue; } else { if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } } } if ( ! access_allowed( op, rs->sr_entry, desc, NULL, ACL_READ, &acl_state ) ) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu " "access to attribute %s not allowed\n", op->o_connid, desc->ad_cname.bv_val ); continue; } rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname ); if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu " "ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encoding description error" ); rc = rs->sr_err; goto error_return; } if ( ! attrsonly ) { for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { if ( ! access_allowed( op, rs->sr_entry, desc, &a->a_vals[i], ACL_READ, &acl_state ) ) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu " "access to %s, value %d not allowed\n", op->o_connid, desc->ad_cname.bv_val, i ); continue; } if ( op->o_vrFilter && e_flags[j][i] == 0 ){ continue; } if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encoding values error" ); rc = rs->sr_err; goto error_return; } } } if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber_printf failed\n", op->o_connid ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encode end error" ); rc = rs->sr_err; goto error_return; } } /* free e_flags */ if ( e_flags ) { slap_sl_free( e_flags, op->o_tmpmemctx ); e_flags = NULL; } rc = ber_printf( ber, /*{{*/ "}N}" ); if( rc != -1 ) { rc = send_ldap_controls( op, ber, rs->sr_ctrls ); } if( rc != -1 ) { #ifdef LDAP_CONNECTIONLESS if( op->o_conn && op->o_conn->c_is_udp ) { if ( op->o_protocol != LDAP_VERSION2 ) { rc = ber_printf( ber, /*{*/ "N}" ); } } else #endif if ( op->o_res_ber == NULL ) { rc = ber_printf( ber, /*{*/ "N}" ); } } if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "ber_printf failed\n" ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encode entry end error" ); rc = rs->sr_err; goto error_return; } Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n", op->o_log_prefix, rs->sr_entry->e_nname.bv_val ); rs_flush_entry( op, rs, NULL ); if ( op->o_res_ber == NULL ) { bytes = send_ldap_ber( op, ber ); ber_free_buf( ber ); if ( bytes < 0 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu ber write failed.\n", op->o_connid ); rc = LDAP_UNAVAILABLE; goto error_return; } rs->sr_nentries++; ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 ); ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); } Debug( LDAP_DEBUG_TRACE, "<= send_search_entry: conn %lu exit.\n", op->o_connid ); rc = LDAP_SUCCESS; error_return:; if ( op->o_callback ) { (void)slap_cleanup_play( op, rs ); } if ( e_flags ) { slap_sl_free( e_flags, op->o_tmpmemctx ); } /* FIXME: Can break if rs now contains an extended response */ if ( rs->sr_operational_attrs ) { attrs_free( rs->sr_operational_attrs ); rs->sr_operational_attrs = NULL; } rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED; if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) { rs_flush_entry( op, rs, NULL ); } else { RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); } if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ if ( rs->sr_ctrls ) { slap_free_ctrls( op, rs->sr_ctrls ); rs->sr_ctrls = NULL; } } return( rc ); }
void VmDirSendLdapReferralResult( VDIR_OPERATION * op, PCSTR pszRefSuffix, PBOOLEAN pbRefSent ) { DWORD dwError = 0; BerElementBuffer berbuf; BerElement * ber = (BerElement *) &berbuf; ber_int_t msgId = 0; PCSTR pszSocketInfo = NULL; PSTR pszLeader = NULL; PSTR pszRef = NULL; PVDIR_BERVALUE pBerv = NULL; BOOLEAN bIsLdaps = FALSE; *pbRefSent = FALSE; (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer )); msgId = op->msgId; ber_init2( ber, NULL, LBER_USE_DER ); if (op->conn) { pszSocketInfo = op->conn->szClientIP; } dwError = VmDirRaftGetLeader(&pszLeader); BAIL_ON_VMDIR_ERROR(dwError); if (pszLeader == NULL) { //server self is a raft leader or leader cannot determined (e.g. in voting stage). goto done; } if (op->conn->dwServerPort == VmDirGetLdapsPort()) { bIsLdaps = TRUE; } dwError = VmDirAllocateStringPrintf(&pszRef, "%s://%s/%s", bIsLdaps ? "ldaps":"ldap", pszLeader, pszRefSuffix ); BAIL_ON_VMDIR_ERROR(dwError); op->ldapResult.errCode = 0; if ((op->reqCode == LDAP_REQ_SEARCH && gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_SEARCH_REFERRAL_ERROR_CODE) || ((op->reqCode == LDAP_REQ_ADD || op->reqCode == LDAP_REQ_DELETE || op->reqCode == LDAP_REQ_MODIFY || op->reqCode == LDAP_REQ_MODDN) && gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_ENABLE_UPDATE_ERROR_CODE)) { op->ldapResult.errCode = LDAP_REFERRAL; } dwError = VmDirAllocateMemory( sizeof(VDIR_BERVALUE) * 2, (PVOID*)&pBerv); BAIL_ON_VMDIR_ERROR(dwError); pBerv[0].lberbv_len = VmDirStringLenA(pszRef); pBerv[0].lberbv_val = pszRef; pBerv[0].bOwnBvVal = TRUE; pBerv[1].lberbv_val = NULL; pBerv[1].lberbv_len = 0; dwError = ber_printf(ber, "{it{W}N}{it{ess}N}", msgId, LDAP_RES_SEARCH_REFERENCE, pBerv, msgId, GetResultTag(op->reqCode), op->ldapResult.errCode, "", ""); BAIL_ON_LBER_ERROR(dwError); dwError = WriteBerOnSocket( op->conn, ber ); BAIL_ON_VMDIR_ERROR(dwError); *pbRefSent = TRUE; VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "VmDirSendLdapReferralResult: sent with referral %s", pszRef); done: ber_free_buf( ber ); VmDirFreeBervalArrayContent(pBerv, 1); VMDIR_SAFE_FREE_MEMORY(pBerv); VMDIR_SAFE_FREE_MEMORY(pszLeader); return; error: goto done; }
static int vc_create_response( void *conn, int resultCode, const char *diagnosticMessage, struct berval *servercred, struct berval *authzid, LDAPControl **ctrls, struct berval **val ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval bv; int rc; assert( val != NULL ); *val = NULL; ber_init2( ber, NULL, LBER_USE_DER ); (void)ber_printf( ber, "{is" /*}*/ , resultCode, diagnosticMessage ? diagnosticMessage : "" ); if ( conn ) { struct berval cookie; cookie.bv_len = sizeof( conn ); cookie.bv_val = (char *)&conn; (void)ber_printf( ber, "tO", 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, &cookie ); } if ( servercred ) { ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS, servercred ); } #if 0 if ( authzid ) { ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_AUTHZID, authzid ); } #endif if ( ctrls ) { int c; rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ); if ( rc == -1 ) goto done; for ( c = 0; ctrls[c] != NULL; c++ ) { rc = ber_printf( ber, "{s" /*}*/, ctrls[c]->ldctl_oid ); if ( ctrls[c]->ldctl_iscritical ) { rc = ber_printf( ber, "b", (ber_int_t)ctrls[c]->ldctl_iscritical ) ; if ( rc == -1 ) goto done; } if ( ctrls[c]->ldctl_value.bv_val != NULL ) { rc = ber_printf( ber, "O", &ctrls[c]->ldctl_value ); if( rc == -1 ) goto done; } rc = ber_printf( ber, /*{*/"N}" ); if ( rc == -1 ) goto done; } rc = ber_printf( ber, /*{*/"N}" ); if ( rc == -1 ) goto done; } ber_printf( ber, /*{*/ "}" ); rc = ber_flatten2( ber, &bv, 0 ); *val = ber_bvdup( &bv ); done:; ber_free_buf( ber ); return rc; }
int slap_send_search_reference( Operation *op, SlapReply *rs ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; int rc = 0; int bytes; char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)"; AttributeDescription *ad_ref = slap_schema.si_ad_ref; AttributeDescription *ad_entry = slap_schema.si_ad_entry; rs->sr_type = REP_SEARCHREF; if ( op->o_callback ) { rc = slap_response_play( op, rs ); if ( rc != SLAP_CB_CONTINUE ) { goto rel; } } Debug( LDAP_DEBUG_TRACE, "=> send_search_reference: dn=\"%s\"\n", edn ); if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL ) ) { Debug( LDAP_DEBUG_ACL, "send_search_reference: access to entry not allowed\n" ); rc = 1; goto rel; } if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_ref, NULL, ACL_READ, NULL ) ) { Debug( LDAP_DEBUG_ACL, "send_search_reference: access " "to reference not allowed\n" ); rc = 1; goto rel; } if( op->o_domain_scope ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: domainScope control in (%s)\n", edn ); rc = 0; goto rel; } if( rs->sr_ref == NULL ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: null ref in (%s)\n", edn ); rc = 1; goto rel; } if( op->o_protocol < LDAP_VERSION3 ) { rc = 0; /* save the references for the result */ if( rs->sr_ref[0].bv_val != NULL ) { if( value_add( &rs->sr_v2ref, rs->sr_ref ) ) rc = LDAP_OTHER; } goto rel; } #ifdef LDAP_CONNECTIONLESS if( op->o_conn && op->o_conn->c_is_udp ) { ber = op->o_res_ber; } else #endif { ber_init_w_nullc( ber, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid, LDAP_RES_SEARCH_REFERENCE, rs->sr_ref ); if( rc != -1 ) { rc = send_ldap_controls( op, ber, rs->sr_ctrls ); } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: ber_printf failed\n" ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) #endif ber_free_buf( ber ); set_ldap_error( rs, LDAP_OTHER, "encode DN error" ); goto rel; } rc = 0; rs_flush_entry( op, rs, NULL ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) { #endif bytes = send_ldap_ber( op, ber ); ber_free_buf( ber ); if ( bytes < 0 ) { rc = LDAP_UNAVAILABLE; } else { ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 ); ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); } #ifdef LDAP_CONNECTIONLESS } #endif if ( rs->sr_ref != NULL ) { int r; for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) { Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n", op->o_log_prefix, r, rs->sr_ref[0].bv_val ); } } else { Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n", op->o_log_prefix ); } Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n" ); if ( 0 ) { rel: rs_flush_entry( op, rs, NULL ); } if ( op->o_callback ) { (void)slap_cleanup_play( op, rs ); } if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ if ( rs->sr_ctrls ) { slap_free_ctrls( op, rs->sr_ctrls ); rs->sr_ctrls = NULL; } } return rc; }
static int send_ldap_response( Operation *op, SlapReply *rs ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; int rc = LDAP_SUCCESS; long bytes; /* op was actually aborted, bypass everything if client didn't Cancel */ if (( rs->sr_err == SLAPD_ABANDON ) && !op->o_cancel ) { rc = SLAPD_ABANDON; goto clean2; } if ( op->o_callback ) { rc = slap_response_play( op, rs ); if ( rc != SLAP_CB_CONTINUE ) { goto clean2; } } /* op completed, connection aborted, bypass sending response */ if ( op->o_abandon && !op->o_cancel ) { rc = SLAPD_ABANDON; goto clean2; } #ifdef LDAP_CONNECTIONLESS if (op->o_conn && op->o_conn->c_is_udp) ber = op->o_res_ber; else #endif { ber_init_w_nullc( ber, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } rc = rs->sr_err; if ( rc == SLAPD_ABANDON && op->o_cancel ) rc = LDAP_CANCELLED; Debug( LDAP_DEBUG_TRACE, "send_ldap_response: msgid=%d tag=%lu err=%d\n", rs->sr_msgid, rs->sr_tag, rc ); if( rs->sr_ref ) { Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n", rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" ); } #ifdef LDAP_CONNECTIONLESS if (op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 ) { rc = ber_printf( ber, "t{ess" /*"}"*/, rs->sr_tag, rc, rs->sr_matched == NULL ? "" : rs->sr_matched, rs->sr_text == NULL ? "" : rs->sr_text ); } else #endif if ( rs->sr_type == REP_INTERMEDIATE ) { rc = ber_printf( ber, "{it{" /*"}}"*/, rs->sr_msgid, rs->sr_tag ); } else { rc = ber_printf( ber, "{it{ess" /*"}}"*/, rs->sr_msgid, rs->sr_tag, rc, rs->sr_matched == NULL ? "" : rs->sr_matched, rs->sr_text == NULL ? "" : rs->sr_text ); } if( rc != -1 ) { if ( rs->sr_ref != NULL ) { assert( rs->sr_err == LDAP_REFERRAL ); rc = ber_printf( ber, "t{W}", LDAP_TAG_REFERRAL, rs->sr_ref ); } else { assert( rs->sr_err != LDAP_REFERRAL ); } } if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) { rc = ber_printf( ber, "tO", LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata ); } if( rc != -1 && ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE )) { if ( rs->sr_rspoid != NULL ) { rc = ber_printf( ber, "ts", rs->sr_type == REP_EXTENDED ? LDAP_TAG_EXOP_RES_OID : LDAP_TAG_IM_RES_OID, rs->sr_rspoid ); } if( rc != -1 && rs->sr_rspdata != NULL ) { rc = ber_printf( ber, "tO", rs->sr_type == REP_EXTENDED ? LDAP_TAG_EXOP_RES_VALUE : LDAP_TAG_IM_RES_VALUE, rs->sr_rspdata ); } } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } if( rc != -1 ) { rc = send_ldap_controls( op, ber, rs->sr_ctrls ); } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } #ifdef LDAP_CONNECTIONLESS if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } #endif if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "ber_printf failed\n" ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) #endif { ber_free_buf( ber ); } goto cleanup; } /* send BER */ bytes = send_ldap_ber( op, ber ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) #endif { ber_free_buf( ber ); } if ( bytes < 0 ) { Debug( LDAP_DEBUG_ANY, "send_ldap_response: ber write failed\n" ); goto cleanup; } ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); cleanup:; /* Tell caller that we did this for real, as opposed to being * overridden by a callback */ rc = SLAP_CB_CONTINUE; clean2:; if ( op->o_callback ) { (void)slap_cleanup_play( op, rs ); } if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) { rs->sr_flags ^= REP_MATCHED_MUSTBEFREED; /* paranoia */ if ( rs->sr_matched ) { free( (char *)rs->sr_matched ); rs->sr_matched = NULL; } } if ( rs->sr_flags & REP_REF_MUSTBEFREED ) { rs->sr_flags ^= REP_REF_MUSTBEFREED; /* paranoia */ if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ if ( rs->sr_ctrls ) { slap_free_ctrls( op, rs->sr_ctrls ); rs->sr_ctrls = NULL; } } return rc; }
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; }