int wt_hasSubordinates( Operation *op, Entry *e, int *hasSubordinates ) { struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; wt_ctx *wc = NULL; int rc; assert( e != NULL ); wc = wt_ctx_get(op, wi); if( !wc ){ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_compare) ": wt_ctx_get failed\n", 0, 0, 0 ); return LDAP_OTHER; } rc = wt_dn2id_has_children(op, wc->session, e->e_id); switch(rc){ case 0: *hasSubordinates = LDAP_COMPARE_TRUE; break; case WT_NOTFOUND: *hasSubordinates = LDAP_COMPARE_FALSE; rc = LDAP_SUCCESS; break; default: Debug(LDAP_DEBUG_ANY, "<=- " LDAP_XSTRING(wt_hasSubordinates) ": has_children failed: %s (%d)\n", wiredtiger_strerror(rc), rc, 0 ); rc = LDAP_OTHER; } return rc; }
int wt_compare( Operation *op, SlapReply *rs ) { struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; Entry *e = NULL; int manageDSAit = get_manageDSAit( op ); int rc; wt_ctx *wc = NULL; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_compare) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); wc = wt_ctx_get(op, wi); if( !wc ){ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_compare) ": wt_ctx_get failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } rs->sr_err = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e); switch( rs->sr_err ) { case 0: case WT_NOTFOUND: break; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rs->sr_err == WT_NOTFOUND ) { if ( 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_matched = ch_strdup( e->e_dn ); if ( is_entry_referral( e )) { BerVarray ref = get_entry_referrals( op, e ); rs->sr_ref = referral_rewrite( ref, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); } else { rs->sr_ref = NULL; } rs->sr_err = LDAP_REFERRAL; } wt_entry_return( e ); e = NULL; } else { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; } rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; send_ldap_result( op, rs ); goto done; } if (!manageDSAit && is_entry_referral( e ) ) { /* 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 { /* entry is a referral, don't allow compare */ rs->sr_ref = get_entry_referrals( op, e ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e->e_name.bv_val; } Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); send_ldap_result( op, rs ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; rs->sr_matched = NULL; goto done; } rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); return_results: send_ldap_result( op, rs ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: case LDAP_COMPARE_TRUE: rs->sr_err = LDAP_SUCCESS; break; } done: if ( e != NULL ) { wt_entry_return( e ); } return rs->sr_err; }
int wt_bind( Operation *op, SlapReply *rs ) { struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; WT_SESSION *session; wt_ctx *wc; int rc; Entry *e = NULL; Attribute *a; AttributeDescription *password = slap_schema.si_ad_userPassword; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_bind) ": dn: %s\n", op->o_req_dn.bv_val, 0, 0); /* allow noauth binds */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err = LDAP_SUCCESS; default: /* give the database a chance */ /* NOTE: this behavior departs from that of other backends, * since the others, in case of password checking failure * do not give the database a chance. If an entry with * rootdn's name does not exist in the database the result * will be the same. See ITS#4962 for discussion. */ break; } wc = wt_ctx_get(op, wi); if( !wc ){ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_bind) ": wt_ctx_get failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } /* get entry */ rc = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e); switch( rc ) { case 0: break; case WT_NOTFOUND: rs->sr_err = LDAP_INVALID_CREDENTIALS; send_ldap_result( op, rs ); return rs->sr_err; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } ber_dupbv( &op->oq_bind.rb_edn, &e->e_name ); /* check for deleted */ if ( is_entry_subentry( e ) ) { /* entry is an subentry, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_alias( e ) ) { /* entry is an alias, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_referral( e ) ) { Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } switch ( op->oq_bind.rb_method ) { case LDAP_AUTH_SIMPLE: a = attr_find( e->e_attrs, password ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { /* failure; stop front end from sending result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } rs->sr_err = 0; break; default: rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; rs->sr_text = "authentication method not supported"; } done: /* free entry */ if (e) { wt_entry_return(e); } if (rs->sr_err) { send_ldap_result( op, rs ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } return rs->sr_err; }
int wt_modify( Operation *op, SlapReply *rs ) { struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; wt_ctx *wc = NULL; Entry *e = NULL; int manageDSAit = get_manageDSAit( op ); char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; Entry dummy = {0}; LDAPControl **preread_ctrl = NULL; LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; int rc; Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(wt_modify) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); #ifdef LDAP_X_TXN if( op->o_txnSpec && txn_preop( op, rs )) return rs->sr_err; #endif ctrls[num_ctrls] = NULL; wc = wt_ctx_get(op, wi); if( !wc ){ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_add) ": wt_ctx_get failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } /* Don't touch the opattrs, if this is a contextCSN update * initiated from updatedn */ if ( !be_isupdate(op) || !op->orm_modlist || op->orm_modlist->sml_next || op->orm_modlist->sml_desc != slap_schema.si_ad_contextCSN ) { slap_mods_opattrs( op, &op->orm_modlist, 1 ); } /* get entry */ rc = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e); switch( rc ) { case 0: break; case WT_NOTFOUND: Debug( LDAP_DEBUG_ARGS, "<== " LDAP_XSTRING(wt_delete) ": no such object %s\n", op->o_req_dn.bv_val, 0, 0); /* TODO: lookup referrals */ rs->sr_err = LDAP_NO_SUCH_OBJECT; goto return_results; default: Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_modify) ": wt_dn2entry failed (%d)\n", rc, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( !manageDSAit && is_entry_referral( e ) ) { /* entry is a referral, don't allow modify */ rs->sr_ref = get_entry_referrals( op, e ); Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_modify) ": entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e->e_name.bv_val; rs->sr_flags = REP_REF_MUSTBEFREED; send_ldap_result( op, rs ); rs->sr_matched = NULL; goto done; } if ( get_assert( op ) && ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } if( op->o_preread ) { if( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if ( slap_read_controls( op, rs, e, &slap_pre_read_bv, preread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(wt_modify) ": 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 return_results; } } } /* begin transaction */ rc = wc->session->begin_transaction(wc->session, NULL); if( rc ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_add) ": begin_transaction failed: %s (%d)\n", wiredtiger_strerror(rc), rc, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "begin_transaction failed"; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_modify) ": session id: %p\n", wc->session, 0, 0 ); /* Modify the entry */ dummy = *e; rs->sr_err = wt_modify_internal( op, wc, op->orm_modlist, &dummy, &rs->sr_text, textbuf, textlen ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_modify) ": modify failed (%d)\n", rs->sr_err, 0, 0 ); /* Only free attrs if they were dup'd. */ if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL; goto return_results; } /* change the entry itself */ rs->sr_err = wt_id2entry_update( op, wc->session, &dummy ); if ( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_modify) ": id2entry update failed " "(%d)\n", rs->sr_err, 0, 0 ); if ( rs->sr_err == LDAP_ADMINLIMIT_EXCEEDED ) { rs->sr_text = "entry too big"; } else { rs->sr_err = LDAP_OTHER; rs->sr_text = "entry update failed"; } goto return_results; } if( op->o_noop ) { wc->session->rollback_transaction(wc->session, NULL); rs->sr_err = LDAP_X_NO_OPERATION; goto return_results; } /* Only free attrs if they were dup'd. */ if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL; rc = wc->session->commit_transaction(wc->session, NULL); if( rc ) { Debug( LDAP_DEBUG_TRACE, "<== " LDAP_XSTRING(wt_modify) ": commit failed: %s (%d)\n", wiredtiger_strerror(rc), rc, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "commit failed"; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_modify) ": updated%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", dummy.e_id, op->o_req_dn.bv_val ); if( op->o_postread ) { if( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &dummy, &slap_post_read_bv, postread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(wt_modify) ": 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 return_results; } } } if( num_ctrls ) rs->sr_ctrls = ctrls; rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; return_results: if( dummy.e_attrs ) { attrs_free( dummy.e_attrs ); } send_ldap_result( op, rs ); done: slap_graduate_commit_csn( op ); if( e != NULL ) { wt_entry_return( e ); } 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 ); } rs->sr_text = NULL; return rs->sr_err; }