diff --git a/docs/dictionary/property/secureMode.lcdoc b/docs/dictionary/property/secureMode.lcdoc index fd38b178d0e..632be5b8f3f 100644 --- a/docs/dictionary/property/secureMode.lcdoc +++ b/docs/dictionary/property/secureMode.lcdoc @@ -41,10 +41,17 @@ The application cannot access remote files with the URL . The If the application is started from a Unix or Windows command line, this property can be set to true on startup by using the -f option. +The application also can not use the command to load an extension +from a file or data. + >*Important:* Once the is set to true, it > cannot be set back to false. To change it back to true, you must quit > and restart the . +Changes: +In version 9.5 the loading of extensions was added to the secureMode +restrictions. + References: write to file (command), open file (command), put (command), launch (command), open process (command), read from file (command), get (command), function (control structure), shell (function), @@ -53,7 +60,7 @@ queryRegistry (function), property (glossary), stack file (glossary), Windows (glossary), web server (glossary), keyword (glossary), registry (glossary), function (glossary), command (glossary), application (glossary), file (keyword), securityPermissions (property), -securityCategories (property) +securityCategories (property), load extension (command) Tags: file system diff --git a/docs/dictionary/property/securityCategories.lcdoc b/docs/dictionary/property/securityCategories.lcdoc index 527edb1f71c..b7a080003c7 100644 --- a/docs/dictionary/property/securityCategories.lcdoc +++ b/docs/dictionary/property/securityCategories.lcdoc @@ -31,10 +31,15 @@ supported security categories. Returned values are: * doalternate - use of the 'do ... as ...' alternate language execution feature * external - loading externals + * extension - loading extensions from file or data. Extensions included when + building a standalone are not restricted. +Changes: +In version 9.5 the extension category was added to restrict loading of +extensions. References: launch (command), property (glossary), -securityPermissions (property), secureMode (property) +securityPermissions (property), secureMode (property), load extension (command) Tags: file system diff --git a/docs/dictionary/property/securityPermissions.lcdoc b/docs/dictionary/property/securityPermissions.lcdoc index 0a593cd40ef..8e414ab5c7e 100644 --- a/docs/dictionary/property/securityPermissions.lcdoc +++ b/docs/dictionary/property/securityPermissions.lcdoc @@ -41,14 +41,19 @@ delimited values for are: * doalternate - use of the 'do ... as ...' alternate language execution feature * external - loading externals - + * extension - loading extensions from file or data. Extensions included when + building a standalone are not restricted. Once is set, the security permissions can only be reduced and not increased. +Changes: +In version 9.5 the extension category was added to restrict loading of +extensions. + References: launch (command), empty (constant), files (function), property (glossary), application (glossary), web server (glossary), -securityCategories (property), secureMode (property) +securityCategories (property), secureMode (property), load extension (command) Tags: file system diff --git a/docs/notes/bugfix-21343.md b/docs/notes/bugfix-21343.md new file mode 100644 index 00000000000..b7a39790f48 --- /dev/null +++ b/docs/notes/bugfix-21343.md @@ -0,0 +1 @@ +# Add `extension` as a category to the `securityPermissions` property to restrict the `load extension` command \ No newline at end of file diff --git a/engine/src/exec-engine.cpp b/engine/src/exec-engine.cpp index eb96f9d22a8..f82979c06fb 100644 --- a/engine/src/exec-engine.cpp +++ b/engine/src/exec-engine.cpp @@ -102,6 +102,7 @@ static MCExecSetTypeElementInfo _kMCEngineSecurityCategoriesElementInfo[] = { "applescript", kMCSecureModeTypeApplescriptBit }, { "doalternate", kMCSecureModeTypeDoalternateBit }, { "external", kMCSecureModeTypeExternalBit }, + { "extension", kMCSecureModeTypeExtensionBit }, }; static MCExecSetTypeInfo _kMCEngineSecurityCategoriesTypeInfo = diff --git a/engine/src/exec-extension.cpp b/engine/src/exec-extension.cpp index 0df143c9933..0d7a071fa9d 100644 --- a/engine/src/exec-extension.cpp +++ b/engine/src/exec-extension.cpp @@ -225,6 +225,12 @@ void MCEngineAddExtensionsFromModulesArray(MCAutoScriptModuleRefArray& p_modules void MCEngineLoadExtensionFromData(MCExecContext& ctxt, MCDataRef p_extension_data, MCStringRef p_resource_path) { + if (!MCSecureModeCanAccessExtension()) + { + ctxt . SetTheResultToStaticCString("no permission to load module"); + return; + } + MCAutoScriptModuleRefArray t_modules; if (!MCScriptCreateModulesFromData(p_extension_data, t_modules)) { diff --git a/engine/src/securemode.cpp b/engine/src/securemode.cpp index 0560374a4aa..4f9ae63ae52 100644 --- a/engine/src/securemode.cpp +++ b/engine/src/securemode.cpp @@ -133,6 +133,11 @@ bool MCSecureModeCanAccessExternal(void) return ((MCsecuremode & MC_SECUREMODE_EXTERNAL) == 0); } +bool MCSecureModeCanAccessExtension(void) +{ + return ((MCsecuremode & MC_SECUREMODE_EXTENSION) == 0); +} + bool MCSecureModeCheckPrivacy(uint2 line, uint2 pos) { if ((MCsecuremode & MC_SECUREMODE_PRIVACY) == 0) diff --git a/engine/src/securemode.h b/engine/src/securemode.h index 9385c3dd342..3266dbfc761 100644 --- a/engine/src/securemode.h +++ b/engine/src/securemode.h @@ -30,6 +30,7 @@ enum MCSecureModeType kMCSecureModeTypeApplescriptBit, kMCSecureModeTypeDoalternateBit, kMCSecureModeTypeExternalBit, + kMCSecureModeTypeExtensionBit, }; #define MC_SECUREMODE_DISK (1 << kMCSecureModeTypeDiskBit) @@ -42,13 +43,14 @@ enum MCSecureModeType #define MC_SECUREMODE_APPLESCRIPT (1 << kMCSecureModeTypeApplescriptBit) #define MC_SECUREMODE_DOALTERNATE (1 << kMCSecureModeTypeDoalternateBit) #define MC_SECUREMODE_EXTERNAL (1 << kMCSecureModeTypeExternalBit) +#define MC_SECUREMODE_EXTENSION (1 << kMCSecureModeTypeExtensionBit) #define MC_SECUREMODE_ALL (MC_SECUREMODE_DISK | MC_SECUREMODE_NETWORK | MC_SECUREMODE_PROCESS \ | MC_SECUREMODE_REGISTRY_READ | MC_SECUREMODE_REGISTRY_WRITE \ | MC_SECUREMODE_PRINT | MC_SECUREMODE_PRIVACY | MC_SECUREMODE_APPLESCRIPT \ - | MC_SECUREMODE_DOALTERNATE | MC_SECUREMODE_EXTERNAL) + | MC_SECUREMODE_DOALTERNATE | MC_SECUREMODE_EXTERNAL | MC_SECUREMODE_EXTENSION) -#define MC_SECUREMODE_MODECOUNT (10) +#define MC_SECUREMODE_MODECOUNT (11) extern const char *MCsecuremode_strings[MC_SECUREMODE_MODECOUNT]; @@ -71,12 +73,14 @@ bool MCSecureModeCheckPrivacy(uint2 line = 0, uint2 pos = 0); bool MCSecureModeCheckAppleScript(uint2 line = 0, uint2 pos = 0); bool MCSecureModeCheckDoAlternate(uint2 line = 0, uint2 pos = 0); bool MCSecureModeCheckExternal(uint2 line = 0, uint2 pos = 0); +bool MCSecureModeCheckExtension(uint2 line = 0, uint2 pos = 0); bool MCSecureModeCanAccessDisk(void); bool MCSecureModeCanAccessNetwork(void); bool MCSecureModeCanAccessPrinter(void); bool MCSecureModeCanAccessDoAlternate(void); bool MCSecureModeCanAccessExternal(void); +bool MCSecureModeCanAccessExtension(void); // MW-2013-08-07: [[ Bug 10865 ]] New check method for whether AppleScript is // enabled. diff --git a/tests/lcs/core/security/_extension.lcb b/tests/lcs/core/security/_extension.lcb new file mode 100644 index 00000000000..db2511f70dc --- /dev/null +++ b/tests/lcs/core/security/_extension.lcb @@ -0,0 +1,9 @@ +library com.livecode.lcs_tests.core.security.extension + +use com.livecode.engine + +public handler TestCoreSecurityExtension() returns String + return "Foo" +end handler + +end library diff --git a/tests/lcs/core/security/securitypermissions.livecodescript b/tests/lcs/core/security/securitypermissions.livecodescript new file mode 100644 index 00000000000..bda7b91f211 --- /dev/null +++ b/tests/lcs/core/security/securitypermissions.livecodescript @@ -0,0 +1,40 @@ +script "CoreSecurityPermissions" +/* +Copyright (C) 2018 LiveCode Ltd. + +This file is part of LiveCode. + +LiveCode is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License v3 as published by the Free +Software Foundation. + +LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with LiveCode. If not see . */ + +on TestSetup + TestSkipIfNot "securityPermissions", "set" +end TestSetup + +on TestSecurityPermissionExtension + local tCategories + put the securityCategories into tCategories + TestAssert "default securityCategories contains extension", "extension" is among the items of tCategories + + filter items of tCategories without "extension" + set the securityPermissions to tCategories + TestAssert "extension can be removed from securityPermissions", the securityPermissions is tCategories + + local tError + try + TestLoadAuxiliaryExtension "_extension" + catch tError + -- TestLoadAuxiliaryExtension throws the result on failure + end try + TestAssert "load extension fails with no permission", tError is not empty + +end TestSecurityPermissionExtension \ No newline at end of file