2 * Copyright (c) 2014-2015 Sylvain Peyrefitte
4 * This file is part of node-rdpjs.
6 * node-rdpjs is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20var spec = require('./spec');
21var type = require('../core').type;
22var error = require('../core').error;
23var inherits = require('util').inherits;
26 * ASN.1 Universal tags
27 * @see http://www.obj-sys.com/asn1tutorial/node124.html
52 * @param value {boolean} inner value
54function Boolean(value) {
55 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.Boolean));
56 this.value = value || false;
59inherits(Boolean, spec.Asn1Spec);
62 * @param s {type.Stream}
63 * @param decoder {ber.decoder}
66Boolean.prototype.decode = function(s, decoder) {
67 this.value = new type.UInt8().read(new type.Stream(decoder.decode(s, this.tag).value)).value !== 0;
72 * @param decoder {ber.decoder}
75Boolean.prototype.encode = function(encoder) {
77 return encoder.encode(this.tag, new type.UInt8(0xff));
80 return encoder.encode(this.tag, new type.UInt8(0));
86 * @param value {integer | Buffer}
88function Integer(value) {
89 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.Integer));
90 this.value = value || 0;
93inherits(Integer, spec.Asn1Spec);
96 * @param s {type.Stream}
97 * @param decoder {ber.decoder}
100Integer.prototype.decode = function(s, decoder) {
101 var integerBuffer = decoder.decode(s, this.tag).value;
102 if(integerBuffer.length < 5) {
103 var integerStream = new type.Stream(integerBuffer);
104 while (integerStream.availableLength() > 0) {
105 this.value = this.value << 8;
106 this.value |= new type.UInt8().read(integerStream).value;
111 this.value = integerBuffer;
117 * @param encoder {ber.decoder}
120Integer.prototype.encode = function(encoder) {
121 if(this.value <= 0xff) {
122 return encoder.encode(this.tag, new type.UInt8(this.value));
124 else if(this.value <= 0xffff) {
125 return encoder.encode(this.tag, new type.UInt16Be(this.value));
128 return encoder.encode(this.tag, new type.UInt32Be(this.value));
134 * @param value {object}
136function Sequence(value) {
137 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Constructed, UniversalTag.Sequence));
138 this.value = value || [];
141inherits(Sequence, spec.Asn1Spec);
144 * @param s {type.Stream}
145 * @param decoder {ber.decoder}
146 * @returns {Sequence}
148Sequence.prototype.decode = function(s, decoder) {
149 var sequenceStream = new type.Stream(decoder.decode(s, this.tag).value);
150 for (var i in this.value) {
151 var rec = sequenceStream.offset;
153 this.value[i].decode(sequenceStream, decoder);
155 if ((e.message === 'NODE_RDP_ASN1_BER_INVALID_TAG') && !this.value[i].opt) {
156 throw new error.ProtocolError('NODE_RDP_ASN1_UNIV_SEQUENCE_FIELD_NOT_PRESENT');
158 sequenceStream.offset = rec;
167 * @returns {type.Component}
169Sequence.prototype.encode = function(encoder) {
170 var sequence = new type.Component([]);
171 for (var i in this.value) {
172 sequence.obj.push(this.value[i].encode(encoder))
174 return encoder.encode(this.tag, sequence);
180 * @param value {integer}
182function Enumerate(value) {
183 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.Enumerate));
184 this.value = value || 0;
187inherits(Enumerate, spec.Asn1Spec);
190 * @param s {type.Stream}
191 * @param decoder {ber.decoder}
192 * @returns {Enumerate}
194Enumerate.prototype.decode = function(s, decoder) {
195 this.value = new type.UInt8().read(new type.Stream(decoder.decode(s, this.tag).value)).value;
200 * Encode enumerate type
202 * @returns {type.Component}
204Enumerate.prototype.encode = function(encoder) {
205 return encoder.encode(this.tag, new type.UInt8(this.value));
210 * @param value {Buffer}
212function OctetString(value) {
213 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.OctetString));
214 this.value = value || Buffer.alloc(0);
217inherits(OctetString, spec.Asn1Spec);
220 * @param s {type.Stream}
221 * @param decoder {ber.decoder}
222 * @returns {OctetString}
224OctetString.prototype.decode = function(s, decoder) {
225 this.value = decoder.decode(s, this.tag).value;
230 * Encode Octet String
232 * @returns {type.Component}
234OctetString.prototype.encode = function(encoder) {
235 return encoder.encode(this.tag, new type.BinaryString(this.value));
239 * ObjectIdentifier type
240 * @param value {Buffer}
242function ObjectIdentifier(value) {
243 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.ObjectIdentifier));
244 this.value = value || Buffer.alloc(5);
247inherits(ObjectIdentifier, spec.Asn1Spec);
250 * @param s {type.Stream}
251 * @param decoder {ber.decoder}
252 * @returns {ObjectIdentifier}
254ObjectIdentifier.prototype.decode = function(s, decoder) {
255 this.value = decoder.decode(s, this.tag).value;
263 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.Null));
266inherits(Null, spec.Asn1Spec);
269 * @param s {type.Stream}
270 * @param decoder {ber.decoder}
273Null.prototype.decode = function(s, decoder) {
274 decoder.decode(s, this.tag);
280 * @param value {object} list of available type
282function Choice(value) {
284 spec.Asn1Spec.call(this, new spec.Asn1Tag());
288inherits(Choice, spec.Asn1Spec);
291 * @param s {type.Stream}
292 * @param decoder {ber.decoder}
295Choice.prototype.decode = function(s, decoder) {
296 for (var i in this.value) {
299 this.value[i].decode(s, decoder);
311 * @param factory {function} type builder
312 * @param value {object} list of available type
314function SetOf(factory, value) {
316 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Constructed, UniversalTag.Set));
317 this.factory = factory;
318 this.value = value || [];
321inherits(SetOf, spec.Asn1Spec);
324 * @param s {type.Stream}
325 * @param decoder {ber.decoder}
328SetOf.prototype.decode = function(s, decoder) {
329 var setOfStream = new type.Stream(decoder.decode(s, this.tag).value);
330 while (setOfStream.availableLength() > 0) {
331 this.value.push(this.factory().decode(setOfStream, decoder));
338 * @param factory {function} type builder
339 * @param value {object} list of available type
341function SequenceOf(factory, value) {
343 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Constructed, UniversalTag.Sequence));
344 this.factory = factory;
345 this.value = value || [];
348inherits(SequenceOf, spec.Asn1Spec);
351 * @param s {type.Stream}
352 * @param decoder {ber.decoder}
353 * @returns {SequenceOf}
355SequenceOf.prototype.decode = function(s, decoder) {
356 var sequenceOfStream = new type.Stream(decoder.decode(s, this.tag).value);
357 while (sequenceOfStream.availableLength() > 0) {
358 this.value.push(this.factory().decode(sequenceOfStream, decoder));
365 * @param value {Buffer}
367function BitString(value) {
368 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.BitString));
372inherits(BitString, spec.Asn1Spec);
375 * @param s {type.Stream}
376 * @param decoder {ber.decoder}
377 * @returns {BitString}
379BitString.prototype.decode = function(s, decoder) {
380 var bitStream = new type.Stream(decoder.decode(s, this.tag).value);
381 var padding = new type.UInt8().read(bitStream).value;
383 for(var i = 0; i < padding; i++) {
387 while(bitStream.availableLength() > 0) {
388 var octet = new type.UInt8().read(bitStream).value;
389 var currentPadding = 0;
390 if(bitStream.availableLength() === 0) {
391 currentPadding = padding;
393 for(var i = 7; i >= currentPadding; i--) {
394 value.push(((octet >> i) & 1)?1:0);
402 * Convert bit string to buffer object
405BitString.prototype.toBuffer = function () {
406 var length = this.value.length / 8;
407 var resultStream = new type.Stream(length);
408 for (var i = 0; i < length; i ++) {
409 var currentOctet = 0;
410 for (var j = 0; j < 8; j++) {
411 currentOctet = currentOctet | (this.value[i * 8 + j] << (7 - j));
413 new type.UInt8(currentOctet).write(resultStream);
415 return resultStream.buffer;
420 * @param value {Buffer}
422function T61String(value) {
423 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.T61String));
427inherits(T61String, spec.Asn1Spec);
430 * @param s {type.Stream}
431 * @param decoder {ber.decoder}
432 * @returns {T61String}
434T61String.prototype.decode = function(s, decoder) {
435 this.value = decoder.decode(s, this.tag).value;
440 * PrintableString type
441 * @param value {Buffer}
443function PrintableString(value) {
444 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.PrintableString));
448inherits(PrintableString, spec.Asn1Spec);
451 * @param s {type.Stream}
452 * @param decoder {ber.decoder}
453 * @returns {PrintableString}
455PrintableString.prototype.decode = function(s, decoder) {
456 this.value = decoder.decode(s, this.tag).value;
461 * UniversalString type
462 * @param value {Buffer}
464function UniversalString(value) {
465 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.UniversalString));
469inherits(UniversalString, spec.Asn1Spec);
472 * @param s {type.Stream}
473 * @param decoder {ber.decoder}
474 * @returns {UniversalString}
476UniversalString.prototype.decode = function(s, decoder) {
477 this.value = decoder.decode(s, this.tag).value;
483 * @param value {Buffer}
485function UTF8String(value) {
486 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.UTF8String));
490inherits(UTF8String, spec.Asn1Spec);
493 * @param s {type.Stream}
494 * @param decoder {ber.decoder}
495 * @returns {UTF8String}
497UTF8String.prototype.decode = function(s, decoder) {
498 this.value = decoder.decode(s, this.tag).value;
504 * @param value {Buffer}
506function BMPString(value) {
507 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.BMPString));
511inherits(BMPString, spec.Asn1Spec);
514 * @param s {type.Stream}
515 * @param decoder {ber.decoder}
516 * @returns {BMPString}
518BMPString.prototype.decode = function(s, decoder) {
519 this.value = decoder.decode(s, this.tag).value;
525 * @param value {Buffer}
527function IA5String(value) {
528 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.IA5String));
532inherits(IA5String, spec.Asn1Spec);
535 * @param s {type.Stream}
536 * @param decoder {ber.decoder}
537 * @returns {IA5String}
539IA5String.prototype.decode = function(s, decoder) {
540 this.value = decoder.decode(s, this.tag).value;
546 * @param value {Buffer}
548function UTCTime(value) {
549 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.UTCTime));
553inherits(UTCTime, spec.Asn1Spec);
556 * @param s {type.Stream}
557 * @param decoder {ber.decoder}
560UTCTime.prototype.decode = function(s, decoder) {
561 this.value = decoder.decode(s, this.tag).value;
566 * GeneralizedTime type
567 * @param value {Buffer}
569function GeneralizedTime(value) {
570 spec.Asn1Spec.call(this, new spec.Asn1Tag(spec.TagClass.Universal, spec.TagFormat.Primitive, UniversalTag.GeneralizedTime));
574inherits(GeneralizedTime, spec.Asn1Spec);
577 * @param s {type.Stream}
578 * @param decoder {ber.decoder}
579 * @returns {GeneralizedTime}
581GeneralizedTime.prototype.decode = function(s, decoder) {
582 this.value = decoder.decode(s, this.tag).value;
590 Enumerate : Enumerate,
591 OctetString : OctetString,
592 ObjectIdentifier : ObjectIdentifier,
595 SequenceOf : SequenceOf,
597 BitString : BitString,
598 T61String : T61String,
599 PrintableString : PrintableString,
600 UniversalString : UniversalString,
601 UTF8String : UTF8String,
602 BMPString : BMPString,
603 IA5String : IA5String,
605 GeneralizedTime : GeneralizedTime