Project

General

Profile

« Previous | Next » 

Revision 8465

Added by Jing Tao almost 11 years ago

Change the code to use BCryptHash to protect password.

View differences:

src/edu/ucsb/nceas/metacat/authentication/AuthFile.java
60 60
 *<?xml version="1.0" encoding="UTF-8" ?>
61 61
 * <subjects>
62 62
 *  <users>
63
 *      <user name="uid=tao,o=NCEAS,dc=ecoinformatics,dc=org">
63
 *      <user dn="uid=tao,o=NCEAS,dc=ecoinformatics,dc=org">
64 64
 *          <password>*******</password>
65
 *          <email>foo@foo.com</email>
66
 *          <surName>Smith</surName>
67
 *          <givenName>John</givenName>
65 68
 *          <group>nceas-dev</group>
66 69
 *      </user>
67 70
 *  </users>
68 71
 *  <groups>
69
 *    <group name="nceas-dev"/>
72
 *    <group name="nceas-dev">
73
 *        <description>developers at NCEAS</description>
74
 *    </group>
70 75
 *  </groups>
71 76
 * </subjects>
72 77
 * http://commons.apache.org/proper/commons-configuration/userguide/howto_xml.html
......
76 81
public class AuthFile implements AuthInterface {
77 82
    private static final String ORGANIZATION = "UNkown";
78 83
    private static final String NAME = "name";
79
    private static final String UID = "uid";
84
    private static final String DN = "dn";
80 85
    private static final String DESCRIPTION = "description";
81 86
    private static final String PASSWORD = "password";
82 87
    private static final String SLASH = "/";
......
86 91
    private static final String USER = "user";
87 92
    private static final String GROUPS = "groups";
88 93
    private static final String GROUP = "group";
94
    private static final String EMAIL = "email";
95
    private static final String SURNAME = "surName";
96
    private static final String GIVENNAME = "givenName";
89 97
    private static final String INITCONTENT = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"+
90 98
                                    "<"+SUBJECTS+">\n"+"<"+USERS+">\n"+"</"+USERS+">\n"+"<"+GROUPS+">\n"+"</"+GROUPS+">\n"+"</"+SUBJECTS+">\n";
91 99
    
......
95 103
    };
96 104
    private static Log log = LogFactory.getLog(AuthFile.class);
97 105
    private static AuthFile authFile = null;
98
    private XMLConfiguration userpassword = null;
106
    private static XMLConfiguration userpassword = null;
99 107
    private String authURI = null;
100 108
    private static String passwordFilePath = null;
101
    private static  char[] masterPass = "enfldsgbnlsngdlksdsgm".toCharArray();
109
    private static AuthFileHashInterface hashClass = null;
102 110
    /**
103 111
     * Get the instance of the AuthFile
104 112
     * @return
......
139 147
    /*
140 148
     * Initialize the user/password configuration
141 149
     */
142
    private void init() throws PropertyNotFoundException, IOException, ConfigurationException {
150
    private void init() throws PropertyNotFoundException, IOException, ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException {
143 151
        if(passwordFilePath == null) {
144 152
            passwordFilePath  = PropertyService.getProperty("auth.file.path");
145 153
        }
146 154
        File passwordFile = new File(passwordFilePath);
147
        try {
148
            String password = PropertyService.getProperty("auth.file.pass");
149
            if(password != null && !password.trim().equals("")) {
150
                masterPass = password.toCharArray();
151
            }
152
            authURI = SystemUtil.getContextURL();
153
        }catch(PropertyNotFoundException e) {
154
            log.warn("AuthFile.init - can't find the auth.file.pass in the metacat.properties. Metacat will use the default one as password.");
155
        }
156
       
155
        
156
        authURI = SystemUtil.getContextURL();
157
        String hashClassName = PropertyService.getProperty("auth.file.hashClassName");
158
        Class classDefinition = Class.forName(hashClassName);
159
        Object object = classDefinition.newInstance();
160
        hashClass = (AuthFileHashInterface) object;
161
        
157 162
        //if the password file doesn't exist, create a new one and set the initial content
158 163
        if(!passwordFile.exists()) {
159 164
            passwordFile.createNewFile();
......
178 183
    @Override
179 184
    public boolean authenticate(String user, String password)
180 185
                    throws AuthenticationException {
181
        String passwordRecord = userpassword.getString(USERS+SLASH+USER+"["+AT+UID+"='"+user+"']"+SLASH+PASSWORD);
186
        boolean match = false;
187
        String passwordRecord = userpassword.getString(USERS+SLASH+USER+"["+AT+DN+"='"+user+"']"+SLASH+PASSWORD);
182 188
        if(passwordRecord != null) {
183 189
            try {
184
                passwordRecord = decrypt(passwordRecord);
190
                match = hashClass.match(password, passwordRecord);
185 191
            } catch (Exception e) {
186
                throw new AuthenticationException("AuthFile.authenticate - can't decrypt the password for the user "+user+" since "+e.getMessage());
192
                throw new AuthenticationException(e.getMessage());
187 193
            }
188
            if(passwordRecord.equals(password)) {
189
                return true;
190
            }
194
            
191 195
        }
192
        return false;
196
        return match;
193 197
    }
194 198
    
195 199
    @Override
......
199 203
     */
200 204
    public String[][] getUsers(String user, String password)
201 205
                    throws ConnectException {
202
        List<Object> users = userpassword.getList(USERS+SLASH+USER+SLASH+AT+UID);
206
        List<Object> users = userpassword.getList(USERS+SLASH+USER+SLASH+AT+DN);
203 207
        if(users != null && users.size() > 0) {
204 208
            String[][] usersArray = new String[users.size()][1];
205 209
            for(int i=0; i<users.size(); i++) {
......
232 236
     */
233 237
    public String[] getUsers(String user, String password, String group)
234 238
                    throws ConnectException {
235
        List<Object> users = userpassword.getList(USERS+SLASH+USER+"["+GROUP+"='"+group+"']"+SLASH+AT+UID);
239
        List<Object> users = userpassword.getList(USERS+SLASH+USER+"["+GROUP+"='"+group+"']"+SLASH+AT+DN);
236 240
        if(users != null && users.size() > 0) {
237 241
            String[] usersArray = new String[users.size()];
238 242
            for(int i=0; i<users.size(); i++) {
......
268 272
     */
269 273
    public String[][] getGroups(String user, String password, String foruser)
270 274
                    throws ConnectException {
271
        List<Object> groups = userpassword.getList(USERS+SLASH+USER+"["+AT+UID+"='"+foruser+"']"+SLASH+GROUP);
275
        List<Object> groups = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+foruser+"']"+SLASH+GROUP);
272 276
        if(groups != null && groups.size() > 0) {
273 277
            String[][] groupsArray = new String[groups.size()][1];
274 278
            for(int i=0; i<groups.size(); i++) {
......
375 379
     * @param groups  the groups the user belong to. The group should exist in the file
376 380
     * @param password  the password of the user
377 381
     */
378
    public void addUser(String userName, String[] groups, String password) throws AuthenticationException{
379
        if(userName == null || userName.trim().equals("")) {
380
            throw new AuthenticationException("AuthFile.addUser - can't add a user whose name is null or blank.");
381
        }
382
        if(password == null || password.trim().equals("")) {
383
            throw new AuthenticationException("AuthFile.addUser - can't add a user whose password is null or blank.");
384
        }
385
        try {
386
            password = encrypt(password);
387
        } catch (Exception e) {
388
            throw new AuthenticationException("AuthFile.addUser - can't encript the password since "+e.getMessage());
389
        }
390
        
391
        if(!userExists(userName)) {
392
            if(userpassword != null) {
393
              userpassword.addProperty(USERS+" "+USER+AT+UID, userName);
394
              userpassword.addProperty(USERS+SLASH+USER+"["+AT+UID+"='"+userName+"']"+" "+PASSWORD, password);
395
              if(groups != null) {
396
                  for(int i=0; i<groups.length; i++) {
397
                      String group = groups[i];
398
                      if(group != null && !group.trim().equals("")) {
399
                          if(groupExists(group)) {
400
                              userpassword.addProperty(USERS+SLASH+USER+"["+AT+UID+"='"+userName+"']"+" "+GROUP, group);
401
                          }
402
                      }
403
                  }
404
              }
405
              //userpassword.reload();
406
             }
407
        } else {
408
            throw new AuthenticationException("AuthFile.addUser - can't add the user "+userName+" since it already exists.");
409
        }
382
    public void addUser(String dn, String[] groups, String plainPass, String hashedPass, String email, String surName, String givenName) throws AuthenticationException{
383
       User user = new User();
384
       user.setDN(dn);
385
       user.setGroups(groups);
386
       user.setEmail(email);
387
       user.setSurName(surName);
388
       user.setGivenName(givenName);
389
       user.serialize();
410 390
    }
411 391
    
412 392
    /**
......
430 410
        }
431 411
    }
432 412
    
413
   
414
    
433 415
    /**
434
     * Reset the password for the user
435
     * @param userName  the name of the user. The user should already exist
436
     * @param password  the password of the user.
437
     * @return
416
     * Change the password of the user to the new one which is hashed
417
     * @param usrName the specified user.   
418
     * @param newPassword the new password which will be set
438 419
     */
439
    public String resetPassword(String userName) throws AuthenticationException {
440
        String password = new String(RandomPasswordGenerator.generatePswd(10, 12, 4, 3, 2));
441
        changePassword(userName, password);
442
        return password;
420
    public void modifyPassWithHash(String userName, String newHashPassword) throws AuthenticationException {
421
       User user = new User();
422
       user.setDN(userName);
423
       user.modifyHashPass(newHashPassword);
443 424
    }
444 425
    
445 426
    /**
446
     * Change the password of the user to the new one. But we need to know the old password
427
     * Change the password of the user to the new one which is plain. However, only the hashed version will be serialized.
447 428
     * @param usrName the specified user.   
448
     * @param oldPassword the old password of the user      
449 429
     * @param newPassword the new password which will be set
450 430
     */
451
    public void modifyPassword(String userName, String oldPassword, String newPassword) throws AuthenticationException {
452
        if(!authenticate(userName, oldPassword)) {
453
            throw new AuthenticationException("AuthFile.modifyUserPassword - the username or the old password is not correct");
454
        }
455
        changePassword(userName, newPassword);
431
    public void modifyPassWithPlain(String userName, String newPlainPassword) throws AuthenticationException {
432
        User user = new User();
433
        user.setDN(userName);
434
        user.modifyPlainPass(newPlainPassword);
456 435
    }
457 436
    
437
    
458 438
    /**
459 439
     * Add a user to a group
460 440
     * @param userName  the name of the user. the user should already exist
461 441
     * @param group  the name of the group. the group should already exist
462 442
     */
463 443
    public void addUserToGroup(String userName, String group) throws AuthenticationException {
464
        if(!userExists(userName)) {
465
            throw new AuthenticationException("AuthFile.addUserToGroup - the user "+userName+ " doesn't exist.");
466
        }
467
        if(!groupExists(group)) {
468
            throw new AuthenticationException("AuthFile.addUserToGroup - the group "+group+ " doesn't exist.");
469
        }
470
        List<Object> existingGroups = userpassword.getList(USERS+SLASH+USER+"["+AT+UID+"='"+userName+"']"+SLASH+GROUP);
471
        if(existingGroups.contains(group)) {
472
            throw new AuthenticationException("AuthFile.addUserToGroup - the user "+userName+ " already is the memember of the group "+group);
473
        }
474
        userpassword.addProperty(USERS+SLASH+USER+"["+AT+UID+"='"+userName+"']"+" "+GROUP, group);
444
        User user = new User();
445
        user.setDN(userName);
446
        user.addToGroup(group);
475 447
    }
476 448
    
477 449
    /**
......
480 452
     * @param group the name of the group
481 453
     */
482 454
    public void removeUserFromGroup(String userName, String group) throws AuthenticationException{
483
        if(!userExists(userName)) {
484
            throw new AuthenticationException("AuthFile.removeUserFromGroup - the user "+userName+ " doesn't exist.");
485
        }
486
        if(!groupExists(group)) {
487
            throw new AuthenticationException("AuthFile.removeUserFromGroup - the group "+group+ " doesn't exist.");
488
        }
489
        String key = USERS+SLASH+USER+"["+AT+UID+"='"+userName+"']"+SLASH+GROUP;
490
        List<Object> existingGroups = userpassword.getList(key);
491
        if(!existingGroups.contains(group)) {
492
            throw new AuthenticationException("AuthFile.removeUserFromGroup - the user "+userName+ " isn't the memember of the group "+group);
493
        } else {
494
            userpassword.clearProperty(key+"[.='"+group+"']");
495
        }
455
        User user = new User();
456
        user.setDN(userName);
457
        user.removeFromGroup(group);
496 458
    }
497 459
    
498
    /**
499
     * Change the password of the user to the specified one
500
     * @param userName
501
     * @param password
502
     */
503
    private void changePassword(String userName, String password) throws AuthenticationException{
504
        if(!userExists(userName)) {
505
            throw new AuthenticationException("AuthFile.changePassword - can't change the password for the user "+userName+" since it doesn't eixt.");
506
        }
507
        String encryped = null;
508
        try {
509
            encryped = encrypt(password);
510
        } catch (Exception e) {
511
            throw new AuthenticationException("AuthFile.changepassword - can't encrype the new password for the user "+userName+" since "+e.getMessage());
512
        }
513
        userpassword.setProperty(USERS+SLASH+USER+"["+AT+UID+"='"+userName+"']"+SLASH+PASSWORD, encryped);
514
    }
460
  
515 461
    
516 462
    /**
517 463
     * If the specified user name exist or not
518 464
     * @param userName the name of the user
519 465
     * @return true if the user eixsit
520 466
     */
521
    private boolean userExists(String userName) throws AuthenticationException{
467
    private synchronized boolean userExists(String userName) throws AuthenticationException{
522 468
        if(userName == null || userName.trim().equals("")) {
523 469
            throw new AuthenticationException("AuthFile.userExist - can't judge if a user exists when its name is null or blank.");
524 470
        }
525
        List<Object> users = userpassword.getList(USERS+SLASH+USER+SLASH+AT+UID);
471
        List<Object> users = userpassword.getList(USERS+SLASH+USER+SLASH+AT+DN);
526 472
        if(users != null && users.contains(userName)) {
527 473
            return true;
528 474
        } else {
......
535 481
     * @param groupName the name of the group
536 482
     * @return true if the user exists
537 483
     */
538
    private boolean groupExists(String groupName) throws AuthenticationException{
484
    private synchronized boolean groupExists(String groupName) throws AuthenticationException{
539 485
        if(groupName == null || groupName.trim().equals("")) {
540 486
            throw new AuthenticationException("AuthFile.groupExist - can't judge if a group exists when its name is null or blank.");
541 487
        }
......
548 494
    }
549 495
    
550 496
    /*
551
     * Encrypt a string
497
     * Encrypt a plain text
552 498
     */
553
    private static String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
554
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
555
        //System.out.println("===================== tha master password "+masterPass);
556
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(masterPass));
557
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
558
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
559
        return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8")));
499
    private static String encrypt(String plain)  {
500
      return hashClass.hash(plain);
560 501
    }
502
    
561 503

  
562
    /*
563
     * Transform a byte array to a string
564
     */
565
    private static String base64Encode(byte[] bytes) {
566
        return Base64.encodeBase64String(bytes);
567
    }
568

  
569
    /*
570
     * Decrypt a string
571
     */
572
    private static String decrypt(String property) throws GeneralSecurityException, IOException {
573
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
574
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(masterPass));
575
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
576
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
577
        return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
578
    }
579

  
580
    /*
581
     * Transform a string to a byte array
582
     */
583
    private static byte[] base64Decode(String property) throws IOException {
584
        return Base64.decodeBase64(property);
585
    }
586 504
    
587 505
    /**
588
     * A internal class to generate random passowrd
506
     * An class represents the information for a user. 
589 507
     * @author tao
590 508
     *
591 509
     */
592
    static class RandomPasswordGenerator {
593
        private static final String ALPHA_CAPS  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
594
        private static final String ALPHA   = "abcdefghijklmnopqrstuvwxyz";
595
        private static final String NUM     = "0123456789";
596
        private static final String SPL_CHARS   = "!$^_-/";
597
     
598
        public static char[] generatePswd(int minLen, int maxLen, int noOfCAPSAlpha,
599
                int noOfDigits, int noOfSplChars) {
600
            if(minLen > maxLen)
601
                throw new IllegalArgumentException("Min. Length > Max. Length!");
602
            if( (noOfCAPSAlpha + noOfDigits + noOfSplChars) > minLen )
603
                throw new IllegalArgumentException
604
                ("Min. Length should be atleast sum of (CAPS, DIGITS, SPL CHARS) Length!");
605
            Random rnd = new Random();
606
            int len = rnd.nextInt(maxLen - minLen + 1) + minLen;
607
            char[] pswd = new char[len];
608
            int index = 0;
609
            for (int i = 0; i < noOfCAPSAlpha; i++) {
610
                index = getNextIndex(rnd, len, pswd);
611
                pswd[index] = ALPHA_CAPS.charAt(rnd.nextInt(ALPHA_CAPS.length()));
510
    private class User {
511
        private String dn = null;//the distinguish name
512
        private String plainPass = null;
513
        private String hashedPass = null;
514
        private String email = null;
515
        private String surName = null;
516
        private String givenName = null;
517
        private String cn = null;//the common name
518
        private String[] groups = null;
519
        
520
        /**
521
         * Get the distinguish name of the user
522
         * @return the distinguish name 
523
         */
524
        public String getDN() {
525
            return this.dn;
526
        }
527
        
528
        /**
529
         * Set the distinguish name for the user
530
         * @param dn the specified dn
531
         */
532
        public void setDN(String dn) {
533
            this.dn = dn;
534
        }
535
        
536
        /**
537
         * Get the plain password for the user. This value will NOT be serialized to
538
         * the password file
539
         * @return the plain password for the user
540
         */
541
        public String getPlainPass() {
542
            return plainPass;
543
        }
544
        
545
        /**
546
         * Set the plain password for the user.
547
         * @param plainPass the plain password will be set.
548
         */
549
        public void setPlainPass(String plainPass) {
550
            this.plainPass = plainPass;
551
        }
552
        
553
        /**
554
         * Get the hashed password of the user
555
         * @return the hashed password of the user
556
         */
557
        public String getHashedPass() {
558
            return hashedPass;
559
        }
560
        
561
        /**
562
         * Set the hashed the password for the user.
563
         * @param hashedPass the hashed password will be set.
564
         */
565
        public void setHashedPass(String hashedPass) {
566
            this.hashedPass = hashedPass;
567
        }
568
        
569
        /**
570
         * Get the email of the user
571
         * @return the email of the user
572
         */
573
        public String getEmail() {
574
            return email;
575
        }
576
        
577
        /**
578
         * Set the email address for the user
579
         * @param email the eamil address will be set
580
         */
581
        public void setEmail(String email) {
582
            this.email = email;
583
        }
584
        
585
        /**
586
         * Get the surname of the user
587
         * @return the surname of the user
588
         */
589
        public String getSurName() {
590
            return surName;
591
        }
592
        
593
        /**
594
         * Set the surname of the user
595
         * @param surName
596
         */
597
        public void setSurName(String surName) {
598
            this.surName = surName;
599
        }
600
        
601
        /**
602
         * Get the given name of the user
603
         * @return the given name of the user
604
         */
605
        public String getGivenName() {
606
            return givenName;
607
        }
608
        
609
        /**
610
         * Set the GivenName of the user
611
         * @param givenName
612
         */
613
        public void setGivenName(String givenName) {
614
            this.givenName = givenName;
615
        }
616
        
617
        /**
618
         * Get the common name of the user. If the cn is null, the GivenName +SurName will
619
         * be returned
620
         * @return the common name
621
         */
622
        public String getCn() {
623
            if(cn != null) {
624
                return cn;
625
            } else {
626
                if (givenName != null && surName != null) {
627
                    return givenName+" "+surName;
628
                } else if (givenName != null) {
629
                    return givenName;
630
                } else if (surName != null ) {
631
                    return surName;
632
                } else {
633
                    return null;
634
                }
612 635
            }
613
            for (int i = 0; i < noOfDigits; i++) {
614
                index = getNextIndex(rnd, len, pswd);
615
                pswd[index] = NUM.charAt(rnd.nextInt(NUM.length()));
636
        }
637
        
638
        /**
639
         * Set the common name for the user
640
         * @param cn
641
         */
642
        public void setCn(String cn) {
643
            this.cn = cn;
644
        }
645
        
646
        /**
647
         * Get the groups of the user belong to
648
         * @return
649
         */
650
        public String[] getGroups() {
651
            return groups;
652
        }
653
        
654
        /**
655
         * Set the groups of the user belong to
656
         * @param groups
657
         */
658
        public void setGroups(String[] groups) {
659
            this.groups = groups;
660
        }
661
        
662
        /**
663
         * Add the user to a group and serialize the change to the password file.
664
         * @param group the group which the user will join
665
         * @throws AuthenticationException 
666
         */
667
        public void addToGroup(String group) throws AuthenticationException {
668
            if(group == null || group.trim().equals("")) {
669
                throw new IllegalArgumentException("AuthFile.User.addGroup - the group can't be null or blank");
616 670
            }
617
            for (int i = 0; i < noOfSplChars; i++) {
618
                index = getNextIndex(rnd, len, pswd);
619
                pswd[index] = SPL_CHARS.charAt(rnd.nextInt(SPL_CHARS.length()));
671
            if(!userExists(dn)) {
672
                throw new AuthenticationException("AuthFile.addUserToGroup - the user "+dn+ " doesn't exist.");
620 673
            }
621
            for(int i = 0; i < len; i++) {
622
                if(pswd[i] == 0) {
623
                    pswd[i] = ALPHA.charAt(rnd.nextInt(ALPHA.length()));
674
            if(!groupExists(group)) {
675
                throw new AuthenticationException("AuthFile.addUserToGroup - the group "+group+ " doesn't exist.");
676
            }
677
            List<Object> existingGroups = userpassword.getList(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+GROUP);
678
            if(existingGroups != null && existingGroups.contains(group)) {
679
                throw new AuthenticationException("AuthFile.addUserToGroup - the user "+dn+ " already is the memember of the group "+group);
680
            }
681
            userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+GROUP, group);
682
            //add information to the memory
683
            if(groups == null) {
684
                if(existingGroups == null || existingGroups.isEmpty()) {
685
                    groups = new String[1];
686
                    groups[0] = group;
687
                } else {
688
                    groups = new String[existingGroups.size()+1];
689
                    for(int i=0; i<existingGroups.size(); i++) {
690
                        groups[i] = (String)existingGroups.get(i);
691
                    }
692
                    groups[existingGroups.size()] = group;
624 693
                }
694
                
695
            } else {
696
                String[] oldGroups = groups;
697
                groups = new String[oldGroups.length+1];
698
                for(int i=0; i<oldGroups.length; i++) {
699
                    groups[i]= oldGroups[i];
700
                }
701
                groups[oldGroups.length] = group;
702
                
625 703
            }
626
            return pswd;
627 704
        }
628
     
629
        private static int getNextIndex(Random rnd, int len, char[] pswd) {
630
            int index = rnd.nextInt(len);
631
            while(pswd[index = rnd.nextInt(len)] != 0);
632
            return index;
705
        
706
        /**
707
         * Remove the user from a group and serialize the change to the password file
708
         * @param group
709
         * @throws AuthenticationException
710
         */
711
        public void removeFromGroup(String group) throws AuthenticationException {
712
            if(!userExists(dn)) {
713
                throw new AuthenticationException("AuthFile.removeUserFromGroup - the user "+dn+ " doesn't exist.");
714
            }
715
            if(!groupExists(group)) {
716
                throw new AuthenticationException("AuthFile.removeUserFromGroup - the group "+group+ " doesn't exist.");
717
            }
718
            String key = USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+GROUP;
719
            List<Object> existingGroups = userpassword.getList(key);
720
            if(!existingGroups.contains(group)) {
721
                throw new AuthenticationException("AuthFile.removeUserFromGroup - the user "+dn+ " isn't the memember of the group "+group);
722
            } else {
723
                userpassword.clearProperty(key+"[.='"+group+"']");
724
            }
725
            //change the value in the memory.
726
            if(groups != null) {
727
                boolean contains = false;
728
                for(int i=0; i<groups.length; i++) {
729
                    if(groups[i].equals(group)) {
730
                        contains = true;
731
                        break;
732
                    }
733
                }
734
                String[] newGroups = new String[groups.length-1];
735
                int k =0;
736
                for(int i=0; i<groups.length; i++) {
737
                    if(!groups[i].equals(group)) {
738
                       newGroups[k] = groups[i];
739
                       k++;
740
                    }
741
                }
742
                groups = newGroups;
743
            }
633 744
        }
745
        
746
        /**
747
         * Modify the hash password and serialize it to the password file
748
         * @param hashPass
749
         * @throws AuthenticationException
750
         */
751
        public void modifyHashPass(String hashPass) throws AuthenticationException {
752
            if(hashPass == null || hashPass.trim().equals("")) {
753
                throw new AuthenticationException("AuthFile.User.modifyHashPass - can't change the password to the null or blank.");
754
            }
755
            if(!userExists(dn)) {
756
                throw new AuthenticationException("AuthFile.modifyHashPass - can't change the password for the user "+dn+" since it doesn't eixt.");
757
            }
758
            userpassword.setProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+PASSWORD, hashPass);
759
            setHashedPass(hashPass);
760
      
761
        }
762
        
763
        /**
764
         * Modify the plain password and serialize its hash version to the password file
765
         * @param plainPass
766
         * @throws AuthenticationException 
767
         */
768
        public void modifyPlainPass(String plainPass) throws AuthenticationException {
769
            if(plainPass == null || plainPass.trim().equals("")) {
770
                throw new AuthenticationException("AuthFile.User.modifyPlainPass - can't change the password to the null or blank.");
771
            }
772
            if(!userExists(dn)) {
773
                throw new AuthenticationException("AuthFile.modifyPlainPass - can't change the password for the user "+dn+" since it doesn't eixt.");
774
            }
775
            String hashPassword = null;
776
            try {
777
                hashPassword = encrypt(plainPass);
778
            } catch (Exception e) {
779
                throw new AuthenticationException("AuthFile.addUser - can't encript the password since "+e.getMessage());
780
            }
781
            userpassword.setProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+SLASH+PASSWORD, hashPassword);
782
            setPlainPass(plainPass);
783
        }
784
        
785
        /**
786
         * Add the user to the password file. 
787
         */
788
        public void serialize() throws AuthenticationException {
789
            if(dn == null || dn.trim().equals("")) {
790
                throw new AuthenticationException("AuthFile.addUser - can't add a user whose name is null or blank.");
791
            }
792
            if(hashedPass == null || hashedPass.trim().equals("")) {
793
                if(plainPass == null || plainPass.trim().equals("")) {
794
                    throw new AuthenticationException("AuthFile.addUser - can't add a user whose password is null or blank.");
795
                } else {
796
                    try {
797
                        hashedPass = encrypt(plainPass);
798
                    } catch (Exception e) {
799
                        throw new AuthenticationException("AuthFile.addUser - can't encript the password since "+e.getMessage());
800
                    }
801
                }
802
            }
803

  
804
            if(!userExists(dn)) {
805
                if(userpassword != null) {
806
                  userpassword.addProperty(USERS+" "+USER+AT+DN, dn);
807
                  userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+PASSWORD, hashedPass);
808
                  
809
                  if(email != null && !email.trim().equals("")) {
810
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+EMAIL, email);
811
                  }
812
                  
813
                  if(surName != null && !surName.trim().equals("")) {
814
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+SURNAME, surName);
815
                  }
816
                  
817
                  if(givenName != null && !givenName.trim().equals("")) {
818
                      userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+GIVENNAME, givenName);
819
                  }
820

  
821
                  if(groups != null) {
822
                      for(int i=0; i<groups.length; i++) {
823
                          String group = groups[i];
824
                          if(group != null && !group.trim().equals("")) {
825
                              if(groupExists(group)) {
826
                                  userpassword.addProperty(USERS+SLASH+USER+"["+AT+DN+"='"+dn+"']"+" "+GROUP, group);
827
                              }
828
                          }
829
                      }
830
                  }
831
                  //userpassword.reload();
832
                 }
833
            } else {
834
                throw new AuthenticationException("AuthFile.addUser - can't add the user "+dn+" since it already exists.");
835
            }
836
        }
634 837
    }
635 838

  
636 839
}
src/edu/ucsb/nceas/metacat/authentication/AuthFileHashInterface.java
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
/**
24
 * This an interface for different hash algorithms using to protect users' password
25
 * in the username/password file 
26
 * @author tao
27
 *
28
 */
29
public interface AuthFileHashInterface {
30
    
31
    /**
32
     * Check if the plain password matches the hashed password. Return true if they match;
33
     * false otherwise.
34
     * @param plain  the plain password
35
     * @param hashed  the hashed password
36
     * @return true if they match
37
     * @throws Exception
38
     */
39
    public boolean match(String plain, String hashed) throws Exception;
40
    
41
    
42
    /**
43
     * Generate the hash value for a specified plaint password
44
     * @param plain  the plain password
45
     * @return the hash value of the password
46
     */
47
    public String hash(String plain);
48
}
src/edu/ucsb/nceas/metacat/authentication/AuthFileBCryptHash.java
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 org.mindrot.jbcrypt.BCrypt;
24

  
25

  
26
/**
27
 * A class to use the BCryptHash algorithm to generate the hash. This is a recommended way
28
 * to protect password.
29
 * @author tao
30
 *
31
 */
32
public class AuthFileBCryptHash implements AuthFileHashInterface {
33
    
34
    /**
35
     * Default Constructor
36
     */
37
    public AuthFileBCryptHash() {
38
        
39
    }
40
    
41
    @Override
42
    public boolean match(String plain, String hashed) throws Exception {
43
        if(plain == null || plain.trim().equals("")) {
44
            throw new IllegalArgumentException("AuthFileBrryptHash.match - the password parameter can't be null or blank");   
45
        }
46
        if(hashed == null || hashed.trim().equals("")) {
47
            throw new IllegalArgumentException("AuthFileBrryptHash.match - the hashed value of password parameter can't be null or blank");
48
        }
49
        return BCrypt.checkpw(plain, hashed);
50
    }
51
    
52
    @Override
53
    public String hash(String plain) {
54
        if(plain == null || plain.trim().equals("")) {
55
            throw new IllegalArgumentException("AuthFileBrryptHash.hash - the password parameter can't be null or blank");   
56
        }
57
        return BCrypt.hashpw(plain, BCrypt.gensalt());
58
    }
59
    
60
}

Also available in: Unified diff