]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/modify.c
ITS#2368 - fix deleting key from range IDL
[openldap] / servers / slapd / modify.c
index cf06590296596a615b186e4bd5e33d248839af0f..1d3c7b325ff97b4b7e77bd46dcfd3a418d15838b 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include "portable.h"
-#include "slapi_common.h"
 
 #include <stdio.h>
 
 #include <ac/string.h>
 #include <ac/time.h>
 
-#include "lutil.h"
-
 #include "ldap_pvt.h"
 #include "slap.h"
+#ifdef LDAP_SLAPI
 #include "slapi.h"
+#endif
+#include "lutil.h"
 
-#ifdef LDAP_SLAPI
-static LDAPMod **Modifications2LDAPMods (Modifications *modlist);
-static void FreeLDAPMods (LDAPMod **);
-#endif /* LDAP_SLAPI */
 
 int
 do_modify(
@@ -48,17 +44,17 @@ do_modify(
        ber_len_t       len;
        Modifications   *modlist = NULL;
        Modifications   **modtail = &modlist;
-#ifdef LDAP_SLAPI
-       LDAPMod         **modv = NULL;
-#endif
 #ifdef LDAP_DEBUG
        Modifications *tmp;
+#endif
+#ifdef LDAP_SLAPI
+       LDAPMod         **modv = NULL;
+       Slapi_PBlock *pb = op->o_pb;
 #endif
        Backend         *be;
        int rc;
        const char      *text;
        int manageDSAit;
-       Slapi_PBlock *pb = op->o_pb;
 
 #ifdef NEW_LOGGING
        LDAP_LOG( OPERATION, ENTRY, "do_modify: enter\n", 0, 0, 0 );
@@ -113,9 +109,12 @@ do_modify(
                ber_int_t mop;
                Modifications tmp, *mod;
 
+#ifdef SLAP_NVALUES
+               tmp.sml_nvalues = NULL;
+#endif
 
                if ( ber_scanf( op->o_ber, "{i{m[W]}}", &mop,
-                   &tmp.sml_type, &tmp.sml_bvalues )
+                   &tmp.sml_type, &tmp.sml_values )
                    == LBER_ERROR )
                {
                        send_ldap_disconnect( conn, op,
@@ -127,14 +126,17 @@ do_modify(
                mod = (Modifications *) ch_malloc( sizeof(Modifications) );
                mod->sml_op = mop;
                mod->sml_type = tmp.sml_type;
-               mod->sml_bvalues = tmp.sml_bvalues;
+               mod->sml_values = tmp.sml_values;
+#ifdef SLAP_NVALUES
+               mod->sml_nvalues = NULL;
+#endif
                mod->sml_desc = NULL;
-               mod->sml_next =NULL;
+               mod->sml_next = NULL;
                *modtail = mod;
 
                switch( mop ) {
                case LDAP_MOD_ADD:
-                       if ( mod->sml_bvalues == NULL ) {
+                       if ( mod->sml_values == NULL ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG( OPERATION, ERR, 
                                        "do_modify: modify/add operation (%ld) requires values\n",
@@ -243,11 +245,11 @@ do_modify(
                        "add" : (tmp->sml_op == LDAP_MOD_DELETE ?
                        "delete" : "replace"), tmp->sml_type.bv_val, 0 );
 
-               if ( tmp->sml_bvalues == NULL ) {
+               if ( tmp->sml_values == NULL ) {
                        LDAP_LOG( OPERATION, DETAIL1, "\t\tno values", 0, 0, 0 );
-               } else if ( tmp->sml_bvalues[0].bv_val == NULL ) {
+               } else if ( tmp->sml_values[0].bv_val == NULL ) {
                        LDAP_LOG( OPERATION, DETAIL1, "\t\tzero values", 0, 0, 0 );
-               } else if ( tmp->sml_bvalues[1].bv_val == NULL ) {
+               } else if ( tmp->sml_values[1].bv_val == NULL ) {
                        LDAP_LOG( OPERATION, DETAIL1, "\t\tone value", 0, 0, 0 );
                } else {
                        LDAP_LOG( OPERATION, DETAIL1, "\t\tmultiple values", 0, 0, 0 );
@@ -259,22 +261,21 @@ do_modify(
                                ? "add" : (tmp->sml_op == LDAP_MOD_DELETE
                                        ? "delete" : "replace"), tmp->sml_type.bv_val, 0 );
 
-               if ( tmp->sml_bvalues == NULL ) {
+               if ( tmp->sml_values == NULL ) {
                        Debug( LDAP_DEBUG_ARGS, "%s\n",
                           "\t\tno values", NULL, NULL );
-               } else if ( tmp->sml_bvalues[0].bv_val == NULL ) {
+               } else if ( tmp->sml_values[0].bv_val == NULL ) {
                        Debug( LDAP_DEBUG_ARGS, "%s\n",
                           "\t\tzero values", NULL, NULL );
-               } else if ( tmp->sml_bvalues[1].bv_val == NULL ) {
+               } else if ( tmp->sml_values[1].bv_val == NULL ) {
                        Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n",
-                          "\t\tone value", (long) tmp->sml_bvalues[0].bv_len, NULL );
+                          "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL );
                } else {
                        Debug( LDAP_DEBUG_ARGS, "%s\n",
                           "\t\tmultiple values", NULL, NULL );
                }
 #endif
        }
-#endif
 
        if ( StatslogTest( LDAP_DEBUG_STATS ) ) {
                char abuf[BUFSIZ/2], *ptr = abuf;
@@ -302,6 +303,7 @@ do_modify(
                                op->o_connid, op->o_opid, abuf, 0, 0 );
                }
        }
+#endif /* LDAP_DEBUG */
 
        manageDSAit = get_manageDSAit( op );
 
@@ -335,16 +337,13 @@ do_modify(
                goto cleanup;
        }
 
-       /* deref suffix alias if appropriate */
-       suffix_alias( be, &ndn );
-
 #if defined( LDAP_SLAPI )
-       slapi_backend_set_pb( pb, be );
-       slapi_connection_set_pb( pb, conn );
-       slapi_operation_set_pb( pb, op );
+       slapi_x_backend_set_pb( pb, be );
+       slapi_x_connection_set_pb( pb, conn );
+       slapi_x_operation_set_pb( pb, op );
        slapi_pblock_set( pb, SLAPI_MODIFY_TARGET, (void *)dn.bv_val );
-       slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) );
-       modv = Modifications2LDAPMods( modlist );
+       slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)manageDSAit );
+       modv = slapi_x_modifications2ldapmods( &modlist );
        slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)modv );
 
        rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_MODIFY_FN, pb );
@@ -360,10 +359,24 @@ do_modify(
                Debug(LDAP_DEBUG_TRACE, "do_modify: modify preoperation plugin failed.\n",
                                0, 0, 0);
 #endif
-               if ( slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void *)&rc ) != 0)
-                       rc = LDAP_OPERATIONS_ERROR;
+               if ( slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void *)&rc ) != 0) {
+                       rc = LDAP_OTHER;
+               }
+               ldap_mods_free( modv, 1 );
+               modv = NULL;
                goto cleanup;
        }
+
+       /*
+        * It's possible that the preoperation plugin changed the
+        * modification array, so we need to convert it back to
+        * a Modification list.
+        *
+        * Calling slapi_x_modifications2ldapmods() destroyed modlist so
+        * we don't need to free it.
+        */
+       slapi_pblock_get( pb, SLAPI_MODIFY_MODS, (void **)&modv );
+       modlist = slapi_x_ldapmods2modifications( modv );
 #endif /* defined( LDAP_SLAPI ) */
 
        /*
@@ -459,8 +472,8 @@ cleanup:
        free( pdn.bv_val );
        free( ndn.bv_val );
        if ( modlist != NULL ) slap_mods_free( modlist );
-#ifdef LDAP_SLAPI
-       if ( modv != NULL ) FreeLDAPMods( modv );
+#if defined( LDAP_SLAPI )
+       if ( modv != NULL ) slapi_x_free_ldapmods( modv );
 #endif
        return rc;
 }
@@ -533,7 +546,7 @@ int slap_mods_check(
                }
 
                if ( is_at_obsolete( ad->ad_type ) &&
-                       ( ml->sml_op == LDAP_MOD_ADD || ml->sml_bvalues != NULL ) )
+                       ( ml->sml_op == LDAP_MOD_ADD || ml->sml_values != NULL ) )
                {
                        /*
                         * attribute is obsolete,
@@ -549,7 +562,7 @@ int slap_mods_check(
                /*
                 * check values
                 */
-               if( ml->sml_bvalues != NULL ) {
+               if( ml->sml_values != NULL ) {
                        ber_len_t nvals;
                        slap_syntax_validate_func *validate =
                                ad->ad_type->sat_syntax->ssyn_validate;
@@ -570,14 +583,14 @@ int slap_mods_check(
                         * check that each value is valid per syntax
                         *      and pretty if appropriate
                         */
-                       for( nvals = 0; ml->sml_bvalues[nvals].bv_val; nvals++ ) {
+                       for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {
                                struct berval pval;
                                if( pretty ) {
                                        rc = pretty( ad->ad_type->sat_syntax,
-                                               &ml->sml_bvalues[nvals], &pval );
+                                               &ml->sml_values[nvals], &pval );
                                } else {
                                        rc = validate( ad->ad_type->sat_syntax,
-                                               &ml->sml_bvalues[nvals] );
+                                               &ml->sml_values[nvals] );
                                }
 
                                if( rc != 0 ) {
@@ -589,8 +602,8 @@ int slap_mods_check(
                                }
 
                                if( pretty ) {
-                                       ber_memfree( ml->sml_bvalues[nvals].bv_val );
-                                       ml->sml_bvalues[nvals] = pval;
+                                       ber_memfree( ml->sml_values[nvals].bv_val );
+                                       ml->sml_values[nvals] = pval;
                                }
                        }
 
@@ -598,15 +611,48 @@ int slap_mods_check(
                         * a rough single value check... an additional check is needed
                         * to catch add of single value to existing single valued attribute
                         */
-                       if( ( ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE )
+                       if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE)
                                && nvals > 1 && is_at_single_value( ad->ad_type ))
                        {
                                snprintf( textbuf, textlen,
-                                       "%s: multiple value provided",
+                                       "%s: multiple values provided",
                                        ml->sml_type.bv_val );
                                *text = textbuf;
                                return LDAP_CONSTRAINT_VIOLATION;
                        }
+
+#ifdef SLAP_NVALUES
+                       if( nvals && ad->ad_type->sat_equality &&
+                               ad->ad_type->sat_equality->smr_normalize )
+                       {
+                               ml->sml_nvalues = ch_malloc( (nvals+1)*sizeof(struct berval) );
+                               for( nvals = 0; ml->sml_values[nvals].bv_val; nvals++ ) {
+                                       rc = ad->ad_type->sat_equality->smr_normalize(
+                                               0,
+                                               ad->ad_type->sat_syntax,
+                                               ad->ad_type->sat_equality,
+                                               &ml->sml_values[nvals], &ml->sml_nvalues[nvals] );
+                                       if( rc ) {
+#ifdef NEW_LOGGING
+                                               LDAP_LOG( OPERATION, DETAIL1,
+                                                       "str2entry:  NULL (ssyn_normalize %d)\n",
+                                                       rc, 0, 0 );
+#else
+                                               Debug( LDAP_DEBUG_ANY,
+                                                       "<= str2entry NULL (ssyn_normalize %d)\n",
+                                                       rc, 0, 0 );
+#endif
+                                               snprintf( textbuf, textlen,
+                                                       "%s: value #%ld normalization failed",
+                                                       ml->sml_type.bv_val, (long) nvals );
+                                               *text = textbuf;
+                                               return rc;
+                                       }
+                               }
+                               ml->sml_nvalues[nvals].bv_val = NULL;
+                               ml->sml_nvalues[nvals].bv_len = 0;
+                       }
+#endif
                }
        }
 
@@ -622,6 +668,9 @@ int slap_mods_opattrs(
        char *textbuf, size_t textlen )
 {
        struct berval name, timestamp, csn;
+#ifdef SLAP_NVALUES
+       struct berval nname;
+#endif
        char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
        char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
        Modifications *mod;
@@ -650,8 +699,14 @@ int slap_mods_opattrs(
                if( op->o_dn.bv_len == 0 ) {
                        name.bv_val = SLAPD_ANONYMOUS;
                        name.bv_len = sizeof(SLAPD_ANONYMOUS)-1;
+#ifdef SLAP_NVALUES
+                       nname = name;
+#endif
                } else {
                        name = op->o_dn;
+#ifdef SLAP_NVALUES
+                       nname = op->o_ndn;
+#endif
                }
        }
 
@@ -669,10 +724,20 @@ int slap_mods_opattrs(
                        mod->sml_op = mop;
                        mod->sml_type.bv_val = NULL;
                        mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
-                       mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-                       ber_dupbv( &mod->sml_bvalues[0], &tmpval );
-                       mod->sml_bvalues[1].bv_val = NULL;
-                       assert( mod->sml_bvalues[0].bv_val );
+                       mod->sml_values =
+                               (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+                       ber_dupbv( &mod->sml_values[0], &tmpval );
+                       mod->sml_values[1].bv_len = 0;
+                       mod->sml_values[1].bv_val = NULL;
+                       assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+                       mod->sml_nvalues =
+                               (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+                       ber_dupbv( &mod->sml_nvalues[0], &tmpval );
+                       mod->sml_nvalues[1].bv_len = 0;
+                       mod->sml_nvalues[1].bv_val = NULL;
+                       assert( mod->sml_nvalues[0].bv_val );
+#endif
                        *modtail = mod;
                        modtail = &mod->sml_next;
                }
@@ -687,10 +752,15 @@ int slap_mods_opattrs(
                        mod->sml_op = mop;
                        mod->sml_type.bv_val = NULL;
                        mod->sml_desc = slap_schema.si_ad_entryUUID;
-                       mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-                       ber_dupbv( &mod->sml_bvalues[0], &tmpval );
-                       mod->sml_bvalues[1].bv_val = NULL;
-                       assert( mod->sml_bvalues[0].bv_val );
+                       mod->sml_values =
+                               (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+                       ber_dupbv( &mod->sml_values[0], &tmpval );
+                       mod->sml_values[1].bv_len = 0;
+                       mod->sml_values[1].bv_val = NULL;
+                       assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+                       mod->sml_nvalues = NULL;
+#endif
                        *modtail = mod;
                        modtail = &mod->sml_next;
 
@@ -698,10 +768,19 @@ int slap_mods_opattrs(
                        mod->sml_op = mop;
                        mod->sml_type.bv_val = NULL;
                        mod->sml_desc = slap_schema.si_ad_creatorsName;
-                       mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-                       ber_dupbv( &mod->sml_bvalues[0], &name );
-                       mod->sml_bvalues[1].bv_val = NULL;
-                       assert( mod->sml_bvalues[0].bv_val );
+                       mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+                       ber_dupbv( &mod->sml_values[0], &name );
+                       mod->sml_values[1].bv_len = 0;
+                       mod->sml_values[1].bv_val = NULL;
+                       assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+                       mod->sml_nvalues =
+                               (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+                       ber_dupbv( &mod->sml_nvalues[0], &nname );
+                       mod->sml_nvalues[1].bv_len = 0;
+                       mod->sml_nvalues[1].bv_val = NULL;
+                       assert( mod->sml_nvalues[0].bv_val );
+#endif
                        *modtail = mod;
                        modtail = &mod->sml_next;
 
@@ -709,10 +788,14 @@ int slap_mods_opattrs(
                        mod->sml_op = mop;
                        mod->sml_type.bv_val = NULL;
                        mod->sml_desc = slap_schema.si_ad_createTimestamp;
-                       mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-                       ber_dupbv( &mod->sml_bvalues[0], &timestamp );
-                       mod->sml_bvalues[1].bv_val = NULL;
-                       assert( mod->sml_bvalues[0].bv_val );
+                       mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+                       ber_dupbv( &mod->sml_values[0], &timestamp );
+                       mod->sml_values[1].bv_len = 0;
+                       mod->sml_values[1].bv_val = NULL;
+                       assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+                       mod->sml_nvalues = NULL;
+#endif
                        *modtail = mod;
                        modtail = &mod->sml_next;
                }
@@ -723,10 +806,14 @@ int slap_mods_opattrs(
                mod->sml_op = mop;
                mod->sml_type.bv_val = NULL;
                mod->sml_desc = slap_schema.si_ad_entryCSN;
-               mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-               ber_dupbv( &mod->sml_bvalues[0], &csn );
-               mod->sml_bvalues[1].bv_val = NULL;
-               assert( mod->sml_bvalues[0].bv_val );
+               mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+               ber_dupbv( &mod->sml_values[0], &csn );
+               mod->sml_values[1].bv_len = 0;
+               mod->sml_values[1].bv_val = NULL;
+               assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+               mod->sml_nvalues = NULL;
+#endif
                *modtail = mod;
                modtail = &mod->sml_next;
 
@@ -734,10 +821,19 @@ int slap_mods_opattrs(
                mod->sml_op = mop;
                mod->sml_type.bv_val = NULL;
                mod->sml_desc = slap_schema.si_ad_modifiersName;
-               mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-               ber_dupbv( &mod->sml_bvalues[0], &name );
-               mod->sml_bvalues[1].bv_val = NULL;
-               assert( mod->sml_bvalues[0].bv_val );
+               mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+               ber_dupbv( &mod->sml_values[0], &name );
+               mod->sml_values[1].bv_len = 0;
+               mod->sml_values[1].bv_val = NULL;
+               assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+               mod->sml_nvalues =
+                       (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+               ber_dupbv( &mod->sml_nvalues[0], &nname );
+               mod->sml_nvalues[1].bv_len = 0;
+               mod->sml_nvalues[1].bv_val = NULL;
+               assert( mod->sml_nvalues[0].bv_val );
+#endif
                *modtail = mod;
                modtail = &mod->sml_next;
 
@@ -745,10 +841,14 @@ int slap_mods_opattrs(
                mod->sml_op = mop;
                mod->sml_type.bv_val = NULL;
                mod->sml_desc = slap_schema.si_ad_modifyTimestamp;
-               mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
-               ber_dupbv( &mod->sml_bvalues[0], &timestamp );
-               mod->sml_bvalues[1].bv_val = NULL;
-               assert( mod->sml_bvalues[0].bv_val );
+               mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
+               ber_dupbv( &mod->sml_values[0], &timestamp );
+               mod->sml_values[1].bv_len = 0;
+               mod->sml_values[1].bv_val = NULL;
+               assert( mod->sml_values[0].bv_val );
+#ifdef SLAP_NVALUES
+               mod->sml_nvalues = NULL;
+#endif
                *modtail = mod;
                modtail = &mod->sml_next;
        }
@@ -757,71 +857,3 @@ int slap_mods_opattrs(
        return LDAP_SUCCESS;
 }
 
-#ifdef LDAP_SLAPI
-/*
- * Synthesise an LDAPMod array from a Modifications list to pass
- * to SLAPI.
- */
-static LDAPMod **Modifications2LDAPMods(Modifications *modlist)
-{
-       LDAPMod *mods, **modv;
-       int i, j;
-       Modifications *ml;
-
-       /* based on back-ldap/modify.c */
-       for( i = 0, ml = modlist; ml != NULL; i++, ml = ml->sml_next )
-               ;
-
-       mods = (LDAPMod *)ch_malloc( i * sizeof(LDAPMod) );
-       if (mods == NULL) {
-               return NULL;
-       }
-
-       modv = (LDAPMod **)ch_malloc( (i + 1) * sizeof(LDAPMod *) );
-       if (modv == NULL) {
-               ch_free(mods);
-               return NULL;
-       }
-
-       for( i = 0, ml = modlist; ml != NULL; ml = ml->sml_next ) {
-               if ( ml->sml_desc->ad_type->sat_no_user_mod ) {
-                       continue;
-               }
-               modv[i] = &mods[i];
-               mods[i].mod_op = ml->sml_op | LDAP_MOD_BVALUES;
-               mods[i].mod_type = ml->sml_desc->ad_cname.bv_val;
-               if (ml->sml_bvalues != NULL) {
-                       for( j = 0; ml->sml_bvalues[j].bv_val != NULL; j++ )
-                               ;
-                       mods[i].mod_bvalues = (struct berval **)ch_malloc( (j + 1) *
-                               sizeof(struct berval *) );
-                       for( j = 0; ml->sml_bvalues[j].bv_val != NULL; j++ )
-                               mods[i].mod_bvalues[j] = &ml->sml_bvalues[j];
-               } else {
-                       mods[i].mod_bvalues = NULL;
-               }
-               i++;
-       }
-       modv[i] = NULL;
-
-       return modv;
-}
-
-/*
- * Free a contiguous block of LDAP modifications.
- */
-static void FreeLDAPMods(LDAPMod **modv)
-{
-       int i;
-       LDAPMod *mods;
-
-       mods = modv[0];
-
-       for( i = 0; modv[i] != NULL; i++ ) {
-               ch_free( modv[i]->mod_bvalues );
-       }
-       ch_free( mods );
-       ch_free( modv );
-}
-#endif /* LDAP_SLAPI */
-