From c45aebc9ab4610b77dd183e63c1e08cb8ab42f4c Mon Sep 17 00:00:00 2001 From: Thomas Boop <52323235+thboop@users.noreply.github.com> Date: Mon, 27 Jan 2020 21:38:31 -0500 Subject: [PATCH] Update Base64 Encoders to deal with suffixes (#284) * Update Base64 Encoders to deal with suffixes * Set UriDataEscape to public for unit tests --- src/Runner.Common/HostContext.cs | 1 + src/Sdk/DTLogging/Logging/ValueEncoders.cs | 32 ++++++++++++++++++++-- src/Test/L0/HostContextL0.cs | 17 +++++++++--- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/Runner.Common/HostContext.cs b/src/Runner.Common/HostContext.cs index f110bbd40a1..48a785bd574 100644 --- a/src/Runner.Common/HostContext.cs +++ b/src/Runner.Common/HostContext.cs @@ -83,6 +83,7 @@ public HostContext(string hostType, string logFile = null) _loadContext.Unloading += LoadContext_Unloading; this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscape); + this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeTrimmed); this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeShift1); this.SecretMasker.AddValueEncoder(ValueEncoders.Base64StringEscapeShift2); this.SecretMasker.AddValueEncoder(ValueEncoders.ExpressionStringEscape); diff --git a/src/Sdk/DTLogging/Logging/ValueEncoders.cs b/src/Sdk/DTLogging/Logging/ValueEncoders.cs index 77478799178..52f46083379 100644 --- a/src/Sdk/DTLogging/Logging/ValueEncoders.cs +++ b/src/Sdk/DTLogging/Logging/ValueEncoders.cs @@ -16,6 +16,11 @@ public static String Base64StringEscape(String value) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(value)); } + + public static String Base64StringEscapeTrimmed(String value) + { + return TrimBase64End(Convert.ToBase64String(Encoding.UTF8.GetBytes(value))); + } // Base64 is 6 bits -> char // A byte is 8 bits @@ -67,15 +72,15 @@ private static string Base64StringEscapeShift(String value, int shift) { var shiftArray = new byte[bytes.Length - shift]; Array.Copy(bytes, shift, shiftArray, 0, bytes.Length - shift); - return Convert.ToBase64String(shiftArray); + return TrimBase64End(Convert.ToBase64String(shiftArray)); } else { - return Convert.ToBase64String(bytes); + return TrimBase64End(Convert.ToBase64String(bytes)); } } - private static String UriDataEscape( + public static String UriDataEscape( String value, Int32 maxSegmentSize) { @@ -103,5 +108,26 @@ private static String UriDataEscape( return result.ToString(); } + + private static String TrimBase64End(String value) + { + if (String.IsNullOrEmpty(value)) + { + return String.Empty; + } + if (value.EndsWith('=')) + { + var trimmed = value.TrimEnd('='); + if (trimmed.Length > 1) + { + // If a base64 string ends in '=' it indicates that the base 64 character is only using 2 or 4 of the six bytes and will change if another character is added + // For example 'ab' is 'YWI=' in base 64 + // 'abc' is 'YWJj' + // We need to detect YW, not YWI so we trim the last character ('I') + return trimmed.Substring(0, trimmed.Length - 1); + } + } + return value; + } } } diff --git a/src/Test/L0/HostContextL0.cs b/src/Test/L0/HostContextL0.cs index 4b5bbf6d172..ce608781834 100644 --- a/src/Test/L0/HostContextL0.cs +++ b/src/Test/L0/HostContextL0.cs @@ -93,12 +93,21 @@ public void DefaultSecretMaskers() Assert.Equal("123***123", _hc.SecretMasker.MaskSecrets("123Pass%20word%20123%21123")); Assert.Equal("123***123", _hc.SecretMasker.MaskSecrets("123Pass<word>123!123")); Assert.Equal("123***123", _hc.SecretMasker.MaskSecrets("123Pass''word''123!123")); - Assert.Equal("OlBh***", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($":Password123!")))); - Assert.Equal("YTpQ***", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"a:Password123!")))); + Assert.Equal("OlBh***Q==", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($":Password123!")))); + Assert.Equal("YTpQ***E=", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"a:Password123!")))); Assert.Equal("YWI6***", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"ab:Password123!")))); - Assert.Equal("YWJjOlBh***", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"abc:Password123!")))); - Assert.Equal("YWJjZDpQ***", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"abcd:Password123!")))); + Assert.Equal("YWJjOlBh***Q==", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"abc:Password123!")))); + Assert.Equal("YWJjZDpQ***E=", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"abcd:Password123!")))); Assert.Equal("YWJjZGU6***", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"abcde:Password123!")))); + Assert.Equal("***Og==", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"Password123!:")))); + Assert.Equal("***OmE=", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"Password123!:a")))); + Assert.Equal("***OmFi", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"Password123!:ab")))); + Assert.Equal("***OmFiYw==", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"Password123!:abc")))); + Assert.Equal("***OmFiY2Q=", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"Password123!:abcd")))); + Assert.Equal("***OmFiY2Rl", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"Password123!:abcde")))); + Assert.Equal("OlBh***To=", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($":Password123!:")))); + Assert.Equal("YTpQ***E6YQ==", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"a:Password123!:a")))); + Assert.Equal("YWJjOlBh***Tph", _hc.SecretMasker.MaskSecrets(Convert.ToBase64String(Encoding.UTF8.GetBytes($"abc:Password123!:a")))); } finally {