Allow multiple IDN xn-- indicators
authorRich Salz <rsalz@openssl.org>
Mon, 12 Jan 2015 17:39:00 +0000 (12:39 -0500)
committerRich Salz <rsalz@openssl.org>
Mon, 12 Jan 2015 17:40:29 +0000 (12:40 -0500)
Update the X509v3 name parsing to allow multiple xn-- international
domain name indicators in a name.  Previously, only allowed one at
the beginning of a name, which was wrong.

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
(cherry picked from commit 31d1d3741f16bd80ec25f72dcdbf6bbdc5664374)

crypto/x509v3/v3_utl.c

index 10a7aa876aa4ed472bc36a45377a5635e7330086..c9a6e79838c36f7528745883b20613ad9bf09da6 100644 (file)
@@ -752,7 +752,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
                        {
                        int atstart = (state & LABEL_START);
                        int atend = (i == len - 1 || p[i+i] == '.');
-                       /*
+                       /*-
                         * At most one wildcard per pattern.
                         * No wildcards in IDNA labels.
                         * No wildcards after the first label.
@@ -769,45 +769,26 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
                        star = &p[i];
                        state &= ~LABEL_START;
                        }
-               else if ((state & LABEL_START) != 0)
-                       {
-                       /*
-                        * At the start of a label, skip any "xn--" and
-                        * remain in the LABEL_START state, but set the
-                        * IDNA label state
-                        */
-                       if ((state & LABEL_IDNA) == 0 && len - i >= 4
-                           && strncasecmp((char *)&p[i], "xn--", 4) == 0)
-                               {
-                               i += 3;
-                               state |= LABEL_IDNA;
-                               continue;
-                               }
-                       /* Labels must start with a letter or digit */
-                       state &= ~LABEL_START;
-                       if (('a' <= p[i] && p[i] <= 'z')
-                           || ('A' <= p[i] && p[i] <= 'Z')
-                           || ('0' <= p[i] && p[i] <= '9'))
-                               continue;
-                       return NULL;
-                       }
                else if (('a' <= p[i] && p[i] <= 'z')
                         || ('A' <= p[i] && p[i] <= 'Z')
                         || ('0' <= p[i] && p[i] <= '9'))
                        {
-                       state &= LABEL_IDNA;
-                       continue;
+                       if ((state & LABEL_START) != 0
+                           && len - i >= 4
+                           && strncasecmp((char *)&p[i], "xn--", 4) == 0)
+                               state |= LABEL_IDNA;
+                       state &= ~(LABEL_HYPHEN|LABEL_START);
                        }
                else if (p[i] == '.')
                        {
-                       if (state & (LABEL_HYPHEN | LABEL_START))
+                       if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
                                return NULL;
                        state = LABEL_START;
                        ++dots;
                        }
                else if (p[i] == '-')
                        {
-                       if (state & LABEL_HYPHEN)
+                       if ((state & LABEL_HYPHEN) != 0)
                                return NULL;
                        state |= LABEL_HYPHEN;
                        }