Advanced   Java   Services RMI mit SecurityManager Back Next Up Home


RMI mit SecurityManager

Obige Beispiele sind zwar lauffähig, aber mit Vorsicht zu genießen, da keinerlei Sicherheitsvorkehrungen getroffen wurden. Server und Client sind JavaApplikation mit allen Rechten. Irgendein Client auf irgendeinem Rechner kann zu unserem Server Verbindung aufnehmen und alle Methoden des Interfaces rufen. Solange man bloß ein Datum geliefert bekommt, ist das nicht problematisch, wenn aber andere Daten geliefert werden, so kann das schon anders aussehen. Um Mißbrauch einzudämmen gibt es SecurityManager. Wird ein SecurityManager gesetzt, so überprüft er, ob für einen bestimmten Vorgang die Genehmigung erteilt worden ist. Ohne Genehmigung endet der Versuch den Vorgang auszuführen mit einer java.security.AccessControlException. Genehmigungen werden erteilt durch einen entsprechenden Eintrag in die Datei java.policy, die sich Im Verzeichnis $JAVA_HOME/jre/lib/security befindet.


Standardinhalt der Datei java.policy
// Standard extensions get all permissions by default
grant codeBase "file:${java.home}/lib/ext/*"
{
   permission java.security.AllPermission;
};

// default permissions granted to all domains
grant
{
   // Allows any thread to stop itself using the java.lang.Thread.stop()
   // method that takes no argument.
   // Note that this permission is granted by default only to remain
   // backwards compatible.
   // It is strongly recommended that you either remove this permission
   // from this policy file or further restrict it to code sources
   // that you specify, because Thread.stop() is potentially unsafe.
   // See "http://java.sun.com/notes" for more information.
   permission java.lang.RuntimePermission "stopThread";

   // allows anyone to listen on un-privileged ports
   permission java.net.SocketPermission "localhost:1024-", "listen";

   // "standard" properties that can be read by anyone
   permission java.util.PropertyPermission "java.version", "read";
   permission java.util.PropertyPermission "java.vendor", "read";
   permission java.util.PropertyPermission "java.vendor.url", "read";
   permission java.util.PropertyPermission "java.class.version", "read";
   permission java.util.PropertyPermission "os.name", "read";
   permission java.util.PropertyPermission "os.version", "read";
   permission java.util.PropertyPermission "os.arch", "read";
   permission java.util.PropertyPermission "file.separator", "read";
   permission java.util.PropertyPermission "path.separator", "read";
   permission java.util.PropertyPermission "line.separator", "read";

   permission java.util.PropertyPermission "java.specification.version", "read";
   permission java.util.PropertyPermission "java.specification.vendor", "read";
   permission java.util.PropertyPermission "java.specification.name", "read";

   permission java.util.PropertyPermission "java.vm.specification.version", "read";
   permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
   permission java.util.PropertyPermission "java.vm.specification.name", "read";
   permission java.util.PropertyPermission "java.vm.version", "read";
   permission java.util.PropertyPermission "java.vm.vendor", "read";
   permission java.util.PropertyPermission "java.vm.name", "read";
};

Setzen und Ermitteln des SecurityManagers

Per Default ist in einer JavaApplikation kein SecurityManager gesetzt. Die Klasse System bietet statische set/get-Methoden für einen SecurityManager an. Wir setzen den RMISecurityManager mit

System.setSecurityManager( new RMISecurityManager() ) ;

gleich am Anfang. Entsprechend gibt es eine Methode getSecurityManager(), die den gesetzten SecurityManager liefert oder null, wenn keiner gesetzt ist.


Sicherheitsvorkehrungen auf der Serverseite

Nach dem Setzen des RMISecurityManagers endet der Versuch, den Server zu starten mit folgender Exceptionmeldung

java.security.AccessControlException: access denied
(java.net.SocketPermission 192.168.45.3:1099 connect,resolve)

Wir müssen nun explizit dem Server die Erlaubnis erteilen, eine Verbindung aufzubauen. Der grant Eintrag in java.policy sieht folgendermaßen aus:

grant codeBase "file:c:/path/to/dateserver/*"
{
   // Allow the server to connect
   permission java.net.SocketPermission "192.168.45.3:1024-", "connect, resolve";
};

Das allerdings reicht nicht. Denn der nächste Versuch, den server zu starten endet mit

java.rmi.UnmarshalException: Error unmarshaling return header;
nested exception is: java.io.EOFException java.security.AccessControlException:
access denied (java.net.SocketPermission 192.168.45.3:1036 accept,resolve)

Wir müssen dem Server nicht nur einen Verbindungsaufbau erlauben, sondern auch das Annehmen von Anfragen.

grant codeBase "file:c:/path/to/dateserver/*"
{
   // Allow the server to connect
   permission java.net.SocketPermission "192.168.45.3:1024-", "accept, connect, resolve";
};

Jetzt können wir den Server starten. Allerings wird es einem Client nicht gelingen, eine Verbindung aufzubauen, er wird eine AccessControlException erhalten. Wir müssen noch zusätzlich angeben, welcher Client überhaupt berechtigt ist, eine Verbindung zum Server aufzubauen. Der vollständige grant-Eintrag sieht also wie folgt aus

grant codeBase "file:c:/path/to/dateserver/*"
{
   // Allow the server to connect and accept
   permission java.net.SocketPermission "192.168.45.3:1024-", "accept, connect, resolve";
   // Allow the client to connect and accept
   permission java.net.SocketPermission "192.168.45.1:1024-", "accept, connect, resolve";
};

1024- heißt, das für die jeweiligen IP-Adressen die Ports ab 1024 freigegeben sind. Es reicht nicht, nur den Port 1099 freizugeben.


Sicherheitsvorkehrungen auf der Clientseite

Setzt man für den Client ebenfalls einen RMISecurityManager, so muß man dem Client explizit erlauben, eine Verbindung zum Server aufzubauen. Der Eintrag in java.policy sieht folgendermaßen aus.

grant codeBase "file:c:/path/to/dateclient/*"
{
   // Allow the client to connect to the server , server = 192.168.45.3
   // connect schließt resolve ein, client braucht nur connect
   permission java.net.SocketPermission "192.168.45.3:1024-", "connect";
};

Client ist ein Applet

Der SecurityManager eines Applets

Ein Applet kann nur Kontakt zu dem Server aufnehmen, von dem es geladen worden ist. Dies stellt ein spezieller SecurityManager für Applets sicher, der für jedes Applet per default verwendet wird. Verwendet der Browser das plug-in von SUN, so ist das sun.plugin.security.ActivatorSecurityManager.


Server verwendet keinen RMISecurityManager

Wenn der Server keinen SecurityManager aktiviert, kann ein Applet ohne weiteres Kontakt zum DateServer aufnehmen, egal von wo aus es das tut, wichtig ist nur, daß es von dem Rechner stammt zu dem es Kontakt aufnehmen will.


Server verwendet einen RMISecurityManager

Auch in diesem Fall kann der Client ein Applet sein. Da das Applet aber lokal auf dem Client läuft wird bei einem Verbindungsaufbau zum Server die lokale IP-Adresse übermittelt und das heißt, daß serverseitig in der java.policy explizit die IP-Adressen stehen müssen, für die der Zugriff erlaubt ist. Für dynamische Adressen ist somit kein Zugriff möglich.

Valid XHTML 1.0 Strict top Back Next Up Home