Commit 0ca35c2f authored by Harald Sitter's avatar Harald Sitter 🏳️‍🌈
Browse files

ACL support

special() now supports
0xAD,url - get ACL: returns "ACL" in metaData as samba acl string
0xACD,url,sid,ace - modify ACL: replaces the ACE string of SID on URL
parent 88ed362b
Pipeline #207337 passed with stage
in 1 minute and 43 seconds
/*
SPDX-License-Identifier: GPL-2.0-or-later
SPDX-FileCopyrightText: 2000 Caldera Systems Inc.
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
SPDX-FileContributor: Matthew Peterson <mpeterson@caldera.com>
*/
......@@ -225,6 +225,8 @@ private:
Q_REQUIRED_RESULT WorkerResult smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags);
bool workaroundEEXIST(const int errNum) const;
int statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEntry &udsentry);
Q_REQUIRED_RESULT WorkerResult getACE(QDataStream &stream);
Q_REQUIRED_RESULT WorkerResult setACE(QDataStream &stream);
/**
* Used in open(), read(), write(), and close()
......
/*
SPDX-License-Identifier: LGPL-2.0-or-later
SPDX-FileCopyrightText: 2000 Alexander Neundorf <neundorf@kde.org>
SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
*/
#include "kio_smb.h"
......@@ -14,7 +15,78 @@
#include <QDir>
#include <unistd.h>
WorkerResult SMBWorker::special(const QByteArray &data)
WorkerResult SMBWorker::getACE(QDataStream &stream)
{
QUrl qurl;
stream >> qurl;
const SMBUrl url(qurl);
// Use the same buffer for all properties to reduce the likelihood of having needless allocations. ACL will usually
// be the largest of the lot and if we try to get that first we'll probably fit all the other properties into the
// same buffer easy peasy.
constexpr auto defaultArraySize = 4096; // arbitrary, the ACL is of unknown size
const int pageSize = static_cast<int>(sysconf(_SC_PAGESIZE));
Q_ASSERT(pageSize == sysconf(_SC_PAGESIZE)); // ensure conversion accuracy
QVarLengthArray<char, defaultArraySize> value(pageSize);
for (auto xattr : {
"system.nt_sec_desc.acl.*+",
"system.nt_sec_desc.owner+",
"system.nt_sec_desc.group+",
}) {
while (true) {
const auto result = smbc_getxattr(url.toSmbcUrl(), xattr, value.data(), value.size());
if (const auto error = errno; result < 0) {
// https://bugzilla.samba.org/show_bug.cgi?id=15088
if (error == ERANGE) {
value.resize(value.size() + pageSize);
continue;
}
qWarning() << xattr << strerror(error);
return WorkerResult::fail(ERR_INTERNAL, strerror(error));
}
qCDebug(KIO_SMB_LOG) << "XATTR" << xattr << value.data();
if (QLatin1String("system.nt_sec_desc.acl.*+") == QLatin1String(xattr)) {
setMetaData("ACL", QString::fromUtf8(value.constData()));
}
if (QLatin1String("system.nt_sec_desc.owner+") == QLatin1String(xattr)) {
setMetaData("OWNER", QString::fromUtf8(value.constData()));
}
if (QLatin1String("system.nt_sec_desc.group+") == QLatin1String(xattr)) {
setMetaData("GROUP", QString::fromUtf8(value.constData()));
}
break;
}
}
return WorkerResult::pass();
}
KIO::WorkerResult SMBWorker::setACE(QDataStream &stream)
{
QUrl qurl;
stream >> qurl;
const SMBUrl url(qurl);
QString sid;
QString aceString;
stream >> sid >> aceString;
const QString attr = QLatin1String("system.nt_sec_desc.acl+:") + sid;
qCDebug(KIO_SMB_LOG) << attr << aceString;
// https://bugzilla.samba.org/show_bug.cgi?id=15089
auto flags = SMBC_XATTR_FLAG_REPLACE | SMBC_XATTR_FLAG_CREATE;
const QByteArray ace = aceString.toUtf8();
int result = smbc_setxattr(url.toSmbcUrl(), qUtf8Printable(attr), ace.constData(), ace.size(), flags);
if (const auto error = errno; result < 0) {
qCDebug(KIO_SMB_LOG) << "smbc_setxattr" << result << strerror(error);
return WorkerResult::fail(ERR_INTERNAL, strerror(error));
}
return WorkerResult::pass();
}
// TODO: rename this file _special instead of _mount. Or better yet: stop having multiple cpp files for the same class.
KIO::WorkerResult SMBWorker::special(const QByteArray &data)
{
qCDebug(KIO_SMB_LOG) << "Smb::special()";
int tmp;
......@@ -140,8 +212,13 @@ WorkerResult SMBWorker::special(const QByteArray &data)
return WorkerResult::fail(KIO::ERR_CANNOT_RMDIR, mountPoint);
}
}
} break;
case 0xAC: { // ACL
return getACE(stream);
}
case 0xACD: { // setACE
return setACE(stream);
}
break;
default:
break;
}
......
Supports Markdown
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