1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  package org.abstracthorizon.danube.auth.jaas.memory;
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.net.URI;
20  import java.net.URISyntaxException;
21  import java.net.URLConnection;
22  import java.security.MessageDigest;
23  import java.security.NoSuchAlgorithmException;
24  import java.security.Security;
25  import java.security.cert.CertificateException;
26  import java.util.ArrayList;
27  import java.util.Enumeration;
28  import java.util.HashMap;
29  import java.util.HashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Properties;
33  import java.util.Set;
34  
35  import javax.security.auth.login.AppConfigurationEntry;
36  import javax.security.auth.login.Configuration;
37  
38  import org.bouncycastle.jce.provider.BouncyCastleProvider;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  
43  
44  
45  
46  
47  
48  public class PropertiesModuleService {
49  
50      protected Logger logger = LoggerFactory.getLogger(getClass());
51  
52      
53      private String loginContext;
54  
55      
56      private String controlFlag = "required";
57  
58      
59      private Configuration configuration;
60  
61      
62      private Map<String, Object> options = new HashMap<String, Object>();
63  
64      
65      private String propertiesURI;
66      
67      
68      private Properties properties = new Properties();
69      
70      static {
71          Security.addProvider(new BouncyCastleProvider());
72      }
73  
74      
75  
76  
77      public PropertiesModuleService() {
78      }
79  
80      
81  
82  
83  
84      public void start() throws Exception {
85  
86          AppConfigurationEntry.LoginModuleControlFlag flag = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
87  
88          if (AppConfigurationEntry.LoginModuleControlFlag.REQUIRED.toString().indexOf(controlFlag) > 0 ) {
89              flag = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
90          } else if( AppConfigurationEntry.LoginModuleControlFlag.REQUISITE.toString().indexOf(controlFlag) > 0 ) {
91              flag = AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
92          } else if( AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT.toString().indexOf(controlFlag) > 0 ) {
93              flag = AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
94          }else if( AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL.toString().indexOf(controlFlag) > 0 ) {
95              flag = AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
96          }
97  
98          
99          options.put("properties", properties);
100         AppConfigurationEntry entry = new AppConfigurationEntry(PropertiesLoginModule.class.getName(), flag, options);
101 
102         AppConfigurationEntry[] list = new AppConfigurationEntry[1];
103         list[0] = entry;
104         Method method = configuration.getClass().getMethod("setAppConfigurationEntry", new Class[]{String.class, list.getClass()});
105         Object[] args = {loginContext, list};
106         method.invoke(configuration, args);
107         logger.info("Set up login context '" + loginContext + "'");
108     }
109 
110 
111     public void stop() throws Exception {
112         Method method = configuration.getClass().getMethod("removeAppConfigurationEntry", new Class[]{String.class});
113         Object[] args = {loginContext};
114         method.invoke(configuration, args);
115         logger.info("Removed login context '" + loginContext + "'");
116     }
117 
118     
119 
120 
121 
122 
123     public String listUsersString() throws Exception {
124         List<String> u = listUsers();
125         String[] users = new String[u.size()];
126         users = (String[])u.toArray(users);
127 
128         StringBuffer res = new StringBuffer();
129         res.append("[");
130         for (int i=0; i<users.length; i++) {
131             if (i > 0) {
132                 res.append(", ");
133             }
134             res.append(users[i]);
135         }
136         res.append("]");
137         return res.toString();
138     }
139 
140     
141 
142 
143 
144 
145     public List<String> listUsers() throws Exception {
146         ArrayList<String> users = new ArrayList<String>();
147         Enumeration<?> en = properties.propertyNames();
148         while (en.hasMoreElements()) {
149             users.add((String)en.nextElement());
150         }
151         return users;
152     }
153 
154     
155 
156 
157 
158 
159 
160 
161     public void changePassword(String user, String oldPassword, String newPassword) throws Exception {
162         newPassword = generateMD5Hash(newPassword);
163         String line = properties.getProperty(user);
164         if (line != null) {
165             int i = line.indexOf(',');
166             if (i < 0) {
167                 properties.setProperty(user, newPassword);
168             } else {
169                 properties.setProperty(user, newPassword + line.substring(i));
170             }
171         }
172         storeProperties();
173     }
174 
175     
176 
177 
178 
179 
180 
181     public void addUser(String user, String passwd) throws Exception {
182         properties.setProperty(user, generateMD5Hash(passwd));
183         storeProperties();
184     }
185 
186     
187 
188 
189 
190 
191     public void removeUser(String user) throws Exception {
192         properties.remove(user);
193         storeProperties();
194     }
195 
196     public Set<String> getUserRoles(String user) {
197         String line = properties.getProperty(user);
198         if (line == null) {
199             return null;
200         }
201         Set<String> res = new HashSet<String>();
202         String[] roles = line.split(",");
203         for (int i = 1; i < roles.length; i++) {
204             res.add(roles[i]);
205         }
206         return res;
207     }
208     
209     public String[] getUserRolesAsArray(String user) {
210         String line = properties.getProperty(user);
211         if (line == null) {
212             return null;
213         }
214         String[] roles = line.split(",");
215         String[] res = new String[roles.length - 1];
216         if (roles.length > 1) {
217             System.arraycopy(roles, 1, res, 0, roles.length - 1);
218         }
219         return res;
220     }
221     
222     public void loadProperties() throws CertificateException, IOException, URISyntaxException {
223         if (propertiesURI != null) {
224             logger.info("Loading properties from " + propertiesURI.toString() + " for login context '" + loginContext + "'");
225             InputStream keystoreInputStream = new URI(propertiesURI).toURL().openStream();
226             try {
227                 properties.load(keystoreInputStream);
228             } finally {
229                 keystoreInputStream.close();
230             }
231         }
232     }
233 
234     public void storeProperties() throws IOException, URISyntaxException {
235 
236         if ((properties != null) && (propertiesURI != null)) {
237             
238             logger.info("Storing properties to " + propertiesURI.toString() + " for login context '" + loginContext + "'");
239             OutputStream keystoreOutputStream = null;
240             URLConnection connection = new URI(propertiesURI).toURL().openConnection();
241             connection.setDoOutput(true);
242             keystoreOutputStream = connection.getOutputStream();
243     
244             try {
245                 properties.store(keystoreOutputStream, "For login context " + loginContext);
246             } finally {
247                 keystoreOutputStream.close();
248             }
249         }
250     }
251 
252 
253     
254 
255 
256 
257     public String getPropertiesURI() {
258         return propertiesURI;
259     }
260 
261     
262 
263 
264 
265     public void setPropertesURI(String uri) {
266         propertiesURI = uri;
267     }
268 
269     
270 
271 
272 
273     public void setLoginContext(String loginContext) {
274         this.loginContext = loginContext;
275     }
276 
277     
278 
279 
280 
281     public String getLoginContext() {
282         return loginContext;
283     }
284 
285     
286 
287 
288 
289     public void setControlFlag(String controlFlag) {
290         this.controlFlag = controlFlag;
291     }
292 
293     
294 
295 
296 
297     public String getControlFlag() {
298         return controlFlag;
299     }
300 
301     
302 
303 
304 
305     public Configuration getConfiguration() {
306         return configuration;
307     }
308 
309     
310 
311 
312 
313     public void setConfiguration(Configuration configuration) {
314         this.configuration = configuration;
315     }
316 
317     public Properties getProperties() {
318         return properties;
319     }
320     
321     public void setProperties(Properties properties) {
322         this.properties = properties;
323     }
324 
325     public static String generateMD5Hash(String password) throws NoSuchAlgorithmException {
326         return generateHash("MD5", password);
327     }
328     public static String generateHash(String algorithm, String password) throws NoSuchAlgorithmException {
329         MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
330         StringBuilder res = new StringBuilder();
331         res.append("{MD5}");
332         byte[] bytes = messageDigest.digest(password.getBytes());
333         String h = null;
334         int i;
335         for (byte b : bytes) {
336             i = (int)b;
337             if (i < 0) {
338                 i = - i + 127;
339             }
340             h = Integer.toString(i, 16);
341             if (h.length() < 2) {
342                 res.append('0').append(h);
343             } else {
344                 res.append(h);
345             }
346         }
347         return res.toString();
348 
349     }
350 }