CS361 Assignment 1

Due: Friday, June 13 by the end of the day. This means that your submission must be dated on or before that date, so you have until midnight.

Each assignment is graded on a 10 point scale. For this assignment, it is possible to get up to 2 extra credit points. That info is at the bottom.

Deliverables: You will be submitting your code electronically using the turnin program. Make sure that you clearly identify the members of your team (one or two people). Your program must be able to run on the UT Linux machines, so if you develop it on Windows, make sure it runs on Linux.

For this assignment:

  1. The primary file name should be SecureSystem.java. Students are welcome to organize their assignments into multiple files and must submit those files as well. However, the main method must be in SecureSystem.java and we should be able to compile your program with javac *.java.

  2. The program should be executed via the command: java SecureSystem instructionList

  3. Include a README file containing the names and email addresses of the authors, along with any additional information you'd like us to know about your program.

Make sure that both members of your team understand the code and contribute equally, as much as possible, to its development. If anyone gets a free ride, they'll be disadvantaged later.

The Assignment

Your assignment is to implement in Java a simple "secure" system following the Bell and LaPadula (BLP) security rules--simple security, the *-property, and strong tranquility. Take care with this assignment, because it will form the basis of at least the next assignment.

A Simple Non-secure System

Imagine a system with subjects and objects. Each object has a name and a current value (initially 0). Each subject has a name and an integer variable TEMP recording the value it most recently read (also initially 0). Subjects can perform READ or WRITE operations on objects. For a READ, the subject reads the current value of the object, and saves that value into its TEMP variable (a subsequent READ will smash it). When a subject does a WRITE, the object's value is updated. Objects are managed by the ObjectManager class. Think of ObjectManager as a very simple file system that READs and WRITEs objects by name.

Imagine that the input for your system is a file of commands. For the current assignment, legal commands are of the form:

   READ subject_name object_name 
   WRITE subject_name object_name value 

All fields of the instruction are strings except the value, which is an integer.

You will read successive lines from the file and parse each into an InstructionObject class object. Commands are not case-sensitive, even object and subject names. Arbitrary whitespace is allowed in commands, though you can assume that each command is on one line.

Be sure to deal with the possibility of errors in the instructions (neither READ nor WRITE, wrong number of arguments, etc.). For illegal instructions, generate a BadInstruction constant object.

For example, suppose your input file contains the following instructions. The top two and the last three are bad and the others syntactically legal.

write Hal HObj 
read Hal 
write Lyle LObj 10
read Hal LObj 
write Lyle HObj 20
write Hal LObj 200
read Hal HObj
read Lyle LObj
read Lyle HObj
foo Lyle LObj
Hi Lyle,This is Hal
The missile launch code is 1234567
Notice that you're not checking security attributes or definedness of the subjects/objects (yet), merely the syntactic well-formedness of the commands.

Assuming that Hal and Lyle are subjects and LObj and HObj are objects, we might write an interpreter for this system, that would perform the legal instructions and ignore the others. A reasonable implementation might end with a state in which the objects have values: LObj 200 and HObj 20; the subjects' TEMP variables would contain: Hal 20 and Lyle 20.

The Secure System

Let's do something like that, but under a secure interpretation. We'll start by giving both subjects and objects associated security labels (levels). These labels are maintained by a ReferenceMonitor class object and can't be changed after they are created (strong tranquility). Think of the reference monitor as maintaining two mappings from subject/object names to security labels.

In the secure version of our system, whenever a subject requests to perform an action (READ or WRITE), the action is submitted to the reference monitor, which decides whether to perform the action or not based on the BLP properties (Simple Security and the *-Property). If legal and allowed by the BLP rules, the reference monitor tells the ObjectManager to perform the appropriate action; otherwise, no objects are accessed. Commands referencing any subject/object that does not exist on the system are not allowed. However, the reference monitor always returns an integer value to the subject: the value of the object read, if the command was a legal READ; and 0 otherwise. If the subject is performing a READ, it stores this value into its TEMP variable. Think of the reference monitor as a firewill around the ObjectManager. Note that the ObjectManager doesn't know or care about labels or security; it just performs simple accesses.

Think of the top level class (SecureSystem) as managing subjects and the reference monitor but also serving as the interpreter. It reads successive instructions from the instruction list, parses them, and submits them to the reference monitor, which performs them (or not). The value returned by the reference monitor is passed to the subject executing the instruction.

Your task is to implement all this, subject to the following constraints.

  1. The ObjectManager must be local to the ReferenceMonitor.
  2. SecurityLevel should be a class with a defined "dominates" relation. You can assume that levels are linearly ordered. That is, you don't need to worry about need-to-know categories. Within that class define two constant levels HIGH and LOW such that HIGH dominates LOW.
  3. When you parse an instruction from the input file, create an InstructionObject (with fields representing the instruction type (READ, WRITE, BAD), the subject's name, the object's name, value if any). It's this InstructionObject that you pass to ReferenceMonitor. For an ill-formed instruction you should pass a constant BadInstruction object. The ReferenceMonitor should know how to deal with these objects.
To see how your system is behaving, you should write a debugging method printState in the SecureSystem class that prints out current values from the state: the value of objects and the TEMP value for subjects. See the example below for what the output of this could look like. Ideally, you would be able to iterate over your data structures to handle an arbitrary number of subjects/objects, but for this assignment you can assume that there are only two of each and you know their names. (Note: printing this kind of information is not something that a typical system user should be able to do.)

The main function in your SecureSystem class should perform the following tasks:

  1. Create two new subjects: Lyle of security level LOW, and Hal of security level HIGH. Store these subjects into the state and inform the reference monitor about them.

  2. Create two new objects: LObj of security level LOW, and HObj of security level HIGH. Store these in the ObjectManager, telling the ReferenceMonitor about their levels. The initial value of each should be 0.

  3. Read successive instructions from the input file and execute them, following the Bell and LaPadula constraints on reading and writing. You should have methods executeRead and executeWrite within your ReferenceMonitor class that check access requests and perform the appropriate update (if any) on the state, following the instruction semantics outlined above.

  4. After each instruction, call printState to display the state change, if any, from the instruction execution.

Below is a snippet of code from my main function. You don't have to follow this model, but you're welcome to.

 

        // LOW and HIGH are constants defined in the SecurityLevel 
        // class, such that HIGH dominates LOW.

	SecurityLevel low  = SecurityLevel.LOW;
	SecurityLevel high = SecurityLevel.HIGH;

	// We add two subjects, one high and one low.

	sys.createSubject("Lyle", low);
	sys.createSubject("Hal", high);

	// We add two objects, one high and one low.

	sys.getReferenceMonitor().createNewObject("Lobj", low);
	sys.getReferenceMonitor().createNewObject("Hobj", high);

	...

While designing your system consider the following questions: Are there security flaws in this design? What are they? How might you go about fixing them?

As an example of the execution, given the instruction list from Part 1, my implementation gives the following output. Note: none of this output would ordinarily be visible to Hal and Lyle.

> java SecureSystem instructionList

Reading from file: instructionList

Bad Instruction
The current state is: 
   LObj has value: 0
   HObj has value: 0
   Lyle has recently read: 0
   Hal has recently read: 0

Bad Instruction
The current state is: 
   LObj has value: 0
   HObj has value: 0
   Lyle has recently read: 0
   Hal has recently read: 0

lyle writes value 10 to lobj
The current state is: 
   LObj has value: 10
   HObj has value: 0
   Lyle has recently read: 0
   Hal has recently read: 0

hal reads lobj
The current state is: 
   LObj has value: 10
   HObj has value: 0
   Lyle has recently read: 0
   Hal has recently read: 10

lyle writes value 20 to hobj
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 10

hal writes value 200 to lobj
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 10

hal reads hobj
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 20

lyle reads lobj
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 10
   Hal has recently read: 20

lyle reads hobj
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 20

Bad Instruction
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 20

Bad Instruction
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 20

Bad Instruction
The current state is: 
   LObj has value: 10
   HObj has value: 20
   Lyle has recently read: 0
   Hal has recently read: 20

Extra Credit

You can get up to 2 points extra credit on this assignment. Since it's extra credit, I'm not going to give you detailed instructions on this part. If you want to do this one, you will have to use some ingenuity, though I'm happy to help you individually.

If you decide to do the extra credit, you should do the regular assignment and submit it. Then do this part separately. We'll tell you how to submit.

The assignment above is unrealistic in that the actions of subjects Lyle and Hal are totally synchronized according to the ordering of instructions in the input. Reimplement this assignment so that Lyle and Hal run as separate processes (threads), each reads from its own instruction file (remove the subject name argument to each instruction), and the reference monitor is a shared resource.

If you do this in the most straightforward way, they will run in an arbitrarily interleaved fashion depending on the OS scheduling. If the instruction lists are too short, whichever one gets the processor first likely will just blow through his instruction list, finishing before the other thread ever runs. Add an additional SLEEP instruction that relinguishes the processor. I.e., if Hal is running and executes a SLEEP instruction, then the processor should be handed to Lyle, etc. That way you can force interesting interleavings. Note that this still may not work as expected on multi-processor systems where the threads are scheduled on separate processors. Also, printing of the output may be oddly interleaved. Don't worry about that.

If you're having problems with the threads programming, these may help. Here is an excellent description of Java Synchronization by Ron Rockhold: Java Synchronization, and a link to helpful short paper by Prof. Mike Dahlin: Threads Programming.