Use the right socket for the data stream
[mono.git] / mcs / class / System / System.Security.Cryptography.X509Certificates / X509BasicConstraintsExtension.cs
1 //
2 // System.Security.Cryptography.X509BasicConstraintsExtension
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //      Tim Coleman (tim@timcoleman.com)
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
32 #if SECURITY_DEP || MOONLIGHT
33
34 using System.Text;
35
36 using Mono.Security;
37
38 namespace System.Security.Cryptography.X509Certificates {
39
40         public sealed class X509BasicConstraintsExtension : X509Extension {
41
42                 internal const string oid = "2.5.29.19";
43                 internal const string friendlyName = "Basic Constraints";
44
45                 private bool _certificateAuthority;
46                 private bool _hasPathLengthConstraint;
47                 private int _pathLengthConstraint;
48                 private AsnDecodeStatus _status;
49
50                 // constructors
51
52                 public X509BasicConstraintsExtension ()
53                 {
54                         _oid = new Oid (oid, friendlyName);
55                 }
56
57                 public X509BasicConstraintsExtension (AsnEncodedData encodedBasicConstraints, bool critical)
58                 {
59                         // ignore the Oid provided by encodedKeyUsage (our rules!)
60                         _oid = new Oid (oid, friendlyName);
61                         _raw = encodedBasicConstraints.RawData;
62                         base.Critical = critical;
63                         _status = Decode (this.RawData);
64                 }
65
66                 public X509BasicConstraintsExtension (bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical)
67                 {
68                         if (hasPathLengthConstraint) {
69                                 if (pathLengthConstraint < 0)
70                                         throw new ArgumentOutOfRangeException ("pathLengthConstraint");
71                                 _pathLengthConstraint = pathLengthConstraint;
72                         }
73                         _hasPathLengthConstraint = hasPathLengthConstraint;
74                         _certificateAuthority = certificateAuthority;
75                         _oid = new Oid (oid, friendlyName);
76                         base.Critical = critical;
77                         RawData = Encode ();
78                 }
79
80                 // properties
81
82                 public bool CertificateAuthority {
83                         get {
84                                 switch (_status) {
85                                 case AsnDecodeStatus.Ok:
86                                 case AsnDecodeStatus.InformationNotAvailable:
87                                         return _certificateAuthority;
88                                 default:
89                                         throw new CryptographicException ("Badly encoded extension.");
90                                 }
91                         }
92                 }
93
94                 public bool HasPathLengthConstraint {
95                         get {
96                                 switch (_status) {
97                                 case AsnDecodeStatus.Ok:
98                                 case AsnDecodeStatus.InformationNotAvailable:
99                                         return _hasPathLengthConstraint;
100                                 default:
101                                         throw new CryptographicException ("Badly encoded extension.");
102                                 }
103                         }
104                 }
105
106                 public int PathLengthConstraint {
107                         get {
108                                 switch (_status) {
109                                 case AsnDecodeStatus.Ok:
110                                 case AsnDecodeStatus.InformationNotAvailable:
111                                         return _pathLengthConstraint;
112                                 default:
113                                         throw new CryptographicException ("Badly encoded extension.");
114                                 }
115                         }
116                 }
117
118                 // methods
119
120                 public override void CopyFrom (AsnEncodedData asnEncodedData) 
121                 {
122                         if (asnEncodedData == null)
123                                 throw new ArgumentNullException ("asnEncodedData");
124
125                         X509Extension ex = (asnEncodedData as X509Extension);
126                         if (ex == null)
127                                 throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
128
129                         if (ex._oid == null)
130                                 _oid = new Oid (oid, friendlyName);
131                         else 
132                                 _oid = new Oid (ex._oid);
133
134                         RawData = ex.RawData;
135                         base.Critical = ex.Critical;
136                         // and we deal with the rest later
137                         _status = Decode (this.RawData);
138                 }
139
140                 // internal
141
142                 internal AsnDecodeStatus Decode (byte[] extension)
143                 {
144                         if ((extension == null) || (extension.Length == 0))
145                                 return AsnDecodeStatus.BadAsn;
146                         if (extension [0] != 0x30)
147                                 return AsnDecodeStatus.BadTag;
148                         if (extension.Length < 3) {
149                                 if (!((extension.Length == 2) && (extension [1] == 0x00)))
150                                         return AsnDecodeStatus.BadLength;
151                         }
152
153                         try {
154                                 ASN1 sequence = new ASN1 (extension);
155                                 int n = 0;
156                                 ASN1 a = sequence [n++];
157                                 if ((a != null) && (a.Tag == 0x01)) {
158                                         _certificateAuthority = (a.Value [0] == 0xFF);
159                                         a = sequence [n++];
160                                 }
161                                 if ((a != null) && (a.Tag == 0x02)) {
162                                         _hasPathLengthConstraint = true;
163                                         _pathLengthConstraint = ASN1Convert.ToInt32 (a);
164                                 }
165                         }
166                         catch {
167                                 return AsnDecodeStatus.BadAsn;
168                         }
169
170                         return AsnDecodeStatus.Ok;
171                 }
172
173                 internal byte[] Encode ()
174                 {
175                         ASN1 ex = new ASN1 (0x30);
176
177                         if (_certificateAuthority)
178                                 ex.Add (new ASN1 (0x01, new byte[] { 0xFF }));
179                         if (_hasPathLengthConstraint) {
180                                 // MS encodes the 0 (pathLengthConstraint is OPTIONAL)
181                                 // and in a long form (02 00 versus 02 01 00)
182                                 if (_pathLengthConstraint == 0)
183                                         ex.Add (new ASN1 (0x02, new byte[] { 0x00 }));
184                                 else
185                                         ex.Add (ASN1Convert.FromInt32 (_pathLengthConstraint));
186                         }
187
188                         return ex.GetBytes ();
189                 }
190
191                 internal override string ToString (bool multiLine)
192                 {
193                         switch (_status) {
194                         case AsnDecodeStatus.BadAsn:
195                                 return String.Empty;
196                         case AsnDecodeStatus.BadTag:
197                         case AsnDecodeStatus.BadLength:
198                                 return FormatUnkownData (_raw);
199                         case AsnDecodeStatus.InformationNotAvailable:
200                                 return "Information Not Available";
201                         }
202
203                         if (_oid.Value != oid)
204                                 return String.Format ("Unknown Key Usage ({0})", _oid.Value);
205
206                         StringBuilder sb = new StringBuilder ();
207
208                         sb.Append ("Subject Type=");
209                         if (_certificateAuthority)
210                                 sb.Append ("CA");
211                         else
212                                 sb.Append ("End Entity");
213                         if (multiLine)
214                                 sb.Append (Environment.NewLine);
215                         else
216                                 sb.Append (", ");
217
218                         sb.Append ("Path Length Constraint=");
219                         if (_hasPathLengthConstraint) 
220                                 sb.Append (_pathLengthConstraint);
221                         else
222                                 sb.Append ("None");
223                         if (multiLine)
224                                 sb.Append (Environment.NewLine);
225
226                         return sb.ToString ();
227                 }
228         }
229 }
230
231 #endif