static int valsort_parseCtrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { ber_tag_t tag; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_int_t flag = 0; if ( BER_BVISNULL( &ctrl->ldctl_value )) { rs->sr_text = "valSort control value is absent"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value )) { rs->sr_text = "valSort control value is empty"; return LDAP_PROTOCOL_ERROR; } ber_init2( ber, &ctrl->ldctl_value, 0 ); if (( tag = ber_scanf( ber, "{b}", &flag )) == LBER_ERROR ) { rs->sr_text = "valSort control: flag decoding error"; return LDAP_PROTOCOL_ERROR; } op->o_ctrlflag[valsort_cid] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; if ( flag ) op->o_ctrlflag[valsort_cid] |= SLAP_CONTROL_DATA0; return LDAP_SUCCESS; }
static void tlsg_x509_cert_dn( struct berval *cert, struct berval *dn, int get_subject ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_len_t len; ber_int_t i; ber_init2( ber, cert, LBER_USE_DER ); tag = ber_skip_tag( ber, &len ); /* Sequence */ tag = ber_skip_tag( ber, &len ); /* Sequence */ tag = ber_skip_tag( ber, &len ); /* Context + Constructed (version) */ if ( tag == 0xa0 ) /* Version is optional */ tag = ber_get_int( ber, &i ); /* Int: Version */ tag = ber_skip_tag( ber, &len ); /* Int: Serial (can be longer than ber_int_t) */ ber_skip_data( ber, len ); tag = ber_skip_tag( ber, &len ); /* Sequence: Signature */ ber_skip_data( ber, len ); if ( !get_subject ) { tag = ber_peek_tag( ber, &len ); /* Sequence: Issuer DN */ } else { tag = ber_skip_tag( ber, &len ); ber_skip_data( ber, len ); tag = ber_skip_tag( ber, &len ); /* Sequence: Validity */ ber_skip_data( ber, len ); tag = ber_peek_tag( ber, &len ); /* Sequence: Subject DN */ } len = ber_ptrlen( ber ); dn->bv_val = cert->bv_val + len; dn->bv_len = cert->bv_len - len; }
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; }
int ParseSyncStateControlVal( BerValue * controlValue, // Input: control value encoded as ber, int * entryState) // Output { int retVal = LDAP_SUCCESS; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." ); ber_init2( ber, controlValue, LBER_USE_DER ); if (ber_scanf( ber, "{i}", entryState ) == -1 ) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseSyncStateControlVal: ber_scanf to read entryState failed" ); retVal = LDAP_OPERATIONS_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } cleanup: VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." ); return retVal; error: goto cleanup; }
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 ); ber_init2( ber, NULL, 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 _ParseCondWriteControlVal( VDIR_OPERATION * pOp, BerValue * pControlBer, // Input: control value encoded as ber VDIR_CONDWRITE_CONTROL_VALUE * pCtrlVal, // Output VDIR_LDAP_RESULT * pLdapResult // Output ) { int retVal = LDAP_SUCCESS; BerElementBuffer berbuf; BerElement * ber = (BerElement *)&berbuf; PSTR pszLocalErrorMsg = NULL; PSTR pszCondFilter = NULL; if (!pOp) { retVal = LDAP_PROTOCOL_ERROR; BAIL_ON_VMDIR_ERROR( retVal ); } ber_init2( ber, pControlBer, LBER_USE_DER ); /* * https://confluence.eng.vmware.com/display/LIG/Conditional+LDAP+Write+Operation * * The ConditionalWriteControl is a null terminated STRING wrapping the BER-encoded version of the following SEQUENCE: * * ControlValue ::= SEQUENCE { * ConditionalWriteFilter OCTET STRING * } */ if (ber_scanf(ber, "{a}", &pszCondFilter) == LBER_ERROR) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_scanf failed while parsing filter value", __FUNCTION__); pLdapResult->errCode = LDAP_PROTOCOL_ERROR; retVal = LDAP_NOTICE_OF_DISCONNECT; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Error in reading conditional write control filter"); } retVal = VmDirAllocateStringA(pszCondFilter, &(pCtrlVal->pszFilter)); BAIL_ON_VMDIR_ERROR(retVal); cleanup: if (pszCondFilter) { ber_memfree(pszCondFilter); } VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); return retVal; error: VMDIR_APPEND_ERROR_MSG(pLdapResult->pszErrMsg, pszLocalErrorMsg); goto cleanup; }
/* 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 slap_read_controls( Operation *op, SlapReply *rs, Entry *e, const struct berval *oid, LDAPControl **ctrl ) { int rc; struct berval bv; BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; LDAPControl c; Operation myop; Debug( LDAP_DEBUG_ANY, "%s slap_read_controls: (%s) %s\n", op->o_log_prefix, oid->bv_val, e->e_dn ); rs->sr_entry = e; rs->sr_attrs = ( oid == &slap_pre_read_bv ) ? op->o_preread_attrs : op->o_postread_attrs; 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 ); /* create new operation */ myop = *op; /* FIXME: o_bd needed for ACL */ myop.o_bd = op->o_bd; myop.o_res_ber = ber; myop.o_callback = NULL; myop.ors_slimit = 1; myop.ors_attrsonly = 0; rc = slap_send_search_entry( &myop, rs ); if( rc ) return rc; rc = ber_flatten2( ber, &c.ldctl_value, 0 ); if( rc == -1 ) return LDAP_OTHER; c.ldctl_oid = oid->bv_val; c.ldctl_iscritical = 0; if ( *ctrl == NULL ) { /* first try */ *ctrl = (LDAPControl *) slap_sl_calloc( 1, sizeof(LDAPControl), NULL ); } else { /* retry: free previous try */ slap_sl_free( (*ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); } **ctrl = c; return LDAP_SUCCESS; }
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 ); }
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; }
/* Rewrite an LDAP DN in DER form * Input must be valid DN, therefore no error checking is done here. */ static int autoca_dnbv2der( Operation *op, struct berval *bv, struct berval *der ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; LDAPDN dn; LDAPRDN rdn; LDAPAVA *ava; AttributeDescription *ad; int irdn, iava; ldap_bv2dn_x( bv, &dn, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ); ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); /* count RDNs, we need them in reverse order */ for (irdn = 0; dn[irdn]; irdn++); irdn--; /* DN is a SEQuence of RDNs */ ber_start_seq( ber, LBER_SEQUENCE ); for (; irdn >=0; irdn--) { /* RDN is a SET of AVAs */ ber_start_set( ber, LBER_SET ); rdn = dn[irdn]; for (iava = 0; rdn[iava]; iava++) { const char *text; char oid[1024]; struct berval bvo = { sizeof(oid), oid }; struct berval bva; /* AVA is a SEQuence of attr and value */ ber_start_seq( ber, LBER_SEQUENCE ); ava = rdn[iava]; ad = NULL; slap_bv2ad( &ava->la_attr, &ad, &text ); ber_str2bv( ad->ad_type->sat_oid, 0, 0, &bva ); ber_encode_oid( &bva, &bvo ); ber_put_berval( ber, &bvo, LBER_TAG_OID ); ber_put_berval( ber, &ava->la_value, LBER_TAG_UTF8 ); ber_put_seq( ber ); } ber_put_set( ber ); } ber_put_seq( ber ); ber_flatten2( ber, der, 0 ); ldap_dnfree_x( dn, op->o_tmpmemctx ); return 0; }
/* Conforms to RFC4510 re: Criticality, original RFC2891 spec is broken * Also see ITS#7253 for discussion */ static int sss_parseCtrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { BerElementBuffer berbuf; BerElement *ber; ber_tag_t tag; ber_len_t len; int i; sort_ctrl *sc; rs->sr_err = LDAP_PROTOCOL_ERROR; if ( op->o_ctrlflag[sss_cid] > SLAP_CONTROL_IGNORED ) { rs->sr_text = "sorted results control specified multiple times"; } else if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "sorted results control value is absent"; } else if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "sorted results control value is empty"; } else { rs->sr_err = LDAP_SUCCESS; } if ( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err; op->o_ctrlflag[sss_cid] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; ber = (BerElement *)&berbuf; ber_init2( ber, &ctrl->ldctl_value, 0 ); i = count_key( ber ); sc = op->o_tmpalloc( sizeof(sort_ctrl) + (i-1) * sizeof(sort_key), op->o_tmpmemctx ); sc->sc_nkeys = i; op->o_controls[sss_cid] = sc; /* peel off initial sequence */ ber_scanf( ber, "{" ); i = 0; do { if ( build_key( ber, rs, &sc->sc_keys[i] ) != LDAP_SUCCESS ) break; i++; tag = ber_peek_tag( ber, &len ); } while ( tag != LBER_DEFAULT ); return rs->sr_err; }
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; }
/* 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 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; }
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; }
/* NOTE: The DN in *id is NOT NUL-terminated here. dnNormalize will * reject it in this condition, the caller must NUL-terminate it. * FIXME: should dnNormalize still be complaining about that? */ int slap_passwd_parse( struct berval *reqdata, struct berval *id, struct berval *oldpass, struct berval *newpass, const char **text ) { int rc = LDAP_SUCCESS; ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; if( reqdata == NULL ) { return LDAP_SUCCESS; } if( reqdata->bv_len == 0 ) { *text = "empty request data field"; return LDAP_PROTOCOL_ERROR; } /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, reqdata, 0 ); tag = ber_skip_tag( ber, &len ); if( tag != LBER_SEQUENCE ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: decoding error\n", 0, 0, 0 ); rc = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) { if( id == NULL ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n", 0, 0, 0 ); *text = "user must change own password"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_get_stringbv( ber, id, LBER_BV_NOTERM ); if( tag == LBER_ERROR ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n", 0, 0, 0 ); goto decoding_error; } tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ) { if( oldpass == NULL ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n", 0, 0, 0 ); *text = "use bind to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_get_stringbv( ber, oldpass, LBER_BV_NOTERM ); if( tag == LBER_ERROR ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n", 0, 0, 0 ); goto decoding_error; } if( oldpass->bv_len == 0 ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD empty.\n", 0, 0, 0 ); *text = "old password value is empty"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ) { if( newpass == NULL ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n", 0, 0, 0 ); *text = "user specified passwords disallowed"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_get_stringbv( ber, newpass, LBER_BV_NOTERM ); if( tag == LBER_ERROR ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW parse failed.\n", 0, 0, 0 ); goto decoding_error; } if( newpass->bv_len == 0 ) { Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW empty.\n", 0, 0, 0 ); *text = "new password value is empty"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_peek_tag( ber, &len ); } if( len != 0 ) { decoding_error: Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: decoding error, len=%ld\n", (long) len, 0, 0 ); *text = "data decoding error"; rc = LDAP_PROTOCOL_ERROR; } done: return rc; }
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 deref_parseCtrl ( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { ber_tag_t tag; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_len_t len; char *last; DerefSpec *dshead = NULL, **dsp = &dshead; BerVarray attributes = NULL; if ( op->o_deref != SLAP_CONTROL_NONE ) { rs->sr_text = "Dereference control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "Dereference control value is absent"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "Dereference control value is empty"; return LDAP_PROTOCOL_ERROR; } ber_init2( ber, &ctrl->ldctl_value, 0 ); for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { struct berval derefAttr; DerefSpec *ds, *dstmp; const char *text; int rc; ber_len_t cnt = sizeof(struct berval); ber_len_t off = 0; if ( ber_scanf( ber, "{m{M}}", &derefAttr, &attributes, &cnt, off ) == LBER_ERROR || !cnt ) { rs->sr_text = "Dereference control: derefSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds = (DerefSpec *)op->o_tmpcalloc( 1, sizeof(DerefSpec) + sizeof(AttributeDescription *)*(cnt + 1), op->o_tmpmemctx ); ds->ds_attributes = (AttributeDescription **)&ds[ 1 ]; ds->ds_nattrs = cnt; rc = slap_bv2ad( &derefAttr, &ds->ds_derefAttr, &text ); if ( rc != LDAP_SUCCESS ) { rs->sr_text = "Dereference control: derefAttr decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } for ( dstmp = dshead; dstmp && dstmp != ds; dstmp = dstmp->ds_next ) { if ( dstmp->ds_derefAttr == ds->ds_derefAttr ) { rs->sr_text = "Dereference control: derefAttr must be unique within control"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } if ( !( ds->ds_derefAttr->ad_type->sat_syntax->ssyn_flags & SLAP_SYNTAX_DN )) { if ( ctrl->ldctl_iscritical ) { rs->sr_text = "Dereference control: derefAttr syntax not distinguishedName"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } rs->sr_err = LDAP_SUCCESS; goto justcleanup; } for ( cnt = 0; !BER_BVISNULL( &attributes[ cnt ] ); cnt++ ) { rc = slap_bv2ad( &attributes[ cnt ], &ds->ds_attributes[ cnt ], &text ); if ( rc != LDAP_SUCCESS ) { rs->sr_text = "Dereference control: attribute decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } ber_memfree_x( attributes, op->o_tmpmemctx ); attributes = NULL; *dsp = ds; dsp = &ds->ds_next; } op->o_ctrlderef = (void *)dshead; op->o_deref = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; rs->sr_err = LDAP_SUCCESS; done:; if ( rs->sr_err != LDAP_SUCCESS ) { justcleanup:; for ( ; dshead; ) { DerefSpec *dsnext = dshead->ds_next; op->o_tmpfree( dshead, op->o_tmpmemctx ); dshead = dsnext; } } if ( attributes != NULL ) { ber_memfree_x( attributes, op->o_tmpmemctx ); } return rs->sr_err; }
static int ldap_back_exop_passwd( Operation *op, SlapReply *rs, ldapconn_t **lcp ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = *lcp; req_pwdexop_s *qpw = &op->oq_pwdexop; LDAPMessage *res; ber_int_t msgid; int rc, isproxy, freedn = 0; int do_retry = 1; char *text = NULL; struct berval dn = op->o_req_dn, ndn = op->o_req_ndn; assert( lc != NULL ); assert( rs->sr_ctrls == NULL ); if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) { /* NOTE: most of this code is mutated * from slap_passwd_parse(); * But here we only need * the first berval... */ ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval tmpid = BER_BVNULL; if ( op->ore_reqdata->bv_len == 0 ) { return LDAP_PROTOCOL_ERROR; } /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, op->ore_reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if ( tag == LBER_ERROR ) { return LDAP_PROTOCOL_ERROR; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) { tag = ber_get_stringbv( ber, &tmpid, LBER_BV_NOTERM ); if ( tag == LBER_ERROR ) { return LDAP_PROTOCOL_ERROR; } } if ( !BER_BVISEMPTY( &tmpid ) ) { char idNull = tmpid.bv_val[tmpid.bv_len]; tmpid.bv_val[tmpid.bv_len] = '\0'; rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn, &ndn, op->o_tmpmemctx ); tmpid.bv_val[tmpid.bv_len] = idNull; if ( rs->sr_err != LDAP_SUCCESS ) { /* should have been successfully parsed earlier! */ return rs->sr_err; } freedn = 1; } else { dn = op->o_dn; ndn = op->o_ndn; } } isproxy = ber_bvcmp( &ndn, &op->o_ndn ); Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n", dn.bv_val, isproxy ? " (proxy)" : "", 0 ); retry: rc = ldap_passwd( lc->lc_ld, &dn, qpw->rs_old.bv_val ? &qpw->rs_old : NULL, qpw->rs_new.bv_val ? &qpw->rs_new : NULL, op->o_ctrls, NULL, &msgid ); if ( rc == LDAP_SUCCESS ) { /* TODO: set timeout? */ /* by now, make sure no timeout is used (ITS#6282) */ struct timeval tv = { -1, 0 }; if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); rs->sr_err = rc; } else { /* only touch when activity actually took place... */ if ( li->li_idle_timeout ) { lc->lc_time = op->o_time; } /* sigh. parse twice, because parse_passwd * doesn't give us the err / match / msg info. */ rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, (char **)&rs->sr_matched, &text, NULL, &rs->sr_ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { struct berval newpw; /* this never happens because * the frontend is generating * the new password, so when * the passwd exop is proxied, * it never delegates password * generation to the remote server */ rc = ldap_parse_passwd( lc->lc_ld, res, &newpw ); if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &newpw ) ) { rs->sr_type = REP_EXTENDED; rs->sr_rspdata = slap_passwd_return( &newpw ); free( newpw.bv_val ); } } else { rc = rs->sr_err; } } ldap_msgfree( res ); } } if ( rc != LDAP_SUCCESS ) { rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( text ) rs->sr_text = text; send_ldap_extended( op, rs ); /* otherwise frontend resends result */ rc = rs->sr_err = SLAPD_ABANDON; } else if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_EXTENDED ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); if ( freedn ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); } /* these have to be freed anyway... */ if ( rs->sr_matched ) { free( (char *)rs->sr_matched ); rs->sr_matched = NULL; } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } if ( text ) { free( text ); rs->sr_text = NULL; } /* in case, cleanup handler */ if ( lc == NULL ) { *lcp = NULL; } return rc; }
int asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate) { a_metainfo_t *mi; a_metatarget_t *mt; a_metasingleconn_t *msc; Operation *op = bc->op; SlapReply *rs; int i, rc = LDAP_SUCCESS, sres; SlapReply *candidates; char **references = NULL; LDAPControl **ctrls = NULL; a_dncookie dc; LDAPMessage *msg; ber_int_t id; rs = &bc->rs; mi = mc->mc_info; mt = mi->mi_targets[ candidate ]; msc = &mc->mc_conns[ candidate ]; dc.op = op; dc.target = mt; dc.to_from = MASSAGE_REP; id = ldap_msgid(res); candidates = bc->candidates; i = candidate; while (res && !META_BACK_CONN_INVALID(msc)) { for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) { switch(ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p entry\n", op->o_log_prefix, msc ); if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } /* count entries returned by target */ candidates[ i ].sr_nentries++; if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) { rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg ); } else { goto err_cleanup; } switch ( rs->sr_err ) { case LDAP_SIZELIMIT_EXCEEDED: asyncmeta_send_ldap_result(bc, op, rs); rs->sr_err = LDAP_SUCCESS; goto err_cleanup; case LDAP_UNAVAILABLE: rs->sr_err = LDAP_OTHER; break; default: break; } bc->is_ok++; break; case LDAP_RES_SEARCH_REFERENCE: if ( META_BACK_TGT_NOREFS( mt ) ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; rc = ldap_parse_reference( msc->msc_ldr, msg, &references, &rs->sr_ctrls, 0 ); if ( rc != LDAP_SUCCESS || references == NULL ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } /* FIXME: merge all and return at the end */ { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); } { dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref ); } if ( rs->sr_ref != NULL ) { if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) { /* ignore return value by now */ ( void )send_search_reference( op, rs ); } ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } /* cleanup */ if ( references ) { ber_memvfree( (void **)references ); } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_INTERMEDIATE: if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; /* FIXME: response controls * are passed without checks */ rs->sr_err = ldap_parse_intermediate( msc->msc_ldr, msg, (char **)&rs->sr_rspoid, &rs->sr_rspdata, &rs->sr_ctrls, 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_type = REP_RESULT; rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } slap_send_ldap_intermediate( op, rs ); if ( rs->sr_rspoid != NULL ) { ber_memfree( (char *)rs->sr_rspoid ); rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); rs->sr_rspdata = NULL; } if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_SEARCH_RESULT: if ( mi->mi_idle_timeout != 0 ) { asyncmeta_set_msc_time(msc); } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p result\n", op->o_log_prefix, msc ); candidates[ i ].sr_type = REP_RESULT; candidates[ i ].sr_msgid = META_MSGID_IGNORE; /* NOTE: ignores response controls * (and intermediate response controls * as well, except for those with search * references); this may not be correct, * but if they're not ignored then * back-meta would need to merge them * consistently (think of pagedResults...) */ /* FIXME: response controls? */ rs->sr_err = ldap_parse_result( msc->msc_ldr, msg, &candidates[ i ].sr_err, (char **)&candidates[ i ].sr_matched, (char **)&candidates[ i ].sr_text, &references, &ctrls /* &candidates[ i ].sr_ctrls (unused) */ , 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_err = rs->sr_err; sres = slap_map_api2result( &candidates[ i ] ); candidates[ i ].sr_type = REP_RESULT; goto finish; } rs->sr_err = candidates[ i ].sr_err; /* massage matchedDN if need be */ if ( candidates[ i ].sr_matched != NULL ) { struct berval match, mmatch; ber_str2bv( candidates[ i ].sr_matched, 0, 0, &match ); candidates[ i ].sr_matched = NULL; dc.memctx = NULL; asyncmeta_dn_massage( &dc, &match, &mmatch ); if ( mmatch.bv_val == match.bv_val ) { candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val ); } else { candidates[ i ].sr_matched = mmatch.bv_val; } bc->candidate_match++; ldap_memfree( match.bv_val ); } /* add references to array */ /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references != NULL && references[ 0 ] != NULL && references[ 0 ][ 0 ] != '\0' ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s asncmeta_search_result[%d]: " "got referrals with err=%d\n", op->o_log_prefix, i, rs->sr_err ); } else { BerVarray sr_ref; int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &sr_ref[ cnt ] ); dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, sr_ref ); if ( rs->sr_v2ref == NULL ) { rs->sr_v2ref = sr_ref; } else { for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) { ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ], op->o_tmpmemctx ); } ber_memfree_x( sr_ref, op->o_tmpmemctx ); } } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d]: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, i, rs->sr_err ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } /* cleanup */ ber_memvfree( (void **)references ); sres = slap_map_api2result( rs ); if ( candidates[ i ].sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err ); } else { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld (%s)", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) ); } switch ( sres ) { case LDAP_NO_SUCH_OBJECT: /* is_ok is touched any time a valid * (even intermediate) result is * returned; as a consequence, if * a candidate returns noSuchObject * it is ignored and the candidate * is simply demoted. */ if ( bc->is_ok ) { sres = LDAP_SUCCESS; } break; case LDAP_SUCCESS: if ( ctrls != NULL && ctrls[0] != NULL ) { #ifdef SLAPD_META_CLIENT_PR LDAPControl *pr_c; pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); if ( pr_c != NULL ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_int_t prsize; struct berval prcookie; /* unsolicited, do not accept */ if ( mt->mt_ps == 0 ) { rs->sr_err = LDAP_OTHER; goto err_pr; } ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER ); tag = ber_scanf( ber, "{im}", &prsize, &prcookie ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_OTHER; goto err_pr; } /* more pages? new search request */ if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) { if ( mt->mt_ps > 0 ) { /* ignore size if specified */ prsize = 0; } else if ( prsize == 0 ) { /* guess the page size from the entries returned so far */ prsize = candidates[ i ].sr_nentries; } candidates[ i ].sr_nentries = 0; candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_INTERMEDIATE; assert( candidates[ i ].sr_matched == NULL ); assert( candidates[ i ].sr_text == NULL ); assert( candidates[ i ].sr_ref == NULL ); switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) ) { case META_SEARCH_CANDIDATE: assert( candidates[ i ].sr_msgid >= 0 ); ldap_controls_free( ctrls ); // goto free_message; case META_SEARCH_ERR: case META_SEARCH_NEED_BIND: err_pr:; candidates[ i ].sr_err = rs->sr_err; candidates[ i ].sr_type = REP_RESULT; if ( META_BACK_ONERR_STOP( mi ) ) { asyncmeta_send_ldap_result(bc, op, rs); ldap_controls_free( ctrls ); goto err_cleanup; } /* fallthru */ case META_SEARCH_NOT_CANDIDATE: /* means that asyncmeta_back_search_start() * failed but onerr == continue */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_RESULT; break; default: /* impossible */ assert( 0 ); break; } break; } } #endif /* SLAPD_META_CLIENT_PR */ ldap_controls_free( ctrls ); } /* fallthru */ case LDAP_REFERRAL: bc->is_ok++; break; case LDAP_SIZELIMIT_EXCEEDED: /* if a target returned sizelimitExceeded * and the entry count is equal to the * proxy's limit, the target would have * returned more, and the error must be * propagated to the client; otherwise, * the target enforced a limit lower * than what requested by the proxy; * ignore it */ candidates[ i ].sr_err = rs->sr_err; if ( rs->sr_nentries == op->ors_slimit || META_BACK_ONERR_STOP( mi ) ) { const char *save_text; got_err: save_text = rs->sr_text; rs->sr_text = candidates[ i ].sr_text; asyncmeta_send_ldap_result(bc, op, rs); if (candidates[ i ].sr_text != NULL) { ch_free( (char *)candidates[ i ].sr_text ); candidates[ i ].sr_text = NULL; } rs->sr_text = save_text; ldap_controls_free( ctrls ); goto err_cleanup; } break; default: candidates[ i ].sr_err = rs->sr_err; if ( META_BACK_ONERR_STOP( mi ) ) { goto got_err; } break; } /* if this is the last result we will ever receive, send it back */ rc = rs->sr_err; if (asyncmeta_is_last_result(mc, bc, i) == 0) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p last result\n", op->o_log_prefix, msc ); asyncmeta_search_last_result(mc, bc, i, sres); err_cleanup: rc = rs->sr_err; ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); asyncmeta_drop_bc( mc, bc); asyncmeta_clear_bm_context(bc); ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); ldap_msgfree(res); return rc; } finish: break; default: continue; } } ldap_msgfree(res); res = NULL; if (candidates[ i ].sr_type != REP_RESULT) { struct timeval tv = {0}; rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res ); if (res != NULL) { msc->msc_result_time = slap_get_time(); } } } ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); bc->bc_active--; ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); return rc; }
int ber_decode_krb5_key_data(struct berval *encoded, int *m_kvno, int *numk, krb5_key_data **data) { krb5_key_data *keys = NULL; BerElement *be = NULL; void *tmp; int i = 0; ber_tag_t tag; ber_int_t major_vno; ber_int_t minor_vno; ber_int_t kvno; ber_int_t mkvno; ber_int_t type; ber_tag_t seqtag; ber_len_t seqlen; ber_len_t setlen; ber_tag_t retag; ber_tag_t opttag; struct berval tval; int ret; be = ber_alloc_t(LBER_USE_DER); if (!be) { return ENOMEM; } /* reinit the ber element with the new val */ ber_init2(be, encoded, LBER_USE_DER); /* fill key_data struct with the data */ retag = ber_scanf(be, "{t[i]t[i]t[i]t[i]t[{", &tag, &major_vno, &tag, &minor_vno, &tag, &kvno, &tag, &mkvno, &seqtag); if (retag == LBER_ERROR || major_vno != 1 || minor_vno != 1 || seqtag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4)) { ret = EINVAL; goto done; } retag = ber_skip_tag(be, &seqlen); /* sequence of keys */ for (i = 0; retag == LBER_SEQUENCE; i++) { tmp = realloc(keys, (i + 1) * sizeof(krb5_key_data)); if (!tmp) { ret = ENOMEM; goto done; } keys = tmp; memset(&keys[i], 0, sizeof(krb5_key_data)); keys[i].key_data_kvno = kvno; /* do we have a salt type ? (optional) */ retag = ber_scanf(be, "t", &opttag); if (retag == LBER_ERROR) { ret = EINVAL; goto done; } if (opttag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) { keys[i].key_data_ver = 2; retag = ber_scanf(be, "[l{tl[i]", &seqlen, &tag, &setlen, &type); if (tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) { ret = EINVAL; goto done; } keys[i].key_data_type[1] = type; /* do we have salt data ? (optional) */ if (seqlen > setlen + 2) { retag = ber_scanf(be, "t[o]", &tag, &tval); if (retag == LBER_ERROR || tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) { ret = EINVAL; goto done; } keys[i].key_data_length[1] = tval.bv_len; keys[i].key_data_contents[1] = (krb5_octet *)tval.bv_val; } retag = ber_scanf(be, "}]t", &opttag); if (retag == LBER_ERROR) { ret = EINVAL; goto done; } } else { keys[i].key_data_ver = 1; } if (opttag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) { ret = EINVAL; goto done; } /* get the key */ retag = ber_scanf(be, "[{t[i]t[o]}]", &tag, &type, &tag, &tval); if (retag == LBER_ERROR) { ret = EINVAL; goto done; } keys[i].key_data_type[0] = type; keys[i].key_data_length[0] = tval.bv_len; keys[i].key_data_contents[0] = (krb5_octet *)tval.bv_val; /* check for sk2params */ retag = ber_peek_tag(be, &setlen); if (retag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2)) { /* not supported yet, skip */ retag = ber_scanf(be, "t[x]}"); } else { retag = ber_scanf(be, "}"); } if (retag == LBER_ERROR) { ret = EINVAL; goto done; } retag = ber_skip_tag(be, &seqlen); } ret = 0; done: ber_free(be, 0); /* internal buffer is 'encoded' */ if (ret) { for (i -= 1; keys && i >= 0; i--) { free(keys[i].key_data_contents[0]); free(keys[i].key_data_contents[1]); } free(keys); keys = NULL; mkvno = 0; } *m_kvno = mkvno; *numk = i; *data = keys; return ret; }
int slap_passwd_parse( struct berval *reqdata, struct berval *id, struct berval *oldpass, struct berval *newpass, const char **text ) { int rc = LDAP_SUCCESS; ber_tag_t tag; ber_len_t len; char berbuf[LBER_ELEMENT_SIZEOF]; BerElement *ber = (BerElement *)berbuf; if( reqdata == NULL ) { return LDAP_SUCCESS; } if( reqdata->bv_len == 0 ) { *text = "empty request data field"; return LDAP_PROTOCOL_ERROR; } /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if( tag != LBER_ERROR ) { tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) { if( id == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: ID not allowed.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n", 0, 0, 0 ); #endif *text = "user must change own password"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_scanf( ber, "m", id ); if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: ID parse failed.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n", 0, 0, 0 ); #endif goto decoding_error; } tag = ber_peek_tag( ber, &len); } if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ) { if( oldpass == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: OLD not allowed.\n" , 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n", 0, 0, 0 ); #endif *text = "use bind to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_scanf( ber, "m", oldpass ); if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: ID parse failed.\n" , 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n", 0, 0, 0 ); #endif goto decoding_error; } tag = ber_peek_tag( ber, &len ); } if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ) { if( newpass == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: NEW not allowed.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n", 0, 0, 0 ); #endif *text = "user specified passwords disallowed"; rc = LDAP_UNWILLING_TO_PERFORM; goto done; } tag = ber_scanf( ber, "m", newpass ); if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: OLD parse failed.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n", 0, 0, 0 ); #endif goto decoding_error; } tag = ber_peek_tag( ber, &len ); } if( len != 0 ) { decoding_error: #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "slap_passwd_parse: decoding error, len=%ld\n", (long)len, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: decoding error, len=%ld\n", (long) len, 0, 0 ); #endif *text = "data decoding error"; rc = LDAP_PROTOCOL_ERROR; } done: return rc; }
static int vc_exop( Operation *op, SlapReply *rs ) { int rc = LDAP_SUCCESS; ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval reqdata = BER_BVNULL; struct berval cookie = BER_BVNULL; struct berval bdn = BER_BVNULL; ber_tag_t authtag; struct berval cred = BER_BVNULL; struct berval ndn = BER_BVNULL; struct berval mechanism = BER_BVNULL; vc_conn_t *conn = NULL; vc_cb_t vc = { 0 }; slap_callback sc = { 0 }; SlapReply rs2 = { 0 }; if ( op->ore_reqdata == NULL || op->ore_reqdata->bv_len == 0 ) { rs->sr_text = "empty request data field in VerifyCredentials exop"; return LDAP_PROTOCOL_ERROR; } /* optimistic */ rs->sr_err = LDAP_SUCCESS; ber_dupbv_x( &reqdata, op->ore_reqdata, op->o_tmpmemctx ); /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, &reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if ( tag != LBER_SEQUENCE ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ) { /* * cookie: the pointer to the connection * of this operation */ ber_scanf( ber, "m", &cookie ); if ( cookie.bv_len != sizeof(Connection *) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } /* DN, authtag */ tag = ber_scanf( ber, "mt", &bdn, &authtag ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } rc = dnNormalize( 0, NULL, NULL, &bdn, &ndn, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } switch ( authtag ) { case LDAP_AUTH_SIMPLE: /* cookie only makes sense for SASL bind (so far) */ if ( !BER_BVISNULL( &cookie ) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_scanf( ber, "m", &cred ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } break; case LDAP_AUTH_SASL: tag = ber_scanf( ber, "{s" /*}*/ , &mechanism ); if ( tag == LBER_ERROR || BER_BVISNULL( &mechanism ) || BER_BVISEMPTY( &mechanism ) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == LBER_OCTETSTRING ) { ber_scanf( ber, "m", &cred ); } tag = ber_scanf( ber, /*{*/ "}" ); break; default: rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } if ( !BER_BVISNULL( &cookie ) ) { vc_conn_t tmp = { 0 }; AC_MEMCPY( (char *)&tmp.conn, (const char *)cookie.bv_val, cookie.bv_len ); ldap_pvt_thread_mutex_lock( &vc_mutex ); conn = (vc_conn_t *)avl_find( vc_tree, (caddr_t)&tmp, vc_conn_cmp ); if ( conn == NULL || ( conn != NULL && conn->refcnt != 0 ) ) { conn = NULL; ldap_pvt_thread_mutex_unlock( &vc_mutex ); rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } conn->refcnt++; ldap_pvt_thread_mutex_unlock( &vc_mutex ); } else { void *thrctx; conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) ); conn->refcnt = 1; thrctx = ldap_pvt_thread_pool_context(); connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 ); conn->op = &conn->opbuf.ob_op; snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ), "%s VERIFYCREDENTIALS", op->o_log_prefix ); } conn->op->o_tag = LDAP_REQ_BIND; memset( &conn->op->oq_bind, 0, sizeof( conn->op->oq_bind ) ); conn->op->o_req_dn = ndn; conn->op->o_req_ndn = ndn; conn->op->o_protocol = LDAP_VERSION3; conn->op->orb_method = authtag; conn->op->o_callback = ≻ /* TODO: controls */ tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ) { conn->op->o_ber = ber; rc = get_ctrls2( conn->op, &rs2, 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } tag = ber_skip_tag( ber, &len ); if ( len || tag != LBER_DEFAULT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } switch ( authtag ) { case LDAP_AUTH_SIMPLE: break; case LDAP_AUTH_SASL: conn->op->orb_mech = mechanism; break; } conn->op->orb_cred = cred; sc.sc_response = vc_cb; sc.sc_private = &vc; conn->op->o_bd = frontendDB; rs->sr_err = frontendDB->be_bind( conn->op, &rs2 ); if ( conn->op->o_conn->c_sasl_bind_in_progress ) { rc = vc_create_response( conn, rs2.sr_err, rs2.sr_text, !BER_BVISEMPTY( &vc.sasldata ) ? &vc.sasldata : NULL, NULL, vc.ctrls, &rs->sr_rspdata ); } else { rc = vc_create_response( NULL, rs2.sr_err, rs2.sr_text, NULL, &conn->op->o_conn->c_dn, vc.ctrls, &rs->sr_rspdata ); } if ( rc != 0 ) { rs->sr_err = LDAP_OTHER; goto done; } if ( !BER_BVISNULL( &conn->op->o_conn->c_dn ) && conn->op->o_conn->c_dn.bv_val != conn->op->o_conn->c_ndn.bv_val ) ber_memfree( conn->op->o_conn->c_dn.bv_val ); if ( !BER_BVISNULL( &conn->op->o_conn->c_ndn ) ) ber_memfree( conn->op->o_conn->c_ndn.bv_val ); done:; if ( conn ) { if ( conn->op->o_conn->c_sasl_bind_in_progress ) { if ( conn->conn == NULL ) { conn->conn = conn; conn->refcnt--; ldap_pvt_thread_mutex_lock( &vc_mutex ); rc = avl_insert( &vc_tree, (caddr_t)conn, vc_conn_cmp, vc_conn_dup ); ldap_pvt_thread_mutex_unlock( &vc_mutex ); assert( rc == 0 ); } else { ldap_pvt_thread_mutex_lock( &vc_mutex ); conn->refcnt--; ldap_pvt_thread_mutex_unlock( &vc_mutex ); } } else { if ( conn->conn != NULL ) { vc_conn_t *tmp; ldap_pvt_thread_mutex_lock( &vc_mutex ); tmp = avl_delete( &vc_tree, (caddr_t)conn, vc_conn_cmp ); ldap_pvt_thread_mutex_unlock( &vc_mutex ); } SLAP_FREE( conn ); } } if ( vc.ctrls ) { ldap_controls_free( vc.ctrls ); vc.ctrls = NULL; } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ndn ); } op->o_tmpfree( reqdata.bv_val, op->o_tmpmemctx ); BER_BVZERO( &reqdata ); return rs->sr_err; }
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; }
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 txn_end_extop( Operation *op, SlapReply *rs ) { int rc; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_len_t len; ber_int_t commit=1; struct berval txnid; Statslog( LDAP_DEBUG_STATS, "%s TXN END\n", op->o_log_prefix, 0, 0, 0, 0 ); if( op->ore_reqdata == NULL ) { rs->sr_text = "request data expected"; return LDAP_PROTOCOL_ERROR; } if( op->ore_reqdata->bv_len == 0 ) { rs->sr_text = "empty request data"; return LDAP_PROTOCOL_ERROR; } op->o_bd = op->o_conn->c_authz_backend; if( backend_check_restrictions( op, rs, (struct berval *)&slap_EXOP_TXN_END ) != LDAP_SUCCESS ) { return rs->sr_err; } ber_init2( ber, op->ore_reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if( tag == LBER_ERROR ) { rs->sr_text = "request data decoding error"; return LDAP_PROTOCOL_ERROR; } tag = ber_peek_tag( ber, &len ); if( tag == LBER_BOOLEAN ) { tag = ber_scanf( ber, "b", &commit ); if( tag == LBER_ERROR ) { rs->sr_text = "request data decoding error"; return LDAP_PROTOCOL_ERROR; } } tag = ber_scanf( ber, /*{*/ "m}", &txnid ); if( tag == LBER_ERROR ) { rs->sr_text = "request data decoding error"; return LDAP_PROTOCOL_ERROR; } if( txnid.bv_len ) { rs->sr_text = "invalid transaction identifier"; return LDAP_X_TXN_ID_INVALID; } /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); if( op->o_conn->c_txn != CONN_TXN_SPECIFY ) { rs->sr_text = "invalid transaction identifier"; rc = LDAP_X_TXN_ID_INVALID; goto done; } op->o_conn->c_txn = CONN_TXN_SETTLE; if( commit ) { if ( op->o_abandon ) { } if( LDAP_STAILQ_EMPTY(&op->o_conn->c_txn_ops) ) { /* no updates to commit */ rs->sr_text = "no updates to commit"; rc = LDAP_OPERATIONS_ERROR; goto settled; } rs->sr_text = "not yet implemented"; rc = LDAP_UNWILLING_TO_PERFORM; } else { rs->sr_text = "transaction aborted"; rc = LDAP_SUCCESS;; } drain: /* drain txn ops list */ settled: assert( LDAP_STAILQ_EMPTY(&op->o_conn->c_txn_ops) ); assert( op->o_conn->c_txn == CONN_TXN_SETTLE ); op->o_conn->c_txn = CONN_TXN_INACTIVE; op->o_conn->c_txn_backend = NULL; done: /* release connection lock */ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); return rc; }
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; }