@xmpp/tls
Version:
XMPP TLS for JavaScript
223 lines (196 loc) • 9.35 kB
JavaScript
const test = require("ava");
const ConnectionTLS = require("./lib/Connection");
const tls = require("tls");
const { promise } = require("@xmpp/test");
// eslint-disable-next-line n/no-extraneous-require
const selfsigned = require("selfsigned");
test("socketParameters()", (t) => {
t.deepEqual(ConnectionTLS.prototype.socketParameters("xmpps://foo"), {
port: 5223,
host: "foo",
});
t.deepEqual(ConnectionTLS.prototype.socketParameters("xmpps://foo:1234"), {
port: 1234,
host: "foo",
});
t.deepEqual(
ConnectionTLS.prototype.socketParameters("xmpp://foo"),
undefined,
);
t.deepEqual(
ConnectionTLS.prototype.socketParameters("xmpp://foo:1234"),
undefined,
);
});
test("rejects expired certificates", async (t) => {
const options = {
key: `-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDSyWGs4hf07dd5
VS8yPNxAeotrFuMloSD1OpHcbwhPYuDFKO+3WUC4kZnKJlWqkZBCSvLNy73D3gWJ
ZmP5ck2gUdWg4YE/6ATu7mbQWo3BEeakW2jnuYDnFZhJf4Ip2bs7alKer4WUzoxJ
jU9dAEdz3B4qjfZ6ZXc6LSiFxBzHDl/Z0os6qpFrrs3RHskY7xrcZEcAfgClkmsP
M8/oxGTK24Zfo5yrdRtLYNMiYSsX+CoBmcSzld8BAIp4vesBrp2N3Rrjp9x6pFZb
BSdCJysMU5uwcpdZrZrbDEB0tzbP2mtLNv149WSzZtHl4K5pRghQqx7MBh1V9lVd
jyi4zLLVAgMBAAECggEBAJTcKYHZjkeoLHMAqLsW5gkXQhyX5kSt3UOyYE5Hj5vY
3Zn/hgN7Icz27qAnoHo8IJ/gpEaYK2UHB+v4BoSkp5OgF3ltqETEi69dZ/ie6ts9
1B+gep6jkBgiVREa3obFwId+V+i/Vlw33jUXecPZLZzyB8/PwBDCVYgdWi/Vxuj/
wnO839LUikTph4hhnW+2tCrJ4zzdd9gJb+VVye5goeAaXLIVpsY/YKX4upJOJ7tP
lW3PJgeoHeT4EwQVGHCiTAd+8I2EqqvNTCxzY3x5vgd0EHePTuThsM+6n1vFwKp+
5UBYfGJtf8QKfhfac6WrvREvbVc/WmOtysXBtfdHhAECgYEA8Uysoj+pcY56uvMI
tFovYQtgGIxX2VyzuStXwGtdrzNB+SoDlrwcmKoPMSA2WhkBjoynHX41YHnOZDEq
T9+oJSSoxTE4TgDiVnGjkC5v/mV+E760IsuyUGVmy2WJu1BSrMml/hBnDRSZ717s
gGsEDwKPRSh8ooOPzGV/iM7wT9UCgYEA36DThRmUK6pF+cdO2T/064GFk/PPfKOf
xFUS34RVjkRTknYte+6uYIRzE7JCeoY4o9hwj3x/AyYhFf1H8o90rPVZLBVWdeML
TfxbCTmTQ14BIkLSRWIy8ocmbttMzwMgC/2/ofQ1Ryrl/BLlOeEIyGYVcS8ihjRz
bme6PyxPVwECgYACmmQmX+9xBSt3xtVqNKrcLiY8PY9ZDfH2ZmxM7BuXn0Lv8C8X
ujHIx9TgH8vWTvzAT+4hmFH1F3tNg2ZEdFI5DFsxvWUxGjtW2WT9UjLtGKUyi1Ug
Jvhme6GPQiopNiWeLZK32e9yqa07cte0TvM9QjbPdS9bBXZQqyukCy92fQKBgQDM
HDWTkZIs/KAb6C9umTKJ1dE/BlTGFW5Yu7GbM2UHkhOZZaYELQkZ7So/uv90Z5fA
7Gdof6BKFn4yXNhTa156EwIN+3fL56xExOWumM9xuJZeWBEl5QhNVs/cdOs5M0gH
ydYkEwqh52S8294/Isdqacp+YSAo0Czfg2t6B45vAQKBgQClJxXVWfIET5bZ7Mtf
CFHUJ3Yc+nCXrCj5Lev65z/8tbsl8gAHD8I/NatKcZcOLXr4XpDdkkLb3wyGzuc1
aMCv/THk7vEyLtnhHJ+N3OuN5kmPLwL69cWsob5Vtua0vHwxLmDnNSkiT7+XQ2j4
mrEOeSCP5DOqcpHZ8q8kpjd/nQ==
-----END PRIVATE KEY-----`,
cert: `-----BEGIN CERTIFICATE-----
MIIDjTCCAnWgAwIBAgIUdQelxJbMGT60o3krKrqQ1C5t5UAwDQYJKoZIhvcNAQEL
BQAwVjELMAkGA1UEBhMCVVMxDzANBgNVBAgMBkRlbmlhbDEUMBIGA1UEBwwLU3By
aW5nZmllbGQxDDAKBgNVBAoMA0RpczESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIw
MDEwMjIwMTIxN1oXDTIxMDEwMTIwMTIxN1owVjELMAkGA1UEBhMCVVMxDzANBgNV
BAgMBkRlbmlhbDEUMBIGA1UEBwwLU3ByaW5nZmllbGQxDDAKBgNVBAoMA0RpczES
MBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA0slhrOIX9O3XeVUvMjzcQHqLaxbjJaEg9TqR3G8IT2LgxSjvt1lAuJGZyiZV
qpGQQkryzcu9w94FiWZj+XJNoFHVoOGBP+gE7u5m0FqNwRHmpFto57mA5xWYSX+C
Kdm7O2pSnq+FlM6MSY1PXQBHc9weKo32emV3Oi0ohcQcxw5f2dKLOqqRa67N0R7J
GO8a3GRHAH4ApZJrDzPP6MRkytuGX6Ocq3UbS2DTImErF/gqAZnEs5XfAQCKeL3r
Aa6djd0a46fceqRWWwUnQicrDFObsHKXWa2a2wxAdLc2z9prSzb9ePVks2bR5eCu
aUYIUKsezAYdVfZVXY8ouMyy1QIDAQABo1MwUTAdBgNVHQ4EFgQU2aR0TjlCwgTJ
uDw4Hi055hOydDEwHwYDVR0jBBgwFoAU2aR0TjlCwgTJuDw4Hi055hOydDEwDwYD
VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQQj4RB7+oSU52Oi0jPKs
B/7f/wuN7KCPmosalazJmhT7BDCeTWkM1FfIKiAGx4LNxlu6Ut/jhESFY2wRptfr
bLFrZr09gtzG57VNOBlSQ3yfxCGCes7dOAG1HhM2qTLY9HsjEu6ygY1BHJoPVBPe
VJbaqufFQEdO4D4J+lRsXs8KqAyNgZrsChqia4lpBPn1DFwAy32hiTw8HZQNqYzQ
LN7+csuY9MGIz7wDy7EYaO7thYxeBF+eoa7leivp/HNPre0v1gmjD+eDJ8ToCOVs
NebQHyTBqa5P7vjSioiWiSRCNOIL4HywMWtN/nZVk0cl8zwlLtMaGt9Tz7ty2OgL
1A==
-----END CERTIFICATE-----`,
};
const server = tls.createServer(options);
server.listen(0);
await promise(server, "listening");
const conn = new ConnectionTLS();
conn.connect(`xmpps://localhost:${server.address().port}`).catch(() => {});
const error = await promise(conn, "error");
t.is(error.message, "certificate has expired");
await conn.close().catch(() => {});
server.close();
});
test("rejects self signed certificates", async (t) => {
const attrs = [{ name: "commonName", value: "localhost" }];
const pem = selfsigned.generate(attrs, {
days: 365,
keySize: 2048,
});
const server = tls.createServer({ key: pem.private, cert: pem.cert });
server.listen(0);
await promise(server, "listening");
const conn = new ConnectionTLS();
conn.connect(`xmpps://localhost:${server.address().port}`).catch(() => {});
const error = await promise(conn, "error");
t.is(error.code, "DEPTH_ZERO_SELF_SIGNED_CERT");
await conn.close().catch(() => {});
server.close();
});
test("waits before emitting connect on tls 1.3", async (t) => {
const key = `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGMXUuq7NZXEt6
fiSSkfTGuXHdpMbM/Bn4YVwaNrEmW0I8ZpROHQsEPo6AA/Dz5XM6zkXc+HZoxVfg
Va6T91NRrNnwJYan6+InZOcJI50axYu5KrOyi2X5HBqlUW2MrB+y5LgE1/22id/4
pIGXxfTK3GbzE7qzmB/ff+Mn5gIY1QysBayFG4xtpGLVg+kVkxSDLSMOmX/ezdG5
wNfejVMenBzyylKB8NX50E5Hj28jnVk5zyoXptjsb31/rp82YI3YIFxl8OKX4zEC
GmTULCy19b5c/OeqKL+/XnR6db91Iort80F54p0SCApth+yH0eLsssJpzWaEG05/
+bAc8F/rAgMBAAECggEARsuP4jXvALKZO44nnjuIxhuj8tpTMRG0bSbJ8YsryFm8
1TqHK0fwkXmPCWdfAKArgwv/pKkUEuS7OSUiETS9jGVEDCY7bWwzAoNmi7su+Usr
V99LBTIKIOvLENZ/XUp2oD5XBVPqCvRBDt4kdIR/pp8IHzgi7tgeOoXCLJRal2eS
C+h4+QxkRVk7ML9Qywydh+U/FIvnS95FWUqXy9YF5X5Gv9onYF3jDFC4wA3cFPYD
/h5ppYKnGWvmItxAnzqXJaLUZaqSKFHvr3ub6OL3d6XURbAtmDBrbBiB/mA+V75H
IHNwgINtg24jTeimj12yWjFWD/v1JqAIXhKhnkbH4QKBgQDjAXm61tNMDF0K9RFP
nBtIbIfjkTnD0dcyQEteUx1ETpZLEtgxCTdafu9RX0lZwZa4JAhX7kzn1BjPcI90
zhnQ8jyiVOjsaxA09ptX3VaK7qMXbNhXndKNAqfx2Fwi/PtK6nafjKSDE7RC/iPT
R0UBexOx8zxRuqxRXknlDM/PwwKBgQDfgeH/LjDVyJpLR3+NWp1MtMlCRQYFfvWw
6RE0zKi05/3P+Hmm4QN02dLIMJKWN0n1qKLNTpgoeLwqilxM/bUjeHKFrhkWqmgJ
CunadWoLbj//PI4etWvVNg3RfYd2G5amwW4kvNfEUL2xNrOum+cUZ4rPGSI0Z+ty
Hk7BRtgUuQKBgQC2SdIJskbc87SnfuIWzqGuB9Ebcdw0HkaziKO9K/r9hin0QT6w
Kdl0ZyggbOcHF4jDd9PnYGoLY+tEcPwR7QsYGd2M8ahVaSgLj9hwt0GusTDwN6yG
tyqDp5VbhMWAJyxYHW2Cc7sLsv/3KAN2vu1v4fiP1mYir0d+07t9HkumZwKBgQDV
0YNKg/3kBwzUh4nWyKFDCJCg/TdNeq/AlrcHM+MRbf66PpLiutB7sQaczRru6eWv
Ray5jD60OQyKBeNXJD9tt4SXrn4B2PO98trVSw4v8UD4BA5SAm0ug4+kodo9excc
YF/mdWJVRIi0SAiNOkhOlN+OUBUQ3Xm4qpXdANEmwQKBgDOJbGNzV9exj83FSJIA
3vE2ec9mESWNOKsVbGmY6J5dqkE/tU0UZw/jyym2f1C5UKS3HIdTWyq1+EMn94iQ
mfmZ/2a0ypN53Z0JMpfKHUBK0XPrRaaKMqnYV7CBm5Os217bpNp2eojocZW+X/GR
6xMKh//fd6uKBFPCqf4cp2Ct
-----END PRIVATE KEY-----`;
const cert = `-----BEGIN CERTIFICATE-----
MIIDjTCCAnWgAwIBAgIUB6DHC0wV8ht//JFAJGanpRBapKIwDQYJKoZIhvcNAQEL
BQAwVjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE
CgwTRGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIx
MDgyMjA5NTU1N1oXDTIyMDgyMjA5NTU1N1owVjELMAkGA1UEBhMCWFgxFTATBgNV
BAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDES
MBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAxjF1LquzWVxLen4kkpH0xrlx3aTGzPwZ+GFcGjaxJltCPGaUTh0LBD6OgAPw
8+VzOs5F3Ph2aMVX4FWuk/dTUazZ8CWGp+viJ2TnCSOdGsWLuSqzsotl+RwapVFt
jKwfsuS4BNf9tonf+KSBl8X0ytxm8xO6s5gf33/jJ+YCGNUMrAWshRuMbaRi1YPp
FZMUgy0jDpl/3s3RucDX3o1THpwc8spSgfDV+dBOR49vI51ZOc8qF6bY7G99f66f
NmCN2CBcZfDil+MxAhpk1CwstfW+XPznqii/v150enW/dSKK7fNBeeKdEggKbYfs
h9Hi7LLCac1mhBtOf/mwHPBf6wIDAQABo1MwUTAdBgNVHQ4EFgQUVwsfTVjMB0gO
62nwCNGHLmlM8WYwHwYDVR0jBBgwFoAUVwsfTVjMB0gO62nwCNGHLmlM8WYwDwYD
VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAs/o3MhYjPNceA65Yc0mI
DZpSD/Ds0rSoPtnUX4pXwzcpAh7yVlgqhzex+l/bJuq0tBnxUuM0NYc1US26SHCf
4+pPhYgrACqMG5ecMebzgwMP0vnZsqtt22eeO1mzhz9z3hPYJciyMOU00gotZJHS
GM9inlF4SFttfwgopJSAb4rAvI0u5jzhLrEvu5wRmWEc0zHWmcTGF46gzXW+79ti
jlJ03ZMth8cH6wL8BcbuPBTKj4hjaLdtIcQiQ0a6wG/+z/vaS2XiahNJ6pMDlV3m
aUOpdCwFaeFw/eL7rQr8rQqCtOO8BsNJ54tS4qbTwmHNb+UqcZQRq8qIq/b+z3qp
yA==
-----END CERTIFICATE-----`;
const server = tls.createServer({
key,
cert,
minVersion: "TLSv1.3",
maxVersion: "TLSv1.3",
});
server.listen(0);
await promise(server, "listening");
const conn = new ConnectionTLS();
conn.socketParameters = () => {
return {
port: server.address().port,
host: "localhost",
rejectUnauthorized: false,
minVersion: "TLSv1.3",
maxVersion: "TLSv1.3",
};
};
// Let's trigger connect but not await it
const promiseConnect = conn.connect(
`xmpps://localhost:${server.address().port}`,
);
// Let's keep track of weither `connect` was emitted on conn.socket
let connect_emitted_on_conn_socket = false;
conn.socket.on("connect", () => {
connect_emitted_on_conn_socket = true;
});
await promise(conn.socket.socket, "secureConnect");
// If connect was emitted immeditaly after secureConnect this would be true
t.is(connect_emitted_on_conn_socket, false);
// Now let's wait for connect to resolve
// and assert the right protocol is used
await promiseConnect;
t.is(conn.socket.socket.getProtocol(), "TLSv1.3");
// If the previous assertion is false and this one is true
// it means `connect` was triggered asynchronously after secureConnect
// which is what we want as it delays the sending of the stream header (conn.open)
t.is(connect_emitted_on_conn_socket, true);
await conn.close().catch(() => {});
server.close();
});
;