Advertisement
Guest User

Untitled

a guest
Apr 18th, 2015
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.87 KB | None | 0 0
  1. var secureString = new SecureString();
  2. secureString.AppendChar('a');
  3. secureString.AppendChar('q');
  4. secureString.AppendChar('1');
  5.  
  6. using (var command = new SqlCommand("select case when @secureParam = 'aq1' then 'yes' else 'no' end", connection))
  7. {
  8. object returnValue;
  9.  
  10. using (command.Parameters.AddSecure("secureParam", secureString))
  11. {
  12. // At this point no copies exist in the clear
  13. returnValue = (string)command.ExecuteScalar();
  14. // Now one pinned String object exists in the clear (referenced at the internal property command.Parameters[0].CoercedValue)
  15. }
  16. // At this point no copies exist in the clear
  17. }
  18.  
  19. public static class SecureSqlParameterExtensions
  20. {
  21. [DllImport("kernel32.dll", EntryPoint = "CopyMemory")]
  22. private static extern void CopyMemory(IntPtr dest, IntPtr src, IntPtr count);
  23. [DllImport("kernel32.dll", EntryPoint = "RtlZeroMemory")]
  24. private static extern void ZeroMemory(IntPtr ptr, IntPtr count);
  25.  
  26. /// <summary>
  27. /// You must dispose the return value as soon as SqlCommand.Execute* is called.
  28. /// </summary>
  29. public static IDisposable AddSecure(this SqlParameterCollection collection, string name, SecureString secureString)
  30. {
  31. var value = new SecureStringParameterValue(secureString);
  32. collection.Add(name, SqlDbType.NVarChar).Value = value;
  33. return value;
  34. }
  35.  
  36. private sealed class SecureStringParameterValue : IConvertible, IDisposable
  37. {
  38. private readonly SecureString secureString;
  39. private int length;
  40. private string insecureManagedCopy;
  41. private GCHandle insecureManagedCopyGcHandle;
  42.  
  43. public SecureStringParameterValue(SecureString secureString)
  44. {
  45. this.secureString = secureString;
  46. }
  47.  
  48. #region IConvertible
  49.  
  50. public TypeCode GetTypeCode()
  51. {
  52. return TypeCode.String;
  53. }
  54.  
  55. public string ToString(IFormatProvider provider)
  56. {
  57. if (insecureManagedCopy != null) return insecureManagedCopy;
  58. if (secureString == null || secureString.Length == 0) return string.Empty;
  59.  
  60. // We waited till the last possible minute.
  61.  
  62. // Here's the plan:
  63. // 1. Create a new managed string initialized to zero
  64. // 2. Pin the managed string so the GC leaves it alone
  65. // 3. Copy the contents of the SecureString into the managed string
  66. // 4. Use the string as a SqlParameter
  67. // 5. Zero the managed string after Execute* is called and free the GC handle
  68.  
  69. length = secureString.Length;
  70. insecureManagedCopy = new string('', length);
  71. insecureManagedCopyGcHandle = GCHandle.Alloc(insecureManagedCopy, GCHandleType.Pinned); // Do not allow the GC to move this around and leave copies behind
  72.  
  73. try
  74. {
  75. // This is the only way to read the contents, sadly.
  76. // SecureStringToBSTR picks where to put it, so we have to copy it from there and zerofree the unmanaged copy as fast as possible.
  77. var insecureUnmanagedCopy = Marshal.SecureStringToBSTR(secureString);
  78. try
  79. {
  80. CopyMemory(insecureManagedCopyGcHandle.AddrOfPinnedObject(), insecureUnmanagedCopy, (IntPtr)(length * 2));
  81. }
  82. finally
  83. {
  84. if (insecureUnmanagedCopy != IntPtr.Zero) Marshal.ZeroFreeBSTR(insecureUnmanagedCopy);
  85. }
  86.  
  87. // Now the string managed string has the contents in the clear.
  88. return insecureManagedCopy;
  89. }
  90. catch
  91. {
  92. Dispose();
  93. throw;
  94. }
  95. }
  96.  
  97. public void Dispose()
  98. {
  99. if (insecureManagedCopy == null) return;
  100. insecureManagedCopy = null;
  101. ZeroMemory(insecureManagedCopyGcHandle.AddrOfPinnedObject(), (IntPtr)(length * 2));
  102. insecureManagedCopyGcHandle.Free();
  103. }
  104.  
  105. public bool ToBoolean(IFormatProvider provider)
  106. {
  107. throw new NotImplementedException();
  108. }
  109.  
  110. public char ToChar(IFormatProvider provider)
  111. {
  112. throw new NotImplementedException();
  113. }
  114.  
  115. public sbyte ToSByte(IFormatProvider provider)
  116. {
  117. throw new NotImplementedException();
  118. }
  119.  
  120. public byte ToByte(IFormatProvider provider)
  121. {
  122. throw new NotImplementedException();
  123. }
  124.  
  125. public short ToInt16(IFormatProvider provider)
  126. {
  127. throw new NotImplementedException();
  128. }
  129.  
  130. public ushort ToUInt16(IFormatProvider provider)
  131. {
  132. throw new NotImplementedException();
  133. }
  134.  
  135. public int ToInt32(IFormatProvider provider)
  136. {
  137. throw new NotImplementedException();
  138. }
  139.  
  140. public uint ToUInt32(IFormatProvider provider)
  141. {
  142. throw new NotImplementedException();
  143. }
  144.  
  145. public long ToInt64(IFormatProvider provider)
  146. {
  147. throw new NotImplementedException();
  148. }
  149.  
  150. public ulong ToUInt64(IFormatProvider provider)
  151. {
  152. throw new NotImplementedException();
  153. }
  154.  
  155. public float ToSingle(IFormatProvider provider)
  156. {
  157. throw new NotImplementedException();
  158. }
  159.  
  160. public double ToDouble(IFormatProvider provider)
  161. {
  162. throw new NotImplementedException();
  163. }
  164.  
  165. public decimal ToDecimal(IFormatProvider provider)
  166. {
  167. throw new NotImplementedException();
  168. }
  169.  
  170. public DateTime ToDateTime(IFormatProvider provider)
  171. {
  172. throw new NotImplementedException();
  173. }
  174.  
  175. public object ToType(Type conversionType, IFormatProvider provider)
  176. {
  177. throw new NotImplementedException();
  178. }
  179.  
  180. #endregion
  181. }
  182. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement