]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#7080 Postread control support for back-ldif/config
authorOndřej Kuzník <ondra@mistotebe.net>
Wed, 12 May 2021 10:04:08 +0000 (11:04 +0100)
committerQuanah Gibson-Mount <quanah@openldap.org>
Sun, 27 Jun 2021 17:39:46 +0000 (17:39 +0000)
servers/slapd/back-ldif/ldif.c
servers/slapd/bconfig.c

index 0def1980e73bb8c1fb6b3a6f8736b9e38b365cac..184bb5dee52e3b9b9ef38d83b9a1331101a3e66c 100644 (file)
@@ -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;
index b019554a034f7ba2d0fac719d6775b2940457133..446d2a9769c72063a3fabf538f451bfb4b32a7cc 100644 (file)
@@ -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
        };