Commit be979be8 authored by Harald Sitter's avatar Harald Sitter 🐰

smb: revise auth behavior as per upstream suggestions

- We no longer attempt to auto-anonymous as that can increase the failed
logon count for no good reason. As a silly side effect it'd also mean
that servers that actually support anonymous login would always be used
anonymously and the user then has no visible way to actually login short
of editing the URI to smb://username@host
- Domain field is gone now. Folded into username as per UPN foramt
- Anonymous field is also gone now. Also folded into username

This largely roots in the fact that windows logons are a range of
formats, so upstream rightly suggested that they all should go through
the same username field (which is also how this is done on windows).
This also streamlines the auth dialog a lot and removes a bit of excess
code.
https://docs.microsoft.com/en-us/windows/win32/secauthn/user-name-formats

Anonymous/guest login actually is also implemented thusly by either
using empty or invalid usernames (kinda depends on how the server,
specifically samba, is configured anyway).

To communicate these options to the user we use a new feature in KF5
that allows us to set a fairly visible hint on the username field to
describe in greater detail what the username may be.

I've tested this against my windows server 2019 setup and all the login
options described work as expected.
parent 8bc9c7f0
/*
SPDX-License-Identifier: GPL-2.0-or-later
SPDX-FileCopyrightText: 2000 Caldera Systems, Inc.
SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
SPDX-FileContributor: Matthew Peterson <mpeterson@caldera.com>
*/
......@@ -30,8 +31,18 @@ int SMBSlave::checkPassword(SMBUrl &url)
info.verifyPath = true;
info.keepPassword = true;
info.setExtraField("anonymous", true); // arbitrary default for dialog
info.setExtraField("domain", m_context.authenticator()->defaultWorkgroup());
// By suggestion from upstream we do not split login variants through the UI but rather expect different
// username inputs. This is also more in line with how logon works in windows.
// https://bugzilla.samba.org/show_bug.cgi?id=14326
// https://docs.microsoft.com/en-us/windows/win32/secauthn/user-name-formats
info.setExtraField(QStringLiteral("username-context-help"),
xi18nc("@info:whatsthis",
"<para>There are various options for authenticating on SMB shares.</para>"
"<para><placeholder>username</placeholder>: When authenticating within a home network the username on the server is sufficient</para>"
"<para><placeholder>username@domain.com</placeholder>: Modern corporate logon names are formed like e-mail addresses</para>"
"<para><placeholder>DOMAIN\\username</placeholder>: For ancient corporate networks or workgroups you may need to prefix the NetBIOS domain name (pre-Windows 2000)</para>"
"<para><placeholder>anonymous</placeholder>: Anonymous logins can be attempted using empty username and password. Depending on server configuration non-empty usernames may be required</para>"
));
if (share.isEmpty())
info.prompt = i18n("<qt>Please enter authentication information for <b>%1</b></qt>", url.host());
......
......@@ -10,6 +10,7 @@
#include <KConfig>
#include <KConfigGroup>
#include <KIO/AuthInfo>
#include <KLocalizedString>
#include <QTextCodec>
#include "smburl.h"
......@@ -85,37 +86,26 @@ void SMBAuthenticator::auth(const char *server, const char *share, char *workgro
info.username = s_username;
info.password = s_password;
info.verifyPath = true;
info.setExtraField("domain", s_workgroup);
qCDebug(KIO_SMB_LOG) << "libsmb-auth-callback URL:" << info.url;
if (!m_frontend.checkCachedAuthentication(info)) {
if (m_defaultUser.isEmpty()) {
// ok, we do not know the password. Let's try anonymous before we try for real
info.username = "anonymous";
info.password.clear();
} else {
// user defined a default username/password in kcontrol; try this
info.username = m_defaultUser;
info.password = m_defaultPassword;
}
qCDebug(KIO_SMB_LOG) << "trying defaults for user" << info.username;
} else
// NOTE: By suggestion from upstream we do not default to any amount of
// anonymous/guest logins as it's not safe to do in many environments:
// https://bugzilla.samba.org/show_bug.cgi?id=14326
if (m_frontend.checkCachedAuthentication(info)) {
qCDebug(KIO_SMB_LOG) << "got password through cache" << info.username << info.password;
} else if (!m_defaultUser.isEmpty()) {
// user defined a default username/password in kcontrol; try this
info.username = m_defaultUser;
info.password = m_defaultPassword;
qCDebug(KIO_SMB_LOG) << "trying defaults for user" << info.username;
}
// Make sure it'll be safe to cast to size_t (unsigned)
Q_ASSERT(unmaxlen > 0);
Q_ASSERT(pwmaxlen > 0);
Q_ASSERT(wgmaxlen > 0);
strncpy(username, info.username.toUtf8(), static_cast<size_t>(unmaxlen - 1));
strncpy(password, info.password.toUtf8(), static_cast<size_t>(pwmaxlen - 1));
// TODO: isEmpty guard can be removed in 20.08+
// It is only here to prevent us setting an empty work group if a user updates
// but doesn't restart so kiod5 could hold an old cache without domain
// field. In that event we'll leave the input workgroup as-is.
const QString domain = info.getExtraField("domain").toString();
if (!domain.isEmpty()) {
strncpy(workgroup, domain.toUtf8(), static_cast<size_t>(wgmaxlen - 1));
}
}
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