Threat level

From OpenSimulator

Jump to: navigation, search

To permit region owners to enable the extended scripting functionality of OSSL, without allowing malicious scripts to access potentially troublesome functions, each OSSL function is assigned a threat level, and access to the functions is granted or denied based on a default threshold set in OpenSim.ini (which can be overridden for individual functions on a case-by-case basis). Review OSSL Enabling Functions page with a full example for Implementing the various osFunctions for your system.

The threat levels, from wholly unthreatening to most potentially damaging, are:

None
Function is no threat at all. It doesn't constitute a threat to either users or the system and has no known side effects.
Functions with the threat level "None":
See Category:OSSL_Functions/ThreatLevel:None
Nuisance
Abuse of this command can cause a nuisance to the region operator, such as log message spew.
Functions with the threat level "Nuisance":
See Category:OSSL_Functions/ThreatLevel:Nuisance
VeryLow
Extreme levels of abuse of this function can cause impaired functioning of the region, or very gullible users can be tricked into experiencing harmless effects.
Functions with the threat level "VeryLow":
See Category:OSSL_Functions/ThreatLevel:VeryLow
Low
Intentional abuse can cause crashes or malfunction under certain circumstances, which can be easily rectified; or certain users can be tricked into certain situations in an avoidable manner.
Functions with the threat level "Low":
See Category:OSSL_Functions/ThreatLevel:Low
Moderate
Intentional abuse can cause denial of service and crashes with potential of data or state loss; or trusting users can be tricked into embarrassing or uncomfortable situations.
Functions with the threat level "Moderate":
See Category:OSSL_Functions/ThreatLevel:Moderate
High
Casual abuse can cause impaired functionality or temporary denial of service conditions. Intentional abuse can easily cause crashes with potential data loss, or can be used to trick experienced and cautious users into unwanted situations, or changes global data permanently and without undo ability.
Functions with the threat level "High":
See Category:OSSL_Functions/ThreatLevel:High
VeryHigh
Even normal use may, depending on the number of instances, or frequency of use, result in severe service impairment or crash with loss of data, or can be used to cause unwanted or harmful effects on users without giving the user a means to avoid it.
Functions with the threat level "VeryHigh":
See Category:OSSL_Functions/ThreatLevel:VeryHigh
Severe
Even casual use is a danger to region stability, or function allows console or OS command execution, or function allows taking money without consent, or allows deletion or modification of user data, or allows the compromise of sensitive data by design.
Functions with the threat level "Severe":
See Category:OSSL_Functions/ThreatLevel:Severe

The OSFunctionThreatLevel setting in the script engines' configuration sections of OpenSim.ini controls what classes of functions are accessible to scripts owned by any avatar; any function at the same threat level or lower than the value provided for OsFunctionThreatLevel is permitted to run. If OSFunctionThreatLevel is absent from the configuration file, the default value is VeryLow.

We do not recommend that you set a general level above Low unless you have a very high level of trust in all the visitors to the simulator that have the ability to run scripts.

It is safer to explicitly allow certain types of user to run higher threat level OSSL functions on an individual basis. This can be done by adding Allow_* lines to the script engine's configuration section. To permit scripts owned by anyone to access a function, even if its threat level exceeds the value of OSFunctionThreatLevel, use the value 'true':

Allow_osMakeNotecard = true

You can also prohibit individual OSSL functions, even if its threat level is equal to or below the value of OSFunctionThreatLevel:

Allow_osMovePen = false

To allow scripts owned by only certain avatars to access a function, use the UUIDs of the avatars owning the scripts. If multiple avatars are to be permitted access, separate the UUIDs with commas:

Allow_osMakeNotecard = a1cbbdd7-8adb-4158-aa52-c0ee882c4492
Allow_osTeleportAgent = a1cbbdd7-8adb-4158-aa52-c0ee882c4492,9cab27da-764c-4469-a628-369d978ba436

You can also allow categories of users to call given OSSL functions. Currently, the categories are

  • PARCEL_GROUP_MEMBER: allow if object group is the same group as the parcel
  • PARCEL_OWNER: allow if the object owner is parcel owner
  • ESTATE_MANAGER: allow if the object owner is an estate manager
  • ESTATE_OWNER: allow if object owner is estate owner

For example

Allow_osSetRegionWaterHeight = PARCEL_OWNER, ESTATE_OWNER

Note that wiki may not have the threat levels for some functions or have wrong threat levels. You can check actual threat levels by looking into OpenSim.Region.ScriptEngine.Shared.Api.OSSL_Api class in the source distribution or git master(see CheckThreatLevel() calling).


Ascertaining privilege to use a function

There is not currently a function which would allow a script to determine whether or not it has permission to use any specific OSSL function. Such a function was proposed, but rejected by a developer on the grounds that it could permit a griefer script too much knowledge of its environment (though, as shown below, this information is already available through other methods, albeit less efficient ones).

Leaving the question of griefer scripts aside, such knowledge is also useful to legitimate scripts (for instance, an animation vendor with a "Try me!" button, which might use osAvatarPlayAnimation() to demonstrate the animation without requiring the user to explicitly grant permission, but fall back to llStartAnimation() in the event that osAvatarPlayAnimation() is unavailable).

If a script attempts to use an OSSL function that it does not have permission to use, only the current invocation of the event handler which called the function crashes; the script remains running, and the event handler will be executed again the next time the event fires. A script may take advantage of this fact to ascertain which functions are available to it, by using an information-gathering state with a timer to iterate quickly through the OSSL functions it needs; when a function call succeeds, it can then set a variable indicating that the function is available. Once it has iterated through all the functions, it then switches out of the information-gathering state.

// OSSL Function Availability Tester
//
// Demonstrates a method by which a script may determine whether or not it is permitted to call
// various OSSL functions.
//
 
integer WhichProbeFunction; // to tell us which function we're probing
integer NumberOfFunctionsToCheck; // how many functions are we probing?
 
list FunctionNames = [
    "osTeleportAgent", 
    "osGetAgentIP", 
    "osGetAgents", 
    "osAvatarPlayAnimation",
    "osAvatarStopAnimation", 
    "osAvatarName2Key", 
    "osKey2Name"
];
 
list FunctionPermitted = [ 0, 0, 0, 0, 0, 0, 0 ]; // 0 = not permitted, 1 = permitted
 
 
// isFunctionAvailable() takes the name of a function, and returns 1 if it is available, 
// and 0 if it is forbidden or has not been tested.
 
integer isFunctionAvailable( string whichFunction )
{
    integer index = llListFindList( FunctionNames, whichFunction );
    if (index == -1) return 0; // Return FALSE if the function name wasn't one of the ones we checked.
    return llList2Integer( FunctionPermitted, index ); // return the appropriate availability flag.
}
 
// The default state uses the timer to call all the OSSL functions we're interested in using, in turn.
// If the function call fails, the timer event handler will abend, but the script doesn't crash. We can
// use this fact to check all of our desired functions in turn, and then pass control to the Running
// state once we've checked them all.
 
default
{
    state_entry()
    {
        llOwnerSay( "Probing OSSL functions to see what we can use" );
        NumberOfFunctionsToCheck = llGetListLength( FunctionNames );
        WhichProbeFunction = -1;
        llSetTimerEvent( 0.25 ); // check only four functions a second, just to be nice.
    }
 
    timer()
    {
        string BogusKey = "12345678-1234-1234-1234-123456789abc"; // it doesn't need to be valid
        string s; // for storing the result of string functions
        list l; // for storing the result of list functions
 
        if (++WhichProbeFunction == NumberOfFunctionsToCheck) // Increment WhichProbeFunction; exit if we're done
        {
            llSetTimerEvent( 0.0 ); // stop the timer
            state Running; // switch to the Running state
        }
 
        llOwnerSay( "Checking function " + llList2String( FunctionNames, WhichProbeFunction )); // say status
        if (WhichProbeFunction == 0)
            osTeleportAgent( BogusKey, ZERO_VECTOR, ZERO_VECTOR );
        else if (WhichProbeFunction == 1)
            s = osGetAgentIP( BogusKey );
        else if (WhichProbeFunction == 2)
            l = osGetAgents();
        else if (WhichProbeFunction == 3)
            osAvatarPlayAnimation( BogusKey, BogusKey );
        else if (WhichProbeFunction == 4)
            osAvatarStopAnimation( BogusKey, BogusKey );
        else if (WhichProbeFunction == 5)
            s = osAvatarName2Key( "John", "Smith" );
        else if (WhichProbeFunction == 6)
            s = osKey2Name( BogusKey );
 
        // If we got here, then the timer() handler didn't crash, which means the function it checked for
        // was actually permitted. So we update the list to indicate that we can use that particular function.
        FunctionPermitted = llListReplaceList( FunctionPermitted, [ 1 ], WhichProbeFunction, WhichProbeFunction );
    }
}
 
state Running
{
    state_entry()
    {
        string s = "Here are the functions we can use: ";
        string t = "Here are the functions we cannot use: ";
        integer i = llGetListLength( FunctionNames );
 
        while (i--)
            if (llList2Integer( FunctionPermitted, i ))
                s += llList2String( FunctionNames, i ) + " ";
            else
                t += llList2String( FunctionNames, i ) + " ";
 
        llOwnerSay( s );
        llOwnerSay( t );
 
        if (isFunctionAvailable( "osKey2Name" ))
        {
            key theUUID = "190482f8-b1bc-4c36-aa8d-cfb36c8fea61";
            llOwnerSay( "UUID " + (string) theUUID + " maps to the name " + osKey2Name( theUUID ) + "." );
        }
 
        else
        {
            llOwnerSay( "osKey2Name() is unavailable; cannot map UUID to name." );
        }
    }
}
Personal tools
General
About This Wiki