Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2013 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
package edu.ucsb.nceas.metacat.authentication;
22

    
23
import java.io.Console;
24
import java.io.File;
25
import java.io.FileOutputStream;
26
import java.io.IOException;
27
import java.io.OutputStreamWriter;
28
import java.io.UnsupportedEncodingException;
29
import java.net.ConnectException;
30
import java.util.HashMap;
31
import java.util.List;
32
import java.util.Vector;
33

    
34
import org.apache.commons.configuration.ConfigurationException;
35
import org.apache.commons.configuration.XMLConfiguration;
36
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
37
import org.apache.commons.logging.Log;
38
import org.apache.commons.logging.LogFactory;
39

    
40
import edu.ucsb.nceas.metacat.AuthInterface;
41
import edu.ucsb.nceas.metacat.AuthLdap;
42
import edu.ucsb.nceas.metacat.properties.PropertyService;
43
import edu.ucsb.nceas.metacat.util.SystemUtil;
44
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
45

    
46
/**
47
 * This an authentication class base on a username/password file.
48
 * It is an alternative authentication mechanism of the ldap authentication.
49
 * The password file looks like:
50
 *<?xml version="1.0" encoding="UTF-8" ?>
51
 * <subjects>
52
 *  <users>
53
 *      <user dn="uid=tao,o=NCEAS,dc=ecoinformatics,dc=org">
54
 *          <password>*******</password>
55
 *          <email>foo@foo.com</email>
56
 *          <surName>Smith</surName>
57
 *          <givenName>John</givenName>
58
 *          <organization>NCEAS</organization>
59
 *          <memberof>nceas-dev</memberof>
60
 *      </user>
61
 *  </users>
62
 *  <groups>
63
 *    <group name="nceas-dev">
64
 *        <description>developers at NCEAS</description>
65
 *    </group>
66
 *  </groups>
67
 * </subjects>
68
 * http://commons.apache.org/proper/commons-configuration/userguide/howto_xml.html
69
 * @author tao
70
 *
71
 */
72
public class AuthFile implements AuthInterface {
73
    private static final String ORGANIZATIONNAME = "Unknown";
74
    private static final String ORGANIZATION = "organization";
75
    private static final String NAME = "name";
76
    private static final String DN = "dn";
77
    private static final String DESCRIPTION = "description";
78
    private static final String PASSWORD = "password";
79
    private static final String SLASH = "/";
80
    private static final String AT = "@";
81
    private static final String SUBJECTS = "subjects";
82
    private static final String USERS = "users";
83
    private static final String USER = "user";
84
    private static final String GROUPS = "groups";
85
    private static final String GROUP = "group";
86
    private static final String EMAIL = "email";
87
    private static final String SURNAME = "surName";
88
    private static final String GIVENNAME = "givenName";
89
    private static final String MEMBEROF = "memberof";
90
    private static final String INITCONTENT = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"+
91
                                    "<"+SUBJECTS+">\n"+"<"+USERS+">\n"+"</"+USERS+">\n"+"<"+GROUPS+">\n"+"</"+GROUPS+">\n"+"</"+SUBJECTS+">\n";
92
   
93
    
94
    
95
    private static Log log = LogFactory.getLog(AuthFile.class);
96
    private static XMLConfiguration userpassword = null;
97
    private String authURI = null;
98
    private static String passwordFilePath = null;
99
    private static AuthFileHashInterface hashClass = null;
100
    private boolean readPathFromProperty = true;
101
    
102
    /**
103
     * Get the instance of the AuthFile
104
     * @return
105
     * @throws AuthenticationException
106
     */
107
    /*public static AuthFile getInstance() throws AuthenticationException {
108
        if(authFile == null) {
109
            authFile = new AuthFile();
110
        }
111
        return authFile;
112
    }*/
113
    
114
    /**
115
     * Get the instance of the AuthFile from specified password file
116
     * @return
117
     * @throws AuthenticationException
118
     */
119
    /*public static AuthFile getInstance(String passwordFile) throws AuthenticationException {
120
        passwordFilePath = passwordFile;
121
        if(authFile == null) {
122
            authFile = new AuthFile();
123
        }
124
        return authFile;
125
    }*/
126
    
127
    /**
128
     * Constructor
129
     */
130
    public AuthFile() throws AuthenticationException {
131
        try {
132
            init();
133
        } catch (Exception e) {
134
            e.printStackTrace();
135
            throw new AuthenticationException(e.getMessage());
136
        }
137
        
138
    }
139
    
140
    /**
141
     * 
142
     * @param passwordFile
143
     * @throws AuthenticationException
144
     */
145
    public  AuthFile (String passwordFile) throws AuthenticationException {
146
        passwordFilePath = passwordFile;
147
        readPathFromProperty = false;
148
        try {
149
            init();
150
        } catch (Exception e) {
151
            e.printStackTrace();
152
            throw new AuthenticationException(e.getMessage());
153
        }
154
    }
155
    
156
    /*
157
     * Initialize the user/password configuration
158
     */
159
    private void init() throws PropertyNotFoundException, IOException, ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException {
160
        if(readPathFromProperty || passwordFilePath == null) {
161
            passwordFilePath  = PropertyService.getProperty("auth.file.path");
162
        }
163
        //System.out.println("the password file path is ======================= "+passwordFilePath);
164
        File passwordFile = new File(passwordFilePath);
165
        
166
        authURI = SystemUtil.getContextURL();
167
        String hashClassName = PropertyService.getProperty("auth.file.hashClassName");
168
        Class classDefinition = Class.forName(hashClassName);
169
        Object object = classDefinition.newInstance();
170
        hashClass = (AuthFileHashInterface) object;
171
        
172
        //if the password file doesn't exist, create a new one and set the initial content
173
        if(!passwordFile.exists()) {
174
            File parent = passwordFile.getParentFile();
175
            if(!parent.exists()) {
176
                boolean success = false;
177
                try {
178
                    success = parent.mkdirs();
179
                } catch (Exception e) {
180
                    throw new IOException("AuthFile.init - couldn't create the directory "+parent.getAbsolutePath()+ " since "+e.getMessage());
181
                }
182
                if(!success) {
183
                    throw new IOException("AuthFile.init - couldn't create the directory "+parent.getAbsolutePath()+ ", probably since the metacat doesn't have the write permission.");
184
                }
185
            }
186
            boolean success = false;
187
            try {
188
                success = passwordFile.createNewFile();
189
            }  catch (Exception e) {
190
                throw new IOException("AuthFile.init - couldn't create the file "+passwordFile.getAbsolutePath()+ " since "+e.getMessage());
191
            }
192
            if(!success) {
193
                throw new IOException("AuthFile.init - couldn't create the file "+parent.getAbsolutePath()+ ", probably since the metacat doesn't have the write permission.");
194
            }
195
            
196
            OutputStreamWriter writer = null;
197
            FileOutputStream output = null;
198
            try {
199
              output = new FileOutputStream(passwordFile);
200
              writer = new OutputStreamWriter(output, "UTF-8");
201
              writer.write(INITCONTENT);
202
            } finally {
203
              writer.close();
204
              output.close();
205
            }
206
          }
207
          userpassword = new XMLConfiguration(passwordFile);
208
          userpassword.setExpressionEngine(new XPathExpressionEngine());
209
          userpassword.setAutoSave(true);
210
          userpassword.setDelimiterParsingDisabled(true);
211
          userpassword.setAttributeSplittingDisabled(true);
212
    }
213
    
214
    @Override
215
    public boolean authenticate(String user, String password)
216
                    throws AuthenticationException {
217
        boolean match = false;
218
        String passwordRecord = userpassword.getString(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+PASSWORD);
219
        if(passwordRecord != null) {
220
            try {
221
                match = hashClass.match(password, passwordRecord);
222
            } catch (Exception e) {
223
                throw new AuthenticationException(e.getMessage());
224
            }
225
            
226
        }
227
        return match;
228
    }
229
    
230
    @Override
231
    /**
232
     * Get all users. This is two-dimmention array. Each row is a user. The first element of
233
     * a row is the user name. The second element is common name. The third one is the organization name (null).
234
     * The fourth one is the organization unit name (null). The fifth one is the email address.
235
     */
236
    public String[][] getUsers(String user, String password)
237
                    throws ConnectException {
238
        List<Object> users = userpassword.getList(USERS+SLASH+USER+SLASH+AT+DN);
239
        if(users != null && users.size() > 0) {
240
            String[][] usersArray = new String[users.size()][5];
241
            for(int i=0; i<users.size(); i++) {
242
                
243
                String dn = (String)users.get(i);
244
                usersArray[i][AuthInterface.USERDNINDEX] = dn; //dn
245
                String[] userInfo = getUserInfo(dn, password);
246
                usersArray[i][AuthInterface.USERCNINDEX] = userInfo[AuthInterface.USERINFOCNINDEX];//common name
247
                usersArray[i][AuthInterface.USERORGINDEX] = userInfo[AuthInterface.USERINFOORGANIDEX];//organization name. We set null
248
                usersArray[i][AuthInterface.USERORGUNITINDEX] = null;//organization ou name. We set null.
249
                usersArray[i][AuthInterface.USEREMAILINDEX] = userInfo[AuthInterface.USERINFOEMAILINDEX];
250
               
251
            }
252
            return usersArray;
253
        }
254
        return null;
255
    }
256
    
257
    @Override
258
    /**
259
     * Get an array about the user. The first column is the common name, the second column is the organization name.
260
     * The third column is the email address. It always returns an array. But the elements of the array can be null.
261
     */
262
    public String[] getUserInfo(String user, String password)
263
                    throws ConnectException {
264
        String[] userinfo = new String[3];
265
        User aUser = new User();
266
        aUser.setDN(user);
267
        String surname = null;
268
        List<Object> surNames = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+SURNAME);
269
        if(surNames != null && !surNames.isEmpty()) {
270
            surname = (String)surNames.get(0);
271
        }
272
        aUser.setSurName(surname);
273
        String givenName = null;
274
        List<Object> givenNames = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+GIVENNAME);
275
        if(givenNames != null && !givenNames.isEmpty()) {
276
            givenName = (String)givenNames.get(0);
277
        }
278
        aUser.setGivenName(givenName);
279
        userinfo[AuthInterface.USERINFOCNINDEX] = aUser.getCn();//common name
280
        String organization = null;
281
        List<Object> organizations = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+ORGANIZATION);
282
        if(organizations != null && !organizations.isEmpty()) {
283
            organization = (String)organizations.get(0);
284
        }
285
        userinfo[AuthInterface.USERINFOORGANIDEX] = organization;//organization name.
286
        aUser.setOrganization(organization);
287
        List<Object> emails = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+EMAIL);
288
        String email = null;
289
        if(emails != null && !emails.isEmpty() ) {
290
            email = (String)emails.get(0);
291
        }
292
        aUser.setEmail(email);
293
        userinfo[AuthInterface.USERINFOEMAILINDEX] = email;
294
        return userinfo;
295
    }
296
    
297
    
298
    @Override
299
    /**
300
     * Get the users for a particular group from the authentication service
301
     * The null will return if there is no user.
302
     * @param user
303
     *            the user for authenticating against the service
304
     * @param password
305
     *            the password for authenticating against the service
306
     * @param group
307
     *            the group whose user list should be returned
308
     * @returns string array of the user names belonging to the group
309
     */
310
    public String[] getUsers(String user, String password, String group)
311
                    throws ConnectException {
312
        List<Object> users = userpassword.getList(USERS+SLASH+USER+"["+MEMBEROF+"='"+group+"']"+SLASH+AT+DN);
313
        if(users != null && users.size() > 0) {
314
            String[] usersArray = new String[users.size()];
315
            for(int i=0; i<users.size(); i++) {
316
                usersArray[i] = (String) users.get(i);
317
            }
318
            return usersArray;
319
        }
320
        return null;
321
    }
322
    
323
    @Override
324
    /**
325
     * Get all groups from the authentication service. It returns a two dimmension array. Each row is a
326
     * group. The first column is the group name. The second column is the description. The null will return if no group found.
327
     */
328
    public String[][] getGroups(String user, String password)
329
                    throws ConnectException {
330
        List<Object> groups = userpassword.getList(GROUPS+SLASH+GROUP+SLASH+AT+NAME);
331
        if(groups!= null && groups.size() >0) {
332
            String[][] groupsArray = new String[groups.size()][2];
333
            for(int i=0; i<groups.size(); i++) {
334
                String groupName = (String) groups.get(i);
335
                groupsArray[i][AuthInterface.GROUPNAMEINDEX] = groupName;
336
                String description = null;
337
                List<Object>descriptions = userpassword.getList(GROUPS+SLASH+GROUP+"["+AT+NAME+"='"+groupName+"']"+SLASH+DESCRIPTION);
338
                if(descriptions != null && !descriptions.isEmpty()) {
339
                    description = (String)descriptions.get(0);
340
                }
341
                groupsArray[i][AuthInterface.GROUPDESINDEX] = description; 
342
            }
343
            return groupsArray;
344
        }
345
        return null;
346
    }
347
    
348
    @Override
349
    /**
350
     * Get groups from a specified user. It returns two dimmension array. Each row is a
351
     * group. The first column is the group name. The null will return if no group found.
352
     */
353
    public String[][] getGroups(String user, String password, String foruser)
354
                    throws ConnectException {
355
        List<Object> groups = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+foruser+"']"+SLASH+MEMBEROF);
356
        if(groups != null && groups.size() > 0) {
357
            String[][] groupsArray = new String[groups.size()][2];
358
            for(int i=0; i<groups.size(); i++) {
359
                String groupName = (String) groups.get(i);
360
                groupsArray[i][AuthInterface.GROUPNAMEINDEX] = groupName;
361
                String description = null;
362
                List<Object>descriptions = userpassword.getList(GROUPS+SLASH+GROUP+"["+AT+NAME+"='"+groupName+"']"+SLASH+DESCRIPTION);
363
                if(descriptions != null && !descriptions.isEmpty()) {
364
                    description = (String)descriptions.get(0);
365
                }
366
                groupsArray[i][AuthInterface.GROUPDESINDEX] = description; 
367
            }
368
            return groupsArray;
369
        }
370
        return null;
371
    }
372
    
373
    @Override
374
    public HashMap<String, Vector<String>> getAttributes(String foruser)
375
                    throws ConnectException {
376
        //we only check if the user exists or not.
377
        if(!userExists(foruser)) {
378
            throw new ConnectException("NameNotFoundException - the user "+foruser+" doesn't exist in the password file.");
379
        }
380
        return null;
381
    }
382
    
383
    @Override
384
    public HashMap<String, Vector<String>> getAttributes(String user,
385
                    String password, String foruser) throws ConnectException {
386
        // TODO Auto-generated method stub
387
        return null;
388
    }
389
    
390
    @Override
391
    public String getPrincipals(String user, String password)
392
                    throws ConnectException {
393
            StringBuffer out = new StringBuffer();
394

    
395
            out.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
396
            out.append("<principals>\n");
397
            out.append("  <authSystem URI=\"" +authURI
398
                    + "\" organization=\"" + ORGANIZATIONNAME + "\">\n");
399

    
400
            // get all groups for directory context
401
            String[][] groups = getGroups(user, password);
402
            String[][] users = getUsers(user, password);
403
            int userIndex = 0;
404

    
405
            // for the groups and users that belong to them
406
            if (groups != null && users != null && groups.length > 0) {
407
                for (int i = 0; i < groups.length; i++) {
408
                    out.append("    <group>\n");
409
                    out.append("      <groupname>" + groups[i][AuthInterface.GROUPNAMEINDEX] + "</groupname>\n");
410
                    if(groups[i].length > 1) {
411
                        out.append("      <description>" + groups[i][AuthInterface.GROUPDESINDEX] + "</description>\n");
412
                    }
413
                    String[] usersForGroup = getUsers(user, password, groups[i][0]);
414
                    if(usersForGroup != null) {
415
                        for (int j = 0; j < usersForGroup.length; j++) {
416
                            userIndex = AuthLdap.searchUser(usersForGroup[j], users);
417
                            out.append("      <user>\n");
418

    
419
                            if (userIndex < 0) {
420
                                out.append("        <username>" + usersForGroup[j]
421
                                        + "</username>\n");
422
                            } else {
423
                                out.append("        <username>" + users[userIndex][0]
424
                                        + "</username>\n");
425
                                if(users[userIndex][AuthInterface.USERCNINDEX] != null) {
426
                                    out.append("        <name>" + users[userIndex][AuthInterface.USERCNINDEX]
427
                                                    + "</name>\n");
428
                                }
429
                                if(users[userIndex][AuthInterface.USERORGINDEX] != null) {
430
                                    out.append("        <organization>" + users[userIndex][AuthInterface.USERORGINDEX]
431
                                                    + "</organization>\n");
432
                                }
433
                                
434
                                if(users[userIndex][AuthInterface.USERORGUNITINDEX] != null) {
435
                                    out.append("      <organizationUnitName>"
436
                                                    + users[userIndex][AuthInterface.USERORGUNITINDEX]
437
                                                    + "</organizationUnitName>\n");
438
                                }
439
                                if(users[userIndex][AuthInterface.USEREMAILINDEX] != null) {
440
                                    out.append("        <email>" + users[userIndex][AuthInterface.USEREMAILINDEX]
441
                                                    + "</email>\n");
442
                                }
443
                               
444
                            }
445

    
446
                            out.append("      </user>\n");
447
                        }
448
                    }
449
                   
450
                    out.append("    </group>\n");
451
                }
452
            }
453

    
454
            if (users != null) {
455
                // for the users not belonging to any grou8p
456
                for (int j = 0; j < users.length; j++) {
457
                    out.append("    <user>\n");
458
                    out.append("      <username>" + users[j][0] + "</username>\n");
459
                    if(users[j][AuthInterface.USERCNINDEX] != null) {
460
                        out.append("        <name>" + users[j][AuthInterface.USERCNINDEX]
461
                                        + "</name>\n");
462
                    }
463
                    if(users[j][AuthInterface.USERORGINDEX] != null) {
464
                        out.append("        <organization>" + users[j][AuthInterface.USERORGINDEX]
465
                                        + "</organization>\n");
466
                    }
467
                    
468
                    if(users[j][AuthInterface.USERORGUNITINDEX] != null) {
469
                        out.append("      <organizationUnitName>"
470
                                        + users[j][AuthInterface.USERORGUNITINDEX]
471
                                        + "</organizationUnitName>\n");
472
                    }
473
                    if(users[j][AuthInterface.USEREMAILINDEX] != null) {
474
                        out.append("        <email>" + users[j][AuthInterface.USEREMAILINDEX]
475
                                        + "</email>\n");
476
                    }
477
                   
478
                    out.append("    </user>\n");
479
                }
480
            }
481

    
482
            out.append("  </authSystem>\n");
483
        
484
        out.append("</principals>");
485
        return out.toString();
486
    }
487
    
488
    /**
489
     * Add a user to the file
490
     * @param userName the name of the user
491
     * @param groups  the groups the user belong to. The group should exist in the file
492
     * @param password  the password of the user
493
     */
494
    public void addUser(String dn, String[] groups, String plainPass, String hashedPass, String email, String surName, String givenName, String organization) throws AuthenticationException{
495
       User user = new User();
496
       user.setDN(dn);
497
       user.setGroups(groups);
498
       user.setPlainPass(plainPass);
499
       user.setHashedPass(hashedPass);
500
       user.setEmail(email);
501
       user.setSurName(surName);
502
       user.setGivenName(givenName);
503
       user.setOrganization(organization);
504
       user.serialize();
505
    }
506
    
507
    /**
508
     * Add a group into the file
509
     * @param groupName the name of group
510
     */
511
    public void addGroup(String groupName, String description) throws AuthenticationException{
512
        if(groupName == null || groupName.trim().equals("")) {
513
            throw new AuthenticationException("AuthFile.addGroup - can't add a group whose name is null or blank.");
514
        }
515
        if(!groupExists(groupName)) {
516
            if(userpassword != null) {
517
              userpassword.addProperty(GROUPS+" "+GROUP+AT+NAME, groupName);
518
              if(description != null && !description.trim().equals("")) {
519
                  userpassword.addProperty(GROUPS+SLASH+GROUP+"["+AT+NAME+"='"+groupName+"']"+" "+DESCRIPTION, description);
520
              }
521
              //userpassword.reload();
522
             }
523
        } else {
524
            throw new AuthenticationException("AuthFile.addGroup - can't add the group "+groupName+" since it already exists.");
525
        }
526
    }
527
    
528
   
529
    
530
    /**
531
     * Change the password of the user to the new one which is hashed
532
     * @param usrName the specified user.   
533
     * @param newPassword the new password which will be set
534
     */
535
    public void modifyPassWithHash(String userName, String newHashPassword) throws AuthenticationException {
536
       User user = new User();
537
       user.setDN(userName);
538
       user.modifyHashPass(newHashPassword);
539
    }
540
    
541
    /**
542
     * Change the password of the user to the new one which is plain. However, only the hashed version will be serialized.
543
     * @param usrName the specified user.   
544
     * @param newPassword the new password which will be set
545
     */
546
    public void modifyPassWithPlain(String userName, String newPlainPassword) throws AuthenticationException {
547
        User user = new User();
548
        user.setDN(userName);
549
        user.modifyPlainPass(newPlainPassword);
550
    }
551
    
552
    
553
    /**
554
     * Add a user to a group
555
     * @param userName  the name of the user. the user should already exist
556
     * @param group  the name of the group. the group should already exist
557
     */
558
    public void addUserToGroup(String userName, String group) throws AuthenticationException {
559
        User user = new User();
560
        user.setDN(userName);
561
        user.addToGroup(group);
562
    }
563
    
564
    /**
565
     * Remove a user from a group.
566
     * @param userName  the name of the user. the user should already exist.
567
     * @param group the name of the group
568
     */
569
    public void removeUserFromGroup(String userName, String group) throws AuthenticationException{
570
        User user = new User();
571
        user.setDN(userName);
572
        user.removeFromGroup(group);
573
    }
574
    
575
  
576
    
577
    /**
578
     * If the specified user name exist or not
579
     * @param userName the name of the user
580
     * @return true if the user eixsit
581
     */
582
    private synchronized boolean userExists(String userName) throws AuthenticationException{
583
        if(userName == null || userName.trim().equals("")) {
584
            throw new AuthenticationException("AuthFile.userExist - can't judge if a user exists when its name is null or blank.");
585
        }
586
        List<Object> users = userpassword.getList(USERS+SLASH+USER+SLASH+AT+DN);
587
        if(users != null && users.contains(userName)) {
588
            return true;
589
        } else {
590
            return false;
591
        }
592
    }
593
    
594
    /**
595
     * If the specified group exist or not
596
     * @param groupName the name of the group
597
     * @return true if the user exists
598
     */
599
    private synchronized boolean groupExists(String groupName) throws AuthenticationException{
600
        if(groupName == null || groupName.trim().equals("")) {
601
            throw new AuthenticationException("AuthFile.groupExist - can't judge if a group exists when its name is null or blank.");
602
        }
603
        List<Object> groups = userpassword.getList(GROUPS+SLASH+GROUP+SLASH+AT+NAME);
604
        if(groups != null && groups.contains(groupName)) {
605
            return true;
606
        } else {
607
            return false;
608
        }
609
    }
610
    
611
    /*
612
     * Encrypt a plain text
613
     */
614
    private static String encrypt(String plain)  {
615
      return hashClass.hash(plain);
616
    }
617
    
618
    
619
    /**
620
     * A method is used to help administrator to manage users and groups
621
     * @param argus
622
     * @throws Exception
623
     */
624
    public static void main(String[] argus) throws Exception {
625
            String USERADD = "useradd";
626
            String USERMOD = "usermod";
627
            String GROUPADD = "groupadd";
628
            String USAGE = "usage";
629
            if(argus == null || argus.length ==0) {
630
              System.out.println("Please make sure that there are two arguments - \"$BASE_WEB_INF\" and\" $@\" after the class name edu.ucsb.nceas.metacat.authentication.AuthFile in the script file.");
631
              System.exit(1);
632
            } else if(argus.length ==1) {
633
                printUsage();
634
                System.exit(1);
635
            }
636
            PropertyService.getInstance(argus[0]);
637
            AuthFile authFile = new AuthFile();
638
            if(argus[1] != null && argus[1].equals(GROUPADD)) {
639
                handleGroupAdd(authFile,argus);
640
            } else if (argus[1] != null && argus[1].equals(USERADD)) {
641
                handleUserAdd(authFile,argus);
642
            } else if (argus[1] != null && argus[1].equals(USERMOD)) {
643
                handleUserMod(authFile, argus);
644
            } else if (argus[1] != null && argus[1].equals(USAGE)) {
645
                printUsage();
646
            } else {
647
                System.out.print("Error: the unknown action "+argus[1]);
648
            }
649
    }
650
    
651
    /*
652
     * Handle the groupAdd action in the main method
653
     */
654
    private static void handleGroupAdd(AuthFile authFile, String[]argus) throws AuthenticationException {
655
        HashMap<String, String> map = null;
656
        String G = "-g";
657
        String D = "-d";
658
        Vector<String> pairedOptions = new Vector<String>();
659
        pairedOptions.add(G);
660
        pairedOptions.add(D);
661
        int startIndex = 2;
662
        try {
663
            map = parseArgus(startIndex, argus, pairedOptions, null);
664
        } catch (Exception e ) {
665
            System.out.println("Error in the groupadd command: "+e.getMessage());
666
            System.exit(1);
667
        }
668
        String groupName = null;
669
        String description = null;
670
        if(map.keySet().size() == 0) {
671
            System.out.println("Error in the groupadd command: the \""+G+" group-name\" is required.");
672
            System.exit(1);
673
        } else if(map.keySet().size() ==1 || map.keySet().size() ==2) {
674
            groupName = map.get(G);
675
            if(groupName == null || groupName.trim().equals("")) {
676
                System.out.println("Error in the groupadd command : the \""+G+" group-name\" is required.");
677
                System.exit(1);
678
            }
679
            description = map.get(D);
680
            authFile.addGroup(groupName, description);
681
            System.out.println("Successfully added a group \""+groupName+"\" to the file authentication system");
682
        } else {
683
            printError(argus);
684
            System.exit(1);
685
        }
686
    }
687
    
688
    /*
689
     * Handle the userAdd action in the main method
690
     */
691
    private static void  handleUserAdd(AuthFile authFile,String[]argus) throws UnsupportedEncodingException, AuthenticationException{
692
      
693
        String I = "-i";
694
        String H = "-h";
695
        String DN = "-dn";
696
        String G = "-g";
697
        String E = "-e";
698
        String S = "-s";
699
        String F = "-f";
700
        String O = "-o";
701
        Vector<String> pairedOptions = new Vector<String>();
702
        pairedOptions.add(H);
703
        pairedOptions.add(DN);
704
        pairedOptions.add(G);
705
        pairedOptions.add(E);
706
        pairedOptions.add(S);
707
        pairedOptions.add(F);
708
        pairedOptions.add(O);
709
        Vector<String> singleOptions = new Vector<String>();
710
        singleOptions.add(I);
711
        
712
        HashMap<String, String> map = new HashMap<String, String>();
713
        int startIndex = 2;
714
        try {
715
            map = parseArgus(startIndex, argus, pairedOptions, singleOptions);
716
        } catch (Exception e) {
717
            System.out.println("Error in the useradd command: "+e.getMessage());
718
            System.exit(1);
719
        }
720
       
721
        String dn = map.get(DN);
722
        if(dn == null || dn.trim().equals("")) {
723
            System.out.println("The \"-dn user-distinguish-name\" is requried in the useradd command ."); 
724
            System.exit(1);
725
        } 
726
        String plainPassword = null;
727
        String hashedPassword = null;
728
       
729
        
730
        String input = map.get(I);
731
        String passHash = map.get(H);
732
        if(input != null && passHash != null) {
733
            System.out.println("Error in the useradd command: you only can choose either \"-i\" (input a password) or \"-h hashed-password\" (pass through a hashed passwword).");
734
            System.exit(1);
735
        } else if (input == null && passHash == null) {
736
            System.out.println("Error in the useradd command: you must choose either \"-i\" (input a password) or \"-h hashed-password\" (pass through a hashed password).");
737
            System.exit(1);
738
        } else if(input != null) {
739
            plainPassword = inputPassword();
740
            //System.out.println("============the plain password is "+plainPassword);
741
        } else if(passHash != null) {
742
            hashedPassword = passHash;
743
        }
744
        
745
        String group = map.get(G);
746
        //System.out.println("the groups name is "+group);
747
        String[] groups = null;
748
        if(group != null && !group.trim().equals("")) {
749
            groups = new String[1];
750
            groups[0]=group;
751
            //System.out.println("set the first element of the groups to "+groups[0]);
752
        }
753
        String email = map.get(E);
754
        String surname = map.get(S);
755
        String givenname = map.get(F);
756
        String organization = map.get(O);
757
        authFile.addUser(dn, groups, plainPassword, hashedPassword, email, surname, givenname, organization);
758
        System.out.println("Successfully added a user \""+dn+"\" to the file authentication system ");
759
    }
760
    
761
    /*
762
     * Handle modify a user's password or group information.
763
     */
764
    private static void handleUserMod(AuthFile authFile, String[] argus) throws AuthenticationException, UnsupportedEncodingException {
765
        String PASSWORD = "-password";
766
        String GROUP = "-group";
767
        if(argus.length < 3) {
768
            System.out.println("Error: the sub action \"-password\" or \"-group\" should follow the action \"usermod\"");
769
            System.exit(1);
770
        } else {
771
            if(argus[2] != null && argus[2].equals(PASSWORD)) {
772
                handleModifyPass(authFile, argus);
773
            } else if (argus[2] != null && argus[2].equals(GROUP)) {
774
                handleModifyGroup(authFile, argus);
775
            } else {
776
                System.out.println("Error: the sub action \""+argus[2]+"\" is unkown in the action \"usermod\"");
777
                System.exit(1);
778
            }
779
        }
780
    }
781
    
782
    /*
783
     * Handle the action to modify the password of a user
784
     */
785
    private static void handleModifyPass(AuthFile authFile, String[] argus) throws UnsupportedEncodingException, AuthenticationException {
786
        String DN = "-dn";
787
        String I = "-i";
788
        String H = "-h";
789
        Vector<String> pairedOptions = new Vector<String>();
790
        pairedOptions.add(H);
791
        pairedOptions.add(DN);
792
        Vector<String> singleOptions = new Vector<String>();
793
        singleOptions.add(I);
794
        HashMap<String, String> map = new HashMap<String, String>();
795
        int startIndex = 3;
796
        try {
797
            map = parseArgus(startIndex, argus, pairedOptions, singleOptions);
798
        } catch (Exception e) {
799
            System.out.println("Error in the usermod -password command: "+e.getMessage());
800
            System.exit(1);
801
        }
802
      
803
        String dn = map.get(DN);
804
        if(dn == null || dn.trim().equals("")) {
805
            System.out.println("Error in the usermod -password command: The \"-dn user-distinguish-name\" is requried."); 
806
            System.exit(1);
807
        }
808
        String plainPassword = null;
809
        String hashedPassword = null;
810
        
811
        String input = map.get(I);
812
        String passHash = map.get(H);
813
        if(input != null && passHash != null) {
814
            System.out.println("Error in the usermod -password command: you only can choose either \"-i\" (input a password) or \"-h hashed-password\" (pass through a hashed password).");
815
            System.exit(1);
816
        } else if (input == null && passHash == null) {
817
            System.out.println("Error in the usermod -password command: you must choose either \"-i\" (input a password) or \"-h hashed-password\" (pass through a hashed password).");
818
            System.exit(1);
819
        } else if(input != null) {
820
            plainPassword = inputPassword();
821
            //System.out.println("============the plain password is "+plainPassword);
822
            authFile.modifyPassWithPlain(dn, plainPassword);
823
            System.out.println("Successfully modified the password for the user \""+dn+"\".");
824
        } else if(passHash != null) {
825
            hashedPassword = passHash;
826
            authFile.modifyPassWithHash(dn, hashedPassword);
827
            System.out.println("Successfully modified the password for the user "+dn+"\".");
828
        }
829
    }
830
    
831
    /*
832
     * Handle the action adding/removing a user to/from a group
833
     */
834
    private static void handleModifyGroup(AuthFile authFile, String[] argus) throws AuthenticationException {
835
        String DN = "-dn";
836
        String A = "-a";
837
        String R = "-r";
838
        String G = "-g";
839
        Vector<String> pairedOptions = new Vector<String>();
840
        pairedOptions.add(G);
841
        pairedOptions.add(DN);
842
        Vector<String> singleOptions = new Vector<String>();
843
        singleOptions.add(A);
844
        singleOptions.add(R);
845
        HashMap<String, String> map = new HashMap<String, String>();
846
        int startIndex = 3;
847
        try {
848
            map = parseArgus(startIndex, argus, pairedOptions, singleOptions);
849
        } catch (Exception e) {
850
            System.out.println("Error in the usermod -group command: "+e.getMessage());
851
            System.exit(1);
852
        }
853
               
854
        String add = map.get(A);
855
        String remove = map.get(R);
856
        String group = map.get(G);
857
        String dn = map.get(DN);
858
        if(dn == null || dn.trim().equals("")) {
859
            System.out.println("Error in the usermod -group command: the \"-dn user-distinguish-name\" is required.");
860
            System.exit(1);
861
        }
862
        
863
        if(group == null || group.trim().equals("")) {
864
            System.out.println("Error in the usermod -group command: the \"-g group-name\" is required.");
865
            System.exit(1);
866
        }
867
        
868
        if(add != null && remove!= null) {
869
            System.out.println("Error in the usermod -group command: You can only choose either \"-a\" (add the user to the group) or \"-r\" (remove the user from the group).");
870
            System.exit(1);
871
        } else if (add == null && remove == null) {
872
            System.out.println("Error in the usermod -group command: You must choose either \"-a\" (add the user to the group) or \"-r\" (remove the user from the group).");
873
            System.exit(1);
874
        } else if (remove != null) {
875
            authFile.removeUserFromGroup(dn, group);
876
            System.out.println("Successfully removed the user "+dn+" from the group \""+group+"\".");
877
        } else {
878
            authFile.addUserToGroup(dn, group);
879
            System.out.println("Successfully added the user "+dn+" to the group \""+group+"\".");
880
        }
881
    }
882
    
883
    
884
    /**
885
     * Parse the arguments to get the pairs of option/value. If it is a single option (it doesn't need a value), the pair will be switch/switch. 
886
     * @param startIndex the index of arguments where we will start.
887
     * @param argus the arguments array will be parsed.
888
     * @param pairedOptions the known options which should be a pair
889
     * @param singleOptions the know options which just has a single value
890
     * @return the empty map if there is no pairs were found
891
     * @throws Exception if there is an illegal argument.
892
     */
893
    private static HashMap<String, String> parseArgus(int startIndex, String[]argus, Vector<String>pairedOptions, Vector<String>singleOptions) throws Exception {
894
        HashMap<String, String> map = new HashMap<String, String>();
895
        if(argus != null) {
896
            for(int i=startIndex; i<argus.length; i++) {
897
                String arg = argus[i];
898
                if(map.containsKey(arg)) {
899
                    throw new Exception("The command line can't have duplicate options \""+arg+"\".");
900
                }
901
                
902
                if(singleOptions != null && singleOptions.contains(arg)) {
903
                    //we find a single option
904
                    if(i==argus.length-1) {
905
                        //it is the last argument, this is fine.
906
                        map.put(arg, arg);
907
                    } else if (i<argus.length -1) {
908
                        //it is not the last argument. 
909
                        if ((pairedOptions != null && pairedOptions.contains(argus[i+1])) || singleOptions.contains(argus[i+1])) {
910
                            //it follows an option, this is fine
911
                            map.put(arg, arg);
912
                        } else {
913
                            //it follows a vlaue, this is illegal
914
                            throw new Exception("The option \""+arg+"\" shouldn't be followed any value, e.g. "+ argus[i+1]+".");
915
                        }
916
                    }
917
                } else if (pairedOptions != null && pairedOptions.contains(arg)) {
918
                    //we found an option which should follow a vlaue
919
                    if(i==argus.length-1) {
920
                        //it is the last argument (no value follows it)
921
                        throw new Exception("The option \""+arg+"\" must be followed by a value");
922
                    } else {
923
                        //it is not the last argument and we need to check its following value
924
                        if (!pairedOptions.contains(argus[i+1]) && (singleOptions == null || !singleOptions.contains(argus[i+1]))) {
925
                            //it is NOT followed by an option, this is fine
926
                            map.put(arg, argus[i+1]);
927
                        } else {
928
                            //it is followed by an option, this is illegal
929
                            throw new Exception("The option \""+arg+"\" shouldn't be followed the option \""+ argus[i+1]+"\". It should be followed by a value.");
930
                        }
931
                    }
932
                } else {
933
                    //we found an argument is not an option
934
                    if(pairedOptions == null || !pairedOptions.contains(argus[i-1])) {
935
                        //the previous argument is not an option switch
936
                        throw new Exception("The \""+arg+"\" is an illegal argument");
937
                    }
938
                }
939
            } 
940
        }
941
        return map;
942
    }
943
    
944
    /*
945
     * Input the password
946
     */
947
    private static String inputPassword() throws UnsupportedEncodingException {
948
        String password = null;
949
        String quit = "q";
950
        Console console = System.console();
951
        if (console == null) {
952
            System.out.println("Sorry, we can't fetch the console from the system. You can't use the option \"-i\" to input a password. You have to use the option \"-h hashed-password\" to pass through a hashed passwprd in the useradd command. ");
953
            System.exit(1);
954
        }
955
  
956
        while(true) {
957
                System.out.print("Enter your new password (input 'q' to quit): ");
958
                String password1 = new String(console.readPassword());
959
                if(password1== null || password1.trim().equals("")) {
960
                    System.out.println("Error: the password can't be blank or null. Please try again.");
961
                    continue;
962
                } else if (password1.equals(quit)) {
963
                    System.exit(0);
964
                }
965
                System.out.print("Confirm your new password (input 'q' to quit): ");
966
                String password2 = new String(console.readPassword());
967
                if(password2 == null || password2.trim().equals("")) {
968
                    System.out.println("Error: the password can't be blank or null. Please try again.");
969
                    continue;
970
                }  else if (password2.equals(quit)) {
971
                    System.exit(0);
972
                }
973
                
974
                if(!password1.equals(password2)) {
975
                    System.out.println("Error: The second password does't match the first one. Please try again.");
976
                } else {
977
                    password = password1;
978
                    break;
979
                }
980
                
981
            
982
        }
983
        
984
        return password;
985
        
986
    }
987
    /*
988
     * Print out the usage statement
989
     */
990
    private static void printUsage() {
991
        System.out.println("Usage:\n"+
992
                        "./authFileManager.sh useradd -i -dn <user-distinguish-name> [-g <group-name> -e <email-address> -s <surname> -f <given-name> -o <organizationName>]\n" +
993
                        "./authFileManager.sh useradd -h <hashed-password> -dn <user-distinguish-name> [-g <group-name> -e <email-address> -s <surname> -f <given-name> -o <organizationName>]\n"+
994
                        "./authFileManager.sh groupadd -g group-name [-d description]\n" +
995
                        "./authFileManager.sh usermod -password -dn <user-distinguish-name> -i\n"+
996
                        "./authFileManager.sh usermod -password -dn <user-distinguish-name> -h <new-hashed-password>\n"+
997
                        "./authFileManager.sh usermod -group -a -dn <user-distinguish-name> -g <added-group-name>\n" +
998
                        "./authFileManager.sh usermod -group -r -dn <user-distinguish-name> -g <removed-group-name>\n"+
999
                        "Note:\n"+"1. Metacat currently uses Bcrypt algorithm to hash the password. The hashed password following the \"-h\" should be generated by a Bcrypt algorithm.\n"+
1000
                        "  The hash string usually has $ signs which can interfere with the command line arguments. You should use two SINGLE quotes to wrap the entire hashed string.\n"+
1001
                        "2. The user-distinguish-name must look like \"uid=john,o=something,dc=something,dc=something\" and the group-name must look like \"cn=dev,o=something,dc=something,dc=something\".\n"+
1002
                        "3. if a value of an option has spaces, the value should be enclosed by the double quotes.\n"+
1003
                        "  For example: ./authFileManager.sh groupadd -g cn=dev,o=something,dc=something,dc=something -d \"Developers at NCEAS\"\n"+
1004
                        "4. \"-d description\" in the \"groupadd\" command is optional; \"-g groupname -e email-address -s surname -f given-name -o organizationName\" in the \"useradd\" command are optional as well.");
1005
                       
1006
                        
1007
    }
1008
    
1009
    /*
1010
     * Print out the statement to say it is a illegal command
1011
     */
1012
    private static void printError(String[] argus) {
1013
        if(argus != null) {
1014
            System.out.println("Error: it is an illegal command (probably with some illegal options): ");
1015
            for(int i=0; i<argus.length; i++) {
1016
                if(i!= 0) {
1017
                    System.out.print(argus[i]+" ");
1018
                }
1019
            }
1020
            System.out.println("");
1021
        }
1022
       
1023
    }
1024

    
1025
    
1026
    /**
1027
     * An class represents the information for a user. 
1028
     * @author tao
1029
     *
1030
     */
1031
    private class User {
1032
        private String dn = null;//the distinguish name
1033
        private String plainPass = null;
1034
        private String hashedPass = null;
1035
        private String email = null;
1036
        private String surName = null;
1037
        private String givenName = null;
1038
        private String cn = null;//the common name
1039
        private String[] groups = null;
1040
        private String organization = null;
1041
        
1042
        /**
1043
         * Get the organization of the user
1044
         * @return
1045
         */
1046
        public String getOrganization() {
1047
            return organization;
1048
        }
1049
        
1050
        /**
1051
         * Set the organization for the user.
1052
         * @param organization
1053
         */
1054
        public void setOrganization(String organization) {
1055
            this.organization = organization;
1056
        }
1057
        /**
1058
         * Get the distinguish name of the user
1059
         * @return the distinguish name 
1060
         */
1061
        public String getDN() {
1062
            return this.dn;
1063
        }
1064
        
1065
        /**
1066
         * Set the distinguish name for the user
1067
         * @param dn the specified dn
1068
         */
1069
        public void setDN(String dn) {
1070
            this.dn = dn;
1071
        }
1072
        
1073
        /**
1074
         * Get the plain password for the user. This value will NOT be serialized to
1075
         * the password file
1076
         * @return the plain password for the user
1077
         */
1078
        public String getPlainPass() {
1079
            return plainPass;
1080
        }
1081
        
1082
        /**
1083
         * Set the plain password for the user.
1084
         * @param plainPass the plain password will be set.
1085
         */
1086
        public void setPlainPass(String plainPass) {
1087
            this.plainPass = plainPass;
1088
        }
1089
        
1090
        /**
1091
         * Get the hashed password of the user
1092
         * @return the hashed password of the user
1093
         */
1094
        public String getHashedPass() {
1095
            return hashedPass;
1096
        }
1097
        
1098
        /**
1099
         * Set the hashed the password for the user.
1100
         * @param hashedPass the hashed password will be set.
1101
         */
1102
        public void setHashedPass(String hashedPass) {
1103
            this.hashedPass = hashedPass;
1104
        }
1105
        
1106
        /**
1107
         * Get the email of the user
1108
         * @return the email of the user
1109
         */
1110
        public String getEmail() {
1111
            return email;
1112
        }
1113
        
1114
        /**
1115
         * Set the email address for the user
1116
         * @param email the eamil address will be set
1117
         */
1118
        public void setEmail(String email) {
1119
            this.email = email;
1120
        }
1121
        
1122
        /**
1123
         * Get the surname of the user
1124
         * @return the surname of the user
1125
         */
1126
        public String getSurName() {
1127
            return surName;
1128
        }
1129
        
1130
        /**
1131
         * Set the surname of the user
1132
         * @param surName
1133
         */
1134
        public void setSurName(String surName) {
1135
            this.surName = surName;
1136
        }
1137
        
1138
        /**
1139
         * Get the given name of the user
1140
         * @return the given name of the user
1141
         */
1142
        public String getGivenName() {
1143
            return givenName;
1144
        }
1145
        
1146
        /**
1147
         * Set the GivenName of the user
1148
         * @param givenName
1149
         */
1150
        public void setGivenName(String givenName) {
1151
            this.givenName = givenName;
1152
        }
1153
        
1154
        /**
1155
         * Get the common name of the user. If the cn is null, the GivenName +SurName will
1156
         * be returned
1157
         * @return the common name
1158
         */
1159
        public String getCn() {
1160
            if(cn != null) {
1161
                return cn;
1162
            } else {
1163
                if (givenName != null && surName != null) {
1164
                    return givenName+" "+surName;
1165
                } else if (givenName != null) {
1166
                    return givenName;
1167
                } else if (surName != null ) {
1168
                    return surName;
1169
                } else {
1170
                    return null;
1171
                }
1172
            }
1173
        }
1174
        
1175
        /**
1176
         * Set the common name for the user
1177
         * @param cn
1178
         */
1179
        public void setCn(String cn) {
1180
            this.cn = cn;
1181
        }
1182
        
1183
        /**
1184
         * Get the groups of the user belong to
1185
         * @return
1186
         */
1187
        public String[] getGroups() {
1188
            return groups;
1189
        }
1190
        
1191
        /**
1192
         * Set the groups of the user belong to
1193
         * @param groups
1194
         */
1195
        public void setGroups(String[] groups) {
1196
            this.groups = groups;
1197
        }
1198
        
1199
        /**
1200
         * Add the user to a group and serialize the change to the password file.
1201
         * @param group the group which the user will join
1202
         * @throws AuthenticationException 
1203
         */
1204
        public void addToGroup(String group) throws AuthenticationException {
1205
            if(group == null || group.trim().equals("")) {
1206
                throw new IllegalArgumentException("AuthFile.User.addToGroup - the group can't be null or blank");
1207
            }
1208
            if(!userExists(dn)) {
1209
                throw new AuthenticationException("AuthFile.User.addUserToGroup - the user "+dn+ " doesn't exist.");
1210
            }
1211
            if(!groupExists(group)) {
1212
                throw new AuthenticationException("AuthFile.User.addUserToGroup - the group "+group+ " doesn't exist.");
1213
            }
1214
            List<Object> existingGroups = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+MEMBEROF);
1215
            if(existingGroups != null && existingGroups.contains(group)) {
1216
                throw new AuthenticationException("AuthFile.User.addUserToGroup - the user "+dn+ " already is the memember of the group "+group);
1217
            }
1218
            userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+MEMBEROF, group);
1219
            //add information to the memory
1220
            if(groups == null) {
1221
                if(existingGroups == null || existingGroups.isEmpty()) {
1222
                    groups = new String[1];
1223
                    groups[0] = group;
1224
                } else {
1225
                    groups = new String[existingGroups.size()+1];
1226
                    for(int i=0; i<existingGroups.size(); i++) {
1227
                        groups[i] = (String)existingGroups.get(i);
1228
                    }
1229
                    groups[existingGroups.size()] = group;
1230
                }
1231
                
1232
            } else {
1233
                String[] oldGroups = groups;
1234
                groups = new String[oldGroups.length+1];
1235
                for(int i=0; i<oldGroups.length; i++) {
1236
                    groups[i]= oldGroups[i];
1237
                }
1238
                groups[oldGroups.length] = group;
1239
                
1240
            }
1241
        }
1242
        
1243
        /**
1244
         * Remove the user from a group and serialize the change to the password file
1245
         * @param group
1246
         * @throws AuthenticationException
1247
         */
1248
        public void removeFromGroup(String group) throws AuthenticationException {
1249
            if(!userExists(dn)) {
1250
                throw new AuthenticationException("AuthFile.User.removeUserFromGroup - the user "+dn+ " doesn't exist.");
1251
            }
1252
            if(!groupExists(group)) {
1253
                throw new AuthenticationException("AuthFile.User.removeUserFromGroup - the group "+group+ " doesn't exist.");
1254
            }
1255
            String key = USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+MEMBEROF;
1256
            List<Object> existingGroups = userpassword.getList(key);
1257
            if(!existingGroups.contains(group)) {
1258
                throw new AuthenticationException("AuthFile.User.removeUserFromGroup - the user "+dn+ " isn't the memember of the group "+group);
1259
            } else {
1260
                userpassword.clearProperty(key+"[.='"+group+"']");
1261
            }
1262
            //change the value in the memory.
1263
            if(groups != null) {
1264
                boolean contains = false;
1265
                for(int i=0; i<groups.length; i++) {
1266
                    if(groups[i].equals(group)) {
1267
                        contains = true;
1268
                        break;
1269
                    }
1270
                }
1271
                String[] newGroups = new String[groups.length-1];
1272
                int k =0;
1273
                for(int i=0; i<groups.length; i++) {
1274
                    if(!groups[i].equals(group)) {
1275
                       newGroups[k] = groups[i];
1276
                       k++;
1277
                    }
1278
                }
1279
                groups = newGroups;
1280
            }
1281
        }
1282
        
1283
        /**
1284
         * Modify the hash password and serialize it to the password file
1285
         * @param hashPass
1286
         * @throws AuthenticationException
1287
         */
1288
        public void modifyHashPass(String hashPass) throws AuthenticationException {
1289
            if(hashPass == null || hashPass.trim().equals("")) {
1290
                throw new AuthenticationException("AuthFile.User.modifyHashPass - can't change the password to the null or blank.");
1291
            }
1292
            if(!userExists(dn)) {
1293
                throw new AuthenticationException("AuthFile.User.modifyHashPass - can't change the password for the user "+dn+" since it doesn't eixt.");
1294
            }
1295
            userpassword.setProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+PASSWORD, hashPass);
1296
            setHashedPass(hashPass);
1297
      
1298
        }
1299
        
1300
        /**
1301
         * Modify the plain password and serialize its hash version to the password file
1302
         * @param plainPass
1303
         * @throws AuthenticationException 
1304
         */
1305
        public void modifyPlainPass(String plainPass) throws AuthenticationException {
1306
            if(plainPass == null || plainPass.trim().equals("")) {
1307
                throw new AuthenticationException("AuthFile.User.modifyPlainPass - can't change the password to the null or blank.");
1308
            }
1309
            if(!userExists(dn)) {
1310
                throw new AuthenticationException("AuthFile.User.modifyPlainPass - can't change the password for the user "+dn+" since it doesn't eixt.");
1311
            }
1312
            String hashPassword = null;
1313
            try {
1314
                hashPassword = encrypt(plainPass);
1315
            } catch (Exception e) {
1316
                throw new AuthenticationException("AuthFile.User.modifyPlainPass - can't encript the password since "+e.getMessage());
1317
            }
1318
            userpassword.setProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+PASSWORD, hashPassword);
1319
            setPlainPass(plainPass);
1320
        }
1321
        
1322
        /**
1323
         * Add the user to the password file. 
1324
         */
1325
        public void serialize() throws AuthenticationException {
1326
            if(dn == null || dn.trim().equals("")) {
1327
                throw new AuthenticationException("AuthFile.User.serialize - can't add a user whose name is null or blank.");
1328
            }
1329
            if(hashedPass == null || hashedPass.trim().equals("")) {
1330
                if(plainPass == null || plainPass.trim().equals("")) {
1331
                    throw new AuthenticationException("AuthFile.User.serialize - can't add a user whose password is null or blank.");
1332
                } else {
1333
                    try {
1334
                        hashedPass = encrypt(plainPass);
1335
                    } catch (Exception e) {
1336
                        throw new AuthenticationException("AuthFile.User.serialize - can't encript the password since "+e.getMessage());
1337
                    }
1338
                }
1339
            }
1340
            if(groups != null) {
1341
                for(int i=0; i<groups.length; i++) {
1342
                    String group = groups[i];
1343
                    if(group != null && !group.trim().equals("")) {
1344
                        if(!groupExists(group)) {
1345
                            throw new AuthenticationException("AuthFile.User.serialize - can't put the user into a non-existing group "+group);
1346
                        }
1347
                    }
1348
                }
1349
            }
1350

    
1351
            if(!userExists(dn)) {
1352
                if(userpassword != null) {
1353
                  userpassword.addProperty(USERS+" "+USER+AT+DN, dn);
1354
                  userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+PASSWORD, hashedPass);
1355
                  
1356
                  if(email != null && !email.trim().equals("")) {
1357
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+EMAIL, email);
1358
                  }
1359
                  
1360
                  if(surName != null && !surName.trim().equals("")) {
1361
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+SURNAME, surName);
1362
                  }
1363
                  
1364
                  if(givenName != null && !givenName.trim().equals("")) {
1365
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+GIVENNAME, givenName);
1366
                  }
1367
                  
1368
                  if(organization != null && !organization.trim().equals("")) {
1369
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+ORGANIZATION, organization);
1370
                  }
1371

    
1372
                  if(groups != null) {
1373
                      for(int i=0; i<groups.length; i++) {
1374
                          String group = groups[i];
1375
                          if(group != null && !group.trim().equals("")) {
1376
                              if(groupExists(group)) {
1377
                                  userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+MEMBEROF, group);
1378
                              }
1379
                          }
1380
                      }
1381
                  }
1382
                  //userpassword.reload();
1383
                 }
1384
            } else {
1385
                throw new AuthenticationException("AuthFile.User.serialize - can't add the user "+dn+" since it already exists.");
1386
            }
1387
        }
1388
    }
1389

    
1390
}
(1-1/4)