MachineKeySection.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //
  2. // System.Web.Configuration.MachineKeySection
  3. //
  4. // Authors:
  5. // Chris Toshok ([email protected])
  6. // Sebastien Pouliot <[email protected]>
  7. //
  8. // (c) Copyright 2005, 2010 Novell, Inc (http://www.novell.com)
  9. //
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. #if NET_2_0
  31. using System;
  32. using System.ComponentModel;
  33. using System.Configuration;
  34. using System.Security.Cryptography;
  35. using System.Web.Util;
  36. namespace System.Web.Configuration {
  37. public sealed class MachineKeySection : ConfigurationSection
  38. {
  39. static ConfigurationProperty decryptionProp;
  40. static ConfigurationProperty decryptionKeyProp;
  41. static ConfigurationProperty validationProp;
  42. static ConfigurationProperty validationKeyProp;
  43. static ConfigurationPropertyCollection properties;
  44. static MachineKeyValidationConverter converter = new MachineKeyValidationConverter ();
  45. #if NET_4_0
  46. MachineKeyValidation validation;
  47. #endif
  48. static MachineKeySection ()
  49. {
  50. decryptionProp = new ConfigurationProperty ("decryption", typeof (string), "Auto",
  51. PropertyHelper.WhiteSpaceTrimStringConverter,
  52. PropertyHelper.NonEmptyStringValidator,
  53. ConfigurationPropertyOptions.None);
  54. decryptionKeyProp = new ConfigurationProperty ("decryptionKey", typeof (string), "AutoGenerate,IsolateApps",
  55. PropertyHelper.WhiteSpaceTrimStringConverter,
  56. PropertyHelper.NonEmptyStringValidator,
  57. ConfigurationPropertyOptions.None);
  58. #if NET_4_0
  59. validationProp = new ConfigurationProperty ("validation", typeof (string), "HMACSHA256",
  60. PropertyHelper.WhiteSpaceTrimStringConverter,
  61. PropertyHelper.NonEmptyStringValidator,
  62. ConfigurationPropertyOptions.None);
  63. #else
  64. validationProp = new ConfigurationProperty ("validation", typeof (MachineKeyValidation),
  65. MachineKeyValidation.SHA1, converter,
  66. PropertyHelper.DefaultValidator,
  67. ConfigurationPropertyOptions.None);
  68. #endif
  69. validationKeyProp = new ConfigurationProperty ("validationKey", typeof (string), "AutoGenerate,IsolateApps",
  70. PropertyHelper.WhiteSpaceTrimStringConverter,
  71. PropertyHelper.NonEmptyStringValidator,
  72. ConfigurationPropertyOptions.None);
  73. properties = new ConfigurationPropertyCollection ();
  74. properties.Add (decryptionProp);
  75. properties.Add (decryptionKeyProp);
  76. properties.Add (validationProp);
  77. properties.Add (validationKeyProp);
  78. Config.AutoGenerate (MachineKeyRegistryStorage.KeyType.Encryption);
  79. Config.AutoGenerate (MachineKeyRegistryStorage.KeyType.Validation);
  80. }
  81. #if NET_4_0
  82. public MachineKeySection ()
  83. {
  84. // get DefaultValue from ValidationAlgorithm
  85. validation = (MachineKeyValidation) converter.ConvertFrom (null, null, ValidationAlgorithm);
  86. }
  87. [MonoTODO]
  88. public MachineKeyCompatibilityMode CompatibilityMode {
  89. get; set;
  90. }
  91. #endif
  92. protected override void Reset (ConfigurationElement parentElement)
  93. {
  94. base.Reset (parentElement);
  95. decryption_key = null;
  96. validation_key = null;
  97. decryption_template = null;
  98. validation_template = null;
  99. }
  100. [TypeConverter (typeof (WhiteSpaceTrimStringConverter))]
  101. [StringValidator (MinLength = 1)]
  102. [ConfigurationProperty ("decryption", DefaultValue = "Auto")]
  103. public string Decryption {
  104. get { return (string) base [decryptionProp];}
  105. set {
  106. decryption_template = MachineKeySectionUtils.GetDecryptionAlgorithm (value);
  107. base[decryptionProp] = value;
  108. }
  109. }
  110. [TypeConverter (typeof (WhiteSpaceTrimStringConverter))]
  111. [StringValidator (MinLength = 1)]
  112. [ConfigurationProperty ("decryptionKey", DefaultValue = "AutoGenerate,IsolateApps")]
  113. public string DecryptionKey {
  114. get { return (string) base [decryptionKeyProp];}
  115. set {
  116. base[decryptionKeyProp] = value;
  117. SetDecryptionKey (value);
  118. }
  119. }
  120. #if NET_4_0
  121. // property exists for backward compatibility
  122. public MachineKeyValidation Validation {
  123. get { return validation; }
  124. set {
  125. if (value == MachineKeyValidation.Custom)
  126. throw new ArgumentException ();
  127. string algo = value.ToString ();
  128. // enum and accept values differs for TripleDES
  129. ValidationAlgorithm = (algo == "TripleDES") ? "3DES" : algo;
  130. }
  131. }
  132. [StringValidator (MinLength = 1)]
  133. [TypeConverter (typeof (WhiteSpaceTrimStringConverter))]
  134. [ConfigurationProperty ("validation", DefaultValue = "HMACSHA256")]
  135. public string ValidationAlgorithm {
  136. get { return (string) base [validationProp];}
  137. set {
  138. if (value == null)
  139. return;
  140. if (value.StartsWith ("alg:"))
  141. validation = MachineKeyValidation.Custom;
  142. else
  143. validation = (MachineKeyValidation) converter.ConvertFrom (null, null, value);
  144. base[validationProp] = value;
  145. }
  146. }
  147. #else
  148. [TypeConverter (typeof (MachineKeyValidationConverter))]
  149. [ConfigurationProperty ("validation", DefaultValue = "SHA1")]
  150. public MachineKeyValidation Validation {
  151. get { return (MachineKeyValidation) base [validationProp];}
  152. set { base[validationProp] = value; }
  153. }
  154. #endif
  155. [TypeConverter (typeof (WhiteSpaceTrimStringConverter))]
  156. [StringValidator (MinLength = 1)]
  157. [ConfigurationProperty ("validationKey", DefaultValue = "AutoGenerate,IsolateApps")]
  158. public string ValidationKey {
  159. get { return (string) base [validationKeyProp];}
  160. set {
  161. base[validationKeyProp] = value;
  162. SetValidationKey (value);
  163. }
  164. }
  165. protected override ConfigurationPropertyCollection Properties {
  166. get { return properties; }
  167. }
  168. internal static MachineKeySection Config {
  169. get { return WebConfigurationManager.GetSection ("system.web/machineKey") as MachineKeySection; }
  170. }
  171. byte[] decryption_key;
  172. byte[] validation_key;
  173. SymmetricAlgorithm decryption_template;
  174. KeyedHashAlgorithm validation_template;
  175. internal SymmetricAlgorithm GetDecryptionAlgorithm ()
  176. {
  177. // code location to help with unit testing the code
  178. return MachineKeySectionUtils.GetDecryptionAlgorithm (Decryption);
  179. }
  180. // not to be reused outside algorithm and key validation purpose
  181. SymmetricAlgorithm DecryptionTemplate {
  182. get {
  183. if (decryption_template == null)
  184. decryption_template = GetDecryptionAlgorithm ();
  185. return decryption_template;
  186. }
  187. }
  188. internal byte [] GetDecryptionKey ()
  189. {
  190. if (decryption_key == null)
  191. SetDecryptionKey (DecryptionKey);
  192. return decryption_key;
  193. }
  194. void SetDecryptionKey (string key)
  195. {
  196. if ((key == null) || key.StartsWith ("AutoGenerate")) {
  197. decryption_key = AutoGenerate (MachineKeyRegistryStorage.KeyType.Encryption);
  198. } else {
  199. try {
  200. decryption_key = MachineKeySectionUtils.GetBytes (key, key.Length);
  201. DecryptionTemplate.Key = decryption_key;
  202. }
  203. catch {
  204. decryption_key = null;
  205. throw new ArgumentException ("Invalid key length");
  206. }
  207. }
  208. }
  209. internal KeyedHashAlgorithm GetValidationAlgorithm ()
  210. {
  211. // code location to help with unit testing the code
  212. return MachineKeySectionUtils.GetValidationAlgorithm (this);
  213. }
  214. // not to be reused outside algorithm and key validation purpose
  215. KeyedHashAlgorithm ValidationTemplate {
  216. get {
  217. if (validation_template == null)
  218. validation_template = GetValidationAlgorithm ();
  219. return validation_template;
  220. }
  221. }
  222. internal byte [] GetValidationKey ()
  223. {
  224. if (validation_key == null)
  225. SetValidationKey (ValidationKey);
  226. return validation_key;
  227. }
  228. // key can be expended for HMAC - i.e. a small key, e.g. 32 bytes, is still accepted as valid
  229. // the HMAC class already deals with keys larger than what it can use (digested to right size)
  230. void SetValidationKey (string key)
  231. {
  232. if ((key == null) || key.StartsWith ("AutoGenerate")) {
  233. validation_key = AutoGenerate (MachineKeyRegistryStorage.KeyType.Validation);
  234. } else {
  235. try {
  236. validation_key = MachineKeySectionUtils.GetBytes (key, key.Length);
  237. ValidationTemplate.Key = validation_key;
  238. }
  239. catch (CryptographicException) {
  240. // second chance, use the key length that the HMAC really wants
  241. try {
  242. byte[] expanded_key = new byte [ValidationTemplate.Key.Length];
  243. Array.Copy (validation_key, 0, expanded_key, 0, validation_key.Length);
  244. ValidationTemplate.Key = expanded_key;
  245. validation_key = expanded_key;
  246. }
  247. catch {
  248. validation_key = null;
  249. throw new ArgumentException ("Invalid key length");
  250. }
  251. }
  252. }
  253. }
  254. byte[] AutoGenerate (MachineKeyRegistryStorage.KeyType type)
  255. {
  256. byte[] key = null;
  257. #if TARGET_J2EE
  258. {
  259. #else
  260. try {
  261. key = MachineKeyRegistryStorage.Retrieve (type);
  262. // ensure the stored key is usable with the selection algorithm
  263. if (type == MachineKeyRegistryStorage.KeyType.Encryption)
  264. DecryptionTemplate.Key = key;
  265. else if (type == MachineKeyRegistryStorage.KeyType.Validation)
  266. ValidationTemplate.Key = key;
  267. } catch (Exception) {
  268. key = null;
  269. }
  270. #endif
  271. // some algorithms have special needs for key (e.g. length, parity, weak keys...)
  272. // so we better ask them to provide a default key (than to generate/use bad ones)
  273. if (key == null) {
  274. if (type == MachineKeyRegistryStorage.KeyType.Encryption)
  275. key = DecryptionTemplate.Key;
  276. else if (type == MachineKeyRegistryStorage.KeyType.Validation)
  277. key = ValidationTemplate.Key;
  278. #if !TARGET_J2EE
  279. MachineKeyRegistryStorage.Store (key, type);
  280. #endif
  281. }
  282. return key;
  283. }
  284. }
  285. }
  286. #endif