NtlmAuth.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // **********************************************************************************
  2. // CassiniDev - http://cassinidev.codeplex.com
  3. //
  4. // Copyright (c) 2010 Sky Sanders. All rights reserved.
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // This source code is subject to terms and conditions of the Microsoft Public
  8. // License (Ms-PL). A copy of the license can be found in the license.txt file
  9. // included in this distribution.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // **********************************************************************************
  14. #region
  15. using System;
  16. using System.Security;
  17. using System.Security.Principal;
  18. #endregion
  19. namespace CassiniDev
  20. {
  21. [SuppressUnmanagedCodeSecurity]
  22. internal sealed class NtlmAuth : IDisposable
  23. {
  24. private readonly bool _credentialsHandleAcquired;
  25. private string _blob;
  26. private bool _completed;
  27. private Interop.SecHandle _credentialsHandle;
  28. private Interop.SecBuffer _inputBuffer;
  29. private Interop.SecBufferDesc _inputBufferDesc;
  30. private Interop.SecBuffer _outputBuffer;
  31. private Interop.SecBufferDesc _outputBufferDesc;
  32. private Interop.SecHandle _securityContext;
  33. private bool _securityContextAcquired;
  34. private uint _securityContextAttributes;
  35. private SecurityIdentifier _sid;
  36. private long _timestamp;
  37. public NtlmAuth()
  38. {
  39. if (
  40. Interop.AcquireCredentialsHandle(null, "NTLM", 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
  41. ref _credentialsHandle, ref _timestamp) != 0)
  42. {
  43. throw new InvalidOperationException();
  44. }
  45. _credentialsHandleAcquired = true;
  46. }
  47. public string Blob
  48. {
  49. get { return _blob; }
  50. }
  51. public bool Completed
  52. {
  53. get { return _completed; }
  54. }
  55. public SecurityIdentifier SID
  56. {
  57. get { return _sid; }
  58. }
  59. #region IDisposable Members
  60. void IDisposable.Dispose()
  61. {
  62. FreeUnmanagedResources();
  63. GC.SuppressFinalize(this);
  64. }
  65. #endregion
  66. public unsafe bool Authenticate(string blobString)
  67. {
  68. _blob = null;
  69. byte[] buffer = Convert.FromBase64String(blobString);
  70. byte[] inArray = new byte[0x4000];
  71. fixed (void* ptrRef = &_securityContext)
  72. {
  73. fixed (void* ptrRef2 = &_inputBuffer)
  74. {
  75. fixed (void* ptrRef3 = &_outputBuffer)
  76. {
  77. fixed (void* ptrRef4 = buffer)
  78. {
  79. fixed (void* ptrRef5 = inArray)
  80. {
  81. IntPtr zero = IntPtr.Zero;
  82. if (_securityContextAcquired)
  83. {
  84. zero = (IntPtr) ptrRef;
  85. }
  86. _inputBufferDesc.ulVersion = 0;
  87. _inputBufferDesc.cBuffers = 1;
  88. _inputBufferDesc.pBuffers = (IntPtr) ptrRef2;
  89. _inputBuffer.cbBuffer = (uint) buffer.Length;
  90. _inputBuffer.BufferType = 2;
  91. _inputBuffer.pvBuffer = (IntPtr) ptrRef4;
  92. _outputBufferDesc.ulVersion = 0;
  93. _outputBufferDesc.cBuffers = 1;
  94. _outputBufferDesc.pBuffers = (IntPtr) ptrRef3;
  95. _outputBuffer.cbBuffer = (uint) inArray.Length;
  96. _outputBuffer.BufferType = 2;
  97. _outputBuffer.pvBuffer = (IntPtr) ptrRef5;
  98. int num = Interop.AcceptSecurityContext(ref _credentialsHandle, zero,
  99. ref _inputBufferDesc, 20,
  100. 0, ref _securityContext, ref _outputBufferDesc,
  101. ref _securityContextAttributes, ref _timestamp);
  102. if (num == 0x90312)
  103. {
  104. _securityContextAcquired = true;
  105. _blob = Convert.ToBase64String(inArray, 0, (int) _outputBuffer.cbBuffer);
  106. }
  107. else
  108. {
  109. if (num != 0)
  110. {
  111. return false;
  112. }
  113. IntPtr phToken = IntPtr.Zero;
  114. if (Interop.QuerySecurityContextToken(ref _securityContext, ref phToken) != 0)
  115. {
  116. return false;
  117. }
  118. try
  119. {
  120. using (WindowsIdentity identity = new WindowsIdentity(phToken))
  121. {
  122. _sid = identity.User;
  123. }
  124. }
  125. finally
  126. {
  127. Interop.CloseHandle(phToken);
  128. }
  129. _completed = true;
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }
  136. return true;
  137. }
  138. ~NtlmAuth()
  139. {
  140. FreeUnmanagedResources();
  141. }
  142. private void FreeUnmanagedResources()
  143. {
  144. if (_securityContextAcquired)
  145. {
  146. Interop.DeleteSecurityContext(ref _securityContext);
  147. }
  148. if (_credentialsHandleAcquired)
  149. {
  150. Interop.FreeCredentialsHandle(ref _credentialsHandle);
  151. }
  152. }
  153. }
  154. }