Subject: Destroying a character

From: Andrew Donkin <[email-masked]>
Date: Wed, 14 Apr 1993 17:51:25 -0700

I have a few newbie questions - please bear with me.

=  To recycle a player, I can `@toad' then `@recycle' them - that I
   understand.  Is there an easy way to recycle of of that player's objects
   without looping through their .owned_objects and @recycling them one by
   one?  Like, perhaps, a `@totallyscrewplayer' verb that I have missed?

=  How do I take advantage of core updates when they are released?  Say when
   LambdaCore 1.8 arrives, how can I extract my local info and re-
   incorporate it into the new core?

Thanks in advance - 

,------------------------------------------------------------------------,
|            Andrew Donkin - [email-masked]            |
`------------------------------------------------------------------------'

---

From: [email-masked] (Sarah Elizabeth Heacock)
Date: Wed, 14 Apr 1993 22:35:08 -0700

Can anyone give me some pointers as to common security leaks in
programming in MOO? (IE, if you are a janitor on a MOO, what do
you need to look out for/be careful when coding to make sure that
others can not use your code to gain access to commands and powers
they otherwise shouldn't have?)

I don't intend on doing too much code on the janitor/wiz/director
type character until I know more about MOO, but was hoping that 
someone might be willing to help me not lay myself open to blatant
security loopholes

(Like, for example, when you force an object on MUSH, you have to remember to
put all the commands in {}... taht's the kind of thing I am talking about.)

Sarah E. heacock
[email-masked]

---

From: Pavel Curtis <[email-masked]>
Date: Thu, 15 Apr 1993 11:41:10 -0700

> Date:	Wed, 14 Apr 1993 17:51:25 -0700
> From:	Andrew Donkin <[email-masked]>
> 

Not that I'm aware of, though a very simpleminded one would be easy to write.

>    incorporate it into the new core?

Unfortunately, there is no simple way to do this and, arguably, no even
feasible way.

	Pavel/Haakon

---

From: Roger Crew <[email-masked]>
Date: Thu, 15 Apr 1993 11:57:50 -0700

Random tips:

1.  Every wizard-owned verb is a potential security hole; don't write
    a wizardly verb if a nonwizardly one will do the job.

2.  Use set_task_perms(caller_perms()) where possible.  Anything bad
    that you do in such a verb will only screw the caller.  Note that 
    this doesn't completely protect you, since the caller might be another 
    wizard verb.

3.  If you make any references to "player" under the assumption that
    this is a command verb and (player==whoever typed the command),
    make sure the verb is -x.

    This is particularly important if the verb contains set_task_perms(player).

    At one point we had a number of breakins on Lambda resulting from
    verbs being inadvertantly left +x.  The current LambdaCore should
    have a version of @verb that has -x be the default for non
    this-none-this verbs.

4.  set_task_perms(caller.owner) is usually a mistake.

    A single instance of this means that no wizard should own a child
    of anything not itself owned by someone trusted.  E.g., wizard
    owns A, cracker owns B==parent(A), cracker installs B:breakin that
    calls a verb that does set_task_perms(caller.owner), cracker calls
    A:breakin... now the verb is running with wizard permissions and
    the set_task_perms is basically useless.

5.  Be extremely careful with verbs that call either eval() or
    set_verb_code().  These can take arbitrary text and run it with
    your permissions, so if you write, e.g., eval(x) in wizard-owned
    code (or even your own code), you have to ask yourself, "Where is
    x coming from and who has control over it?"

    In particular, if x is coming from an argument:
     (a) put in set_task_perms(caller_perms())
     (b) check all WIZARD verbs that call this.
    
    Use $no_one:eval() where you can.

Many of these tips have their counterparts for non-wizard code,
the worry being that a careless verb might enable someone to usurp
the verb-owner's permissions.  

This is, in fact, the flip-side to (1).  That is, although you'll
sleep easier if it's a nonwizard verb; if that nonwizard owns
something important you now have to worry about who can usurp his/her
permissions as well.  In particular, the released LambdaCore has a
single player $hacker who owns everything of interest.

In fact, you probably don't want to be writing new Hacker
verbs anyway.  If you're planning a new facility of some sort, the
right thing to do is create a distinct player and have the verbs
be owned by that player.  That way, any mistakes you make will
only compromise that player.

This is the reason why on Lambda, $editor.owner is a distinct
player, though the issue there is as much protecting the editor
against mistakes in the rest of the core as protecting the core
against mistakes in the editor.  $editor.owner is something of a
special case since $verb_editor.owner is able to rewrite any verb
on the moo, thus its permissions have to be as guarded as wizard
permissions are.

Actually the $verb_editor is just a particular case of (5) since it
contains a wizard-owned verb that calls set_verb_code().

--
Roger Crew
Internet:   [email-masked]
LambdaMOO:  Rog

---

From: Larry Masinter <[email-masked]>
Date: Thu, 15 Apr 1993 11:57:38 -0700

This is what I've been using lately to zap inactive players:
================================================================
#13331:"@zap"   any any any
"@zap player";
whostr = args[1];
if (!(callers() ? caller_perms() | player).wizard)
  player:notify("Yeah, right... you wish.");
  return;
elseif ($command_utils:player_match_failed(who = $string_utils:match_player(whostr), whostr))
  return;
elseif (whostr != who.name && !(whostr in who.aliases) && whostr != tostr(who))
  player:notify(tostr("Must be a full name or an object number:  ", who.name, "(", who, ")"));
  return;
elseif (who == player)
  player:notify("If you want to toad yourself, you have to do it by hand.");
  return;
endif
this:("@report")(tostr(dobj = who));
if (time() - who.last_connect_time < 3 * 30 * 24 * 60 * 60)
  player:tell("***** LESS THAN 3 MONTHS IDLE ****");
endif
if ($command_utils:yes_or_no("@toad " + who.name + "?"))
  if ((email = who.email_address) && (current = $registration_db:find_exact(email)) && (ind = $list_utils:iassoc(who, current)))
    current[ind] = {@current[ind], "zapped due to inactivity"};
    $registration_db:insert(email, current);
  endif
  for x in ({@setremove(who.owned_objects, who), who})
    player:tell("x ", this:object_audit_string(x));
    $recycler:_recycle(x);
  endfor
  player:tell(whostr, " zapped!");
else
  player:tell(whostr, " saved!");
endif