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 */
020package org.apache.directory.kerberos.client;
021
022
023import java.nio.ByteBuffer;
024import java.util.Collections;
025import java.util.LinkedHashSet;
026import java.util.Set;
027
028import org.apache.directory.api.asn1.DecoderException;
029import org.apache.directory.api.asn1.ber.Asn1Decoder;
030import org.apache.directory.shared.kerberos.codec.etypeInfo.ETypeInfoContainer;
031import org.apache.directory.shared.kerberos.codec.etypeInfo2.ETypeInfo2Container;
032import org.apache.directory.shared.kerberos.codec.methodData.MethodDataContainer;
033import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
034import org.apache.directory.shared.kerberos.codec.types.PaDataType;
035import org.apache.directory.shared.kerberos.components.ETypeInfo;
036import org.apache.directory.shared.kerberos.components.ETypeInfo2;
037import org.apache.directory.shared.kerberos.components.ETypeInfo2Entry;
038import org.apache.directory.shared.kerberos.components.ETypeInfoEntry;
039import org.apache.directory.shared.kerberos.components.MethodData;
040import org.apache.directory.shared.kerberos.components.PaData;
041import org.apache.directory.shared.kerberos.messages.KrbError;
042
043
044/**
045 * A class with utility methods.
046 *
047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048 */
049public class KdcClientUtil
050{
051    public static String extractRealm( String principal )
052    {
053        int pos = principal.indexOf( '@' );
054
055        if ( pos > 0 )
056        {
057            return principal.substring( pos + 1 );
058        }
059
060        throw new IllegalArgumentException( "Not a valid principal, missing realm name" );
061    }
062
063
064    public static String extractName( String principal )
065    {
066        int pos = principal.indexOf( '@' );
067
068        if ( pos < 0 )
069        {
070            return principal;
071        }
072
073        return principal.substring( 0, pos );
074    }
075
076
077    public static Set<EncryptionType> getEtypesFromError( KrbError error )
078    {
079        try
080        {
081            ByteBuffer stream = ByteBuffer.wrap( error.getEData() );
082
083            MethodDataContainer container = new MethodDataContainer();
084            container.setStream( stream );
085            Asn1Decoder.decode( stream, container );
086
087            MethodData methodData = container.getMethodData();
088
089            for ( PaData pd : methodData.getPaDatas() )
090            {
091                if ( pd.getPaDataType() == PaDataType.PA_ENCTYPE_INFO2 )
092                {
093                    return parseEtpeInfo2( pd.getPaDataValue() );
094                }
095                else if ( pd.getPaDataType() == PaDataType.PA_ENCTYPE_INFO )
096                {
097                    return parseEtpeInfo( pd.getPaDataValue() );
098                }
099            }
100        }
101        catch ( Exception e )
102        {
103            // shouldn't happen, but iff happens blast off
104            throw new RuntimeException( e );
105        }
106
107        return Collections.emptySet();
108    }
109
110
111    private static Set<EncryptionType> parseEtpeInfo2( byte[] data ) throws DecoderException
112    {
113        ByteBuffer stream = ByteBuffer.wrap( data );
114
115        ETypeInfo2Container container = new ETypeInfo2Container();
116        container.setStream( stream );
117        Asn1Decoder.decode( stream, container );
118
119        ETypeInfo2 info2 = container.getETypeInfo2();
120
121        Set<EncryptionType> lstEtypes = new LinkedHashSet<>();
122
123        for ( ETypeInfo2Entry e2e : info2.getETypeInfo2Entries() )
124        {
125            lstEtypes.add( e2e.getEType() );
126        }
127
128        return lstEtypes;
129    }
130
131
132    private static Set<EncryptionType> parseEtpeInfo( byte[] data ) throws DecoderException
133    {
134        ByteBuffer stream = ByteBuffer.wrap( data );
135
136        ETypeInfoContainer container = new ETypeInfoContainer();
137        container.setStream( stream );
138        Asn1Decoder.decode( stream, container );
139
140        ETypeInfo einfo = container.getETypeInfo();
141
142        Set<EncryptionType> lstEtypes = new LinkedHashSet<>();
143
144        for ( ETypeInfoEntry eie : einfo.getETypeInfoEntries() )
145        {
146            lstEtypes.add( eie.getEType() );
147        }
148
149        return lstEtypes;
150    }
151
152}