From: Pierangelo Masarati Date: Sun, 26 Aug 2007 15:39:45 +0000 (+0000) Subject: add support for CSNSIDMatch; use it to set contextCSN as appropriate when slapadd... X-Git-Tag: OPENLDAP_REL_ENG_2_4_MP~71 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=2132aa3b16d2916f0c7a498fc6fc6b458c174d14;p=openldap add support for CSNSIDMatch; use it to set contextCSN as appropriate when slapadd'ing -w --- diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 65dcd939fe..900f35a5d4 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -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 )", diff --git a/servers/slapd/slapadd.c b/servers/slapd/slapadd.c index f28dd17f22..6701291106 100644 --- a/servers/slapd/slapadd.c +++ b/servers/slapd/slapadd.c @@ -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 ); + } } } } diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 8e0ed215a4..404f9579a5 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -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; } }