lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
PRIVILEGES & PROTECTIONS

In most multi-user environments it is necessary to restrict manipulation
of files and data in certain ways. MUDs are now exceptions. For example,
as the administrator of a MUD, you don't want the average wizard to tamper
with the login object (for example by logging passwords) and most wizards
don't want their files writeable by other wizards unless they are
specifically granted permission to do so.

Therefore, we need means to enforce a scheme that protects data (in
particular files) from arbitrary manipulation. To do so, we introduce
the concept of privileges (what a particular piece of code is allowed
to do) and protections (the barrier that must be bypassed in order to
manipulate a particular file).

Both privileges and protections are drawn from the same set of values:
The integers 1 and 0 (representing the top- and bottommost levels) as
well as almost arbitrary strings. Most values will fit one of the
following templates:

"wizard"	The privilege that this wizard's player object has.
"wizard:"	The privilege that most of this wizard's objects have
		by default (unless changed).
"wizard:sub"	One of many possible sub-privileges that a wizard may
		create (for example, to make a sub directory where other
		wizards may write to, it will typically have such a
		string as its protection and - as we will see later -
		the maximum privilege for objects residing therein).
"Domain"	The controlling privilege for a domain. Note that the
		domain name is capitalized. Although there will not be
		a 'player object' with this privilege, it is used for
		certain internal manipulation.
"Domain:"	Default privilege/protection for the domain's objects.
"Domain:sub"	Special privileges/protections for the domain.
"@data"		Privileges beginning with "@" are reserved for administrative
		purposes.
1		Not a string, but the integer 1. It is the topmost privilege
		in the hierarchy. Objects with this privilege can do
		anything if they desire to do so. Using 1 as a file protection
		means restricting access to administrators.
0		Again not a string, but the integer 0. It is the bottommost
		privilege in the hierarchy. Objects with this privilege
		can do almost nothing in terms of file access except accessing
		publicly available data. But since most files are publicly
		readable, you only need a different privilege for write
		access.

THE HIERARCHY

As mentioned above, there is a highest privilege (1) and a lowest privilege
(0). All the other privileges lie in between. In fact, we may write a graph
for a simple system comprising two wizards "a" and "b" and a domain "D":

		1
	      / | \
	    /   |   \
	  "a"  "D"  "b"
	   |    |    |
	  "a:" "D:" "b:"
	    \   |   /
	      \ | /
	        0

It is noteworthy that none of "a", "b" or "D" is higher or lower than any
of the other privileges except 0. This is what we want, because by default
neither wizard "a" nor wizard "b" should be able to write to each other's
directory. On the other hand, what if both "a" and "b" are members of the
domain "D"?

Let us assume that "a" becomes member of "D". Then we will have the
following diagram:

		1
	      / | \
	    /   |   \
	  "a"  "D"  "b"
	   | \  |    |
	   |  \ |    |
	  "a:" "D:" "b:"
	    \   |   /
	      \ | /
	        0

Note that there is no link between nodes "a" and "D" in the above graph.
This is because privileges without a ":" are so-called control
privileges and privileges with a ":" are so-called data privileges. This
means that only by by access to a control privilege new data privileges
with this prefix can be created or deleted. Example: Wizard "a" can
create privileges "a:data", "a:log", "a:foo" or in general anything with
an "a:" in front. He cannot create something with a "D:" in front,
because he'd need access to privilege "D" for that and access to a
domain's control privilege is reserved for the lords of that domain.

Besides privileges bound to wizards or domains there is also a third
type for general purpose stuff. Such privileges start with a "@". For
example, "@doc" or "@syslog". Normally they can only be created by
wizards with privilege 1. However, once a wizard is given access to,
say, "@doc", it acts as a control privilege and he can create data
privileges like "@doc:open" etc.

FILES AND ACCESS TO THEM

In general, access is controlled in a simple manner. Files have a
protection level and objects have access to them if and only if they
have the same or a higher privilege.

However, not every single file will have a different protection level.
In fact, protection levels are assigned on a per-directory basis. Thus
you can for example assign the privilege "@doc:open" to /doc/open if it
is a directory, but not "@doc:open1" to /doc/open/file1 and "@doc:open2"
to /doc/open/file2.

Note that a directory can have different protection levels for read and
write access. There will, however, be only a few files that are
read-protected, like mail files or players' data files.

The access mechanism is a bit more complicated than outlined above, but
far from difficult.

All security is based on the simul_efun check_privilege(). It gets a
privilege as its argument, checks whether it is safe to do operations at
this privilege level and returns 1 (true) or 0 (false) accordingly.

It works as follows: The entire object stack is checked. For every
single object on the stack its privilege is compared to the argument of
check_privilege(). If the object's privilege is too low, computation is
aborted and 0 is returned. Otherwise we proceed until the entire object
stack is checked.

You may wonder what this thing called 'object stack' is. A simple
example will illustrate this: Let us assume, a wizard uses an alias tool
to execute a roommaker command. In particular this will imply that the
wizard calls some routine in the alias tool which in turn calls a
routine in the roommaker. Thus the object stack is made up of the three
element list (wizard, alias tool, roommaker).

This procedure seems overly complicated but prevents 99% of all
possibilities to do mischief. For example, if someone gave you a fake
alias tool (or roommaker), its privilege would be his and it would be
impossible to access your files unless you explicitly gave him access to
them in which case there wouldn't be a need for him to use such a
complicated way anyway.

The same idea enables us to give most system tools privilege 1 without
having to worry about security since all file accesses will be
restricted by the wizard's privilege.

There is, however, a problem. For example, there will be no interactive
player in a heart_beat() or call_out() and thus the top of the object
stack would be undefined and all file accesses would fail. Or what if a
player wants to do a 'save'? Surely we can't make the players' data
files publicly accessible lest somebody goes there and edits the
password or other security realetd stuff and poses as somebody else?

To solve these problems, there is the unguarded() call. It takes two or
three arguments. The first is a privilege, the second a closure and the
third a list of optional arguments to that closure. unguarded() will
proceed to evaluate the closure at the privilege level given by the
first argument. It will also pass the third parameter as arguments to
the closure as in the efun apply(). In addition, all objects in the
object list above the one that did that call will no longer be checked
for their privilege. In particular, if in the above example the
roommaker wants to save its current state to "/save/roommaker.o" for
debugging, independent of who uses it, it would do something like:

unguarded(1,#'save_object,"/save/roommaker");

This would (a) perform the save at privilege level 1 (of course the
roommaker must be able to use that privilege) and (b) ignore the alias
tool and the wizard in the above example.

TECHNICAL DETAILS

If you just were trying the above example, you'd notice that it fails
spectacularly. In particular, the compiler will complain about a missing
function unguarded() (and probably a lot more).

The reason is that most of the above stuff is hidden in a module that
you have to inherit to use it. This is done as follows:

#include <kernel.h>
inherit ACCESS;

Including kernel.h provides you, among other things, with a definition
of ACCESS. Inheriting ACCESS then gives you the following routines:

set_privilege()		This routine takes a privilege as its argument
			and will set the object's current privilege to
			it (if possible).

query_privilege()	Returns the current privilege an object has.
			However, it is preferable to use the simul_efun
			get_privilege(obj) to get the current privilege
			for an object, because there is a chance that
			obj->query_privilege() is faked if somebody has
			been careless. get_privilege() has appropriate
			safeguards built in.

unguarded()		This routine has been described above. Take care,
			however, when using it. It is the only possibility
			to introduce security leaks in the system (besides
			other stupid stuff like inheriting files like
			"/open/anybody_can_change_me.c" or the like).

			However, a few simple precautions make it quite safe
			to use. For example, if all the arguments are safe,
			like if they are constants or have been checked
			for correctness then there is no problem. Avoid,
			however, stuff like:

			foo(file,data)
			{
			  unguarded(1,#'write-file, ({ file, data }) );
			}

			This would make a nice security leak.

COMMANDS

Several command to manipulate the access structure are supplied in the
tool /bin/admin. First, there are the commands beginning with 'access':

access define <privilege>

   Defines a new privilege. You need to have access to the control
   privilege, though.

access undefine <privilege>

   Gets rid of this privilege again.

access link <privilege> to <directory>

   Binds the given privilege to the given directory as its protection
   level for write access.

access link -read <privilege> to <directory>

   Same as above, but for read access.

access unlink <directory>

   Gives the directory its default write protection level again (i.e.
   the one it has inherited from the directory containing it.

access unlink -read <directory>

   Same as above, but for read access.

access open <privilege1> for <privilege2>

   Gives any object with <privilege2> access to <privilege1>

access close <privilege1> for <privilege2>

   Denies access again.

access show <privilege> (not yet implemented)

   Shows the privilege, all dependent privileges and all other
   privileges that have access to them.

access list <directory> (not yet implemented)

  Shows the directory tree beginning at <directory> and all
  protection levels therein.

access makewiz <name>

  Tells the security server that the named player is now a
  wizard. This is required to define privileges for him.
  Note that this is normally done implicitly by the player
  object when promoting him to wizard and there is no need
  to repeat it manually.

access zapwiz <name>

  Tells the security server that the named player is not
  longer a wizard.

Second, there are commands to administrate domains:

domain create <name>

  Creates the domain <name>.

domain delete <name>

  Deletes it.

domain add <member> to <domain>

  Adds a new member to said domain.

domain add -lord <member> to <domain>

  Adds a new lord to a domain or promotes an existing member to lord.

domain remove <member> from <domain>

  Gets rid of him again.

domain show <domain>

  Shows the lords and members of a domain (or of more than one, if given).

domain list

  Lists all existing domains.

domain list <wizard>

  Lists all domains, the wizard is a member of.

(remark: the add, remove, show and list commands take also multiple arguments.)

EXAMPLES

This section has yet to be written.