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 }