List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:September 29 2009 11:18am
Subject:bzr commit into mysql-5.4.5-next-mr branch (alik:2884) Bug#43006
View as plain text  
#At file:///mnt/raid/alik/MySQL/bzr/ipv6/mysql-next-mr-ipv6/ based on revid:alik@stripped

 2884 Alexander Nozdrin	2009-09-29
      Backporting patch for Bug#43006 from 6.0.
      Revision in mysql-6.0-codebase:
      
        ------------------------------------------------------------
        revno: 2617.69.6
        committer: Alexander Nozdrin <alik@stripped>
        branch nick: azalea-bf-bug45584
        timestamp: Wed 2009-08-05 21:38:11 +0400
        message:
          Fix for Bug#43006 (main.skip_name_resolve fails on Windows in PB2).
          
          The problem consisted of two parts:
          
            - Windows resolves localhost to IPv6 '::1' address, instead of IPv4
              '127.0.0.1', which is supposed by the server configuration.
          
              To fix this issue a new grant to root@'::1' should be added into
              mysql.user at database initialization
              (mysql_system_tables_data.sql)
          
            - ACL module didn't take IPv6 addresses into account.
          
              When name resolving is off, the ACL module checks every hostname
              from mysql.user whether it requires name resolving or not. The
              code was written at IPv4 era, so it treated '::1' as a hostname.
          
              In order to fix this issue, the ACL code was improved. The code
              now supposes that:
          
                - if a string contains any symbol from the {':', '%', '_', '/'}
                  set, it is an IPv6 address, or a patter, or a IPv4 network
                  address. Thus the string should not be resolved.
          
                - if after that the string contains only digits and dots, it is
                  an IPv4 address. Thus the string should not be resolved.
                  Otherwise, it is a host name and should be resolved.
        ------------------------------------------------------------

    modified:
      scripts/mysql_system_tables_data.sql
      sql/sql_acl.cc
=== modified file 'scripts/mysql_system_tables_data.sql'
--- a/scripts/mysql_system_tables_data.sql	2008-10-03 15:54:22 +0000
+++ b/scripts/mysql_system_tables_data.sql	2009-09-29 11:18:11 +0000
@@ -24,6 +24,7 @@ set @current_hostname= @@hostname;
 INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
 REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost';
 REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+REPLACE INTO tmp_user VALUES (':1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
 INSERT INTO tmp_user (host,user) VALUES ('localhost','');
 INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost';
 INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2009-09-17 09:20:11 +0000
+++ b/sql/sql_acl.cc	2009-09-29 11:18:11 +0000
@@ -1784,24 +1784,83 @@ static bool compare_hostname(const acl_h
 	  (ip && !wild_compare(ip, host->hostname, 0)));
 }
 
+/**
+  Check if the given host name needs to be resolved or not.
+  Host name has to be resolved if it actually contains *name*.
+
+  For example:
+    192.168.1.1               --> FALSE
+    192.168.1.0/255.255.255.0 --> FALSE
+    %                         --> FALSE
+    192.168.1.%               --> FALSE
+    AB%                       --> FALSE
+
+    AAAAFFFF                  --> TRUE (Hostname)
+    AAAA:FFFF:1234:5678       --> FALSE
+    ::1                       --> FALSE
+
+  This function does not check if the given string is a valid host name or
+  not. It assumes that the argument is a valid host name.
+
+  @param hostname   the string to check.
+
+  @return a flag telling if the argument needs to be resolved or not.
+  @retval TRUE the argument is a host name and needs to be resolved.
+  @retval FALSE the argument is either an IP address, or a patter and
+          should not be resolved.
+*/
+
 bool hostname_requires_resolving(const char *hostname)
 {
-  char cur;
   if (!hostname)
     return FALSE;
-  size_t namelen= strlen(hostname);
-  size_t lhlen= strlen(my_localhost);
-  if ((namelen == lhlen) &&
-      !my_strnncoll(system_charset_info, (const uchar *)hostname,  namelen,
-		    (const uchar *)my_localhost, strlen(my_localhost)))
+
+  /* Check if hostname is the localhost. */
+
+  size_t hostname_len= strlen(hostname);
+  size_t localhost_len= strlen(my_localhost);
+
+  if (hostname == my_localhost ||
+      hostname_len == localhost_len &&
+      !my_strnncoll(system_charset_info,
+                    (const uchar *) hostname,  hostname_len,
+		    (const uchar *) my_localhost, strlen(my_localhost)))
+  {
     return FALSE;
-  for (; (cur=*hostname); hostname++)
+  }
+
+  /*
+    If the string contains any of {':', '%', '_', '/'}, it is definitely
+    not a host name:
+      - ':' means that the string is an IPv6 address;
+      - '%' or '_' means that the string is a pattern;
+      - '/' means that the string is an IPv4 network address;
+  */
+
+  for (const char *p= hostname; *p; ++p)
   {
-    if ((cur != '%') && (cur != '_') && (cur != '.') && (cur != '/') &&
-	((cur < '0') || (cur > '9')))
-      return TRUE;
+    switch (*p) {
+      case ':':
+      case '%':
+      case '_':
+      case '/':
+        return FALSE;
+    }
   }
-  return FALSE;
+
+  /*
+    Now we have to tell a host name (ab.cd, 12.ab) from an IPv4 address
+    (12.34.56.78). The assumption is that if the string contains only
+    digits and dots, it is an IPv4 address. Otherwise -- a host name.
+  */
+
+  for (const char *p= hostname; *p; ++p)
+  {
+    if (*p != '.' && !my_isdigit(&my_charset_latin1, *p))
+      return TRUE; /* a "letter" has been found. */
+  }
+
+  return FALSE; /* all characters are either dots or digits. */
 }
 
 


Attachment: [text/bzr-bundle] bzr/alik@sun.com-20090929111811-edilgztmg4e3yz15.bundle
Thread
bzr commit into mysql-5.4.5-next-mr branch (alik:2884) Bug#43006Alexander Nozdrin29 Sep