]> git.sur5r.net Git - openldap/commitdiff
ITS#5070 use lutil_str2bin() for certificate serialNumbers
authorHoward Chu <hyc@openldap.org>
Mon, 1 Oct 2007 06:55:02 +0000 (06:55 +0000)
committerHoward Chu <hyc@openldap.org>
Mon, 1 Oct 2007 06:55:02 +0000 (06:55 +0000)
Still need to fix serialNumberAndIssuerPretty to accept hex

servers/slapd/schema_init.c

index 220ff84fe8e04384dd825f551099c28c26da5374..79dfba72d4f2a1b3698c0496092eb8b76f7ce2a4 100644 (file)
@@ -3062,9 +3062,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 );
@@ -3177,8 +3179,26 @@ serialNumberAndIssuerNormalize(
                                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;
@@ -3265,8 +3285,26 @@ serialNumberAndIssuerNormalize(
                                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;
@@ -3301,15 +3339,27 @@ serialNumberAndIssuerNormalize(
 
        if( rc ) return LDAP_INVALID_SYNTAX;
 
-       /* make room from sn + "$" */
+       /* 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 \"\" }" )
-               + sn.bv_len + ni.bv_len;
+               + ( 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;
@@ -3318,7 +3368,17 @@ 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 \"" );
@@ -3336,9 +3396,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
@@ -3378,20 +3441,16 @@ 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 */
 
-       /* Use hex format. [-]0x123456789abcdef
-        * Don't try to make special cases for multi-precision math
-        * support here, normalized values need to be canonical and
-        * consistent from machine to machine.
+       /* Use hex format. '123456789abcdef'H
         */
-       if ( len > sizeof(ber_int_t) ) {
+       {
                unsigned char *ptr;
                char *sptr;
-               char sign = 0;
                
                tag = ber_skip_tag( ber, &len );
                ptr = (unsigned char *)ber->ber_ptr;
@@ -3401,7 +3460,6 @@ certificateExactNormalize(
                if ( ptr[0] & 0x80 ) {
                        if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
                                return LDAP_INVALID_SYNTAX;
-                       sign = -1;
                } else if ( ptr[0] == 0 ) {
                        if (!( ptr[1] & 0x80 ))
                                return LDAP_INVALID_SYNTAX;
@@ -3409,25 +3467,18 @@ certificateExactNormalize(
                        len--;
                }
 
-               seriallen = len * 2 + 3;        /* leading 0x, NUL */
-               if ( sign )
-                       seriallen++;
+               seriallen = len * 2 + 4;        /* quotes, H, NUL */
                if ( seriallen > sizeof( serialbuf ))
                        serial = slap_sl_malloc( seriallen, ctx );
                sptr = serial;
-               if ( sign )
-                       *sptr++ = '-';
-               *sptr++ = '0';
-               *sptr++ = 'x';
+               *sptr++ = '\'';
                for ( i = 0; i<len; i++ ) {
                        sprintf( sptr, "%02x", sign ? 256 - ptr[i] : ptr[i] );
                        sptr += 2;
                }
+               *sptr++ = '\'';
+               *sptr++ = 'H';
                seriallen--;
-
-       } else {
-               tag = ber_get_int( ber, &i );   /* serial */
-               seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
        }
        tag = ber_skip_tag( ber, &len );        /* SignatureAlg */
        ber_skip_data( ber, len );