diff --git a/dali/base/dadfs.cpp b/dali/base/dadfs.cpp index fece27870fc..3bd45dd497e 100644 --- a/dali/base/dadfs.cpp +++ b/dali/base/dadfs.cpp @@ -1181,6 +1181,7 @@ protected: friend class CDistributedFile; IDistributedSuperFile *lookupSuperFile(const char *logicalname, IUserDescriptor *user, AccessMode accessMode, IDistributedFileTransaction *transaction, unsigned timeout=INFINITE); SecAccessFlags getFilePermissions(const char *lname,IUserDescriptor *user,unsigned auditflags); + SecAccessFlags getFScopePermissions(const char *scope,IUserDescriptor *user,unsigned auditflags); SecAccessFlags getNodePermissions(const IpAddress &ip,IUserDescriptor *user,unsigned auditflags); SecAccessFlags getFDescPermissions(IFileDescriptor *,IUserDescriptor *user,unsigned auditflags=0); SecAccessFlags getDLFNPermissions(CDfsLogicalFileName &dlfn,IUserDescriptor *user,unsigned auditflags=0); @@ -11889,6 +11890,11 @@ SecAccessFlags CDistributedFileDirectory::getDropZoneScopePermissions(const char return getScopePermissions(dlfn.get(),user,auditflags); } +SecAccessFlags CDistributedFileDirectory::getFScopePermissions(const char *scope,IUserDescriptor *user,unsigned auditflags) +{ + return getScopePermissions(scope,user,auditflags); +} + void CDistributedFileDirectory::setDefaultUser(IUserDescriptor *user) { if (user) diff --git a/dali/base/dadfs.hpp b/dali/base/dadfs.hpp index 71e29bd750a..813509ee022 100644 --- a/dali/base/dadfs.hpp +++ b/dali/base/dadfs.hpp @@ -642,6 +642,7 @@ interface IDistributedFileDirectory: extends IInterface virtual void removeSuperFile(const char *_logicalname, bool delSubs=false, IUserDescriptor *user=NULL, IDistributedFileTransaction *transaction=NULL)=0; virtual SecAccessFlags getFilePermissions(const char *lname,IUserDescriptor *user,unsigned auditflags=0)=0; // see dasess for auditflags values + virtual SecAccessFlags getFScopePermissions(const char *scope,IUserDescriptor *user,unsigned auditflags=0)=0; // see dasess for auditflags values virtual void setDefaultUser(IUserDescriptor *user)=0; virtual IUserDescriptor* queryDefaultUser()=0; virtual SecAccessFlags getNodePermissions(const IpAddress &ip,IUserDescriptor *user,unsigned auditflags=0)=0; diff --git a/dali/dfu/dfurun.cpp b/dali/dfu/dfurun.cpp index 991148ccd47..48941717df8 100644 --- a/dali/dfu/dfurun.cpp +++ b/dali/dfu/dfurun.cpp @@ -668,7 +668,6 @@ class CDFUengine: public CInterface, implements IDFUengine auditflags |= DALI_LDAP_WRITE_WANTED; SecAccessFlags perm; - bool checkLegacyPhysicalPerms = getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms",!isContainerized()); IClusterInfo *iClusterInfo = fd->queryClusterNum(0); const char *planeName = iClusterInfo->queryGroupName(); if (!isEmptyString(planeName)) @@ -685,17 +684,19 @@ class CDFUengine: public CInterface, implements IDFUengine throw makeStringExceptionV(-1,"Invalid DropZone directory %s.",dir); perm = queryDistributedFileDirectory().getDropZoneScopePermissions(planeName,relativePath,user,auditflags); - if (((!write&&!HASREADPERMISSION(perm))||(write&&!HASWRITEPERMISSION(perm)))&&checkLegacyPhysicalPerms) - perm = queryDistributedFileDirectory().getFDescPermissions(fd,user,auditflags); + if (((!write&&!HASREADPERMISSION(perm))||(write&&!HASWRITEPERMISSION(perm)))) + { + if (getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms",!isContainerized())) + perm = queryDistributedFileDirectory().getFDescPermissions(fd,user,auditflags); + } } else { #ifndef _CONTAINERIZED Owned factory = getEnvironmentFactory(true); Owned env = factory->openEnvironment(); - if (env->isDropZoneRestrictionEnabled()||!checkLegacyPhysicalPerms) + if (env->isDropZoneRestrictionEnabled()) throw makeStringException(-1,"Empty plane name."); - perm = queryDistributedFileDirectory().getFDescPermissions(fd,user,auditflags); #else throw makeStringException(-1,"Unexpected empty plane name."); // should never be the case in containerized setups #endif diff --git a/esp/services/ws_fs/ws_fsBinding.cpp b/esp/services/ws_fs/ws_fsBinding.cpp index 353c591f245..f64b89286d0 100644 --- a/esp/services/ws_fs/ws_fsBinding.cpp +++ b/esp/services/ws_fs/ws_fsBinding.cpp @@ -410,16 +410,11 @@ int CFileSpraySoapBindingEx::downloadFile(IEspContext &context, CHttpRequest* re if (!osStr.isEmpty() && (atoi(osStr.str())== OS_WINDOWS)) pathSep = '\\'; pathStr.replace(pathSep=='\\'?'/':'\\', pathSep); - addPathSepChar(pathStr); - 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); - 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)); + validateDropZoneReq(context, dropZoneName, netAddressStr, pathStr, SecAccess_Read); StringBuffer fullName; + addPathSepChar(pathStr); fullName.appendf("%s%s", pathStr.str(), nameStr.str()); StringBuffer headerStr("attachment;"); @@ -463,13 +458,7 @@ int CFileSpraySoapBindingEx::onStartUpload(IEspContext& ctx, CHttpRequest* reque request->getParameter("NetAddress", netAddress); request->getParameter("Path", path); 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); - 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)); - + validateDropZoneReq(ctx, dropZoneName, netAddress, path, SecAccess_Full); return EspHttpBinding::onStartUpload(ctx, request, response, serv, method); } diff --git a/esp/services/ws_fs/ws_fsService.cpp b/esp/services/ws_fs/ws_fsService.cpp index 9f59f53b92a..ef7cb765ac7 100644 --- a/esp/services/ws_fs/ws_fsService.cpp +++ b/esp/services/ws_fs/ws_fsService.cpp @@ -2036,10 +2036,7 @@ void CFileSprayEx::readAndCheckSpraySourceReq(IEspContext& context, MemoryBuffer { //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)); + validateDZFileScopePermsAndLegacyPhysicalPerms(context, sourcePlaneReq, path, sourceIPReq, SecAccess_Read); } if (!sourcePathReq.isEmpty()) @@ -2585,10 +2582,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); - if (permission < SecAccess_Write) - throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). Write Access Required.", - destPlane, destfileWithPath.str(), context.queryUserId(), getSecAccessFlagName(permission)); + validateDZFileScopePermsAndLegacyPhysicalPerms(context, destPlane, destfileWithPath, destip, SecAccess_Write); } else destfileWithPath.append(destfile).trim(); @@ -3029,23 +3023,18 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE } else { - StringBuffer dzName; - if (isEmptyString(dropZoneName)) - dropZoneName = findDropZonePlaneName(netaddr, sPath, dzName); - if (!isEmptyString(dropZoneName)) + Owned dropZone = getDropZoneAndValidateHostAndPath(dropZoneName, netaddr, sPath); + if (dropZone) // In bare-metal and isDropZoneRestrictionEnabled()==false, the dropZone may be nullptr. { - 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)); + if (isEmptyString(dropZoneName)) + dropZoneName = dropZone->queryProp("@name"); + validateDZPathScopePermsAndLegacyPhysicalPerms(context, dropZoneName, sPath, netaddr, SecAccess_Read); } StringArray hosts; if (isEmptyString(netaddr)) - { - Owned dropZone = getDropZonePlane(dropZoneName); - if (!dropZone) - throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Unknown landing zone: %s", dropZoneName); + { // If the netaddr is empty, the dropZoneName will not be empty and the dropZone should be + // set by the getDropZoneAndValidateHostAndPath(). getPlaneHosts(hosts, dropZone); if (!hosts.ordinality()) hosts.append("localhost"); @@ -3055,9 +3044,7 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE ForEachItemIn(i, hosts) { - const char* host = hosts.item(i); - if (validateDropZoneHostAndPath(dropZoneName, host, sPath)) - getPhysicalFiles(context, dropZoneName, host, sPath, fileNameMask, directoryOnly, files); + getPhysicalFiles(context, dropZoneName, hosts.item(i), sPath, fileNameMask, directoryOnly, files); } } @@ -3145,7 +3132,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 (getDZPathScopePermsAndLegacyPhysicalPerms(context, dropZoneName, dir, server, SecAccess_Read) < SecAccess_Read) return false; RemoteFilename rfn; @@ -3366,7 +3353,7 @@ void CFileSprayEx::getPhysicalFiles(IEspContext &context, const char *dropZoneNa if (dropZoneName && di->isDir()) { VStringBuffer fullPath("%s%s", path, fileName.str()); - if (getDZPathScopePermissions(context, dropZoneName, fullPath, nullptr) < SecAccess_Read) + if (getDZPathScopePermsAndLegacyPhysicalPerms(context, dropZoneName, fullPath, host, SecAccess_Read) < SecAccess_Read) continue; } @@ -3477,7 +3464,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 (!isEmptyString(dzName) && (getDZPathScopePermsAndLegacyPhysicalPerms(context, dzName, directoryStr, netAddress, SecAccess_Read) < SecAccess_Read)) return false; bool directoryOnly = req.getDirectoryOnly(); @@ -3627,12 +3614,7 @@ void CFileSprayEx::checkDropZoneFileScopeAccess(IEspContext &context, const char 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); - } + validateDZPathScopePermsAndLegacyPhysicalPerms(context, dropZoneName, dropZonePath, netAddress, accessReq); RemoteFilename rfn; SocketEndpoint ep(netAddress); @@ -3674,7 +3656,8 @@ 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 = isEmptyString(dropZoneName) ? accessReq + : getDZPathScopePermsAndLegacyPhysicalPerms(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..dfe5abad996 100644 --- a/esp/smc/SMCLib/TpCommon.cpp +++ b/esp/smc/SMCLib/TpCommon.cpp @@ -148,33 +148,38 @@ StringBuffer &findDropZonePlaneName(const char *host, const char *path, StringBu return planeName; } -extern TPWRAPPER_API bool validateDropZoneHostAndPath(const char* dropZoneName, const char* hostToCheck, const char* pathToCheck) -{ - //Both hostToCheck and pathToCheck should not be empty. For backward compatibility, the dropZoneName may be empty. - if (isEmptyString(hostToCheck)) - throw makeStringException(ECLWATCH_INVALID_INPUT, "Host not defined."); - if (isEmptyString(pathToCheck)) - throw makeStringException(ECLWATCH_INVALID_INPUT, "Path not defined."); - if (isContainerized() && streq("localhost", hostToCheck)) - hostToCheck = nullptr; // "localhost" is a placeholder for mounted dropzones that have no hosts. - if (isEmptyString(hostToCheck) && isEmptyString(dropZoneName)) - throw makeStringException(ECLWATCH_INVALID_INPUT, "No dropzone or host provided."); +//If the dropZoneName is empty, find out the dropzone based on the host and path. In bare-metal and +//isDropZoneRestrictionEnabled()==false, the dropzone may not be found. +//If the dropZoneName is not empty, find out the dropzone based on the dropZoneName and validate the host and path. +extern TPWRAPPER_API IPropertyTree* getDropZoneAndValidateHostAndPath(const char* dropZoneName, const char* host, const char* path) +{ + StringBuffer pathToCheck(path); + addPathSepChar(pathToCheck); - if (containsRelPaths(pathToCheck)) //Detect a path like: /home/lexis/runtime/var/lib/HPCCSystems/mydropzone/../../../ - throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Invalid path %s", pathToCheck); + const char* hostToCheck = nullptr; + if (isContainerized() && strsame(host, "localhost")) + hostToCheck = nullptr; // "localhost" is a placeholder for mounted dropzones that have no hosts. + else + hostToCheck = host; - StringBuffer path(pathToCheck); - addPathSepChar(path); + Owned dropZone; if (isEmptyString(dropZoneName)) { - Owned plane = findDropZonePlane(path, hostToCheck, isIPAddress(hostToCheck), false); - return nullptr != plane; + dropZone.setown(findDropZonePlane(pathToCheck, hostToCheck, isIPAddress(hostToCheck), false)); + if (!dropZone) + throwOrLogDropZoneLookUpError(ECLWATCH_INVALID_INPUT, "DropZone not found for host '%s' path '%s'.", + isEmptyString(host) ? "unspecified" : host, isEmptyString(path) ? "unspecified" : path); + } + else + { + dropZone.setown(getDropZonePlane(dropZoneName)); + if (!dropZone) + throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DropZone '%s' not found.", dropZoneName); + if (!validateDropZone(dropZone, pathToCheck, hostToCheck, isIPAddress(hostToCheck))) + throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "The host '%s' or path '%s' is not valid for dropzone %s.", + isEmptyString(host) ? "unspecified" : host, isEmptyString(path) ? "unspecified" : path, dropZoneName); } - - Owned plane = getDropZonePlane(dropZoneName); - if (nullptr == plane) - return false; - return validateDropZone(plane, path, hostToCheck, isIPAddress(hostToCheck)); + return dropZone.getClear(); } static SecAccessFlags getDropZoneScopePermissions(IEspContext& context, const IPropertyTree* dropZone, const char* dropZonePath) @@ -196,7 +201,7 @@ 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 getDZPathScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost) { if (isEmptyString(dropZonePath)) throw makeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "getDZPathScopePermissions(): DropZone path must be specified."); @@ -207,7 +212,8 @@ extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& conte dropZone.setown(findDropZonePlane(dropZonePath, dropZoneHost, true, false)); if (!dropZone) { - throwOrLogDropZoneLookUpError(ECLWATCH_INVALID_INPUT, "getDZPathScopePermissions(): DropZone %s not found.", dropZoneName); + throwOrLogDropZoneLookUpError(ECLWATCH_INVALID_INPUT, "getDZPathScopePermissions(): DropZone not found for host '%s' path '%s'.", + isEmptyString(dropZoneHost) ? "unspecified" : dropZoneHost, isEmptyString(dropZonePath) ? "unspecified" : dropZonePath); return SecAccess_Full; } } @@ -221,7 +227,7 @@ extern TPWRAPPER_API SecAccessFlags getDZPathScopePermissions(IEspContext& conte return getDropZoneScopePermissions(context, dropZone, dropZonePath); } -extern TPWRAPPER_API SecAccessFlags getDZFileScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, +static SecAccessFlags getDZFileScopePermissions(IEspContext& context, const char* dropZoneName, const char* dropZonePath, const char* dropZoneHost) { StringBuffer dir, fileName; @@ -230,6 +236,104 @@ extern TPWRAPPER_API SecAccessFlags getDZFileScopePermissions(IEspContext& conte return getDZPathScopePermissions(context, dropZoneName, dropZonePath, dropZoneHost); } +static SecAccessFlags getLegacyDZPhysicalPerms(IEspContext& context, const char* dropZoneName, const char* dropZoneHost, + const char* dropZoneFile, bool isPath) +{ + if (isEmptyString(dropZoneHost) && isEmptyString(dropZoneName)) + throw makeStringException(ECLWATCH_INVALID_INPUT, "Neither dropzone plane or host specified."); + + 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"; + } + + CDfsLogicalFileName dlfn; + SocketEndpoint ep(dropZoneHost); + dlfn.setExternal(ep, dropZoneFile); + + StringBuffer scopes; + const char *scopesToCheck = nullptr; + if (isPath) + scopesToCheck = dlfn.get(); + else + { + dlfn.getScopes(scopes); + scopesToCheck = scopes; + } + return queryDistributedFileDirectory().getFScopePermissions(scopesToCheck, userDesc); +} + +//Get dropzone file permission for a dropzone file path (the path does NOT contain a file name). +//This function (and the validate functions below) calls the getDZPathScopePermissions(). In the +//getDZPathScopePermissions(), the isDropZoneRestrictionEnabled() will be used for bare-metal if +//a dropzone cannot be found based on host and path. +extern TPWRAPPER_API SecAccessFlags getDZPathScopePermsAndLegacyPhysicalPerms(IEspContext &context, const char *dropZoneName, const char *path, + const char *host, SecAccessFlags permissionReq) +{ + SecAccessFlags permission = getDZPathScopePermissions(context, dropZoneName, path, host); + if ((permission < permissionReq) && getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms", !isContainerized())) + permission = getLegacyDZPhysicalPerms(context, dropZoneName, host, path, true); + return permission; +} + +//Validate dropzone file permission for a dropzone file path (the path does NOT contain a file name) +extern TPWRAPPER_API void validateDZPathScopePermsAndLegacyPhysicalPerms(IEspContext &context, const char *dropZoneName, const char *path, + const char *host, SecAccessFlags permissionReq) +{ + SecAccessFlags permission = getDZPathScopePermsAndLegacyPhysicalPerms(context, dropZoneName, path, host, permissionReq); + if (permission < permissionReq) + throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone %s %s not allowed for user %s (permission:%s). Read Access Required.", + dropZoneName, path, context.queryUserId(), getSecAccessFlagName(permission)); +} + +//Validate dropzone file permission for a dropzone file path (the path DOES contain a file name) +extern TPWRAPPER_API void validateDZFileScopePermsAndLegacyPhysicalPerms(IEspContext& context, const char* dropZoneName, const char* path, + const char* host, SecAccessFlags permissionReq) +{ + SecAccessFlags permission = getDZFileScopePermissions(context, dropZoneName, path, host); + if ((permission < permissionReq) && getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms", !isContainerized())) + permission = getLegacyDZPhysicalPerms(context, dropZoneName, host, path, false); + if (permission < permissionReq) + throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone %s %s not allowed for user %s (permission:%s). %s permission Required.", + dropZoneName, path, context.queryUserId(), getSecAccessFlagName(permission), getSecAccessFlagName(permissionReq)); +} + +//This function is called when uploading a file to a dropzone or downloading a file to a dropzone. +//1. both host and filePath should not be empty. +//2. the filePath should not contain bad file path. +//3. call the getDropZoneAndValidateHostAndPath(). +//4. if the dropzone name is available, validate dropzone file permission. Should be available unless bare-metal and isDropZoneRestrictionEnabled()==false. +extern TPWRAPPER_API void validateDropZoneReq(IEspContext& ctx, const char* dropZoneName, const char* host, const char* filePath, SecAccessFlags permissionReq) +{ + if (isEmptyString(host) || isEmptyString(filePath)) //The host and filePath must be specified for accessing a DropZone file. + throw makeStringException(ECLWATCH_INVALID_INPUT, "Host or file path not defined."); + + if (containsRelPaths(filePath)) //Detect a path like: /home/lexis/runtime/var/lib/HPCCSystems/mydropzone/../../../ + throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Invalid path %s", filePath); + + Owned dropZone = getDropZoneAndValidateHostAndPath(dropZoneName, host, filePath); + if (dropZone) + dropZoneName = dropZone->queryProp("@name"); + + if (!isEmptyString(dropZoneName)) + validateDZPathScopePermsAndLegacyPhysicalPerms(ctx, dropZoneName, filePath, host, permissionReq); +} + +//This function is called when accessing a dropzone file from the WsFileIO service (the fileNameWithRelPath is a relative path). +//1. the targetDZNameOrHost could be a dropzone name or dropzone host. Find out the dropzone. +// If the targetDZNameOrHost is a dropzone name and the hostReq is not empty, validate the hostReq inside the dropzone. +// If the dropzone cannot be found based on the targetDZNameOrHost, throw an exception. +//2. the fileNameWithRelPath should not contain bad file path. +//3. validate dropzone file permission. +//4. set the dlfn using dropzone name and fileNameWithRelPath. extern TPWRAPPER_API void validateDropZoneAccess(IEspContext& context, const char* targetDZNameOrHost, const char* hostReq, SecAccessFlags permissionReq, const char* fileNameWithRelPath, CDfsLogicalFileName& dlfn) { @@ -246,8 +350,14 @@ extern TPWRAPPER_API void validateDropZoneAccess(IEspContext& context, const cha } const char *dropZoneName = dropZone->queryProp("@name"); SecAccessFlags permission = getDZFileScopePermissions(context, dropZoneName, fileNameWithRelPath, hostReq); + if ((permission < permissionReq) && getGlobalConfigSP()->getPropBool("expert/@failOverToLegacyPhysicalPerms", !isContainerized())) + { + StringBuffer fullPath(dropZone->queryProp("@prefix")); + addNonEmptyPathSepChar(fullPath).append(fileNameWithRelPath); + permission = getLegacyDZPhysicalPerms(context, dropZoneName, hostReq, fullPath, false); + } if (permission < permissionReq) - throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone Scope %s %s not allowed for user %s (permission:%s). %s Access Required.", + throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "Access DropZone %s %s not allowed for user %s (permission:%s). %s Access Required.", dropZoneName, fileNameWithRelPath, context.queryUserId(), getSecAccessFlagName(permission), getSecAccessFlagName(permissionReq)); dlfn.setPlaneExternal(dropZoneName, fileNameWithRelPath); } diff --git a/esp/smc/SMCLib/TpWrapper.hpp b/esp/smc/SMCLib/TpWrapper.hpp index bbc89ee91b0..3c68dd133c7 100644 --- a/esp/smc/SMCLib/TpWrapper.hpp +++ b/esp/smc/SMCLib/TpWrapper.hpp @@ -240,10 +240,14 @@ extern TPWRAPPER_API bool validateDataPlaneName(const char *remoteDali, const ch extern TPWRAPPER_API bool matchNetAddressRequest(const char* netAddressReg, bool ipReq, IConstTpMachine& tpMachine); 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 IPropertyTree* getDropZoneAndValidateHostAndPath(const char* dropZoneName, const char* host, const char* path); extern TPWRAPPER_API void validateDropZoneAccess(IEspContext& context, const char* targetDZNameOrHost, const char* hostReq, SecAccessFlags permissionReq, const char* fileNameWithRelPath, CDfsLogicalFileName& dlfn); +extern TPWRAPPER_API SecAccessFlags getDZPathScopePermsAndLegacyPhysicalPerms(IEspContext &context, const char *dropZoneName, const char *path, + const char *host, SecAccessFlags permissionReq); +extern TPWRAPPER_API void validateDZPathScopePermsAndLegacyPhysicalPerms(IEspContext &context, const char *dropZoneName, const char *path, + const char *host, SecAccessFlags permissionReq); +extern TPWRAPPER_API void validateDropZoneReq(IEspContext& ctx, const char* dropZoneName, const char* host, const char* path, SecAccessFlags permissionReq); +extern TPWRAPPER_API void validateDZFileScopePermsAndLegacyPhysicalPerms(IEspContext& context, const char* dropZoneName, const char* path, const char* host, SecAccessFlags permissionReq); #endif //_ESPWIZ_TpWrapper_HPP__