]> git.sur5r.net Git - openldap/commitdiff
add support for CSNSIDMatch; use it to set contextCSN as appropriate when slapadd...
authorPierangelo Masarati <ando@openldap.org>
Sun, 26 Aug 2007 15:39:45 +0000 (15:39 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 26 Aug 2007 15:39:45 +0000 (15:39 +0000)
servers/slapd/schema_init.c
servers/slapd/slapadd.c
servers/slapd/syncrepl.c

index 65dcd939fe5c836f05e7abd5c0da55ddbcb768bb..900f35a5d44d323cd574d92429c77789cc5e365e 100644 (file)
@@ -2431,7 +2431,7 @@ numericStringNormalize(
                }
        }
 
-       /* we should have copied no more then is in val */
+       /* we should have copied no more than is in val */
        assert( (q - normalized->bv_val) <= (p - val->bv_val) );
 
        /* null terminate */
@@ -3478,6 +3478,84 @@ done:
        return rc;
 }
 
+/* Normalize a SID as used inside a CSN:
+ * three-digit numeric string */
+static int
+SIDNormalize(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       if ( val->bv_len != 3 ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       if ( !ASCII_DIGIT( val->bv_val[ 0 ] ) || 
+               !ASCII_DIGIT( val->bv_val[ 1 ] ) ||
+               !ASCII_DIGIT( val->bv_val[ 2 ] ) )
+       {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       ber_dupbv_x( normalized, val, ctx );
+
+       return LDAP_SUCCESS;
+}
+
+/* Normalize a SID as used inside a CSN, either as-is
+ * (assertion value) or extracted from the CSN
+ * (attribute value) */
+static int
+csnSIDNormalize(
+       slap_mask_t usage,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *val,
+       struct berval *normalized,
+       void *ctx )
+{
+       struct berval   bv;
+       char            *ptr;
+
+       if ( BER_BVISEMPTY( val ) ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
+               return SIDNormalize( 0, NULL, NULL, val, normalized, ctx );
+       }
+
+       assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
+
+       ptr = ber_bvchr( val, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
+
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_val = ptr + 1;
+       bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
+               
+       ptr = ber_bvchr( &bv, '#' );
+       if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       bv.bv_len = ptr - bv.bv_val;
+
+       return SIDNormalize( 0, NULL, NULL, &bv, normalized, ctx );
+}
+
 
 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
 /* slight optimization - does not need the start parameter */
@@ -4352,6 +4430,10 @@ static slap_syntax_defs_rec syntax_defs[] = {
        {NULL, 0, NULL, NULL, NULL}
 };
 
+char *csnSIDMatchSyntaxes[] = {
+       "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
+       NULL
+};
 char *certificateExactMatchSyntaxes[] = {
        "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
        NULL
@@ -4777,6 +4859,13 @@ static slap_mrule_defs_rec mrule_defs[] = {
                NULL, NULL,
                "CSNMatch" },
 
+       {"( 1.3.6.1.4.1.4203.666.11.2.4 NAME 'CSNSIDMatch' "
+               "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
+               SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
+               NULL, csnSIDNormalize, octetStringMatch,
+               octetStringIndexer, octetStringFilter,
+               NULL },
+
        /* FIXME: OID is unused, but not registered yet */
        {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
                "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
index f28dd17f224b8098e24b1d6c5385311688742271..67012911069b30d823febb9ea7006cd7865fa7be 100644 (file)
@@ -39,7 +39,7 @@
 #include "slapcommon.h"
 
 static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
-static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
+static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE * ( SLAP_SYNC_SID_MAX + 1 ) ];
 
 int
 slapadd( int argc, char **argv )
@@ -51,7 +51,9 @@ slapadd( int argc, char **argv )
        const char *progname = "slapadd";
 
        struct berval csn;
-       struct berval maxcsn;
+       struct berval maxcsn[ SLAP_SYNC_SID_MAX + 1 ];
+       MatchingRule *mr_csnsid;
+       unsigned long sid;
        struct berval bvtext;
        Attribute *attr;
        Entry *ctxcsn_e;
@@ -102,8 +104,13 @@ slapadd( int argc, char **argv )
        }
 
        if ( update_ctxcsn ) {
-               maxcsn.bv_val = maxcsnbuf;
-               maxcsn.bv_len = 0;
+               mr_csnsid = mr_find( "CSNSIDMatch" );
+               assert( mr_csnsid != NULL );
+               maxcsn[ 0 ].bv_val = maxcsnbuf;
+               for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+                       maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_LUTIL_CSNSTR_BUFSIZE;
+                       maxcsn[ sid ].bv_len = 0;
+               }
        }
 
        /* nextline is the line number of the end of the current entry */
@@ -273,19 +280,37 @@ slapadd( int argc, char **argv )
                        }
 
                        if ( update_ctxcsn ) {
+                               struct berval   nsid;
+
                                attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
-                               if ( maxcsn.bv_len != 0 ) {
-                                       match = 0;
-                                       value_match( &match, slap_schema.si_ad_entryCSN,
-                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
-                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               &maxcsn, &attr->a_nvals[0], &text );
+                               assert( attr != NULL );
+                               
+                               rc = mr_csnsid->smr_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                       NULL, NULL, &attr->a_nvals[ 0 ], &nsid, NULL );
+                               assert( rc == LDAP_SUCCESS );
+                               rc = lutil_atoulx( &sid, nsid.bv_val, 16 );
+                               ber_memfree( nsid.bv_val );
+                               if ( rc ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: could not "
+                                               "extract SID from entryCSN=%s\n",
+                                               progname, attr->a_nvals[ 0 ].bv_val, 0 );
+
                                } else {
-                                       match = -1;
-                               }
-                               if ( match < 0 ) {
-                                       strcpy( maxcsn.bv_val, attr->a_nvals[0].bv_val );
-                                       maxcsn.bv_len = attr->a_nvals[0].bv_len;
+                                       assert( sid <= SLAP_SYNC_SID_MAX );
+
+                                       if ( maxcsn[ sid ].bv_len != 0 ) {
+                                               match = 0;
+                                               value_match( &match, slap_schema.si_ad_entryCSN,
+                                                       slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+                                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       &maxcsn[ sid ], &attr->a_nvals[0], &text );
+                                       } else {
+                                               match = -1;
+                                       }
+                                       if ( match < 0 ) {
+                                               strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val );
+                                               maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len;
+                                       }
                                }
                        }
                }
@@ -317,7 +342,7 @@ slapadd( int argc, char **argv )
        bvtext.bv_val = textbuf;
        bvtext.bv_val[0] = '\0';
 
-       if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && maxcsn.bv_len ) {
+       if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) {
                ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix );
                if ( ctxcsn_id == NOID ) {
                        fprintf( stderr, "%s: context entry is missing\n", progname );
@@ -325,33 +350,78 @@ slapadd( int argc, char **argv )
                } else {
                        ctxcsn_e = be->be_entry_get( be, ctxcsn_id );
                        if ( ctxcsn_e != NULL ) {
-                               attr = attr_find( ctxcsn_e->e_attrs,
-                                                                       slap_schema.si_ad_contextCSN );
+                               attr = attr_find( ctxcsn_e->e_attrs, slap_schema.si_ad_contextCSN );
                                if ( attr ) {
-                                       value_match( &match, slap_schema.si_ad_entryCSN,
-                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
-                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
-                                               &maxcsn, &attr->a_nvals[0], &text );
-                                       if ( match > 0 ) {
-                                               AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
-                                               attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
-                                               attr->a_vals[0].bv_len = maxcsn.bv_len;
+                                       int             i;
+
+                                       for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
+                                               struct berval   nsid;
+
+                                               rc = mr_csnsid->smr_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       NULL, NULL, &attr->a_nvals[ i ], &nsid, NULL );
+
+                                               /* must succeed, since it passed
+                                                * validation/normalization */
+                                               assert( rc == LDAP_SUCCESS );
+
+                                               rc = lutil_atoulx( &sid, nsid.bv_val, 16 );
+                                               ber_memfree( nsid.bv_val );
+
+                                               if ( rc ) {
+                                                       Debug( LDAP_DEBUG_ANY,
+                                                               "%s: unable to extract SID "
+                                                               "from #%d contextCSN=%s\n",
+                                                               progname, i,
+                                                               attr->a_nvals[ i ].bv_val );
+                                                       continue;
+                                               }
+
+                                               if ( maxcsn[ sid ].bv_len == 0 ) {
+                                                       match = -1;
+
+                                               } else {
+                                                       value_match( &match, slap_schema.si_ad_entryCSN,
+                                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+                                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                               &maxcsn[ sid ], &attr->a_nvals[i], &text );
+                                               }
+
+                                               if ( match < 0 ) {
+                                                       AC_MEMCPY( maxcsn[ sid ].bv_val,
+                                                               attr->a_nvals[ i ].bv_val,
+                                                               attr->a_nvals[ i ].bv_len );
+                                                       maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0';
+                                                       maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len;
+                                               }
                                        }
-                               } else {
-                                       match = 1;
-                                       attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN, &maxcsn, NULL );
+
+#if 0
+                                       if ( attr->a_nvals && attr->a_nvals != attr->a_vals ) {
+                                               ber_bvarray_free( attr->a_nvals );
+                                       }
+                                       ber_bvarray_free( attr->a_vals );
+#endif
+
+                                       attr->a_vals = NULL;
+                                       attr->a_nvals = NULL;
                                }
-                               if ( match > 0 ) {
-                                       ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
-                                       if( ctxcsn_id == NOID ) {
-                                               fprintf( stderr, "%s: could not modify ctxcsn\n",
-                                                                               progname);
-                                               rc = EXIT_FAILURE;
-                                       } else if ( verbose ) {
-                                               fprintf( stderr, "modified: \"%s\" (%08lx)\n",
-                                                                                ctxcsn_e->e_dn, (long) ctxcsn_id );
+
+                               for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+                                       if ( maxcsn[ sid ].bv_len ) {
+                                               attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN,
+                                                       &maxcsn[ sid], NULL );
                                        }
                                }
+                       
+                               ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
+                               if( ctxcsn_id == NOID ) {
+                                       fprintf( stderr, "%s: could not modify ctxcsn\n",
+                                               progname);
+                                       rc = EXIT_FAILURE;
+                               } else if ( verbose ) {
+                                       fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+                                               ctxcsn_e->e_dn, (long) ctxcsn_id );
+                               }
                        }
                } 
        }
index 8e0ed215a42bd95f7a1b0bccad371a5aa2567d0e..404f9579a5292a1aa3d78708d010b12d48fe5e76 100644 (file)
@@ -2856,11 +2856,12 @@ dn_callback(
                                new = attr_find( dni->new_entry->e_attrs,
                                        slap_schema.si_ad_entryCSN );
                                if ( new && old ) {
-                                       int len = old->a_vals[0].bv_len;
+                                       int rc, len = old->a_vals[0].bv_len;
                                        if ( len > new->a_vals[0].bv_len )
                                                len = new->a_vals[0].bv_len;
-                                       if ( memcmp( old->a_vals[0].bv_val,
-                                               new->a_vals[0].bv_val, len ) >= 0 ) {
+                                       rc = memcmp( old->a_vals[0].bv_val,
+                                               new->a_vals[0].bv_val, len );
+                                       if ( rc > 0 ) {
                                                Debug( LDAP_DEBUG_SYNC,
                                                        "dn_callback : new entry is older than ours "
                                                        "%s ours %s, new %s\n",
@@ -2868,6 +2869,14 @@ dn_callback(
                                                        old->a_vals[0].bv_val,
                                                        new->a_vals[0].bv_val );
                                                return LDAP_SUCCESS;
+                                       } else if ( rc == 0 ) {
+                                               Debug( LDAP_DEBUG_SYNC,
+                                                       "dn_callback : entries have identical CSN "
+                                                       "%s ours %s, new %s\n",
+                                                       rs->sr_entry->e_name.bv_val,
+                                                       old->a_vals[0].bv_val,
+                                                       new->a_vals[0].bv_val );
+                                               return LDAP_SUCCESS;
                                        }
                                }