X509BasicConstraintsExtension.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. //
  2. // System.Security.Cryptography.X509BasicConstraintsExtension
  3. //
  4. // Author:
  5. // Sebastien Pouliot <[email protected]>
  6. // Tim Coleman ([email protected])
  7. //
  8. // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
  9. // Copyright (C) Tim Coleman, 2004
  10. // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. #if NET_2_0
  32. using System.Text;
  33. using Mono.Security;
  34. namespace System.Security.Cryptography.X509Certificates {
  35. public sealed class X509BasicConstraintsExtension : X509Extension {
  36. internal const string oid = "2.5.29.19";
  37. internal const string friendlyName = "Basic Constraints";
  38. private bool _certificateAuthority;
  39. private bool _hasPathLengthConstraint;
  40. private int _pathLengthConstraint;
  41. private AsnDecodeStatus _status;
  42. // constructors
  43. public X509BasicConstraintsExtension ()
  44. {
  45. _oid = new Oid (oid, friendlyName);
  46. }
  47. public X509BasicConstraintsExtension (AsnEncodedData encodedBasicConstraints, bool critical)
  48. {
  49. // ignore the Oid provided by encodedKeyUsage (our rules!)
  50. _oid = new Oid (oid, friendlyName);
  51. _raw = encodedBasicConstraints.RawData;
  52. base.Critical = critical;
  53. _status = Decode (this.RawData);
  54. }
  55. public X509BasicConstraintsExtension (bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical)
  56. {
  57. if (hasPathLengthConstraint) {
  58. if (pathLengthConstraint < 0)
  59. throw new ArgumentOutOfRangeException ("pathLengthConstraint");
  60. _pathLengthConstraint = pathLengthConstraint;
  61. }
  62. _hasPathLengthConstraint = hasPathLengthConstraint;
  63. _certificateAuthority = certificateAuthority;
  64. _oid = new Oid (oid, friendlyName);
  65. base.Critical = critical;
  66. RawData = Encode ();
  67. }
  68. // properties
  69. public bool CertificateAuthority {
  70. get {
  71. switch (_status) {
  72. case AsnDecodeStatus.Ok:
  73. case AsnDecodeStatus.InformationNotAvailable:
  74. return _certificateAuthority;
  75. default:
  76. throw new CryptographicException ("Badly encoded extension.");
  77. }
  78. }
  79. }
  80. public bool HasPathLengthConstraint {
  81. get {
  82. switch (_status) {
  83. case AsnDecodeStatus.Ok:
  84. case AsnDecodeStatus.InformationNotAvailable:
  85. return _hasPathLengthConstraint;
  86. default:
  87. throw new CryptographicException ("Badly encoded extension.");
  88. }
  89. }
  90. }
  91. public int PathLengthConstraint {
  92. get {
  93. switch (_status) {
  94. case AsnDecodeStatus.Ok:
  95. case AsnDecodeStatus.InformationNotAvailable:
  96. return _pathLengthConstraint;
  97. default:
  98. throw new CryptographicException ("Badly encoded extension.");
  99. }
  100. }
  101. }
  102. // methods
  103. public override void CopyFrom (AsnEncodedData asnEncodedData)
  104. {
  105. if (asnEncodedData == null)
  106. throw new ArgumentException ("asnEncodedData");
  107. // MS BUG throw new ArgumentNullException ("asnEncodedData");
  108. X509Extension ex = (asnEncodedData as X509Extension);
  109. if (ex == null)
  110. throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
  111. if (ex._oid == null)
  112. _oid = new Oid (oid, friendlyName);
  113. else
  114. _oid = new Oid (ex._oid);
  115. RawData = ex.RawData;
  116. base.Critical = ex.Critical;
  117. // and we deal with the rest later
  118. _status = Decode (this.RawData);
  119. }
  120. // internal
  121. internal AsnDecodeStatus Decode (byte[] extension)
  122. {
  123. if ((extension == null) || (extension.Length == 0))
  124. return AsnDecodeStatus.BadAsn;
  125. if (extension [0] != 0x30)
  126. return AsnDecodeStatus.BadTag;
  127. if (extension.Length < 3) {
  128. if (!((extension.Length == 2) && (extension [1] == 0x00)))
  129. return AsnDecodeStatus.BadLength;
  130. }
  131. try {
  132. ASN1 sequence = new ASN1 (extension);
  133. int n = 0;
  134. ASN1 a = sequence [n++];
  135. if ((a != null) && (a.Tag == 0x01)) {
  136. _certificateAuthority = (a.Value [0] == 0xFF);
  137. a = sequence [n++];
  138. }
  139. if ((a != null) && (a.Tag == 0x02)) {
  140. _hasPathLengthConstraint = true;
  141. _pathLengthConstraint = ASN1Convert.ToInt32 (a);
  142. }
  143. }
  144. catch {
  145. return AsnDecodeStatus.BadAsn;
  146. }
  147. return AsnDecodeStatus.Ok;
  148. }
  149. internal byte[] Encode ()
  150. {
  151. ASN1 ex = new ASN1 (0x30);
  152. if (_certificateAuthority)
  153. ex.Add (new ASN1 (0x01, new byte[] { 0xFF }));
  154. if (_hasPathLengthConstraint) {
  155. // MS encodes the 0 (pathLengthConstraint is OPTIONAL)
  156. // and in a long form (02 00 versus 02 01 00)
  157. if (_pathLengthConstraint == 0)
  158. ex.Add (new ASN1 (0x02, new byte[] { 0x00 }));
  159. else
  160. ex.Add (ASN1Convert.FromInt32 (_pathLengthConstraint));
  161. }
  162. return ex.GetBytes ();
  163. }
  164. internal override string ToString (bool multiLine)
  165. {
  166. switch (_status) {
  167. case AsnDecodeStatus.BadAsn:
  168. return String.Empty;
  169. case AsnDecodeStatus.BadTag:
  170. case AsnDecodeStatus.BadLength:
  171. return FormatUnkownData (_raw);
  172. case AsnDecodeStatus.InformationNotAvailable:
  173. return "Information Not Available";
  174. }
  175. if (_oid.Value != oid)
  176. return String.Format ("Unknown Key Usage ({0})", _oid.Value);
  177. StringBuilder sb = new StringBuilder ();
  178. sb.Append ("Subject Type=");
  179. if (_certificateAuthority)
  180. sb.Append ("CA");
  181. else
  182. sb.Append ("End Entity");
  183. if (multiLine)
  184. sb.Append (Environment.NewLine);
  185. else
  186. sb.Append (", ");
  187. sb.Append ("Path Length Constraint=");
  188. if (_hasPathLengthConstraint)
  189. sb.Append (_pathLengthConstraint);
  190. else
  191. sb.Append ("None");
  192. if (multiLine)
  193. sb.Append (Environment.NewLine);
  194. return sb.ToString ();
  195. }
  196. }
  197. }
  198. #endif