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 [CLSCompliantAttribute(true)]
71 public class LBEREncoder
: Asn1Encoder
74 /* Encoders for ASN.1 simple type Contents
76 public void GetObjectData(System
.Runtime
.Serialization
.SerializationInfo info
, System
.Runtime
.Serialization
.StreamingContext context
)
79 /// <summary> BER Encode an Asn1Boolean directly into the specified output stream.</summary>
80 public virtual void encode(Asn1Boolean b
, System
.IO
.Stream out_Renamed
)
83 encode(b
.getIdentifier(), out_Renamed
);
85 /* Encode the length */
86 out_Renamed
.WriteByte((System
.Byte
) 0x01);
88 /* Encode the boolean content*/
89 out_Renamed
.WriteByte((byte) (b
.booleanValue()?(sbyte) SupportClass
.Identity(0xff):(sbyte) 0x00));
94 /// <summary> Encode an Asn1Numeric directly into the specified outputstream.
96 /// Use a two's complement representation in the fewest number of octets
99 /// Can be used to encode INTEGER and ENUMERATED values.
101 public void encode(Asn1Numeric n
, System
.IO
.Stream out_Renamed
)
103 sbyte[] octets
= new sbyte[8];
105 long value_Renamed
= n
.longValue();
106 long endValue
= (value_Renamed
< 0)?- 1:0;
107 long endSign
= endValue
& 0x80;
109 for (len
= 0; len
== 0 || value_Renamed
!= endValue
|| (octets
[len
- 1] & 0x80) != endSign
; len
++)
111 octets
[len
] = (sbyte) (value_Renamed
& 0xFF);
115 encode(n
.getIdentifier(), out_Renamed
);
116 out_Renamed
.WriteByte((byte) len
); // Length
117 for (int i
= len
- 1; i
>= 0; i
--)
119 out_Renamed
.WriteByte((byte) octets
[i
]);
123 /* Asn1 TYPE NOT YET SUPPORTED
124 * Encode an Asn1Real directly to a stream.
125 public void encode(Asn1Real r, OutputStream out)
128 throw new IOException("LBEREncoder: Encode to a stream not implemented");
132 /// <summary> Encode an Asn1Null directly into the specified outputstream.</summary>
133 public void encode(Asn1Null n
, System
.IO
.Stream out_Renamed
)
135 encode(n
.getIdentifier(), out_Renamed
);
136 out_Renamed
.WriteByte((System
.Byte
) 0x00); // Length (with no Content)
140 /* Asn1 TYPE NOT YET SUPPORTED
141 * Encode an Asn1BitString directly to a stream.
142 public void encode(Asn1BitString bs, OutputStream out)
145 throw new IOException("LBEREncoder: Encode to a stream not implemented");
149 /// <summary> Encode an Asn1OctetString directly into the specified outputstream.</summary>
150 public void encode(Asn1OctetString os
, System
.IO
.Stream out_Renamed
)
152 encode(os
.getIdentifier(), out_Renamed
);
153 encodeLength(os
.byteValue().Length
, out_Renamed
);
154 sbyte[] temp_sbyteArray
;
155 temp_sbyteArray
= os
.byteValue();
156 out_Renamed
.Write(SupportClass
.ToByteArray(temp_sbyteArray
), 0, temp_sbyteArray
.Length
);;;
160 /* Asn1 TYPE NOT YET SUPPORTED
161 * Encode an Asn1ObjectIdentifier directly to a stream.
162 * public void encode(Asn1ObjectIdentifier oi, OutputStream out)
165 * throw new IOException("LBEREncoder: Encode to a stream not implemented");
169 /* Asn1 TYPE NOT YET SUPPORTED
170 * Encode an Asn1CharacterString directly to a stream.
171 * public void encode(Asn1CharacterString cs, OutputStream out)
174 * throw new IOException("LBEREncoder: Encode to a stream not implemented");
178 /* Encoders for ASN.1 structured types
181 /// <summary> Encode an Asn1Structured into the specified outputstream. This method
182 /// can be used to encode SET, SET_OF, SEQUENCE, SEQUENCE_OF
184 public void encode(Asn1Structured c
, System
.IO
.Stream out_Renamed
)
186 encode(c
.getIdentifier(), out_Renamed
);
188 Asn1Object
[] value_Renamed
= c
.toArray();
190 System
.IO
.MemoryStream output
= new System
.IO
.MemoryStream();
192 /* Cycle through each element encoding each element */
193 for (int i
= 0; i
< value_Renamed
.Length
; i
++)
195 (value_Renamed
[i
]).encode(this, output
);
198 /* Encode the length */
199 encodeLength((int)output
.Length
, out_Renamed
);
201 /* Add each encoded element into the output stream */
202 sbyte[] temp_sbyteArray
;
203 temp_sbyteArray
= SupportClass
.ToSByteArray(output
.ToArray());
204 out_Renamed
.Write(SupportClass
.ToByteArray(temp_sbyteArray
), 0, temp_sbyteArray
.Length
);;;
208 /// <summary> Encode an Asn1Tagged directly into the specified outputstream.</summary>
209 public void encode(Asn1Tagged t
, System
.IO
.Stream out_Renamed
)
213 encode(t
.getIdentifier(), out_Renamed
);
215 /* determine the encoded length of the base type. */
216 System
.IO
.MemoryStream encodedContent
= new System
.IO
.MemoryStream();
217 t
.taggedValue().encode(this, encodedContent
);
219 encodeLength((int)encodedContent
.Length
, out_Renamed
);
220 sbyte[] temp_sbyteArray
;
221 temp_sbyteArray
= SupportClass
.ToSByteArray(encodedContent
.ToArray());
222 out_Renamed
.Write(SupportClass
.ToByteArray(temp_sbyteArray
), 0, temp_sbyteArray
.Length
);;;;
226 t
.taggedValue().encode(this, out_Renamed
);
231 /* Encoders for ASN.1 useful types
233 /* Encoder for ASN.1 Identifier
236 /// <summary> Encode an Asn1Identifier directly into the specified outputstream.</summary>
237 public void encode(Asn1Identifier id
, System
.IO
.Stream out_Renamed
)
239 int c
= id
.Asn1Class
;
241 sbyte ccf
= (sbyte) ((c
<< 6) | (id
.Constructed
?0x20:0));
246 out_Renamed
.WriteByte((System
.Byte
) (ccf
| t
));
251 out_Renamed
.WriteByte((System
.Byte
) (ccf
| 0x1F));
252 encodeTagInteger(t
, out_Renamed
);
257 /* Private helper methods
261 * Encodes the specified length into the the outputstream
263 private void encodeLength(int length
, System
.IO
.Stream out_Renamed
)
267 out_Renamed
.WriteByte((System
.Byte
) length
);
271 sbyte[] octets
= new sbyte[4]; // 4 bytes sufficient for 32 bit int.
273 for (n
= 0; length
!= 0; n
++)
275 octets
[n
] = (sbyte) (length
& 0xFF);
279 out_Renamed
.WriteByte((System
.Byte
) (0x80 | n
));
281 for (int i
= n
- 1; i
>= 0; i
--)
282 out_Renamed
.WriteByte((byte) octets
[i
]);
287 /// <summary> Encodes the provided tag into the outputstream.</summary>
288 private void encodeTagInteger(int value_Renamed
, System
.IO
.Stream out_Renamed
)
290 sbyte[] octets
= new sbyte[5];
292 for (n
= 0; value_Renamed
!= 0; n
++)
294 octets
[n
] = (sbyte) (value_Renamed
& 0x7F);
295 value_Renamed
= value_Renamed
>> 7;
297 for (int i
= n
- 1; i
> 0; i
--)
299 out_Renamed
.WriteByte((System
.Byte
) (octets
[i
] | 0x80));
301 out_Renamed
.WriteByte((byte) octets
[0]);