]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/rwm.c
check for ee == NULL
[openldap] / servers / slapd / overlays / rwm.c
index ce1e2ff0e1086c1976c1234d0298603d6e4e16a5..ed9fbfa9bb20377093a0a18dfda2fcd3403357d1 100644 (file)
@@ -39,7 +39,7 @@ typedef struct rwm_op_state {
 } rwm_op_state;
 
 static int
-rwm_db_destroy( BackendDB *be );
+rwm_db_destroy( BackendDB *be, ConfigReply *cr );
 
 typedef struct rwm_op_cb {
        slap_callback cb;
@@ -226,9 +226,7 @@ rwm_op_add( Operation *op, SlapReply *rs )
                {
                        int             j, last;
 
-                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[ last ] ); last++ )
-                                       /* count values */ ;
-                       last--;
+                       last = (*ap)->a_numvals - 1;
                        for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
                                struct ldapmapping      *mapping = NULL;
 
@@ -245,6 +243,7 @@ rwm_op_add( Operation *op, SlapReply *rs )
                                                        (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
                                                }
                                                BER_BVZERO( &(*ap)->a_vals[ last ] );
+                                               (*ap)->a_numvals--;
                                                last--;
                                                j--;
                                        }
@@ -502,16 +501,12 @@ rwm_op_modify( Operation *op, SlapReply *rs )
        }
 
        isupdate = be_shadow_update( op );
-       for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
+       for ( mlp = &op->orm_modlist; *mlp; ) {
                int                     is_oc = 0;
-               Modifications           *ml;
+               Modifications           *ml = *mlp;
                struct ldapmapping      *mapping = NULL;
 
-               /* duplicate the modlist */
-               ml = ch_malloc( sizeof( Modifications ));
-               *ml = **mlp;
-               *mlp = ml;
-
+               /* ml points to a temporary mod until needs duplication */
                if ( ml->sml_desc == slap_schema.si_ad_objectClass 
                                || ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
                {
@@ -519,6 +514,15 @@ rwm_op_modify( Operation *op, SlapReply *rs )
 
                } else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
                {
+                       ml = ch_malloc( sizeof( Modifications ) );
+                       *ml = **mlp;
+                       if ( (*mlp)->sml_values ) {
+                               ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
+                               if ( (*mlp)->sml_nvalues ) {
+                                       ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
+                               }
+                       }
+                       *mlp = ml;
                        goto next_mod;
 
                } else {
@@ -533,6 +537,11 @@ rwm_op_modify( Operation *op, SlapReply *rs )
                        }
                }
 
+               /* duplicate the modlist */
+               ml = ch_malloc( sizeof( Modifications ));
+               *ml = **mlp;
+               *mlp = ml;
+
                if ( ml->sml_values != NULL ) {
                        int i, num;
                        struct berval *bva;
@@ -835,8 +844,11 @@ rwm_exop_passwd( Operation *op, SlapReply *rs )
        }
 
        if ( !BER_BVISNULL( &id ) ) {
+               char idNul = id.bv_val[id.bv_len];
+               id.bv_val[id.bv_len] = '\0';
                rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
                                &op->o_req_ndn, op->o_tmpmemctx );
+               id.bv_val[id.bv_len] = idNul;
                if ( rs->sr_err != LDAP_SUCCESS ) {
                        rs->sr_text = "Invalid DN";
                        return rs->sr_err;
@@ -986,6 +998,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
        int                     rc;
        Attribute               **ap;
        int                     isupdate;
+       int                     check_duplicate_attrs = 0;
 
        /*
         * Rewrite the dn attrs, if needed
@@ -1010,7 +1023,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
        for ( ap = a_first; *ap; ) {
                struct ldapmapping      *mapping = NULL;
                int                     drop_missing;
-               int                     last=-1;
+               int                     last = -1;
                Attribute               *a;
 
                if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
@@ -1042,10 +1055,9 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                                        mapping->m_dst_ad->ad_type->sat_equality &&
                                        mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
                                {
-                                       int i=0;
-                                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
-                                               /* just count */ ;
+                                       int i = 0;
 
+                                       last = (*ap)->a_numvals;
                                        if ( last )
                                        {
                                                (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
@@ -1070,8 +1082,12 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                                                BER_BVZERO( &(*ap)->a_nvals[i] );
                                        }
                                }
+
                                /* rewrite the attribute description */
                                (*ap)->a_desc = mapping->m_dst_ad;
+
+                               /* will need to check for duplicate attrs */
+                               check_duplicate_attrs++;
                        }
                }
 
@@ -1090,8 +1106,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                }
 
                if ( last == -1 ) { /* not yet counted */ 
-                       for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
-                               /* just count */ ;
+                       last = (*ap)->a_numvals;
                }
 
                if ( last == 0 ) {
@@ -1110,6 +1125,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
 
                                rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
                                if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
+remove_oc:;
                                        ch_free( bv[0].bv_val );
                                        BER_BVZERO( &bv[0] );
                                        if ( &(*ap)->a_vals[last] > &bv[0] ) {
@@ -1120,12 +1136,32 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                                        bv--;
 
                                } else if ( mapped.bv_val != bv[0].bv_val ) {
+                                       int     i;
+
+                                       for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
+                                               if ( &(*ap)->a_vals[ i ] == bv ) {
+                                                       continue;
+                                               }
+
+                                               if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
+                                                       break;
+                                               }
+                                       }
+
+                                       if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
+                                               goto remove_oc;
+                                       }
+
                                        /*
                                         * FIXME: after LBER_FREEing
                                         * the value is replaced by
                                         * ch_alloc'ed memory
                                         */
                                        ber_bvreplace( &bv[0], &mapped );
+
+                                       /* FIXME: will need to check
+                                        * if the structuralObjectClass
+                                        * changed */
                                }
                        }
 
@@ -1170,6 +1206,46 @@ cleanup_attr:;
                attr_free( a );
        }
 
+       /* only check if some mapping occurred */
+       if ( check_duplicate_attrs ) {
+               for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
+                       Attribute       **tap;
+
+                       for ( tap = &(*ap)->a_next; *tap != NULL; ) {
+                               if ( (*tap)->a_desc == (*ap)->a_desc ) {
+                                       Entry           e = { 0 };
+                                       Modification    mod = { 0 };
+                                       const char      *text = NULL;
+                                       char            textbuf[ SLAP_TEXT_BUFLEN ];
+                                       Attribute       *next = (*tap)->a_next;
+
+                                       BER_BVSTR( &e.e_name, "" );
+                                       BER_BVSTR( &e.e_nname, "" );
+                                       e.e_attrs = *ap;
+                                       mod.sm_op = LDAP_MOD_ADD;
+                                       mod.sm_desc = (*ap)->a_desc;
+                                       mod.sm_type = mod.sm_desc->ad_cname;
+                                       mod.sm_numvals = (*tap)->a_numvals;
+                                       mod.sm_values = (*tap)->a_vals;
+                                       mod.sm_nvalues = (*tap)->a_nvals;
+
+                                       (void)modify_add_values( &e, &mod,
+                                               /* permissive */ 1,
+                                               &text, textbuf, sizeof( textbuf ) );
+
+                                       /* should not insert new attrs! */
+                                       assert( e.e_attrs == *ap );
+
+                                       attr_free( *tap );
+                                       *tap = next;
+
+                               } else {
+                                       tap = &(*tap)->a_next;
+                               }
+                       }
+               }
+       }
+
        return 0;
 }
 
@@ -1572,10 +1648,10 @@ enum {
        /* rewrite */
        RWM_CF_REWRITE = 1,
        RWM_CF_SUFFIXMASSAGE,
-       RWM_CF_T_F_SUPPORT,
 
        /* map */
        RWM_CF_MAP,
+       RWM_CF_T_F_SUPPORT,
        RWM_CF_NORMALIZE_MAPPED,
 
        RWM_CF_LAST
@@ -1706,8 +1782,15 @@ rwm_cf_gen( ConfigArgs *c )
 
                switch ( c->type ) {
                case RWM_CF_REWRITE:
-                       slap_rewrite_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
-                       if ( !c->rvalue_vals ) rc = 1;
+                       if ( rwmap->rwm_bva_rewrite == NULL ) {
+                               rc = 1;
+
+                       } else {
+                               slap_rewrite_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
+                               if ( !c->rvalue_vals ) {
+                                       rc = 1;
+                               }
+                       }
                        break;
 
                case RWM_CF_T_F_SUPPORT:
@@ -1749,8 +1832,9 @@ rwm_cf_gen( ConfigArgs *c )
                                /* single modification is not allowed */
                                rc = 1;
 
-                       } else {
+                       } else if ( rwmap->rwm_rw != NULL ) {
                                rewrite_info_delete( &rwmap->rwm_rw );
+                               assert( rwmap->rwm_rw == NULL );
 
                                ber_bvarray_free( rwmap->rwm_bva_rewrite );
                                rwmap->rwm_bva_rewrite = NULL;
@@ -1895,15 +1979,10 @@ rwm_cf_gen( ConfigArgs *c )
        return rc;
 }
 
-
-
-
-
-
-
 static int
 rwm_db_init(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst           *on = (slap_overinst *) be->bd_info;
        struct ldaprwmap        *rwmap;
@@ -1934,7 +2013,7 @@ error_return:;
        on->on_bi.bi_private = (void *)rwmap;
 
        if ( rc ) {
-               (void)rwm_db_destroy( be );
+               (void)rwm_db_destroy( be, NULL );
        }
 
        return rc;
@@ -1942,7 +2021,8 @@ error_return:;
 
 static int
 rwm_db_destroy(
-       BackendDB       *be )
+       BackendDB       *be,
+       ConfigReply     *cr )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
        int             rc = 0;