pioneerspacesim/pioneer — pull request #1706 by robn (2012-11-12 09:32:54+00:00)
Title: Lua: allow protected interfaces that can only be used by core scripts

## Background

Slightly rabbit-holeish it, but I think its important.

I'm working on adding an RPC agent to Pioneer to send/receive data to/from a server (see `robn/rpc-agent` for implementation and [Network features](http://pioneerwiki.com/wiki/Idea_Network_features) for reasons).

Naturally, this agent will be exposed to Lua. This puts us in the situation where a script in a mod could eg use the `FileSystem` interface to send information from the local filesystem to a server. Now there are extra protections in the server stuff in that it can only used if enabled in config, and its locked to a single server, also specified in config. Normally that would be fine.

But, as part of the the new UI work, config is eventually going to need to be readable and writable from Lua (for the settings screen). So now we have the case where a malicious mod could, without the player's knowledge, enable the network, set the server, and then upload local data.

The solution to is to mark interfaces like `FileSystem` and (the as-yet-nonexistent) `Config` as "protected", and only allow it to be accessed by scripts that come bundled with Lua. That's what this PR is about.

## Implementation

1. We set up a concept of a "trusted" `FileSource`. Its just a flag on the source; it doesn't nothing by itself but can be interrogated as necessary. `FileSystem::dataFilesApp` is the only one that gets the "trusted" flag.
2. When loading a Lua file, we look at the "trusted" flag for its source. If its trusted, we add some recognisable text to the chunk name when we load it in.
3. Meanwhile, when creating an API object, we allow a "protected" flag to be specified. If its true, we wrap the API functions with a small trampoline function that checks to make sure the caller is trusted.

## Notes

* The check to see if a function came from a trusted source is pretty skanky, but I don't see another way. Its not enough to just record the name of the file in a trusted list, because core files get replaced by local ones (there should still be only one but this still feels safer). It has to be stored in the file (chunk) name because that's the only controllable data that can be retrieved about the caller from Lua.
* I've checked the list of standard Lua libraries that we enable, and I don't think any of them can be used to get at potentially-unsafe data (include `debug`).
* I've looked over our interfaces, ditto.
* Right now this can only be applied to top-level one-off objects (created via `LuaObject::CreateObject`). We could do it for whole classes, but its not needed for anything we have and I haven't quite thought through the semantics. We can worry about that when and if we need it.
* I'm not bothered about people adding stuff to the core Lua scripts to work around that. I'm not bothered about the console. And I'm not bothered about high-grade security either. This is merely supposed to provide a simple layer of protection to prevent mods from doing possibly-nasty things without the user's knowledge.