Advertisement
Guest User

Untitled

a guest
Dec 20th, 2014
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.90 KB | None | 0 0
  1. How to implement plugin permisisons (for all servers written in OOP languages with PocketMine-style API: commands, events, schedules) in code for access to API functions
  2. ===
  3. The principle of this system is to make use of the characteristic of executing code on one thread - code flows single-direction - to identify what context (server or what plugin or what) the code is flowing to currently and decide whether the current context has permission to do something.
  4.  
  5. First, the server has to declare a class that extends a class called `Context` and instantiate an object that has any permissions. The object serves as a lock and shall not be accessible by plugins. Every object that represents a plugin (but these objects must not be declared by the plugin) should have a context too. This is an example for the `Context` class in Java:
  6.  
  7. ```java
  8. import java.util.List;
  9.  
  10. public class Context{
  11. private List<UsedPermission> perms;
  12. private List<Context> owningContexts;
  13. public boolean usesPermission(UsedPermission perm){
  14. for(UsedPermission hasPerm : perms){
  15. if(hasPerm == perm){
  16. return true;
  17. }
  18. }
  19. return false;
  20. }
  21. public boolean ownsContext(Context other){
  22. if(other == this){
  23. return true;
  24. }
  25. for(Context ctx: owningContexts){
  26. if(ctx == other){
  27. return true;
  28. }
  29. }
  30. return false;
  31. }
  32. }
  33. ```
  34.  
  35. Then, in the main server class, there should be a private static property `runningContext` of type `Context` and another called `mainThread` of type `Thread` (or thread ID). In the constructor of the server object, `runningContext` should be set to the context lock and `mainThread` should be set to represent the current thread.
  36.  
  37. In the manifest (e.g. `plugin.yml`) for every plugin, a `used-permissions` property should be set to declare the permissions that the plugin uses. If a plugin interacts with another, it must specify it in the manifest too.
  38.  
  39. Every time the server calls to an interface/abstract method of the plugin (like `onEnable()` or `onCommand()` in PocketMine. that runs arbitrary code specified by a plugin), it should call this method on the server object: (in Java for example)
  40.  
  41. ```java
  42. public void switchCurrentContext(Context newContext, Context lock) throws IllegalAccessException{
  43. if(Thread.getCurrentThread() != this.mainThread){
  44. throw new IllegalAccessException("This method must be accessed from the main thread"); // this avoids access from other threads started by the plugin that knocks the door when the context is back to the server lock
  45. }
  46. if(lock != this.lock){
  47. throw new IllegalAccessException("Illegal lock");
  48. }
  49. this.currentContext = newContext;
  50. }
  51. ```
  52.  
  53. Such that when a plugin calls an API function, the API function checks this:
  54.  
  55. ```java
  56. public void iAmAnApiFunction(Context ctx) throws IllegalAccessException{
  57. UsedPermission permission_to_use_this-function;
  58. if(!server.isContextOwnedByCurentContext(ctx)){
  59. throw new IllegalAccessException("Illegal context passed");
  60. }
  61. if(!ctx.usePermission(permission_to_use_this_function)){
  62. throw new IlelgalAccessException("Context does not use permission to use this function");
  63. }
  64. }
  65. ```
  66.  
  67. Improvements
  68. ===
  69. A `java.util.Random` object can be used if the
  70.  
  71. Bugs of this system
  72. ===
  73. The system is vulnerable to reflection attacks. For example, in PocketMine PHP, this is possible:
  74.  
  75. ```php
  76. /** @var \pocketmine\Server $server */
  77. $property = new \ReflectionClass($server)->getProperty("context"); // assuming that the private context lock is stored in $server->context
  78. $property->setAccessible(true);
  79. $context = $property->getValue($server); // Yay! We seized the throne!
  80. ```
  81.  
  82. A fix to this method is not to pass any objects that directly or indirectly have reference to the lock to plugins and to keep them away from the global context and static properties. However, in some cases this may carelessly lead to garbaging of the lock.
  83.  
  84. Another fix is to review it by man that a plugin doesn't include such malicious code, although in this case the system is as useful as non-existent.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement