1 /******************************************************************************
3 * Copyright (c) 2003 Novell Inc. www.novell.com
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 *******************************************************************************/
24 // Novell.Directory.Ldap.Asn1.LBEREncoder.cs
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
34 namespace Novell.Directory.Ldap.Asn1
37 /// <summary> This class provides LBER encoding routines for ASN.1 Types. LBER is a
38 /// subset of BER as described in the following taken from 5.1 of RFC 2251:
40 /// 5.1. Mapping Onto BER-based Transport Services
42 /// The protocol elements of Ldap are encoded for exchange using the
43 /// Basic Encoding Rules (BER) [11] of ASN.1 [3]. However, due to the
44 /// high overhead involved in using certain elements of the BER, the
45 /// following additional restrictions are placed on BER-encodings of Ldap
46 /// protocol elements:
48 /// <li>(1) Only the definite form of length encoding will be used.</li>
50 /// <li>(2) OCTET STRING values will be encoded in the primitive form only.</li>
52 /// <li>(3) If the value of a BOOLEAN type is true, the encoding MUST have
53 /// its contents octets set to hex "FF".</li>
55 /// <li>(4) If a value of a type is its default value, it MUST be absent.
56 /// Only some BOOLEAN and INTEGER types have default values in this
57 /// protocol definition.
59 /// These restrictions do not apply to ASN.1 types encapsulated inside of
60 /// OCTET STRING values, such as attribute values, unless otherwise
63 /// [3] ITU-T Rec. X.680, "Abstract Syntax Notation One (ASN.1) -
64 /// Specification of Basic Notation", 1994.
66 /// [11] ITU-T Rec. X.690, "Specification of ASN.1 encoding rules: Basic,
67 /// Canonical, and Distinguished Encoding Rules", 1994.
70 public class LBEREncoder : Asn1Encoder
73 /* Encoders for ASN.1 simple type Contents
75 public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
78 /// <summary> BER Encode an Asn1Boolean directly into the specified output stream.</summary>
79 public virtual void encode(Asn1Boolean b, System.IO.Stream out_Renamed)
82 encode(b.getIdentifier(), out_Renamed);
84 /* Encode the length */
85 out_Renamed.WriteByte((System.Byte) 0x01);
87 /* Encode the boolean content*/
88 out_Renamed.WriteByte((byte) (b.booleanValue()?(sbyte) SupportClass.Identity(0xff):(sbyte) 0x00));
93 /// <summary> Encode an Asn1Numeric directly into the specified outputstream.
95 /// Use a two's complement representation in the fewest number of octets
98 /// Can be used to encode INTEGER and ENUMERATED values.
100 public void encode(Asn1Numeric n, System.IO.Stream out_Renamed)
102 sbyte[] octets = new sbyte[8];
104 long value_Renamed = n.longValue();
105 long endValue = (value_Renamed < 0)?- 1:0;
106 long endSign = endValue & 0x80;
108 for (len = 0; len == 0 || value_Renamed != endValue || (octets[len - 1] & 0x80) != endSign; len++)
110 octets[len] = (sbyte) (value_Renamed & 0xFF);
114 encode(n.getIdentifier(), out_Renamed);
115 out_Renamed.WriteByte((byte) len); // Length
116 for (int i = len - 1; i >= 0; i--)
118 out_Renamed.WriteByte((byte) octets[i]);
122 /* Asn1 TYPE NOT YET SUPPORTED
123 * Encode an Asn1Real directly to a stream.
124 public void encode(Asn1Real r, OutputStream out)
127 throw new IOException("LBEREncoder: Encode to a stream not implemented");
131 /// <summary> Encode an Asn1Null directly into the specified outputstream.</summary>
132 public void encode(Asn1Null n, System.IO.Stream out_Renamed)
134 encode(n.getIdentifier(), out_Renamed);
135 out_Renamed.WriteByte((System.Byte) 0x00); // Length (with no Content)
139 /* Asn1 TYPE NOT YET SUPPORTED
140 * Encode an Asn1BitString directly to a stream.
141 public void encode(Asn1BitString bs, OutputStream out)
144 throw new IOException("LBEREncoder: Encode to a stream not implemented");
148 /// <summary> Encode an Asn1OctetString directly into the specified outputstream.</summary>
149 public void encode(Asn1OctetString os, System.IO.Stream out_Renamed)
151 encode(os.getIdentifier(), out_Renamed);
152 encodeLength(os.byteValue().Length, out_Renamed);
153 sbyte[] temp_sbyteArray;
154 temp_sbyteArray = os.byteValue();
155 out_Renamed.Write(SupportClass.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);;;
159 /* Asn1 TYPE NOT YET SUPPORTED
160 * Encode an Asn1ObjectIdentifier directly to a stream.
161 * public void encode(Asn1ObjectIdentifier oi, OutputStream out)
164 * throw new IOException("LBEREncoder: Encode to a stream not implemented");
168 /* Asn1 TYPE NOT YET SUPPORTED
169 * Encode an Asn1CharacterString directly to a stream.
170 * public void encode(Asn1CharacterString cs, OutputStream out)
173 * throw new IOException("LBEREncoder: Encode to a stream not implemented");
177 /* Encoders for ASN.1 structured types
180 /// <summary> Encode an Asn1Structured into the specified outputstream. This method
181 /// can be used to encode SET, SET_OF, SEQUENCE, SEQUENCE_OF
183 public void encode(Asn1Structured c, System.IO.Stream out_Renamed)
185 encode(c.getIdentifier(), out_Renamed);
187 Asn1Object[] value_Renamed = c.toArray();
189 System.IO.MemoryStream output = new System.IO.MemoryStream();
191 /* Cycle through each element encoding each element */
192 for (int i = 0; i < value_Renamed.Length; i++)
194 (value_Renamed[i]).encode(this, output);
197 /* Encode the length */
198 encodeLength((int)output.Length, out_Renamed);
200 /* Add each encoded element into the output stream */
201 sbyte[] temp_sbyteArray;
202 temp_sbyteArray = SupportClass.ToSByteArray(output.ToArray());
203 out_Renamed.Write(SupportClass.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);;;
207 /// <summary> Encode an Asn1Tagged directly into the specified outputstream.</summary>
208 public void encode(Asn1Tagged t, System.IO.Stream out_Renamed)
212 encode(t.getIdentifier(), out_Renamed);
214 /* determine the encoded length of the base type. */
215 System.IO.MemoryStream encodedContent = new System.IO.MemoryStream();
216 t.taggedValue().encode(this, encodedContent);
218 encodeLength((int)encodedContent.Length, out_Renamed);
219 sbyte[] temp_sbyteArray;
220 temp_sbyteArray = SupportClass.ToSByteArray(encodedContent.ToArray());
221 out_Renamed.Write(SupportClass.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);;;;
225 t.taggedValue().encode(this, out_Renamed);
230 /* Encoders for ASN.1 useful types
232 /* Encoder for ASN.1 Identifier
235 /// <summary> Encode an Asn1Identifier directly into the specified outputstream.</summary>
236 public void encode(Asn1Identifier id, System.IO.Stream out_Renamed)
238 int c = id.Asn1Class;
240 sbyte ccf = (sbyte) ((c << 6) | (id.Constructed?0x20:0));
245 out_Renamed.WriteByte((System.Byte) (ccf | t));
250 out_Renamed.WriteByte((System.Byte) (ccf | 0x1F));
251 encodeTagInteger(t, out_Renamed);
256 /* Private helper methods
260 * Encodes the specified length into the the outputstream
262 private void encodeLength(int length, System.IO.Stream out_Renamed)
266 out_Renamed.WriteByte((System.Byte) length);
270 sbyte[] octets = new sbyte[4]; // 4 bytes sufficient for 32 bit int.
272 for (n = 0; length != 0; n++)
274 octets[n] = (sbyte) (length & 0xFF);
278 out_Renamed.WriteByte((System.Byte) (0x80 | n));
280 for (int i = n - 1; i >= 0; i--)
281 out_Renamed.WriteByte((byte) octets[i]);
286 /// <summary> Encodes the provided tag into the outputstream.</summary>
287 private void encodeTagInteger(int value_Renamed, System.IO.Stream out_Renamed)
289 sbyte[] octets = new sbyte[5];
291 for (n = 0; value_Renamed != 0; n++)
293 octets[n] = (sbyte) (value_Renamed & 0x7F);
294 value_Renamed = value_Renamed >> 7;
296 for (int i = n - 1; i > 0; i--)
298 out_Renamed.WriteByte((System.Byte) (octets[i] | 0x80));
300 out_Renamed.WriteByte((byte) octets[0]);