]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/schema_init.c
Added bdb_attribute and bdb_group ACL support routines
[openldap] / servers / slapd / schema_init.c
index 1116854d4d557ebb1276252545918011f11d37cd..f55e6d93183d237d8a8a929aa1e5c5ff9c6a5b9b 100644 (file)
@@ -255,7 +255,7 @@ dnNormalize(
 
        if ( val->bv_len != 0 ) {
                char *dn;
-               out = ber_bvstr( UTF8normalize( val->bv_val, UTF8_CASEFOLD ) );
+               out = ber_bvstr( UTF8normalize( val, UTF8_CASEFOLD ) );
 
                dn = dn_validate( out->bv_val );
 
@@ -331,13 +331,10 @@ nameUIDValidate(
                                break;
                        }
                }
-               if( dn->bv_val[i] != '\'' ) {
-                       return LDAP_INVALID_SYNTAX;
-               }
-               if( dn->bv_val[i-1] != 'B' ) {
-                       return LDAP_INVALID_SYNTAX;
-               }
-               if( dn->bv_val[i-2] != '#' ) {
+               if( dn->bv_val[i] != '\'' ||
+                   dn->bv_val[i-1] != 'B' ||
+                   dn->bv_val[i-2] != '#' ) {
+                       ber_bvfree( dn );
                        return LDAP_INVALID_SYNTAX;
                }
 
@@ -620,7 +617,7 @@ UTF8SubstringsassertionNormalize(
        }
 
        if( sa->sa_initial != NULL ) {
-               nsa->sa_initial = ber_bvstr( UTF8normalize( sa->sa_initial->bv_val, casefold ) );
+               nsa->sa_initial = ber_bvstr( UTF8normalize( sa->sa_initial, casefold ) );
                if( nsa->sa_initial == NULL ) {
                        goto err;
                }
@@ -632,7 +629,7 @@ UTF8SubstringsassertionNormalize(
                }
                nsa->sa_any = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
                for( i=0; sa->sa_any[i] != NULL; i++ ) {
-                       nsa->sa_any[i] = ber_bvstr( UTF8normalize( sa->sa_any[i]->bv_val, casefold ) );
+                       nsa->sa_any[i] = ber_bvstr( UTF8normalize( sa->sa_any[i], casefold ) );
                        if( nsa->sa_any[i] == NULL ) {
                                goto err;
                        }
@@ -641,7 +638,7 @@ UTF8SubstringsassertionNormalize(
        }
 
        if( sa->sa_final != NULL ) {
-               nsa->sa_final = ber_bvstr( UTF8normalize( sa->sa_final->bv_val, casefold ) );
+               nsa->sa_final = ber_bvstr( UTF8normalize( sa->sa_final, casefold ) );
                if( nsa->sa_final == NULL ) {
                        goto err;
                }
@@ -650,9 +647,9 @@ UTF8SubstringsassertionNormalize(
        return nsa;
 
 err:
-       ch_free( nsa->sa_final );
+       ber_bvfree( nsa->sa_final );
        ber_bvecfree( nsa->sa_any );
-       ch_free( nsa->sa_initial );
+       ber_bvfree( nsa->sa_initial );
        ch_free( nsa );
        return NULL;
 }
@@ -700,23 +697,23 @@ approxMatch(
        struct berval *value,
        void *assertedValue )
 {
-       char *val, *assertv, **values, **words, *c;
+       char *val, *nval, *assertv, **values, **words, *c;
        int i, count, len, nextchunk=0, nextavail=0;
        size_t avlen;
 
        /* Yes, this is necessary */
-       val = UTF8normalize( value->bv_val, UTF8_NOCASEFOLD );
-       if( val == NULL ) {
+       nval = UTF8normalize( value, UTF8_NOCASEFOLD );
+       if( nval == NULL ) {
                *matchp = 1;
                return LDAP_SUCCESS;
        }
-       strip8bitChars( val );
+       strip8bitChars( nval );
 
        /* Yes, this is necessary */
-       assertv = UTF8normalize( ((struct berval *)assertedValue)->bv_val,
+       assertv = UTF8normalize( ((struct berval *)assertedValue),
                                 UTF8_NOCASEFOLD );
        if( assertv == NULL ) {
-               free( val );
+               ch_free( nval );
                *matchp = 1;
                return LDAP_SUCCESS;
        }
@@ -724,7 +721,7 @@ approxMatch(
        avlen = strlen( assertv );
 
        /* Isolate how many words there are */
-       for( c=val,count=1; *c; c++ ) {
+       for( c=nval,count=1; *c; c++ ) {
                c = strpbrk( c, SLAPD_APPROX_DELIMITER );
                if ( c == NULL ) break;
                *c = '\0';
@@ -734,7 +731,7 @@ approxMatch(
        /* Get a phonetic copy of each word */
        words = (char **)ch_malloc( count * sizeof(char *) );
        values = (char **)ch_malloc( count * sizeof(char *) );
-       for( c=val,i=0;  i<count;  i++,c+=strlen(c)+1 ) {
+       for( c=nval,i=0;  i<count;  i++,c+=strlen(c)+1 ) {
                words[i] = c;
                values[i] = phonetic(c);
        }
@@ -770,6 +767,7 @@ approxMatch(
                                        break;
                                }
                        }
+                       ch_free( val );
                }
 
                /* This chunk in the asserted value was NOT within the *value. */
@@ -797,7 +795,7 @@ approxMatch(
        }
        ch_free( values );
        ch_free( words );
-       free( val );
+       ch_free( nval );
 
        return LDAP_SUCCESS;
 }
@@ -818,7 +816,7 @@ approxIndexer(
 
        for( j=0; values[j] != NULL; j++ ) {
                /* Yes, this is necessary */
-               val = UTF8normalize( values[j]->bv_val, UTF8_NOCASEFOLD );
+               val = UTF8normalize( values[j], UTF8_NOCASEFOLD );
                strip8bitChars( val );
 
                /* Isolate how many words there are. There will be a key for each */
@@ -871,7 +869,7 @@ approxFilter(
        struct berval **keys;
 
        /* Yes, this is necessary */
-       val = UTF8normalize( ((struct berval *)assertValue)->bv_val,
+       val = UTF8normalize( ((struct berval *)assertValue),
                             UTF8_NOCASEFOLD );
        if( val == NULL ) {
                keys = (struct berval **)ch_malloc( sizeof(struct berval *) );
@@ -926,14 +924,14 @@ approxMatch(
        char *s, *t;
 
        /* Yes, this is necessary */
-       s = UTF8normalize( value->bv_val, UTF8_NOCASEFOLD );
+       s = UTF8normalize( value, UTF8_NOCASEFOLD );
        if( s == NULL ) {
                *matchp = 1;
                return LDAP_SUCCESS;
        }
 
        /* Yes, this is necessary */
-       t = UTF8normalize( ((struct berval *)assertedValue)->bv_val,
+       t = UTF8normalize( ((struct berval *)assertedValue),
                           UTF8_NOCASEFOLD );
        if( t == NULL ) {
                free( s );
@@ -981,7 +979,7 @@ approxIndexer(
        /* Copy each value and run it through phonetic() */
        for( i=0; values[i] != NULL; i++ ) {
                /* Yes, this is necessary */
-               s = UTF8normalize( values[i]->bv_val, UTF8_NOCASEFOLD );
+               s = UTF8normalize( values[i], UTF8_NOCASEFOLD );
 
                /* strip 8-bit chars and run through phonetic() */
                keys[i] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
@@ -1010,7 +1008,7 @@ approxFilter(
        keys = (struct berval **)ch_malloc( sizeof( struct berval * ) * 2 );
 
        /* Yes, this is necessary */
-       s = UTF8normalize( ((struct berval *)assertValue)->bv_val,
+       s = UTF8normalize( ((struct berval *)assertValue),
                             UTF8_NOCASEFOLD );
        if( s == NULL ) {
                keys[0] = NULL;
@@ -1061,7 +1059,7 @@ caseExactIgnoreSubstringsMatch(
        casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
                ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
 
-       nav = UTF8normalize( value->bv_val, casefold );
+       nav = UTF8normalize( value, casefold );
        if( nav == NULL ) {
                match = 1;
                goto done;
@@ -1152,6 +1150,11 @@ retry:
 
                        if( idx >= left.bv_len ) {
                                /* this shouldn't happen */
+                               free( nav );
+                               ch_free( sub->sa_final );
+                               ber_bvecfree( sub->sa_any );
+                               ch_free( sub->sa_initial );
+                               ch_free( sub );
                                return LDAP_OTHER;
                        }
 
@@ -1183,9 +1186,9 @@ retry:
 done:
        free( nav );
        if( sub != NULL ) {
-               ch_free( sub->sa_final );
+               ber_bvfree( sub->sa_final );
                ber_bvecfree( sub->sa_any );
-               ch_free( sub->sa_initial );
+               ber_bvfree( sub->sa_initial );
                ch_free( sub );
        }
        *matchp = match;
@@ -1229,7 +1232,7 @@ int caseExactIgnoreIndexer(
 
        for( i=0; values[i] != NULL; i++ ) {
                struct berval *value;
-               value = ber_bvstr( UTF8normalize( values[i]->bv_val,
+               value = ber_bvstr( UTF8normalize( values[i],
                        casefold ) );
 
                HASH_Init( &HASHcontext );
@@ -1281,7 +1284,7 @@ int caseExactIgnoreFilter(
        casefold = strcmp( mr->smr_oid, caseExactMatchOID )
                ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
 
-       value = ber_bvstr( UTF8normalize( ((struct berval *) assertValue)->bv_val,
+       value = ber_bvstr( UTF8normalize( ((struct berval *) assertValue),
                casefold ) );
        /* This usually happens if filter contains bad UTF8 */
        if( value == NULL ) {
@@ -1350,7 +1353,7 @@ int caseExactIgnoreSubstringsIndexer(
 
        nvalues = ch_malloc( sizeof( struct berval * ) * (i+1) );
        for( i=0; values[i] != NULL; i++ ) {
-               nvalues[i] = ber_bvstr( UTF8normalize( values[i]->bv_val,
+               nvalues[i] = ber_bvstr( UTF8normalize( values[i],
                        casefold ) );
        }
        nvalues[i] = NULL;
@@ -1390,6 +1393,7 @@ int caseExactIgnoreSubstringsIndexer(
        if( nkeys == 0 ) {
                /* no keys to generate */
                *keysp = NULL;
+               ber_bvecfree( nvalues );
                return LDAP_SUCCESS;
        }
 
@@ -1550,6 +1554,10 @@ int caseExactIgnoreSubstringsFilter(
        }
 
        if( nkeys == 0 ) {
+               ber_bvfree( sa->sa_final );
+               ber_bvecfree( sa->sa_any );
+               ber_bvfree( sa->sa_initial );
+               ch_free( sa );
                *keysp = NULL;
                return LDAP_SUCCESS;
        }
@@ -1661,9 +1669,9 @@ int caseExactIgnoreSubstringsFilter(
                ch_free( keys );
                *keysp = NULL;
        }
-       ch_free( sa->sa_final );
+       ber_bvfree( sa->sa_final );
        ber_bvecfree( sa->sa_any );
-       ch_free( sa->sa_initial );
+       ber_bvfree( sa->sa_initial );
        ch_free( sa );
 
        return LDAP_SUCCESS;
@@ -3481,7 +3489,8 @@ asn1_integer2str(ASN1_INTEGER *a)
                                 * Way too large, we need to leave
                                 * room for sign if negative
                                 */
-                         return NULL;
+                               free(copy);
+                               return NULL;
                        }
                        *--p = digit[carry];
                        if (copy[base] == 0)
@@ -3497,6 +3506,7 @@ asn1_integer2str(ASN1_INTEGER *a)
        return ber_bvstrdup(p);
 }
 
+/* Get a DN in RFC2253 format from a X509_NAME internal struct */
 static struct berval *
 dn_openssl2ldap(X509_NAME *name)
 {
@@ -3505,8 +3515,15 @@ dn_openssl2ldap(X509_NAME *name)
 
        bio = BIO_new(BIO_s_mem());
        if ( !bio ) {
-               fprintf(stderr, ERR_error_string(ERR_get_error(),NULL));
-               /* ERR_print_errors(bio_err); */
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                          "dn_openssl2ldap: error creating BIO_s_mem: %s\n",
+                          ERR_error_string(ERR_get_error(),NULL)));
+#else
+               Debug( LDAP_DEBUG_ARGS, "dn_openssl2ldap: "
+                      "error creating BIO: %s\n",
+                      ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
                return NULL;
        }
        X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
@@ -3517,6 +3534,88 @@ dn_openssl2ldap(X509_NAME *name)
        return ber_bvstrdup(issuer_dn);
 }
 
+/*
+ * Given a certificate in DER format, extract the corresponding
+ * assertion value for certificateExactMatch
+ */
+static int
+certificateExactConvert(
+       struct berval * in,
+       struct berval ** out )
+{
+       X509 *xcert;
+       unsigned char *p = in->bv_val;
+       struct berval *serial;
+       struct berval *issuer_dn;
+       struct berval *bv_tmp;
+       int ret;
+
+       xcert = d2i_X509(NULL, &p, in->bv_len);
+       if ( !xcert ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                          "certificateExactConvert: error parsing cert: %s\n",
+                          ERR_error_string(ERR_get_error(),NULL)));
+#else
+               Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
+                      "error parsing cert: %s\n",
+                      ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       serial = asn1_integer2str(xcert->cert_info->serialNumber);
+       if ( !serial ) {
+               X509_free(xcert);
+               return LDAP_INVALID_SYNTAX;
+       }
+       issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
+       if ( !issuer_dn ) {
+               X509_free(xcert);
+               ber_bvfree(serial);
+               return LDAP_INVALID_SYNTAX;
+       }
+       /* Actually, dn_openssl2ldap returns in a normalized format, but
+          it is different from our normalized format */
+       bv_tmp = issuer_dn;
+       if ( dnNormalize(NULL, bv_tmp, &issuer_dn) != LDAP_SUCCESS ) {
+               X509_free(xcert);
+               ber_bvfree(serial);
+               ber_bvfree(bv_tmp);
+               return LDAP_INVALID_SYNTAX;
+       }
+       ber_bvfree(bv_tmp);
+
+       X509_free(xcert);
+
+       *out = ch_malloc(sizeof(struct berval));
+       (*out)->bv_len = serial->bv_len + 3 + issuer_dn->bv_len + 1;
+       (*out)->bv_val = ch_malloc((*out)->bv_len);
+       p = (*out)->bv_val;
+       AC_MEMCPY(p, serial->bv_val, serial->bv_len);
+       p += serial->bv_len;
+       AC_MEMCPY(p, " $ ", 3);
+       p += 3;
+       AC_MEMCPY(p, issuer_dn->bv_val, issuer_dn->bv_len);
+       p += issuer_dn->bv_len;
+       *p++ = '\0';
+
+#ifdef NEW_LOGGING
+       LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                  "certificateExactConvert: \n %s\n",
+                  (*out)->bv_val));
+#else
+       Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
+               "\n\t\"%s\"\n",
+               (*out)->bv_val, NULL, NULL );
+#endif
+
+       ber_bvfree(serial);
+       ber_bvfree(issuer_dn);
+
+       return LDAP_SUCCESS;
+}
+
 static int
 serial_and_issuer_parse(
        struct berval *assertion,
@@ -3538,11 +3637,11 @@ serial_and_issuer_parse(
 
        /* p now points at the $ sign, now use begin and end to delimit the
           serial number */
-       while (ASCII_SPACE(*begin++))
-               ;
-       end = p;
-       while (ASCII_SPACE(*end--))
-               ;
+       while (ASCII_SPACE(*begin))
+               begin++;
+       end = p-1;
+       while (ASCII_SPACE(*end))
+               end--;
 
        q = ch_malloc( (end-begin+1)+1 );
        AC_MEMCPY( q, begin, end-begin+1 );
@@ -3552,14 +3651,14 @@ serial_and_issuer_parse(
        /* now extract the issuer, remember p was at the dollar sign */
        begin = p+1;
        end = assertion->bv_val+assertion->bv_len-1;
-       while (ASCII_SPACE(*begin++))
-               ;
+       while (ASCII_SPACE(*begin))
+               begin++;
        /* should we trim spaces at the end too? is it safe always? */
 
        q = ch_malloc( (end-begin+1)+1 );
        AC_MEMCPY( q, begin, end-begin+1 );
        q[end-begin+1] = '\0';
-       *issuer_dn = ber_bvstr(q);
+       *issuer_dn = ber_bvstr(dn_normalize(q));
 
        return LDAP_SUCCESS;
 }
@@ -3583,7 +3682,16 @@ certificateExactMatch(
 
        xcert = d2i_X509(NULL, &p, value->bv_len);
        if ( !xcert ) {
-               ERR_error_string(ERR_get_error(),NULL);
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                          "certificateExactMatch: error parsing cert: %s\n",
+                          ERR_error_string(ERR_get_error(),NULL)));
+#else
+               Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
+                      "error parsing cert: %s\n",
+                      ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+               return LDAP_INVALID_SYNTAX;
        }
 
        serial = asn1_integer2str(xcert->cert_info->serialNumber);
@@ -3604,6 +3712,7 @@ certificateExactMatch(
                asserted_serial);
        if ( ret == LDAP_SUCCESS ) {
                if ( *matchp == 0 ) {
+                       /* We need to normalize everything for dnMatch */
                        ret = dnMatch(
                                matchp,
                                flags,
@@ -3614,6 +3723,20 @@ certificateExactMatch(
                }
        }
 
+#ifdef NEW_LOGGING
+       LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                  "certificateExactMatch: %d\n  %s $ %s\n       %s $   %s\n",
+                  *matchp, serial->bv_val, issuer_dn->bv_val,
+                  asserted->serial->bv_val, asserted_issuer_dn->bv_val));
+#else
+       Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
+               "%d\n\t\"%s $ %s\"\n",
+               *matchp, serial->bv_val, issuer_dn->bv_val );
+       Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
+               asserted_serial->bv_val, asserted_issuer_dn->bv_val,
+               NULL );
+#endif
+
        ber_bvfree(serial);
        ber_bvfree(issuer_dn);
        ber_bvfree(asserted_serial);
@@ -3621,6 +3744,105 @@ certificateExactMatch(
 
        return ret;
 }
+
+/* 
+ * Index generation function
+ * We just index the serials, in most scenarios the issuer DN is one of
+ * a very small set of values.
+ */
+int certificateExactIndexer(
+       slap_mask_t use,
+       slap_mask_t flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *prefix,
+       struct berval **values,
+       struct berval ***keysp )
+{
+       int i;
+       struct berval **keys;
+       X509 *xcert;
+       unsigned char *p;
+       struct berval * serial;
+
+       /* we should have at least one value at this point */
+       assert( values != NULL && values[0] != NULL );
+
+       for( i=0; values[i] != NULL; i++ ) {
+               /* empty -- just count them */
+       }
+
+       keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
+
+       for( i=0; values[i] != NULL; i++ ) {
+               p = values[i]->bv_val;
+               xcert = d2i_X509(NULL, &p, values[i]->bv_len);
+               if ( !xcert ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                           "certificateExactIndexer: error parsing cert: %s\n",
+                               ERR_error_string(ERR_get_error(),NULL)));
+#else
+                       Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
+                              "error parsing cert: %s\n",
+                              ERR_error_string(ERR_get_error(),NULL),
+                              NULL, NULL );
+#endif
+                       /* Do we leak keys on error? */
+                       return LDAP_INVALID_SYNTAX;
+               }
+
+               serial = asn1_integer2str(xcert->cert_info->serialNumber);
+               X509_free(xcert);
+               integerNormalize( slap_schema.si_syn_integer,
+                                 serial,
+                                 &keys[i] );
+               ber_bvfree(serial);
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+                          "certificateExactIndexer: returning: %s\n",
+                          keys[i]->bv_val));
+#else
+               Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
+                      "returning: %s\n",
+                      keys[i]->bv_val,
+                      NULL, NULL );
+#endif
+       }
+
+       keys[i] = NULL;
+       *keysp = keys;
+       return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+/* We think this is always called with a value in matching rule syntax */
+int certificateExactFilter(
+       slap_mask_t use,
+       slap_mask_t flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *prefix,
+       void * assertValue,
+       struct berval ***keysp )
+{
+       struct berval **keys;
+       struct berval *asserted_serial;
+       struct berval *asserted_issuer_dn;
+
+       serial_and_issuer_parse(assertValue,
+                               &asserted_serial,
+                               &asserted_issuer_dn);
+
+       keys = ch_malloc( sizeof( struct berval * ) * 2 );
+       integerNormalize( syntax, asserted_serial, &keys[0] );
+       keys[1] = NULL;
+       *keysp = keys;
+
+       ber_bvfree(asserted_serial);
+       ber_bvfree(asserted_issuer_dn);
+       return LDAP_SUCCESS;
+}
 #endif
 
 static int
@@ -4038,7 +4260,7 @@ struct syntax_defs_rec syntax_defs[] = {
        {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
                0, IA5StringValidate, IA5StringNormalize, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
-               0, integerValidate, integerNormalize, integerPretty},
+               0, integerValidate, integerNormalize, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
                SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
@@ -4081,7 +4303,7 @@ struct syntax_defs_rec syntax_defs[] = {
        {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
                0, NULL, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
-               0, printableStringValidate, IA5StringNormalize, NULL},
+               0, printablesStringValidate, IA5StringNormalize, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
                0, utcTimeValidate, utcTimeNormalize, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
@@ -4103,8 +4325,11 @@ struct syntax_defs_rec syntax_defs[] = {
 
 #ifdef HAVE_TLS
        /* From PKIX */
-       /* These OIDs are not published yet, but have been assigned */
-       {"( 1.3.6.1.4.1.1466.115.121.1.9999 DESC 'Serial Number and Issuer' )",
+       /* These OIDs are not published yet, but will be in the next
+        * I-D for PKIX LDAPv3 schema as have been advanced by David
+        * Chadwick in private mail.
+        */
+       {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
                0, NULL, NULL, NULL},
 #endif
 
@@ -4373,10 +4598,11 @@ struct mrule_defs_rec mrule_defs[] = {
 
 #ifdef HAVE_TLS
        {"( 2.5.13.34 NAME 'certificateExactMatch' "
-               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.9999 )",
+               "SYNTAX 1.2.826.0.1.3344810.7.1 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT,
-               NULL, NULL,
-               certificateExactMatch, NULL, NULL,
+               certificateExactConvert, NULL,
+               certificateExactMatch,
+               certificateExactIndexer, certificateExactFilter,
                NULL},
 #endif
 
@@ -4500,3 +4726,12 @@ schema_init( void )
        schema_init_done = 1;
        return LDAP_SUCCESS;
 }
+
+void
+schema_destroy( void )
+{
+       oc_destroy();
+       at_destroy();
+       mr_destroy();
+       syn_destroy();
+}