infinispan 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Jenkinsfile-release +1 -1
- package/README.md +31 -907
- package/documentation/asciidoc/stories/assembly_client_usage_examples.adoc +10 -0
- package/documentation/asciidoc/stories/assembly_installation_configuration.adoc +20 -0
- package/documentation/asciidoc/titles/js_client.asciidoc +28 -0
- package/documentation/asciidoc/titles/stories.adoc +5 -0
- package/documentation/asciidoc/topics/attributes/community-attributes.adoc +8 -0
- package/documentation/asciidoc/topics/attributes/downstream-attributes.adoc +2 -0
- package/documentation/asciidoc/topics/code_examples/authentication-digest.js +12 -0
- package/documentation/asciidoc/topics/code_examples/authentication-external.js +15 -0
- package/documentation/asciidoc/topics/code_examples/authentication-oauthbearer.js +10 -0
- package/documentation/asciidoc/topics/code_examples/authentication-plain.js +11 -0
- package/documentation/asciidoc/topics/code_examples/authentication-scram.js +11 -0
- package/documentation/asciidoc/topics/code_examples/await-multiple-entries.js +36 -0
- package/documentation/asciidoc/topics/code_examples/await-single-entries.js +29 -0
- package/documentation/asciidoc/topics/code_examples/conditional-operations.js +57 -0
- package/documentation/asciidoc/topics/code_examples/connection-multiple-servers.js +23 -0
- package/documentation/asciidoc/topics/code_examples/connection-xsite-cluster-switch.js +39 -0
- package/documentation/asciidoc/topics/code_examples/connection-xsite.js +13 -0
- package/documentation/asciidoc/topics/code_examples/data-types.js +30 -0
- package/documentation/asciidoc/topics/code_examples/encryption-crypto-store.js +11 -0
- package/documentation/asciidoc/topics/code_examples/encryption-private-key.js +13 -0
- package/documentation/asciidoc/topics/code_examples/encryption-sni-hostname.js +9 -0
- package/documentation/asciidoc/topics/code_examples/encryption-trust-certs.js +8 -0
- package/documentation/asciidoc/topics/code_examples/ephemeral-data.js +52 -0
- package/documentation/asciidoc/topics/code_examples/hello-world.js +42 -0
- package/documentation/asciidoc/topics/code_examples/key-value-converter.js +67 -0
- package/documentation/asciidoc/topics/code_examples/logging-configuration.js +2 -0
- package/documentation/asciidoc/topics/code_examples/multiple-entries.js +64 -0
- package/documentation/asciidoc/topics/code_examples/register-event-listener.js +64 -0
- package/documentation/asciidoc/topics/code_examples/sample-script-execute.js +33 -0
- package/documentation/asciidoc/topics/code_examples/sample-script.js +3 -0
- package/documentation/asciidoc/topics/code_examples/single-entries.js +49 -0
- package/documentation/asciidoc/topics/config_examples/logging.json +14 -0
- package/documentation/asciidoc/topics/proc_configuring_authentication.adoc +16 -0
- package/documentation/asciidoc/topics/proc_configuring_connections.adoc +25 -0
- package/documentation/asciidoc/topics/proc_configuring_connections_xsite.adoc +18 -0
- package/documentation/asciidoc/topics/proc_configuring_data_formats.adoc +30 -0
- package/documentation/asciidoc/topics/proc_configuring_encryption.adoc +15 -0
- package/documentation/asciidoc/topics/proc_configuring_logging.adoc +28 -0
- package/documentation/asciidoc/topics/proc_installing_clients.adoc +58 -0
- package/documentation/asciidoc/topics/proc_switching_clusters.adoc +17 -0
- package/documentation/asciidoc/topics/ref_authentication_mechanisms.adoc +68 -0
- package/documentation/asciidoc/topics/ref_client_usage.adoc +116 -0
- package/documentation/asciidoc/topics/ref_encryption.adoc +71 -0
- package/lib/codec.js +153 -2
- package/lib/infinispan.js +33 -1
- package/lib/io.js +23 -16
- package/lib/protocols.js +165 -68
- package/lib/protostream/message-wrapping.proto +134 -0
- package/lib/protostream/query.proto +122 -0
- package/lib/sasl/bitops.js +24 -0
- package/lib/sasl/digest.js +188 -0
- package/lib/sasl/external.js +54 -0
- package/lib/sasl/factory.js +71 -0
- package/lib/sasl/oauthbearer.js +63 -0
- package/lib/sasl/plain.js +65 -0
- package/lib/sasl/scram.js +135 -0
- package/lib/utils.js +1 -1
- package/memory-profiling/helper.js +9 -0
- package/memory-profiling/infinispan_memory_many_get.js +1 -3
- package/memory-profiling/infinispan_memory_one_get.js +6 -4
- package/package.json +7 -13
- package/run-servers.sh +17 -8
- package/run-testsuite.sh +1 -1
- package/smoke-tests.sh +8 -2
- package/spec/codec_spec.js +7 -7
- package/spec/configs/infinispan-clustered.xml +17 -14
- package/spec/configs/infinispan-ssl.xml +25 -22
- package/spec/configs/infinispan-xsite-EARTH.xml +17 -14
- package/spec/configs/infinispan-xsite-MOON.xml +14 -11
- package/spec/configs/infinispan.xml +22 -13
- package/spec/infinispan_auth_spec.js +16 -37
- package/spec/protostream_spec.js +237 -0
- package/spec/utils/testing.js +1 -3
- package/lib/bitops.js +0 -26
- package/lib/scram.js +0 -116
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof exports === 'object') {
|
|
3
|
+
// CommonJS
|
|
4
|
+
factory(exports, module, require('crypto'));
|
|
5
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
6
|
+
// AMD
|
|
7
|
+
define(['exports', 'module', 'crypto'], factory);
|
|
8
|
+
}
|
|
9
|
+
}(this, function (exports, module, crypto) {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* DIGEST `Mechanism` constructor.
|
|
13
|
+
*
|
|
14
|
+
* This class implements the DIGEST-* SASL mechanism.
|
|
15
|
+
*
|
|
16
|
+
* References:
|
|
17
|
+
* - [RFC 2831](http://tools.ietf.org/html/rfc2831)
|
|
18
|
+
*
|
|
19
|
+
* @api public
|
|
20
|
+
*/
|
|
21
|
+
function Mechanism(options) {
|
|
22
|
+
options = options || {};
|
|
23
|
+
this._genNonce = options.genNonce || genNonce(32);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Mechanism.prototype.name = 'DIGEST';
|
|
27
|
+
Mechanism.prototype.clientFirst = false;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Encode a response using given credential.
|
|
31
|
+
*
|
|
32
|
+
* Options:
|
|
33
|
+
* - `username`
|
|
34
|
+
* - `password`
|
|
35
|
+
* - `host`
|
|
36
|
+
* - `serviceType`
|
|
37
|
+
* - `authzid` authorization identity (optional)
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} cred
|
|
40
|
+
* @api public
|
|
41
|
+
*/
|
|
42
|
+
Mechanism.prototype.response = function (cred) {
|
|
43
|
+
// TODO: Implement support for subsequent authentication. This requires
|
|
44
|
+
// that the client be able to store username, realm, nonce,
|
|
45
|
+
// nonce-count, cnonce, and qop values from prior authentication.
|
|
46
|
+
// The impact of this requirement needs to be investigated.
|
|
47
|
+
//
|
|
48
|
+
// See RFC 2831 (Section 2.2) for further details.
|
|
49
|
+
|
|
50
|
+
// TODO: Implement support for auth-int and auth-conf, as defined in RFC
|
|
51
|
+
// 2831 sections 2.3 Integrity Protection and 2.4 Confidentiality
|
|
52
|
+
// Protection, respectively.
|
|
53
|
+
//
|
|
54
|
+
// Note that supporting this functionality has implications
|
|
55
|
+
// regarding the negotiation of security layers via SASL. Due to
|
|
56
|
+
// the fact that TLS has largely superseded this functionality,
|
|
57
|
+
// implementing it is a low priority.
|
|
58
|
+
|
|
59
|
+
var uri = cred.serviceType + '/' + cred.host;
|
|
60
|
+
if (cred.serviceName && cred.host !== cred.serviceName) {
|
|
61
|
+
uri += '/' + serviceName;
|
|
62
|
+
}
|
|
63
|
+
var realm = cred.realm || this._realm || ''
|
|
64
|
+
, cnonce = this._genNonce()
|
|
65
|
+
, nc = '00000001'
|
|
66
|
+
, qop = 'auth'
|
|
67
|
+
, ha1
|
|
68
|
+
, ha2
|
|
69
|
+
, digest;
|
|
70
|
+
var str = '';
|
|
71
|
+
str += 'username="' + cred.username + '"';
|
|
72
|
+
if (realm) { str += ',realm="' + realm + '"'; };
|
|
73
|
+
str += ',nonce="' + this._nonce + '"';
|
|
74
|
+
str += ',cnonce="' + cnonce + '"';
|
|
75
|
+
str += ',nc=' + nc;
|
|
76
|
+
str += ',qop=' + qop;
|
|
77
|
+
str += ',digest-uri="' + uri + '"';
|
|
78
|
+
var base = crypto.createHash('md5')
|
|
79
|
+
.update(cred.username)
|
|
80
|
+
.update(':')
|
|
81
|
+
.update(realm)
|
|
82
|
+
.update(':')
|
|
83
|
+
.update(cred.password)
|
|
84
|
+
.digest();
|
|
85
|
+
ha1 = crypto.createHash('md5')
|
|
86
|
+
.update(base)
|
|
87
|
+
.update(':')
|
|
88
|
+
.update(this._nonce)
|
|
89
|
+
.update(':')
|
|
90
|
+
.update(cnonce);
|
|
91
|
+
if (cred.authzid) {
|
|
92
|
+
ha1.update(':').update(cred.authzid);
|
|
93
|
+
}
|
|
94
|
+
ha1 = ha1.digest('hex');
|
|
95
|
+
ha2 = crypto.createHash('md5')
|
|
96
|
+
.update('AUTHENTICATE:')
|
|
97
|
+
.update(uri);
|
|
98
|
+
if (qop === 'auth-int' || qop === 'auth-conf') {
|
|
99
|
+
ha2.update(':00000000000000000000000000000000');
|
|
100
|
+
}
|
|
101
|
+
ha2 = ha2.digest('hex');
|
|
102
|
+
digest = crypto.createHash('md5')
|
|
103
|
+
.update(ha1)
|
|
104
|
+
.update(':')
|
|
105
|
+
.update(this._nonce)
|
|
106
|
+
.update(':')
|
|
107
|
+
.update(nc)
|
|
108
|
+
.update(':')
|
|
109
|
+
.update(cnonce)
|
|
110
|
+
.update(':')
|
|
111
|
+
.update(qop)
|
|
112
|
+
.update(':')
|
|
113
|
+
.update(ha2)
|
|
114
|
+
.digest('hex');
|
|
115
|
+
str += ',response=' + digest;
|
|
116
|
+
if (this._charset == 'utf-8') { str += ',charset=utf-8'; }
|
|
117
|
+
if (cred.authzid) { str += 'authzid="' + cred.authzid + '"'; }
|
|
118
|
+
return str;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Decode a challenge issued by the server.
|
|
123
|
+
*
|
|
124
|
+
* @param {String} chal
|
|
125
|
+
* @return {Mechanism} for chaining
|
|
126
|
+
* @api public
|
|
127
|
+
*/
|
|
128
|
+
Mechanism.prototype.challenge = function (chal) {
|
|
129
|
+
var dtives = parse(chal);
|
|
130
|
+
|
|
131
|
+
// TODO: Implement support for multiple realm directives, as allowed by the
|
|
132
|
+
// DIGEST-MD5 specification.
|
|
133
|
+
this._realm = dtives['realm'];
|
|
134
|
+
this._nonce = dtives['nonce'];
|
|
135
|
+
this._qop = (dtives['qop'] || 'auth').split(',');
|
|
136
|
+
this._stale = dtives['stale'];
|
|
137
|
+
this._maxbuf = parseInt(dtives['maxbuf']) || 65536;
|
|
138
|
+
this._charset = dtives['charset'];
|
|
139
|
+
this._algo = dtives['algorithm'];
|
|
140
|
+
this._cipher = dtives['cipher'];
|
|
141
|
+
if (this._cipher) { this._cipher.split(','); }
|
|
142
|
+
return this;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Parse challenge.
|
|
148
|
+
*
|
|
149
|
+
* @api private
|
|
150
|
+
*/
|
|
151
|
+
function parse(chal) {
|
|
152
|
+
var dtives = {};
|
|
153
|
+
var tokens = chal.split(/,(?=(?:[^"]|"[^"]*")*$)/);
|
|
154
|
+
for (var i = 0, len = tokens.length; i < len; i++) {
|
|
155
|
+
var dtiv = /(\w+)=["]?([^"]+)["]?$/.exec(tokens[i]);
|
|
156
|
+
if (dtiv) {
|
|
157
|
+
dtives[dtiv[1]] = dtiv[2];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return dtives;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Return a unique nonce with the given `len`.
|
|
165
|
+
*
|
|
166
|
+
* genNonce(10)();
|
|
167
|
+
* // => "FDaS435D2z"
|
|
168
|
+
*
|
|
169
|
+
* @param {Number} len
|
|
170
|
+
* @return {Function}
|
|
171
|
+
* @api private
|
|
172
|
+
*/
|
|
173
|
+
function genNonce(len) {
|
|
174
|
+
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
175
|
+
, charlen = chars.length;
|
|
176
|
+
|
|
177
|
+
return function () {
|
|
178
|
+
var buf = [];
|
|
179
|
+
for (var i = 0; i < len; ++i) {
|
|
180
|
+
buf.push(chars[Math.random() * charlen | 0]);
|
|
181
|
+
}
|
|
182
|
+
return buf.join('');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
exports = module.exports = Mechanism;
|
|
187
|
+
|
|
188
|
+
}));
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof exports === 'object') {
|
|
3
|
+
// CommonJS
|
|
4
|
+
factory(exports, module);
|
|
5
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
6
|
+
// AMD
|
|
7
|
+
define(['exports', 'module'], factory);
|
|
8
|
+
}
|
|
9
|
+
}(this, function (exports, module) {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* EXTERNAL `Mechanism` constructor.
|
|
13
|
+
*
|
|
14
|
+
* This class implements the EXTERNAL SASL mechanism.
|
|
15
|
+
*
|
|
16
|
+
* The EXTERNAL SASL mechanism provides support for authentication using
|
|
17
|
+
* credentials established by external means.
|
|
18
|
+
*
|
|
19
|
+
* References:
|
|
20
|
+
* - [RFC 4422](http://tools.ietf.org/html/rfc4422)
|
|
21
|
+
*
|
|
22
|
+
* @api public
|
|
23
|
+
*/
|
|
24
|
+
function Mechanism() {
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Mechanism.prototype.name = 'EXTERNAL';
|
|
28
|
+
Mechanism.prototype.clientFirst = true;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Encode a response using given credential.
|
|
32
|
+
*
|
|
33
|
+
* Options:
|
|
34
|
+
* - `authzid` authorization identity (optional)
|
|
35
|
+
*
|
|
36
|
+
* @param {Object} cred
|
|
37
|
+
* @api public
|
|
38
|
+
*/
|
|
39
|
+
Mechanism.prototype.response = function (cred) {
|
|
40
|
+
return cred.authzid || '';
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Decode a challenge issued by the server.
|
|
45
|
+
*
|
|
46
|
+
* @param {String} chal
|
|
47
|
+
* @api public
|
|
48
|
+
*/
|
|
49
|
+
Mechanism.prototype.challenge = function (chal) {
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
exports = module.exports = Mechanism;
|
|
53
|
+
|
|
54
|
+
}));
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
(function(root, factory) {
|
|
2
|
+
if (typeof exports === 'object') {
|
|
3
|
+
// CommonJS
|
|
4
|
+
factory(exports, module);
|
|
5
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
6
|
+
// AMD
|
|
7
|
+
define(['exports', 'module'], factory);
|
|
8
|
+
}
|
|
9
|
+
}(this, function(exports, module) {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `Factory` constructor.
|
|
13
|
+
*
|
|
14
|
+
* @api public
|
|
15
|
+
*/
|
|
16
|
+
function Factory() {
|
|
17
|
+
this._mechs = [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Utilize the given `mech` with optional `name`, overridding the mechanism's
|
|
22
|
+
* default name.
|
|
23
|
+
*
|
|
24
|
+
* Examples:
|
|
25
|
+
*
|
|
26
|
+
* factory.use(FooMechanism);
|
|
27
|
+
*
|
|
28
|
+
* factory.use('XFOO', FooMechanism);
|
|
29
|
+
*
|
|
30
|
+
* @param {String|Mechanism} name
|
|
31
|
+
* @param {Mechanism} mech
|
|
32
|
+
* @return {Factory} for chaining
|
|
33
|
+
* @api public
|
|
34
|
+
*/
|
|
35
|
+
Factory.prototype.use = function(name, mech) {
|
|
36
|
+
if (!mech) {
|
|
37
|
+
mech = name;
|
|
38
|
+
name = mech.prototype.name;
|
|
39
|
+
}
|
|
40
|
+
this._mechs.push({ name: name, mech: mech });
|
|
41
|
+
return this;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create a new mechanism from supported list of `mechs`.
|
|
46
|
+
*
|
|
47
|
+
* If no mechanisms are supported, returns `null`.
|
|
48
|
+
*
|
|
49
|
+
* Examples:
|
|
50
|
+
*
|
|
51
|
+
* var mech = factory.create(['FOO', 'BAR']);
|
|
52
|
+
*
|
|
53
|
+
* @param {Array} mechs
|
|
54
|
+
* @return {Mechanism}
|
|
55
|
+
* @api public
|
|
56
|
+
*/
|
|
57
|
+
Factory.prototype.create = function(mechs) {
|
|
58
|
+
for (var i = 0, len = this._mechs.length; i < len; i++) {
|
|
59
|
+
for (var j = 0, jlen = mechs.length; j < jlen; j++) {
|
|
60
|
+
var entry = this._mechs[i];
|
|
61
|
+
if (entry.name == mechs[j]) {
|
|
62
|
+
return new entry.mech();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
exports = module.exports = Factory;
|
|
70
|
+
|
|
71
|
+
}));
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof exports === 'object') {
|
|
3
|
+
// CommonJS
|
|
4
|
+
factory(exports, module);
|
|
5
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
6
|
+
// AMD
|
|
7
|
+
define(['exports', 'module'], factory);
|
|
8
|
+
}
|
|
9
|
+
}(this, function (exports, module) {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* OAUTHBEARER `Mechanism` constructor.
|
|
13
|
+
*
|
|
14
|
+
* This class implements the OAUTHBEARER SASL mechanism.
|
|
15
|
+
*
|
|
16
|
+
* The OAUTHBEARER SASL mechanism provides support for exchanging a token obtained via OAuth with the server.
|
|
17
|
+
*
|
|
18
|
+
* References:
|
|
19
|
+
* - [RFC 4616](http://tools.ietf.org/html/rfc4616)
|
|
20
|
+
*
|
|
21
|
+
* @api public
|
|
22
|
+
*/
|
|
23
|
+
function Mechanism() {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Mechanism.prototype.name = 'OAUTHBEARER';
|
|
27
|
+
Mechanism.prototype.clientFirst = true;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Encode a response using given credential.
|
|
31
|
+
*
|
|
32
|
+
* Options:
|
|
33
|
+
* - `token` an OAuth token
|
|
34
|
+
* - `authzid` authorization identity (optional)
|
|
35
|
+
*
|
|
36
|
+
* @param {Object} cred
|
|
37
|
+
* @api public
|
|
38
|
+
*/
|
|
39
|
+
Mechanism.prototype.response = function (cred) {
|
|
40
|
+
var str = 'n,';
|
|
41
|
+
if (cred.authzid) {
|
|
42
|
+
str += 'a=' + cred.authzid;
|
|
43
|
+
}
|
|
44
|
+
str += ',%x01,auth=Bearer ';
|
|
45
|
+
str += cred.token;
|
|
46
|
+
str += '%x01';
|
|
47
|
+
return str;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Decode a challenge issued by the server.
|
|
52
|
+
*
|
|
53
|
+
* @param {String} chal
|
|
54
|
+
* @return {Mechanism} for chaining
|
|
55
|
+
* @api public
|
|
56
|
+
*/
|
|
57
|
+
Mechanism.prototype.challenge = function (chal) {
|
|
58
|
+
return this;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
exports = module.exports = Mechanism;
|
|
62
|
+
|
|
63
|
+
}));
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof exports === 'object') {
|
|
3
|
+
// CommonJS
|
|
4
|
+
factory(exports, module);
|
|
5
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
6
|
+
// AMD
|
|
7
|
+
define(['exports', 'module'], factory);
|
|
8
|
+
}
|
|
9
|
+
}(this, function (exports, module) {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* PLAIN `Mechanism` constructor.
|
|
13
|
+
*
|
|
14
|
+
* This class implements the PLAIN SASL mechanism.
|
|
15
|
+
*
|
|
16
|
+
* The PLAIN SASL mechanism provides support for exchanging a clear-text
|
|
17
|
+
* username and password. This mechanism should not be used without adequate
|
|
18
|
+
* security provided by an underlying transport layer.
|
|
19
|
+
*
|
|
20
|
+
* References:
|
|
21
|
+
* - [RFC 4616](http://tools.ietf.org/html/rfc4616)
|
|
22
|
+
*
|
|
23
|
+
* @api public
|
|
24
|
+
*/
|
|
25
|
+
function Mechanism() {
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Mechanism.prototype.name = 'PLAIN';
|
|
29
|
+
Mechanism.prototype.clientFirst = true;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Encode a response using given credential.
|
|
33
|
+
*
|
|
34
|
+
* Options:
|
|
35
|
+
* - `username`
|
|
36
|
+
* - `password`
|
|
37
|
+
* - `authzid` authorization identity (optional)
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} cred
|
|
40
|
+
* @api public
|
|
41
|
+
*/
|
|
42
|
+
Mechanism.prototype.response = function (cred) {
|
|
43
|
+
var str = '';
|
|
44
|
+
str += cred.authzid || '';
|
|
45
|
+
str += '\0';
|
|
46
|
+
str += cred.username;
|
|
47
|
+
str += '\0';
|
|
48
|
+
str += cred.password;
|
|
49
|
+
return str;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Decode a challenge issued by the server.
|
|
54
|
+
*
|
|
55
|
+
* @param {String} chal
|
|
56
|
+
* @return {Mechanism} for chaining
|
|
57
|
+
* @api public
|
|
58
|
+
*/
|
|
59
|
+
Mechanism.prototype.challenge = function (chal) {
|
|
60
|
+
return this;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
exports = module.exports = Mechanism;
|
|
64
|
+
|
|
65
|
+
}));
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof exports === 'object') {
|
|
3
|
+
// CommonJS
|
|
4
|
+
factory(exports, module, require('./bitops'), require('../utils'));
|
|
5
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
6
|
+
// AMD
|
|
7
|
+
define(['exports', 'module', 'bitops', 'utils'], factory);
|
|
8
|
+
}
|
|
9
|
+
}(this, function (exports, module, bitops, utils) {
|
|
10
|
+
var RESP = {};
|
|
11
|
+
var CLIENT_KEY = 'Client Key';
|
|
12
|
+
var SERVER_KEY = 'Server Key';
|
|
13
|
+
|
|
14
|
+
function Mechanism(options) {
|
|
15
|
+
options = options || {};
|
|
16
|
+
this._genNonce = options.genNonce || utils.genNonce;
|
|
17
|
+
this._stage = 'one';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Conform to the SASL lib's expectations
|
|
21
|
+
Mechanism.Mechanism = Mechanism;
|
|
22
|
+
Mechanism.prototype.name = 'SCRAM';
|
|
23
|
+
Mechanism.prototype.clientFirst = true;
|
|
24
|
+
|
|
25
|
+
Mechanism.prototype.response = function (cred) {
|
|
26
|
+
return RESP[this._stage](this, cred);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
Mechanism.prototype.challenge = function (chal) {
|
|
30
|
+
var values = parse(chal);
|
|
31
|
+
this._salt = Buffer.from(values.s, 'base64');
|
|
32
|
+
this._iterationCount = parseInt(values.i, 10);
|
|
33
|
+
this._nonce = values.r;
|
|
34
|
+
this._verifier = values.v;
|
|
35
|
+
this._error = values.e;
|
|
36
|
+
this._challenge = chal;
|
|
37
|
+
return this;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parse challenge.
|
|
42
|
+
*
|
|
43
|
+
* @api private
|
|
44
|
+
*/
|
|
45
|
+
function parse(chal) {
|
|
46
|
+
var dtives = {};
|
|
47
|
+
var tokens = chal.split(/,(?=(?:[^"]|"[^"]*")*$)/);
|
|
48
|
+
for (var i = 0, len = tokens.length; i < len; i++) {
|
|
49
|
+
var dtiv = /(\w+)=["]?(.+)["]?$/.exec(tokens[i]);
|
|
50
|
+
if (dtiv) {
|
|
51
|
+
dtives[dtiv[1]] = dtiv[2];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return dtives;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
RESP.one = function (mech, cred) {
|
|
59
|
+
mech._cnonce = mech._genNonce();
|
|
60
|
+
|
|
61
|
+
var authzid = '';
|
|
62
|
+
if (cred.authzid) {
|
|
63
|
+
authzid = 'a=' + utils.saslname(cred.authzid);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
mech._gs2Header = 'n,' + authzid + ',';
|
|
67
|
+
|
|
68
|
+
var nonce = 'r=' + mech._cnonce;
|
|
69
|
+
var username = 'n=' + utils.saslname(cred.username || '');
|
|
70
|
+
|
|
71
|
+
mech._clientFirstMessageBare = username + ',' + nonce;
|
|
72
|
+
var result = mech._gs2Header + mech._clientFirstMessageBare;
|
|
73
|
+
|
|
74
|
+
mech._stage = 'two';
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
RESP.two = function (mech, cred) {
|
|
81
|
+
var gs2Header = Buffer.from(mech._gs2Header).toString('base64');
|
|
82
|
+
mech._clientFinalMessageWithoutProof = 'c=' + gs2Header + ',r=' + mech._nonce;
|
|
83
|
+
|
|
84
|
+
var saltedPassword, clientKey, serverKey;
|
|
85
|
+
|
|
86
|
+
var algorithm = cred.mechanism.substring(6).toLowerCase().replace("-", "");
|
|
87
|
+
|
|
88
|
+
// If our cached salt is the same, we can reuse cached credentials to speed
|
|
89
|
+
// up the hashing process.
|
|
90
|
+
if (cred.salt && Buffer.compare(cred.salt, mech._salt) === 0) {
|
|
91
|
+
if (cred.clientKey && cred.serverKey) {
|
|
92
|
+
clientKey = cred.clientKey;
|
|
93
|
+
serverKey = cred.serverKey;
|
|
94
|
+
} else if (cred.saltedPassword) {
|
|
95
|
+
saltedPassword = cred.saltedPassword;
|
|
96
|
+
clientKey = bitops.HMAC(algorithm, saltedPassword, CLIENT_KEY);
|
|
97
|
+
serverKey = bitops.HMAC(algorithm, saltedPassword, SERVER_KEY);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
saltedPassword = bitops.Hi(algorithm, cred.password || '', mech._salt, mech._iterationCount);
|
|
101
|
+
clientKey = bitops.HMAC(algorithm, saltedPassword, CLIENT_KEY);
|
|
102
|
+
serverKey = bitops.HMAC(algorithm, saltedPassword, SERVER_KEY);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
var storedKey = bitops.H(algorithm, clientKey);
|
|
106
|
+
var authMessage = mech._clientFirstMessageBare + ',' +
|
|
107
|
+
mech._challenge + ',' +
|
|
108
|
+
mech._clientFinalMessageWithoutProof;
|
|
109
|
+
var clientSignature = bitops.HMAC(algorithm, storedKey, authMessage);
|
|
110
|
+
|
|
111
|
+
var clientProof = bitops.XOR(clientKey, clientSignature).toString('base64');
|
|
112
|
+
|
|
113
|
+
mech._serverSignature = bitops.HMAC(algorithm, serverKey, authMessage);
|
|
114
|
+
|
|
115
|
+
var result = mech._clientFinalMessageWithoutProof + ',p=' + clientProof;
|
|
116
|
+
|
|
117
|
+
mech._stage = 'final';
|
|
118
|
+
|
|
119
|
+
mech.cache = {
|
|
120
|
+
salt: mech._salt,
|
|
121
|
+
saltedPassword: saltedPassword,
|
|
122
|
+
clientKey: clientKey,
|
|
123
|
+
serverKey: serverKey
|
|
124
|
+
};
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
RESP.final = function () {
|
|
129
|
+
return '';
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
exports = module.exports = Mechanism;
|
|
134
|
+
|
|
135
|
+
}));
|
package/lib/utils.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const v8 = require('v8');
|
|
3
|
+
|
|
4
|
+
exports.createHeapSnapshot = function() {
|
|
5
|
+
const snapshotStream = v8.getHeapSnapshot();
|
|
6
|
+
const fileName = `${Date.now()}.heapsnapshot`;
|
|
7
|
+
const fileStream = fs.createWriteStream('/tmp/' + fileName);
|
|
8
|
+
snapshotStream.pipe(fileStream);
|
|
9
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var _ = require('underscore');
|
|
2
2
|
var infinispan = require('../lib/infinispan');
|
|
3
|
-
|
|
4
|
-
var heapdump = require('heapdump');
|
|
3
|
+
var helper = require('./helper');
|
|
5
4
|
|
|
6
5
|
var connected = infinispan.client({port: 11222, host: '127.0.0.1'},{cacheName: 'namedCache'});
|
|
7
6
|
console.log("Connected to JDG server");
|
|
@@ -12,7 +11,6 @@ connected.then(function (client) {
|
|
|
12
11
|
|
|
13
12
|
return put.then(function() {
|
|
14
13
|
var heapUseAfterPut = process.memoryUsage().heapUsed;
|
|
15
|
-
//heapdump.writeSnapshot('/tmp/' + Date.now() + '.heapsnapshot');
|
|
16
14
|
|
|
17
15
|
var temp = [];
|
|
18
16
|
var numOps = 10000; // 500000
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
var _ = require('underscore');
|
|
2
2
|
var infinispan = require('../lib/infinispan');
|
|
3
|
+
var helper = require('./helper');
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const v8 = require('v8');
|
|
5
7
|
|
|
6
8
|
var connected = infinispan.client({port: 11222, host: '127.0.0.1'},{cacheName: 'namedCache'});
|
|
7
9
|
console.log("Connected to JDG server");
|
|
@@ -12,7 +14,7 @@ connected.then(function (client) {
|
|
|
12
14
|
var afterPut = put.then(function() {
|
|
13
15
|
//console.log("After put, heapUsed: "+process.memoryUsage().heapUsed);
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
helper.createHeapSnapshot();
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
var get1 = afterPut.then(function test_get1() {
|
|
@@ -27,7 +29,7 @@ connected.then(function (client) {
|
|
|
27
29
|
global.gc();
|
|
28
30
|
//console.log("After get1, heapUsed: "+process.memoryUsage().heapUsed);
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
helper.createHeapSnapshot();
|
|
31
33
|
});
|
|
32
34
|
|
|
33
35
|
var get2 = dumpAfterGet1.then(function test_get2() {
|
|
@@ -42,7 +44,7 @@ connected.then(function (client) {
|
|
|
42
44
|
global.gc();
|
|
43
45
|
//console.log("After get2, heapUsed: "+process.memoryUsage().heapUsed);
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
helper.createHeapSnapshot();
|
|
46
48
|
});
|
|
47
49
|
|
|
48
50
|
return dumpAfterGet2.then(function test_disconnect() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infinispan",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Infinispan Javascript client",
|
|
5
5
|
"main": "index",
|
|
6
6
|
"directories": {
|
|
@@ -25,21 +25,15 @@
|
|
|
25
25
|
"url": "https://github.com/infinispan/js-client"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"promise.prototype.finally": "^3.1.0",
|
|
33
|
-
"randombytes": "^2.0.1",
|
|
34
|
-
"sasl-digest-md5": "^0.1.0",
|
|
35
|
-
"saslmechanisms": "^0.1.1",
|
|
36
|
-
"underscore": "^1.9.1"
|
|
28
|
+
"buffer-xor": "^2.0.2",
|
|
29
|
+
"log4js": "^6.4.6",
|
|
30
|
+
"protobufjs": "^7.0.0",
|
|
31
|
+
"underscore": "^1.13.3"
|
|
37
32
|
},
|
|
38
33
|
"devDependencies": {
|
|
39
34
|
"growl": "^1.10.5",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"jsdoc": "^3.6.6",
|
|
35
|
+
"jasmine-node": "^3.0.0",
|
|
36
|
+
"jsdoc": "^3.6.10",
|
|
43
37
|
"request": "^2.88.0"
|
|
44
38
|
}
|
|
45
39
|
}
|