Skip to content

Commit

Permalink
Set noImplicityAny to true and fix type annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
jcbrand committed Jul 15, 2023
1 parent 8b1d44e commit 35bc231
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 79 deletions.
17 changes: 12 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"xhr2": "^0.2.1"
},
"dependencies": {
"@types/ws": "^8.5.5",
"abab": "^2.0.3"
},
"optionalDependencies": {
Expand Down
30 changes: 24 additions & 6 deletions src/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ import { SessionError } from './errors.js';
* @memberof Strophe
*/
class Connection {
/**
* @typedef {Object.<string, string>} Cookie
* @typedef {Cookie|Object.<string, Cookie>} Cookies
*/

/**
* @typedef {Object} ConnectionOptions
* @property {Object} [cookies]
* @property {Cookies} [cookies]
* Allows you to pass in cookies that will be included in HTTP requests.
* Relevant to both the BOSH and Websocket transports.
*
Expand Down Expand Up @@ -286,7 +291,9 @@ class Connection {
if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) {
const F = function () {};
F.prototype = Strophe._connectionPlugins[k];
// @ts-ignore
this[k] = new F();
// @ts-ignore
this[k].init(this);
}
}
Expand Down Expand Up @@ -421,6 +428,15 @@ class Connection {
this.protocolErrorHandlers[protocol][status_code] = callback;
}

/**
* @typedef {Object} Password
* @property {string} Password.name
* @property {string} Password.ck
* @property {string} Password.sk
* @property {number} Password.iter
* @property {string} Password.salt
*/

/**
* Starts the connection process.
*
Expand Down Expand Up @@ -449,7 +465,7 @@ class Connection {
* ck: String, the base64 encoding of the SCRAM client key
* sk: String, the base64 encoding of the SCRAM server key
* }
* @param {string|Object} pass - The user password
* @param {string|Password} pass - The user password
* @param {Function} callback - The connect callback function.
* @param {number} wait - The optional HTTPBIND wait value. This is the
* time the server will wait before returning an empty result for
Expand Down Expand Up @@ -1100,6 +1116,7 @@ class Connection {
// notify all plugins listening for status changes
for (const k in Strophe._connectionPlugins) {
if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) {
// @ts-ignore
const plugin = this[k];
if (plugin.statusChanged) {
try {
Expand Down Expand Up @@ -1506,20 +1523,21 @@ class Connection {
* sends it, creating a handler (calling back to _auth2_cb()) to
* handle the result
* @private
*
* @param {Element} elem - The stanza that triggered the callback.
* @return {false} `false` to remove the handler.
*/
// eslint-disable-next-line no-unused-vars
_onLegacyAuthIQResult(elem) {
//
_onLegacyAuthIQResult() {
const pass = typeof this.pass === 'string' ? this.pass : '';

// build plaintext auth iq
const iq = $iq({ type: 'set', id: '_auth_2' })
.c('query', { xmlns: Strophe.NS.AUTH })
.c('username', {})
.t(Strophe.getNodeFromJid(this.jid))
.up()
.c('password')
.t(this.pass);
.t(pass);

if (!Strophe.getResourceFromJid(this.jid)) {
// since the user has not supplied a resource, we pick
Expand Down
9 changes: 4 additions & 5 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,26 @@ export const NS = {
* Used in the {@link Strophe.createHtml} function to filter incoming html into the allowed XHTML-IM subset.
* See [XEP-0071](http://xmpp.org/extensions/xep-0071.html#profile-summary) for the list of recommended
* allowed tags and their attributes.
*
* @typedef {Object} XHTML
* @property {Array} XHTML.tags
* @property {Object} XHTML.attributes
* @property {Array} XHTML.css
*/
export const XHTML = {
tags: ['a', 'blockquote', 'br', 'cite', 'em', 'img', 'li', 'ol', 'p', 'span', 'strong', 'ul', 'body'],
attributes: {
'a': ['href'],
'blockquote': ['style'],
/** @type {never[]} */
'br': [],
'cite': ['style'],
/** @type {never[]} */
'em': [],
'img': ['src', 'alt', 'style', 'height', 'width'],
'li': ['style'],
'ol': ['style'],
'p': ['style'],
'span': ['style'],
/** @type {never[]} */
'strong': [],
'ul': ['style'],
/** @type {never[]} */
'body': [],
},
css: [
Expand Down
14 changes: 14 additions & 0 deletions src/sasl-sha256.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @typedef {import("./connection.js").default} Connection
*/
import SASLMechanism from './sasl.js';
import scram from './scram.js';

Expand All @@ -9,16 +12,27 @@ class SASLSHA256 extends SASLMechanism {
super(mechname, isClientFirst, priority);
}

/**
* @param {Connection} connection
*/
// eslint-disable-next-line class-methods-use-this
test(connection) {
return connection.authcid !== null;
}

/**
* @param {Connection} connection
* @param {string} [challenge]
*/
// eslint-disable-next-line class-methods-use-this
async onChallenge(connection, challenge) {
return await scram.scramResponse(connection, challenge, 'SHA-256', 256);
}

/**
* @param {Connection} connection
* @param {string} [test_cnonce]
*/
// eslint-disable-next-line class-methods-use-this
clientChallenge(connection, test_cnonce) {
return scram.clientChallenge(connection, test_cnonce);
Expand Down
14 changes: 14 additions & 0 deletions src/sasl-sha384.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @typedef {import("./connection.js").default} Connection
*/
import SASLMechanism from './sasl.js';
import scram from './scram.js';

Expand All @@ -9,16 +12,27 @@ class SASLSHA384 extends SASLMechanism {
super(mechname, isClientFirst, priority);
}

/**
* @param {Connection} connection
*/
// eslint-disable-next-line class-methods-use-this
test(connection) {
return connection.authcid !== null;
}

/**
* @param {Connection} connection
* @param {string} [challenge]
*/
// eslint-disable-next-line class-methods-use-this
async onChallenge(connection, challenge) {
return await scram.scramResponse(connection, challenge, 'SHA-384', 384);
}

/**
* @param {Connection} connection
* @param {string} [test_cnonce]
*/
// eslint-disable-next-line class-methods-use-this
clientChallenge(connection, test_cnonce) {
return scram.clientChallenge(connection, test_cnonce);
Expand Down
12 changes: 9 additions & 3 deletions src/sasl-sha512.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import SASLMechanism from './sasl.js';
import scram from './scram.js';

/**
* @typedef {import("./connection.js").default} Connection
*/
import SASLMechanism from './sasl.js';
import scram from './scram.js';

class SASLSHA512 extends SASLMechanism {
/**
Expand All @@ -13,6 +12,9 @@ class SASLSHA512 extends SASLMechanism {
super(mechname, isClientFirst, priority);
}

/**
* @param {Connection} connection
*/
// eslint-disable-next-line class-methods-use-this
test(connection) {
return connection.authcid !== null;
Expand All @@ -27,6 +29,10 @@ class SASLSHA512 extends SASLMechanism {
return await scram.scramResponse(connection, challenge, 'SHA-512', 512);
}

/**
* @param {Connection} connection
* @param {string} [test_cnonce]
*/
// eslint-disable-next-line class-methods-use-this
clientChallenge(connection, test_cnonce) {
return scram.clientChallenge(connection, test_cnonce);
Expand Down
50 changes: 40 additions & 10 deletions src/scram.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import utils from './utils';
import Strophe from './core.js';

/**
* @param {string} authMessage
* @param {ArrayBufferLike} clientKey
* @param {string} hashName
*/
async function scramClientProof(authMessage, clientKey, hashName) {
const storedKey = await crypto.subtle.importKey(
'raw',
Expand Down Expand Up @@ -70,6 +75,11 @@ function scramParseChallenge(challenge) {
* { ck: ArrayBuffer, the client key
* sk: ArrayBuffer, the server key
* }
* @param {string} password
* @param {BufferSource} salt
* @param {number} iter
* @param {string} hashName
* @param {number} hashBits
*/
async function scramDeriveKeys(password, salt, iter, hashName, hashBits) {
const saltedPasswordBits = await crypto.subtle.deriveBits(
Expand All @@ -91,6 +101,11 @@ async function scramDeriveKeys(password, salt, iter, hashName, hashBits) {
};
}

/**
* @param {string} authMessage
* @param {BufferSource} sk
* @param {string} hashName
*/
async function scramServerSign(authMessage, sk, hashName) {
const serverKey = await crypto.subtle.importKey('raw', sk, { 'name': 'HMAC', 'hash': hashName }, false, ['sign']);

Expand All @@ -107,6 +122,15 @@ function generate_cnonce() {
return utils.arrayBufToBase64(crypto.getRandomValues(bytes).buffer);
}

/**
* @typedef {Object} Password
* @property {string} Password.name
* @property {string} Password.ck
* @property {string} Password.sk
* @property {number} Password.iter
* @property {string} salt
*/

const scram = {
/**
* On success, sets
Expand All @@ -118,6 +142,9 @@ const scram = {
*
* On failure, returns connection._sasl_failure_cb();
* @param {Connection} connection
* @param {string} challenge
* @param {string} hashName
* @param {number} hashBits
*/
async scramResponse(connection, challenge, hashName, hashBits) {
const cnonce = connection._sasl_data.cnonce;
Expand All @@ -133,24 +160,27 @@ const scram = {

let clientKey, serverKey;

// Either restore the client key and server key passed in, or derive new ones
if (
connection.pass?.name === hashName &&
connection.pass?.salt === utils.arrayBufToBase64(challengeData.salt) &&
connection.pass?.iter === challengeData.iter
) {
clientKey = utils.base64ToArrayBuf(connection.pass.ck);
serverKey = utils.base64ToArrayBuf(connection.pass.sk);
} else if (typeof connection.pass === 'string' || connection.pass instanceof String) {
const { pass } = connection;

if (typeof connection.pass === 'string' || connection.pass instanceof String) {
const keys = await scramDeriveKeys(
connection.pass,
/** @type {string} */ (pass),
challengeData.salt,
challengeData.iter,
hashName,
hashBits
);
clientKey = keys.ck;
serverKey = keys.sk;
} else if (
// Either restore the client key and server key passed in, or derive new ones
/** @type {Password} */ (pass)?.name === hashName &&
/** @type {Password} */ (pass)?.salt === utils.arrayBufToBase64(challengeData.salt) &&
/** @type {Password} */ (pass)?.iter === challengeData.iter
) {
const { ck, sk } = /** @type {Password} */ (pass);
clientKey = utils.base64ToArrayBuf(ck);
serverKey = utils.base64ToArrayBuf(sk);
} else {
return connection._sasl_failure_cb();
}
Expand Down
Loading

0 comments on commit 35bc231

Please sign in to comment.