Commit bb83a071 authored by Harald Sitter's avatar Harald Sitter 🌈
Browse files

smb: fix ipv6 support

Summary:
libsmbc doesn't presently support smb://[ABCD::DCBA]/ uris because it
has very opinionated colon parsing. as a workaround we convert hosts
that are ipv6 addresses to their windows ipv6 literal representation.
that is basically s/:/-/g and s/%/s/g and appending .ipv6-literal.net.

BUG: 417682
FIXED-IN: 20.04

Test Plan: builds, test passes, `'smb://[::1]/foo'` works as expected

Reviewers: ngraham

Reviewed By: ngraham

Subscribers: cfeck, thiago, kde-frameworks-devel, kfm-devel

Tags: #dolphin, #frameworks

Differential Revision: https://phabricator.kde.org/D27802
parent d8d92670
......@@ -62,6 +62,33 @@ private Q_SLOTS:
SMBUrl url(QUrl("cifs://host/share/file"));
QCOMPARE(url.toSmbcUrl(), "smb://host/share/file");
}
void testIPv6Literal()
{
// https://bugs.kde.org/show_bug.cgi?id=417682
// Samba cannot deal with RFC5952 IPv6 notation (e.g. ::1%lo)
// to work around we convert to windows ipv6 literals.
// The actual represented URL should not change!
// i.e. towards the KIO client we do not leak the IPv6
// literal when returning an URL.
QCOMPARE(SMBUrl(QUrl("smb://[::1]/share")).toString(),
"smb://[::1]/share");
// The internal smbc representation should be literal though:
// :: prefix
QCOMPARE(SMBUrl(QUrl("smb://[::1]/share")).toSmbcUrl(),
"smb://0--1.ipv6-literal.net/share");
// :: suffix
QCOMPARE(SMBUrl(QUrl("smb://[fe80::]/share")).toSmbcUrl(),
"smb://fe80--0.ipv6-literal.net/share");
// %lo scope
QCOMPARE(SMBUrl(QUrl("smb://[::1%lo]/share")).toSmbcUrl(),
"smb://0--1slo.ipv6-literal.net/share");
// random valid addr
QCOMPARE(SMBUrl(QUrl("smb://[fe80::9cd7:32c7:faeb:f23d]/share")).toSmbcUrl(),
"smb://fe80--9cd7-32c7-faeb-f23d.ipv6-literal.net/share");
}
};
QTEST_GUILESS_MAIN(SMBUrlTest)
......
......@@ -11,6 +11,7 @@
//---------------------------------------------------------------------------
//
// Copyright (c) 2000 Caldera Systems, Inc.
// Copyright (c) 2020 Harald Sitter <sitter@kde.org>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
......@@ -32,6 +33,7 @@
#include "smb-logsettings.h"
#include <QDir>
#include <QHostAddress>
#include <KConfig>
#include <KIO/Global>
......@@ -77,10 +79,43 @@ void SMBUrl::updateCache()
// SMB URLs are UTF-8 encoded
qCDebug(KIO_SMB_LOG) << "updateCache " << QUrl::path();
if (QUrl::url() == "smb:/")
QUrl sambaUrl(*this);
const QHostAddress address(sambaUrl.host());
switch (address.protocol()) {
case QAbstractSocket::IPv6Protocol: {
// Convert to Windows IPv6 literal to bypass limitations in samba.
// https://bugzilla.samba.org/show_bug.cgi?id=14297
// https://docs.microsoft.com/en-us/windows/win32/api/winnetwk/nf-winnetwk-wnetaddconnection2a
// https://devblogs.microsoft.com/oldnewthing/20100915-00/?p=12863
// https://www.samba.org/~idra/code/nss-ipv6literal/README.html
// https://ipv6-literal.com
QString literal = address.toString();
literal.replace(':', '-'); // address
literal.replace('%', 's'); // scope
if (literal.front() == '-') {
// Special prefix for [::f] so it doesn't start with a dash.
literal.prepend('0');
}
if (literal.back() == '-') {
// Special suffix, also cannot end with a dash.
literal.append('0');
}
literal += ".ipv6-literal.net"; // reserved host host
qCDebug(KIO_SMB_LOG) << "converting IPv6 to literal " << host() << literal;
sambaUrl.setHost(literal);
break;
}
case QAbstractSocket::IPv4Protocol:
case QAbstractSocket::AnyIPProtocol:
case QAbstractSocket::UnknownNetworkLayerProtocol:
break;
}
if (sambaUrl.url() == "smb:/")
m_surl = "smb://";
else
m_surl = toString(QUrl::PrettyDecoded).toUtf8();
m_surl = sambaUrl.toString(QUrl::PrettyDecoded).toUtf8();
m_type = SMBURLTYPE_UNKNOWN;
// update m_type
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment