KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > realm > providers > PropertiesFileLoginModule


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.geronimo.security.realm.providers;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.geronimo.common.GeronimoSecurityException;
23 import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
24 import org.apache.geronimo.system.serverinfo.ServerInfo;
25 import org.apache.geronimo.util.encoders.HexTranslator;
26
27 import javax.security.auth.Subject JavaDoc;
28 import javax.security.auth.callback.Callback JavaDoc;
29 import javax.security.auth.callback.CallbackHandler JavaDoc;
30 import javax.security.auth.callback.NameCallback JavaDoc;
31 import javax.security.auth.callback.PasswordCallback JavaDoc;
32 import javax.security.auth.callback.UnsupportedCallbackException JavaDoc;
33 import javax.security.auth.login.FailedLoginException JavaDoc;
34 import javax.security.auth.login.LoginException JavaDoc;
35 import javax.security.auth.spi.LoginModule JavaDoc;
36 import java.io.IOException JavaDoc;
37 import java.io.InputStream JavaDoc;
38 import java.net.URI JavaDoc;
39 import java.security.MessageDigest JavaDoc;
40 import java.security.NoSuchAlgorithmException JavaDoc;
41 import java.util.Enumeration JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.HashSet JavaDoc;
44 import java.util.Iterator JavaDoc;
45 import java.util.Map JavaDoc;
46 import java.util.Properties JavaDoc;
47 import java.util.Set JavaDoc;
48
49
50 /**
51  * A LoginModule that reads a list of users and group from files on disk. The
52  * files should be formatted using standard Java properties syntax. Expects
53  * to be run by a GenericSecurityRealm (doesn't work on its own).
54  *
55  * @version $Rev: 478545 $ $Date: 2006-11-23 07:20:40 -0500 (Thu, 23 Nov 2006) $
56  */

57 public class PropertiesFileLoginModule implements LoginModule JavaDoc {
58     public final static String JavaDoc USERS_URI = "usersURI";
59     public final static String JavaDoc GROUPS_URI = "groupsURI";
60     public final static String JavaDoc DIGEST = "digest";
61     private static Log log = LogFactory.getLog(PropertiesFileLoginModule.class);
62     final Properties JavaDoc users = new Properties JavaDoc();
63     final Map JavaDoc groups = new HashMap JavaDoc();
64     private String JavaDoc digest;
65
66     Subject JavaDoc subject;
67     CallbackHandler JavaDoc handler;
68     String JavaDoc username;
69     String JavaDoc password;
70
71     public void initialize(Subject JavaDoc subject, CallbackHandler JavaDoc callbackHandler, Map JavaDoc sharedState, Map JavaDoc options) {
72         this.subject = subject;
73         this.handler = callbackHandler;
74         try {
75             ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
76             final String JavaDoc users = (String JavaDoc)options.get(USERS_URI);
77             final String JavaDoc groups = (String JavaDoc)options.get(GROUPS_URI);
78             digest = (String JavaDoc) options.get(DIGEST);
79             if(digest != null && !digest.equals("")) {
80                 // Check if the digest algorithm is available
81
try {
82                     MessageDigest.getInstance(digest);
83                 } catch(NoSuchAlgorithmException JavaDoc e) {
84                     log.error("Initialization failed. Digest algorithm "+digest+" is not available.", e);
85                     throw new IllegalArgumentException JavaDoc("Unable to configure properties file login module: "+e.getMessage());
86                 }
87             }
88             if(users == null || groups == null) {
89                 throw new IllegalArgumentException JavaDoc("Both "+USERS_URI+" and "+GROUPS_URI+" must be provided!");
90             }
91             URI JavaDoc usersURI = new URI JavaDoc(users);
92             URI JavaDoc groupsURI = new URI JavaDoc(groups);
93             loadProperties(serverInfo, usersURI, groupsURI);
94         } catch (Exception JavaDoc e) {
95             log.error("Initialization failed", e);
96             throw new IllegalArgumentException JavaDoc("Unable to configure properties file login module: "+e.getMessage());
97         }
98     }
99
100     public void loadProperties(ServerInfo serverInfo, URI JavaDoc userURI, URI JavaDoc groupURI) throws GeronimoSecurityException {
101         try {
102             URI JavaDoc userFile = serverInfo.resolveServer(userURI);
103             URI JavaDoc groupFile = serverInfo.resolveServer(groupURI);
104             InputStream JavaDoc stream = userFile.toURL().openStream();
105             users.load(stream);
106             stream.close();
107
108             Properties JavaDoc temp = new Properties JavaDoc();
109             stream = groupFile.toURL().openStream();
110             temp.load(stream);
111             stream.close();
112
113             Enumeration JavaDoc e = temp.keys();
114             while (e.hasMoreElements()) {
115                 String JavaDoc groupName = (String JavaDoc) e.nextElement();
116                 String JavaDoc[] userList = ((String JavaDoc) temp.get(groupName)).split(",");
117
118                 Set JavaDoc userset = (Set JavaDoc) groups.get(groupName);
119                 if (userset == null) {
120                     userset = new HashSet JavaDoc();
121                     groups.put(groupName, userset);
122                 }
123
124                 for (int i = 0; i < userList.length; i++) {
125                     userset.add(userList[i]);
126                 }
127             }
128
129         } catch (Exception JavaDoc e) {
130             log.error("Properties File Login Module - data load failed", e);
131             throw new GeronimoSecurityException(e);
132         }
133     }
134
135
136     public boolean login() throws LoginException JavaDoc {
137         Callback JavaDoc[] callbacks = new Callback JavaDoc[2];
138
139         callbacks[0] = new NameCallback JavaDoc("User name");
140         callbacks[1] = new PasswordCallback JavaDoc("Password", false);
141         try {
142             handler.handle(callbacks);
143         } catch (IOException JavaDoc ioe) {
144             throw (LoginException JavaDoc) new LoginException JavaDoc().initCause(ioe);
145         } catch (UnsupportedCallbackException JavaDoc uce) {
146             throw (LoginException JavaDoc) new LoginException JavaDoc().initCause(uce);
147         }
148         assert callbacks.length == 2;
149         username = ((NameCallback JavaDoc) callbacks[0]).getName();
150         if(username == null || username.equals("")) {
151             return false;
152         }
153         String JavaDoc realPassword = users.getProperty(username);
154         char[] entered = ((PasswordCallback JavaDoc) callbacks[1]).getPassword();
155         password = entered == null ? null : new String JavaDoc(entered);
156         boolean result = (realPassword == null && password == null) ||
157                 (realPassword != null && password != null && checkPassword(realPassword, password));
158         if(!result) {
159             throw new FailedLoginException JavaDoc();
160         }
161         return true;
162     }
163
164     public boolean commit() throws LoginException JavaDoc {
165         Set JavaDoc principals = subject.getPrincipals();
166
167         principals.add(new GeronimoUserPrincipal(username));
168
169         Iterator JavaDoc e = groups.keySet().iterator();
170         while (e.hasNext()) {
171             String JavaDoc groupName = (String JavaDoc) e.next();
172             Set JavaDoc users = (Set JavaDoc) groups.get(groupName);
173             Iterator JavaDoc iter = users.iterator();
174             while (iter.hasNext()) {
175                 String JavaDoc user = (String JavaDoc) iter.next();
176                 if (username.equals(user)) {
177                     principals.add(new GeronimoGroupPrincipal(groupName));
178                     break;
179                 }
180             }
181         }
182
183         return true;
184     }
185
186     public boolean abort() throws LoginException JavaDoc {
187         username = null;
188         password = null;
189
190         return true;
191     }
192
193     public boolean logout() throws LoginException JavaDoc {
194         username = null;
195         password = null;
196         //todo: should remove principals added by commit
197
return true;
198     }
199
200     /**
201      * Gets the names of all principal classes that may be populated into
202      * a Subject.
203      */

204     public String JavaDoc[] getPrincipalClassNames() {
205         return new String JavaDoc[]{GeronimoUserPrincipal.class.getName(), GeronimoGroupPrincipal.class.getName()};
206     }
207
208     /**
209      * Gets a list of all the principals of a particular type (identified by
210      * the principal class). These are available for manual role mapping.
211      */

212     public String JavaDoc[] getPrincipalsOfClass(String JavaDoc className) {
213         Set JavaDoc s;
214         if(className.equals(GeronimoGroupPrincipal.class.getName())) {
215             s = groups.keySet();
216         } else if(className.equals(GeronimoUserPrincipal.class.getName())) {
217             s = users.keySet();
218         } else {
219             throw new IllegalArgumentException JavaDoc("No such principal class "+className);
220         }
221         return (String JavaDoc[]) s.toArray(new String JavaDoc[s.size()]);
222     }
223
224     /**
225      * This method checks if the provided password is correct. The original password may have been digested.
226      * @param real Original password in digested form if applicable
227      * @param provided User provided password in clear text
228      * @return true If the password is correct
229      */

230     private boolean checkPassword(String JavaDoc real, String JavaDoc provided){
231         if(digest == null || digest.equals("")) {
232             // No digest algorithm is used
233
return real.equals(provided);
234         }
235         try {
236             // Digest the user provided password
237
MessageDigest JavaDoc md = MessageDigest.getInstance(digest);
238             byte[] data = md.digest(provided.getBytes());
239             // Convert bytes to hex digits
240
byte[] hexData = new byte[data.length * 2];
241             HexTranslator ht = new HexTranslator();
242             ht.encode(data, 0, data.length, hexData, 0);
243             // Compare the digested provided password with the actual one
244
return real.equalsIgnoreCase(new String JavaDoc(hexData));
245         } catch (NoSuchAlgorithmException JavaDoc e) {
246             // Should not occur. Availability of algorithm has been checked at initialization
247
log.error("Should not occur. Availability of algorithm has been checked at initialization.", e);
248         }
249         return false;
250     }
251 }
252
Popular Tags