diff --git a/esp/services/ws_fs/ws_fsBinding.cpp b/esp/services/ws_fs/ws_fsBinding.cpp index 353c591f245..daf99c0090b 100644 --- a/esp/services/ws_fs/ws_fsBinding.cpp +++ b/esp/services/ws_fs/ws_fsBinding.cpp @@ -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)); @@ -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)); diff --git a/esp/services/ws_fs/ws_fsService.cpp b/esp/services/ws_fs/ws_fsService.cpp index b4ffedc9bfa..845036c3960 100644 --- a/esp/services/ws_fs/ws_fsService.cpp +++ b/esp/services/ws_fs/ws_fsService.cpp @@ -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(","); @@ -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)); @@ -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)) @@ -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& 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; @@ -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; } @@ -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(); @@ -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); @@ -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 diff --git a/esp/smc/SMCLib/TpCommon.cpp b/esp/smc/SMCLib/TpCommon.cpp index 195c2f6e909..f8b0e3eed07 100644 --- a/esp/smc/SMCLib/TpCommon.cpp +++ b/esp/smc/SMCLib/TpCommon.cpp @@ -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 userDesc = createUserDescriptor(); + userDesc->set(context.queryUserId(), context.queryPassword(), context.querySignature()); + + StringBuffer host; + if (isEmptyString(dropZoneHost)) + { + Owned 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."); @@ -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 @@ -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, @@ -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)); diff --git a/esp/smc/SMCLib/TpWrapper.hpp b/esp/smc/SMCLib/TpWrapper.hpp index bbc89ee91b0..589fcb41c17 100644 --- a/esp/smc/SMCLib/TpWrapper.hpp +++ b/esp/smc/SMCLib/TpWrapper.hpp @@ -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);