[Commits] Rev 3126: MDEV-221 - Properly escape command line when starting mysql_install_db in file:///H:/bzr/5.2/

Vladislav Vaintroub wlad at montyprogram.com
Mon Apr 16 16:28:57 EEST 2012


At file:///H:/bzr/5.2/

------------------------------------------------------------
revno: 3126
revision-id: wlad at montyprogram.com-20120416132833-kjz2qqldkck8vgee
parent: sanja at montyprogram.com-20120314100903-a6txqk4l73smh189
fixes bug(s): https://launchpad.net/bugs/983047
committer: Vladislav Vaintroub <wlad at montyprogram.com>
branch nick: 5.2
timestamp: Mon 2012-04-16 15:28:33 +0200
message:
  MDEV-221 - Properly escape command line when starting mysql_install_db 
  since password characters can contain quotes or spaces.
  
  The proper quoting method for command line arguments used here was  extracted from
  http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
  
  Additionally, mysql_install_db.exe now passes root password to "mysqld.exe --bootstrap"
   in hexadecimal form, to handle potential special chars inside password string literal.
-------------- next part --------------
=== modified file 'sql/mysql_install_db.cc'
--- a/sql/mysql_install_db.cc	2011-04-07 23:42:47 +0000
+++ b/sql/mysql_install_db.cc	2012-04-16 13:28:33 +0000
@@ -316,9 +316,9 @@
 
 
 static const char update_root_passwd_part1[]=
-  "UPDATE mysql.user SET Password = PASSWORD('";
+  "UPDATE mysql.user SET Password = PASSWORD(";
 static const char update_root_passwd_part2[]=
-  "') where User='root';\n";
+  ") where User='root';\n";
 static const char remove_default_user_cmd[]= 
   "DELETE FROM mysql.user where User='';\n";
 static const char allow_remote_root_access_cmd[]=
@@ -589,11 +589,19 @@
   }
 
   /* Change root password if requested. */
-  if (opt_password)
+  if (opt_password && opt_password[0])
   {
-    verbose("Changing root password",remove_default_user_cmd);
+    verbose("Setting root password",remove_default_user_cmd);
     fputs(update_root_passwd_part1, in);
-    fputs(opt_password, in);
+
+    /* Use hex encoding for password, to avoid escaping problems.*/
+    fputc('0', in);
+    fputc('x', in);
+    for(int i= 0; opt_password[i]; i++)
+    {
+      fprintf(in,"%02x",opt_password[i]);
+    }
+
     fputs(update_root_passwd_part2, in);
     fflush(in);
   }

=== modified file 'win/packaging/ca/CustomAction.cpp'
--- a/win/packaging/ca/CustomAction.cpp	2011-04-08 00:49:04 +0000
+++ b/win/packaging/ca/CustomAction.cpp	2012-04-16 13:28:33 +0000
@@ -71,6 +71,82 @@
   return WcaFinalize(er); 
 }
 
+/*
+  Escape command line parameter fpr pass to CreateProcess().
+
+  We assume out has enough space to include encoded string 
+  2*wcslen(in) is enough.
+
+  It is assumed that called will add double quotation marks before and after
+  the string.
+*/
+static void EscapeCommandLine(const wchar_t *in, wchar_t *out)
+{
+  const wchar_t special_chars[]=L" \t\n\v\"";
+  bool needs_escaping= false;
+  size_t pos;
+
+  for(int i=0; i< sizeof(special_chars) -1; i++)
+  {
+    if (wcschr(in, special_chars[i]))
+    {
+      needs_escaping = true;
+      break;
+    }
+  }
+
+  if(!needs_escaping)
+  {
+    wcscpy(out, in);
+    return;
+  }
+
+  pos= 0;
+  for(int i = 0 ; ; i++) 
+  {
+    size_t n_backslashes = 0;
+    wchar_t c;
+    while (in[i] == L'\\') 
+    {
+      i++;
+      n_backslashes++;
+    }
+
+    c= in[i];
+    if (c == 0) 
+    {
+      /*
+        Escape all backslashes, but let the terminating double quotation mark 
+        that caller adds be interpreted as a metacharacter.
+      */
+      for(int j= 0; j < 2*n_backslashes;j++)
+      {
+        out[pos++]=L'\\';
+      }
+      break;
+    }
+    else if (c == L'"') 
+    {
+      /*
+        Escape all backslashes and the following double quotation mark.
+      */
+      for(int j= 0; j < 2*n_backslashes + 1; j++)
+      {
+        out[pos++]=L'\\';
+      }
+      out[pos++]= L'"';
+    }
+    else 
+    {
+      /* Backslashes aren't special here. */
+      for (int j=0; j < n_backslashes; j++)
+        out[pos++] = L'\\';
+
+      out[pos++]= c;
+    }
+  }
+  out[pos++]= 0;
+}
 /* 
   Check for if directory is empty during install, 
   sets "<PROPERTY>_NOT_EMPTY" otherise
@@ -460,6 +536,8 @@
   return totalPhys;
 #endif
 }
+
+
 /*
   Checks SERVICENAME, PORT and BUFFERSIZE parameters 
 */
@@ -468,6 +546,8 @@
   wchar_t ServiceName[MAX_PATH]={0};
   wchar_t SkipNetworking[MAX_PATH]={0};
   wchar_t QuickConfig[MAX_PATH]={0};
+  wchar_t Password[MAX_PATH]={0};
+  wchar_t EscapedPassword[2*MAX_PATH+2];
   wchar_t Port[6];
   wchar_t BufferPoolSize[16];
   DWORD PortLen=6;
@@ -510,8 +590,12 @@
     }
   }
 
+  DWORD PasswordLen= MAX_PATH;
+  MsiGetPropertyW (hInstall, L"PASSWORD", Password, &PasswordLen);
+  EscapeCommandLine(Password, EscapedPassword);
+  MsiSetPropertyW(hInstall,L"ESCAPEDPASSWORD",EscapedPassword);
+
   DWORD SkipNetworkingLen= MAX_PATH;
-
   MsiGetPropertyW(hInstall, L"SKIPNETWORKING", SkipNetworking, 
     &SkipNetworkingLen);
   MsiGetPropertyW(hInstall, L"PORT", Port, &PortLen);

=== modified file 'win/packaging/extra.wxs.in'
--- a/win/packaging/extra.wxs.in	2011-10-12 10:07:14 +0000
+++ b/win/packaging/extra.wxs.in	2012-04-16 13:28:33 +0000
@@ -34,6 +34,7 @@
 
     <!-- Root password -->
     <Property Id="PASSWORD" Hidden="yes" Secure="yes" />
+    <Property Id="ESCAPEDPASSWORD" Hidden="yes" Secure="yes" />
     <!-- Database port -->
     <Property Id="PORT" Value="3306" Secure="yes"/>
     <!-- Whether to allow remote access for root user -->
@@ -668,7 +669,7 @@
     <CustomAction Id='PresetDatabaseProperties' BinaryKey='wixca.dll' DllEntry='PresetDatabaseProperties' />
     <CustomAction Id="CreateDatabaseCommand" Property="CreateDatabase"
     Value=
-    "&quot;[#F.bin.mysql_install_db.exe]&quot;  &quot;--service=[SERVICENAME]&quot; --port=[PORT] &quot;--password=[PASSWORD]&quot; &quot;--datadir=[DATADIR]\&quot; [SKIPNETWORKING] [ALLOWREMOTEROOTACCESS] [DEFAULTUSER]"
+    "&quot;[#F.bin.mysql_install_db.exe]&quot;  &quot;--service=[SERVICENAME]&quot; --port=[PORT] &quot;--password=[ESCAPEDPASSWORD]&quot; &quot;--datadir=[DATADIR]\&quot; [SKIPNETWORKING] [ALLOWREMOTEROOTACCESS] [DEFAULTUSER]"
      Execute="immediate"
      HideTarget="yes"
      />
@@ -703,7 +704,7 @@
         <![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]>
       </Custom>
       <Custom Action="ErrorDataDirNotEmpty" After="CheckDataDirectoryEmpty" >DATADIRNOTEMPTY</Custom>
-
+      <Custom Action="CheckDatabaseProperties" Before="CreateDatabaseCommand">SERVICENAME</Custom>
       <Custom Action="CreateDatabaseCommand" After="CostFinalize" >
         <![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]>
       </Custom>



More information about the commits mailing list