CS361 Assignment 1

Due: Monday, September 22 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 information is at the bottom.

Submission: In order to get the first 10 points, you must submit a zip file, the name of which has to be UTEID_program1.zip (where UTEID is your UT EID). If you have a partner, please provide both your UTEIDs in the name of the zip file: UTEID1_UTEID2_program1.zip. In order to get the extra credit points, you need to submit another zip file: UTEID_program1_extra.zip file. Note these may be graded by different graders. You can't get the first 10 points based on UTEID_program1_extra.zip. Similarly, you can't get extra credit points based on UTEID_program1.zip. We'll be using a program to collect everyone's submission file. If you use an incorrect naming convention, you will have to go to the TA's office hours to handle this issue.

Partner/Team: If you're working in a team, ONLY one of the student in the team needs to submit the zip file using his/her account.

Grading README file: Your zip file must contain a README.txt file. Here's a sample: Sample README fils. We're also using a program to grade your README.txt file. Any other names or formats of REAMDE file won't be accepted, e.g. readme.txt, readme, README, README.c, README.java. The README.txt file is worth 2 (of the 10 points). If you use the incorrect REAMDE.txt file, you have to go to TA's office hour to handle this issue.

For the README.txt file, the maximum point is 2.

  1. First Five Lines [0.5 point] have to match the following format

    UTEID: jd1234; bp5678;

    FIRSTNAME: Johnny; Brad;

    LASTNAME: Deep; Pitt;

    CSACCOUNT: johnyd; bradp;

    EMAIL: johnyd@cs.utexas.edu; bradp@cs.utexas.edu;

    Please don't remove "UTEID". Please don't remove ":". Also please don't remove ";".

  2. Good description of your code [0.5 point]

    You have to write some sentences(at least 400 words) to explain high-level idea of program, some short description of the key/important function in your code.

  3. You need to tell us how much you've finished [0.5 point]

    (1) Finished all requirements (2) Only finished parts of the requirements.

    If you're in the case (2), you have to list the unfinished things and write down the reasons for each, either no time or have some bugs. If grader thought you explanation is very good and detailed, you won't lose 1 point even if you didn't finish many requirements of program.

  4. Create enough of your own test cases [0.5 point]

    First, you have to write down one sentence to claim how many test cases have you created. If you have >=4 test cases, you will get 0.5 point. Second, you still need to attach all your own test cases and the output of that at the end of README.txt file. Third, you don't need to create some crazy test cases, our test case has around 10-20 lines. It is already very nice if your test case has 10 lines. You don't need to create some crazy test cases that have > 100 lines.

The grading scheme of this README.txt file has very little to do with the correctness of your program. Even if your program doesn't work well, please try your best to provide the details of the README.txt file, you still have a chance to get 2 out of 2 points.

Grading Program: For the program, the maximum point is 8.

  1. You will get [2 points] if the program can be compiled. Before submission, make sure that your code can be compiled and executed on the Linux Machine (in our CS Lab). Even if your code is working on your own machine(Windows, ...), and not working on CS Lab machine, you won't get any points!

  2. You will get [4 points] If the program can be run.

  3. We will run a few simple test cases(similar to the example that provided later in this page) and check the output of your program line by line. Each line can be counted at most 1 mistake. You will get [6 points] If the program makes >= 8 mistakes.

  4. You will get [7 points] If the program makes fewer than 4 mistakes.

  5. You will get [8 points] If the program makes no mistake.

Deliverables: You will be submitting your code electronically using Canvas. 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.