summaryrefslogtreecommitdiff
path: root/win
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@montyprogram.com>2012-04-16 15:28:33 +0200
committerVladislav Vaintroub <wlad@montyprogram.com>2012-04-16 15:28:33 +0200
commit4da30b3e3db552894825c5ec94cbdb110d13fbf0 (patch)
tree6a0b6aec93ce58a07220ae3138640d969ebf0555 /win
parente638e605895fb572047ec8027e91c5438d77cbf4 (diff)
downloadmariadb-git-4da30b3e3db552894825c5ec94cbdb110d13fbf0.tar.gz
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.
Diffstat (limited to 'win')
-rw-r--r--win/packaging/ca/CustomAction.cpp86
-rw-r--r--win/packaging/extra.wxs.in5
2 files changed, 88 insertions, 3 deletions
diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp
index 81c9f7eea92..e943d1a58b8 100644
--- a/win/packaging/ca/CustomAction.cpp
+++ b/win/packaging/ca/CustomAction.cpp
@@ -71,6 +71,82 @@ LExit:
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 @@ unsigned long long GetMaxBufferSize(unsigned long long totalPhys)
return totalPhys;
#endif
}
+
+
/*
Checks SERVICENAME, PORT and BUFFERSIZE parameters
*/
@@ -468,6 +546,8 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
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 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall)
}
}
- DWORD SkipNetworkingLen= MAX_PATH;
+ 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);
diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in
index 37b12575328..2c01b024544 100644
--- a/win/packaging/extra.wxs.in
+++ b/win/packaging/extra.wxs.in
@@ -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>