]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/unique.c
ITS#6953 do not use the cache db when refreshing
[openldap] / servers / slapd / overlays / unique.c
index 6852f917d57c919387c8f56966e4ac3609872788..845b24d2e0454e1b2861f1e939e7bc5611f0971e 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2007 The OpenLDAP Foundation.
+ * Copyright 2004-2011 The OpenLDAP Foundation.
  * Portions Copyright 2004,2006-2007 Symas Corporation.
  * All rights reserved.
  *
@@ -44,16 +44,17 @@ typedef struct unique_attrs_s {
 
 typedef struct unique_domain_uri_s {
        struct unique_domain_uri_s *next;
-       struct berval *dn;
-       struct berval *ndn;
-       struct berval *filter;
+       struct berval dn;
+       struct berval ndn;
+       struct berval filter;
+       Filter *f;
        struct unique_attrs_s *attrs;
        int scope;
 } unique_domain_uri;
 
 typedef struct unique_domain_s {
        struct unique_domain_s *next;
-       struct berval *domain_spec;
+       struct berval domain_spec;
        struct unique_domain_uri_s *uri;
        char ignore;                          /* polarity of attributes */
        char strict;                          /* null considered unique too */
@@ -138,9 +139,10 @@ unique_free_domain_uri ( unique_domain_uri *uri )
 
        while ( uri ) {
                next_uri = uri->next;
-               ber_bvfree ( uri->dn );
-               ber_bvfree ( uri->ndn );
-               ber_bvfree ( uri->filter );
+               ch_free ( uri->dn.bv_val );
+               ch_free ( uri->ndn.bv_val );
+               ch_free ( uri->filter.bv_val );
+               filter_free( uri->f );
                attr = uri->attrs;
                while ( attr ) {
                        next_attr = attr->next;
@@ -160,7 +162,7 @@ unique_free_domain ( unique_domain *domain )
 
        while ( domain ) {
                next_domain = domain->next;
-               ber_bvfree ( domain->domain_spec );
+               ch_free ( domain->domain_spec.bv_val );
                unique_free_domain_uri ( domain->uri );
                ch_free ( domain );
                domain = next_domain;
@@ -183,28 +185,44 @@ unique_new_domain_uri ( unique_domain_uri **urip,
        uri = ch_calloc ( 1, sizeof ( unique_domain_uri ) );
 
        if ( url_desc->lud_dn && url_desc->lud_dn[0] ) {
-               ber_str2bv( url_desc->lud_dn, 0, 1, &bv );
+               ber_str2bv( url_desc->lud_dn, 0, 0, &bv );
                rc = dnPrettyNormal( NULL,
                                     &bv,
-                                    uri->dn,
-                                    uri->ndn,
+                                    &uri->dn,
+                                    &uri->ndn,
                                     NULL );
                if ( rc != LDAP_SUCCESS ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "<%s> invalid DN %d (%s)",
                                  url_desc->lud_dn, rc, ldap_err2string( rc ));
                        rc = ARG_BAD_CONF;
                        goto exit;
                }
 
-               if ( !dnIsSuffix ( uri->ndn, &be->be_nsuffix[0] ) ) {
-                       sprintf ( c->msg,
+               if ( be->be_nsuffix == NULL ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                 "suffix must be set" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
+                       goto exit;
+               }
+
+               if ( !dnIsSuffix ( &uri->ndn, &be->be_nsuffix[0] ) ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "dn <%s> is not a suffix of backend base dn <%s>",
-                                 uri->dn->bv_val,
+                                 uri->dn.bv_val,
                                  be->be_nsuffix[0].bv_val );
                        rc = ARG_BAD_CONF;
                        goto exit;
                }
+
+               if ( BER_BVISNULL( &be->be_rootndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) {
+                       Debug( LDAP_DEBUG_ANY,
+                               "slapo-unique needs a rootdn; "
+                               "backend <%s> has none, YMMV.\n",
+                               be->be_nsuffix[0].bv_val, 0, 0 );
+               }
        }
 
        attr_str = url_desc->lud_attrs;
@@ -220,7 +238,7 @@ unique_new_domain_uri ( unique_domain_uri **urip,
                                attr->next = uri->attrs;
                                uri->attrs = attr;
                        } else {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                          "unique: attribute: %s: %s",
                                          attr_str[i], text );
                                rc = ARG_BAD_CONF;
@@ -231,31 +249,38 @@ unique_new_domain_uri ( unique_domain_uri **urip,
 
        uri->scope = url_desc->lud_scope;
        if ( !uri->scope ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                          "unique: uri with base scope will always be unique");
                rc = ARG_BAD_CONF;
                goto exit;
        }
 
        if (url_desc->lud_filter) {
-               Filter * f;
-               uri->filter = ber_str2bv( url_desc->lud_filter, 0, 1, NULL);
-               f = str2filter( uri->filter->bv_val );
-               if ( !f ) {
-                       snprintf( c->msg, sizeof( c->msg ),
+               char *ptr;
+               uri->f = str2filter( url_desc->lud_filter );
+               if ( !uri->f ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                 "unique: bad filter");
+                       rc = ARG_BAD_CONF;
+                       goto exit;
+               }
+               /* make sure the strfilter is in normal form (ITS#5581) */
+               filter2bv( uri->f, &uri->filter );
+               ptr = strstr( uri->filter.bv_val, "(?=" /*)*/ );
+               if ( ptr != NULL && ptr <= ( uri->filter.bv_val - STRLENOF( "(?=" /*)*/ ) + uri->filter.bv_len ) )
+               {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "unique: bad filter");
                        rc = ARG_BAD_CONF;
                        goto exit;
                }
-               filter_free( f );
        }
 exit:
-       if ( bv.bv_val ) ber_memfree ( bv.bv_val );
        uri->next = *urip;
        *urip = uri;
        if ( rc ) {
                Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s: %s\n", c->log, c->msg, 0 );
+                       "%s: %s\n", c->log, c->cr_msg, 0 );
                unique_free_domain_uri ( uri );
                *urip = NULL;
        }
@@ -305,7 +330,7 @@ unique_new_domain ( unique_domain **domainp,
              domain_spec, 0, 0);
 
        domain = ch_calloc ( 1, sizeof (unique_domain) );
-       domain->domain_spec = ber_str2bv( domain_spec, 0, 1, NULL );
+       ber_str2bv( domain_spec, 0, 1, &domain->domain_spec );
 
        uri_start = domain_spec;
        if ( strncasecmp ( uri_start, "ignore ",
@@ -326,7 +351,7 @@ unique_new_domain ( unique_domain **domainp,
        }
        rc = ldap_url_parselist_ext ( &url_descs, uri_start, " ", 0 );
        if ( rc ) {
-               snprintf( c->msg, sizeof( c->msg ),
+               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                          "<%s> invalid ldap urilist",
                          uri_start );
                rc = ARG_BAD_CONF;
@@ -352,7 +377,7 @@ exit:
        *domainp = domain;
        if ( rc ) {
                Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s: %s\n", c->log, c->msg, 0 );
+                       "%s: %s\n", c->log, c->cr_msg, 0 );
                unique_free_domain ( domain );
                *domainp = NULL;
        }
@@ -372,24 +397,23 @@ unique_cf_base( ConfigArgs *c )
        switch ( c->op ) {
        case SLAP_CONFIG_EMIT:
                rc = 0;
-               if ( legacy && legacy->uri && legacy->uri->dn ) {
+               if ( legacy && legacy->uri && legacy->uri->dn.bv_val ) {
                        rc = value_add_one ( &c->rvalue_vals,
-                                            legacy->uri->dn );
+                                            &legacy->uri->dn );
                        if ( rc ) return rc;
                        rc = value_add_one ( &c->rvalue_nvals,
-                                            legacy->uri->ndn );
+                                            &legacy->uri->ndn );
                        if ( rc ) return rc;
                }
                break;
        case LDAP_MOD_DELETE:
-               assert ( legacy && legacy->uri && legacy->uri->dn );
+               assert ( legacy && legacy->uri && legacy->uri->dn.bv_val );
                rc = 0;
-               ber_bvfree ( legacy->uri->dn );
-               ber_bvfree ( legacy->uri->ndn );
-               legacy->uri->dn = NULL;
-               legacy->uri->ndn = NULL;
-               if ( !legacy->uri->attrs
-                    && !legacy->uri->dn ) {
+               ch_free ( legacy->uri->dn.bv_val );
+               ch_free ( legacy->uri->ndn.bv_val );
+               BER_BVZERO( &legacy->uri->dn );
+               BER_BVZERO( &legacy->uri->ndn );
+               if ( !legacy->uri->attrs ) {
                        unique_free_domain_uri ( legacy->uri );
                        legacy->uri = NULL;
                }
@@ -401,19 +425,27 @@ unique_cf_base( ConfigArgs *c )
        case LDAP_MOD_ADD:
        case SLAP_CONFIG_ADD:
                if ( domains ) {
-                       sprintf ( c->msg,
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "cannot set legacy attrs when URIs are present" );
                        Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
-                               c->msg, NULL, NULL );
+                               c->cr_msg, NULL, NULL );
+                       rc = ARG_BAD_CONF;
+                       break;
+               }
+               if ( be->be_nsuffix == NULL ) {
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                 "suffix must be set" );
+                       Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
+                               c->cr_msg, NULL, NULL );
                        rc = ARG_BAD_CONF;
                        break;
                }
                if ( !dnIsSuffix ( &c->value_ndn,
                                   &be->be_nsuffix[0] ) ) {
-                       sprintf ( c->msg,
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "dn is not a suffix of backend base" );
                        Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
-                               c->msg, NULL, NULL );
+                               c->cr_msg, NULL, NULL );
                        rc = ARG_BAD_CONF;
                        break;
                }
@@ -425,16 +457,23 @@ unique_cf_base( ConfigArgs *c )
                }
                if ( !legacy->uri )
                        unique_new_domain_uri_basic ( &legacy->uri, c );
-               ber_bvfree ( legacy->uri->dn );
-               ber_bvfree ( legacy->uri->ndn );
-               legacy->uri->dn = ber_bvdup ( &c->value_dn );
-               legacy->uri->ndn = ber_bvdup ( &c->value_ndn );
+               ch_free ( legacy->uri->dn.bv_val );
+               ch_free ( legacy->uri->ndn.bv_val );
+               legacy->uri->dn = c->value_dn;
+               legacy->uri->ndn = c->value_ndn;
                rc = 0;
                break;
        default:
                abort();
        }
 
+       if ( rc ) {
+               ch_free( c->value_dn.bv_val );
+               BER_BVZERO( &c->value_dn );
+               ch_free( c->value_ndn.bv_val );
+               BER_BVZERO( &c->value_ndn );
+       }
+
        return rc;
 }
 
@@ -485,7 +524,7 @@ unique_cf_attrs( ConfigArgs *c )
                                ch_free (attr);
                        }
                        if ( !legacy->uri->attrs
-                            && !legacy->uri->dn ) {
+                            && !legacy->uri->dn.bv_val ) {
                                unique_free_domain_uri ( legacy->uri );
                                legacy->uri = NULL;
                        }
@@ -499,10 +538,10 @@ unique_cf_attrs( ConfigArgs *c )
        case LDAP_MOD_ADD:
        case SLAP_CONFIG_ADD:
                if ( domains ) {
-                       sprintf ( c->msg,
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "cannot set legacy attrs when URIs are present" );
                        Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
-                               c->msg, NULL, NULL );
+                               c->cr_msg, NULL, NULL );
                        rc = ARG_BAD_CONF;
                        break;
                }
@@ -510,10 +549,10 @@ unique_cf_attrs( ConfigArgs *c )
                     && legacy->uri
                     && legacy->uri->attrs
                     && (c->type == UNIQUE_IGNORE) != legacy->ignore ) {
-                       sprintf ( c->msg,
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "cannot set both attrs and ignore-attrs" );
                        Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
-                               c->msg, NULL, NULL );
+                               c->cr_msg, NULL, NULL );
                        rc = ARG_BAD_CONF;
                        break;
                }
@@ -538,7 +577,7 @@ unique_cf_attrs( ConfigArgs *c )
                                attr->next = new_attrs;
                                new_attrs = attr;
                        } else {
-                               snprintf( c->msg, sizeof( c->msg ),
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                          "unique: attribute: %s: %s",
                                          c->argv[i], text );
                                for ( attr = new_attrs;
@@ -575,7 +614,7 @@ unique_cf_attrs( ConfigArgs *c )
 
        if ( rc ) {
                Debug ( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
-                       "%s: %s\n", c->log, c->msg, 0 );
+                       "%s: %s\n", c->log, c->cr_msg, 0 );
        }
        return rc;
 }
@@ -620,10 +659,10 @@ unique_cf_strict( ConfigArgs *c )
        case LDAP_MOD_ADD:
        case SLAP_CONFIG_ADD:
                if ( domains ) {
-                       sprintf ( c->msg,
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "cannot set legacy attrs when URIs are present" );
                        Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
-                               c->msg, NULL, NULL );
+                               c->cr_msg, NULL, NULL );
                        rc = ARG_BAD_CONF;
                        break;
                }
@@ -663,10 +702,7 @@ unique_cf_uri( ConfigArgs *c )
                      domain;
                      domain = domain->next ) {
                        rc = value_add_one ( &c->rvalue_vals,
-                                            domain->domain_spec );
-                       if ( rc ) break;
-                       rc = value_add_one ( &c->rvalue_nvals,
-                                            domain->domain_spec );
+                                            &domain->domain_spec );
                        if ( rc ) break;
                }
                break;
@@ -705,10 +741,10 @@ unique_cf_uri( ConfigArgs *c )
        case SLAP_CONFIG_ADD: /* fallthrough */
        case LDAP_MOD_ADD:
                if ( legacy ) {
-                       sprintf ( c->msg,
+                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                  "cannot set Uri when legacy attrs are present" );
                        Debug ( LDAP_DEBUG_CONFIG, "unique config: %s\n",
-                               c->msg, NULL, NULL );
+                               c->cr_msg, NULL, NULL );
                        rc = ARG_BAD_CONF;
                        break;
                }
@@ -740,7 +776,8 @@ unique_cf_uri( ConfigArgs *c )
 
 static int
 unique_db_init(
-       BackendDB       *be
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -755,7 +792,8 @@ unique_db_init(
 
 static int
 unique_db_destroy(
-       BackendDB       *be
+       BackendDB       *be,
+       ConfigReply     *cr
 )
 {
        slap_overinst *on = (slap_overinst *)be->bd_info;
@@ -779,7 +817,8 @@ unique_db_destroy(
 
 static int
 unique_open(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        Debug(LDAP_DEBUG_TRACE, "unique_open: overlay initialized\n", 0, 0, 0);
@@ -795,7 +834,8 @@ unique_open(
 
 static int
 unique_close(
-       BackendDB *be
+       BackendDB *be,
+       ConfigReply *cr
 )
 {
        slap_overinst *on       = (slap_overinst *) be->bd_info;
@@ -898,6 +938,7 @@ build_filter(
        AttributeDescription *ad,
        BerVarray b,
        char *kp,
+       int ks,
        void *ctx
 )
 {
@@ -919,15 +960,21 @@ build_filter(
                if ( b && b[0].bv_val ) {
                        for ( i = 0; b[i].bv_val; i++ ) {
                                struct berval   bv;
+                               int len;
 
                                ldap_bv2escaped_filter_value_x( &b[i], &bv, 1, ctx );
-                               kp += sprintf( kp, "(%s=%s)", ad->ad_cname.bv_val, bv.bv_val );
+                               len = snprintf( kp, ks, "(%s=%s)", ad->ad_cname.bv_val, bv.bv_val );
+                               assert( len >= 0 && len < ks );
+                               kp += len;
                                if ( bv.bv_val != b[i].bv_val ) {
                                        ber_memfree_x( bv.bv_val, ctx );
                                }
                        }
                } else if ( domain->strict ) {
-                       kp += sprintf( kp, "(%s=*)", ad->ad_cname.bv_val );
+                       int len;
+                       len = snprintf( kp, ks, "(%s=*)", ad->ad_cname.bv_val );
+                       assert( len >= 0 && len < ks );
+                       kp += len;
                }
                break;
        }
@@ -941,7 +988,7 @@ unique_search(
        struct berval * dn,
        int scope,
        SlapReply *rs,
-       char *key
+       struct berval *key
 )
 {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
@@ -950,10 +997,17 @@ unique_search(
        unique_counter uq = { NULL, 0 };
        int rc;
 
-       Debug(LDAP_DEBUG_TRACE, "==> unique_search %s\n", key, 0, 0);
+       Debug(LDAP_DEBUG_TRACE, "==> unique_search %s\n", key->bv_val, 0, 0);
 
-       nop->ors_filter = str2filter_x(nop, key);
-       ber_str2bv(key, 0, 0, &nop->ors_filterstr);
+       nop->ors_filter = str2filter_x(nop, key->bv_val);
+       if(nop->ors_filter == NULL) {
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               send_ldap_error(op, rs, LDAP_OTHER,
+                       "unique_search invalid filter");
+               return(rs->sr_err);
+       }
+
+       nop->ors_filterstr = *key;
 
        cb.sc_response  = (slap_response*)count_attr_cb;
        cb.sc_private   = &uq;
@@ -974,8 +1028,8 @@ unique_search(
 
        nop->o_bd = on->on_info->oi_origdb;
        rc = nop->o_bd->be_search(nop, &nrs);
-       filter_free_x(nop, nop->ors_filter);
-       op->o_tmpfree( key, op->o_tmpmemctx );
+       filter_free_x(nop, nop->ors_filter, 1);
+       op->o_tmpfree( key->bv_val, op->o_tmpmemctx );
 
        if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) {
                op->o_bd->bd_info = (BackendInfo *) on->on_info;
@@ -1009,6 +1063,7 @@ unique_add(
        Operation nop = *op;
        Attribute *a;
        char *key, *kp;
+       struct berval bvkey;
        int rc = SLAP_CB_CONTINUE;
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n",
@@ -1016,18 +1071,32 @@ unique_add(
 
        for ( domain = legacy ? legacy : domains;
              domain;
-             domain = domain->next ) {
+             domain = domain->next )
+       {
                unique_domain_uri *uri;
-               int ks = 0;
 
                for ( uri = domain->uri;
                      uri;
-                     uri = uri->next ) {
+                     uri = uri->next )
+               {
+                       int len;
+                       int ks = 0;
 
-                       if ( uri->ndn
-                            && !dnIsSuffix( &op->o_req_ndn, uri->ndn ))
+                       if ( uri->ndn.bv_val
+                            && !dnIsSuffix( &op->o_req_ndn, &uri->ndn ))
                                continue;
 
+                       if ( uri->f ) {
+                               if ( test_filter( NULL, op->ora_e, uri->f )
+                                       == LDAP_COMPARE_FALSE )
+                               {
+                                       Debug( LDAP_DEBUG_TRACE,
+                                               "==> unique_add_skip<%s>\n",
+                                               op->o_req_dn.bv_val, 0, 0 );
+                                       continue;
+                               }
+                       }
+
                        if(!(a = op->ora_e->e_attrs)) {
                                op->o_bd->bd_info = (BackendInfo *) on->on_info;
                                send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
@@ -1047,13 +1116,21 @@ unique_add(
                        /* skip this domain-uri if it isn't involved */
                        if ( !ks ) continue;
 
-                       if ( uri->filter && uri->filter->bv_len )
-                               ks += uri->filter->bv_len + STRLENOF ("(&)");
+                       /* terminating NUL */
+                       ks += sizeof("(|)");
+
+                       if ( uri->filter.bv_val && uri->filter.bv_len )
+                               ks += uri->filter.bv_len + STRLENOF ("(&)");
                        kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
 
-                       if ( uri->filter && uri->filter->bv_len )
-                               kp += sprintf (kp, "(&%s", uri->filter->bv_val);
-                       kp += sprintf(kp, "(|");
+                       if ( uri->filter.bv_val && uri->filter.bv_len ) {
+                               len = snprintf (kp, ks, "(&%s", uri->filter.bv_val);
+                               assert( len >= 0 && len < ks );
+                               kp += len;
+                       }
+                       len = snprintf(kp, ks - (kp - key), "(|");
+                       assert( len >= 0 && len < ks - (kp - key) );
+                       kp += len;
 
                        for(a = op->ora_e->e_attrs; a; a = a->a_next)
                                kp = build_filter(domain,
@@ -1061,20 +1138,28 @@ unique_add(
                                                  a->a_desc,
                                                  a->a_vals,
                                                  kp,
+                                                 ks - ( kp - key ),
                                                  op->o_tmpmemctx);
 
-                       kp += sprintf(kp, ")");
-                       if ( uri->filter && uri->filter->bv_len )
-                               kp += sprintf (kp, ")");
+                       len = snprintf(kp, ks - (kp - key), ")");
+                       assert( len >= 0 && len < ks - (kp - key) );
+                       kp += len;
+                       if ( uri->filter.bv_val && uri->filter.bv_len ) {
+                               len = snprintf(kp, ks - (kp - key), ")");
+                               assert( len >= 0 && len < ks - (kp - key) );
+                               kp += len;
+                       }
+                       bvkey.bv_val = key;
+                       bvkey.bv_len = kp - key;
 
                        rc = unique_search ( op,
                                             &nop,
-                                            uri->ndn ?
-                                            uri->ndn :
+                                            uri->ndn.bv_val ?
+                                            &uri->ndn :
                                             &op->o_bd->be_nsuffix[0],
                                             uri->scope,
                                             rs,
-                                            key);
+                                            &bvkey);
 
                        if ( rc != SLAP_CB_CONTINUE ) break;
                }
@@ -1099,6 +1184,7 @@ unique_modify(
        Operation nop = *op;
        Modifications *m;
        char *key, *kp;
+       struct berval bvkey;
        int rc = SLAP_CB_CONTINUE;
 
        Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n",
@@ -1106,16 +1192,19 @@ unique_modify(
 
        for ( domain = legacy ? legacy : domains;
              domain;
-             domain = domain->next ) {
+             domain = domain->next )
+       {
                unique_domain_uri *uri;
-               int ks = 0;
 
                for ( uri = domain->uri;
                      uri;
-                     uri = uri->next ) {
+                     uri = uri->next )
+               {
+                       int len;
+                       int ks = 0;
 
-                       if ( uri->ndn
-                            && !dnIsSuffix( &op->o_req_ndn, uri->ndn ))
+                       if ( uri->ndn.bv_val
+                            && !dnIsSuffix( &op->o_req_ndn, &uri->ndn ))
                                continue;
 
                        if ( !(m = op->orm_modlist) ) {
@@ -1138,13 +1227,21 @@ unique_modify(
                        /* skip this domain-uri if it isn't involved */
                        if ( !ks ) continue;
 
-                       if ( uri->filter && uri->filter->bv_len )
-                               ks += uri->filter->bv_len + STRLENOF ("(&)");
+                       /* terminating NUL */
+                       ks += sizeof("(|)");
+
+                       if ( uri->filter.bv_val && uri->filter.bv_len )
+                               ks += uri->filter.bv_len + STRLENOF ("(&)");
                        kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
 
-                       if ( uri->filter && uri->filter->bv_len )
-                               kp += sprintf (kp, "(&%s", uri->filter->bv_val);
-                       kp += sprintf(kp, "(|");
+                       if ( uri->filter.bv_val && uri->filter.bv_len ) {
+                               len = snprintf(kp, ks, "(&%s", uri->filter.bv_val);
+                               assert( len >= 0 && len < ks );
+                               kp += len;
+                       }
+                       len = snprintf(kp, ks - (kp - key), "(|");
+                       assert( len >= 0 && len < ks - (kp - key) );
+                       kp += len;
 
                        for(m = op->orm_modlist; m; m = m->sml_next)
                                if ( (m->sml_op & LDAP_MOD_OP)
@@ -1154,20 +1251,28 @@ unique_modify(
                                                            m->sml_desc,
                                                            m->sml_values,
                                                            kp,
+                                                           ks - (kp - key),
                                                            op->o_tmpmemctx );
 
-                       kp += sprintf (kp, ")");
-                       if ( uri->filter && uri->filter->bv_len )
-                               kp += sprintf (kp, ")");
+                       len = snprintf(kp, ks - (kp - key), ")");
+                       assert( len >= 0 && len < ks - (kp - key) );
+                       kp += len;
+                       if ( uri->filter.bv_val && uri->filter.bv_len ) {
+                               len = snprintf (kp, ks - (kp - key), ")");
+                               assert( len >= 0 && len < ks - (kp - key) );
+                               kp += len;
+                       }
+                       bvkey.bv_val = key;
+                       bvkey.bv_len = kp - key;
 
                        rc = unique_search ( op,
                                             &nop,
-                                            uri->ndn ?
-                                            uri->ndn :
+                                            uri->ndn.bv_val ?
+                                            &uri->ndn :
                                             &op->o_bd->be_nsuffix[0],
                                             uri->scope,
                                             rs,
-                                            key);
+                                            &bvkey);
 
                        if ( rc != SLAP_CB_CONTINUE ) break;
                }
@@ -1191,6 +1296,7 @@ unique_modrdn(
        unique_domain *domain;
        Operation nop = *op;
        char *key, *kp;
+       struct berval bvkey;
        LDAPRDN newrdn;
        struct berval bv[2];
        int rc = SLAP_CB_CONTINUE;
@@ -1200,19 +1306,21 @@ unique_modrdn(
 
        for ( domain = legacy ? legacy : domains;
              domain;
-             domain = domain->next ) {
+             domain = domain->next )
+       {
                unique_domain_uri *uri;
-               int ks = 0;
 
                for ( uri = domain->uri;
                      uri;
-                     uri = uri->next ) {
-                       int i;
+                     uri = uri->next )
+               {
+                       int i, len;
+                       int ks = 0;
 
-                       if ( uri->ndn
-                            && !dnIsSuffix( &op->o_req_ndn, uri->ndn )
+                       if ( uri->ndn.bv_val
+                            && !dnIsSuffix( &op->o_req_ndn, &uri->ndn )
                             && (!op->orr_nnewSup
-                                || !dnIsSuffix( op->orr_nnewSup, uri->ndn )))
+                                || !dnIsSuffix( op->orr_nnewSup, &uri->ndn )))
                                continue;
 
                        if ( ldap_bv2rdn_x ( &op->oq_modrdn.rs_newrdn,
@@ -1255,13 +1363,21 @@ unique_modrdn(
                        /* skip this domain if it isn't involved */
                        if ( !ks ) continue;
 
-                       if ( uri->filter && uri->filter->bv_len )
-                               ks += uri->filter->bv_len + STRLENOF ("(&)");
+                       /* terminating NUL */
+                       ks += sizeof("(|)");
+
+                       if ( uri->filter.bv_val && uri->filter.bv_len )
+                               ks += uri->filter.bv_len + STRLENOF ("(&)");
                        kp = key = op->o_tmpalloc(ks, op->o_tmpmemctx);
 
-                       if ( uri->filter && uri->filter->bv_len )
-                               kp += sprintf (kp, "(&%s", uri->filter->bv_val);
-                       kp += sprintf(kp, "(|");
+                       if ( uri->filter.bv_val && uri->filter.bv_len ) {
+                               len = snprintf(kp, ks, "(&%s", uri->filter.bv_val);
+                               assert( len >= 0 && len < ks );
+                               kp += len;
+                       }
+                       len = snprintf(kp, ks - (kp - key), "(|");
+                       assert( len >= 0 && len < ks - (kp - key) );
+                       kp += len;
 
                        for ( i=0; newrdn[i]; i++) {
                                bv[0] = newrdn[i]->la_value;
@@ -1270,21 +1386,29 @@ unique_modrdn(
                                                    newrdn[i]->la_private,
                                                    bv,
                                                    kp,
+                                                   ks - (kp - key ),
                                                    op->o_tmpmemctx);
                        }
 
-                       kp += sprintf(kp, ")");
-                       if ( uri->filter && uri->filter->bv_len )
-                               kp += sprintf (kp, ")");
+                       len = snprintf(kp, ks - (kp - key), ")");
+                       assert( len >= 0 && len < ks - (kp - key) );
+                       kp += len;
+                       if ( uri->filter.bv_val && uri->filter.bv_len ) {
+                               len = snprintf (kp, ks - (kp - key), ")");
+                               assert( len >= 0 && len < ks - (kp - key) );
+                               kp += len;
+                       }
+                       bvkey.bv_val = key;
+                       bvkey.bv_len = kp - key;
 
                        rc = unique_search ( op,
                                             &nop,
-                                            uri->ndn ?
-                                            uri->ndn :
+                                            uri->ndn.bv_val ?
+                                            &uri->ndn :
                                             &op->o_bd->be_nsuffix[0],
                                             uri->scope,
                                             rs,
-                                            key);
+                                            &bvkey);
 
                        if ( rc != SLAP_CB_CONTINUE ) break;
                }