@@ -63,8 +63,31 @@ ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
63
63
IMPLEMENT_ASN1_ALLOC_FUNCTIONS (GENERAL_SUBTREE )
64
64
IMPLEMENT_ASN1_ALLOC_FUNCTIONS (NAME_CONSTRAINTS )
65
65
66
+
67
+ #define IA5_OFFSET_LEN (ia5base , offset ) \
68
+ ((ia5base )-> length - ((unsigned char * )(offset ) - (ia5base )- > data ))
69
+
70
+ /* Like memchr but for ASN1_IA5STRING. Additionally you can specify the
71
+ * starting point to search from
72
+ */
73
+ # define ia5memchr (str , start , c ) memchr (start , c , IA5_OFFSET_LEN (str , start ))
74
+
75
+ /* Like memrrchr but for ASN1_IA5STRING */
76
+ static char * ia5memrchr (ASN1_IA5STRING * str , int c )
77
+ {
78
+ int i ;
79
+
80
+ for (i = str -> length ; i > 0 && str -> data [i - 1 ] != c ; i -- ) ;
81
+
82
+ if (i == 0 )
83
+ return NULL ;
84
+
85
+ return (char * )& str -> data [i - 1 ];
86
+ }
87
+
66
88
/*
67
- * We cannot use strncasecmp here because that applies locale specific rules.
89
+ * We cannot use strncasecmp here because that applies locale specific rules. It
90
+ * also doesn't work with ASN1_STRINGs that may have embedded NUL characters.
68
91
* For example in Turkish 'I' is not the uppercase character for 'i'. We need to
69
92
* do a simple ASCII case comparison ignoring the locale (that is why we use
70
93
* numeric constants below).
@@ -89,20 +112,12 @@ static int ia5ncasecmp(const char *s1, const char *s2, size_t n)
89
112
90
113
/* c1 > c2 */
91
114
return 1 ;
92
- } else if (* s1 == 0 ) {
93
- /* If we get here we know that *s2 == 0 too */
94
- return 0 ;
95
115
}
96
116
}
97
117
98
118
return 0 ;
99
119
}
100
120
101
- static int ia5casecmp (const char * s1 , const char * s2 )
102
- {
103
- return ia5ncasecmp (s1 , s2 , SIZE_MAX );
104
- }
105
-
106
121
static void * v2i_NAME_CONSTRAINTS (const X509V3_EXT_METHOD * method ,
107
122
X509V3_CTX * ctx , STACK_OF (CONF_VALUE ) * nval )
108
123
{
@@ -337,7 +352,7 @@ static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen)
337
352
-- utf8_length ;
338
353
339
354
/* Reject *embedded* NULs */
340
- if (( size_t ) utf8_length != strlen (( char * ) utf8_value ) ) {
355
+ if (memchr ( utf8_value , 0 , utf8_length ) != NULL ) {
341
356
OPENSSL_free (utf8_value );
342
357
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX ;
343
358
}
@@ -536,9 +551,14 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
536
551
{
537
552
char * baseptr = (char * )base -> data ;
538
553
char * dnsptr = (char * )dns -> data ;
554
+
539
555
/* Empty matches everything */
540
- if (! * baseptr )
556
+ if (base -> length == 0 )
541
557
return X509_V_OK ;
558
+
559
+ if (dns -> length < base -> length )
560
+ return X509_V_ERR_PERMITTED_VIOLATION ;
561
+
542
562
/*
543
563
* Otherwise can add zero or more components on the left so compare RHS
544
564
* and if dns is longer and expect '.' as preceding character.
@@ -549,7 +569,7 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
549
569
return X509_V_ERR_PERMITTED_VIOLATION ;
550
570
}
551
571
552
- if (ia5casecmp (baseptr , dnsptr ))
572
+ if (ia5ncasecmp (baseptr , dnsptr , base -> length ))
553
573
return X509_V_ERR_PERMITTED_VIOLATION ;
554
574
555
575
return X509_V_OK ;
@@ -560,16 +580,17 @@ static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
560
580
{
561
581
const char * baseptr = (char * )base -> data ;
562
582
const char * emlptr = (char * )eml -> data ;
583
+ const char * baseat = ia5memrchr (base , '@' );
584
+ const char * emlat = ia5memrchr (eml , '@' );
585
+ size_t basehostlen , emlhostlen ;
563
586
564
- const char * baseat = strchr (baseptr , '@' );
565
- const char * emlat = strchr (emlptr , '@' );
566
587
if (!emlat )
567
588
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX ;
568
589
/* Special case: initial '.' is RHS match */
569
- if (!baseat && (* baseptr == '.' )) {
590
+ if (!baseat && base -> length > 0 && (* baseptr == '.' )) {
570
591
if (eml -> length > base -> length ) {
571
592
emlptr += eml -> length - base -> length ;
572
- if (ia5casecmp (baseptr , emlptr ) == 0 )
593
+ if (ia5ncasecmp (baseptr , emlptr , base -> length ) == 0 )
573
594
return X509_V_OK ;
574
595
}
575
596
return X509_V_ERR_PERMITTED_VIOLATION ;
@@ -589,8 +610,10 @@ static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
589
610
baseptr = baseat + 1 ;
590
611
}
591
612
emlptr = emlat + 1 ;
613
+ basehostlen = IA5_OFFSET_LEN (base , baseptr );
614
+ emlhostlen = IA5_OFFSET_LEN (eml , emlptr );
592
615
/* Just have hostname left to match: case insensitive */
593
- if (ia5casecmp (baseptr , emlptr ))
616
+ if (basehostlen != emlhostlen || ia5ncasecmp (baseptr , emlptr , emlhostlen ))
594
617
return X509_V_ERR_PERMITTED_VIOLATION ;
595
618
596
619
return X509_V_OK ;
@@ -601,32 +624,36 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
601
624
{
602
625
const char * baseptr = (char * )base -> data ;
603
626
const char * hostptr = (char * )uri -> data ;
604
- const char * p = strchr ( hostptr , ':' );
627
+ const char * p = ia5memchr ( uri , ( char * ) uri -> data , ':' );
605
628
int hostlen ;
629
+
606
630
/* Check for foo:// and skip past it */
607
- if (!p || (p [1 ] != '/' ) || (p [2 ] != '/' ))
631
+ if (p == NULL
632
+ || IA5_OFFSET_LEN (uri , p ) < 3
633
+ || p [1 ] != '/'
634
+ || p [2 ] != '/' )
608
635
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX ;
609
636
hostptr = p + 3 ;
610
637
611
638
/* Determine length of hostname part of URI */
612
639
613
640
/* Look for a port indicator as end of hostname first */
614
641
615
- p = strchr ( hostptr , ':' );
642
+ p = ia5memchr ( uri , hostptr , ':' );
616
643
/* Otherwise look for trailing slash */
617
- if (! p )
618
- p = strchr ( hostptr , '/' );
644
+ if (p == NULL )
645
+ p = ia5memchr ( uri , hostptr , '/' );
619
646
620
- if (! p )
621
- hostlen = strlen ( hostptr );
647
+ if (p == NULL )
648
+ hostlen = IA5_OFFSET_LEN ( uri , hostptr );
622
649
else
623
650
hostlen = p - hostptr ;
624
651
625
652
if (hostlen == 0 )
626
653
return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX ;
627
654
628
655
/* Special case: initial '.' is RHS match */
629
- if (* baseptr == '.' ) {
656
+ if (base -> length > 0 && * baseptr == '.' ) {
630
657
if (hostlen > base -> length ) {
631
658
p = hostptr + hostlen - base -> length ;
632
659
if (ia5ncasecmp (p , baseptr , base -> length ) == 0 )
0 commit comments