Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jsd/ftp/server/ftp/usermanager/LdapUserManager.java


1   /*
2    * ----------------------------------------------------------------------------
3    * JStrangeDownloader and all accompanying source code files are
4    * Copyright (C) 2002 Dusty Davidson (dustyd@iastate.edu)
5    * 
6    * This program is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU General Public License
8    * as published by the Free Software Foundation; either version 2
9    * of the License, or (at your option) any later version.
10   * 
11   * This program 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
14   * GNU General Public License for more details.
15   * 
16   * You should have received a copy of the GNU General Public License
17   * along with this program; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19   * ----------------------------------------------------------------------------
20   *  
21   * Please see gpl.txt for the full text of the GNU General Public
22   * License.
23   */
24  
25  package jsd.ftp.server.ftp.usermanager;
26  
27  import java.io.File;
28  import java.util.Collection;
29  import java.util.ArrayList;
30  import java.util.Properties;
31  import java.util.Collections;
32  import javax.naming.NamingException;
33  import javax.naming.Context;
34  import javax.naming.NamingEnumeration;
35  import javax.naming.directory.Attribute;
36  import javax.naming.directory.BasicAttribute;
37  import javax.naming.directory.DirContext;
38  import javax.naming.directory.InitialDirContext;
39  import javax.naming.directory.Attributes;
40  import javax.naming.directory.BasicAttributes;
41  import javax.naming.directory.SearchResult;
42  import javax.naming.directory.ModificationItem;
43  
44  import jsd.ftp.io.LogFile;
45  import jsd.ftp.server.ftp.FtpConfig;
46  
47  /**
48   * Ldap based user manager class. Tested using Netscape Directory Server 4.1.
49   * The LDAP requires the password to be nonempty for simple authentication. So
50   * instead of using empty string password (""), we will be using single space (" ").
51   * 
52   * @author <a href="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
53   */
54  public
55  class LdapUserManager extends UserManager {
56      
57      
58      // LDAP attributes
59    private final static String LOGIN      = "memberuid";
60      private final static String UID        = "uid";
61      private final static String CN         = "cn";
62      private final static String SN         = "sn";
63      private final static String PASSWORD   = "userpassword";
64      private final static String OBJ_CLASS  = "objectclass";
65      private final static String ENABLE     = "enableflag";
66      private final static String ROOT_DIR   = "homedirectory";
67      private final static String WRITE_PERM = "writepermission";
68      private final static String IDLE_TIME  = "idletime";
69      private final static String UP_RATE    = "uploadrate";
70      private final static String DOWN_RATE  = "downloadrate";
71    
72      private final static String[] ALL_ATTRS = {
73        CN,
74        LOGIN,
75          ENABLE,
76          ROOT_DIR,
77          WRITE_PERM,
78          IDLE_TIME,
79          UP_RATE,
80          DOWN_RATE
81      };
82      
83      private final static Attribute OBJCLASS_ATTR = new BasicAttribute(OBJ_CLASS, true);
84      
85      
86      // Currently we are using only one connection.
87      // This will be replaced by LDAP connection pool. 
88      private DirContext mAdminContext;
89      private Properties mAdminEnv;
90    private String mstLdapRoot;
91      
92    
93      /**
94       * Instantiate <code>UserManager</code> implementation.
95       * Open LDAP connection pool.
96       */
97      public LdapUserManager(FtpConfig cfg) throws Exception { 
98        super(cfg);
99          
100         // get ldap parameters
101         String url      = cfg.getProperty(FtpConfig.PREFIX + "ldap.url");
102         String ldapRoot = cfg.getProperty(FtpConfig.PREFIX + "ldap.root");
103         String admin    = cfg.getProperty(FtpConfig.PREFIX + "ldap.admin");
104         String password = cfg.getProperty(FtpConfig.PREFIX + "ldap.password");
105         String auth     = cfg.getProperty(FtpConfig.PREFIX + "ldap.authentication");
106         
107         mAdminEnv = new Properties();
108         mAdminEnv.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
109         mAdminEnv.setProperty(Context.PROVIDER_URL, url);
110         mAdminEnv.setProperty(Context.SECURITY_AUTHENTICATION, auth);             
111         mAdminEnv.setProperty(Context.SECURITY_PRINCIPAL, admin);             
112         mAdminEnv.setProperty(Context.SECURITY_CREDENTIALS, password);             
113                      
114         mAdminContext = new InitialDirContext(mAdminEnv);
115         mstLdapRoot = ldapRoot;
116         getConfig().getLogger().info("LDAP user manager opened.");
117     }
118     
119     
120     /**
121      * Get common name
122      */
123     private synchronized String getCommonName(String login) throws NamingException {
124       Attributes matchAttrs = new BasicAttributes(true);
125     matchAttrs.put(new BasicAttribute(LOGIN, login));
126         matchAttrs.put(OBJCLASS_ATTR);
127         NamingEnumeration answers = mAdminContext.search("ou=people," + mstLdapRoot, matchAttrs, ALL_ATTRS);
128     
129         String cn = null;
130         if (answers.hasMore()) {
131           SearchResult sr = (SearchResult)answers.next();
132             cn = sr.getAttributes().get(CN).get().toString();
133         }
134         answers.close();
135         return cn;
136     }
137     
138     
139     /**
140      * Get all user names
141      */
142     public synchronized Collection getAllUserNames() {
143         ArrayList allUsers = new ArrayList();
144         
145         try {
146           Attributes matchAttrs = new BasicAttributes(true);
147           matchAttrs.put(OBJCLASS_ATTR);
148           NamingEnumeration answers = mAdminContext.search("ou=people," + mstLdapRoot, matchAttrs, ALL_ATTRS);
149           while (answers.hasMore()) {
150             SearchResult sr = (SearchResult)answers.next();
151               String login = sr.getAttributes().get(LOGIN).get().toString();
152             allUsers.add(login);
153             }
154         }
155         catch(NamingException ex) {
156           getConfig().getLogger().error(ex);
157         }
158         
159         Collections.sort(allUsers);
160         return allUsers;
161     } 
162     
163     
164     /**
165      * Get user object.
166      */
167     public synchronized User getUserByName(String name) {
168       User user = null;
169         
170         try {
171           Attributes matchAttrs = new BasicAttributes(true);
172             matchAttrs.put(new BasicAttribute(LOGIN, name));
173           matchAttrs.put(OBJCLASS_ATTR);
174           NamingEnumeration answers = mAdminContext.search("ou=people," + mstLdapRoot, matchAttrs, ALL_ATTRS);
175           if (answers.hasMore()) {
176             SearchResult sr = (SearchResult)answers.next();
177                 Attributes attrs = sr.getAttributes();
178                         
179                 user = new User();
180                 user.setName(attrs.get(LOGIN).get().toString());
181                 user.getVirtualDirectory().setRootDirectory(new File(attrs.get(ROOT_DIR).get().toString()));
182               user.setEnabled(Boolean.TRUE.toString().equals(attrs.get(ENABLE).get().toString()));
183                 user.getVirtualDirectory().setWritePermission(Boolean.TRUE.toString().equals(attrs.get(WRITE_PERM).get().toString()));  
184               user.setMaxIdleTime( Integer.parseInt(attrs.get(IDLE_TIME).get().toString()) );
185                 user.setMaxUploadRate( Integer.parseInt(attrs.get(UP_RATE).get().toString()) );
186                 user.setMaxDownloadRate( Integer.parseInt(attrs.get(DOWN_RATE).get().toString()) );
187             }
188             answers.close();
189         }
190         catch(NamingException ex) {
191           getConfig().getLogger().error(ex);
192             user = null;
193         }
194         
195         return user;
196     }
197     
198     
199     /**
200      * User authentication.
201      */
202     public boolean authenticate(String name, String password) {
203         
204         // empty password string is not allowed
205         if (password == null) {
206           password = " ";
207         }
208         if (password.equals("")) {
209           password = " ";
210         }
211         
212         try {
213           String cn = getCommonName(name);
214             if (cn != null) {
215               Properties userProp = (Properties)mAdminEnv.clone();
216                 String dn = CN + '=' + cn + ",ou=people," + mstLdapRoot;
217               userProp.setProperty(Context.SECURITY_PRINCIPAL, dn);             
218             userProp.setProperty(Context.SECURITY_CREDENTIALS, password);
219                 DirContext userContext = new InitialDirContext(userProp);
220                 userContext.close(); 
221                 return true;
222             }
223         }
224         catch(NamingException ex) {  
225         }
226         return false;
227     }
228     
229     
230     /**
231      * Save user
232      */
233     public synchronized void save(User user) throws NamingException {
234       if (doesExist(user.getName())) {
235         update(user);
236         }
237         else {
238           add(user);
239         }
240     }
241     
242     
243     /**
244      * Add a new user
245      */
246     private synchronized void add(User user) throws NamingException {
247       
248         // empty password is not allowed
249         if (user.getPassword() == null) {
250           user.setPassword(" ");
251         }
252         if (user.getPassword().equals("")) {
253           user.setPassword(" ");
254         }
255         
256         String cn = user.getName() + "-" + System.currentTimeMillis();
257       String path = CN + '=' + cn + ",ou=people," + mstLdapRoot;
258         
259         Attributes attrs = new BasicAttributes(true);
260         attrs.put(new BasicAttribute(LOGIN, user.getName()));
261         attrs.put(new BasicAttribute(UID, user.getName()));
262         attrs.put(new BasicAttribute(CN, cn));
263         attrs.put(new BasicAttribute(SN, user.getName()));
264       attrs.put(new BasicAttribute(PASSWORD, user.getPassword()));
265       attrs.put(OBJCLASS_ATTR);
266         attrs.put(new BasicAttribute(ENABLE, String.valueOf(user.getEnabled())));
267         attrs.put(new BasicAttribute(ROOT_DIR, user.getVirtualDirectory().getRootDirectory()));
268         attrs.put(new BasicAttribute(WRITE_PERM, String.valueOf(user.getVirtualDirectory().getWritePermission())));
269         attrs.put(new BasicAttribute(IDLE_TIME, String.valueOf(user.getMaxIdleTime())));
270         attrs.put(new BasicAttribute(UP_RATE, String.valueOf(user.getMaxUploadRate())));
271         attrs.put(new BasicAttribute(DOWN_RATE, String.valueOf(user.getMaxDownloadRate())));
272         
273         mAdminContext.bind(path, null, attrs);
274     }
275     
276     
277     /**
278      * Update an existing user
279      */
280     private synchronized void update(User user) throws NamingException {
281       String cn = getCommonName(user.getName());
282         String dn = CN + '=' + cn + ",ou=people," + mstLdapRoot;
283         ArrayList mods = new ArrayList();
284         
285         if (user.getPassword() != null) {
286           if (user.getPassword().equals("")) {
287             user.setPassword(" ");
288             }
289           mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(PASSWORD, user.getPassword())));
290         }
291         mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(ENABLE, String.valueOf(user.getEnabled()))));
292         mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(ROOT_DIR, user.getVirtualDirectory().getRootDirectory())));
293         mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(WRITE_PERM, String.valueOf(user.getVirtualDirectory().getWritePermission()))));
294       mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(IDLE_TIME, String.valueOf(user.getMaxIdleTime()))));
295         mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(UP_RATE, String.valueOf(user.getMaxUploadRate()))));
296       mods.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(DOWN_RATE, String.valueOf(user.getMaxDownloadRate()))));
297       
298         
299         ModificationItem modArr[] = new ModificationItem[mods.size()];
300         for(int i=0; i<modArr.length; i++) {
301             modArr[i] = (ModificationItem)mods.get(i);
302         }
303         mAdminContext.modifyAttributes(dn, modArr);
304     }
305     
306     
307     /**
308      * User existance check
309      */
310     public synchronized boolean doesExist(String name) {
311       String cn = null;
312         try {
313           cn = getCommonName(name);
314         }
315         catch(NamingException ex) {
316           getConfig().getLogger().error(ex);
317         }
318         return cn != null;
319     }
320     
321     
322     /**
323      * Delete user
324      */
325     public synchronized void delete(String userName) throws NamingException {
326       String cn = getCommonName(userName);
327         if (cn != null) {
328           String dn = CN + '=' + cn + ",ou=people," + mstLdapRoot;
329             mAdminContext.unbind(dn);
330         }
331     }
332     
333     
334     /**
335      * Close user manager
336      */
337     public synchronized void dispose() {
338         if (mAdminContext != null) {
339             try {
340                 mAdminContext.close();
341             }
342             catch(NamingException ex) {
343             }
344             mAdminContext = null;
345         }
346     }
347         
348     // static block
349     static {
350         OBJCLASS_ATTR.add("top");
351         OBJCLASS_ATTR.add("person");
352         OBJCLASS_ATTR.add("organizationalPerson");
353         OBJCLASS_ATTR.add("inetOrgPerson");
354         OBJCLASS_ATTR.add("ftpUsers");
355     }
356 }    
357