Skip to content

Commit 69309ed

Browse files
authored
Add support for providing client TLS certificate (#239)
* Add support for providing client TLS certificate * Future proof sasl_mechanism * Request sasl cap if mechanism is set to EXTERNAL * Send blank authenticate for EXTERNAL mechanism
1 parent 3f1c702 commit 69309ed

File tree

3 files changed

+36
-20
lines changed

3 files changed

+36
-20
lines changed

docs/clientapi.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ new Irc.Client({
2727
'local-port': 6697,
2828
'remote-port': 21726,
2929
},
30-
}
30+
},
31+
client_certificate: {
32+
private_key: '-----BEGIN RSA PRIVATE KEY-----[...]',
33+
certificate: '-----BEGIN CERTIFICATE-----[...]',
34+
},
3135
});
3236
~~~
3337

src/commands/handlers/registration.js

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ var handlers = {
131131
];
132132

133133
// Optional CAPs depending on settings
134-
if (handler.connection.options.password) {
134+
if (handler.connection.options.password || handler.connection.options.sasl_mechanism === 'EXTERNAL') {
135135
want.push('sasl');
136136
}
137137
if (handler.connection.options.enable_chghost) {
@@ -179,8 +179,8 @@ var handlers = {
179179
}
180180
if (handler.network.cap.negotiating) {
181181
if (handler.network.cap.isEnabled('sasl')) {
182-
if (handler.connection.options.sasl_mechanism === 'AUTHCOOKIE') {
183-
handler.connection.write('AUTHENTICATE AUTHCOOKIE');
182+
if (typeof handler.connection.options.sasl_mechanism === 'string') {
183+
handler.connection.write('AUTHENTICATE ' + handler.connection.options.sasl_mechanism);
184184
} else {
185185
handler.connection.write('AUTHENTICATE PLAIN');
186186
}
@@ -241,25 +241,35 @@ var handlers = {
241241
},
242242

243243
AUTHENTICATE: function(command, handler) {
244-
var auth_str = handler.connection.options.nick + '\0' +
244+
if (command.params[0] !== '+') {
245+
if (handler.network.cap.negotiating) {
246+
handler.connection.write('CAP END');
247+
handler.network.cap.negotiating = false;
248+
}
249+
250+
return;
251+
}
252+
253+
// Send blank authenticate for EXTERNAL mechanism
254+
if (handler.connection.options.sasl_mechanism === 'EXTERNAL') {
255+
handler.connection.write('AUTHENTICATE +');
256+
return;
257+
}
258+
259+
const auth_str = handler.connection.options.nick + '\0' +
245260
handler.connection.options.nick + '\0' +
246261
handler.connection.options.password;
247-
var b = Buffer.from(auth_str, 'utf8');
248-
var b64 = b.toString('base64');
262+
const b = Buffer.from(auth_str, 'utf8');
263+
let b64 = b.toString('base64');
249264

250-
if (command.params[0] === '+') {
251-
while (b64.length >= 400) {
252-
handler.connection.write('AUTHENTICATE ' + b64.slice(0, 399));
253-
b64 = b64.slice(399);
254-
}
255-
if (b64.length > 0) {
256-
handler.connection.write('AUTHENTICATE ' + b64);
257-
} else {
258-
handler.connection.write('AUTHENTICATE +');
259-
}
260-
} else if (handler.network.cap.negotiating) {
261-
handler.connection.write('CAP END');
262-
handler.network.cap.negotiating = false;
265+
while (b64.length >= 400) {
266+
handler.connection.write('AUTHENTICATE ' + b64.slice(0, 399));
267+
b64 = b64.slice(399);
268+
}
269+
if (b64.length > 0) {
270+
handler.connection.write('AUTHENTICATE ' + b64);
271+
} else {
272+
handler.connection.write('AUTHENTICATE +');
263273
}
264274
},
265275

src/transports/net.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ module.exports = class Connection extends EventEmitter {
113113
host: ircd_host,
114114
port: ircd_port,
115115
rejectUnauthorized: options.rejectUnauthorized,
116+
key: options.client_certificate && options.client_certificate.private_key,
117+
cert: options.client_certificate && options.client_certificate.certificate,
116118
localAddress: options.outgoing_addr,
117119
family: this.getAddressFamily(options.outgoing_addr)
118120
});

0 commit comments

Comments
 (0)