001: //
002: // This file is part of the prose package.
003: //
004: // The contents of this file are subject to the Mozilla Public License
005: // Version 1.1 (the "License"); you may not use this file except in
006: // compliance with the License. You may obtain a copy of the License at
007: // http://www.mozilla.org/MPL/
008: //
009: // Software distributed under the License is distributed on an "AS IS" basis,
010: // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: // for the specific language governing rights and limitations under the
012: // License.
013: //
014: // The Original Code is prose.
015: //
016: // The Initial Developer of the Original Code is Andrei Popovici. Portions
017: // created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
018: // All Rights Reserved.
019: //
020: // Contributor(s):
021: // $Id: SecureLocalAspectManager.java,v 1.2 2005/06/25 17:23:09 anicoara Exp $
022: // =====================================================================
023: //
024: // (history at end)
025: //
026:
027: package ch.ethz.prose;
028:
029: // used packages
030: import java.io.FileInputStream;
031: import java.io.IOException;
032: import java.security.AccessController;
033: import java.security.KeyStore;
034: import java.security.KeyStoreException;
035: import java.security.NoSuchAlgorithmException;
036: import java.security.PrivilegedAction;
037: import java.security.PublicKey;
038: import java.security.cert.Certificate;
039: import java.security.cert.CertificateException;
040: import java.util.Enumeration;
041: import java.util.Hashtable;
042:
043: import ch.ethz.inf.util.Logger;
044:
045: /**
046: * Class SecureLocalAspectManager extends LocalAspectManager. It recognizes
047: * SignedExtensions in <code>insertExtension</code> and performs the insertion
048: * under the permissions granted to the SecureLocalAspectManager class, in case
049: * that the signature is valid and the signer is trusted to insert extensions.<p>
050: *
051: * @version $Revision: 1.2 $
052: * @author Marcel Mueller
053: *
054: * <P>
055: * Used Properties:
056: * <UL>
057: * <LI><CODE>ch.ethz.prose.keystore.location</CODE>
058: * <b>Values:</b> path to keystore to use<br>
059: * <b>Usage:</b></LI>
060: * <LI><CODE>ch.ethz.prose.keystore.password</CODE>
061: * <b>Values:</b> password to keystore<br>
062: * <b>Usage:</b></LI>
063: * </UL>
064: */
065: public class SecureLocalAspectManager extends LocalAspectManager {
066:
067: private KeyStore keyStore;
068: private Hashtable certTable;
069:
070: /**
071: * Constructs an extension manager that inserts SignedExtensions under privileged rights
072: */
073: public SecureLocalAspectManager(boolean isConnectedToVM,
074: ch.ethz.jvmai.JVMAspectInterface ai) {
075: super (isConnectedToVM, ai);
076: }
077:
078: /**
079: * Decides whether a key is valid and trusted to insert an extension
080: * under the privileged permissions of this class.<p>
081: *
082: * The actual implementation is very restricted: accepts if a trusted
083: * certificate exists in the keystore defined by the system properties
084: * <code>ch.ethz.prose.keystore.location</code> and
085: * <code>ch.ethz.prose.keystore.password</code>. (ATTENTION: THIS
086: * IS A HUGE SECURITY HOLE!!!). Feel free to build a
087: * subclass with a better implementation.<p>
088: *
089: * It was thought to attach certificates to signed extensions to help
090: * the target system to make its decision. As in JDK 1.2.2 the class
091: * java.security.cert.Certificate is not Serializable, this feature is
092: * unluckily not yet implemented.
093: *
094: * @param key the key that signed the extension
095: * @return <code>true</code> if a trusted certificate exists in the keystore
096: */
097: protected boolean validateKey(PublicKey key) {
098: try {
099: return isTrusted(key);
100: } catch (Exception e) {
101: Logger
102: .message("SecureLocalAspectManager.validateKey: exception occurred ("
103: + e + ")");
104: return false;
105: }
106: }
107:
108: /**
109: * Insert the extension <code>ext</code> into the extension
110: * manager. If <code>ext</code> is of type <code>SignedAspect</code>,
111: * the signature is verified and if the key is known to be trusted to
112: * insert extensions, the insertion is performed exclusively under the rights
113: * granted to this class.<p>
114: *
115: * If the extension fails the verification or the key is not trusted, it is attempted
116: * to install the extension in the usual way (without privileged permissions).
117: *
118: * @param ext the extension to be inserted
119: * @exception AspectManagerException if extension cannot be installed
120: */
121: public synchronized void insert(Aspect ext)
122: throws AspectManagerException {
123: if (ext == null) {
124: throw new AspectManagerException(
125: "Attempt to insert \"null\" as Aspect!");
126: }
127:
128: if (ext instanceof SignedAspect) {
129: final SignedAspect se = (SignedAspect) ext;
130:
131: Boolean b = (Boolean) AccessController
132: .doPrivileged(new PrivilegedAction() {
133: public Object run() {
134: try {
135: // verify if extension was signed correctly with containing key
136: se.verifyExtension();
137: } catch (Exception e) {
138: Logger
139: .message("SecureLocalAspectManager.insertExtension: extension could not be verified");
140: return Boolean.FALSE;
141: }
142:
143: // validate the key (do we trust this public key to insert extensions?)
144: if (validateKey(se.getPublicKey())) {
145: // do super: we vouch for the extension to be a friendly one: it is inserted with our privileges
146: try {
147: super InsertExtension(se);
148: } catch (Exception e) {
149: Logger
150: .message("SecureLocalAspectManager.insertExtension: priviliged insertion did not succeed ("
151: + e + ")");
152: }
153: return Boolean.TRUE;
154:
155: } else {
156: Logger
157: .message("SecureLocalAspectManager.insertExtension: signer of extension is not trusted");
158: return Boolean.FALSE;
159: }
160: }
161: });
162:
163: if (b.booleanValue()) {
164: return;
165: }
166: }
167:
168: super .insert(ext);
169: }
170:
171: // work-around, I could not find direct way to call super method out of an inner class
172: private synchronized void super InsertExtension(Aspect ext)
173: throws AspectManagerException {
174: super .insert(ext);
175: }
176:
177: // get keystore instance
178: private KeyStore getKeyStore() throws KeyStoreException,
179: NoSuchAlgorithmException, IOException, CertificateException {
180: if (keyStore == null) {
181: String ksl = System
182: .getProperty("ch.ethz.prose.keystore.location");
183: String ksp = System
184: .getProperty("ch.ethz.prose.keystore.password");
185:
186: keyStore = KeyStore.getInstance("JKS");
187: keyStore.load(new FileInputStream(ksl), ksp.toCharArray());
188: }
189:
190: return keyStore;
191: }
192:
193: // is there a trusted certificate in our keystore?
194: private boolean isTrusted(PublicKey key) throws KeyStoreException,
195: NoSuchAlgorithmException, IOException, CertificateException {
196: if (certTable == null) {
197: certTable = new Hashtable();
198:
199: KeyStore ks = getKeyStore();
200:
201: Enumeration enumeration = ks.aliases();
202: while (enumeration.hasMoreElements()) {
203: String alias = (String) enumeration.nextElement();
204: Certificate[] certs = ks.getCertificateChain(alias);
205:
206: if (certs != null) {
207: for (int i = 0; i < certs.length; i++) {
208: certTable
209: .put(certs[i].getPublicKey(), certs[i]);
210: }
211: }
212: }
213: }
214:
215: return certTable.containsKey(key);
216: }
217: }
218:
219: //======================================================================
220: //
221: // $Log: SecureLocalAspectManager.java,v $
222: // Revision 1.2 2005/06/25 17:23:09 anicoara
223: // Bugfix JDK 5.0: Changed 'enum' with 'enumeration'; 'enum' is a keywork in JDK 5.0
224: //
225: // Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
226: // Imported from ETH Zurich
227: //
228: // Revision 1.1 2003/05/05 13:58:30 popovici
229: // renaming from runes to prose
230: //
231: // Revision 1.1 2003/04/17 15:15:08 popovici
232: // Extension->Aspect renaming
233: //
234: // Revision 1.5 2003/03/04 18:36:36 popovici
235: // Organization of imprts
236: //
237: // Revision 1.4 2003/03/04 11:27:16 popovici
238: // Important refactorization step (march):
239: // - removal of 'JoinPointEvents'; JoinPoints now have the same function as events
240: // - reimplementation of the JVMAIDebuggerAspectInterface (better performance, coding conventions, removal of ProseVM
241: // structures
242: //
243: // Revision 1.3 2002/11/26 17:14:32 pschoch
244: // RootComponent now added (replaces RootComponent now added (replaces old ProseSystem)
245: // ProseSystem now owns and starts the Aspect interface.
246: // ProseSystem now containes a 'test' AspectManager
247: // AspectManager now owns the JoinPointManager.
248: // ExtensionManger can be 'connected' to the JVM, or disconnected. The
249: // JoinPointManager of a connected Ext.Mgr enables joinpoints; the
250: // JoinPointManger of a disconnected Ext.Mgr never enables join-points
251: // Documentation updated accordingly.
252: //
253: // Revision 1.2 2002/03/28 13:48:38 popovici
254: // Mozilla-ified
255: //
256: // Revision 1.1.1.1 2001/11/29 18:13:16 popovici
257: // Sources from runes
258: //
259: // Revision 1.1.2.6 2001/04/28 11:29:32 mrmuller
260: // removed debug info
261: //
262: // Revision 1.1.2.5 2001/04/27 07:06:55 mrmuller
263: // more logging messages at insertExtension
264: //
265: // Revision 1.1.2.4 2001/04/10 16:25:03 mrmuller
266: // added JavaDoc property documentation
267: //
268: // Revision 1.1.2.3 2001/04/10 11:16:03 mrmuller
269: // Signature.getInstance() replaces passing of verification engine as parameter
270: //
271: // Revision 1.1.2.2 2001/03/16 17:29:17 mrmuller
272: // cosmetics, javadoc and exception handling changes
273: //
274: // Revision 1.1.2.1 2001/03/16 13:12:31 mrmuller
275: // initial release of new (really) secure extension insertion mechanism
276: //
277: //
|