Log-in Detection with Attachments

Log-In Detection (LID™) provides a way to determine that the user has logged-in from a script contained in an attachment.

LID™ exploits event-handlers by noticing the following distinction:

  • when an object is attached from inventory, the id parameter of the attach event handler becomes the agent key of the avatar that the object attaches to.
  • when an object is detached, the id parameters of the attach event handler becomes the NULL_KEY.

When the object is detached, LID™ sets a flag (logon := -1) on a linked primitive using the key value data API marking whether the primitive has been attached or detached. A linked primitive is chosen because the root primitive is unable to retain its description once the object is detached. The key value data API is used for consistency but any custom implementation that is able to write to a linked-primitive's description will suffice.

When the object is attached or the avatar logs on, LID™ increments the flag (logon := logon + 1) and resets the script using llResetScript, thus:

  • if the value of the flag logon was -1 (meaning, previously detached), then the new value of logon becomes 0 and LID™ does not trigger.
  • if the value of the flag logon was 0 (meaning the script was previously running), then the new value of logon becomes 1 and LID™ runs.

Lastly, when the avatar logs out, the attach event does not run.

Security Implications

It should be noted that event handlers do not run atomically and may be interrupted on the avatar's whims. This means that LID™ is susceptible to race conditions (generally, the attach event handler is susceptible to race conditions (so is on_rez)). This can be verified by quickly attaching and detaching the object containing a LID™ script which may trigger LID™ when it is not supposed to. The implication for LID™ is that, on interruption of the attach event handler, the variable login may be set to:

  • $\ge 1$ - it is possible with timed attacks (attaching and detaching the object) to increase the value of the variable login beyond 1. This makes LID™ run again in state_entry.
  • $0$ - not allowing the attach handler to run at all which will trigger LID™ on the next attaching of the object.

Practical Applications using Logging-In Detection

  • QuickCollar℠ - the collar uses the default state to check whether RLV is enabled in the viewer and the RLV documentation states that scripts should pause for a certain amount of time (empirically, $\approx 30$ seconds) before querying the viewer (via llOwnerSay("@version=" + (string)_comChannel);) when the user logged-in in order to determine whether RLV is enabled. The judgment is made based on the fact that RLV may not yet be initialized when the avatar logs in. Although, one could choose to wait for 30 seconds every time the script is restarted, LID™ is used instead in order to pause for 30 seconds only when the user logs-in.

Generic LID™ Code

Note that resetting the script in the on_rez event handler is not necessary because the attach event handler resets the script instead - this applies only to worn objects.

//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
default {
    state_entry() {
        // LID™ reasoning - http://grimore.org/fuss:lsl#log-in_detection_with_attachments
        // if LID™, then login = 1
        // else login = 0 - script running | parameter undefined
        if((integer)wasKeyValueGet("login", llGetObjectDesc()) > 0) {
            llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", "0", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]);
            llOwnerSay("[LID™]: The user has logged-in wearing this object.");
        llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", "0", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]);
        llOwnerSay("[LID™]: The script was restarted.");
    // LID™ reasoning - http://grimore.org/fuss:lsl#log-in_detection_with_attachments
    // order: on_rez -> attach
    // if object attached, then login := login+1
    // else login := -1
    attach(key id) {
        // attached
        if(id != NULL_KEY && llGetAttached() != 0) {
            llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", (string)((integer)wasKeyValueGet("login", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))+1), llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]);
            // Reset script for llGetOwner() bugture.
        // detached
        llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet("login", "-1", llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))]);
    // login = 1 after object attached
    //       = -1 after object detached

secondlife/lid.txt · Last modified: 2017/02/22 18:19 (external edit)

Access website using Tor Access website using i2p

For the copyright, license, warranty and privacy terms for the usage of this website please see the license, privacy, data protection and copyright compliance.