Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 47785 invoked from network); 13 Jul 2010 18:36:05 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 13 Jul 2010 18:36:05 -0000 Received: (qmail 13218 invoked by uid 500); 13 Jul 2010 18:36:05 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 13174 invoked by uid 500); 13 Jul 2010 18:36:05 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 13167 invoked by uid 99); 13 Jul 2010 18:36:05 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Jul 2010 18:36:05 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Jul 2010 18:36:02 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 1C2A623889B3; Tue, 13 Jul 2010 18:35:08 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r963807 - /directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java Date: Tue, 13 Jul 2010 18:35:08 -0000 To: commits@directory.apache.org From: kayyagari@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100713183508.1C2A623889B3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kayyagari Date: Tue Jul 13 18:35:07 2010 New Revision: 963807 URL: http://svn.apache.org/viewvc?rev=963807&view=rev Log: o a utility class containing methods related to processing passwords Added: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java Added: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java?rev=963807&view=auto ============================================================================== --- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java (added) +++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java Tue Jul 13 18:35:07 2010 @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.directory.server.core.authn; + + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import org.apache.directory.shared.ldap.constants.LdapSecurityConstants; +import org.apache.directory.shared.ldap.entry.EntryAttribute; +import org.apache.directory.shared.ldap.entry.Value; +import org.apache.directory.shared.ldap.util.DateUtils; +import org.apache.directory.shared.ldap.util.StringTools; +import org.apache.directory.shared.ldap.util.UnixCrypt; + +/** + * A utility class containing methods related to processing passwords. + * + * @author Apache Directory Project + */ +public class PasswordUtil +{ + /** + * Get the algorithm from the stored password. + * It can be found on the beginning of the stored password, between + * curly brackets. + * @param credentials the credentials of the user + * @return the name of the algorithm to use + */ + public static LdapSecurityConstants findAlgorithm( byte[] credentials ) + { + if ( ( credentials == null ) || ( credentials.length == 0 ) ) + { + return null; + } + + if ( credentials[0] == '{' ) + { + // get the algorithm + int pos = 1; + + while ( pos < credentials.length ) + { + if ( credentials[pos] == '}' ) + { + break; + } + + pos++; + } + + if ( pos < credentials.length ) + { + if ( pos == 1 ) + { + // We don't have an algorithm : return the credentials as is + return null; + } + + String algorithm = new String( credentials, 1, pos - 1 ).toLowerCase(); + + return LdapSecurityConstants.getAlgorithm( algorithm ); + } + else + { + // We don't have an algorithm + return null; + } + } + else + { + // No '{algo}' part + return null; + } + } + + + /** + * encrypts the given credentials based on the algorithm name and optional salt + * + * @param credentials the credentials to be encrypted + * @param algorithm the algorithm to be used for encrypting the credentials + * @param salt value to be used as salt (optional) + * @return the encrypted credentials + */ + public static byte[] encryptPassword( byte[] credentials, LdapSecurityConstants algorithm, byte[] salt ) + { + switch ( algorithm ) + { + case HASH_METHOD_SHA: + case HASH_METHOD_SSHA: + return digest( LdapSecurityConstants.HASH_METHOD_SHA, credentials, salt ); + + case HASH_METHOD_SHA256: + return digest( LdapSecurityConstants.HASH_METHOD_SHA256, credentials, salt ); + + case HASH_METHOD_MD5: + case HASH_METHOD_SMD5: + return digest( LdapSecurityConstants.HASH_METHOD_MD5, credentials, salt ); + + case HASH_METHOD_CRYPT: + if ( salt == null ) + { + salt = new byte[2]; + SecureRandom sr = new SecureRandom(); + int i1 = sr.nextInt( 64 ); + int i2 = sr.nextInt( 64 ); + + salt[0] = ( byte ) ( i1 < 12 ? ( i1 + '.' ) : i1 < 38 ? ( i1 + 'A' - 12 ) : ( i1 + 'a' - 38 ) ); + salt[1] = ( byte ) ( i2 < 12 ? ( i2 + '.' ) : i2 < 38 ? ( i2 + 'A' - 12 ) : ( i2 + 'a' - 38 ) ); + } + + String saltWithCrypted = UnixCrypt.crypt( StringTools.utf8ToString( credentials ), StringTools + .utf8ToString( salt ) ); + String crypted = saltWithCrypted.substring( 2 ); + + return StringTools.getBytesUtf8( crypted ); + + default: + return credentials; + } + } + + + /** + * Compute the hashed password given an algorithm, the credentials and + * an optional salt. + * + * @param algorithm the algorithm to use + * @param password the credentials + * @param salt the optional salt + * @return the digested credentials + */ + private static byte[] digest( LdapSecurityConstants algorithm, byte[] password, byte[] salt ) + { + MessageDigest digest; + + try + { + digest = MessageDigest.getInstance( algorithm.getName() ); + } + catch ( NoSuchAlgorithmException e1 ) + { + return null; + } + + if ( salt != null ) + { + digest.update( password ); + digest.update( salt ); + return digest.digest(); + } + else + { + return digest.digest( password ); + } + } + + + /** + * checks if the given password's change time is older than the max age + * + * @param pwdChangedZtime time when the password was last changed + * @param pwdMaxAgeSec the max age value in seconds + * @return true if expired, false otherwise + */ + public static boolean isPwdExpired( String pwdChangedZtime, int pwdMaxAgeSec ) + { + Date pwdChangeDate = DateUtils.getDate( pwdChangedZtime ); + + long time = pwdMaxAgeSec * 1000; + time += pwdChangeDate.getTime(); + + Date expiryDate = new Date( time ); + Date now = new Date(); + + boolean expired = false; + + if( expiryDate.equals( now ) || expiryDate.after( now ) ) + { + expired = true; + } + + return expired; + } + + + /** + * purges failure timestamps which are older than the configured interval + * (section 7.6 in the draft) + */ + public static void purgeFailureTimes( PasswordPolicyConfiguration config, EntryAttribute pwdFailTimeAt ) + { + long interval = config.getPwdFailureCountInterval(); + + if( interval == 0 ) + { + return; + } + + Iterator> itr = pwdFailTimeAt.getAll(); + interval *= 1000; + + long currentTime = System.currentTimeMillis(); + List> valList = new ArrayList>(); + + while( itr.hasNext() ) + { + Value val = itr.next(); + String failureTime = val.getString(); + long time = DateUtils.getDate( failureTime ).getTime(); + time += interval; + + if( currentTime > time ) + { + valList.add( val ); + } + } + + for( Value val : valList ) + { + pwdFailTimeAt.remove( val ); + } + } + +}