Prof. Dr. A. Poetzsch-Heffter Dipl.-Inform. N. Rauch Technische Universität Kaiserslautern Fachbereich Informatik AG Softwaretechnik Übungsblatt 1: Fortgeschrittene Aspekte objektorientierter Programmierung (WS 2005/06) Ausgabe: 11. November 2005 Abgabe: 18. November 2005 Aufgabe 1 Kapselung Diese Aufgabe behandelt den Zusammenhang zwischen Kapselungstechniken und Sicherheitsfragen. Gegeben ist folgendes Szenario: Eine Zugangsverwaltung, repräsentiert durch ein Objekt vom Typ ZugangsVerwaltung, verwaltet, welche Personen Zugriff auf geschützte Systemteile haben. Deren Kennungen (Namen der Personen) werden als Strings in einem Objekt der Klasse Befugnis gespeichert. ZugangsVerwaltung und Befugnis sind wie folgt implementiert: package System; public interface ZugangsVerwaltung { public void einfuegenBefugnis(Befugnis b); public Befugnis holeBefugnis(); } package System; public class Befugnis { protected String[] kennungen; public Befugnis() { kennungen = new String[5]; } public String[] holeKennungen() { return kennungen; } } Das Zusammenspiel zwischen ZugangsVerwaltung und Befugnis ist wie folgt: 1. Objekte vom Typ Befugnis können von beliebigen Klassen erzeugt und mit der Methode einfuegenBefugnis an die Zugangsverwaltung übergeben werden. 2. einfuegenBefugnis speichert die übergebene Referenz und trägt die Kennungen der zugelassenen Personen in das String-Feld des Befugnis-Objekts ein, indem es direkt auf dessen Attribut kennungen zugreift. (Beachten Sie, dass ZugangsVerwaltung und Befugnis im gleichen Paket deklariert sind!) 3. Beliebige Nutzer des Systems können mittels der Methoden holeBefugnis und holeKennungen die Kennungen der zugelassenen Personen auslesen, also um diese z.B. mit anderen Kennungen zu vergleichen. Wir nennen das Zusammenspiel zwischen ZugangsVerwaltung und Befugnis ein sicheres System, wenn keine Klasse außerhalb des Pakets System die in einem Befugnis-Objekt gespeicherten Kennungen verändern kann. a) Mit der obigen Implementierung ist das System nicht sicher. Beschreiben Sie, wie ein Angreifer unter Verwendung der Methode holeKennungen() die Liste der Kennungen manipulieren könnte! Unter einem Angreifer verstehen wir eine Klasse, die außerhalb des Pakets System deklariert ist. b) Implementieren Sie Ihre Lösung zu Teilaufgabe a) als Methode public static void angreifen(ZugangsVerwaltung u) {...} einer Klasse Attacke im Paket Angreifer! c) Geben Sie an, wie man die Implementierung der Klasse Befugnis ändern müsste, um den Angriff aus Teilaufgabe a) zu verhindern! Die modifizierte Befugnis-Klasse muss jedoch die Punkte 1–3 des oben beschriebenen Zusammenspiels weiterhin zulassen! Auch die Schnittstelle ZugangsVerwaltung sowie ihre Implementierung müssen von der Änderung unberührt bleiben. d) Betrachten Sie jetzt wieder den ursprünglichen Code und beschreiben Sie, wie ein Angreifer ohne Verwendung der Methode holeKennungen() die Liste der Kennungen manipulieren könnte! e) Implementieren Sie Ihre Lösung zu Teilaufgabe d) als Methode public static void angreifen(ZugangsVerwaltung u) {...} einer Klasse Attacke im Paket Angreifer! f) Geben Sie an, wie man die Implementierung der Klasse Befugnis ändern müsste, um den Angriff aus Teilaufgabe d) zu verhindern! Es gelten die gleichen Rahmenbedingungen wie bei Teilaufgabe c). Aufgabe 2 Atomizität Die Korrektheit nebenläufiger Programme sicherzustellen ist nicht einfach. Hierbei sollte unter anderem die Atomizität von Methoden betrachtet werden. Eine Methode heißt atomar, wenn ihre Ausführung weder durch nebenläufig ablaufende Threads beeinflusst wird noch diese ihrerseits beeinflusst. Betrachten Sie den folgenden Code, der aus der Klasse java.lang.StringBuffer stammt: public final class StringBuffer implements Serializable, CharSequence { int count; char[] value; // ... public synchronized StringBuffer append(StringBuffer stringBuffer) { if (stringBuffer == null) return append("null"); int len = stringBuffer.count; ensureCapacity_unsynchronized(count + len); VMSystem.arraycopy(stringBuffer.value, 0, value, count, len); count += len; return this; } public synchronized void getChars(int srcOffset, int srcEnd, char[] dst, int dstOffset) { /* ... */ } // Diese Methode stellt sicher, dass das Feld value mindestens die // Groesse minimumCapacity hat. private void ensureCapacity_unsynchronized(int minimumCapacity) { /* ... */ } } final class VMSystem { static native void arraycopy(Object src, int srcStart, Object dest, int destStart, int len); } Ist die Methode append atomar? Falls nein: Überlegen Sie sich ein Szenario, in dem die Nicht-Atomizität zum Problem wird, und modifizieren Sie den obigen Code so, dass die Methode atomar wird.