Skip to content

Instantly share code, notes, and snippets.

@typhartez
Last active March 1, 2021 23:05
Show Gist options
  • Select an option

  • Save typhartez/b8de5abc4db9b87a268327de1e2d77b6 to your computer and use it in GitHub Desktop.

Select an option

Save typhartez/b8de5abc4db9b87a268327de1e2d77b6 to your computer and use it in GitHub Desktop.
Authorization reusable script
// Access reusable script: define authorizations from an access control list notecard
// Typhaine Artez 2021
// Under Creative Commons License Attribution-NonCommercial-ShareAlike 4.0 International
//
// Sample .access notecard (/* and */ are not part of the notecard content):
/*
# Authorization notecard. Empty lines or lines starting with # are ignored
# Without configuration, only the owner is allowed to use
# mode = group to enable everyone wearing the same group tag than the object
# mode = all to enable everyone
mode = group
mode = all
# Each line starts with allow or deny, the value determine who is concerned,
# with one of the following formats:
# @grid-name
# Everyone in that grid
# Firstname Lastname
# This avatar matching Firstname Lastname (any grid, case insensitive)
# 7a60dc25-0884-4474-9b0f-bf5844d34d80
# The avatar with this UUID
deny = @bad-grid.com:8002
deny = 7a60dc25-0884-4474-9b0f-bf5844d34d80
deny = Obvious Griefer
allow = Typhaine Artez
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
list acls; // authorization list (first item is mode ("O"=owner, "G"=group, "A"=all)
// followed by pairs of items: "A" for allow, "D" for deny, then the access definition
key nckey; // .access notecard (for automatic reload on notecard change)
integer ncline; // parse notecard
////////////////////////////////////////////////////////////////////////////////////////////////////
// Load Access Control List from notecard
// Returns TRUE if some data need to be read
integer reloadACLs(string data) {
if (EOF == data) {
llOwnerSay("Authorizations loaded.");
return FALSE;
}
if ("--START--" == data) {
nckey = llGetInventoryKey(".access");
if (NULL_KEY != nckey) {
acls = ["O"]; // by default, owner only
ncline = 0;
llGetNotecardLine(".access", ncline);
return TRUE;
}
// no ACLs used
acls = ["A"]; // by default, everyone
return FALSE;
}
if ("" != data && 0 != llSubStringIndex(data, "#")) {
// read data
integer sep = llSubStringIndex(data, "=");
if (~sep) {
string kw = llToLower(llStringTrim(llGetSubString(data, 0, sep-1), STRING_TRIM));
string val = llToLower(llStringTrim(llGetSubString(data, sep+1, -1), STRING_TRIM));
if ("mode" == kw) {
if ("all" == val) val = "A";
else if ("group" == val) val = "G";
else if ("owner" == val) val = "O";
else val = "";
if ("" != val) acls = llListReplaceList(acls, [val], 0, 0);
}
else if ("allow" == kw) acls += ["A", val];
else if ("deny" == kw) acls += ["D", val];
else llOwnerSay("Warning: unrecognized line: " + data);
}
}
// read next line
llGetNotecardLine(".access", ++ncline);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Returns TRUE if user key is allowed to operate
integer isAuthorized(key id) {
if (llGetOwner() == id) return TRUE; // owner always allowed
string mode = llList2String(acls, 0);
string type;
string auth;
string name = llToLower(osReplaceString(osReplaceString(llKey2Name(id), " ?@.*$", "", 1, 0), "\\.", " ", -1, 0));
integer pos;
integer n = llGetListLength(acls) - 2;
for (; 0 < n; n -= 2) {
type = llList2String(acls, n);
auth = llList2String(acls, n+1);
// check agent key, the faster
if (osIsUUID(auth) && id == (key)auth) return ("A" == type);
// normalize name first last (all lower case, without grid suffix, no dots)
auth = osReplaceString(osReplaceString(auth, " ?@.*$", "", 1, 0), "\\.", " ", -1, 0);
if (-1 != ~llSubStringIndex(name, auth)) return ("A" == type);
}
// not matched, check mode
if ("A" == mode || ("G" == mode && llSameGroup(id))) return TRUE;
return FALSE; // owner only
}
////////////////////////////////////////////////////////////////////////////////////////////////////
default {
changed(integer c) {
if (CHANGED_OWNER & c) llResetScript();
if ((CHANGED_INVENTORY & c) && (llGetInventoryKey(".access") != nckey)) reloadACLs("--START--");
}
state_entry() {
reloadACLs("--START--");
}
touch_start(integer n) {
if (!isAuthorized(llDetectedKey(0))) {
llOwnerSay("sorry, you cannot do that");
}
}
dataserver(key id, string data) {
if (!reloadACLs(data)) {
llOwnerSay("> Default allow " + llList2String(["owner only", "same group", "everyone"],
llListFindList(["O","G","A"], [llList2String(acls, 0)])));
integer n = llGetListLength(acls) - 2;
for (; 0 < n; n -= 2) llOwnerSay("> " +
llList2String(["Allow ", "Deny "], llListFindList(["A","D"], [llList2String(acls, n)]))
+ llList2String(acls, n+1));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment