From: Ondřej Kuzník Date: Wed, 12 May 2021 10:04:08 +0000 (+0100) Subject: ITS#7080 Postread control support for back-ldif/config X-Git-Tag: OPENLDAP_REL_ENG_2_6_0~176 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2e9cb1acd007b400381a06e82777c71c2e32ff0;p=thirdparty%2Fopenldap.git ITS#7080 Postread control support for back-ldif/config --- diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index 0def1980e7..184bb5dee5 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -1399,6 +1399,12 @@ ldif_back_add( Operation *op, SlapReply *rs ) char textbuf[SLAP_TEXT_BUFLEN]; int rc; + LDAPControl **postread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn ); rc = entry_schema_check( op, e, NULL, 0, 1, NULL, @@ -1413,6 +1419,26 @@ ldif_back_add( Operation *op, SlapReply *rs ) ldap_pvt_thread_mutex_lock( &li->li_modop_mutex ); rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text ); + + if ( rc == LDAP_SUCCESS && op->o_postread ) { + if ( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, e, + &slap_post_read_bv, postread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "ldif_back_add: " + "post-read failed \"%s\"\n", + e->e_name.bv_val ); + if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + rc = rs->sr_err; + } + } + } + if ( rc == LDAP_SUCCESS ) { ldap_pvt_thread_rdwr_wlock( &li->li_rdwr ); rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text ); @@ -1427,6 +1453,7 @@ ldif_back_add( Operation *op, SlapReply *rs ) send_res: rs->sr_err = rc; + if ( num_ctrls ) rs->sr_ctrls = ctrls; Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n", rc, rs->sr_text ? rs->sr_text : "" ); send_ldap_result( op, rs ); @@ -1445,13 +1472,59 @@ ldif_back_modify( Operation *op, SlapReply *rs ) char textbuf[SLAP_TEXT_BUFLEN]; int rc; + LDAPControl **preread_ctrl = NULL; + LDAPControl **postread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + slap_mods_opattrs( op, &op->orm_modlist, 1 ); ldap_pvt_thread_mutex_lock( &li->li_modop_mutex ); rc = get_entry( op, &entry, &path, &rs->sr_text ); if ( rc == LDAP_SUCCESS ) { + if ( op->o_preread ) { + if ( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, entry, + &slap_pre_read_bv, preread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "ldif_back_modify: " + "pre-read failed \"%s\"\n", + entry->e_name.bv_val ); + if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + rc = rs->sr_err; + } + } + } + rc = apply_modify_to_entry( entry, modlst, op, rs, textbuf ); + + if ( rc == LDAP_SUCCESS && op->o_postread ) { + if ( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, entry, + &slap_post_read_bv, postread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "ldif_back_modify: " + "post-read failed \"%s\"\n", + entry->e_name.bv_val ); + if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + rc = rs->sr_err; + } + } + } + if ( rc == LDAP_SUCCESS ) { ldap_pvt_thread_rdwr_wlock( &li->li_rdwr ); rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text ); @@ -1465,6 +1538,7 @@ ldif_back_modify( Operation *op, SlapReply *rs ) ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex ); rs->sr_err = rc; + if ( num_ctrls ) rs->sr_ctrls = ctrls; send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); rs->sr_text = NULL; /* remove possible pointer to textbuf */ @@ -1479,6 +1553,12 @@ ldif_back_delete( Operation *op, SlapReply *rs ) int rc = LDAP_SUCCESS; char ebuf[128]; + LDAPControl **preread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + if ( BER_BVISEMPTY( &op->o_csn )) { struct berval csn; char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE]; @@ -1517,6 +1597,30 @@ ldif_back_delete( Operation *op, SlapReply *rs ) } } + /* pre-read */ + if ( op->o_preread ) { + Entry *e = NULL; + + if ( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + rc = get_entry( op, &e, &path, &rs->sr_text ); + if ( rc == LDAP_SUCCESS && slap_read_controls( op, rs, e, + &slap_pre_read_bv, preread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "ldif_back_delete: " + "pre-read failed \"%s\"\n", + e->e_name.bv_val ); + if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + rc = rs->sr_err; + } + } + entry_free( e ); + } + if ( rc == LDAP_SUCCESS ) { dir2ldif_name( path ); if ( unlink( path.bv_val ) < 0 ) { @@ -1538,6 +1642,7 @@ ldif_back_delete( Operation *op, SlapReply *rs ) ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr ); ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex ); rs->sr_err = rc; + if ( num_ctrls ) rs->sr_ctrls = ctrls; send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); return rs->sr_err; @@ -1987,6 +2092,8 @@ ldif_back_initialize( BackendInfo *bi ) { static char *controls[] = { LDAP_CONTROL_MANAGEDSAIT, + LDAP_CONTROL_PRE_READ, + LDAP_CONTROL_POST_READ, NULL }; int rc; diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index b019554a03..446d2a9769 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -5945,6 +5945,12 @@ config_back_add( Operation *op, SlapReply *rs ) int renumber, dopause = 1; ConfigArgs ca; + LDAPControl **postread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry, NULL, ACL_WADD, NULL )) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; @@ -6031,6 +6037,22 @@ config_back_add( Operation *op, SlapReply *rs ) op->o_callback = scp; op->o_dn = dn; op->o_ndn = ndn; + } else if ( op->o_postread ) { + if ( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, op->ora_e, + &slap_post_read_bv, postread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "ldif_back_modify: " + "post-read failed \"%s\"\n", + op->ora_e->e_name.bv_val ); + if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + } + } } out2:; @@ -6433,6 +6455,13 @@ config_back_modify( Operation *op, SlapReply *rs ) AttributeDescription *rad = NULL; int do_pause = 1; + LDAPControl **preread_ctrl = NULL; + LDAPControl **postread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + cfb = (CfBackInfo *)op->o_bd->be_private; ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); @@ -6474,6 +6503,26 @@ config_back_modify( Operation *op, SlapReply *rs ) slap_mods_opattrs( op, &op->orm_modlist, 1 ); + /* If we have a backend, it will handle the control */ + if ( !cfb->cb_use_ldif && op->o_preread ) { + if ( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, ce->ce_entry, + &slap_pre_read_bv, preread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "config_back_modify: " + "pre-read failed \"%s\"\n", + ce->ce_entry->e_name.bv_val ); + if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + goto out; + } + } + } + if ( do_pause ) { if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; @@ -6511,11 +6560,24 @@ config_back_modify( Operation *op, SlapReply *rs ) op->o_callback = scp; op->o_dn = dn; op->o_ndn = ndn; + } else if ( op->o_postread ) { + if ( postread_ctrl == NULL ) { + postread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, ce->ce_entry, + &slap_post_read_bv, postread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "config_back_modify: " + "post-read failed \"%s\"\n", + ce->ce_entry->e_name.bv_val ); + } } if ( do_pause ) slap_unpause_server(); out: + if ( num_ctrls ) rs->sr_ctrls = ctrls; send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); return rs->sr_err; @@ -6529,6 +6591,13 @@ config_back_modrdn( Operation *op, SlapReply *rs ) struct berval rdn; int ixold, ixnew, dopause = 1; + LDAPControl **preread_ctrl = NULL; + LDAPControl **postread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + cfb = (CfBackInfo *)op->o_bd->be_private; ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); @@ -6645,6 +6714,26 @@ config_back_modrdn( Operation *op, SlapReply *rs ) goto out; } + /* If we have a backend, it will handle the control */ + if ( !cfb->cb_use_ldif && op->o_preread ) { + if ( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, ce->ce_entry, + &slap_pre_read_bv, preread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "config_back_modrdn: " + "pre-read failed \"%s\"\n", + ce->ce_entry->e_name.bv_val ); + if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + goto out; + } + } + } + if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto out; @@ -6719,6 +6808,7 @@ config_back_modrdn( Operation *op, SlapReply *rs ) if ( dopause ) slap_unpause_server(); out: + if ( num_ctrls ) rs->sr_ctrls = ctrls; send_ldap_result( op, rs ); return rs->sr_err; } @@ -6731,8 +6821,34 @@ config_back_delete( Operation *op, SlapReply *rs ) CfEntryInfo *ce, *last, *ce2; int dopause = 1; + LDAPControl **preread_ctrl = NULL; + LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; + int num_ctrls = 0; + + ctrls[num_ctrls] = NULL; + cfb = (CfBackInfo *)op->o_bd->be_private; + /* If we have a backend, it will handle the control */ + if ( ce && !cfb->cb_use_ldif && op->o_preread ) { + if ( preread_ctrl == NULL ) { + preread_ctrl = &ctrls[num_ctrls++]; + ctrls[num_ctrls] = NULL; + } + if ( slap_read_controls( op, rs, ce->ce_entry, + &slap_pre_read_bv, preread_ctrl ) ) + { + Debug( LDAP_DEBUG_ANY, "config_back_delete: " + "pre-read failed \"%s\"\n", + ce->ce_entry->e_name.bv_val ); + if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + goto out; + } + } + } + ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); if ( !ce ) { if ( last ) @@ -6863,6 +6979,7 @@ config_back_delete( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_UNWILLING_TO_PERFORM; } out: + if ( num_ctrls ) rs->sr_ctrls = ctrls; #else rs->sr_err = LDAP_UNWILLING_TO_PERFORM; #endif /* SLAP_CONFIG_DELETE */ @@ -8022,6 +8139,8 @@ config_back_initialize( BackendInfo *bi ) const char *text; static char *controls[] = { LDAP_CONTROL_MANAGEDSAIT, + LDAP_CONTROL_PRE_READ, + LDAP_CONTROL_POST_READ, NULL };