Allow certificates from unknown CAs from .onion domains
It's barely possible for .onion servers to provide a non-self-signed cert. But that's fine because encryption is provided independently though TOR. see #958
This commit is contained in:
parent
99e98ac8d9
commit
81a5505270
|
@ -196,7 +196,9 @@ public class ConnectionManager : Object {
|
||||||
connection_directly_retry[account] = false;
|
connection_directly_retry[account] = false;
|
||||||
|
|
||||||
change_connection_state(account, ConnectionState.CONNECTING);
|
change_connection_state(account, ConnectionState.CONNECTING);
|
||||||
stream_result = yield Xmpp.establish_stream(account.bare_jid, module_manager.get_modules(account, resource), log_options);
|
stream_result = yield Xmpp.establish_stream(account.bare_jid, module_manager.get_modules(account, resource), log_options,
|
||||||
|
(_, peer_cert, errors) => { return on_invalid_certificate(account.domainpart, peer_cert, errors); }
|
||||||
|
);
|
||||||
connections[account].stream = stream_result.stream;
|
connections[account].stream = stream_result.stream;
|
||||||
|
|
||||||
connection_ongoing[account] = false;
|
connection_ongoing[account] = false;
|
||||||
|
@ -368,6 +370,16 @@ public class ConnectionManager : Object {
|
||||||
connection_errors[account] = error;
|
connection_errors[account] = error;
|
||||||
connection_error(account, error);
|
connection_error(account, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool on_invalid_certificate(string domain, TlsCertificate peer_cert, TlsCertificateFlags errors) {
|
||||||
|
if (domain.has_suffix(".onion") && errors == TlsCertificateFlags.UNKNOWN_CA) {
|
||||||
|
// It's barely possible for .onion servers to provide a non-self-signed cert.
|
||||||
|
// But that's fine because encryption is provided independently though TOR.
|
||||||
|
warning("Accepting TLS certificate from unknown CA from .onion address %s", domain);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,9 @@ public class Register : StreamInteractionModule, Object{
|
||||||
list.add(new Iq.Module());
|
list.add(new Iq.Module());
|
||||||
list.add(new Sasl.Module(account.bare_jid.to_string(), account.password));
|
list.add(new Sasl.Module(account.bare_jid.to_string(), account.password));
|
||||||
|
|
||||||
XmppStreamResult stream_result = yield Xmpp.establish_stream(account.bare_jid.domain_jid, list, Application.print_xmpp);
|
XmppStreamResult stream_result = yield Xmpp.establish_stream(account.bare_jid.domain_jid, list, Application.print_xmpp,
|
||||||
|
(_, peer_cert, errors) => { return ConnectionManager.on_invalid_certificate(account.domainpart, peer_cert, errors); }
|
||||||
|
);
|
||||||
|
|
||||||
if (stream_result.stream == null) {
|
if (stream_result.stream == null) {
|
||||||
if (stream_result.tls_errors != null) {
|
if (stream_result.tls_errors != null) {
|
||||||
|
@ -80,7 +82,9 @@ public class Register : StreamInteractionModule, Object{
|
||||||
Gee.List<XmppStreamModule> list = new ArrayList<XmppStreamModule>();
|
Gee.List<XmppStreamModule> list = new ArrayList<XmppStreamModule>();
|
||||||
list.add(new Iq.Module());
|
list.add(new Iq.Module());
|
||||||
|
|
||||||
XmppStreamResult stream_result = yield Xmpp.establish_stream(jid.domain_jid, list, Application.print_xmpp);
|
XmppStreamResult stream_result = yield Xmpp.establish_stream(jid.domain_jid, list, Application.print_xmpp,
|
||||||
|
(_, peer_cert, errors) => { return ConnectionManager.on_invalid_certificate(jid.domainpart, peer_cert, errors); }
|
||||||
|
);
|
||||||
|
|
||||||
if (stream_result.stream == null) {
|
if (stream_result.stream == null) {
|
||||||
if (stream_result.io_error != null) {
|
if (stream_result.io_error != null) {
|
||||||
|
@ -125,7 +129,9 @@ public class Register : StreamInteractionModule, Object{
|
||||||
list.add(new Iq.Module());
|
list.add(new Iq.Module());
|
||||||
list.add(new Xep.InBandRegistration.Module());
|
list.add(new Xep.InBandRegistration.Module());
|
||||||
|
|
||||||
XmppStreamResult stream_result = yield Xmpp.establish_stream(jid.domain_jid, list, Application.print_xmpp);
|
XmppStreamResult stream_result = yield Xmpp.establish_stream(jid.domain_jid, list, Application.print_xmpp,
|
||||||
|
(_, peer_cert, errors) => { return ConnectionManager.on_invalid_certificate(jid.domainpart, peer_cert, errors); }
|
||||||
|
);
|
||||||
|
|
||||||
if (stream_result.stream == null) {
|
if (stream_result.stream == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -169,7 +175,9 @@ public class Register : StreamInteractionModule, Object{
|
||||||
list.add(new Iq.Module());
|
list.add(new Iq.Module());
|
||||||
list.add(new Xep.InBandRegistration.Module());
|
list.add(new Xep.InBandRegistration.Module());
|
||||||
|
|
||||||
XmppStreamResult stream_result = yield Xmpp.establish_stream(jid.domain_jid, list, Application.print_xmpp);
|
XmppStreamResult stream_result = yield Xmpp.establish_stream(jid.domain_jid, list, Application.print_xmpp,
|
||||||
|
(_, peer_cert, errors) => { return ConnectionManager.on_invalid_certificate(jid.domainpart, peer_cert, errors); }
|
||||||
|
);
|
||||||
|
|
||||||
if (stream_result.stream == null) {
|
if (stream_result.stream == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -2,11 +2,13 @@ public class Xmpp.DirectTlsXmppStream : TlsXmppStream {
|
||||||
|
|
||||||
string host;
|
string host;
|
||||||
uint16 port;
|
uint16 port;
|
||||||
|
TlsXmppStream.OnInvalidCert on_invalid_cert_outer;
|
||||||
|
|
||||||
public DirectTlsXmppStream(Jid remote, string host, uint16 port) {
|
public DirectTlsXmppStream(Jid remote_name, string host, uint16 port, TlsXmppStream.OnInvalidCert on_invalid_cert) {
|
||||||
this.remote_name = remote;
|
base(remote_name);
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
this.on_invalid_cert_outer = on_invalid_cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async void connect() throws IOStreamError {
|
public override async void connect() throws IOStreamError {
|
||||||
|
@ -15,10 +17,11 @@ public class Xmpp.DirectTlsXmppStream : TlsXmppStream {
|
||||||
debug("Connecting to %s %i (tls)", host, port);
|
debug("Connecting to %s %i (tls)", host, port);
|
||||||
IOStream? io_stream = yield client.connect_to_host_async(host, port);
|
IOStream? io_stream = yield client.connect_to_host_async(host, port);
|
||||||
TlsConnection tls_connection = TlsClientConnection.new(io_stream, new NetworkAddress(remote_name.to_string(), port));
|
TlsConnection tls_connection = TlsClientConnection.new(io_stream, new NetworkAddress(remote_name.to_string(), port));
|
||||||
#if ALPN_SUPPORT
|
#if ALPN_SUPPORT
|
||||||
tls_connection.set_advertised_protocols(new string[]{"xmpp-client"});
|
tls_connection.set_advertised_protocols(new string[]{"xmpp-client"});
|
||||||
#endif
|
#endif
|
||||||
tls_connection.accept_certificate.connect(on_invalid_certificate);
|
tls_connection.accept_certificate.connect(on_invalid_certificate);
|
||||||
|
tls_connection.accept_certificate.connect(on_invalid_cert_outer);
|
||||||
reset_stream(tls_connection);
|
reset_stream(tls_connection);
|
||||||
|
|
||||||
yield setup();
|
yield setup();
|
||||||
|
|
|
@ -11,6 +11,10 @@ public abstract class Xmpp.IoXmppStream : XmppStream {
|
||||||
|
|
||||||
internal WriteNodeFunc? write_obj = null;
|
internal WriteNodeFunc? write_obj = null;
|
||||||
|
|
||||||
|
protected IoXmppStream(Jid remote_name) {
|
||||||
|
base(remote_name);
|
||||||
|
}
|
||||||
|
|
||||||
public override async void disconnect() throws IOStreamError, XmlError, IOError {
|
public override async void disconnect() throws IOStreamError, XmlError, IOError {
|
||||||
disconnected = true;
|
disconnected = true;
|
||||||
if (writer == null || reader == null || stream == null) {
|
if (writer == null || reader == null || stream == null) {
|
||||||
|
|
|
@ -4,11 +4,13 @@ public class Xmpp.StartTlsXmppStream : TlsXmppStream {
|
||||||
|
|
||||||
string host;
|
string host;
|
||||||
uint16 port;
|
uint16 port;
|
||||||
|
TlsXmppStream.OnInvalidCert on_invalid_cert_outer;
|
||||||
|
|
||||||
public StartTlsXmppStream(Jid remote, string host, uint16 port) {
|
public StartTlsXmppStream(Jid remote, string host, uint16 port, TlsXmppStream.OnInvalidCert on_invalid_cert) {
|
||||||
this.remote_name = remote;
|
base(remote);
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
this.on_invalid_cert_outer = on_invalid_cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async void connect() throws IOStreamError {
|
public override async void connect() throws IOStreamError {
|
||||||
|
@ -40,6 +42,7 @@ public class Xmpp.StartTlsXmppStream : TlsXmppStream {
|
||||||
reset_stream(conn);
|
reset_stream(conn);
|
||||||
|
|
||||||
conn.accept_certificate.connect(on_invalid_certificate);
|
conn.accept_certificate.connect(on_invalid_certificate);
|
||||||
|
conn.accept_certificate.connect(on_invalid_cert_outer);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
stderr.printf("Failed to start TLS: %s\n", e.message);
|
stderr.printf("Failed to start TLS: %s\n", e.message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ namespace Xmpp {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class XmppStreamResult {
|
public class XmppStreamResult {
|
||||||
public XmppStream? stream { get; set; }
|
public TlsXmppStream? stream { get; set; }
|
||||||
public TlsCertificateFlags? tls_errors { get; set; }
|
public TlsCertificateFlags? tls_errors { get; set; }
|
||||||
public IOStreamError? io_error { get; set; }
|
public IOStreamError? io_error { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async XmppStreamResult establish_stream(Jid bare_jid, Gee.List<XmppStreamModule> modules, string? log_options) {
|
public async XmppStreamResult establish_stream(Jid bare_jid, Gee.List<XmppStreamModule> modules, string? log_options, TlsXmppStream.OnInvalidCert on_invalid_cert) {
|
||||||
Jid remote = bare_jid.domain_jid;
|
Jid remote = bare_jid.domain_jid;
|
||||||
|
|
||||||
//Lookup xmpp-client and xmpps-client SRV records
|
//Lookup xmpp-client and xmpps-client SRV records
|
||||||
|
@ -58,9 +58,9 @@ namespace Xmpp {
|
||||||
foreach (SrvTargetInfo target in targets) {
|
foreach (SrvTargetInfo target in targets) {
|
||||||
try {
|
try {
|
||||||
if (target.service == "xmpp-client") {
|
if (target.service == "xmpp-client") {
|
||||||
stream = new StartTlsXmppStream(remote, target.host, target.port);
|
stream = new StartTlsXmppStream(remote, target.host, target.port, on_invalid_cert);
|
||||||
} else {
|
} else {
|
||||||
stream = new DirectTlsXmppStream(remote, target.host, target.port);
|
stream = new DirectTlsXmppStream(remote, target.host, target.port, on_invalid_cert);
|
||||||
}
|
}
|
||||||
stream.log = new XmppLog(bare_jid.to_string(), log_options);
|
stream.log = new XmppLog(bare_jid.to_string(), log_options);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,12 @@ public abstract class Xmpp.TlsXmppStream : IoXmppStream {
|
||||||
|
|
||||||
public TlsCertificateFlags? errors;
|
public TlsCertificateFlags? errors;
|
||||||
|
|
||||||
|
public delegate bool OnInvalidCert(GLib.TlsConnection conn, GLib.TlsCertificate peer_cert, GLib.TlsCertificateFlags errors);
|
||||||
|
|
||||||
|
protected TlsXmppStream(Jid remote_name) {
|
||||||
|
base(remote_name);
|
||||||
|
}
|
||||||
|
|
||||||
protected bool on_invalid_certificate(TlsCertificate peer_cert, TlsCertificateFlags errors) {
|
protected bool on_invalid_certificate(TlsCertificate peer_cert, TlsCertificateFlags errors) {
|
||||||
this.errors = errors;
|
this.errors = errors;
|
||||||
|
|
||||||
|
@ -13,7 +19,7 @@ public abstract class Xmpp.TlsXmppStream : IoXmppStream {
|
||||||
error_str += @"$(f), ";
|
error_str += @"$(f), ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
warning(@"Tls Certificate Errors: $(error_str)");
|
warning(@"[%p, %s] Tls Certificate Errors: %s", this, this.remote_name, error_str);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,6 +34,10 @@ public abstract class Xmpp.XmppStream {
|
||||||
protected bool setup_needed = false;
|
protected bool setup_needed = false;
|
||||||
protected bool disconnected = false;
|
protected bool disconnected = false;
|
||||||
|
|
||||||
|
protected XmppStream(Jid remote_name) {
|
||||||
|
this.remote_name = remote_name;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract async void connect() throws IOStreamError;
|
public abstract async void connect() throws IOStreamError;
|
||||||
|
|
||||||
public abstract async void disconnect() throws IOStreamError, XmlError, IOError;
|
public abstract async void disconnect() throws IOStreamError, XmlError, IOError;
|
||||||
|
@ -41,7 +45,7 @@ public abstract class Xmpp.XmppStream {
|
||||||
public abstract async StanzaNode read() throws IOStreamError;
|
public abstract async StanzaNode read() throws IOStreamError;
|
||||||
|
|
||||||
[Version (deprecated = true, deprecated_since = "0.1", replacement = "write_async")]
|
[Version (deprecated = true, deprecated_since = "0.1", replacement = "write_async")]
|
||||||
public abstract void write(StanzaNode node);
|
public abstract void write(StanzaNode node);
|
||||||
|
|
||||||
public abstract async void write_async(StanzaNode node) throws IOStreamError;
|
public abstract async void write_async(StanzaNode node) throws IOStreamError;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue