From 2c39a29f355c1b108e6813577d5134021e48cebb Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Sun, 10 Dec 2017 05:07:09 -0500 Subject: [PATCH 01/11] Changing OID format to accept a single digit --- lib/ber/writer.js | 2 +- package.json | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/ber/writer.js b/lib/ber/writer.js index d9d99af..48cfa86 100644 --- a/lib/ber/writer.js +++ b/lib/ber/writer.js @@ -176,7 +176,7 @@ Writer.prototype.writeOID = function(s, tag) { if (typeof(tag) !== 'number') tag = ASN1.OID; - if (!/^([0-9]+\.){3,}[0-9]+$/.test(s)) + if (!/^([0-9]+\.)*[0-9]+$/.test(s)) throw new Error('argument is not a valid OID string'); function encodeOctet(bytes, octet) { diff --git a/package.json b/package.json index f6dfb06..747dc22 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,12 @@ "contributors": [ "David Gwynne ", "Yunong Xiao ", - "Alex Wilson " + "Alex Wilson ", + "Gilles Dufour Date: Tue, 19 Dec 2017 03:23:41 -0500 Subject: [PATCH 02/11] Adding support for indefinite length --- lib/ber/reader.js | 134 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 29 deletions(-) mode change 100644 => 100755 lib/ber/reader.js diff --git a/lib/ber/reader.js b/lib/ber/reader.js old mode 100644 new mode 100755 index 0a00e98..fedd579 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -10,8 +10,6 @@ var errors = require('./errors'); var newInvalidAsn1Error = errors.newInvalidAsn1Error; - - ///--- API function Reader(data) { @@ -20,7 +18,8 @@ function Reader(data) { this._buf = data; this._size = data.length; - + this._blocklevel = 0; + this._blockInfo = {}; // These hold the "current" state this._len = 0; this._offset = 0; @@ -53,8 +52,10 @@ Object.defineProperty(Reader.prototype, 'buffer', { * @return {Number} the next byte, null if not enough data. */ Reader.prototype.readByte = function(peek) { - if (this._size - this._offset < 1) - return null; + if (this._size - this._offset < 1) { + throw new Error(`invalid byte from ${this._offset} with current size ${this._size}`); + return null; + } var b = this._buf[this._offset] & 0xff; @@ -65,6 +66,60 @@ Reader.prototype.readByte = function(peek) { }; +Reader.prototype.readBlock = function(offset) +{ + if (offset === undefined) { + offset = this._offset; + } + var currOffset = offset; + var b, lenB; + + if (this._blockInfo[offset] !== undefined) { + return this._blockInfo[offset]; + } + + while(this.remain > 0) { + b = this._buf[currOffset++]; + lenB = this._buf[currOffset++]; + + if ((b == 0) && (lenB == 0)) { + break; // end of block + } + var len = 0; + if ((lenB & 0x80) == 0x80) { + lenB &= 0x7f; + + if (lenB == 0) { + this._blocklevel++; + lenB = this.readBlock(currOffset); + this._blocklevel--; + } + else { + if (lenB > 4) + throw InvalidAsn1Error('encoding too long'); + + if (this._size - this.offset < lenB) { + return null; + } + + for (var i = 0; i < lenB; i++) { + len = (len << 8) + (this._buf[currOffset++] & 0xff); + } + lenB = len; + } + } + currOffset += lenB; + if (currOffset > this._size) { + throw new Error(`invalid block at offset ${offset}`); + return null; + } + } + lenB = currOffset - offset; + this._blockInfo[offset] = lenB; + + return lenB; +} + Reader.prototype.peek = function() { return this.readByte(true); }; @@ -85,28 +140,34 @@ Reader.prototype.readLength = function(offset) { if (offset === undefined) offset = this._offset; - if (offset >= this._size) - return null; + if (offset >= this._size) { + throw new Error(`offset ${offset} outside buffer size ${this._size}`); + return null; + } var lenB = this._buf[offset++] & 0xff; - if (lenB === null) - return null; + if (lenB === null) { + throw new Error("invalid length"); + return null; + } if ((lenB & 0x80) == 0x80) { lenB &= 0x7f; - if (lenB == 0) - throw newInvalidAsn1Error('Indefinite length not supported'); + if (lenB == 0) { + this._len = this.readBlock(offset); + } + else { + if (lenB > 4) + throw newInvalidAsn1Error('encoding too long'); - if (lenB > 4) - throw newInvalidAsn1Error('encoding too long'); + if (this._size - offset < lenB) + return null; - if (this._size - offset < lenB) - return null; - - this._len = 0; - for (var i = 0; i < lenB; i++) - this._len = (this._len << 8) + (this._buf[offset++] & 0xff); + this._len = 0; + for (var i = 0; i < lenB; i++) + this._len = (this._len << 8) + (this._buf[offset++] & 0xff); + } } else { // Wasn't a variable length @@ -156,32 +217,47 @@ Reader.prototype.readEnumeration = function() { }; + Reader.prototype.readString = function(tag, retbuf) { if (!tag) tag = ASN1.OctetString; var b = this.peek(); - if (b === null) - return null; - + if (b === null) { + throw new Error(`Invalid tag - ${b} expected ${tag.toString(16)}`); + return null; + } if (b !== tag) throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + ': got 0x' + b.toString(16)); var o = this.readLength(this._offset + 1); // stored in `length` - if (o === null) - return null; + if (o === null) { + throw new Error("readString - invalid length"); + } + if (this.length === 0) { + this._offset = o; + return retbuf ? new Buffer(0) : ''; + } + + var length = this.length; + if (this._blockInfo[this._offset + 2] !== undefined) { + length = length - 2; + } - if (this.length > this._size - o) - return null; + + + + if (this.length > this._size - o) { + throw new Error (`invalid block length ${this.length} > ${this._size} - ${o}`); + } this._offset = o; - if (this.length === 0) - return retbuf ? new Buffer(0) : ''; - var str = this._buf.slice(this._offset, this._offset + this.length); + + var str = this._buf.slice(this._offset, this._offset + length); this._offset += this.length; return retbuf ? str : str.toString('utf8'); From 103cb866dd64c05682065d707870a0231b81daf1 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Tue, 19 Dec 2017 03:24:04 -0500 Subject: [PATCH 03/11] version 0.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 747dc22..5448739 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.3.0", + "version": "0.4.0", "repository": { "type": "git", "url": "git://github.com/mcavage/node-asn1.git" From c1f63c9d2c9f80423da1242196afd167e75bf594 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Tue, 19 Dec 2017 08:35:11 -0500 Subject: [PATCH 04/11] extend interger support from 32bits to 64bits --- lib/ber/reader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ber/reader.js b/lib/ber/reader.js index fedd579..804e4c7 100755 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -309,7 +309,7 @@ Reader.prototype._readTag = function(tag) { if (o === null) return null; - if (this.length > 4) + if (this.length > 8) throw newInvalidAsn1Error('Integer too long: ' + this.length); if (this.length > this._size - o) From 46729d279f48dc58b36adedc2d12484159c663b5 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Tue, 2 Jan 2018 10:10:08 -0500 Subject: [PATCH 05/11] Adding read/write relativeOID following X.690 section 8.20 --- lib/ber/reader.js | 26 ++++++++++++++++++++++++++ lib/ber/writer.js | 40 ++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/lib/ber/reader.js b/lib/ber/reader.js index 804e4c7..a141d33 100755 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -263,6 +263,32 @@ Reader.prototype.readString = function(tag, retbuf) { return retbuf ? str : str.toString('utf8'); }; +Reader.prototype.readRelativeOID = function(tag) { + if (!tag) + tag = ASN1.OID; + + var b = this.readString(tag, true); + if (b === null) + return null; + + var values = []; + var value = 0; + + for (var i = 0; i < b.length; i++) { + var byte = b[i] & 0xff; + + value += byte & 0x7F; + if ((byte & 0x80) == 0x80) { + value <<= 7; + continue; + } + values.push(value); + value = 0; + } + + return values.join('.'); +}; + Reader.prototype.readOID = function(tag) { if (!tag) tag = ASN1.OID; diff --git a/lib/ber/writer.js b/lib/ber/writer.js index 48cfa86..95705a3 100644 --- a/lib/ber/writer.js +++ b/lib/ber/writer.js @@ -169,6 +169,46 @@ Writer.prototype.writeStringArray = function(strings) { }); }; +Writer.prototype.writeRelativeOID = function(s,tag) { + if (typeof(s) !== 'string') + throw new TypeError('argument must be a string'); + if (typeof(tag) !== 'number') + tag = ASN1.RelativeOID; + + if (!/^([0-9]+\.)*[0-9]+$/.test(s)) + throw new Error('argument is not a valid OID string'); + + var tmp = s.split('.'); + var bytes = []; + for (var i=0; i < tmp.length; i++) { + var val = parseInt(tmp[i]); + var encodedBytes = []; + while(val > 0x7F) { + var res = val & 0x7F; + encodedBytes.push(res); + val = val >> 7; + } + encodedBytes.push(val); + var j = encodedBytes.length - 1; + while(j >= 0) { + if (j > 0) { + bytes.push(encodedBytes[j] | 0x80); + } + else { + bytes.push(encodedBytes[j]); + } + j--; + } + } + var self = this; + this._ensure(2 + bytes.length); + this.writeByte(tag); + this.writeLength(bytes.length); + bytes.forEach(function(b) { + self.writeByte(b); + }); +}; + // This is really to solve DER cases, but whatever for now Writer.prototype.writeOID = function(s, tag) { if (typeof(s) !== 'string') diff --git a/package.json b/package.json index 5448739..295bfac 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.4.0", + "version": "0.5.0", "repository": { "type": "git", "url": "git://github.com/mcavage/node-asn1.git" From 2fc158464a92e1465523f108295abd54e7ce86db Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Tue, 2 Jan 2018 10:15:18 -0500 Subject: [PATCH 06/11] Fixing relative oid tag for reader --- lib/ber/reader.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ber/reader.js b/lib/ber/reader.js index a141d33..502735c 100755 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -265,7 +265,7 @@ Reader.prototype.readString = function(tag, retbuf) { Reader.prototype.readRelativeOID = function(tag) { if (!tag) - tag = ASN1.OID; + tag = ASN1.RelativeOID; var b = this.readString(tag, true); if (b === null) diff --git a/package.json b/package.json index 295bfac..3e89abd 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.5.0", + "version": "0.5.1", "repository": { "type": "git", "url": "git://github.com/mcavage/node-asn1.git" From c96258af8eb0417908c8667c994eb97c549fc6e0 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Tue, 14 Jan 2020 11:04:35 +0100 Subject: [PATCH 07/11] Fix: Allow empty relative OID --- lib/ber/writer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ber/writer.js b/lib/ber/writer.js index 95705a3..b0090d2 100644 --- a/lib/ber/writer.js +++ b/lib/ber/writer.js @@ -175,10 +175,10 @@ Writer.prototype.writeRelativeOID = function(s,tag) { if (typeof(tag) !== 'number') tag = ASN1.RelativeOID; - if (!/^([0-9]+\.)*[0-9]+$/.test(s)) + if (!/^([0-9]+\.)*[0-9]*$/.test(s)) throw new Error('argument is not a valid OID string'); - var tmp = s.split('.'); + var tmp = s === "" ? [] : s.split('.'); var bytes = []; for (var i=0; i < tmp.length; i++) { var val = parseInt(tmp[i]); From 67d1a3b0c969c4f9dbb5f36149814fcff1efa500 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Mon, 20 Jan 2020 15:12:18 +0100 Subject: [PATCH 08/11] Merge with latest version of original setup --- lib/ber/reader.js | 94 +++++------ lib/ber/writer.js | 45 ++--- package.json | 14 +- tst/ber/reader.test.js | 208 ----------------------- tst/ber/writer.test.js | 370 ----------------------------------------- 5 files changed, 75 insertions(+), 656 deletions(-) mode change 100644 => 100755 lib/ber/writer.js mode change 100644 => 100755 package.json delete mode 100644 tst/ber/reader.test.js delete mode 100644 tst/ber/writer.test.js diff --git a/lib/ber/reader.js b/lib/ber/reader.js index 502735c..3cb5853 100755 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -1,6 +1,7 @@ // Copyright 2011 Mark Cavage All rights reserved. var assert = require('assert'); +var Buffer = require('safer-buffer').Buffer; var ASN1 = require('./types'); var errors = require('./errors'); @@ -52,10 +53,9 @@ Object.defineProperty(Reader.prototype, 'buffer', { * @return {Number} the next byte, null if not enough data. */ Reader.prototype.readByte = function(peek) { - if (this._size - this._offset < 1) { - throw new Error(`invalid byte from ${this._offset} with current size ${this._size}`); + if (this._size - this._offset < 1) return null; - } + var b = this._buf[this._offset] & 0xff; @@ -136,42 +136,38 @@ Reader.prototype.peek = function() { * @return {Number} the amount of offset to advance the buffer. * @throws {InvalidAsn1Error} on bad ASN.1 */ -Reader.prototype.readLength = function(offset) { +Reader.prototype.readLength = function (offset) { if (offset === undefined) offset = this._offset; - if (offset >= this._size) { - throw new Error(`offset ${offset} outside buffer size ${this._size}`); + if (offset >= this._size) return null; - } var lenB = this._buf[offset++] & 0xff; - if (lenB === null) { - throw new Error("invalid length"); + if (lenB === null) return null; - } + - if ((lenB & 0x80) == 0x80) { + if ((lenB & 0x80) === 0x80) { lenB &= 0x7f; - if (lenB == 0) { - this._len = this.readBlock(offset); + if (lenB === 0) { + this._len = this.readBlock(offset); } else { - if (lenB > 4) - throw newInvalidAsn1Error('encoding too long'); + if (lenB > 4) + throw newInvalidAsn1Error('encoding too long'); - if (this._size - offset < lenB) - return null; + if (this._size - offset < lenB) + return null; - this._len = 0; - for (var i = 0; i < lenB; i++) - this._len = (this._len << 8) + (this._buf[offset++] & 0xff); + this._len = 0; + for (var i = 0; i < lenB; i++) + this._len = (this._len << 8) + (this._buf[offset++] & 0xff); } - } else { - // Wasn't a variable length - this._len = lenB; + // Wasn't a variable length + this._len = lenB; } return offset; @@ -185,7 +181,7 @@ Reader.prototype.readLength = function(offset) { * * @return {Number} the sequence's tag. */ -Reader.prototype.readSequence = function(tag) { +Reader.prototype.readSequence = function (tag) { var seq = this.peek(); if (seq === null) return null; @@ -202,60 +198,54 @@ Reader.prototype.readSequence = function(tag) { }; -Reader.prototype.readInt = function() { +Reader.prototype.readInt = function () { return this._readTag(ASN1.Integer); }; -Reader.prototype.readBoolean = function() { +Reader.prototype.readBoolean = function () { return (this._readTag(ASN1.Boolean) === 0 ? false : true); }; -Reader.prototype.readEnumeration = function() { +Reader.prototype.readEnumeration = function () { return this._readTag(ASN1.Enumeration); }; -Reader.prototype.readString = function(tag, retbuf) { +Reader.prototype.readString = function (tag, retbuf) { if (!tag) tag = ASN1.OctetString; var b = this.peek(); - if (b === null) { - throw new Error(`Invalid tag - ${b} expected ${tag.toString(16)}`); + if (b === null) return null; - } + if (b !== tag) throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) + ': got 0x' + b.toString(16)); var o = this.readLength(this._offset + 1); // stored in `length` - if (o === null) { - throw new Error("readString - invalid length"); - } - if (this.length === 0) { - this._offset = o; - return retbuf ? new Buffer(0) : ''; - } - - var length = this.length; - if (this._blockInfo[this._offset + 2] !== undefined) { - length = length - 2; - } - - + if (o === null) + return null; + if (this.length > this._size - o) + return null; - if (this.length > this._size - o) { - throw new Error (`invalid block length ${this.length} > ${this._size} - ${o}`); + + var length = this.length; + if (this._blockInfo[this._offset + 2] !== undefined) { + length = length - 2; } this._offset = o; + + if (length === 0) + return retbuf ? Buffer.alloc(0) : ''; - + var str = this._buf.slice(this._offset, this._offset + length); this._offset += this.length; @@ -289,7 +279,7 @@ Reader.prototype.readRelativeOID = function(tag) { return values.join('.'); }; -Reader.prototype.readOID = function(tag) { +Reader.prototype.readOID = function (tag) { if (!tag) tag = ASN1.OID; @@ -305,7 +295,7 @@ Reader.prototype.readOID = function(tag) { value <<= 7; value += byte & 0x7f; - if ((byte & 0x80) == 0) { + if ((byte & 0x80) === 0) { values.push(value); value = 0; } @@ -319,7 +309,7 @@ Reader.prototype.readOID = function(tag) { }; -Reader.prototype._readTag = function(tag) { +Reader.prototype._readTag = function (tag) { assert.ok(tag !== undefined); var b = this.peek(); @@ -350,7 +340,7 @@ Reader.prototype._readTag = function(tag) { value |= (this._buf[this._offset++] & 0xff); } - if ((fb & 0x80) == 0x80 && i !== 4) + if ((fb & 0x80) === 0x80 && i !== 4) value -= (1 << (i * 8)); return value >> 0; diff --git a/lib/ber/writer.js b/lib/ber/writer.js old mode 100644 new mode 100755 index b0090d2..a88a7d7 --- a/lib/ber/writer.js +++ b/lib/ber/writer.js @@ -1,6 +1,7 @@ // Copyright 2011 Mark Cavage All rights reserved. var assert = require('assert'); +var Buffer = require('safer-buffer').Buffer; var ASN1 = require('./types'); var errors = require('./errors'); @@ -19,12 +20,12 @@ var DEFAULT_OPTS = { function merge(from, to) { assert.ok(from); - assert.equal(typeof(from), 'object'); + assert.equal(typeof (from), 'object'); assert.ok(to); - assert.equal(typeof(to), 'object'); + assert.equal(typeof (to), 'object'); var keys = Object.getOwnPropertyNames(from); - keys.forEach(function(key) { + keys.forEach(function (key) { if (to[key]) return; @@ -42,7 +43,7 @@ function merge(from, to) { function Writer(options) { options = merge(DEFAULT_OPTS, options || {}); - this._buf = new Buffer(options.size || 1024); + this._buf = Buffer.alloc(options.size || 1024); this._size = this._buf.length; this._offset = 0; this._options = options; @@ -55,14 +56,14 @@ function Writer(options) { Object.defineProperty(Writer.prototype, 'buffer', { get: function () { if (this._seq.length) - throw new InvalidAsn1Error(this._seq.length + ' unended sequence(s)'); + throw newInvalidAsn1Error(this._seq.length + ' unended sequence(s)'); return (this._buf.slice(0, this._offset)); } }); -Writer.prototype.writeByte = function(b) { - if (typeof(b) !== 'number') +Writer.prototype.writeByte = function (b) { + if (typeof (b) !== 'number') throw new TypeError('argument must be a Number'); this._ensure(1); @@ -70,10 +71,10 @@ Writer.prototype.writeByte = function(b) { }; -Writer.prototype.writeInt = function(i, tag) { - if (typeof(i) !== 'number') +Writer.prototype.writeInt = function (i, tag) { + if (typeof (i) !== 'number') throw new TypeError('argument must be a Number'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.Integer; var sz = 4; @@ -85,7 +86,7 @@ Writer.prototype.writeInt = function(i, tag) { } if (sz > 4) - throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff'); + throw newInvalidAsn1Error('BER ints cannot be > 0xffffffff'); this._ensure(2 + sz); this._buf[this._offset++] = tag; @@ -99,26 +100,26 @@ Writer.prototype.writeInt = function(i, tag) { }; -Writer.prototype.writeNull = function() { +Writer.prototype.writeNull = function () { this.writeByte(ASN1.Null); this.writeByte(0x00); }; -Writer.prototype.writeEnumeration = function(i, tag) { - if (typeof(i) !== 'number') +Writer.prototype.writeEnumeration = function (i, tag) { + if (typeof (i) !== 'number') throw new TypeError('argument must be a Number'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.Enumeration; return this.writeInt(i, tag); }; -Writer.prototype.writeBoolean = function(b, tag) { - if (typeof(b) !== 'boolean') +Writer.prototype.writeBoolean = function (b, tag) { + if (typeof (b) !== 'boolean') throw new TypeError('argument must be a Boolean'); - if (typeof(tag) !== 'number') + if (typeof (tag) !== 'number') tag = ASN1.Boolean; this._ensure(3); @@ -130,7 +131,7 @@ Writer.prototype.writeBoolean = function(b, tag) { Writer.prototype.writeString = function(s, tag) { if (typeof(s) !== 'string') - throw new TypeError('argument must be a string (was: ' + typeof(s) + ')'); + throw new TypeError('argument must be a string (was: ' + typeof (s) + ')'); if (typeof(tag) !== 'number') tag = ASN1.OctetString; @@ -281,7 +282,7 @@ Writer.prototype.writeLength = function(len) { this._buf[this._offset++] = len >> 8; this._buf[this._offset++] = len; } else { - throw new InvalidAsn1ERror('Length too long (> 4 bytes)'); + throw newInvalidAsn1Error('Length too long (> 4 bytes)'); } }; @@ -319,7 +320,7 @@ Writer.prototype.endSequence = function() { this._buf[seq + 2] = len >> 8; this._buf[seq + 3] = len; } else { - throw new InvalidAsn1Error('Sequence too long'); + throw newInvalidAsn1Error('Sequence too long'); } }; @@ -341,7 +342,7 @@ Writer.prototype._ensure = function(len) { if (sz - this._offset < len) sz += len; - var buf = new Buffer(sz); + var buf = Buffer.alloc(sz); this._buf.copy(buf, 0, 0, this._offset); this._buf = buf; diff --git a/package.json b/package.json old mode 100644 new mode 100755 index 3e89abd..f76ce30 --- a/package.json +++ b/package.json @@ -8,18 +8,24 @@ ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.5.1", + "version": "0.5.2", "repository": { "type": "git", "url": "git://github.com/mcavage/node-asn1.git" }, "main": "lib/index.js", - "dependencies": {}, + "dependencies": { + "safer-buffer": "~2.1.0" + }, "devDependencies": { - "tap": "0.4.8" + "istanbul": "^0.3.6", + "faucet": "0.0.1", + "tape": "^3.5.0", + "eslint": "2.13.1", + "eslint-plugin-joyent": "~1.3.0" }, "scripts": { - "test": "./node_modules/.bin/tap ./tst" + "test": "./node_modules/.bin/tape ./test/ber/*.test.js" }, "license": "MIT" } diff --git a/tst/ber/reader.test.js b/tst/ber/reader.test.js deleted file mode 100644 index 062fd7e..0000000 --- a/tst/ber/reader.test.js +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2011 Mark Cavage All rights reserved. - -var test = require('tap').test; - - - -///--- Globals - -var BerReader; - - - -///--- Tests - -test('load library', function(t) { - BerReader = require('../../lib/index').BerReader; - t.ok(BerReader); - try { - new BerReader(); - t.fail('Should have thrown'); - } catch (e) { - t.ok(e instanceof TypeError, 'Should have been a type error'); - } - t.end(); -}); - - -test('read byte', function(t) { - var reader = new BerReader(new Buffer([0xde])); - t.ok(reader); - t.equal(reader.readByte(), 0xde, 'wrong value'); - t.end(); -}); - - -test('read 1 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x01, 0x03])); - t.ok(reader); - t.equal(reader.readInt(), 0x03, 'wrong value'); - t.equal(reader.length, 0x01, 'wrong length'); - t.end(); -}); - - -test('read 2 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x02, 0x7e, 0xde])); - t.ok(reader); - t.equal(reader.readInt(), 0x7ede, 'wrong value'); - t.equal(reader.length, 0x02, 'wrong length'); - t.end(); -}); - - -test('read 3 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x03, 0x7e, 0xde, 0x03])); - t.ok(reader); - t.equal(reader.readInt(), 0x7ede03, 'wrong value'); - t.equal(reader.length, 0x03, 'wrong length'); - t.end(); -}); - - -test('read 4 byte int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01])); - t.ok(reader); - t.equal(reader.readInt(), 0x7ede0301, 'wrong value'); - t.equal(reader.length, 0x04, 'wrong length'); - t.end(); -}); - - -test('read 1 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x01, 0xdc])); - t.ok(reader); - t.equal(reader.readInt(), -36, 'wrong value'); - t.equal(reader.length, 0x01, 'wrong length'); - t.end(); -}); - - -test('read 2 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x02, 0xc0, 0x4e])); - t.ok(reader); - t.equal(reader.readInt(), -16306, 'wrong value'); - t.equal(reader.length, 0x02, 'wrong length'); - t.end(); -}); - - -test('read 3 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x03, 0xff, 0x00, 0x19])); - t.ok(reader); - t.equal(reader.readInt(), -65511, 'wrong value'); - t.equal(reader.length, 0x03, 'wrong length'); - t.end(); -}); - - -test('read 4 byte negative int', function(t) { - var reader = new BerReader(new Buffer([0x02, 0x04, 0x91, 0x7c, 0x22, 0x1f])); - t.ok(reader); - t.equal(reader.readInt(), -1854135777, 'wrong value'); - t.equal(reader.length, 0x04, 'wrong length'); - t.end(); -}); - - -test('read boolean true', function(t) { - var reader = new BerReader(new Buffer([0x01, 0x01, 0xff])); - t.ok(reader); - t.equal(reader.readBoolean(), true, 'wrong value'); - t.equal(reader.length, 0x01, 'wrong length'); - t.end(); -}); - - -test('read boolean false', function(t) { - var reader = new BerReader(new Buffer([0x01, 0x01, 0x00])); - t.ok(reader); - t.equal(reader.readBoolean(), false, 'wrong value'); - t.equal(reader.length, 0x01, 'wrong length'); - t.end(); -}); - - -test('read enumeration', function(t) { - var reader = new BerReader(new Buffer([0x0a, 0x01, 0x20])); - t.ok(reader); - t.equal(reader.readEnumeration(), 0x20, 'wrong value'); - t.equal(reader.length, 0x01, 'wrong length'); - t.end(); -}); - - -test('read string', function(t) { - var dn = 'cn=foo,ou=unit,o=test'; - var buf = new Buffer(dn.length + 2); - buf[0] = 0x04; - buf[1] = Buffer.byteLength(dn); - buf.write(dn, 2); - var reader = new BerReader(buf); - t.ok(reader); - t.equal(reader.readString(), dn, 'wrong value'); - t.equal(reader.length, dn.length, 'wrong length'); - t.end(); -}); - - -test('read sequence', function(t) { - var reader = new BerReader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff])); - t.ok(reader); - t.equal(reader.readSequence(), 0x30, 'wrong value'); - t.equal(reader.length, 0x03, 'wrong length'); - t.equal(reader.readBoolean(), true, 'wrong value'); - t.equal(reader.length, 0x01, 'wrong length'); - t.end(); -}); - - -test('anonymous LDAPv3 bind', function(t) { - var BIND = new Buffer(14); - BIND[0] = 0x30; // Sequence - BIND[1] = 12; // len - BIND[2] = 0x02; // ASN.1 Integer - BIND[3] = 1; // len - BIND[4] = 0x04; // msgid (make up 4) - BIND[5] = 0x60; // Bind Request - BIND[6] = 7; // len - BIND[7] = 0x02; // ASN.1 Integer - BIND[8] = 1; // len - BIND[9] = 0x03; // v3 - BIND[10] = 0x04; // String (bind dn) - BIND[11] = 0; // len - BIND[12] = 0x80; // ContextSpecific (choice) - BIND[13] = 0; // simple bind - - // Start testing ^^ - var ber = new BerReader(BIND); - t.equal(ber.readSequence(), 48, 'Not an ASN.1 Sequence'); - t.equal(ber.length, 12, 'Message length should be 12'); - t.equal(ber.readInt(), 4, 'Message id should have been 4'); - t.equal(ber.readSequence(), 96, 'Bind Request should have been 96'); - t.equal(ber.length, 7, 'Bind length should have been 7'); - t.equal(ber.readInt(), 3, 'LDAP version should have been 3'); - t.equal(ber.readString(), '', 'Bind DN should have been empty'); - t.equal(ber.length, 0, 'string length should have been 0'); - t.equal(ber.readByte(), 0x80, 'Should have been ContextSpecific (choice)'); - t.equal(ber.readByte(), 0, 'Should have been simple bind'); - t.equal(null, ber.readByte(), 'Should be out of data'); - t.end(); -}); - - -test('long string', function(t) { - var buf = new Buffer(256); - var o; - var s = - '2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' + - 'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' + - 'Teena Vradmin\'s description.'; - buf[0] = 0x04; - buf[1] = 0x81; - buf[2] = 0x94; - buf.write(s, 3); - var ber = new BerReader(buf.slice(0, 3 + s.length)); - t.equal(ber.readString(), s); - t.end(); -}); diff --git a/tst/ber/writer.test.js b/tst/ber/writer.test.js deleted file mode 100644 index d87cb7b..0000000 --- a/tst/ber/writer.test.js +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright 2011 Mark Cavage All rights reserved. - -var test = require('tap').test; -var sys = require('sys'); - -///--- Globals - -var BerWriter; - -var BerReader; - - -///--- Tests - -test('load library', function(t) { - BerWriter = require('../../lib/index').BerWriter; - t.ok(BerWriter); - t.ok(new BerWriter()); - t.end(); -}); - - -test('write byte', function(t) { - var writer = new BerWriter(); - - writer.writeByte(0xC2); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 1, 'Wrong length'); - t.equal(ber[0], 0xC2, 'value wrong'); - - t.end(); -}); - - -test('write 1 byte int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(0x7f); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 3, 'Wrong length for an int: ' + ber.length); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong (2) -> ' + ber[0]); - t.equal(ber[1], 0x01, 'length wrong(1) -> ' + ber[1]); - t.equal(ber[2], 0x7f, 'value wrong(3) -> ' + ber[2]); - - t.end(); -}); - - -test('write 2 byte int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(0x7ffe); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 4, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x02, 'length wrong'); - t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); - t.equal(ber[3], 0xfe, 'value wrong (byte 2)'); - - t.end(); -}); - - -test('write 3 byte int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(0x7ffffe); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 5, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x03, 'length wrong'); - t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); - t.equal(ber[3], 0xff, 'value wrong (byte 2)'); - t.equal(ber[4], 0xfe, 'value wrong (byte 3)'); - - t.end(); -}); - - -test('write 4 byte int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(0x7ffffffe); - var ber = writer.buffer; - - t.ok(ber); - - t.equal(ber.length, 6, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x04, 'length wrong'); - t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); - t.equal(ber[3], 0xff, 'value wrong (byte 2)'); - t.equal(ber[4], 0xff, 'value wrong (byte 3)'); - t.equal(ber[5], 0xfe, 'value wrong (byte 4)'); - - t.end(); -}); - - -test('write 1 byte negative int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(-128); - var ber = writer.buffer; - - t.ok(ber); - - t.equal(ber.length, 3, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x01, 'length wrong'); - t.equal(ber[2], 0x80, 'value wrong (byte 1)'); - - t.end(); -}); - - -test('write 2 byte negative int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(-22400); - var ber = writer.buffer; - - t.ok(ber); - - t.equal(ber.length, 4, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x02, 'length wrong'); - t.equal(ber[2], 0xa8, 'value wrong (byte 1)'); - t.equal(ber[3], 0x80, 'value wrong (byte 2)'); - - t.end(); -}); - - -test('write 3 byte negative int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(-481653); - var ber = writer.buffer; - - t.ok(ber); - - t.equal(ber.length, 5, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x03, 'length wrong'); - t.equal(ber[2], 0xf8, 'value wrong (byte 1)'); - t.equal(ber[3], 0xa6, 'value wrong (byte 2)'); - t.equal(ber[4], 0x8b, 'value wrong (byte 3)'); - - t.end(); -}); - - -test('write 4 byte negative int', function(t) { - var writer = new BerWriter(); - - writer.writeInt(-1522904131); - var ber = writer.buffer; - - t.ok(ber); - - t.equal(ber.length, 6, 'Wrong length for an int'); - t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); - t.equal(ber[1], 0x04, 'length wrong'); - t.equal(ber[2], 0xa5, 'value wrong (byte 1)'); - t.equal(ber[3], 0x3a, 'value wrong (byte 2)'); - t.equal(ber[4], 0x53, 'value wrong (byte 3)'); - t.equal(ber[5], 0xbd, 'value wrong (byte 4)'); - - t.end(); -}); - - -test('write boolean', function(t) { - var writer = new BerWriter(); - - writer.writeBoolean(true); - writer.writeBoolean(false); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 6, 'Wrong length'); - t.equal(ber[0], 0x01, 'tag wrong'); - t.equal(ber[1], 0x01, 'length wrong'); - t.equal(ber[2], 0xff, 'value wrong'); - t.equal(ber[3], 0x01, 'tag wrong'); - t.equal(ber[4], 0x01, 'length wrong'); - t.equal(ber[5], 0x00, 'value wrong'); - - t.end(); -}); - - -test('write string', function(t) { - var writer = new BerWriter(); - writer.writeString('hello world'); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 13, 'wrong length'); - t.equal(ber[0], 0x04, 'wrong tag'); - t.equal(ber[1], 11, 'wrong length'); - t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value'); - - t.end(); -}); - -test('write buffer', function(t) { - var writer = new BerWriter(); - // write some stuff to start with - writer.writeString('hello world'); - var ber = writer.buffer; - var buf = new Buffer([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, - 0xff, 0x01, 0x01, 0xff]); - writer.writeBuffer(buf.slice(2, buf.length), 0x04); - ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 26, 'wrong length'); - t.equal(ber[0], 0x04, 'wrong tag'); - t.equal(ber[1], 11, 'wrong length'); - t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value'); - t.equal(ber[13], buf[0], 'wrong tag'); - t.equal(ber[14], buf[1], 'wrong length'); - for (var i = 13, j = 0; i < ber.length && j < buf.length; i++, j++) { - t.equal(ber[i], buf[j], 'buffer contents not identical'); - } - t.end(); -}); - -test('write string array', function(t) { - var writer = new BerWriter(); - writer.writeStringArray(['hello world', 'fubar!']); - var ber = writer.buffer; - - t.ok(ber); - - t.equal(ber.length, 21, 'wrong length'); - t.equal(ber[0], 0x04, 'wrong tag'); - t.equal(ber[1], 11, 'wrong length'); - t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value'); - - t.equal(ber[13], 0x04, 'wrong tag'); - t.equal(ber[14], 6, 'wrong length'); - t.equal(ber.slice(15).toString('utf8'), 'fubar!', 'wrong value'); - - t.end(); -}); - - -test('resize internal buffer', function(t) { - var writer = new BerWriter({size: 2}); - writer.writeString('hello world'); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 13, 'wrong length'); - t.equal(ber[0], 0x04, 'wrong tag'); - t.equal(ber[1], 11, 'wrong length'); - t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value'); - - t.end(); -}); - - -test('sequence', function(t) { - var writer = new BerWriter({size: 25}); - writer.startSequence(); - writer.writeString('hello world'); - writer.endSequence(); - var ber = writer.buffer; - - t.ok(ber); - console.log(ber); - t.equal(ber.length, 15, 'wrong length'); - t.equal(ber[0], 0x30, 'wrong tag'); - t.equal(ber[1], 13, 'wrong length'); - t.equal(ber[2], 0x04, 'wrong tag'); - t.equal(ber[3], 11, 'wrong length'); - t.equal(ber.slice(4).toString('utf8'), 'hello world', 'wrong value'); - - t.end(); -}); - - -test('nested sequence', function(t) { - var writer = new BerWriter({size: 25}); - writer.startSequence(); - writer.writeString('hello world'); - writer.startSequence(); - writer.writeString('hello world'); - writer.endSequence(); - writer.endSequence(); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 30, 'wrong length'); - t.equal(ber[0], 0x30, 'wrong tag'); - t.equal(ber[1], 28, 'wrong length'); - t.equal(ber[2], 0x04, 'wrong tag'); - t.equal(ber[3], 11, 'wrong length'); - t.equal(ber.slice(4, 15).toString('utf8'), 'hello world', 'wrong value'); - t.equal(ber[15], 0x30, 'wrong tag'); - t.equal(ber[16], 13, 'wrong length'); - t.equal(ber[17], 0x04, 'wrong tag'); - t.equal(ber[18], 11, 'wrong length'); - t.equal(ber.slice(19, 30).toString('utf8'), 'hello world', 'wrong value'); - - t.end(); -}); - - -test('LDAP bind message', function(t) { - var dn = 'cn=foo,ou=unit,o=test'; - var writer = new BerWriter(); - writer.startSequence(); - writer.writeInt(3); // msgid = 3 - writer.startSequence(0x60); // ldap bind - writer.writeInt(3); // ldap v3 - writer.writeString(dn); - writer.writeByte(0x80); - writer.writeByte(0x00); - writer.endSequence(); - writer.endSequence(); - var ber = writer.buffer; - - t.ok(ber); - t.equal(ber.length, 35, 'wrong length (buffer)'); - t.equal(ber[0], 0x30, 'wrong tag'); - t.equal(ber[1], 33, 'wrong length'); - t.equal(ber[2], 0x02, 'wrong tag'); - t.equal(ber[3], 1, 'wrong length'); - t.equal(ber[4], 0x03, 'wrong value'); - t.equal(ber[5], 0x60, 'wrong tag'); - t.equal(ber[6], 28, 'wrong length'); - t.equal(ber[7], 0x02, 'wrong tag'); - t.equal(ber[8], 1, 'wrong length'); - t.equal(ber[9], 0x03, 'wrong value'); - t.equal(ber[10], 0x04, 'wrong tag'); - t.equal(ber[11], dn.length, 'wrong length'); - t.equal(ber.slice(12, 33).toString('utf8'), dn, 'wrong value'); - t.equal(ber[33], 0x80, 'wrong tag'); - t.equal(ber[34], 0x00, 'wrong len'); - - t.end(); -}); - - -test('Write OID', function(t) { - var oid = '1.2.840.113549.1.1.1'; - var writer = new BerWriter(); - writer.writeOID(oid); - - var ber = writer.buffer; - t.ok(ber); - console.log(require('util').inspect(ber)); - console.log(require('util').inspect(new Buffer([0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x01]))); - - t.end(); -}); From 1ec9f6c8531492c0ad00f27dcbcfcbecb4b8cb05 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Mon, 20 Jan 2020 15:12:30 +0100 Subject: [PATCH 09/11] Merge with latest version of original setup --- test/ber/reader.test.js | 209 +++++++++++++++++++++++ test/ber/writer.test.js | 369 ++++++++++++++++++++++++++++++++++++++++ test/run.js | 16 ++ 3 files changed, 594 insertions(+) create mode 100644 test/ber/reader.test.js create mode 100644 test/ber/writer.test.js create mode 100644 test/run.js diff --git a/test/ber/reader.test.js b/test/ber/reader.test.js new file mode 100644 index 0000000..95ac5a9 --- /dev/null +++ b/test/ber/reader.test.js @@ -0,0 +1,209 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var test = require('tape'); +var Buffer = require('safer-buffer').Buffer; + + + +// --- Globals + +var BerReader; + + + +// --- Tests + +test('load library', function (t) { + BerReader = require('../../lib/index').BerReader; + t.ok(BerReader); + try { + var reader = new BerReader(); + t.equal(reader, null, 'reader'); + t.fail('Should have thrown'); + } catch (e) { + t.ok(e instanceof TypeError, 'Should have been a type error'); + } + t.end(); +}); + + +test('read byte', function (t) { + var reader = new BerReader(Buffer.from([0xde])); + t.ok(reader); + t.equal(reader.readByte(), 0xde, 'wrong value'); + t.end(); +}); + + +test('read 1 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x01, 0x03])); + t.ok(reader); + t.equal(reader.readInt(), 0x03, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read 2 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x02, 0x7e, 0xde])); + t.ok(reader); + t.equal(reader.readInt(), 0x7ede, 'wrong value'); + t.equal(reader.length, 0x02, 'wrong length'); + t.end(); +}); + + +test('read 3 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x03, 0x7e, 0xde, 0x03])); + t.ok(reader); + t.equal(reader.readInt(), 0x7ede03, 'wrong value'); + t.equal(reader.length, 0x03, 'wrong length'); + t.end(); +}); + + +test('read 4 byte int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01])); + t.ok(reader); + t.equal(reader.readInt(), 0x7ede0301, 'wrong value'); + t.equal(reader.length, 0x04, 'wrong length'); + t.end(); +}); + + +test('read 1 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x01, 0xdc])); + t.ok(reader); + t.equal(reader.readInt(), -36, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read 2 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x02, 0xc0, 0x4e])); + t.ok(reader); + t.equal(reader.readInt(), -16306, 'wrong value'); + t.equal(reader.length, 0x02, 'wrong length'); + t.end(); +}); + + +test('read 3 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x03, 0xff, 0x00, 0x19])); + t.ok(reader); + t.equal(reader.readInt(), -65511, 'wrong value'); + t.equal(reader.length, 0x03, 'wrong length'); + t.end(); +}); + + +test('read 4 byte negative int', function (t) { + var reader = new BerReader(Buffer.from([0x02, 0x04, 0x91, 0x7c, 0x22, 0x1f])); + t.ok(reader); + t.equal(reader.readInt(), -1854135777, 'wrong value'); + t.equal(reader.length, 0x04, 'wrong length'); + t.end(); +}); + + +test('read boolean true', function (t) { + var reader = new BerReader(Buffer.from([0x01, 0x01, 0xff])); + t.ok(reader); + t.equal(reader.readBoolean(), true, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read boolean false', function (t) { + var reader = new BerReader(Buffer.from([0x01, 0x01, 0x00])); + t.ok(reader); + t.equal(reader.readBoolean(), false, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read enumeration', function (t) { + var reader = new BerReader(Buffer.from([0x0a, 0x01, 0x20])); + t.ok(reader); + t.equal(reader.readEnumeration(), 0x20, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('read string', function (t) { + var dn = 'cn=foo,ou=unit,o=test'; + var buf = Buffer.alloc(dn.length + 2); + buf[0] = 0x04; + buf[1] = Buffer.byteLength(dn); + buf.write(dn, 2); + var reader = new BerReader(buf); + t.ok(reader); + t.equal(reader.readString(), dn, 'wrong value'); + t.equal(reader.length, dn.length, 'wrong length'); + t.end(); +}); + + +test('read sequence', function (t) { + var reader = new BerReader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff])); + t.ok(reader); + t.equal(reader.readSequence(), 0x30, 'wrong value'); + t.equal(reader.length, 0x03, 'wrong length'); + t.equal(reader.readBoolean(), true, 'wrong value'); + t.equal(reader.length, 0x01, 'wrong length'); + t.end(); +}); + + +test('anonymous LDAPv3 bind', function (t) { + var BIND = Buffer.alloc(14); + BIND[0] = 0x30; // Sequence + BIND[1] = 12; // len + BIND[2] = 0x02; // ASN.1 Integer + BIND[3] = 1; // len + BIND[4] = 0x04; // msgid (make up 4) + BIND[5] = 0x60; // Bind Request + BIND[6] = 7; // len + BIND[7] = 0x02; // ASN.1 Integer + BIND[8] = 1; // len + BIND[9] = 0x03; // v3 + BIND[10] = 0x04; // String (bind dn) + BIND[11] = 0; // len + BIND[12] = 0x80; // ContextSpecific (choice) + BIND[13] = 0; // simple bind + + // Start testing ^^ + var ber = new BerReader(BIND); + t.equal(ber.readSequence(), 48, 'Not an ASN.1 Sequence'); + t.equal(ber.length, 12, 'Message length should be 12'); + t.equal(ber.readInt(), 4, 'Message id should have been 4'); + t.equal(ber.readSequence(), 96, 'Bind Request should have been 96'); + t.equal(ber.length, 7, 'Bind length should have been 7'); + t.equal(ber.readInt(), 3, 'LDAP version should have been 3'); + t.equal(ber.readString(), '', 'Bind DN should have been empty'); + t.equal(ber.length, 0, 'string length should have been 0'); + t.equal(ber.readByte(), 0x80, 'Should have been ContextSpecific (choice)'); + t.equal(ber.readByte(), 0, 'Should have been simple bind'); + t.equal(null, ber.readByte(), 'Should be out of data'); + t.end(); +}); + + +test('long string', function (t) { + var buf = Buffer.alloc(256); + var s = + '2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' + + 'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' + + 'Teena Vradmin\'s description.'; + buf[0] = 0x04; + buf[1] = 0x81; + buf[2] = 0x94; + buf.write(s, 3); + var ber = new BerReader(buf.slice(0, 3 + s.length)); + t.equal(ber.readString(), s); + t.end(); +}); diff --git a/test/ber/writer.test.js b/test/ber/writer.test.js new file mode 100644 index 0000000..17c4671 --- /dev/null +++ b/test/ber/writer.test.js @@ -0,0 +1,369 @@ +// Copyright 2011 Mark Cavage All rights reserved. + +var test = require('tape'); +var Buffer = require('safer-buffer').Buffer; + +// --- Globals + +var BerWriter; + + + +// --- Tests + +test('load library', function (t) { + BerWriter = require('../../lib/index').BerWriter; + t.ok(BerWriter); + t.ok(new BerWriter()); + t.end(); +}); + + +test('write byte', function (t) { + var writer = new BerWriter(); + + writer.writeByte(0xC2); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 1, 'Wrong length'); + t.equal(ber[0], 0xC2, 'value wrong'); + + t.end(); +}); + + +test('write 1 byte int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(0x7f); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 3, 'Wrong length for an int: ' + ber.length); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong (2) -> ' + ber[0]); + t.equal(ber[1], 0x01, 'length wrong(1) -> ' + ber[1]); + t.equal(ber[2], 0x7f, 'value wrong(3) -> ' + ber[2]); + + t.end(); +}); + + +test('write 2 byte int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(0x7ffe); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 4, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x02, 'length wrong'); + t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); + t.equal(ber[3], 0xfe, 'value wrong (byte 2)'); + + t.end(); +}); + + +test('write 3 byte int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(0x7ffffe); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 5, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x03, 'length wrong'); + t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); + t.equal(ber[3], 0xff, 'value wrong (byte 2)'); + t.equal(ber[4], 0xfe, 'value wrong (byte 3)'); + + t.end(); +}); + + +test('write 4 byte int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(0x7ffffffe); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 6, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x04, 'length wrong'); + t.equal(ber[2], 0x7f, 'value wrong (byte 1)'); + t.equal(ber[3], 0xff, 'value wrong (byte 2)'); + t.equal(ber[4], 0xff, 'value wrong (byte 3)'); + t.equal(ber[5], 0xfe, 'value wrong (byte 4)'); + + t.end(); +}); + + +test('write 1 byte negative int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(-128); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 3, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x01, 'length wrong'); + t.equal(ber[2], 0x80, 'value wrong (byte 1)'); + + t.end(); +}); + + +test('write 2 byte negative int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(-22400); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 4, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x02, 'length wrong'); + t.equal(ber[2], 0xa8, 'value wrong (byte 1)'); + t.equal(ber[3], 0x80, 'value wrong (byte 2)'); + + t.end(); +}); + + +test('write 3 byte negative int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(-481653); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 5, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x03, 'length wrong'); + t.equal(ber[2], 0xf8, 'value wrong (byte 1)'); + t.equal(ber[3], 0xa6, 'value wrong (byte 2)'); + t.equal(ber[4], 0x8b, 'value wrong (byte 3)'); + + t.end(); +}); + + +test('write 4 byte negative int', function (t) { + var writer = new BerWriter(); + + writer.writeInt(-1522904131); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 6, 'Wrong length for an int'); + t.equal(ber[0], 0x02, 'ASN.1 tag wrong'); + t.equal(ber[1], 0x04, 'length wrong'); + t.equal(ber[2], 0xa5, 'value wrong (byte 1)'); + t.equal(ber[3], 0x3a, 'value wrong (byte 2)'); + t.equal(ber[4], 0x53, 'value wrong (byte 3)'); + t.equal(ber[5], 0xbd, 'value wrong (byte 4)'); + + t.end(); +}); + + +test('write boolean', function (t) { + var writer = new BerWriter(); + + writer.writeBoolean(true); + writer.writeBoolean(false); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 6, 'Wrong length'); + t.equal(ber[0], 0x01, 'tag wrong'); + t.equal(ber[1], 0x01, 'length wrong'); + t.equal(ber[2], 0xff, 'value wrong'); + t.equal(ber[3], 0x01, 'tag wrong'); + t.equal(ber[4], 0x01, 'length wrong'); + t.equal(ber[5], 0x00, 'value wrong'); + + t.end(); +}); + + +test('write string', function (t) { + var writer = new BerWriter(); + writer.writeString('hello world'); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 13, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + +test('write buffer', function (t) { + var writer = new BerWriter(); + // write some stuff to start with + writer.writeString('hello world'); + var ber = writer.buffer; + var buf = Buffer.from([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, + 0xff, 0x01, 0x01, 0xff]); + writer.writeBuffer(buf.slice(2, buf.length), 0x04); + ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 26, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value'); + t.equal(ber[13], buf[0], 'wrong tag'); + t.equal(ber[14], buf[1], 'wrong length'); + for (var i = 13, j = 0; i < ber.length && j < buf.length; i++, j++) { + t.equal(ber[i], buf[j], 'buffer contents not identical'); + } + t.end(); +}); + +test('write string array', function (t) { + var writer = new BerWriter(); + writer.writeStringArray(['hello world', 'fubar!']); + var ber = writer.buffer; + + t.ok(ber); + + t.equal(ber.length, 21, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value'); + + t.equal(ber[13], 0x04, 'wrong tag'); + t.equal(ber[14], 6, 'wrong length'); + t.equal(ber.slice(15).toString('utf8'), 'fubar!', 'wrong value'); + + t.end(); +}); + + +test('resize internal buffer', function (t) { + var writer = new BerWriter({size: 2}); + writer.writeString('hello world'); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 13, 'wrong length'); + t.equal(ber[0], 0x04, 'wrong tag'); + t.equal(ber[1], 11, 'wrong length'); + t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + + +test('sequence', function (t) { + var writer = new BerWriter({size: 25}); + writer.startSequence(); + writer.writeString('hello world'); + writer.endSequence(); + var ber = writer.buffer; + + t.ok(ber); + console.log(ber); + t.equal(ber.length, 15, 'wrong length'); + t.equal(ber[0], 0x30, 'wrong tag'); + t.equal(ber[1], 13, 'wrong length'); + t.equal(ber[2], 0x04, 'wrong tag'); + t.equal(ber[3], 11, 'wrong length'); + t.equal(ber.slice(4).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + + +test('nested sequence', function (t) { + var writer = new BerWriter({size: 25}); + writer.startSequence(); + writer.writeString('hello world'); + writer.startSequence(); + writer.writeString('hello world'); + writer.endSequence(); + writer.endSequence(); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 30, 'wrong length'); + t.equal(ber[0], 0x30, 'wrong tag'); + t.equal(ber[1], 28, 'wrong length'); + t.equal(ber[2], 0x04, 'wrong tag'); + t.equal(ber[3], 11, 'wrong length'); + t.equal(ber.slice(4, 15).toString('utf8'), 'hello world', 'wrong value'); + t.equal(ber[15], 0x30, 'wrong tag'); + t.equal(ber[16], 13, 'wrong length'); + t.equal(ber[17], 0x04, 'wrong tag'); + t.equal(ber[18], 11, 'wrong length'); + t.equal(ber.slice(19, 30).toString('utf8'), 'hello world', 'wrong value'); + + t.end(); +}); + + +test('LDAP bind message', function (t) { + var dn = 'cn=foo,ou=unit,o=test'; + var writer = new BerWriter(); + writer.startSequence(); + writer.writeInt(3); // msgid = 3 + writer.startSequence(0x60); // ldap bind + writer.writeInt(3); // ldap v3 + writer.writeString(dn); + writer.writeByte(0x80); + writer.writeByte(0x00); + writer.endSequence(); + writer.endSequence(); + var ber = writer.buffer; + + t.ok(ber); + t.equal(ber.length, 35, 'wrong length (buffer)'); + t.equal(ber[0], 0x30, 'wrong tag'); + t.equal(ber[1], 33, 'wrong length'); + t.equal(ber[2], 0x02, 'wrong tag'); + t.equal(ber[3], 1, 'wrong length'); + t.equal(ber[4], 0x03, 'wrong value'); + t.equal(ber[5], 0x60, 'wrong tag'); + t.equal(ber[6], 28, 'wrong length'); + t.equal(ber[7], 0x02, 'wrong tag'); + t.equal(ber[8], 1, 'wrong length'); + t.equal(ber[9], 0x03, 'wrong value'); + t.equal(ber[10], 0x04, 'wrong tag'); + t.equal(ber[11], dn.length, 'wrong length'); + t.equal(ber.slice(12, 33).toString('utf8'), dn, 'wrong value'); + t.equal(ber[33], 0x80, 'wrong tag'); + t.equal(ber[34], 0x00, 'wrong len'); + + t.end(); +}); + + +test('Write OID', function (t) { + var oid = '1.2.840.113549.1.1.1'; + var writer = new BerWriter(); + writer.writeOID(oid); + + var ber = writer.buffer; + t.ok(ber); + console.log(require('util').inspect(ber)); + console.log(require('util').inspect(Buffer.from([0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01]))); + + t.end(); +}); diff --git a/test/run.js b/test/run.js new file mode 100644 index 0000000..5e7e80e --- /dev/null +++ b/test/run.js @@ -0,0 +1,16 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright (c) 2018, Joyent, Inc. + */ + +'use strict'; + +// --- Run All Tests + +require('./ber/reader.test.js'); +require('./ber/writer.test.js'); From 727c0be5164dfacf69adb62477c6e843def5cd4a Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Wed, 22 Jan 2020 11:53:30 +0100 Subject: [PATCH 10/11] Added ts declaration --- lib/ber/reader.js | 3 +- lib/index.d.ts | 133 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 135 insertions(+), 3 deletions(-) create mode 100755 lib/index.d.ts diff --git a/lib/ber/reader.js b/lib/ber/reader.js index 3cb5853..bb711fb 100755 --- a/lib/ber/reader.js +++ b/lib/ber/reader.js @@ -110,8 +110,7 @@ Reader.prototype.readBlock = function(offset) } currOffset += lenB; if (currOffset > this._size) { - throw new Error(`invalid block at offset ${offset}`); - return null; + throw new Error("invalid block at offset " + offset); } } lenB = currOffset - offset; diff --git a/lib/index.d.ts b/lib/index.d.ts new file mode 100755 index 0000000..6bb7090 --- /dev/null +++ b/lib/index.d.ts @@ -0,0 +1,133 @@ +// Type definitions for asn1 0.2 +// Project: https://github.com/evs-broadcast/node-asn1 +// Definitions by: Gilles Dufour +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 +/// + +export interface WriterOptions { + size: number, + growthFactor: number +} + +export class Reader { + readonly buffer: Buffer; + readonly offset: number; + readonly _blocklevel: number; + readonly _blockInfo: object; + readonly length: number; + readonly remain: number; + readonly _buf: Buffer; + _size: number; + _offset: number; + + constructor(data: Buffer); + + peek(): number | null; + readBlock(offset: number): number; + readBoolean(): boolean; + readByte(peek: boolean): number | null; + readEnumeration(): number; + readInt(): number; + readLength(offset?: number): number; + readOID(tag?: number): string; + readRelativeOID(tag?: number): string; + readSequence(tag?: number): number | null; + readString(tag?: number): string; + readString(tag: number, retbuf: boolean): Buffer; + _readTag(tag?: number): number; +} + +export class Writer { + readonly buffer: Buffer; + readonly _buf: Buffer; + readonly _size: number; + _offset: number; + + constructor(options?: WriterOptions); + + endSequence(): void; + startSequence(tag?: number): void; + writeBoolean(b: boolean, tag?: number): void; + writeBuffer(buf: Buffer, tag: number): void; + writeByte(b: number): void; + writeEnumeration(i: number, tag?: number): void; + writeInt(i: number, tag?: number): void; + writeLength(len: number): void; + writeNull(): void; + writeOID(s: string, tag: number): void; + writeRelativeOID(s: string,tag: number): void; + writeString(s: string, tag?: number): void; + writeStringArray(strings: ReadonlyArray): void; + _ensure(length: number): void; +} + +export namespace Ber { + const BMPString: number; + const BitString: number; + const Boolean: number; + const CharacterString: number; + const Constructor: number; + const Context: number; + const EOC: number; + const Enumeration: number; + const External: number; + const GeneralString: number; + const GeneralizedTime: number; + const GraphicString: number; + const IA5String: number; + const Integer: number; + const Null: number; + const NumericString: number; + const OID: number; + const ObjectDescriptor: number; + const OctetString: number; + const PDV: number; + const PrintableString: number; + const Real: number; + const RelativeOID: number; + const Sequence: number; + const Set: number; + const T61String: number; + const UTCTime: number; + const UniversalString: number; + const Utf8String: number; + const VideotexString: number; + const VisibleString: number; +} +/* +declare enum BerType { + EOC = 0, + Boolean = 1, + Integer = 2, + BitString = 3, + OctetString = 4, + Null = 5, + OID = 6, + ObjectDescriptor = 7, + External = 8, + Real = 9, // float + Enumeration = 10, + PDV = 11, + Utf8String = 12, + RelativeOID = 13, + Sequence = 16, + Set = 17, + NumericString = 18, + PrintableString = 19, + T61String = 20, + VideotexString = 21, + IA5String = 22, + UTCTime = 23, + GeneralizedTime = 24, + GraphicString = 25, + VisibleString = 26, + GeneralString = 28, + UniversalString = 29, + CharacterString = 30, + BMPString = 31, + Constructor = 32, + Context = 128, +} + +*/ diff --git a/package.json b/package.json index f76ce30..9e2a61e 100755 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.5.2", + "version": "0.5.3", "repository": { "type": "git", "url": "git://github.com/mcavage/node-asn1.git" From 0146823069e479e90595480dc90c72cafa161ba1 Mon Sep 17 00:00:00 2001 From: Gilles Dufour Date: Tue, 28 Jan 2020 13:28:59 +0100 Subject: [PATCH 11/11] Add d.ts for typescript support --- lib/index.d.ts | 1 + lib/index.js | 4 ++-- package.json | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) mode change 100644 => 100755 lib/index.js diff --git a/lib/index.d.ts b/lib/index.d.ts index 6bb7090..df9c2a4 100755 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -4,6 +4,7 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.3 /// +import {Buffer} from 'safer-buffer'; export interface WriterOptions { size: number, diff --git a/lib/index.js b/lib/index.js old mode 100644 new mode 100755 index d1766e7..980214a --- a/lib/index.js +++ b/lib/index.js @@ -13,8 +13,8 @@ module.exports = { Ber: Ber, - BerReader: Ber.Reader, + Reader: Ber.Reader, - BerWriter: Ber.Writer + Writer: Ber.Writer }; diff --git a/package.json b/package.json index 9e2a61e..00bb3f3 100755 --- a/package.json +++ b/package.json @@ -8,13 +8,14 @@ ], "name": "asn1", "description": "Contains parsers and serializers for ASN.1 (currently BER only)", - "version": "0.5.3", + "version": "0.5.4", "repository": { "type": "git", "url": "git://github.com/mcavage/node-asn1.git" }, "main": "lib/index.js", "dependencies": { + "@types/safer-buffer": "^2.1.0", "safer-buffer": "~2.1.0" }, "devDependencies": {