PageRenderTime 27ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/referencesource/System.Web/Configuration/IdentitySection.cs

https://github.com/pruiz/mono
C# | 283 lines | 231 code | 27 blank | 25 comment | 58 complexity | 6d1aaf4e97f66058077192899d03b5d7 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //------------------------------------------------------------------------------
  2. // <copyright file="IdentitySection.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. namespace System.Web.Configuration {
  7. using System;
  8. using System.Xml;
  9. using System.Configuration;
  10. using System.Collections.Specialized;
  11. using System.Collections;
  12. using System.IO;
  13. using System.Text;
  14. using System.Web.Util;
  15. using System.Web.Configuration;
  16. using System.Security.Permissions;
  17. /* <!--
  18. identity Attributes:
  19. impersonate="[true|false]" - Impersonate Windows User
  20. userName="Windows user account to impersonate" | empty string implies impersonate the LOGON user specified by IIS
  21. password="password of above specified account" | empty string
  22. -->
  23. <identity impersonate="false" />
  24. */
  25. public sealed class IdentitySection : ConfigurationSection {
  26. private static ConfigurationPropertyCollection _properties;
  27. private static readonly ConfigurationProperty _propImpersonate =
  28. new ConfigurationProperty("impersonate", typeof(bool), false, ConfigurationPropertyOptions.None);
  29. private static readonly ConfigurationProperty _propUserName =
  30. new ConfigurationProperty("userName", typeof(string), String.Empty, ConfigurationPropertyOptions.None);
  31. private static readonly ConfigurationProperty _propPassword =
  32. new ConfigurationProperty("password", typeof(string), String.Empty, ConfigurationPropertyOptions.None);
  33. private ImpersonateTokenRef _impersonateTokenRef = new ImpersonateTokenRef(IntPtr.Zero);
  34. private string _username;
  35. private string _password;
  36. private bool impersonateCache = false;
  37. private bool impersonateCached = false; // value not read yet
  38. private bool _credentialsValidated;
  39. private object _credentialsValidatedLock = new object();
  40. private String error = String.Empty;
  41. static IdentitySection() {
  42. // Property initialization
  43. _properties = new ConfigurationPropertyCollection();
  44. _properties.Add(_propImpersonate);
  45. _properties.Add(_propUserName);
  46. _properties.Add(_propPassword);
  47. }
  48. protected override object GetRuntimeObject() {
  49. // VSWhidbey 554776: The method ValidateCredentials() is not safe
  50. // when multiple threads are accessing it, because the method access
  51. // and modify member variables. After reviewing the code,
  52. // _impersonateTokenRef.Handle is actually cached, so it is safe to
  53. // cache the validation result as a whole. That will avoid
  54. // ValidateCredentials() to be called with multiple threads.
  55. if (!_credentialsValidated) {
  56. lock (_credentialsValidatedLock) {
  57. if (!_credentialsValidated) {
  58. ValidateCredentials();
  59. _credentialsValidated = true;
  60. }
  61. }
  62. }
  63. return base.GetRuntimeObject();
  64. }
  65. public IdentitySection() {
  66. impersonateCached = false;
  67. }
  68. protected override ConfigurationPropertyCollection Properties {
  69. get {
  70. return _properties;
  71. }
  72. }
  73. [ConfigurationProperty("impersonate", DefaultValue = false)]
  74. public bool Impersonate {
  75. get {
  76. if (impersonateCached == false) {
  77. impersonateCache = (bool)base[_propImpersonate];
  78. impersonateCached = true; // value has been read now
  79. }
  80. return impersonateCache;
  81. }
  82. set {
  83. base[_propImpersonate] = value;
  84. impersonateCache = value;
  85. }
  86. }
  87. [ConfigurationProperty("userName", DefaultValue = "")]
  88. public string UserName {
  89. get {
  90. return (string)base[_propUserName];
  91. }
  92. set {
  93. base[_propUserName] = value;
  94. }
  95. }
  96. [ConfigurationProperty("password", DefaultValue = "")]
  97. public string Password {
  98. get {
  99. return (string)base[_propPassword];
  100. }
  101. set {
  102. base[_propPassword] = value;
  103. }
  104. }
  105. protected override void Reset(ConfigurationElement parentElement) {
  106. base.Reset(parentElement);
  107. IdentitySection parent = parentElement as IdentitySection;
  108. if (parent != null) {
  109. _impersonateTokenRef = parent._impersonateTokenRef;
  110. // No partial overrides
  111. if (Impersonate) {
  112. UserName = null;
  113. Password = null;
  114. _impersonateTokenRef = new ImpersonateTokenRef(IntPtr.Zero);
  115. }
  116. impersonateCached = false; // We don't want to cache the parent's value!
  117. _credentialsValidated = false;
  118. }
  119. }
  120. protected override void Unmerge(ConfigurationElement sourceElement,
  121. ConfigurationElement parentElement,
  122. ConfigurationSaveMode saveMode) {
  123. base.Unmerge(sourceElement, parentElement, saveMode); // do this to unmerge locks
  124. IdentitySection source = sourceElement as IdentitySection;
  125. if (Impersonate != source.Impersonate) { // this will not be copied by unmerge if it is the same as parent
  126. Impersonate = source.Impersonate; // If it is different than expected make sure it is set or validation
  127. } // will be missed
  128. // this section does not inherit in the same manner since partial overrides are not permitted
  129. if (Impersonate) // was impersonate set in the merge
  130. {
  131. if (source.ElementInformation.Properties[_propUserName.Name].IsModified ||
  132. source.ElementInformation.Properties[_propPassword.Name].IsModified) {
  133. UserName = source.UserName;
  134. Password = source.Password;
  135. }
  136. }
  137. }
  138. private void ValidateCredentials() {
  139. _username = UserName;
  140. _password = Password;
  141. if (HandlerBase.CheckAndReadRegistryValue(ref _username, false) == false) {
  142. throw new ConfigurationErrorsException(
  143. SR.GetString(SR.Invalid_registry_config),
  144. ElementInformation.Source, ElementInformation.LineNumber);
  145. }
  146. if (HandlerBase.CheckAndReadRegistryValue(ref _password, false) == false) {
  147. throw new ConfigurationErrorsException(
  148. SR.GetString(SR.Invalid_registry_config),
  149. ElementInformation.Source,
  150. ElementInformation.LineNumber);
  151. }
  152. if (_username != null && _username.Length < 1) {
  153. _username = null;
  154. }
  155. if (_username != null && Impersonate) {
  156. if (_password == null) {
  157. _password = String.Empty;
  158. }
  159. }
  160. else if (_password != null && _username == null && _password.Length > 0 && Impersonate) {
  161. throw new ConfigurationErrorsException(
  162. SR.GetString(SR.Invalid_credentials),
  163. ElementInformation.Properties["password"].Source,
  164. ElementInformation.Properties["password"].LineNumber);
  165. }
  166. if (Impersonate && ImpersonateToken == IntPtr.Zero && _username != null) {
  167. if (error.Length > 0) {
  168. throw new ConfigurationErrorsException(
  169. SR.GetString(SR.Invalid_credentials_2, error),
  170. ElementInformation.Properties["userName"].Source,
  171. ElementInformation.Properties["userName"].LineNumber);
  172. }
  173. else {
  174. throw new ConfigurationErrorsException(
  175. SR.GetString(SR.Invalid_credentials),
  176. ElementInformation.Properties["userName"].Source,
  177. ElementInformation.Properties["userName"].LineNumber);
  178. }
  179. }
  180. }
  181. private void InitializeToken() {
  182. error = String.Empty;
  183. IntPtr token = CreateUserToken(_username, _password, out error);
  184. _impersonateTokenRef = new ImpersonateTokenRef(token);
  185. if (_impersonateTokenRef.Handle == IntPtr.Zero) {
  186. if (error.Length > 0) {
  187. throw new ConfigurationErrorsException(
  188. SR.GetString(SR.Invalid_credentials_2, error),
  189. ElementInformation.Properties["userName"].Source,
  190. ElementInformation.Properties["userName"].LineNumber);
  191. }
  192. else {
  193. throw new ConfigurationErrorsException(
  194. SR.GetString(SR.Invalid_credentials),
  195. ElementInformation.Properties["userName"].Source,
  196. ElementInformation.Properties["userName"].LineNumber);
  197. }
  198. }
  199. }
  200. internal IntPtr ImpersonateToken {
  201. get {
  202. if (_impersonateTokenRef.Handle == IntPtr.Zero) {
  203. if (_username != null && Impersonate) {
  204. InitializeToken();
  205. }
  206. }
  207. return _impersonateTokenRef.Handle;
  208. }
  209. }
  210. internal static IntPtr CreateUserToken(String name, String password, out String error) {
  211. IntPtr token = IntPtr.Zero;
  212. // when using ASP.NET process model call back via ISAPI
  213. if (VersionInfo.ExeName == "aspnet_wp") {
  214. byte[] bOut = new byte[IntPtr.Size];
  215. byte[] bIn1 = System.Text.Encoding.Unicode.GetBytes(name + "\t" + password);
  216. byte[] bIn = new byte[bIn1.Length + 2];
  217. Buffer.BlockCopy(bIn1, 0, bIn, 0, bIn1.Length);
  218. if (UnsafeNativeMethods.PMCallISAPI(IntPtr.Zero,
  219. UnsafeNativeMethods.CallISAPIFunc.GenerateToken,
  220. bIn,
  221. bIn.Length,
  222. bOut,
  223. bOut.Length) == 1) {
  224. Int64 iToken = 0;
  225. for (int iter = 0; iter < IntPtr.Size; iter++) {
  226. iToken = iToken * 256 + bOut[iter];
  227. }
  228. token = (IntPtr)iToken;
  229. Debug.Trace("Token", "Token " + token + " for (" + name + "," + password + ") obtained via ISAPI");
  230. }
  231. }
  232. // try to create the token directly
  233. if (token == IntPtr.Zero) {
  234. StringBuilder errorBuffer = new StringBuilder(256);
  235. token = UnsafeNativeMethods.CreateUserToken(name, password, 1, errorBuffer, 256);
  236. error = errorBuffer.ToString();
  237. if (token != IntPtr.Zero) {
  238. Debug.Trace("Token", "Token " + token + " for (" + name + "," + password + ") obtained directly");
  239. }
  240. }
  241. else {
  242. error = String.Empty;
  243. }
  244. if (token == IntPtr.Zero) {
  245. Debug.Trace("Token", "Failed to create token for (" + name + "," + password + ")");
  246. }
  247. return token;
  248. }
  249. internal ContextInformation ProtectedEvaluationContext {
  250. get {
  251. return this.EvaluationContext;
  252. }
  253. }
  254. }
  255. }