001 package org.cumulus4j.keymanager.api.internal.local;
002
003 import java.io.File;
004 import java.io.IOException;
005 import java.net.MalformedURLException;
006 import java.net.URI;
007 import java.net.URISyntaxException;
008 import java.net.URL;
009 import java.util.Collections;
010 import java.util.HashMap;
011 import java.util.Map;
012
013 import org.cumulus4j.keymanager.AppServer;
014 import org.cumulus4j.keymanager.AppServerManager;
015 import org.cumulus4j.keymanager.api.AuthenticationException;
016 import org.cumulus4j.keymanager.api.CannotDeleteLastUserException;
017 import org.cumulus4j.keymanager.api.CryptoSession;
018 import org.cumulus4j.keymanager.api.DateDependentKeyStrategyInitParam;
019 import org.cumulus4j.keymanager.api.DateDependentKeyStrategyInitResult;
020 import org.cumulus4j.keymanager.api.KeyManagerAPIConfiguration;
021 import org.cumulus4j.keymanager.api.KeyManagerAPIInstantiationException;
022 import org.cumulus4j.keymanager.api.KeyStoreNotEmptyException;
023 import org.cumulus4j.keymanager.api.internal.AbstractKeyManagerAPI;
024 import org.cumulus4j.keystore.DateDependentKeyStrategy;
025 import org.cumulus4j.keystore.KeyStore;
026 import org.cumulus4j.keystore.UserNotFoundException;
027
028 /**
029 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
030 */
031 public class LocalKeyManagerAPI extends AbstractKeyManagerAPI
032 {
033 private KeyStore keyStore;
034 private AppServerManager appServerManager;
035 private Map<String, String> appServerBaseURL2appServerID = Collections.synchronizedMap(new HashMap<String, String>());
036
037 private KeyStore getKeyStore() throws IOException
038 {
039 KeyStore ks = this.keyStore;
040
041 if (ks == null) {
042 ks = new KeyStore(getKeyStoreID(), getKeyStoreFile());
043 this.keyStore = ks;
044 }
045
046 return ks;
047 }
048
049 private AppServerManager getAppServerManager() throws IOException
050 {
051 AppServerManager asm = this.appServerManager;
052
053 if (asm == null) {
054 asm = new AppServerManager(getKeyStore());
055 this.appServerManager = asm;
056 }
057
058 return asm;
059 }
060
061 private File getKeyStoreFile() throws IOException
062 {
063 File keyStoreDir;
064 String keyManagerBaseURL = getKeyManagerBaseURL();
065
066 if (keyManagerBaseURL == null) {
067 String userHome = System.getProperty("user.home"); //$NON-NLS-1$
068 if (userHome == null)
069 throw new IllegalStateException("System property user.home is not set! This should never happen!"); //$NON-NLS-1$
070
071 keyStoreDir = new File(userHome, ".cumulus4j");
072 }
073 else {
074 if (!keyManagerBaseURL.startsWith(FILE_URL_PREFIX))
075 throw new IllegalStateException("keyManagerBaseURL does not start with \"" + FILE_URL_PREFIX + "\"!!!");
076
077 // see: http://weblogs.java.net/blog/kohsuke/archive/2007/04/how_to_convert.html
078 try {
079 keyStoreDir = new File(new URI(keyManagerBaseURL));
080 } catch (URISyntaxException x) {
081 try {
082 keyStoreDir = new File(new URL(keyManagerBaseURL).getPath());
083 } catch (MalformedURLException e) {
084 throw new IllegalStateException("keyManagerBaseURL is malformed: " + e, e);
085 }
086 }
087 }
088
089 if (!keyStoreDir.isDirectory()) {
090 keyStoreDir.mkdirs();
091
092 if (!keyStoreDir.isDirectory())
093 throw new IOException("Creating directory \"" + keyStoreDir.getAbsolutePath() + "\" failed! Check permissions!");
094 }
095
096 return new File(keyStoreDir, getKeyStoreID() + ".keystore");
097 }
098
099 @Override
100 public void setConfiguration(KeyManagerAPIConfiguration configuration) throws IllegalArgumentException, KeyManagerAPIInstantiationException
101 {
102 super.setConfiguration(configuration);
103 this.keyStore = null;
104 this.appServerManager = null;
105 appServerBaseURL2appServerID.clear();
106 }
107
108 public LocalKeyManagerAPI()
109 throws KeyManagerAPIInstantiationException
110 {
111 // We test here, whether the KeyStore is accessible. If it is not, it means the local stuff is not deployed
112 // and it should not be possible to instantiate a LocalKeyManagerAPI.
113 KeyStore.class.getConstructors();
114 }
115
116 @Override
117 public DateDependentKeyStrategyInitResult initDateDependentKeyStrategy(DateDependentKeyStrategyInitParam param)
118 throws KeyStoreNotEmptyException, IOException
119 {
120 if (param == null)
121 throw new IllegalArgumentException("param == null");
122
123 DateDependentKeyStrategyInitResult result = new DateDependentKeyStrategyInitResult();
124
125 try {
126 KeyStore keyStore = getKeyStore();
127 DateDependentKeyStrategy keyStrategy = new DateDependentKeyStrategy(keyStore);
128 keyStrategy.init(getAuthUserName(), getAuthPassword(), param.getKeyActivityPeriodMSec(), param.getKeyStorePeriodMSec());
129
130 result.setGeneratedKeyCount(
131 keyStore.getKeyIDs(getAuthUserName(), getAuthPassword()).size()
132 );
133
134 return result;
135 } catch (org.cumulus4j.keystore.KeyStoreNotEmptyException e) {
136 throw new KeyStoreNotEmptyException(e);
137 } catch (org.cumulus4j.keystore.AuthenticationException e) {
138 throw new IOException(e); // Should never happen, because we were able to initialise the key-store with this auth-data.
139 }
140 }
141
142 @Override
143 public void putUser(String userName, char[] password) throws AuthenticationException, IOException
144 {
145 KeyStore keyStore = getKeyStore();
146 try {
147 try {
148 keyStore.createUser(getAuthUserName(), getAuthPassword(), userName, password);
149 } catch (org.cumulus4j.keystore.UserAlreadyExistsException e) {
150 try {
151 keyStore.changeUserPassword(getAuthUserName(), getAuthPassword(), userName, password);
152 } catch (UserNotFoundException e1) {
153 throw new RuntimeException("What the hell?! Just caught a UserAlreadyExistsException - why is the user not existing now?!", e1);
154 }
155 }
156 } catch (org.cumulus4j.keystore.AuthenticationException e) {
157 throw new AuthenticationException(e);
158 }
159
160 // If we changed the current user's password, we automatically re-configure this API instance.
161 KeyManagerAPIConfiguration conf = getConf();
162 if (conf.getAuthUserName() != null && conf.getAuthUserName().equals(userName)) {
163 KeyManagerAPIConfiguration newConf = new KeyManagerAPIConfiguration(conf);
164 newConf.setAuthPassword(password);
165 try {
166 setConfiguration(newConf);
167 } catch (KeyManagerAPIInstantiationException e) {
168 throw new RuntimeException(e); // Shouldn't happen, because we copied the old configuration.
169 }
170 }
171 }
172
173 @Override
174 public void deleteUser(String userName) throws AuthenticationException, CannotDeleteLastUserException, IOException
175 {
176 KeyStore keyStore = getKeyStore();
177 try {
178 keyStore.deleteUser(getAuthUserName(), getAuthPassword(), userName);
179 } catch (org.cumulus4j.keystore.UserNotFoundException e) {
180 // silently ignore
181 doNothing();
182 } catch (org.cumulus4j.keystore.CannotDeleteLastUserException e) {
183 throw new CannotDeleteLastUserException(e);
184 } catch (org.cumulus4j.keystore.AuthenticationException e) {
185 throw new AuthenticationException(e);
186 }
187 }
188
189 private static final void doNothing() { }
190
191 @Override
192 public CryptoSession getCryptoSession(String appServerBaseURL) throws IOException, AuthenticationException
193 {
194 // try {
195 AppServerManager appServerManager = getAppServerManager();
196 AppServer appServer;
197 synchronized (appServerBaseURL2appServerID) {
198 String appServerID = appServerBaseURL2appServerID.get(appServerBaseURL);
199 if (appServerID == null) {
200 appServer = new AppServer(appServerManager, appServerID, appServerBaseURL);
201 appServerManager.putAppServer(appServer);
202 appServer.getAppServerID();
203 }
204 else
205 appServer = appServerManager.getAppServerForAppServerID(appServerID);
206 }
207
208 // // Try to open the session already now, so that we know already here, whether this works (but lock it immediately, again).
209 // appServer.getSessionManager().acquireSession(getAuthUserName(), getAuthPassword()).release();
210
211 return new LocalCryptoSession(this, appServer);
212 // } catch (org.cumulus4j.keystore.AuthenticationException e) {
213 // throw new AuthenticationException(e);
214 // }
215 }
216
217 }