Skip to content

Commit

Permalink
HPCC-30037 Check legacy DZ physical permission in ESP services
Browse files Browse the repository at this point in the history
1. In the getDZPathScopePermissions(), add code to check legacy
physical permission.
2. Pass the permission requirement to getDZPathScopePermissions().
Check legacy physical permission when Plane Scope permission does
not meet the requirement.
3. Pass the host to getDZPathScopePermissions() in order to check
legacy physical permission.
4. When DZ name is not found, the getDZPathScopePermissions() is
called to check legacy physical permission.

Signed-off-by: wangkx <[email protected]>
  • Loading branch information
wangkx committed Aug 8, 2023
1 parent e3e40de commit 8f42dbd
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 40 deletions.
4 changes: 2 additions & 2 deletions esp/services/ws_fs/ws_fsBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ int CFileSpraySoapBindingEx::downloadFile(IEspContext &context, CHttpRequest* re

if (!validateDropZoneHostAndPath(dropZoneName, netAddressStr, pathStr)) //The pathStr should be the absolute path for the dropzone.
throw makeStringException(ECLWATCH_INVALID_INPUT, "Invalid DropZoneName, NetAddress or Path.");
SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, pathStr, netAddressStr);
SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, pathStr, netAddressStr, SecAccess_Read);
if (permission < SecAccess_Read)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s %s not allowed for user %s (permission:%s). Read Access Required.",
dropZoneName.str(), netAddressStr.str(), pathStr.str(), context.queryUserId(), getSecAccessFlagName(permission));
Expand Down Expand Up @@ -465,7 +465,7 @@ int CFileSpraySoapBindingEx::onStartUpload(IEspContext& ctx, CHttpRequest* reque
request->getParameter("DropZoneName", dropZoneName);
if (!validateDropZoneHostAndPath(dropZoneName, netAddress, path)) //The path should be the absolute path for the dropzone.
throw makeStringException(ECLWATCH_INVALID_INPUT, "Invalid DropZoneName, NetAddress or Path.");
SecAccessFlags permission = getDZPathScopePermissions(ctx, dropZoneName, path, netAddress);
SecAccessFlags permission = getDZPathScopePermissions(ctx, dropZoneName, path, netAddress, SecAccess_Full);
if (permission < SecAccess_Full)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s %s not allowed for user %s (permission:%s). Full Access Required.",
dropZoneName.str(), netAddress.str(), path.str(), ctx.queryUserId(), getSecAccessFlagName(permission));
Expand Down
52 changes: 22 additions & 30 deletions esp/services/ws_fs/ws_fsService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2013,15 +2013,12 @@ void CFileSprayEx::readAndCheckSpraySourceReq(IEspContext& context, MemoryBuffer
}
}

if (dropZone)
{
//Based on the tests, the dfuserver only supports the wildcard inside the file name, like '/path/f*'.
//The dfuserver throws an error if the wildcard is inside the path, like /p*ath/file.
SecAccessFlags permission = getDZFileScopePermissions(context, sourcePlaneReq, path, nullptr);
if (permission < SecAccess_Read)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). Read Access Required.",
sourcePlaneReq.str(), path, context.queryUserId(), getSecAccessFlagName(permission));
}
//Based on the tests, the dfuserver only supports the wildcard inside the file name, like '/path/f*'.
//The dfuserver throws an error if the wildcard is inside the path, like /p*ath/file.
SecAccessFlags permission = getDZFileScopePermissions(context, sourcePlaneReq, path, sourceIPReq, SecAccess_Read);
if (permission < SecAccess_Read)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). Read Access Required.",
sourcePlaneReq.str(), path, context.queryUserId(), getSecAccessFlagName(permission));

if (!sourcePathReq.isEmpty())
sourcePathReq.append(",");
Expand Down Expand Up @@ -2566,7 +2563,7 @@ bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDespray
if (!isEmptyString(destPlane)) // must be true, unless bare-metal and isDropZoneRestrictionEnabled()==false
getDropZoneInfoByDestPlane(version, destPlane, destfile, destfileWithPath, umask, destip);

SecAccessFlags permission = getDZFileScopePermissions(context, destPlane, destfileWithPath, destip);
SecAccessFlags permission = getDZFileScopePermissions(context, destPlane, destfileWithPath, destip, SecAccess_Write);
if (permission < SecAccess_Write)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). Write Access Required.",
isEmptyString(destPlane) ? destip : destPlane, destfileWithPath.str(), context.queryUserId(), getSecAccessFlagName(permission));
Expand Down Expand Up @@ -3010,13 +3007,11 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
StringBuffer dzName;
if (isEmptyString(dropZoneName))
dropZoneName = findDropZonePlaneName(netaddr, sPath, dzName);
if (!isEmptyString(dropZoneName))
{
SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, sPath, nullptr);
if (permission < SecAccess_Read)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). Read Access Required.",
dropZoneName, sPath.str(), context.queryUserId(), getSecAccessFlagName(permission));
}

SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, sPath, netaddr, SecAccess_Read);
if (permission < SecAccess_Read)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). Read Access Required.",
dropZoneName, sPath.str(), context.queryUserId(), getSecAccessFlagName(permission));

StringArray hosts;
if (isEmptyString(netaddr))
Expand Down Expand Up @@ -3123,7 +3118,7 @@ void CFileSprayEx::addPhysicalFile(IEspContext& context, IDirectoryIterator* di,
bool CFileSprayEx::searchDropZoneFiles(IEspContext& context, const char* dropZoneName, const char* server,
const char* dir, const char* relDir, const char* nameFilter, IArrayOf<IConstPhysicalFileStruct>& files, unsigned& filesFound)
{
if (getDZPathScopePermissions(context, dropZoneName, dir, server) < SecAccess_Read)
if (getDZPathScopePermissions(context, dropZoneName, dir, server, SecAccess_Read) < SecAccess_Read)
return false;

RemoteFilename rfn;
Expand Down Expand Up @@ -3341,10 +3336,10 @@ void CFileSprayEx::getPhysicalFiles(IEspContext &context, const char *dropZoneNa
if (!di->isDir() && (directoryOnly || (!isEmptyString(fileNameMask) && !WildMatch(fileName.str(), fileNameMask, true))))
continue;

if (dropZoneName && di->isDir())
if (di->isDir())
{
VStringBuffer fullPath("%s%s", path, fileName.str());
if (getDZPathScopePermissions(context, dropZoneName, fullPath, nullptr) < SecAccess_Read)
if (getDZPathScopePermissions(context, dropZoneName, fullPath, host, SecAccess_Read) < SecAccess_Read)
continue;
}

Expand Down Expand Up @@ -3455,7 +3450,7 @@ bool CFileSprayEx::onDropZoneFiles(IEspContext &context, IEspDropZoneFilesReques
StringBuffer planeName;
if (isEmptyString(dzName))
dzName = findDropZonePlaneName(netAddress, directoryStr, planeName);
if (!isEmptyString(dzName) && getDZPathScopePermissions(context, dzName, directoryStr, nullptr) < SecAccess_Read)
if (getDZPathScopePermissions(context, dzName, directoryStr, netAddress, SecAccess_Read) < SecAccess_Read)
return false;

bool directoryOnly = req.getDirectoryOnly();
Expand Down Expand Up @@ -3604,13 +3599,11 @@ void CFileSprayEx::checkDropZoneFileScopeAccess(IEspContext &context, const char
StringBuffer dzName;
if (isEmptyString(dropZoneName))
dropZoneName = findDropZonePlaneName(netAddress, dropZonePath, dzName);
if (!isEmptyString(dropZoneName))
{
SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, dropZonePath, nullptr);
if (permission < accessReq)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). %s Permission Required.",
dropZoneName, dropZonePath, context.queryUserId(), getSecAccessFlagName(permission), accessReqName);
}

SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, dropZonePath, netAddress, accessReq);
if (permission < accessReq)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). %s Permission Required.",
dropZoneName, dropZonePath, context.queryUserId(), getSecAccessFlagName(permission), accessReqName);

RemoteFilename rfn;
SocketEndpoint ep(netAddress);
Expand Down Expand Up @@ -3651,8 +3644,7 @@ void CFileSprayEx::checkDropZoneFileScopeAccess(IEspContext &context, const char

StringBuffer fullPath(dropZonePath);
addPathSepChar(fullPath).append(pathToCheck);
//If the dropzone name is not found, the DZPathScopePermissions cannot be validated.
SecAccessFlags permission = isEmptyString(dropZoneName) ? accessReq : getDZPathScopePermissions(context, dropZoneName, fullPath, nullptr);
SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, fullPath, netAddress, accessReq);
if (permission < accessReq)
{
uniquePath.setValue(pathToCheck.str(), false); //add a path denied
Expand Down
56 changes: 50 additions & 6 deletions esp/smc/SMCLib/TpCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,37 @@ static SecAccessFlags getDropZoneScopePermissions(IEspContext& context, const IP
return queryDistributedFileDirectory().getDropZoneScopePermissions(dropZone->queryProp("@name"), dropZonePath, userDesc);
}

extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost)
static SecAccessFlags verifyLegacyPhysicalPerms(IEspContext& context, const char* dropZoneName, const char* dropZoneHost, const char* dropZoneScope)
{
Owned<IUserDescriptor> userDesc = createUserDescriptor();
userDesc->set(context.queryUserId(), context.queryPassword(), context.querySignature());

StringBuffer host;
if (isEmptyString(dropZoneHost))
{
Owned<IPropertyTree> plane = getDropZonePlane(dropZoneName);
if (getPlaneHost(host, plane, 0))
dropZoneHost = host.str();
else
dropZoneHost = "localhost";
}

//The setExternal() requests the path with a file name. The file name is not used by the getDLFNPermissions().
//So, the dropZoneScope + a faked file name is passed to the setExternal().
StringBuffer pathWithFakedFileName(dropZoneScope);
addPathSepChar(pathWithFakedFileName).append("any");

CDfsLogicalFileName dlfn;
SocketEndpoint ep(dropZoneHost);
dlfn.setExternal(ep, pathWithFakedFileName);
return queryDistributedFileDirectory().getDLFNPermissions(dlfn, userDesc);
}

extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath,
const char* dropZoneHost, SecAccessFlags permissionReq)
{
if (isEmptyString(dropZoneName) && isEmptyString(dropZoneHost))
throw makeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "getDZPathScopePermissions(): DropZone name or host must be specified.");
if (isEmptyString(dropZonePath))
throw makeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "getDZPathScopePermissions(): DropZone path must be specified.");

Expand All @@ -208,7 +237,9 @@ extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& conte
if (!dropZone)
{
throwOrLogDropZoneLookUpError(ECLWATCH_INVALID_INPUT, "getDZPathScopePermissions(): DropZone %s not found.", dropZoneName);
return SecAccess_Full;
if (!getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms", !isContainerized()))
return SecAccess_Full;
return verifyLegacyPhysicalPerms(context, dropZoneName, dropZoneHost, dropZonePath);
}
}
else
Expand All @@ -218,16 +249,29 @@ extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& conte
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "getDZPathScopePermissions(): DropZone %s not found.", dropZoneName);
}

return getDropZoneScopePermissions(context, dropZone, dropZonePath);
SecAccessFlags permission = getDropZoneScopePermissions(context, dropZone, dropZonePath);
if ((permission < permissionReq) && getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms", !isContainerized()))
{
StringBuffer fileNameWithAbsPath;
if (!isAbsolutePath(dropZonePath))
{ //Only happens when this is called by the validateDropZoneAccess(). In the validateDropZoneAccess(),
//the dropZone is always available. Now, convert the dropZonePath to absolute path.
addPathSepChar(fileNameWithAbsPath.set(dropZone->queryProp("@prefix"))).append(dropZonePath);
dropZonePath = fileNameWithAbsPath.str();
}
permission = verifyLegacyPhysicalPerms(context, dropZoneName, dropZoneHost, dropZonePath);
}

return permission;
}

extern TPWRAPPER_API SecAccessFlags getDZFileScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath,
const char* dropZoneHost)
const char* dropZoneHost, SecAccessFlags permissionReq)
{
StringBuffer dir, fileName;
splitFilename(dropZonePath, &dir, &dir, nullptr, nullptr);
dropZonePath = dir.str();
return getDZPathScopePermissions(context, dropZoneName, dropZonePath, dropZoneHost);
return getDZPathScopePermissions(context, dropZoneName, dropZonePath, dropZoneHost, permissionReq);
}

extern TPWRAPPER_API void validateDropZoneAccess(IEspContext& context, const char* targetDZNameOrHost, const char* hostReq, SecAccessFlags permissionReq,
Expand All @@ -245,7 +289,7 @@ extern TPWRAPPER_API void validateDropZoneAccess(IEspContext& context, const cha
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Host %s is not valid DropZone plane %s", hostReq, targetDZNameOrHost);
}
const char *dropZoneName = dropZone->queryProp("@name");
SecAccessFlags permission = getDZFileScopePermissions(context, dropZoneName, fileNameWithRelPath, hostReq);
SecAccessFlags permission = getDZFileScopePermissions(context, dropZoneName, fileNameWithRelPath, hostReq, permissionReq);
if (permission < permissionReq)
throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). %s Access Required.",
dropZoneName, fileNameWithRelPath, context.queryUserId(), getSecAccessFlagName(permission), getSecAccessFlagName(permissionReq));
Expand Down
4 changes: 2 additions & 2 deletions esp/smc/SMCLib/TpWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ extern TPWRAPPER_API bool matchNetAddressRequest(const char* netAddressReg, bool

extern TPWRAPPER_API StringBuffer &findDropZonePlaneName(const char* host, const char* path, StringBuffer& planeName);
extern TPWRAPPER_API bool validateDropZoneHostAndPath(const char* dropZoneName, const char* hostToCheck, const char* pathToCheck);
extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost);
extern TPWRAPPER_API SecAccessFlags getDZFileScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost);
extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost, SecAccessFlags permissionReq);
extern TPWRAPPER_API SecAccessFlags getDZFileScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost, SecAccessFlags permissionReq);
extern TPWRAPPER_API void validateDropZoneAccess(IEspContext& context, const char* targetDZNameOrHost, const char* hostReq, SecAccessFlags permissionReq,
const char* fileNameWithRelPath, CDfsLogicalFileName& dlfn);

Expand Down

0 comments on commit 8f42dbd

Please sign in to comment.