From: Howard Chu Date: Mon, 1 Oct 2007 06:55:02 +0000 (+0000) Subject: ITS#5070 use lutil_str2bin() for certificate serialNumbers X-Git-Tag: OPENLDAP_REL_ENG_2_4_9~20^2~574 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=4ad821910c8826ec501a332101bc2f69582e8aac;p=openldap ITS#5070 use lutil_str2bin() for certificate serialNumbers Still need to fix serialNumberAndIssuerPretty to accept hex --- diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 220ff84fe8..79dfba72d4 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -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