mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
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.
This commit is contained in:
@@ -316,9 +316,9 @@ static int create_myini()
|
||||
|
||||
|
||||
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 @@ static int create_db_instance()
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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=
|
||||
""[#F.bin.mysql_install_db.exe]" "--service=[SERVICENAME]" --port=[PORT] "--password=[PASSWORD]" "--datadir=[DATADIR]\" [SKIPNETWORKING] [ALLOWREMOTEROOTACCESS] [DEFAULTUSER]"
|
||||
""[#F.bin.mysql_install_db.exe]" "--service=[SERVICENAME]" --port=[PORT] "--password=[ESCAPEDPASSWORD]" "--datadir=[DATADIR]\" [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>
|
||||
|
Reference in New Issue
Block a user