001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.server.kerberos.sam;
021    
022    
023    import java.io.IOException;
024    
025    import javax.security.auth.kerberos.KerberosKey;
026    
027    import org.apache.directory.server.kerberos.shared.crypto.encryption.CipherTextHandler;
028    import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType;
029    import org.apache.directory.server.kerberos.shared.crypto.encryption.KeyUsage;
030    import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
031    import org.apache.directory.server.kerberos.shared.io.decoder.EncryptedDataDecoder;
032    import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
033    import org.apache.directory.server.kerberos.shared.messages.value.EncryptedTimeStamp;
034    import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
035    import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
036    
037    
038    /**
039     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040     * @version $Rev: 563062 $, $Date: 2007-08-06 10:21:20 +0200 (Mon, 06 Aug 2007) $
041     */
042    public class TimestampChecker implements KeyIntegrityChecker
043    {
044        private static final long FIVE_MINUTES = 300000;
045        private static final CipherTextHandler cipherTextHandler = new CipherTextHandler();
046    
047    
048        public boolean checkKeyIntegrity( byte[] encryptedData, KerberosKey kerberosKey )
049        {
050            EncryptionType keyType = EncryptionType.getTypeByOrdinal( kerberosKey.getKeyType() );
051            EncryptionKey key = new EncryptionKey( keyType, kerberosKey.getEncoded() );
052    
053            try
054            {
055                /*
056                 * Since the pre-auth value is of type PA-ENC-TIMESTAMP, it should be a valid
057                 * ASN.1 PA-ENC-TS-ENC structure, so we can decode it into EncryptedData.
058                 */
059                EncryptedData sadValue = EncryptedDataDecoder.decode( encryptedData );
060    
061                /*
062                 * Decrypt the EncryptedData structure to get the PA-ENC-TS-ENC.  Decode the
063                 * decrypted timestamp into our timestamp object.
064                 */
065                EncryptedTimeStamp timestamp = ( EncryptedTimeStamp ) cipherTextHandler.unseal( EncryptedTimeStamp.class,
066                    key, sadValue, KeyUsage.NUMBER1 );
067    
068                /*
069                 * Since we got here we must have a valid timestamp structure that we can
070                 * validate to be within a five minute skew.
071                 */
072                KerberosTime time = timestamp.getTimeStamp();
073    
074                if ( time.isInClockSkew( FIVE_MINUTES ) )
075                {
076                    return true;
077                }
078            }
079            catch ( IOException ioe )
080            {
081                return false;
082            }
083            catch ( KerberosException ke )
084            {
085                return false;
086            }
087            catch ( ClassCastException cce )
088            {
089                return false;
090            }
091    
092            return false;
093        }
094    }