Skip to content

Commit

Permalink
Implement SASL2 (#1030)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephen Paul Weber <[email protected]>
  • Loading branch information
sonnyp and singpolyma authored Dec 22, 2024
1 parent 21720f0 commit f6c77ed
Show file tree
Hide file tree
Showing 23 changed files with 543 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/prosody.list
sudo wget https://prosody.im/files/prosody-debian-packages.key -O/etc/apt/trusted.gpg.d/prosody.gpg
sudo apt-get update
sudo apt-get -y install prosody lua-bitop lua-sec
sudo apt-get -y install lua5.3 liblua5.3-dev prosody-trunk lua-bitop lua-sec luarocks
sudo service prosody stop
# - run: npm install -g npm
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ server/certs/
server/prosody.err
server/prosody.log
server/prosody.pid
server/modules
server/.cache

!.gitkeep
!.editorconfig
Expand Down
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ ci:
make bundlesize

unit:
npx jest
npm run test

e2e:
NODE_TLS_REJECT_UNAUTHORIZED=0 npx jest --runInBand --config e2e.config.cjs
$(warning e2e tests require prosody-trunk and luarocks)
cd server && prosodyctl --config prosody.cfg.lua install mod_sasl2 > /dev/null
# https://github.com/xmppjs/xmpp.js/pull/1006
# cd server && prosodyctl --config prosody.cfg.lua install mod_sasl2_bind2 > /dev/null
# cd server && prosodyctl --config prosody.cfg.lua install mod_sasl2_fast > /dev/null
# cd server && prosodyctl --config prosody.cfg.lua install mod_sasl2_sm > /dev/null
npm run e2e

clean:
make stop
Expand Down
33 changes: 33 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"selfsigned": "^2.4.1"
},
"scripts": {
"test": "npx jest",
"e2e": "NODE_TLS_REJECT_UNAUTHORIZED=0 npx jest --runInBand --config e2e.config.cjs",
"preversion": "make bundle"
},
"engines": {
Expand Down
4 changes: 3 additions & 1 deletion packages/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ xmpp.on("stanza", async (stanza) => {
});

xmpp.on("online", async (address) => {
console.log("online as", address.toString());

// Makes itself available
await xmpp.send(xml("presence"));

Expand All @@ -75,7 +77,7 @@ xmpp.on("online", async (address) => {
await xmpp.send(message);
});

xmpp.start().catch(console.error);
await xmpp.start();
```

## xml
Expand Down
85 changes: 0 additions & 85 deletions packages/client/browser.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/client/example.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { client, xml } from "@xmpp/client";

// eslint-disable-next-line n/no-extraneous-import
import debug from "@xmpp/debug";

Expand Down
30 changes: 24 additions & 6 deletions packages/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import _streamFeatures from "@xmpp/stream-features";
import _iqCaller from "@xmpp/iq/caller.js";
import _iqCallee from "@xmpp/iq/callee.js";
import _resolve from "@xmpp/resolve";

import _starttls from "@xmpp/starttls";
import _sasl2 from "@xmpp/sasl2";
import _sasl from "@xmpp/sasl";
import _resourceBinding from "@xmpp/resource-binding";
import _sessionEstablishment from "@xmpp/session-establishment";
Expand All @@ -23,8 +23,20 @@ import scramsha1 from "@xmpp/sasl-scram-sha-1";
import plain from "@xmpp/sasl-plain";
import anonymous from "@xmpp/sasl-anonymous";

// In browsers and react-native some packages are excluded
// see package.json and https://metrobundler.dev/docs/configuration/#resolvermainfields
// in which case the default import returns an empty object
function setupIfAvailable(module, ...args) {
if (typeof module !== "function") {
return undefined;
}

return module(...args);
}

function client(options = {}) {
const { resource, credentials, username, password, ...params } = options;
const { clientId, software, device } = params;

const { domain, service } = params;
if (!domain && service) {
Expand All @@ -35,8 +47,8 @@ function client(options = {}) {

const reconnect = _reconnect({ entity });
const websocket = _websocket({ entity });
const tcp = _tcp({ entity });
const tls = _tls({ entity });
const tcp = setupIfAvailable(_tcp, { entity });
const tls = setupIfAvailable(_tls, { entity });

const middleware = _middleware({ entity });
const streamFeatures = _streamFeatures({ middleware });
Expand All @@ -47,13 +59,18 @@ function client(options = {}) {
// SASL mechanisms - order matters and define priority
const saslFactory = new SASLFactory();
const mechanisms = Object.entries({
scramsha1,
...(typeof scramsha1 === "function" && { scramsha1 }),
plain,
anonymous,
}).map(([k, v]) => ({ [k]: v(saslFactory) }));

// Stream features - order matters and define priority
const starttls = _starttls({ streamFeatures });
const starttls = setupIfAvailable(_starttls, { streamFeatures });
const sasl2 = _sasl2(
{ streamFeatures, saslFactory },
createOnAuthenticate(credentials ?? { username, password }),
{ clientId, software, device },
);
const sasl = _sasl(
{ streamFeatures, saslFactory },
createOnAuthenticate(credentials ?? { username, password }),
Expand Down Expand Up @@ -84,12 +101,13 @@ function client(options = {}) {
iqCallee,
resolve,
starttls,
saslFactory,
sasl2,
sasl,
resourceBinding,
sessionEstablishment,
streamManagement,
mechanisms,
saslFactory,
});
}

Expand Down
9 changes: 7 additions & 2 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@xmpp/resolve": "^0.13.2",
"@xmpp/resource-binding": "^0.13.2",
"@xmpp/sasl": "^0.13.2",
"@xmpp/sasl2": "^0.13.0",
"@xmpp/sasl-anonymous": "^0.13.2",
"@xmpp/sasl-plain": "^0.13.2",
"@xmpp/sasl-scram-sha-1": "^0.13.2",
Expand All @@ -27,8 +28,12 @@
"@xmpp/websocket": "^0.13.2",
"saslmechanisms": "^0.1.1"
},
"browser": "browser.js",
"react-native": "browser.js",
"browser": {
"@xmpp/tcp": false,
"@xmpp/tls": false,
"@xmpp/starttls": false,
"@xmpp/sasl-scram-sha-1": false
},
"engines": {
"node": ">= 20"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/component/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ xmpp.on("online", async (address) => {
await xmpp.send(message);
});

xmpp.start().catch(console.error);
await xmpp.start();
```

## xml
Expand Down
2 changes: 2 additions & 0 deletions packages/error/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ test("fromElement", () => {
const error = XMPPError.fromElement(nonza);

expect(error instanceof Error).toBe(true);
expect(error instanceof XMPPError).toBe(true);
expect(error.name).toBe("XMPPError");
expect(error.condition).toBe("some-condition");
expect(error.text).toBe("foo");
Expand All @@ -42,6 +43,7 @@ test("fromElement - whitespaces", () => {
const error = XMPPError.fromElement(nonza);

expect(error instanceof Error).toBe(true);
expect(error instanceof XMPPError).toBe(true);
expect(error.name).toBe("XMPPError");
expect(error.condition).toBe("some-condition");
expect(error.text).toBe("\n foo\n ");
Expand Down
4 changes: 2 additions & 2 deletions packages/sasl/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import xml from "@xmpp/xml";

const NS = "urn:ietf:params:xml:ns:xmpp-sasl";

function getMechanismNames(features) {
return features
function getMechanismNames(stanza) {
return stanza
.getChild("mechanisms", NS)
.getChildElements()
.map((el) => el.text());
Expand Down
Loading

0 comments on commit f6c77ed

Please sign in to comment.