Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed the ConnectionString's password persistence in NetCore #453

Merged
merged 1 commit into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ private static class SYNONYM
private readonly string _usersConnectionString;
private readonly Dictionary<string, string> _parsetable;
internal readonly NameValuePair _keyChain;
internal readonly bool _hasPasswordKeyword;

internal Dictionary<string, string> Parsetable
{
Expand All @@ -114,14 +113,14 @@ public string UsersConnectionString(bool hidePassword) =>
private string UsersConnectionString(bool hidePassword, bool forceHidePassword)
{
string connectionString = _usersConnectionString;
if (_hasPasswordKeyword && (forceHidePassword || (hidePassword && !HasPersistablePassword)))
if (HasPasswordKeyword && (forceHidePassword || (hidePassword && !HasPersistablePassword)))
{
ReplacePasswordPwd(out connectionString, false);
}
return connectionString ?? string.Empty;
}

internal bool HasPersistablePassword => _hasPasswordKeyword ?
internal bool HasPersistablePassword => HasPasswordKeyword ?
ConvertValueToBoolean(KEY.Persist_Security_Info, false) :
true; // no password means persistable password so we don't have to munge

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ public DbConnectionOptions(string connectionString, Dictionary<string, string> s

protected DbConnectionOptions(DbConnectionOptions connectionOptions)
{ // Clone used by SqlConnectionString
_usersConnectionString = connectionOptions._usersConnectionString;
_hasPasswordKeyword = connectionOptions._hasPasswordKeyword;
_usersConnectionString = connectionOptions._usersConnectionString;
_parsetable = connectionOptions._parsetable;
_keyChain = connectionOptions._keyChain;
HasPasswordKeyword = connectionOptions.HasPasswordKeyword;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ public static bool IsUTF8Supported()
return retval;
}

public static bool IsTCPConnectionStringPasswordIncluded()
{
return RetrieveValueFromConnStr(TCPConnectionString, new string[] { "Password", "PWD" }) != string.Empty;
}

// the name length will be no more then (16 + prefix.Length + escapeLeft.Length + escapeRight.Length)
// some providers does not support names (Oracle supports up to 30)
public static string GetUniqueName(string prefix)
Expand Down Expand Up @@ -575,23 +580,26 @@ public static string RemoveKeysInConnStr(string connStr, string[] keysToRemove)
{
// tokenize connection string and remove input keys.
string res = "";
string[] keys = connStr.Split(';');
foreach (var key in keys)
if (connStr != null && keysToRemove != null)
{
if (!string.IsNullOrEmpty(key.Trim()))
string[] keys = connStr.Split(';');
foreach (var key in keys)
{
bool removeKey = false;
foreach (var keyToRemove in keysToRemove)
if (!string.IsNullOrEmpty(key.Trim()))
{
if (key.Trim().ToLower().StartsWith(keyToRemove.Trim().ToLower()))
bool removeKey = false;
foreach (var keyToRemove in keysToRemove)
{
removeKey = true;
break;
if (key.Trim().ToLower().StartsWith(keyToRemove.Trim().ToLower()))
{
removeKey = true;
break;
}
}
if (!removeKey)
{
res += key + ";";
}
}
if (!removeKey)
{
res += key + ";";
}
}
}
Expand All @@ -602,17 +610,20 @@ public static string RetrieveValueFromConnStr(string connStr, string[] keywords)
{
// tokenize connection string and retrieve value for a specific key.
string res = "";
string[] keys = connStr.Split(';');
foreach (var key in keys)
if (connStr != null && keywords != null)
{
foreach (var keyword in keywords)
string[] keys = connStr.Split(';');
foreach (var key in keys)
{
if (!string.IsNullOrEmpty(key.Trim()))
foreach (var keyword in keywords)
{
if (key.Trim().ToLower().StartsWith(keyword.Trim().ToLower()))
if (!string.IsNullOrEmpty(key.Trim()))
{
res = key.Substring(key.IndexOf('=') + 1).Trim();
break;
if (key.Trim().ToLower().StartsWith(keyword.Trim().ToLower()))
{
res = key.Substring(key.IndexOf('=') + 1).Trim();
break;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Microsoft.Data.SqlClient.ManualTesting.Tests
{
public static class ConnectivityParametersTest
public static class ConnectivityTest
{
private const string COL_SPID = "SPID";
private const string COL_PROGRAM_NAME = "ProgramName";
Expand Down Expand Up @@ -276,5 +276,33 @@ public static void ConnectionResiliencyTest()
}
}
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsTCPConnectionStringPasswordIncluded))]
public static void ConnectionStringPersistantInfoTest()
{
SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString);
connectionStringBuilder.PersistSecurityInfo = false;
string cnnString = connectionStringBuilder.ConnectionString;

connectionStringBuilder.Clear();
using (SqlConnection sqlCnn = new SqlConnection(cnnString))
{
sqlCnn.Open();
connectionStringBuilder.ConnectionString = sqlCnn.ConnectionString;
Assert.True(connectionStringBuilder.Password == string.Empty, "Password must not persist according to set the PersistSecurityInfo by false!");
}

connectionStringBuilder.ConnectionString = DataTestUtility.TCPConnectionString;
connectionStringBuilder.PersistSecurityInfo = true;
cnnString = connectionStringBuilder.ConnectionString;

connectionStringBuilder.Clear();
using (SqlConnection sqlCnn = new SqlConnection(cnnString))
{
sqlCnn.Open();
connectionStringBuilder.ConnectionString = sqlCnn.ConnectionString;
Assert.True(connectionStringBuilder.Password != string.Empty, "Password must persist according to set the PersistSecurityInfo by true!");
}
}
}
}