Description

Layered architecture organizes large systems such that various system components are divided into groups, called layers, labeled with succesive integers, starting with zero; and which are subject to the following global constraint:

  1. Members of a layered system are assigned a non-negative integer that identifies their layer. This assignment, to given agent x, can be done dynamically, by a distinguished agent called manager, via a message setLevel(k) it sends to x.
  2. components can send messages to each other only if the sender resides at the layer of the target, or at the layer right above it; this constraint does not apply to the setLevel messages, mentioned above).

The example following the layered policy introduces a increased number of novel concepts that are not encountered in the previous example. The reader is urged to perform and understand the previous examples thoroughly. Furthermore, knowledge of certificates and public key cryptosystems are necessary. Since the trust relationship in this example is built using certificates and digital signatures, this example uses programmed agents rather than human (browser) interface (as used in the previous examples). Furthermore, a certified controller will be used in this case, and the laws will be expressed as direct text and not as URL -- as before. Due to this increased level of complexity, it is important that the steps outlined in this example are followed very closely.

The following components are required for this example:

  • key pairs for the controller(s) and the manager. Since the user will be required to fill in for certification authorities, public keys for the controller certifying authority (CA) and system administrator (sysadmin) are also required;
  • certificates for the controller(s) and for the manager;
  • MD5 hash for the public key of the certifying authority and the system administrator;
  • Programmed agents for the manager and optionally for the other agents. The human (browser) interface cannot be used for the manger since it does not allow the submission of certificates.
  • The changing of the law, in order to update the hash of the public keys -- which are hardcoded in the law.

The law

The Prolog version of this law follows:

law(la,authority(cAdmin),language(prolog)).

authority(cAdmin,keyHash(YOUR-KEY-HASH-IN-HERE)).  
authority(sysAdmin,keyHash(YOUR-KEY-HASH-IN-HERE)).

adopted(Par,cert([certificate(issuer(sysAdmin),subject(Self),attributes(A))])) :- 
        do(add(level(0))), (A=role(mgr) -> do(add(role(mgr)));true).

adopted(par(Args)) :- do(add(level(0))).

certified(Name,certificate(issuer(sysAdmin),subject(Self),attributes(role(mgr)))) :- 
        do(add(role(mgr))).

sent(X,getCS,Y) :- do(discloseCS(all)).

sent(X,setLevel(K),Y) :- role(mgr)@CS, do(forward).

arrived(X,setLevel(K),Y) :- level(K1)@CS,do(replace(level(K1),level(K))), do(deliver).

sent(X,M,Y) :- level(K)@CS, do(forward(X,[K,M],Y)).

arrived(X,[K,M],Y) :- level(K1)@CS, (K = K1; K1 is K-1), do(deliver(X,M,Y)).

disconnected :- do(quit).

The Prolog law can be found at:
http://www.moses.rutgers.edu/examples/layered/layered.law

This is the Java version of the law:

law(la,authority(cAdmin),language(java))

authority(cAdmin,keyHash(YOUR-KEY-HASH-IN-HERE)).  
authority(sysAdmin,keyHash(YOUR-KEY-HASH-IN-HERE)).

public class la extends Law{

    public void adopted(String arg, String[] issuer, String[] subject, String[] attributes) { 
        if (issuer.length != 0) {
            if (issuer[0].equals("sysAdmin") && subject[0].equals(Self) && attributes[0].equals("role(mgr)")) {
                doAdd("role(mgr)");
            }
        }
        doAdd("level(0)");
    }

    public void certified(String source, String issuer, String subject, String attributes) {
        if (issuer.equals("sysAdmin") && subject.equals(Self) && attributes.equals("role(mgr)")) {
             doAdd("role(mgr)");
        }
    }

    public void sent(String source, String message, String dest) {
        if (message.equals("getCS"))
	    doDiscloseAllCS();
        if (message.startsWith("setLevel") && CS.has("role(mgr)") ) {
	    doForward();
            return;
        }
        int levelK = CS.fetchInt("level");
	doForward(source, "extendedMessage(" + levelK + "," + message + ")", dest);
    }


    public void arrived(String source, String message, String dest) {
        String content = getContentFromMessage(message);
	Term levelTerm = CS.findT("level(%A)");
        if (message.startsWith("setLevel")) {
            doReplace(levelTerm.toString(),"level(" + content + ")");
            doDeliver();
            return;
        }
        if (message.startsWith("extendedMessage")) {
	    String trueMessage = content.substring(content.indexOf(',') + 1);
	    int levelK = Integer.parseInt(content.substring(0, content.indexOf(',')));
	    int levelK1 = CS.fetchInt("level");

	    if ((levelK >= levelK1) && (levelK <= levelK1 + 1)) {
	      doDeliver(source, trueMessage, Self);
	      return;
	    }            
        }
    }

    public void disconnected() {
	doQuit();
    }

    /**
        Helper method to parse the argument out of a regular expression
    */
    public String getContentFromMessage(String anyMessage) { 

        int index = anyMessage.indexOf("("); 

        if (index == -1) return ""; 
        else return anyMessage.substring(index+1, anyMessage.length()-1); 
    }
}
This law can be found at:
http://www.moses.rutgers.edu/examples/layered/layered.java1

The code of the programmed agent follows. This code differs from the code presented in the Quick Start in two aspects: it provides the agent to verify that a controller is well certified; and it allows an agent to submit certificates to the controller in order to gain privileges within the community.

import java.net.*;
import java.util.*;
import java.io.*;
import java.security.*; 

import moses.member.*;
import moses.security.*;
import moses.controlState.*;
import moses.util.*;

public class SomeAgent implements Agent{
    public void run (String[] args) throws Exception { 
	System.out.println("> Usage:");
	System.out.println("> java SomeAgent contrname contrport lawfile agname");
	System.out.println("> java SomeAgent contrname contrport lawfile agname CApub");
	System.out.println("> java SomeAgent contrname contrport lawfile agname CApub Mycert Myprivkey");
	
	//variables to read from the command line
	String contrname, contrport, lawfile, agname, ca = null, certf = null, priv = null;

	if(args.length < 4) {
	    System.out.println("> java SomeAgent contrname contrport lawfile agname");
	    System.out.println("> java SomeAgent contrname contrport lawfile agname CApub");
	    System.out.println("> java SomeAgent contrname contrport lawfile agname CApub Mycert Myprivkey");
	    return;
	}
	
	contrname = args[0];
	contrport = args[1];
	lawfile = args[2];
	agname = args[3];

	if(args.length ==5)
	    ca = args[4];
	
	if(args.length ==7) {
	    ca = args[4];
	    certf = args[5];
	    priv = args[6];
	}
	
	//retrieve the public key of the CA - required to verify that
	//the controller is properly certified
	Member m;
	PublicKey pubca = null;
	if(ca != null) {
	    pubca =   certCreation.getPublicKey(ca);
	}

	//retrieve the law from a local file

	FileInputStream fis  = new FileInputStream(lawfile);
        byte[] blaw = new byte[fis.available()];
        fis.read(blaw);
        String slaw = new String(blaw);
	

	//create the member of the community
	//if no public key is fed at the agent, the controller is not verified
	if(pubca == null)    
	    m = new Member(slaw,Const.IMM_LAW,contrname, Integer.parseInt(contrport), agname);
	else
	    m = new Member(slaw,Const.IMM_LAW,contrname, Integer.parseInt(contrport), agname, pubca);


	//if this agent is started as a manager, then
	//provide with the manager's certificate and signature
	if (certf!=null) {
	    LGICert  cert = certCreation.getCert(certf);
	    PrivateKey privk =   certCreation.getPrivateKey(priv);
	    byte[] sign = null;
	    sign =  Secu.signSelfCertificate(cert, privk);

	    m.addCertificate(cert, sign);
	}

	//become a member of the community
	System.out.println(m.adopt("mypassword","someargument"));


	//create a receiver object that receives messages
	//assynchronously from the controller

	new Receiver(this,m).start();


	//read messages from the console;
	//these messages are sent to the controller as soon as they are typed in

	System.out.println("Type exit to quit");
	for(;;) {
	    try{
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String command  = in.readLine();
		if (command.equals("exit")) {
		    m.close();
		    System.out.println("The Agent is shutting down...");
		    System.exit(0);
		}
		if (command.startsWith("send")) {
		    Term ct = Term.parse(command);
		    if(ct == null) {
			System.out.println("send(msg,dest) -- not understood. Try again!");
			continue;
		    }
		    Term tt = Term.parse("send(%M,%D)");
		    UnifyResult ur = ct.unify(tt);
		    if(ur == null) {
			System.out.println("send(msg,dest) -- not understood. Try again!");
			continue;
		    }
		    String msg = ur.getSVar("M");
		    String dest = ur.getSVar("D");
		    m.send_lg(msg,dest);
		}
	    } catch(Exception e) {
		;
	    }
	}
    }
    public void processRequest(Member member, String message, String destination) {
	;
    }
    public void processReply(Member member, String reply) {
	System.out.println("Received: " + reply);
    }
    public void processReply(Member member, byte[] breply) {
	System.out.println("Received: " + breply);
    }
    public void processReply(Member member, Object oreply) {
	System.out.println("Received: " + oreply);
    }

    public static void  main (String[] args) throws Exception { 
	SomeAgent somea = new SomeAgent();
	somea.run(args);
    }
}
This law can be found at:
http://www.moses.rutgers.edu/examples/layered/layered.java1

The code of the agent is available for download at:
http://www.moses.rutgers.edu/examples/layered/SomeAgent.java

Running the example

Instructions on running the example -- how to start the agents and how to observe the effects of the law.

  • Create a pair of keys for the controller certifying authority, using:
    > java moses.security.keyPairCreation CApub.key CApriv.key
    
  • Create a pair of keys for the controller , using:
    > java moses.security.keyPairCreation Contrpub.key Contrpriv.key
    
  • Create a pair of keys for the system admin authority, using:
    > java moses.security.keyPairCreation Syspub.key Syspriv.key
    
  • Create a pair of keys for the manager, using:
    > java moses.security.keyPairCreation MGRpub.key MGRpriv.key
    
  • Create a certificate for the controller, signed by the CA, using:
    > java moses.security.certCreation CApub.key CApriv.key Contrpub.key Contrcertfile certifiedController 
  • Create a certificate for the manager, signed by the system authority, using in Unix. Note that this step may vary depending on the type of operating system and shell available (Ex: role(mgr), role\(mgr\), "role\(mgr\)", etc.) :
    > java moses.security.certCreation Syspub.key Syspriv.key MGRpub.key MGRcertfile role(mgr) 
    or in Windows:
    > java moses.security.certCreation Syspub.key Syspriv.key MGRpub.key MGRcertfile role(mgr) 
  • Extract the hash of the public keys for the CA and SysAuth as follows:
    > java moses.controller.AuthorityTable -fCApub.key
    > java moses.controller.AuthorityTable -fSyspub.key
  • Download and modify the layered law such that its preamble displays the newly computed hash for the public key of the CA and the system authority.
    authority(cAdmin,keyHash(1FF4A9E377A649866C9CA89144334406))    
    authority(sysAdmin,keyHash(3B50B143ADFC9A735C4D21EF52952A59)) 
    
  • Start a certified controller, using the following command:
    > java moses.Controller -cFileContrcertfile -kFileContrpriv.key
    Controller starts (use -help option for help)
    Reading certificate and private key from the current directory
    in signing message... 
    ramses.rutgers.edu:9000 is sandboxed
    Location of the configuration files is:
     
    
  • Create a programmed agent that will serve as manager. For this, download SomeAgent.java, compile it and execute it in the same directory with the public keys and certificates, as follows:
    > javac SomeAgent.java
    > java SomeAgent controller-host 9000 layered.java1 mgr CApub.key MGRcertfile MGRpriv.key
    
    The following output should be displayed
    > java SomeAgent contrname contrport lawfile agname
    > java SomeAgent contrname contrport lawfile agname CApub
    > java SomeAgent contrname contrport lawfile agname CApub Mycert Myprivkey
    in signing message... 
    -1
    Type exit to quit
    
    If the output displays error 8 instead of -1 (success), then the CApub.key file does not correspond to the key used in the creation of the controller certificate. If the error number is 10, then the same name (i.e. mgr) is already in use.
  • Open two different consoles, and in the same directory launch two agents x and y, as follows:
    > java SomeAgent research.rutgers.edu 9000 layered.java1 x  CApub.key
    
    > java SomeAgent research.rutgers.edu 9000 layered.java1 y CApub.key
    
    An output identical to the one above should be displayed.
  • In order to observe the communication within the community, try to exchange some messages between x and y. In the x's console, type in send(somemessage,x@hostname) and observe y's console displaying Received: somemessage. Try the same message from y to x. The mesages are permitted because initially x and y have both the same level: 0 .
  • In the manager's window, send the following message send(setLevel(3),x@hostname). X's window should display Received: setLevel(3). When trying to exchange messages between x and y, no message is propagated anymore. Reset y's level by typing in the manager's window the following: send(setLevel(2),y@hostname). Observe now that all the messages from x to y are propagated but not the other way.
  • In order to verify the role of the manager, have an un-authenticated agent try to reset the level of other agent. In order to attempt that, in y's window type in the following message send(setLevel(2),x@hostname). Observe that x does not receive any message (its level is greater that y's level). When the manager attempts that, however, x receives the message and changes its level accordingly.
  • As the last point, in order to show how the authenticated controller works, have the controller started with a wrong private key. Whenever the agent tries to connect to the controller, the agent reports the connection error 8: failure to authenticate the controller. Furthermore, in order to prevent the communication between non authentic controller, run the same experiment with two controllers: one started with a certificate, as above; and one started with no certificate / no private key. Create an agent x, as above, and connect it to the authenticated controller. Create an agent y connected to the un-authenticated controller (without supplying the CApub.key argument). Try to exchange messages between x and y and observe that no message is propagated. This restriction follows from the condition specified in the preamble that all the controllers running the layered law should be authenticated using a certificate signed by CApub.key.
  • For more features, continue the interaction with a greater number of agents and levels, and observe the behavior.