module poaBank { interface Account { | exception InsufficientFunds {}; | | float deposit(in float sum); | | float withdraw(in float sum) raises (InsufficientFunds); | | readonly attribute float balance; }; interface Bank { | exception noSuchAccount {}; | | Account getAccount(in long accountNum) raises (noSuchAccount); }; };
package poaBankSecure; import util.Util; import org.omg.CORBA.Any; import org.omg.CORBA.ORB; import org.omg.CORBA.Policy; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContext; import org.omg.CosNaming.NamingContextHelper; import org.omg.CosNaming.NamingContextPackage.NotFound; import com.sssw.jbroker.api.security.QualityOfProtection; import com.sssw.jbroker.api.security.CSIv2.ClientAuthInfo; import com.sssw.jbroker.api.security.CSIv2.SecurityPolicy; import com.sssw.jbroker.api.security.CSIv2.SecurityCurrent; import com.sssw.jbroker.api.security.CSIv2.SecurityPolicyValue; import com.sssw.jbroker.api.security.CSIv2.Authenticator; import com.sssw.jbroker.api.security.CSIv2.IdentityToken; import com.sssw.jbroker.api.security.CSIv2.InitialContextToken; import org.omg.PortableServer.POA; import org.omg.PortableServer.Servant; import org.omg.PortableServer.LifespanPolicyValue; import org.omg.PortableServer.IdAssignmentPolicyValue; import poaBank.Bank; import poaBank.BankHelper; public class Server { public static void main(String[] args) { | try { | | | | // create the jBroker ORB | | ORB orb = ORB.init(args, null); | | | | // get the root POA | | POA rootPOA = (POA) orb.resolve_initial_references("RootPOA"); | | | | // get the security current | | SecurityCurrent secCurrent = (SecurityCurrent) orb. | | resolve_initial_references("SecurityCurrent"); | | | | // set an authenticator | | secCurrent.setAuthenticator(new Authenticator() { | | | public int authenticate(InitialContextToken initCtxToken) { | | | | System.out.println("user = " + initCtxToken.getUserName()); | | | | System.out.println("password = " + initCtxToken. | | | | getPassword()); | | | | System.out.println("realm = " + initCtxToken.getRealm()); | | | | return Authenticator.SUCCESS; | | | } | | | public boolean assertIdentity(IdentityToken identityToken) | | | { return true; } | | }); | | | | // create the CSIv2 security Policy | | Any any = orb.create_any(); | | any.insert_Value(new SecurityPolicyValue(null, new ClientAuthInfo( | | "bank", false), true)); | | SecurityPolicy secPolicy = (SecurityPolicy) orb.create_policy( | | SecurityPolicy.POLICY_TYPE, any); | | | | // create a persistent user assigned ids POA | | POA bankPOA = (POA) rootPOA.create_POA("bankPOA", | | rootPOA.the_POAManager(), | | new Policy[] { | | | rootPOA.create_id_assignment_policy( | | | IdAssignmentPolicyValue.USER_ID), | | | rootPOA.create_lifespan_policy( | | | LifespanPolicyValue.PERSISTENT), | | | secPolicy, | | }); | | | | // create and activate bank servant | | Servant bank = new BankImpl(orb, bankPOA, args[0]); | | bankPOA.activate_object_with_id("bank".getBytes(), bank); | | | | // get the root of the NameService | | NamingContext root = NamingContextHelper.narrow( | | orb.resolve_initial_references("NameService")); | | | | // if not done before, publish the bank objref | | NameComponent nc = new NameComponent("secureBank", ""); | | NameComponent[] name = new NameComponent[] { nc }; | | try { | | | root.resolve(name); | | } catch (NotFound ex) { | | | // create the bank objref | | | Bank bankObj = BankHelper.narrow(bankPOA. | | | create_reference_with_id("bank".getBytes(), | | | bank._all_interfaces(null, null)[0])); | | | | | | System.out.println(orb.object_to_string(bankObj)); | | | root.rebind(name, bankObj); | | } | | | | // activate bankPOA | | bankPOA.the_POAManager().activate(); | | | | // wait for invocations | | System.out.println("waiting for invocations ..."); | | orb.run(); | | | } catch (Exception ex) { | | ex.printStackTrace(); | } } }
package poaBankSecure; import java.io.File; import org.omg.CORBA.ORB; import org.omg.CORBA.Policy; import org.omg.PortableServer.POA; import org.omg.PortableServer.Servant; import org.omg.PortableServer.IdUniquenessPolicyValue; import org.omg.PortableServer.IdAssignmentPolicyValue; import org.omg.PortableServer.ServantRetentionPolicyValue; import org.omg.PortableServer.RequestProcessingPolicyValue; import com.sssw.jbroker.api.security.CSIv2.SecurityPolicy; import com.sssw.jbroker.api.security.CSIv2.SecurityCurrent; import poaBank.BankPOA; import poaBank.Account; import poaBank.AccountHelper; import poaBank.BankPackage.noSuchAccount; public class BankImpl extends BankPOA { ORB _orb; POA _acctPOA; String _acctRepId; // repository Id for Account Objects Servant _defaultServant; SecurityCurrent _securityCurrent; BankImpl(ORB orb, POA bankPOA, String dir) throws Exception { | _orb = orb; | | // make sure that the DB dir exists | File dbDir = new File (dir); | if (!dbDir.exists()) dbDir.mkdir(); | | // get the securtity current | _securityCurrent = (SecurityCurrent) _orb.resolve_initial_references( | "SecurityCurrent"); | | // create the POA for Transient Account Objects | _acctPOA = bankPOA.create_POA("acctPOA", bankPOA.the_POAManager(), | new Policy[] { | | bankPOA.create_id_assignment_policy( | | IdAssignmentPolicyValue.USER_ID), | | bankPOA.create_request_processing_policy( | | RequestProcessingPolicyValue.USE_DEFAULT_SERVANT), | | bankPOA.create_id_uniqueness_policy( | | IdUniquenessPolicyValue.MULTIPLE_ID) | }); | | // set the servant manager in Acct POA | _defaultServant = new AccountImpl(_orb, dbDir); | _acctPOA.set_servant(_defaultServant); | | // compute the repository id for Account objects | _acctRepId = _defaultServant._all_interfaces(null, null)[0]; } public Account getAccount(int acctNum) throws noSuchAccount { | Account account = null; | | // print out the IP Address of the caller | System.out.println("IP = " + _securityCurrent.getInetAddress()); | | if ((acctNum >= 100) && (acctNum < 110)) { | | | | // construct the object id for account | | byte objectId[] = new byte[1]; | | objectId[0] = (byte) (acctNum & 0xFF); | | | | try { | | | account = AccountHelper.narrow(_acctPOA. | | | create_reference_with_id(objectId, _acctRepId)); | | } catch (Exception ex) { | | | // org.omg.PortableServer.POAPackage.WrongPolicy | | | // thrown on JDK 1.2 and 1.3 | | | ex.printStackTrace(); | | } | } | | if (account == null) throw new noSuchAccount(); | | return account; } }
In this example, the Account datastore is a local Java object. If the Account datastore had been a remote object (possibly running elsewhere), the identity "bankserver" would have propagated to it.
package poaBankSecure; import java.io.File; import org.omg.CORBA.ORB; import org.omg.CORBA.INTERNAL; import org.omg.CORBA.INITIALIZE; import org.omg.CORBA.PERSIST_STORE; import poaBank.AccountPOA; import poaBank.AccountPackage.InsufficientFunds; import com.sssw.jbroker.api.security.SecurityException; import com.sssw.jbroker.api.security.CSIv2.IdentityToken; import com.sssw.jbroker.api.security.CSIv2.SecurityContext; import com.sssw.jbroker.api.security.CSIv2.SecurityCurrent; public class AccountImpl extends AccountPOA { ORB _orb; AccountBalances _accountsDb; SecurityCurrent _securityCurrent; SecurityContext _bankServerCtx; public AccountImpl(ORB orb, File acctDb) throws Exception { | _orb = orb; | | // get the SecurityCurrent | _securityCurrent = (SecurityCurrent) orb. | resolve_initial_references("SecurityCurrent"); | | // create a security context | _bankServerCtx = _securityCurrent.newContext(); | _bankServerCtx.setIdentityToken(_securityCurrent.createIdentityToken( | "bankserver", "bank")); | | // create the account Db | _accountsDb = new AccountBalances(acctDb, _securityCurrent); } private AccountRecord getAccount(int acctNum) { | try { | | try { | | | _securityCurrent.stackThreadContext(_bankServerCtx); | | | | | | return _accountsDb.getAccount(acctNum); | | | | | } finally { | | | _securityCurrent.unstackThreadContext(_bankServerCtx); | | } | | | } catch (SecurityException ex) { | | ex.printStackTrace(); | | throw new INTERNAL(); | } } public float deposit(float sum) { | int acctNum = getAccountNumber(); | | AccountRecord record = getAccount(acctNum); | | float balance = 0; | synchronized (record) { | | balance = record.getBalance() + sum; | | record.setBalance(balance); | } | | return balance; } public float withdraw(float sum) throws InsufficientFunds { | int acctNum = getAccountNumber(); | | AccountRecord record = getAccount(acctNum); | | float balance = 0; | synchronized (record) { | | balance = record.getBalance(); | | if ((balance - sum) < 0) | | throw new InsufficientFunds(); | | balance -= sum; | | record.setBalance(balance); | } | | return balance; } public float balance() { | return getAccount(getAccountNumber()).getBalance(); } private int getAccountNumber() { | return _object_id()[0] & 0x000000FF; } }
5.1 Account Balances
The getAccount method checks that the caller is "bankserver" from the "bank" realm.package poaBankSecure; import java.io.File; import java.util.Hashtable; import org.omg.CORBA.NO_PERMISSION; import com.sssw.jbroker.api.security.SecurityException; import com.sssw.jbroker.api.security.CSIv2.SecurityContext; import com.sssw.jbroker.api.security.CSIv2.SecurityCurrent; // Datastore for Account Balances class AccountBalances { File _dbDir; Hashtable _table; SecurityCurrent _current; AccountBalances(File dbDir, SecurityCurrent current) { | _dbDir = dbDir; | _table = new Hashtable(19); | _current = current; } synchronized AccountRecord getAccount(int acctNum) throws SecurityException { | // verify the caller | if (!_current.getCaller().getIdentityToken("bank").getUser(). | equals("bankserver")) throw new NO_PERMISSION(); | | Integer AcctNum = new Integer(acctNum); | | AccountRecord record = (AccountRecord) _table.get(AcctNum); | | if (record == null) { | | record = new AccountRecord(0, new File(_dbDir, | | AcctNum.toString())); | | _table.put(AcctNum, record); | } | | return record; } }5.2 Account Record
package poaBankSecure; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.omg.CORBA.PERSIST_STORE; class AccountRecord { private float _balance; private File _file; AccountRecord(float balance, File file) { | _file = file; | _balance = balance; | | // if file exists read balance | if (_file.exists()) { | | try { | | | FileInputStream fis = new FileInputStream(_file); | | | ObjectInputStream ois = new ObjectInputStream(fis); | | | _balance = ((Float) ois.readObject()).floatValue(); | | | ois.close(); | | } catch (Exception ex) { | | | throw new PERSIST_STORE(); | | } | } } float getBalance() { | return _balance; } void setBalance(float balance) { | _balance = balance; | | try { | | FileOutputStream fos = new FileOutputStream(_file); | | ObjectOutputStream oos = new ObjectOutputStream(fos); | | oos.writeObject(new Float(_balance)); | | oos.close(); | } catch (Exception ex) { | | throw new PERSIST_STORE(); | } } }
server.main=poaBankSecure.Server server.alias=secureBank server.classpath=/usr/local/JBroker/examples/lib server.args=/usr/local/JBroker/examples/src/poaBankSecure/db server.vmflags=-DORBDebug=true
The client authenticates itself using the account number and PIN it gets from the user and sets the authenticated Principal at the ORB level. Had the client started multiple threads, they would all be running with the same identity.
package poaBankSecure; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.StringTokenizer; import org.omg.CORBA.ORB; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContext; import org.omg.CosNaming.NamingContextHelper; import com.sssw.jbroker.api.security.CSIv2.AuthCallback; import com.sssw.jbroker.api.security.CSIv2.SecurityContext; import com.sssw.jbroker.api.security.CSIv2.SecurityCurrent; import com.sssw.jbroker.api.security.CSIv2.InitialContextToken; import poaBank.Bank; import poaBank.Account; import poaBank.BankHelper; import poaBank.AccountPackage.InsufficientFunds; public class Client { ORB _orb; Bank _bank; Account _account; String _acctNum; String _acctPIN; public static void main(String[] args) { | try { | | new Client().run(args); | } catch (Exception ex) { | | ex.printStackTrace(); | } } public void run(String[] args) throws Exception { | // create the jBroker ORB | _orb = ORB.init(args, null); | | // get the root of the NameService | NamingContext root = NamingContextHelper.narrow( | _orb.resolve_initial_references("NameService")); | | // get the bank object reference | NameComponent nc = new NameComponent(args[0], ""); | NameComponent[] name = new NameComponent[] { nc }; | _bank = BankHelper.narrow(root.resolve(name)); | | // enter the request processing loop | processCommands(); } void processCommands() throws Exception { | // create a input stream reader | BufferedReader reader = new BufferedReader(new InputStreamReader( | System.in)); | | // get the account number | System.out.print("Enter Account number: "); | System.out.flush(); | _acctNum = reader.readLine(); | | // get the account PIN | System.out.print("Enter Account PIN: "); | System.out.flush(); | _acctPIN = reader.readLine(); | | // get the security current | SecurityCurrent secCurrent = (SecurityCurrent) _orb. | resolve_initial_references("SecurityCurrent"); | | // set up the security context | SecurityContext secContext = secCurrent.newContext(); | secContext.setInitialContextToken(secCurrent.createInitialContextToken( | _acctNum, _acctPIN, "bank")); | secCurrent.setORBContext(secContext); | | // get the account object | _account = _bank.getAccount(new Integer(_acctNum).intValue()); | | // enter the read-execute loop | while (true) { | | System.out.print("bank > "); | | executeCommand(readCommandLine(reader)); | } } void executeCommand(String[] command) throws Exception { | if (command.length == 0) | printHelp(); | | // get balance | else if (command[0].equals("b")) | System.out.println("\tbalance: $" + _account.balance()); | | // check the command for addition parameter | else if (command[0].equals("d")) { | | if (command.length != 2) printHelp(); | | else System.out.println("\tbalance: $"+ _account.deposit(new Float( | | command[1]).floatValue())); | } | | // deposit money | else if (command[0].equals("w")) { | | if (command.length != 2) printHelp(); | | else { | | | try { | | | | System.out.println("\tbalance: $"+ _account.withdraw( | | | | new Float(command[1]).floatValue())); | | | } catch (InsufficientFunds ex) { | | | | System.out.println("\tInsufficient Funds!"); | | | } | | } | } | | // quit | else if (command[0].equals("q")) { | | System.exit(0); | } | | // print help | else printHelp(); } void printHelp() { | System.out.println(); | System.out.println("\tCommands:"); | System.out.println("\t b // get balance"); | System.out.println("\t d <sum> // deposit sum"); | System.out.println("\t w <sum> // withdraw sum"); | System.out.println("\t q // quit"); | System.out.println(); } String[] readCommandLine(BufferedReader reader) throws Exception { | int i=0; | | String line = reader.readLine(); | | if (line == null) System.exit(0); | | StringTokenizer tokenizer = new StringTokenizer(line); | String[] command = new String[tokenizer.countTokens()]; | while (tokenizer.hasMoreTokens()) { | | command[i++] = tokenizer.nextToken(); | } | | return command; } }
Copyright © 2000-2003, Novell, Inc. All rights reserved. |