]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/schema_init.c
Plug leak
[openldap] / servers / slapd / schema_init.c
index b5cfcc1bc05a73fd0159c57a74dace837d4554ed..f318a7556476370276add4d1c6eb4b38c4c3ddd9 100644 (file)
@@ -222,21 +222,23 @@ static int certificateListValidate( Syntax *syntax, struct berval *in )
        if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
        ber_skip_data( ber, len );
        tag = ber_skip_tag( ber, &len );        /* thisUpdate */
-       /* NOTE: in the certificates I'm playing with, the time is UTC.
-        * maybe the tag is different from 0x17U for generalizedTime? */
-       if ( tag != 0x17U ) return LDAP_INVALID_SYNTAX;
+       /* Time is a CHOICE { UTCTime, GeneralizedTime } */
+       if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
        ber_skip_data( ber, len );
        /* Optional nextUpdate */
        tag = ber_skip_tag( ber, &len );
-       if ( tag == 0x17U ) {
+       if ( tag == 0x17U || tag == 0x18U ) {
                ber_skip_data( ber, len );
                tag = ber_skip_tag( ber, &len );
        }
-       /* Optional revokedCertificates */
+       /* revokedCertificates - Sequence of Sequence, Optional */
        if ( tag == LBER_SEQUENCE ) {
-               /* Should NOT be empty */
-               ber_skip_data( ber, len );
-               tag = ber_skip_tag( ber, &len );
+               ber_len_t seqlen;
+               if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
+                       /* Should NOT be empty */
+                       ber_skip_data( ber, len );
+                       tag = ber_skip_tag( ber, &len );
+               }
        }
        /* Optional Extensions */
        if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
@@ -2346,6 +2348,19 @@ UUIDNormalize(
        unsigned char octet = '\0';
        int i;
        int j;
+
+       if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
+               /* NOTE: must be a normalized UUID */
+               assert( val->bv_len == 16 );
+
+               normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
+               normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
+                       val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
+               assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
+
+               return LDAP_SUCCESS;
+       }
+
        normalized->bv_len = 16;
        normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
 
@@ -2520,45 +2535,44 @@ integerBitOrMatch(
 }
 
 static int
-serialNumberAndIssuerValidate(
-       Syntax *syntax,
-       struct berval *in )
+serialNumberAndIssuerCheck(
+       struct berval *in,
+       struct berval *sn,
+       struct berval *is,
+       void *ctx
+)
 {
-       int rc;
-       ber_len_t n;
-       struct berval sn, i;
-
-       Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
-               in->bv_val, 0, 0 );
+       int is_hex = 0, n;
 
        if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
 
        if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
                /* Parse old format */
-               i.bv_val = ber_bvchr( in, '$' );
-               if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
+               is->bv_val = ber_bvchr( in, '$' );
+               if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
 
-               sn.bv_val = in->bv_val;
-               sn.bv_len = i.bv_val - in->bv_val;
+               sn->bv_val = in->bv_val;
+               sn->bv_len = is->bv_val - in->bv_val;
 
-               i.bv_val++;
-               i.bv_len = in->bv_len - (sn.bv_len + 1);
+               is->bv_val++;
+               is->bv_len = in->bv_len - (sn->bv_len + 1);
 
                /* eat leading zeros */
-               for( n=0; n < (sn.bv_len-1); n++ ) {
-                       if( sn.bv_val[n] != '0' ) break;
+               for( n=0; n < (sn->bv_len-1); n++ ) {
+                       if( sn->bv_val[n] != '0' ) break;
                }
-               sn.bv_val += n;
-               sn.bv_len -= n;
+               sn->bv_val += n;
+               sn->bv_len -= n;
 
-               for( n=0; n < sn.bv_len; n++ ) {
-                       if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
+               for( n=0; n < sn->bv_len; n++ ) {
+                       if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
                }
 
        } else {
                /* Parse GSER format */ 
                int havesn=0,haveissuer=0;
                struct berval x = *in;
+               struct berval ni;
                x.bv_val++;
                x.bv_len-=2;
 
@@ -2584,27 +2598,33 @@ serialNumberAndIssuerValidate(
                        for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
                                /* empty */;
                        }
-                       
+
+                       /* For backward compatibility, this part is optional */
+                       if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
+                               x.bv_val += STRLENOF("rdnSequence:");
+                               x.bv_len -= STRLENOF("rdnSequence:");
+                       }
+
                        if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
                        x.bv_val++; x.bv_len--;
 
-                       i.bv_val = x.bv_val;
-                       i.bv_len = 0;
+                       is->bv_val = x.bv_val;
+                       is->bv_len = 0;
 
-                       for( ; i.bv_len < x.bv_len; ) {
-                               if ( i.bv_val[i.bv_len] != '"' ) {
-                                       i.bv_len++;
+                       for( ; is->bv_len < x.bv_len; ) {
+                               if ( is->bv_val[is->bv_len] != '"' ) {
+                                       is->bv_len++;
                                        continue;
                                }
-                               if ( i.bv_val[i.bv_len+1] == '"' ) {
+                               if ( is->bv_val[is->bv_len+1] == '"' ) {
                                        /* double dquote */
-                                       i.bv_len+=2;
+                                       is->bv_len+=2;
                                        continue;
                                }
                                break;
                        }
-                       x.bv_val += i.bv_len+1;
-                       x.bv_len -= i.bv_len+1;
+                       x.bv_val += is->bv_len+1;
+                       x.bv_len -= is->bv_len+1;
 
                        if ( x.bv_len < STRLENOF(",serialNumber 0")) {
                                return LDAP_INVALID_SYNTAX;
@@ -2628,24 +2648,42 @@ serialNumberAndIssuerValidate(
                                /* empty */;
                        }
                        
-                       sn.bv_val = x.bv_val;
-                       sn.bv_len = 0;
+                       sn->bv_val = x.bv_val;
+                       sn->bv_len = 0;
 
-                       if( sn.bv_val[0] == '-' ) {
+                       if( sn->bv_val[0] == '-' ) {
                                neg++;
-                               sn.bv_len++;
+                               sn->bv_len++;
                        }
 
-                       for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
-                               if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
+                       if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
+                               sn->bv_val[1] == 'X' )) {
+                               is_hex = 1;
+                               for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
+                                       if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
+                               }
+                       } else if ( sn->bv_val[0] == '\'' ) {
+                               for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
+                                       if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
+                               }
+                               if ( sn->bv_val[sn->bv_len] == '\'' &&
+                                       sn->bv_val[sn->bv_len+1] == 'H' )
+                                       is_hex = 1;
+                               else
+                                       return LDAP_INVALID_SYNTAX;
+                               sn->bv_len += 2;
+                       } else {
+                               for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
+                                       if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
+                               }
                        }
 
-                       if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
-                       if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
+                       if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
+                       if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
                                return LDAP_INVALID_SYNTAX;
                        }
 
-                       x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
+                       x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
 
                        if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
                                return LDAP_INVALID_SYNTAX;
@@ -2678,27 +2716,33 @@ serialNumberAndIssuerValidate(
                        for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
                                 /* empty */;
                        }
-                       
+
+                       /* For backward compatibility, this part is optional */
+                       if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
+                               x.bv_val += STRLENOF("rdnSequence:");
+                               x.bv_len -= STRLENOF("rdnSequence:");
+                       }
+
                        if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
                        x.bv_val++; x.bv_len--;
 
-                       i.bv_val = x.bv_val;
-                       i.bv_len = 0;
+                       is->bv_val = x.bv_val;
+                       is->bv_len = 0;
 
-                       for( ; i.bv_len < x.bv_len; ) {
-                               if ( i.bv_val[i.bv_len] != '"' ) {
-                                       i.bv_len++;
+                       for( ; is->bv_len < x.bv_len; ) {
+                               if ( is->bv_val[is->bv_len] != '"' ) {
+                                       is->bv_len++;
                                        continue;
                                }
-                               if ( i.bv_val[i.bv_len+1] == '"' ) {
+                               if ( is->bv_val[is->bv_len+1] == '"' ) {
                                        /* double dquote */
-                                       i.bv_len+=2;
+                                       is->bv_len+=2;
                                        continue;
                                }
                                break;
                        }
-                       x.bv_val += i.bv_len+1;
-                       x.bv_len -= i.bv_len+1;
+                       x.bv_val += is->bv_len+1;
+                       x.bv_len -= is->bv_len+1;
 
                } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
                        STRLENOF("serialNumber")) == 0 ))
@@ -2716,28 +2760,43 @@ serialNumberAndIssuerValidate(
                                /* empty */;
                        }
                        
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       sn.bv_val = x.bv_val;
-                       sn.bv_len = 0;
+                       sn->bv_val = x.bv_val;
+                       sn->bv_len = 0;
 
-                       if( sn.bv_val[0] == '-' ) {
+                       if( sn->bv_val[0] == '-' ) {
                                neg++;
-                               sn.bv_len++;
+                               sn->bv_len++;
                        }
 
-                       for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
-                               if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
+                       if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
+                               sn->bv_val[1] == 'X' )) {
+                               is_hex = 1;
+                               for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
+                                       if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
+                               }
+                       } else if ( sn->bv_val[0] == '\'' ) {
+                               for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
+                                       if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
+                               }
+                               if ( sn->bv_val[sn->bv_len] == '\'' &&
+                                       sn->bv_val[sn->bv_len+1] == 'H' )
+                                       is_hex = 1;
+                               else
+                                       return LDAP_INVALID_SYNTAX;
+                               sn->bv_len += 2;
+                       } else {
+                               for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
+                                       if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
+                               }
                        }
 
-                       if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
-                       if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
+                       if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
+                       if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
                                return LDAP_INVALID_SYNTAX;
                        }
 
-                       x.bv_val += sn.bv_len;
-                       x.bv_len -= sn.bv_len;
+                       x.bv_val += sn->bv_len;
+                       x.bv_len -= sn->bv_len;
 
                } else return LDAP_INVALID_SYNTAX;
 
@@ -2748,15 +2807,42 @@ serialNumberAndIssuerValidate(
 
                /* should have no characters left... */
                if( x.bv_len ) return LDAP_INVALID_SYNTAX;
+
+               ber_dupbv_x( &ni, is, ctx );
+               *is = ni;
+
+               /* need to handle double dquotes here */
        }
+       return 0;
+}
+       
+static int
+serialNumberAndIssuerValidate(
+       Syntax *syntax,
+       struct berval *in )
+{
+       int rc;
+       struct berval sn, i;
+
+       Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
+               in->bv_val, 0, 0 );
+
+       rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
+       if ( rc )
+               return rc;
 
        /* validate DN -- doesn't handle double dquote */ 
        rc = dnValidate( NULL, &i );
-       if( rc ) return LDAP_INVALID_SYNTAX;
+       if( rc )
+               rc = LDAP_INVALID_SYNTAX;
+
+       if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
+               slap_sl_free( i.bv_val, NULL );
+       }
 
        Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
                0, 0, 0 );
-       return LDAP_SUCCESS;
+       return rc;
 }
 
 int
@@ -2766,8 +2852,7 @@ serialNumberAndIssuerPretty(
        struct berval *out,
        void *ctx )
 {
-       int rc;
-       ber_len_t n;
+       int n, rc;
        struct berval sn, i, ni;
 
        assert( in != NULL );
@@ -2776,226 +2861,9 @@ serialNumberAndIssuerPretty(
        Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
                in->bv_val, 0, 0 );
 
-       if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
-
-       if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
-               /* Parse old format */
-               i.bv_val = ber_bvchr( in, '$' );
-               if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
-
-               sn.bv_val = in->bv_val;
-               sn.bv_len = i.bv_val - in->bv_val;
-
-               i.bv_val++;
-               i.bv_len = in->bv_len - (sn.bv_len + 1);
-
-               /* eat leading zeros */
-               for( n=0; n < (sn.bv_len-1); n++ ) {
-                       if( sn.bv_val[n] != '0' ) break;
-               }
-               sn.bv_val += n;
-               sn.bv_len -= n;
-
-               for( n=0; n < sn.bv_len; n++ ) {
-                       if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
-               }
-
-       } else {
-               /* Parse GSER format */ 
-               int havesn=0,haveissuer=0;
-               struct berval x = *in;
-               x.bv_val++;
-               x.bv_len-=2;
-
-               /* eat leading spaces */
-               for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                       /* empty */;
-               }
-
-               if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
-                       return LDAP_INVALID_SYNTAX;
-               }
-
-               /* should be at issuer or serialNumber NamedValue */
-               if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
-                       /* parse issuer */
-                       x.bv_val += STRLENOF("issuer");
-                       x.bv_len -= STRLENOF("issuer");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                               /* empty */;
-                       }
-                       
-                       if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       i.bv_val = x.bv_val;
-                       i.bv_len = 0;
-
-                       for( ; i.bv_len < x.bv_len; ) {
-                               if ( i.bv_val[i.bv_len] != '"' ) {
-                                       i.bv_len++;
-                                       continue;
-                               }
-                               if ( i.bv_val[i.bv_len+1] == '"' ) {
-                                       /* double dquote */
-                                       i.bv_len+=2;
-                                       continue;
-                               }
-                               break;
-                       }
-                       x.bv_val += i.bv_len+1;
-                       x.bv_len -= i.bv_len+1;
-
-                       if ( x.bv_len < STRLENOF(",serialNumber 0")) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       haveissuer++;
-
-               } else if( strncasecmp( x.bv_val, "serialNumber",
-                       STRLENOF("serialNumber")) == 0 )
-               {
-                       /* parse serialNumber */
-                       int neg=0;
-                       x.bv_val += STRLENOF("serialNumber");
-                       x.bv_len -= STRLENOF("serialNumber");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                               /* empty */;
-                       }
-                       
-                       sn.bv_val = x.bv_val;
-                       sn.bv_len = 0;
-
-                       if( sn.bv_val[0] == '-' ) {
-                               neg++;
-                               sn.bv_len++;
-                       }
-
-                       for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
-                               if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
-                       }
-
-                       if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
-                       if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
-
-                       if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       havesn++;
-
-               } else return LDAP_INVALID_SYNTAX;
-
-               if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
-               x.bv_val++; x.bv_len--;
-
-               /* eat spaces */
-               for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                       /* empty */;
-               }
-
-               /* should be at remaining NamedValue */
-               if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
-                       STRLENOF("issuer" )) == 0 ))
-               {
-                       /* parse issuer */
-                       x.bv_val += STRLENOF("issuer");
-                       x.bv_len -= STRLENOF("issuer");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                                /* empty */;
-                       }
-                       
-                       if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       i.bv_val = x.bv_val;
-                       i.bv_len = 0;
-
-                       for( ; i.bv_len < x.bv_len; ) {
-                               if ( i.bv_val[i.bv_len] != '"' ) {
-                                       i.bv_len++;
-                                       continue;
-                               }
-                               if ( i.bv_val[i.bv_len+1] == '"' ) {
-                                       /* double dquote */
-                                       i.bv_len+=2;
-                                       continue;
-                               }
-                               break;
-                       }
-                       x.bv_val += i.bv_len+1;
-                       x.bv_len -= i.bv_len+1;
-
-               } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
-                       STRLENOF("serialNumber")) == 0 ))
-               {
-                       /* parse serialNumber */
-                       int neg=0;
-                       x.bv_val += STRLENOF("serialNumber");
-                       x.bv_len -= STRLENOF("serialNumber");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
-                               /* empty */;
-                       }
-                       
-                       sn.bv_val = x.bv_val;
-                       sn.bv_len = 0;
-
-                       if( sn.bv_val[0] == '-' ) {
-                               neg++;
-                               sn.bv_len++;
-                       }
-
-                       for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
-                               if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
-                       }
-
-                       if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
-                       if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       x.bv_val += sn.bv_len;
-                       x.bv_len -= sn.bv_len;
-
-               } else return LDAP_INVALID_SYNTAX;
-
-               /* eat trailing spaces */
-               for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                       /* empty */;
-               }
-
-               /* should have no characters left... */
-               if( x.bv_len ) return LDAP_INVALID_SYNTAX;
-
-               ber_dupbv_x( &ni, &i, ctx );
-               i = ni;
-
-               /* need to handle double dquotes here */
-       }
+       rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
+       if ( rc )
+               return rc;
 
        rc = dnPretty( syntax, &i, &ni, ctx );
 
@@ -3006,7 +2874,7 @@ serialNumberAndIssuerPretty(
        if( rc ) return LDAP_INVALID_SYNTAX;
 
        /* make room from sn + "$" */
-       out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
+       out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
                + sn.bv_len + ni.bv_len;
        out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
 
@@ -3024,8 +2892,8 @@ serialNumberAndIssuerPretty(
        AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
        n += sn.bv_len;
 
-       AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
-       n += STRLENOF(", issuer \"");
+       AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
+       n += STRLENOF(", issuer rdnSequence:\"");
 
        AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
        n += ni.bv_len;
@@ -3060,9 +2928,11 @@ serialNumberAndIssuerNormalize(
        struct berval *out,
        void *ctx )
 {
+       struct berval sn, sn2, i, ni;
+       char sbuf[64], *stmp = sbuf;
        int rc;
        ber_len_t n;
-       struct berval sn, i, ni;
+       int is_hex = 0;
 
        assert( in != NULL );
        assert( out != NULL );
@@ -3070,226 +2940,9 @@ serialNumberAndIssuerNormalize(
        Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
                in->bv_val, 0, 0 );
 
-       if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
-
-       if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
-               /* Parse old format */
-               i.bv_val = ber_bvchr( in, '$' );
-               if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
-
-               sn.bv_val = in->bv_val;
-               sn.bv_len = i.bv_val - in->bv_val;
-
-               i.bv_val++;
-               i.bv_len = in->bv_len - (sn.bv_len + 1);
-
-               /* eat leading zeros */
-               for( n=0; n < (sn.bv_len-1); n++ ) {
-                       if( sn.bv_val[n] != '0' ) break;
-               }
-               sn.bv_val += n;
-               sn.bv_len -= n;
-
-               for( n=0; n < sn.bv_len; n++ ) {
-                       if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
-               }
-
-       } else {
-               /* Parse GSER format */ 
-               int havesn=0,haveissuer=0;
-               struct berval x = *in;
-               x.bv_val++;
-               x.bv_len-=2;
-
-               /* eat leading spaces */
-               for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                       /* empty */;
-               }
-
-               if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
-                       return LDAP_INVALID_SYNTAX;
-               }
-
-               /* should be at issuer or serialNumber NamedValue */
-               if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
-                       /* parse issuer */
-                       x.bv_val += STRLENOF("issuer");
-                       x.bv_len -= STRLENOF("issuer");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                               /* empty */;
-                       }
-                       
-                       if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       i.bv_val = x.bv_val;
-                       i.bv_len = 0;
-
-                       for( ; i.bv_len < x.bv_len; ) {
-                               if ( i.bv_val[i.bv_len] != '"' ) {
-                                       i.bv_len++;
-                                       continue;
-                               }
-                               if ( i.bv_val[i.bv_len+1] == '"' ) {
-                                       /* double dquote */
-                                       i.bv_len+=2;
-                                       continue;
-                               }
-                               break;
-                       }
-                       x.bv_val += i.bv_len+1;
-                       x.bv_len -= i.bv_len+1;
-
-                       if ( x.bv_len < STRLENOF(",serialNumber 0")) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       haveissuer++;
-
-               } else if( strncasecmp( x.bv_val, "serialNumber",
-                       STRLENOF("serialNumber")) == 0 )
-               {
-                       /* parse serialNumber */
-                       int neg=0;
-                       x.bv_val += STRLENOF("serialNumber");
-                       x.bv_len -= STRLENOF("serialNumber");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                               /* empty */;
-                       }
-                       
-                       sn.bv_val = x.bv_val;
-                       sn.bv_len = 0;
-
-                       if( sn.bv_val[0] == '-' ) {
-                               neg++;
-                               sn.bv_len++;
-                       }
-
-                       for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
-                               if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
-                       }
-
-                       if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
-                       if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
-
-                       if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       havesn++;
-
-               } else return LDAP_INVALID_SYNTAX;
-
-               if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
-               x.bv_val++; x.bv_len--;
-
-               /* eat spaces */
-               for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                       /* empty */;
-               }
-
-               /* should be at remaining NamedValue */
-               if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
-                       STRLENOF("issuer" )) == 0 ))
-               {
-                       /* parse issuer */
-                       x.bv_val += STRLENOF("issuer");
-                       x.bv_len -= STRLENOF("issuer");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                                /* empty */;
-                       }
-                       
-                       if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       i.bv_val = x.bv_val;
-                       i.bv_len = 0;
-
-                       for( ; i.bv_len < x.bv_len; ) {
-                               if ( i.bv_val[i.bv_len] != '"' ) {
-                                       i.bv_len++;
-                                       continue;
-                               }
-                               if ( i.bv_val[i.bv_len+1] == '"' ) {
-                                       /* double dquote */
-                                       i.bv_len+=2;
-                                       continue;
-                               }
-                               break;
-                       }
-                       x.bv_val += i.bv_len+1;
-                       x.bv_len -= i.bv_len+1;
-
-               } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
-                       STRLENOF("serialNumber")) == 0 ))
-               {
-                       /* parse serialNumber */
-                       int neg=0;
-                       x.bv_val += STRLENOF("serialNumber");
-                       x.bv_len -= STRLENOF("serialNumber");
-
-                       if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
-                       x.bv_val++; x.bv_len--;
-
-                       /* eat leading spaces */
-                       for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
-                               /* empty */;
-                       }
-                       
-                       sn.bv_val = x.bv_val;
-                       sn.bv_len = 0;
-
-                       if( sn.bv_val[0] == '-' ) {
-                               neg++;
-                               sn.bv_len++;
-                       }
-
-                       for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
-                               if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
-                       }
-
-                       if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
-                       if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
-                               return LDAP_INVALID_SYNTAX;
-                       }
-
-                       x.bv_val += sn.bv_len;
-                       x.bv_len -= sn.bv_len;
-
-               } else return LDAP_INVALID_SYNTAX;
-
-               /* eat trailing spaces */
-               for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
-                       /* empty */;
-               }
-
-               /* should have no characters left... */
-               if( x.bv_len ) return LDAP_INVALID_SYNTAX;
-
-               ber_dupbv_x( &ni, &i, ctx );
-               i = ni;
-
-               /* need to handle double dquotes here */
-       }
+       rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
+       if ( rc )
+               return rc;
 
        rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
 
@@ -3299,15 +2952,27 @@ serialNumberAndIssuerNormalize(
 
        if( rc ) return LDAP_INVALID_SYNTAX;
 
-       /* make room from sn + "$" */
-       out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
-               + sn.bv_len + ni.bv_len;
+       /* Convert sn to canonical hex */
+       if ( sn.bv_len > sizeof( sbuf )) {
+               stmp = slap_sl_malloc( sn.bv_len, ctx );
+       }
+       sn2.bv_val = stmp;
+       sn2.bv_len = sn.bv_len;
+       if ( lutil_str2bin( &sn, &sn2 )) {
+               rc = LDAP_INVALID_SYNTAX;
+               goto leave;
+       }
+
+       /* make room for sn + "$" */
+       out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
+               + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
        out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
 
        if( out->bv_val == NULL ) {
                out->bv_len = 0;
                slap_sl_free( ni.bv_val, ctx );
-               return LDAP_OTHER;
+               rc = LDAP_OTHER;
+               goto leave;
        }
 
        n = 0;
@@ -3316,10 +2981,20 @@ serialNumberAndIssuerNormalize(
        n = STRLENOF( "{ serialNumber " );
 
        AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
-       n += sn.bv_len;
+       {
+               int j;
+               unsigned char *v = sn2.bv_val;
+               out->bv_val[n++] = '\'';
+               for ( j = 0; j < sn2.bv_len; j++ ) {
+                       sprintf( &out->bv_val[n], "%02X", v[j] );
+                       n += 2;
+               }
+               out->bv_val[n++] = '\'';
+               out->bv_val[n++] = 'H';
+       }
 
-       AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
-       n += STRLENOF( ", issuer \"" );
+       AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
+       n += STRLENOF( ", issuer rdnSequence:\"" );
 
        AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
        n += ni.bv_len;
@@ -3334,9 +3009,12 @@ serialNumberAndIssuerNormalize(
        Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
                out->bv_val, 0, 0 );
 
+leave:
+       if ( stmp != sbuf )
+               slap_sl_free( stmp, ctx );
        slap_sl_free( ni.bv_val, ctx );
 
-       return LDAP_SUCCESS;
+       return rc;
 }
 
 static int
@@ -3376,60 +3054,44 @@ certificateExactNormalize(
                tag = ber_get_int( ber, &i );   /* version */
        }
 
-       /* NOTE: move the test here from certificateNormalize,
+       /* NOTE: move the test here from certificateValidate,
         * so that we can validate certs with serial longer
         * than sizeof(ber_int_t) */
        tag = ber_peek_tag( ber, &len );        /* serial */
-       if ( len > sizeof(ber_int_t) ) {
+
+       /* Use hex format. '123456789abcdef'H
+        */
+       {
                unsigned char *ptr;
+               char *sptr;
                
                tag = ber_skip_tag( ber, &len );
                ptr = (unsigned char *)ber->ber_ptr;
                ber_skip_data( ber, len );
 
-               while ( ptr[0] == '\0' && len > 0 ) {
-                       ptr++;
-                       len--;
-               }
-
-#if defined(USE_MP_BIGNUM)
-               /* TODO */
-
-#elif defined(USE_MP_GMP)
-               /* TODO */
-               /* hint: use mpz_import(), mpz_get_str() */
-
-#elif defined(USE_MP_LONG_LONG)
-               if ( len <= sizeof( unsigned long long ) ) {
-                       unsigned long long      sn = 0;
-                       int                     i;
-
-                       sn = ptr[0];
-
-                       for ( i = 1; i < len; i++ ) {
-                               sn <<= 8;
-                               sn += ptr[i];
+               /* Check for minimal encodings */
+               if ( len > 1 ) {
+                       if ( ptr[0] & 0x80 ) {
+                               if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
+                                       return LDAP_INVALID_SYNTAX;
+                       } else if ( ptr[0] == 0 ) {
+                               if (!( ptr[1] & 0x80 ))
+                                       return LDAP_INVALID_SYNTAX;
                        }
-
-                       seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
-
-               } else {
-                       /* do not accept serialNumber that requires
-                        * more than long long */
-                       rc = LDAP_INVALID_SYNTAX;
-                       goto done;
                }
 
-#else
-               /* do not accept serialNumber that requires
-                * more than long */
-               rc = LDAP_INVALID_SYNTAX;
-               goto done;
-#endif
-
-       } else {
-               tag = ber_get_int( ber, &i );   /* serial */
-               seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
+               seriallen = len * 2 + 4;        /* quotes, H, NUL */
+               if ( seriallen > sizeof( serialbuf ))
+                       serial = slap_sl_malloc( seriallen, ctx );
+               sptr = serial;
+               *sptr++ = '\'';
+               for ( i = 0; i<len; i++ ) {
+                       sprintf( sptr, "%02X", ptr[i] );
+                       sptr += 2;
+               }
+               *sptr++ = '\'';
+               *sptr++ = 'H';
+               seriallen--;
        }
        tag = ber_skip_tag( ber, &len );        /* SignatureAlg */
        ber_skip_data( ber, len );
@@ -3441,7 +3103,7 @@ certificateExactNormalize(
        rc = dnX509normalize( &bvdn, &issuer_dn );
        if( rc != LDAP_SUCCESS ) goto done;
 
-       normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
+       normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
                + seriallen + issuer_dn.bv_len;
        normalized->bv_val = ch_malloc(normalized->bv_len+1);
 
@@ -3453,8 +3115,8 @@ certificateExactNormalize(
        AC_MEMCPY(p, serial, seriallen);
        p += seriallen;
 
-       AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
-       p += STRLENOF( ", issuer \"" );
+       AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
+       p += STRLENOF( ", issuer rdnSequence:\"" );
 
        AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
        p += issuer_dn.bv_len;
@@ -3508,6 +3170,9 @@ hexNormalize(
 {
        int     i;
 
+       assert( val != NULL );
+       assert( normalized != NULL );
+
        ber_dupbv_x( normalized, val, ctx );
 
        for ( i = 0; i < normalized->bv_len; i++ ) {
@@ -3803,6 +3468,9 @@ csnNormalize(
        char            *ptr;
        int             i;
 
+       assert( val != NULL );
+       assert( normalized != NULL );
+
        assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
 
        if ( BER_BVISEMPTY( val ) ) {