]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/slapi/slapi_utils.c
ITS#3924
[openldap] / servers / slapd / slapi / slapi_utils.c
index e12d8ab90029d7e2c8354368e39b6f0cf492891a..8e7b656468c114a3fdf26af2c54c9aee42eae77c 100644 (file)
@@ -294,7 +294,7 @@ slapi_entry_attr_get_charptr( const Slapi_Entry *e, const char *type )
 
                p = slapi_value_get_string( &attr->a_vals[0] );
                if ( p != NULL ) {
-                       return slapi_ch_strdup( (char *)p );
+                       return slapi_ch_strdup( p );
                }
        }
 
@@ -936,45 +936,69 @@ slapi_dn_parent( const char *_dn )
        return slapi_ch_strdup( parentDN.bv_val );
 }
 
+int slapi_dn_isbesuffix( Slapi_PBlock *pb, char *ldn )
+{
+       struct berval   ndn;
+       Backend         *be;
+
+       if ( slapi_is_rootdse( ldn ) ) {
+               return 0;
+       }
+
+       /* according to spec should already be normalized */
+       ndn.bv_len = strlen( ldn );
+       ndn.bv_val = ldn;
+
+       be = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
+       if ( be == NULL ) {
+               return 0;
+       }
+
+       return be_issuffix( be, &ndn );
+}
+
 /*
  * Returns DN of the parent entry; or NULL if the DN is
  * an empty string, if the DN has no parent, or if the
  * DN is the suffix of the backend database
  */
-char *slapi_dn_beparent( Slapi_PBlock *pb, const char *_dn )
+char *slapi_dn_beparent( Slapi_PBlock *pb, const char *ldn )
 {
        Backend         *be;
        struct berval   dn, prettyDN;
        struct berval   normalizedDN, parentDN;
+       char            *parent = NULL;
 
-       if ( pb == NULL || pb->pb_op == NULL )
+       if ( pb == NULL ) {
                return NULL;
+       }
 
-       be = pb->pb_op->o_bd;
-
-       dn.bv_val = (char *)_dn;
-       dn.bv_len = strlen( _dn );
+       PBLOCK_ASSERT_OP( pb, 0 );
 
-       if ( dnPrettyNormal( NULL, &dn, &prettyDN, &normalizedDN, NULL ) != LDAP_SUCCESS ) {
+       if ( slapi_is_rootdse( ldn ) ) {
                return NULL;
        }
 
-       if ( be != NULL && be_issuffix( be, &normalizedDN ) ) {
-               slapi_ch_free( (void **)&prettyDN.bv_val );
-               slapi_ch_free( (void **)&normalizedDN.bv_val );
+       dn.bv_val = (char *)ldn;
+       dn.bv_len = strlen( ldn );
+
+       if ( dnPrettyNormal( NULL, &dn, &prettyDN, &normalizedDN, NULL ) != LDAP_SUCCESS ) {
                return NULL;
        }
 
-       dnParent( &prettyDN, &parentDN );
+       be = select_backend( &pb->pb_op->o_req_ndn, 0, 0 );
 
-       slapi_ch_free( (void **)&prettyDN.bv_val );
-       slapi_ch_free( (void **)&normalizedDN.bv_val );
+       if ( be == NULL || be_issuffix( be, &normalizedDN ) == 0 ) {
+               dnParent( &prettyDN, &parentDN );
 
-       if ( parentDN.bv_len == 0 ) {
-               return NULL;
+               if ( parentDN.bv_len != 0 )
+                       parent = slapi_ch_strdup( parentDN.bv_val );
        }
 
-       return slapi_ch_strdup( parentDN.bv_val );
+       slapi_ch_free_string( &prettyDN.bv_val );
+       slapi_ch_free_string( &normalizedDN.bv_val );
+
+       return parent;
 }
 
 char *
@@ -1070,15 +1094,15 @@ slapi_ch_realloc(
 }
 
 char *
-slapi_ch_strdup( char *s ) 
+slapi_ch_strdup( const char *s ) 
 {
-       return ch_strdup( (const char *)s );
+       return ch_strdup( s );
 }
 
 size_t
-slapi_ch_stlen( char *s ) 
+slapi_ch_stlen( const char *s ) 
 {
-       return strlen( (const char *)s );
+       return strlen( s );
 }
 
 int 
@@ -2352,7 +2376,7 @@ Slapi_Value *slapi_value_init_berval(Slapi_Value *v, struct berval *bval)
 
 Slapi_Value *slapi_value_init_string(Slapi_Value *v, const char *s)
 {
-       v->bv_val = slapi_ch_strdup( (char *)s );
+       v->bv_val = slapi_ch_strdup( s );
        v->bv_len = strlen( s );
 
        return v;
@@ -2657,7 +2681,7 @@ int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char
        if ( pb == NULL || pb->pb_op == NULL )
                return LDAP_PARAM_ERROR;
 
-       ml = slapi_int_ldapmods2modifications( mods, 0, NULL );
+       ml = slapi_int_ldapmods2modifications( mods );
        if ( ml == NULL ) {
                return LDAP_OTHER;
        }
@@ -2666,8 +2690,7 @@ int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char
                rc = acl_check_modlist( pb->pb_op, e, ml ) ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS;
        }
 
-       /* Careful when freeing the modlist because it has pointers into the mods array. */
-       slapi_int_mods_free( ml );
+       slap_mods_free( ml, 1 );
 
        return rc;
 }
@@ -2680,10 +2703,7 @@ int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char
  * 
  * This function must also be called before slap_mods_check().
  */
-LDAPMod **slapi_int_modifications2ldapmods(
-       Modifications **pmodlist,
-       void *memctx
-)
+LDAPMod **slapi_int_modifications2ldapmods( Modifications **pmodlist )
 {
        Modifications *ml, *modlist;
        LDAPMod **mods, *modp;
@@ -2694,24 +2714,30 @@ LDAPMod **slapi_int_modifications2ldapmods(
        for( i = 0, ml = modlist; ml != NULL; i++, ml = ml->sml_next )
                ;
 
-       mods = (LDAPMod **)slap_sl_malloc( (i + 1) * sizeof(LDAPMod *), memctx );
+       mods = (LDAPMod **)slapi_ch_malloc( (i + 1) * sizeof(LDAPMod *) );
 
        for( i = 0, ml = modlist; ml != NULL; ml = ml->sml_next ) {
-               mods[i] = (LDAPMod *)slap_sl_malloc( sizeof(LDAPMod), memctx );
+               mods[i] = (LDAPMod *)slapi_ch_malloc( sizeof(LDAPMod) );
                modp = mods[i];
                modp->mod_op = ml->sml_op | LDAP_MOD_BVALUES;
-               modp->mod_type = slapi_ch_strdup( ml->sml_type.bv_val );
-               ml->sml_type.bv_val = NULL;
+               if ( BER_BVISNULL( &ml->sml_type ) ) {
+                       /* may happen for internally generated mods */
+                       assert( ml->sml_desc != NULL );
+                       modp->mod_type = slapi_ch_strdup( ml->sml_desc->ad_cname.bv_val );
+               } else {
+                       modp->mod_type = slapi_ch_strdup( ml->sml_type.bv_val );
+                       BER_BVZERO( &ml->sml_type );
+               }
 
                if ( ml->sml_values != NULL ) {
                        for( j = 0; ml->sml_values[j].bv_val != NULL; j++ )
                                ;
-                       modp->mod_bvalues = (struct berval **)slap_sl_malloc( (j + 1) *
-                               sizeof(struct berval *), memctx );
+                       modp->mod_bvalues = (struct berval **)slapi_ch_malloc( (j + 1) *
+                               sizeof(struct berval *) );
                        for( j = 0; ml->sml_values[j].bv_val != NULL; j++ ) {
+                               modp->mod_bvalues[j] = (struct berval *)slapi_ch_malloc(
+                                               sizeof(struct berval) );
                                /* Take ownership of original values. */
-                               modp->mod_bvalues[j] = (struct berval *)slap_sl_malloc(
-                                               sizeof(struct berval), memctx );
                                modp->mod_bvalues[j]->bv_len = ml->sml_values[j].bv_len;
                                modp->mod_bvalues[j]->bv_val = ml->sml_values[j].bv_val;
                                ml->sml_values[j].bv_len = 0;
@@ -2727,7 +2753,7 @@ LDAPMod **slapi_int_modifications2ldapmods(
 
        mods[i] = NULL;
 
-       slap_mods_free( modlist );
+       slap_mods_free( modlist, 1 );
        *pmodlist = NULL;
 
        return mods;
@@ -2735,16 +2761,17 @@ LDAPMod **slapi_int_modifications2ldapmods(
 
 /*
  * Convert a potentially modified array of LDAPMods back to a
- * Modification list. 
- * 
- * The returned Modification list contains pointers into the
- * LDAPMods array; the latter MUST be freed with
- * slapi_int_free_ldapmods() (see below).
+ * Modification list. Unfortunately the values need to be
+ * duplicated because slap_mods_check() will try to free them
+ * before prettying (and we can't easily get out of calling
+ * slap_mods_check() because we need normalized values).
  */
-Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, int dup, void *memctx )
+Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods )
 {
        Modifications *modlist = NULL, **modtail;
        LDAPMod **modp;
+       char textbuf[SLAP_TEXT_BUFLEN];
+       const char *text;
 
        if ( mods == NULL ) {
                return NULL;
@@ -2763,7 +2790,7 @@ Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, int dup, void
                        continue;
                }
 
-               mod = (Modifications *) slap_sl_malloc( sizeof(Modifications), memctx );
+               mod = (Modifications *) slapi_ch_malloc( sizeof(Modifications) );
                mod->sml_op = lmod->mod_op & ~(LDAP_MOD_BVALUES);
                mod->sml_flags = 0;
                mod->sml_type = ad->ad_cname;
@@ -2786,22 +2813,16 @@ Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, int dup, void
                if ( i == 0 ) {
                        mod->sml_values = NULL;
                } else {
-                       mod->sml_values = (BerVarray) slap_sl_malloc( (i + 1) * sizeof(struct berval), memctx );
+                       mod->sml_values = (BerVarray) slapi_ch_malloc( (i + 1) * sizeof(struct berval) );
 
                        /* NB: This implicitly trusts a plugin to return valid modifications. */
                        if ( lmod->mod_op & LDAP_MOD_BVALUES ) {
                                for ( i = 0; lmod->mod_bvalues[i] != NULL; i++ ) {
-                                       if ( dup ) {
-                                               ber_dupbv( &mod->sml_values[i], lmod->mod_bvalues[i] );
-                                       } else {
-                                               mod->sml_values[i].bv_val = lmod->mod_bvalues[i]->bv_val;
-                                               mod->sml_values[i].bv_len = lmod->mod_bvalues[i]->bv_len;
-                                       }
+                                       ber_dupbv( &mod->sml_values[i], lmod->mod_bvalues[i] );
                                }
                        } else {
                                for ( i = 0; lmod->mod_values[i] != NULL; i++ ) {
-                                       mod->sml_values[i].bv_val = dup ? slapi_ch_strdup( lmod->mod_values[i] ) :
-                                               lmod->mod_values[i];
+                                       mod->sml_values[i].bv_val = slapi_ch_strdup( lmod->mod_values[i] );
                                        mod->sml_values[i].bv_len = strlen( lmod->mod_values[i] );
                                }
                        }
@@ -2813,63 +2834,13 @@ Modifications *slapi_int_ldapmods2modifications ( LDAPMod **mods, int dup, void
                *modtail = mod;
                modtail = &mod->sml_next;
        }
-       
-       return modlist;
-}
 
-/*
- * For an internal operation, the unnormalized values are
- * owned by the caller (ie. the plugin making the internal
- * operation).
- */
-void
-slapi_int_mods_free( Modifications *ml )
-{
-       Modifications           *next;
-
-       for ( ; ml != NULL; ml = next ) {
-               next = ml->sml_next;
-
-               if ( ml->sml_nvalues != NULL ) {
-                       ber_bvarray_free( ml->sml_nvalues );
-                       ml->sml_nvalues = NULL;
-               }
-               slapi_ch_free( (void **)&ml->sml_values );
-               slapi_ch_free( (void **)&ml );
+       if ( slap_mods_check( modlist, &text, textbuf, sizeof( textbuf ), NULL ) != LDAP_SUCCESS ) {
+               slap_mods_free( modlist, 1 );
+               modlist = NULL;
        }
-}
 
-/*
- * This function only frees the parts of the mods array that
- * are not shared with the Modification list that was created
- * by slapi_int_ldapmods2modifications() (if dup == 0).
- */
-void
-slapi_int_free_ldapmods ( LDAPMod **mods )
-{
-       int i, j;
-
-       if ( mods == NULL )
-               return;
-
-       for ( i = 0; mods[i] != NULL; i++ ) {
-               /*
-                * Don't free values themselves; they're owned by the
-                * Modification list. Do free the containing array.
-                */
-               if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) {
-                       if ( mods[i]->mod_bvalues != NULL ) {
-                               for ( j = 0; mods[i]->mod_bvalues[j] != NULL; j++ )
-                                       slapi_ch_free( (void **)&mods[i]->mod_bvalues[j] );
-                               slapi_ch_free( (void **)&mods[i]->mod_bvalues );
-                       }
-               } else {
-                       slapi_ch_free( (void **)&mods[i]->mod_values );
-               }
-               slapi_ch_free_string( &mods[i]->mod_type );
-               slapi_ch_free( (void **)&mods[i] );
-       }
-       slapi_ch_free( (void **)&mods );
+       return modlist;
 }
 
 /*
@@ -3224,16 +3195,22 @@ char *slapi_dn_plus_rdn( const char *dn, const char *rdn )
 
 int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e )
 {
-       Backend *be;
+       Backend *be_orig;
        const char *text;
        char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
        size_t textlen = sizeof textbuf;
        int rc = LDAP_SUCCESS;
 
-       be = select_backend( &e->e_nname, 0, 0 );
-       if ( be != NULL )
-               rc = entry_schema_check( be, e, NULL, 0,
+       PBLOCK_ASSERT_OP( pb, 0 );
+
+       be_orig = pb->pb_op->o_bd;
+
+       pb->pb_op->o_bd = select_backend( &e->e_nname, 0, 0 );
+       if ( pb->pb_op->o_bd != NULL ) {
+               rc = entry_schema_check( pb->pb_op, e, NULL, 0,
                        &text, textbuf, textlen );
+       }
+       pb->pb_op->o_bd = be_orig;
 
        return ( rc == LDAP_SUCCESS ) ? 0 : 1;
 }
@@ -3481,6 +3458,44 @@ slapi_op_get_type(Slapi_Operation * op)
        return type;
 }
 
+void slapi_be_set_readonly( Slapi_Backend *be, int readonly )
+{
+       if ( be == NULL )
+               return;
+
+       if ( readonly )
+               be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
+       else
+               be->be_restrictops &= ~(SLAP_RESTRICT_OP_WRITES);
+}
+
+int slapi_be_get_readonly( Slapi_Backend *be )
+{
+       if ( be == NULL )
+               return 0;
+
+       return ( (be->be_restrictops & SLAP_RESTRICT_OP_WRITES) == SLAP_RESTRICT_OP_WRITES );
+}
+
+const char *slapi_x_be_get_updatedn( Slapi_Backend *be )
+{
+       if ( be == NULL )
+               return NULL;
+
+       return be->be_update_ndn.bv_val;
+}
+
+Slapi_Backend *slapi_be_select( const Slapi_DN *sdn )
+{
+       Slapi_Backend *be;
+
+       slapi_sdn_get_ndn( sdn );
+
+       be = select_backend( (struct berval *)&sdn->ndn, 0, 0 );
+
+       return be;
+}
+
 #if 0
 void
 slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag)