Back to index

The copyright situation for this article is unclear. It does not belong to the author of this site. Please see the copyright notice. If you have information about the copyright contact me!

Objects and Trust

by Kevin Littlejohn (Darius)

Straight off the bat, I will point out that this article is biased. Most of the thoughts herein stem from coding issues we have faced in building Moebius, a python-based MySQL-backended muddish engine, and as such, are directly influenced by the aims and restrictions on its development.
Moebius Strip

The never ending two dimensional three dimensional shape.

Moebius is built around an SQL database - the objects, their data and methods all live in this database, and are simply instantiated when needed. By using a combination of python and SQL, we gain a few nifty tricks - like the ability to access, both read and write, all data _and methods_ for all objects externally to the mud. That means we can re-program any method on any object, re-bind to the object, and keep running without batting an eyelid.

The next obvious addition to this was a scripting language - if you are going to write a mud in python, why not give people the ability to code python around the objects, right? Well, this immediately ran us into Really Bizarre Territory, as far as object permissions go, as you will see below.

The first theory we had regarding objects and permissions was that every object was king of its own castle, so to speak - an object had the right to accept or deny requests for its own attributes, or munge those attributes in response to a request. This means that to implement an invisible object, you simply program the object such that it tells people it is invisible (move along please, we are a hedge). This seemed like a fine idea, and was the first cut implementation. This is basically how at least I was taught about objects - an object is fully responsible for its own data, and nothing else should touch that.

The problem with this becomes evident when you try and build a combat system. Suddenly, relying on the object itself is not such a smart idea - I am going to code my object to reply "yes" every time I am asked to drop my hit points, and not drop them. Cool. Bear in mind through this that we have exposed a scripting layer, potentially to every player, but at the very least to all creators. We do not want that scripting layer to be able to bypass all the security - if possible, we want the security built into the objects - intrinsic to their very being.

How do we manage this? About this time, one of the designers came across - a site devoted to a language called E, which purports to solve some of these issues. One of the core concepts for E is 'capabilities' - sort of like keys for attributes, that an object can hand out to other objects. There is a lot about this on, and on related sites linked from there (KeyKOS, and eros, two capabilities-based OS'es). I will not say too much about their particular layout, as I am not entirely sure I would be qualified to speak on it. However, this was our first take on a similar system:

Set up a capabilities system such that an object must have the appropriate cap (or key) before it can get/set/call a given attribute. Do not assume that the object has permissions over its own attributes - that would not solve the problem. Instead, grant those caps only where needed. Said caps would be like keys - an object could create a cap, assign to it any number of "permissions" - get this, set that, etc. - and pass the cap out to other objects, to give them permission to talk to it.

So, say there is an object called 'darius' - that is me, and there is an object called 'socio' - a sociopathic creature, bent on destruction (Hi Phil ;). Socio swings at me, and hits - do I change my hit points? No, because I am not allowed. Does Socio change my hit points? Well, if we allow that, I doubt he would bother swinging - he will just tweak me down to dead and be done with it.

What is needed is a third party - a mediator. It would be the mediator's job to manage these sorts of interactions. Here is the third draft:

Objects have attributes, and caps - caps detail the attribute they relate to, and the type of access they provide. By default, an object has caps to cover all its attributes, granting itself all access.

Mediators exist - they are just another form of object, but they hold special methods, to deal with setting attributes in _other_ objects. They also hold what is called a 'context'.

A context is a way of defining a set of conditions - a contract, if you like. To join a context, you would have to meet a bunch of conditions, defined by the mediator. If you do not meet those conditions, you do not get access to the methods provided by the mediator (and it does not get access to you) - effectively, you choose not to play.

The conditions for a context would be specified primarily in terms of access rights. An example is in order:

A context exists, called the 'fight' context. A mediator controls this context. To join the context, you have to grant the mediator write access over your hit points - and drop write access yourself. If you choose to join, you (the object) can no longer set your hit points yourself. Instead, the mediator will provide a method you can call that will signal hit point gains. It will then decide whether this is legitimate or not, and action it or not at its discretion. Note, you still have get access - you can still see your own hit points, you just can not write to them.

There is a number of side-issues in this - if the mediator changes, the object needs to be given the option to deny the new context, and vice versa. If an object wants to join a context, but has a modified method of some sort for a given attribute, the context will need to recognize that. Also, we are migrating a lot of the "intelligence" regarding objects into the mediators, away from the objects - which in a lot of respects is counter to what we had meant to do in the first place. We may be able to migrate some back, with trusted methods, but because we can potentially change things on the fly, we may not be able to trust the objects enough for even a signing system to work.

It is also worth noting that the work so far has not _really_ been about making distributed objects, but about building a system for trust between objects out of very little. It happens that a lot of that extends out to distributed object issues as we go, which is lucky.

Finally, I am still unconvinced regarding security issues. E is a nice language, and a lot of thought has gone into its capabilities system - but I would be interested to see what a dedicated person with a debug install of VMWare, or gdb, could do with a running instance. The crux of distributing objects still seems to be that code running on a platform outside your control cannot be trusted to have done the "right" thing, for any given definition of right.

For those who are interested in this stuff, or have ideas (or better, solutions ;) for any of the above, feel free to drop into port 5000 (shameless plug, I know ;), I would be more than happy to chat about distributing objects and security...