1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  package org.abstracthorizon.danube.auth.jaas.keystore;
14  
15  import java.io.IOException;
16  import java.io.InputStream;
17  import java.io.OutputStream;
18  import java.lang.reflect.Method;
19  import java.math.BigInteger;
20  import java.net.MalformedURLException;
21  import java.net.URI;
22  import java.net.URISyntaxException;
23  import java.net.URLConnection;
24  import java.security.Key;
25  import java.security.KeyPair;
26  import java.security.KeyPairGenerator;
27  import java.security.KeyStore;
28  import java.security.KeyStoreException;
29  import java.security.NoSuchAlgorithmException;
30  import java.security.NoSuchProviderException;
31  import java.security.Security;
32  import java.security.cert.Certificate;
33  import java.security.cert.CertificateException;
34  import java.util.ArrayList;
35  import java.util.Date;
36  import java.util.Enumeration;
37  import java.util.HashMap;
38  import java.util.List;
39  import java.util.Map;
40  
41  import javax.security.auth.login.AppConfigurationEntry;
42  import javax.security.auth.login.Configuration;
43  
44  import org.bouncycastle.jce.X509Principal;
45  import org.bouncycastle.jce.provider.BouncyCastleProvider;
46  import org.bouncycastle.x509.X509V3CertificateGenerator;
47  import org.slf4j.Logger;
48  import org.slf4j.LoggerFactory;
49  
50  
51  
52  
53  
54  
55  
56  public class KeyStoreModuleService {
57  
58      protected Logger logger = LoggerFactory.getLogger(getClass());
59  
60      
61      private String keystore;
62  
63      
64      private String keystorePassword;
65  
66      
67      private String keystoreType = KeyStore.getDefaultType();
68  
69      
70      private String keystoreProvider = "";
71  
72      
73      private String loginContext;
74  
75      
76      private String controlFlag = "required";
77  
78      
79      private Configuration configuration;
80  
81      
82      private Map<String, Object> options = new HashMap<String, Object>();
83  
84      
85      private URI keystoreResourceURI;
86      
87      static {
88          Security.addProvider(new BouncyCastleProvider());
89      }
90  
91      
92  
93  
94      public KeyStoreModuleService() {
95      }
96  
97      
98  
99  
100 
101     public void start() throws Exception {
102 
103         AppConfigurationEntry.LoginModuleControlFlag flag = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
104 
105         if (AppConfigurationEntry.LoginModuleControlFlag.REQUIRED.toString().indexOf(controlFlag) > 0 ) {
106             flag = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
107         } else if( AppConfigurationEntry.LoginModuleControlFlag.REQUISITE.toString().indexOf(controlFlag) > 0 ) {
108             flag = AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
109         } else if( AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT.toString().indexOf(controlFlag) > 0 ) {
110             flag = AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
111         }else if( AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL.toString().indexOf(controlFlag) > 0 ) {
112             flag = AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
113         }
114 
115         AppConfigurationEntry entry = new AppConfigurationEntry(KeyStoreLoginModule.class.getName(), flag, options);
116 
117         AppConfigurationEntry[] list = new AppConfigurationEntry[1];
118         list[0] = entry;
119         Method method = configuration.getClass().getMethod("setAppConfigurationEntry", new Class[]{String.class, list.getClass()});
120         Object[] args = {loginContext, list};
121         method.invoke(configuration, args);
122         logger.info("Set up login context '" + loginContext + "'");
123     }
124 
125 
126     public void stop() throws Exception {
127         Method method = configuration.getClass().getMethod("removeAppConfigurationEntry", new Class[]{String.class});
128         Object[] args = {loginContext};
129         method.invoke(configuration, args);
130         logger.info("Removed login context '" + loginContext + "'");
131     }
132 
133     
134 
135 
136 
137 
138     public String listUsersString() throws Exception {
139         List<String> u = listUsers();
140         String[] users = new String[u.size()];
141         users = (String[])u.toArray(users);
142 
143         StringBuffer res = new StringBuffer();
144         res.append("[");
145         for (int i=0; i<users.length; i++) {
146             if (i > 0) {
147                 res.append(", ");
148             }
149             res.append(users[i]);
150         }
151         res.append("]");
152         return res.toString();
153     }
154 
155     
156 
157 
158 
159 
160     public List<String> listUsers() throws Exception {
161         KeyStore keyStore = loadKeyStore();
162         ArrayList<String> users = new ArrayList<String>();
163         Enumeration<String> en = keyStore.aliases();
164         while (en.hasMoreElements()) {
165             users.add(en.nextElement());
166         }
167         return users;
168     }
169 
170     
171 
172 
173 
174 
175 
176 
177     public void changePassword(String user, String oldPassword, String newPassword) throws Exception {
178         KeyStore keyStore = loadKeyStore();
179         Key key = keyStore.getKey(user, oldPassword.toCharArray());
180 
181         Certificate[] certs = keyStore.getCertificateChain(user);
182 
183         keyStore.setKeyEntry(user, key, newPassword.toCharArray(), certs);
184         storeKeyStore(keyStore);
185     }
186 
187     
188 
189 
190 
191 
192 
193     public void addUser(String user, String passwd) throws Exception {
194         KeyStore keyStore = loadKeyStore();
195 
196         String name = "CN="+user+", OU=, O=, L=, ST=, C=";
197             
198 
199         Security.addProvider(new BouncyCastleProvider());
200 
201         X509V3CertificateGenerator generator = new X509V3CertificateGenerator();
202         KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
203         kpGen.initialize(1024);
204         KeyPair pair = kpGen.generateKeyPair();
205 
206         generator.setSerialNumber(BigInteger.valueOf(1));
207         generator.setIssuerDN(new X509Principal(name));
208         generator.setNotBefore(new Date());
209         generator.setNotAfter(new Date(System.currentTimeMillis()+1000*60*60*24*365));
210         generator.setSubjectDN(new X509Principal(name));
211         generator.setPublicKey(pair.getPublic());
212         generator.setSignatureAlgorithm("MD5WithRSAEncryption");
213 
214         Certificate cert = generator.generate(pair.getPrivate(), "BC");
215 
216         keyStore.setKeyEntry(user, pair.getPrivate(), passwd.toCharArray(), new Certificate[]{cert});
217         storeKeyStore(keyStore);
218     }
219 
220     
221 
222 
223 
224 
225     public void removeUser(String user) throws Exception {
226         KeyStore keyStore = loadKeyStore();
227         keyStore.deleteEntry(user);
228         storeKeyStore(keyStore);
229     }
230 
231     protected KeyStore loadKeyStore() throws KeyStoreException, NoSuchProviderException, MalformedURLException,
232         IOException, NoSuchAlgorithmException, CertificateException {
233 
234         logger.info("Loading keystore from " + keystoreResourceURI.toString() + " for login context '" + loginContext + "'");
235         InputStream keystoreInputStream = keystoreResourceURI.toURL().openStream();
236         try {
237             KeyStore keyStore;
238             if ((keystoreProvider == null) || (keystoreProvider.length() == 0)) {
239                 keyStore = KeyStore.getInstance(keystoreType);
240             } else {
241                 keyStore = KeyStore.getInstance(keystoreType, keystoreProvider);
242             }
243 
244             
245             keyStore.load(keystoreInputStream, keystorePassword.toCharArray());
246             return keyStore;
247 
248         } finally {
249             keystoreInputStream.close();
250         }
251     }
252 
253     
254 
255 
256 
257 
258 
259 
260 
261 
262 
263     protected void storeKeyStore(KeyStore keystore) throws KeyStoreException, NoSuchProviderException, MalformedURLException,
264         IOException, NoSuchAlgorithmException, CertificateException {
265 
266         logger.info("Storing keystore to " + keystoreResourceURI.toString() + " for login context '" + loginContext + "'");
267         OutputStream keystoreOutputStream = null;
268         URLConnection connection = keystoreResourceURI.toURL().openConnection();
269         connection.setDoOutput(true);
270         keystoreOutputStream = connection.getOutputStream();
271 
272         try {
273             keystore.store(keystoreOutputStream, keystorePassword.toCharArray());
274         } finally {
275             keystoreOutputStream.close();
276         }
277     }
278 
279     
280 
281 
282 
283     public void setKeyStorePassword(String password) {
284         this.keystorePassword = password;
285         if (password != null) {
286             options.put("keyStorePassword", password);
287         } else {
288             options.remove("keyStorePassword");
289         }
290     }
291 
292     
293 
294 
295 
296 
297 
298     public void setKeyStore(String keystore) throws IOException, URISyntaxException {
299         this.keystore = keystore;
300 
301         if (keystore != null) {
302             keystoreResourceURI = new URI(keystore);
303             options.put("keyStoreURL", keystoreResourceURI);
304         } else {
305             keystoreResourceURI = null;
306             options.remove("keyStoreURL");
307         }
308     }
309 
310     
311 
312 
313 
314     public String getKeyStoreURL() {
315         return keystore;
316     }
317 
318     
319 
320 
321 
322     public void setKeyStoreType(String type) {
323         keystoreType = type;
324         if (type != null) {
325             options.put("keyStoreType", type);
326         } else {
327             options.remove("keyStoreType");
328         }
329     }
330 
331     
332 
333 
334 
335     public String getKeyStoreType() {
336         return keystoreType;
337     }
338 
339     
340 
341 
342 
343     public void setKeyStoreProvider(String provider) {
344         this.keystoreProvider = provider;
345         if (provider != null) {
346             options.put("keyStoreProvider", provider);
347         } else {
348             options.remove("keyStoreProvider");
349         }
350     }
351 
352     
353 
354 
355 
356     public String getKeyStoreProvider() {
357         return keystoreProvider;
358     }
359 
360     
361 
362 
363 
364     public void setLoginContext(String loginContext) {
365         this.loginContext = loginContext;
366     }
367 
368     
369 
370 
371 
372     public String getLoginContext() {
373         return loginContext;
374     }
375 
376     
377 
378 
379 
380     public void setControlFlag(String controlFlag) {
381         this.controlFlag = controlFlag;
382     }
383 
384     
385 
386 
387 
388     public String getControlFlag() {
389         return controlFlag;
390     }
391 
392     
393 
394 
395 
396     public Configuration getConfiguration() {
397         return configuration;
398     }
399 
400     
401 
402 
403 
404     public void setConfiguration(Configuration configuration) {
405         this.configuration = configuration;
406     }
407 }