Use device ID from client SSL certificate, not UDP packet

Consider the following scenario:

1. We send a UDP broadcast
2. We receive a reply from 192.168.0.1 with device ID "foo"
3. We connect to 192.168.0.1, and find that the device's certificate
   is actually for a different ID "bar". This could be because the
   packet did not actually originate from 192.168.0.1, or this host is
   malicious / malfunctioning.
4. We remember that device ID "foo" has certificate with common name "bar".
5. When we finally attempt to connect to the real device ID "foo", we
   reject their certificate (common name "foo"). We can now never
   successfully connect to "foo".

On some network (mis-)configurations, this completely prevents
kdeconnectd from connecting to any peers, because a reply which is
seen as originating from the local interface address will cause
kdeconnectd to immediately connect to itself and remember its own
certificate.

Address this by using the certificate display name of the peer, which
will match the real device ID.
This commit is contained in:
Vladimir Panteleev 2021-09-25 12:51:59 +00:00
parent 695e36755b
commit b706750af8
No known key found for this signature in database
GPG key ID: 5004F0FAD051576D

View file

@ -367,7 +367,7 @@ void LanLinkProvider::encrypted()
LanDeviceLink::ConnectionStarted connectionOrigin = (socket->mode() == QSslSocket::SslClientMode)? LanDeviceLink::Locally : LanDeviceLink::Remotely; LanDeviceLink::ConnectionStarted connectionOrigin = (socket->mode() == QSslSocket::SslClientMode)? LanDeviceLink::Locally : LanDeviceLink::Remotely;
NetworkPacket* receivedPacket = m_receivedIdentityPackets[socket].np; NetworkPacket* receivedPacket = m_receivedIdentityPackets[socket].np;
const QString& deviceId = receivedPacket->get<QString>(QStringLiteral("deviceId")); const QString& deviceId = socket->peerCertificate().subjectDisplayName();
if (m_links.contains(deviceId) && m_links[deviceId]->certificate() != socket->peerCertificate()) { if (m_links.contains(deviceId) && m_links[deviceId]->certificate() != socket->peerCertificate()) {
socket->disconnectFromHost(); socket->disconnectFromHost();