From be0fbcdee7c89d541bebd48f52aee84f8e009bd8 Mon Sep 17 00:00:00 2001 From: Martin Holden Date: Wed, 9 Jan 2019 10:59:36 +0000 Subject: [PATCH 1/4] Fixed PasswordDigest Generation The WSSE password digest is best calculated from a byte array of the concat of NONCE, CREATED TIMESTAMP and PASSWORD --- lib/utils.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 19fa8f0f5..dc3a534ad 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -4,8 +4,13 @@ var crypto = require('crypto'); exports.passwordDigest = function passwordDigest(nonce, created, password) { // digest = base64 ( sha1 ( nonce + created + password ) ) var pwHash = crypto.createHash('sha1'); - var rawNonce = new Buffer(nonce || '', 'base64').toString('binary'); - pwHash.update(rawNonce + created + password); + + var NonceBytes = new Buffer(nonce || '', 'base64'); + var CreatedBytes = new Buffer(created || '','utf8'); + var PasswordBytes = new Buffer(password || '', 'utf8'); + var FullBytes = Buffer.concat([NonceBytes, CreatedBytes, PasswordBytes ]); + + pwHash.update(FullBytes); return pwHash.digest('base64'); }; From 2badbe8ef3326e3b9f5316ce5ee5422c64d5ab6c Mon Sep 17 00:00:00 2001 From: Martin Holden Date: Tue, 12 Feb 2019 14:11:34 +0000 Subject: [PATCH 2/4] Added testing for PasswordDigest --- lib/security/WSSecurity.js | 2 ++ test/security/PasswordDigest.js | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/security/PasswordDigest.js diff --git a/lib/security/WSSecurity.js b/lib/security/WSSecurity.js index 4ae1348f3..317c8b883 100644 --- a/lib/security/WSSecurity.js +++ b/lib/security/WSSecurity.js @@ -71,6 +71,8 @@ WSSecurity.prototype.toXML = function() { password += "" + nonce + ""; } } else { + /* Specific Testcase for passwordDigest calculation cover this code + /* istanbul ignore next */ password = "" + passwordDigest(nonce, created, this._password) + "" + "" + nonce + ""; } diff --git a/test/security/PasswordDigest.js b/test/security/PasswordDigest.js new file mode 100644 index 000000000..43ae4c20b --- /dev/null +++ b/test/security/PasswordDigest.js @@ -0,0 +1,22 @@ +'use strict'; + +var Utils = require('../../lib/utils'), + assert = require('assert'); + +describe('PasswordDigest', function () { + + var nonce = "2FW1CIo2ZUOJmSjVRcJZlQ=="; + var created = "2019-02-12T12:34:12.110Z"; + var password = "vM3s1hKVMy6zBOn"; + var expected = "wM9xjA92wCw+QcQI1urjZ6B8+LQ="; + + it('is a function', function () { + Utils.passwordDigest.should.be.type('function'); + }); + + it('should calculate a valid passworddigest ', function () { + + var result = Utils.passwordDigest(nonce, created, password); + assert.equal(result, expected); + }); +}); From bb14b2f89c32190bf26c4d255dde987bfc92797d Mon Sep 17 00:00:00 2001 From: Martin Holden Date: Wed, 13 Feb 2019 16:30:37 +0000 Subject: [PATCH 3/4] Update server-compress-test.js Refactored to ensure the server is running before the test runs --- test/server-compress-test.js | 141 ++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 60 deletions(-) diff --git a/test/server-compress-test.js b/test/server-compress-test.js index 1b1bb6d88..54c7cded3 100644 --- a/test/server-compress-test.js +++ b/test/server-compress-test.js @@ -17,73 +17,94 @@ var request = fs.readFileSync(path + '/request.xml', 'utf8'); var response = fs.readFileSync(path + '/response.xml', 'utf8'); var service = { - MyService: { - MyServicePort: { - DefaultNamespace: function (args) { - return JSON.parse(json); - } - } - } + MyService: { + MyServicePort: { + DefaultNamespace: function (args) { + return JSON.parse(json); + } + } + } }; describe('SOAP Server', function () { - // This test sends two requests and checks the responses for equality. The - // first request is sent through a soap client. The second request sends the - // same request in gzipped format. - it('should properly handle compression', function (done) { - var server = http.createServer(function (req, res) {}); - var clientResponse, gzipResponse; + // This test sends two requests and checks the responses for equality. The + // first request is sent through a soap client. The second request sends the + // same request in gzipped format. + var server = http.createServer(function (req, res) {}); - // If both arguments are defined, check if they are equal and exit the test. - var check = function (a, b) { - if (a && b) { - assert(a === b); - done(); - } - }; + before(function () { + server.listen(8000); + soap.listen(server, '/wsdl', service, xml); + }); + + after(function () { + server.close(); + }); - server.listen(8000); - soap.listen(server, '/wsdl', service, xml); - soap.createClient(wsdl, { - endpoint: 'http://localhost:8000/wsdl' - }, function (error, client) { - assert(!error); - client.DefaultNamespace(json, function (error, response) { - assert(!error); - clientResponse = client.lastResponse; - check(clientResponse, gzipResponse); - }); - }); + it('should properly handle compression', function (done) { + + var clientResponse, + gzipResponse; - var gzip = zlib.createGzip(); + // If both arguments are defined, check if they are equal and exit the test. + var check = function (a, b) { + if (a && b) { + try { + assert(a === b); + done(); + } catch (e) { + done(e); + } + } + }; - // Construct a request with the appropriate headers. - gzip.pipe(http.request({ - host: 'localhost', - path: '/wsdl', - port: 8000, - method: 'POST', - headers: { - 'content-type': 'text/xml; charset=utf-8', - 'content-encoding': 'gzip', - 'soapaction': '"DefaultNamespace"' - } - }, function (res) { - var body = ''; - res.on('data', function (data) { - // Parse the response body. - body += data; - }); - res.on('end', function () { - gzipResponse = body; - check(clientResponse, gzipResponse); - // Don't forget to close the server. - server.close(); - }); - })); + soap.createClient(wsdl, { + endpoint: 'http://localhost:8000/wsdl' + }, function (error, client) { + try { + assert(!error); + } catch (e) { + done(e); + } + client.DefaultNamespace(json, function (error, response) { + try { + assert(!error); + } catch (e) { + done(e); + } + clientResponse = client.lastResponse; + check(clientResponse, gzipResponse); + }); + }); - // Send the request body through the gzip stream to the server. - gzip.end(request); - }); + var gzip = zlib.createGzip(); + + // Construct a request with the appropriate headers. + gzip.pipe(http.request({ + host: 'localhost', + path: '/wsdl', + port: 8000, + method: 'POST', + headers: { + 'content-type': 'text/xml; charset=utf-8', + 'content-encoding': 'gzip', + 'soapaction': '"DefaultNamespace"' + } + }, function (res) { + var body = ''; + res.on('data', function (data) { + // Parse the response body. + body += data; + }); + res.on('end', function () { + gzipResponse = body; + check(clientResponse, gzipResponse); + // Don't forget to close the server. + }); + })); + + // Send the request body through the gzip stream to the server. + gzip.end(request); + }); }); From 75e7f9128975a602c18c454107a1c738e36905cd Mon Sep 17 00:00:00 2001 From: Martin Holden Date: Wed, 13 Feb 2019 17:16:50 +0000 Subject: [PATCH 4/4] Update utils.js Porting to the Buffer.from() --- lib/utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index dc3a534ad..ea2057ad0 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -5,9 +5,9 @@ exports.passwordDigest = function passwordDigest(nonce, created, password) { // digest = base64 ( sha1 ( nonce + created + password ) ) var pwHash = crypto.createHash('sha1'); - var NonceBytes = new Buffer(nonce || '', 'base64'); - var CreatedBytes = new Buffer(created || '','utf8'); - var PasswordBytes = new Buffer(password || '', 'utf8'); + var NonceBytes = Buffer.from(nonce || '', 'base64'); + var CreatedBytes = Buffer.from(created || '','utf8'); + var PasswordBytes = Buffer.from(password || '', 'utf8'); var FullBytes = Buffer.concat([NonceBytes, CreatedBytes, PasswordBytes ]); pwHash.update(FullBytes);