KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > security > JonasSecurityServiceImpl


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2005 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JonasSecurityServiceImpl.java,v 1.33 2005/04/28 08:43:26 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas.security;
27
28 import java.io.File JavaDoc;
29 import java.io.FileNotFoundException JavaDoc;
30 import java.io.FileReader JavaDoc;
31 import java.io.Reader JavaDoc;
32 import java.io.StringReader JavaDoc;
33 import java.security.NoSuchAlgorithmException JavaDoc;
34
35 import javax.management.MBeanServer JavaDoc;
36 import javax.naming.Context JavaDoc;
37 import javax.naming.InitialContext JavaDoc;
38 import javax.naming.NamingException JavaDoc;
39
40 import org.objectweb.jonas.common.Log;
41 import org.objectweb.jonas.jmx.JmxService;
42 import org.objectweb.jonas.jmx.JonasObjectName;
43 import org.objectweb.jonas.security.lib.wrapper.JResourceManagerWrapper;
44 import org.objectweb.jonas.security.realm.factory.JResource;
45 import org.objectweb.jonas.security.realm.factory.JResourceDS;
46 import org.objectweb.jonas.security.realm.factory.JResourceLDAP;
47 import org.objectweb.jonas.security.realm.factory.JResourceMemory;
48 import org.objectweb.jonas.security.realm.factory.JResourceRemote;
49 import org.objectweb.jonas.security.realm.factory.JResourceRemoteImpl;
50 import org.objectweb.jonas.security.realm.lib.HashHelper;
51 import org.objectweb.jonas.service.AbsServiceImpl;
52 import org.objectweb.jonas.service.ServiceException;
53 import org.objectweb.jonas.service.ServiceManager;
54
55 import org.objectweb.util.monolog.api.BasicLevel;
56 import org.objectweb.util.monolog.api.Logger;
57
58 /**
59  * Security Service implementation
60  * @author Jeff Mesnil,Philippe Coq, John Ellis, Joe Gittings for old security
61  * service
62  * @author Florent Benoit - JOnAS 3.x (Add JResources) - JOnAS 4.x (remove
63  * MethodGuard, RoleGuard no more used with JACC)
64  */

65
66 public class JonasSecurityServiceImpl extends AbsServiceImpl implements SecurityService, JonasSecurityServiceImplMBean {
67
68     /**
69      * Logger which is used
70      */

71     private static Logger logger = null;
72
73     /**
74      * Security service configuration properties
75      */

76     public static final String JavaDoc CLASS = "jonas.service.security.class";
77
78     /**
79      * Name of resource
80      */

81     public static final String JavaDoc REMOTE_RESOUCE = "_remoteres";
82
83     /**
84      * Relative path of the realm configuration file
85      */

86     protected static final String JavaDoc CONFIG_FILE = "conf" + File.separator + "jonas-realm.xml";
87
88     /**
89      * Bind the resources into JNDI ?
90      */

91     protected static final String JavaDoc BIND_RESOURCES_INTO_JNDI = "jonas.service.security.realm.jndi.registration";
92
93     /**
94      * Reference to a MBean server.
95      */

96     private MBeanServer JavaDoc mbeanServer = null;
97
98     /**
99      * JResources list
100      */

101     private JResources jResources;
102
103     /**
104      * Initial Context for Naming
105      */

106     private Context JavaDoc ictx = null;
107
108     /**
109      * Bind resource in JNDI
110      */

111     private boolean bindResourcesIntoJndi = false;
112
113
114     /**
115      * Init the Service. Configuration information is passed thru a Context
116      * object.
117      * @param ctx the configuration of the Security service.
118      * @throws ServiceException if the initialization failed.
119      */

120     public void doInit(Context JavaDoc ctx) throws ServiceException {
121         if (logger == null) {
122             logger = Log.getLogger(Log.JONAS_SECURITY_PREFIX);
123         }
124
125         // JResources
126
jResources = new JResources(this);
127
128         // Get the initial Context
129
try {
130             ictx = new InitialContext JavaDoc();
131         } catch (NamingException JavaDoc e) {
132             logger.log(BasicLevel.ERROR, "Cannot create initial context during the mail service initializing", e);
133             throw new ServiceException("Cannot create initial context during the mail service initializing", e);
134         }
135
136         // Register the security remote object (name is based on JOnAS server
137
// name).
138
JResourceRemote jResourceRemote = null;
139         try {
140             jResourceRemote = new JResourceRemoteImpl();
141             ictx.bind(getJonasServerName() + REMOTE_RESOUCE, jResourceRemote);
142         } catch (Exception JavaDoc e) {
143             logger.log(BasicLevel.ERROR, "Cannot bind remote resource for security access", e);
144             throw new ServiceException("Cannot create initial context during the mail service initializing", e);
145         }
146
147         // Get the JMX Server via JMX Service
148
try {
149             mbeanServer = ((JmxService) ServiceManager.getInstance().getJmxService()).getJmxServer();
150         } catch (Exception JavaDoc e) {
151             // the JMX service may not be started
152
mbeanServer = null;
153         }
154
155         try {
156             String JavaDoc s = (String JavaDoc) ctx.lookup(BIND_RESOURCES_INTO_JNDI);
157             bindResourcesIntoJndi = new Boolean JavaDoc(s).booleanValue();
158         } catch (Exception JavaDoc e) {
159             if (logger.isLoggable(BasicLevel.DEBUG)) {
160                 logger.log(BasicLevel.DEBUG, "Property '" + BIND_RESOURCES_INTO_JNDI + "' not available, set it to false by default", e);
161             }
162         }
163
164
165         if (logger.isLoggable(BasicLevel.DEBUG)) {
166             logger.log(BasicLevel.DEBUG, "JonasSecurityService initialized");
167         }
168     }
169
170     /**
171      * Remove the Resource (memory, ldap, datasource,...)
172      * @param resourceName name of the resource
173      * @throws Exception if the resource name does not exist
174      */

175     public void removeJResource(String JavaDoc resourceName) throws Exception JavaDoc {
176
177         // remove the given resource of the list
178
JResource jResource = jResources.remove(resourceName);
179
180         // remove the resource into the jndi
181
if (bindResourcesIntoJndi) {
182             try {
183                 ictx.unbind(resourceName);
184                 if (logger.isLoggable(BasicLevel.DEBUG)) {
185                     logger.log(BasicLevel.DEBUG, "jResource " + resourceName + " remove from the registry.");
186                 }
187             } catch (NamingException JavaDoc e) {
188                 logger.log(BasicLevel.ERROR, "Cannot unbind the resource '" + resourceName + "' into JNDI", e);
189             }
190         }
191
192         try {
193             // Remove mbeans of the resources
194
jResource.removeMBeans();
195
196             // register security factory mbean
197
if (jResource instanceof JResourceMemory) {
198                 mbeanServer.unregisterMBean(JonasObjectName.securityMemoryFactory(resourceName));
199             } else if (jResource instanceof JResourceDS) {
200                 mbeanServer.unregisterMBean(JonasObjectName.securityDatasourceFactory(resourceName));
201             } else if (jResource instanceof JResourceLDAP) {
202                 mbeanServer.unregisterMBean(JonasObjectName.securityLdapFactory(resourceName));
203             }
204         } catch (ServiceException se) {
205             logger.log(BasicLevel.ERROR, "JMX service not available", se);
206         } catch (Exception JavaDoc e) {
207             logger.log(BasicLevel.ERROR, "Can not unregister the MBean for the resource " + resourceName + " : "
208                     + e.getMessage());
209             throw new ServiceException("Can not unregister the MBean for the resource " + resourceName + " : "
210                     + e.getMessage());
211         }
212
213     }
214
215     /**
216      * Start the Service Initialization of the service is already done.
217      * @throws ServiceException if the stop failed.
218      */

219     public void doStart() throws ServiceException {
220         try {
221             // register security service mbean
222
mbeanServer.registerMBean(this, JonasObjectName.securityService());
223         } catch (ServiceException se) {
224             logger.log(BasicLevel.ERROR, "JMX service not available", se);
225         } catch (Exception JavaDoc e) {
226             logger.log(BasicLevel.ERROR, "SecurityService: Cannot start the Security service:\n" + e);
227             throw new ServiceException("SecurityService: Cannot start the Security service", e);
228         }
229
230         createRealm();
231     }
232
233     /**
234      * Stop the Service
235      */

236     public void doStop() {
237
238         // Unregister MBean
239
try {
240             // Unregister Security Service MBean : SecurityServiceImplMBean
241
((JmxService) ServiceManager.getInstance().getJmxService()).getJmxServer().unregisterMBean(
242                     JonasObjectName.securityService());
243         } catch (ServiceException se) {
244             logger.log(BasicLevel.ERROR, "JMX service not available", se);
245         } catch (Exception JavaDoc e) {
246             logger.log(BasicLevel.ERROR, "Cannot stop the security service:\n" + e);
247             throw new ServiceException("Cannot stop the security service", e);
248         }
249     }
250
251     /**
252      * Return a resource by giving its name
253      * @param name the wanted Resource
254      * @return a JResouce
255      */

256     public JResource getJResource(String JavaDoc name) {
257         return jResources.getJResource(name);
258     }
259
260     /**
261      * Parse the xml file and create all the JResource
262      * @throws ServiceException if a JResource can't be created
263      */

264     private void createRealm() throws ServiceException {
265
266         // Execute the digester for the parsing of the jonas-realm.xml file.
267
File JavaDoc configFile = null;
268         Reader JavaDoc reader = null;
269         try {
270             configFile = getConfigFile();
271             reader = new FileReader JavaDoc(configFile);
272         } catch (FileNotFoundException JavaDoc e) {
273             logger.log(BasicLevel.ERROR, "Cannot find config file " + configFile);
274             throw new ServiceException(e.getMessage(), e);
275         }
276
277         try {
278             JResourceManagerWrapper.addResources(jResources, reader, configFile.getPath());
279         } catch (Exception JavaDoc e1) {
280             String JavaDoc err = "Cannot add security resource from '" + configFile + "'";
281             logger.log(BasicLevel.ERROR, err);
282             throw new ServiceException(err, e1);
283         }
284     }
285
286     /**
287      * Return a File object representing the jonas-realm.xml configuration file.
288      * @return a File object representing the jonas-realm.xml configuration
289      * file.
290      * @throws FileNotFoundException if the configuration file is not found.
291      */

292     protected File JavaDoc getConfigFile() throws FileNotFoundException JavaDoc {
293         String JavaDoc fileName = System.getProperty("jonas.base");
294         fileName = fileName + File.separator + CONFIG_FILE;
295         File JavaDoc file = new File JavaDoc(fileName);
296         if (!file.exists()) {
297             String JavaDoc err = "Can't find configuration file : " + fileName;
298             throw new FileNotFoundException JavaDoc(err);
299         }
300         return (file);
301     }
302
303     /**
304      * String representation of the JOnAS realm
305      * @return the xml representation of the JOnAS realm
306      */

307     public String JavaDoc toXML() {
308         return jResources.toXML();
309     }
310
311     /**
312      * Encrypt a string with an algorithm
313      * @param string the string to encode
314      * @param algo algorithm to apply on the given string
315      * @return the encoded string
316      * @throws NoSuchAlgorithmException One reason could be a bad algorithm
317      */

318     public String JavaDoc encryptPassword(String JavaDoc string, String JavaDoc algo) throws NoSuchAlgorithmException JavaDoc {
319         String JavaDoc encrypt = HashHelper.hashPassword(string, algo);
320         // Prefix with algorithm
321
return "{" + algo.toUpperCase() + "}" + encrypt;
322     }
323
324     /**
325      * Check if the given algorithm is a valid algorithm
326      * @param algo algorithm to apply on the given string
327      * @return true if it is a valid algorithm
328      */

329     public boolean isValidAlgorithm(String JavaDoc algo) {
330         boolean b = true;
331         try {
332             encryptPassword("test", algo);
333         } catch (NoSuchAlgorithmException JavaDoc nsae) {
334             b = false;
335         }
336         return b;
337     }
338
339     /**
340      * Add JResources with a given xml configuration
341      * @param xml xml representation of the resources to add
342      * @throws Exception if the resources can't be added
343      */

344     public void addResources(String JavaDoc xml) throws Exception JavaDoc {
345
346         try {
347             JResourceManagerWrapper.addResources(jResources, new StringReader JavaDoc(xml), "");
348         } catch (Exception JavaDoc e1) {
349             String JavaDoc err = "Cannot add security resource from xml '" + xml + "'";
350             logger.log(BasicLevel.ERROR, err);
351             throw new ServiceException(err, e1);
352         }
353     }
354
355     /**
356      * Add a Memory resource
357      * @param name the name of the JResourceMemory to create
358      * @throws Exception if the resource can't be added
359      */

360     public void addJResourceMemory(String JavaDoc name) throws Exception JavaDoc {
361
362         // Build a new JResourceMemory
363
JResourceMemory jResourceMemory = new JResourceMemory();
364         jResourceMemory.setName(name);
365
366         // Build xml
367
StringBuffer JavaDoc xml = new StringBuffer JavaDoc(JResources.HEADER_XML);
368         xml.append("<jonas-realm>");
369         xml.append("<jonas-memoryrealm>");
370         xml.append(jResourceMemory.toXML());
371         xml.append("</jonas-memoryrealm>");
372         xml.append("</jonas-realm>");
373
374         // Add the resource
375
addResources(xml.toString());
376
377     }
378
379     /**
380      * Add a DS resource
381      * @param name the name of the JResourceDS to create
382      * @param dsName Name of the datasource resource to use.
383      * @param userTable Name of table which have the username/password
384      * @param userTableUsernameCol Column of the username of the user table
385      * @param userTablePasswordCol Column of the password of the user table
386      * @param roleTable Name of table which have the username/role
387      * @param roleTableUsernameCol Column of the username of the role table
388      * @param roleTableRolenameCol Column of the role of the role table
389      * @param algorithm Default algorithm. If specified, the default is not
390      * 'clear' password
391      * @throws Exception if the resource can't be added
392      */

393     public void addJResourceDS(String JavaDoc name, String JavaDoc dsName, String JavaDoc userTable, String JavaDoc userTableUsernameCol,
394             String JavaDoc userTablePasswordCol, String JavaDoc roleTable, String JavaDoc roleTableUsernameCol, String JavaDoc roleTableRolenameCol,
395             String JavaDoc algorithm) throws Exception JavaDoc {
396
397         // Build a new JResourceDS
398
JResourceDS jResourceDS = new JResourceDS();
399         jResourceDS.setName(name);
400         jResourceDS.setDsName(dsName);
401         jResourceDS.setUserTable(userTable);
402         jResourceDS.setUserTableUsernameCol(userTableUsernameCol);
403         jResourceDS.setUserTablePasswordCol(userTablePasswordCol);
404         jResourceDS.setRoleTable(roleTable);
405         jResourceDS.setRoleTableUsernameCol(roleTableUsernameCol);
406         jResourceDS.setRoleTableRolenameCol(roleTableRolenameCol);
407         jResourceDS.setAlgorithm(algorithm);
408
409         // Build xml
410
StringBuffer JavaDoc xml = new StringBuffer JavaDoc(JResources.HEADER_XML);
411         xml.append("<jonas-realm>");
412         xml.append("<jonas-dsrealm>");
413         xml.append(jResourceDS.toXML());
414         xml.append("</jonas-dsrealm>");
415         xml.append("</jonas-realm>");
416
417         // Add the resource
418
addResources(xml.toString());
419
420     }
421
422     /**
423      * Add a LDAP resource
424      * @param name the name of the JResourceLDAP to create
425      * @param initialContextFactory Initial context factory for the LDAp server
426      * @param providerUrl Url of the ldap server
427      * @param securityAuthentication Type of the authentication used during the
428      * authentication to the LDAP server
429      * @param securityPrincipal DN of the Principal(username). He can retrieve
430      * the information from the user
431      * @param securityCredentials Credential(password) of the principal
432      * @param securityProtocol Constant that holds the name of the environment
433      * property for specifying the security protocol to use.
434      * @param language Constant that holds the name of the environment property
435      * for specifying the preferred language to use with the service.
436      * @param referral Constant that holds the name of the environment property
437      * for specifying how referrals encountered by the service provider
438      * are to be processed.
439      * @param stateFactories Constant that holds the name of the environment
440      * property for specifying the list of state factories to use.
441      * @param authenticationMode Mode for validate the authentication
442      * (BIND_AUTHENTICATION_MODE or COMPARE_AUTHENTICATION_MODE)
443      * @param userPasswordAttribute Attribute in order to get the password from
444      * the ldap server
445      * @param userRolesAttribute Attribute in order to get the user role from
446      * the ldap server
447      * @param roleNameAttribute Attribute for the role name when performing a
448      * lookup on a role
449      * @param baseDN DN used for the lookup
450      * @param userDN DN used when searching the user DN. Override the baseDN if
451      * it is defined
452      * @param userSearchFilter Filter used when searching the user
453      * @param roleDN DN used when searching the role DN. Override the baseDN if
454      * it is defined
455      * @param roleSearchFilter Filter used when searching the role
456      * @param algorithm Default algorithm. If specified, the default is not
457      * 'clear' password
458      * @throws Exception if the resource can't be added
459      */

460     public void addJResourceLDAP(String JavaDoc name, String JavaDoc initialContextFactory, String JavaDoc providerUrl,
461             String JavaDoc securityAuthentication, String JavaDoc securityPrincipal, String JavaDoc securityCredentials,
462             String JavaDoc securityProtocol, String JavaDoc language, String JavaDoc referral, String JavaDoc stateFactories,
463             String JavaDoc authenticationMode, String JavaDoc userPasswordAttribute, String JavaDoc userRolesAttribute,
464             String JavaDoc roleNameAttribute, String JavaDoc baseDN, String JavaDoc userDN, String JavaDoc userSearchFilter, String JavaDoc roleDN,
465             String JavaDoc roleSearchFilter, String JavaDoc algorithm) throws Exception JavaDoc {
466
467         // Build a new JResourceLDAP
468
JResourceLDAP jResourceLDAP = new JResourceLDAP();
469         jResourceLDAP.setName(name);
470         jResourceLDAP.setInitialContextFactory(initialContextFactory);
471         jResourceLDAP.setProviderUrl(providerUrl);
472         jResourceLDAP.setSecurityAuthentication(securityAuthentication);
473         jResourceLDAP.setSecurityPrincipal(securityPrincipal);
474         jResourceLDAP.setSecurityCredentials(securityCredentials);
475         jResourceLDAP.setSecurityProtocol(securityProtocol);
476         jResourceLDAP.setLanguage(language);
477         jResourceLDAP.setReferral(referral);
478         jResourceLDAP.setStateFactories(stateFactories);
479         jResourceLDAP.setAuthenticationMode(authenticationMode);
480         jResourceLDAP.setUserPasswordAttribute(userPasswordAttribute);
481         jResourceLDAP.setUserRolesAttribute(userRolesAttribute);
482         jResourceLDAP.setRoleNameAttribute(roleNameAttribute);
483         jResourceLDAP.setBaseDN(baseDN);
484         jResourceLDAP.setUserDN(userDN);
485         jResourceLDAP.setUserSearchFilter(userSearchFilter);
486         jResourceLDAP.setRoleDN(roleDN);
487         jResourceLDAP.setRoleSearchFilter(roleSearchFilter);
488         jResourceLDAP.setAlgorithm(algorithm);
489
490         // Build xml
491
StringBuffer JavaDoc xml = new StringBuffer JavaDoc(JResources.HEADER_XML);
492         xml.append("<jonas-realm>");
493         xml.append("<jonas-ldaprealm>");
494         xml.append(jResourceLDAP.toXML());
495         xml.append("</jonas-ldaprealm>");
496         xml.append("</jonas-realm>");
497
498         // Add the resource
499
addResources(xml.toString());
500
501     }
502
503     /**
504      * Bind the given resource with the given name and register with a new
505      * MBean.
506      * @param name resource name
507      * @param jResource resource
508      */

509     public void bindResource(String JavaDoc name, JResource jResource) {
510         // bind the resource into the jndi
511
if (bindResourcesIntoJndi) {
512             try {
513                 ictx.rebind(jResource.getName(), jResource);
514                 if (logger.isLoggable(BasicLevel.DEBUG)) {
515                     logger.log(BasicLevel.DEBUG, "jResource " + jResource.getName() + " bound into the registry.");
516                 }
517             } catch (NamingException JavaDoc e) {
518                 logger.log(BasicLevel.ERROR, "Cannot bind the resource '" + jResource.getName() + "' into JNDI", e);
519             }
520         }
521
522         try {
523             // register security factory mbean
524
if (jResource instanceof JResourceMemory) {
525                 mbeanServer.registerMBean(jResource, JonasObjectName.securityMemoryFactory(jResource.getName()));
526             } else if (jResource instanceof JResourceDS) {
527                 mbeanServer.registerMBean(jResource, JonasObjectName.securityDatasourceFactory(jResource.getName()));
528             } else if (jResource instanceof JResourceLDAP) {
529                 mbeanServer.registerMBean(jResource, JonasObjectName.securityLdapFactory(jResource.getName()));
530             }
531         } catch (ServiceException se) {
532             logger.log(BasicLevel.ERROR, "JMX service not available", se);
533         } catch (Exception JavaDoc e) {
534             logger.log(BasicLevel.ERROR, "Can not register the MBean for the resource " + jResource.getName() + " : "
535                     + e.getMessage());
536             throw new ServiceException("Can not register the MBean for the resource " + jResource.getName() + " : "
537                     + e.getMessage());
538         }
539
540     }
541 }
542
Popular Tags