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.shared.io.decoder;
021
022
023 import java.io.IOException;
024 import java.nio.ByteBuffer;
025 import java.util.Enumeration;
026
027 import org.apache.directory.server.kerberos.shared.KerberosConstants;
028 import org.apache.directory.server.kerberos.shared.KerberosMessageType;
029 import org.apache.directory.server.kerberos.shared.messages.KdcRequest;
030 import org.apache.directory.server.kerberos.shared.messages.value.KdcOptions;
031 import org.apache.directory.server.kerberos.shared.messages.value.PaData;
032 import org.apache.directory.server.kerberos.shared.messages.value.RequestBody;
033 import org.apache.directory.server.kerberos.shared.messages.value.RequestBodyModifier;
034 import org.apache.directory.shared.asn1.der.ASN1InputStream;
035 import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
036 import org.apache.directory.shared.asn1.der.DERBitString;
037 import org.apache.directory.shared.asn1.der.DEREncodable;
038 import org.apache.directory.shared.asn1.der.DERGeneralString;
039 import org.apache.directory.shared.asn1.der.DERGeneralizedTime;
040 import org.apache.directory.shared.asn1.der.DERInteger;
041 import org.apache.directory.shared.asn1.der.DERSequence;
042 import org.apache.directory.shared.asn1.der.DERTaggedObject;
043
044
045 /**
046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
047 * @version $Rev: 590715 $, $Date: 2007-10-31 17:23:32 +0200 (Wed, 31 Oct 2007) $
048 */
049 public class KdcRequestDecoder
050 {
051 /**
052 * Decodes a {@link ByteBuffer} into a {@link KdcRequest}.
053 *
054 * @param in
055 * @return The {@link KdcRequest}.
056 * @throws IOException
057 */
058 public KdcRequest decode( ByteBuffer in ) throws IOException
059 {
060 ASN1InputStream ais = new ASN1InputStream( in );
061
062 DERApplicationSpecific app = ( DERApplicationSpecific ) ais.readObject();
063
064 DERSequence kdcreq = ( DERSequence ) app.getObject();
065
066 return decodeKdcRequestSequence( kdcreq );
067 }
068
069
070 /*
071 AS-REQ ::= [APPLICATION 10] KDC-REQ
072 TGS-REQ ::= [APPLICATION 12] KDC-REQ
073
074 KDC-REQ ::= SEQUENCE {
075 pvno[1] INTEGER,
076 msg-type[2] INTEGER,
077 padata[3] SEQUENCE OF PA-DATA OPTIONAL,
078 req-body[4] KDC-REQ-BODY
079 }*/
080 private KdcRequest decodeKdcRequestSequence( DERSequence sequence ) throws IOException
081 {
082 int pvno = KerberosConstants.KERBEROS_V5;
083 KerberosMessageType msgType = null;
084
085 PaData[] paData = null;
086 RequestBody requestBody = null;
087 byte[] bodyBytes = null;
088
089 for ( Enumeration<DEREncodable> e = sequence.getObjects(); e.hasMoreElements(); )
090 {
091 DERTaggedObject object = ( DERTaggedObject ) e.nextElement();
092 int tag = object.getTagNo();
093 DEREncodable derObject = object.getObject();
094
095 switch ( tag )
096 {
097 case 1:
098 DERInteger tag1 = ( DERInteger ) derObject;
099 pvno = tag1.intValue();
100 break;
101
102 case 2:
103 DERInteger tag2 = ( DERInteger ) derObject;
104 msgType = KerberosMessageType.getTypeByOrdinal( tag2.intValue() );
105 break;
106
107 case 3:
108 DERSequence tag3 = ( DERSequence ) derObject;
109 paData = PreAuthenticationDataDecoder.decodeSequence( tag3 );
110 break;
111
112 case 4:
113 DERSequence tag4 = ( DERSequence ) derObject;
114 requestBody = decodeRequestBody( tag4 );
115
116 /**
117 * Get the raw bytes of the KDC-REQ-BODY for checksum calculation and
118 * comparison with the authenticator checksum during the verification
119 * stage of ticket grant processing.
120 */
121 bodyBytes = object.getOctets();
122
123 break;
124 }
125 }
126
127 return new KdcRequest( pvno, msgType, paData, requestBody, bodyBytes );
128 }
129
130
131 /*
132 KDC-REQ-BODY ::= SEQUENCE {
133 kdc-options[0] KdcOptions,
134 cname[1] PrincipalName OPTIONAL,
135 -- Used only in AS-REQ
136 realm[2] Realm, -- Server's realm
137 -- Also client's in AS-REQ
138 sname[3] PrincipalName OPTIONAL,
139 from[4] KerberosTime OPTIONAL,
140 till[5] KerberosTime,
141 rtime[6] KerberosTime OPTIONAL,
142 nonce[7] INTEGER,
143 etype[8] SEQUENCE OF INTEGER, -- EncryptionType,
144 -- in preference order
145 addresses[9] HostAddresses OPTIONAL,
146 enc-authorization-data[10] EncryptedData OPTIONAL,
147 -- Encrypted AuthorizationData encoding
148 additional-tickets[11] SEQUENCE OF Ticket OPTIONAL
149 }*/
150 private RequestBody decodeRequestBody( DERSequence sequence ) throws IOException
151 {
152 RequestBodyModifier modifier = new RequestBodyModifier();
153
154 for ( Enumeration<DEREncodable> e = sequence.getObjects(); e.hasMoreElements(); )
155 {
156 DERTaggedObject object = ( DERTaggedObject ) e.nextElement();
157 int tag = object.getTagNo();
158 DEREncodable derObject = object.getObject();
159
160 switch ( tag )
161 {
162 case 0:
163 DERBitString kdcOptions = ( DERBitString ) derObject;
164 modifier.setKdcOptions( new KdcOptions( kdcOptions.getOctets() ) );
165 break;
166 case 1:
167 DERSequence cName = ( DERSequence ) derObject;
168 modifier.setClientName( PrincipalNameDecoder.decode( cName ) );
169 break;
170 case 2:
171 DERGeneralString realm = ( DERGeneralString ) derObject;
172 modifier.setRealm( realm.getString() );
173 break;
174 case 3:
175 DERSequence sname = ( DERSequence ) derObject;
176 modifier.setServerName( PrincipalNameDecoder.decode( sname ) );
177 break;
178 case 4:
179 DERGeneralizedTime from = ( DERGeneralizedTime ) derObject;
180 modifier.setFrom( KerberosTimeDecoder.decode( from ) );
181 break;
182 case 5:
183 DERGeneralizedTime till = ( DERGeneralizedTime ) derObject;
184 modifier.setTill( KerberosTimeDecoder.decode( till ) );
185 break;
186 case 6:
187 DERGeneralizedTime rtime = ( DERGeneralizedTime ) derObject;
188 modifier.setRtime( KerberosTimeDecoder.decode( rtime ) );
189 break;
190 case 7:
191 DERInteger nonce = ( DERInteger ) derObject;
192 modifier.setNonce( nonce.intValue() );
193 break;
194 case 8:
195 DERSequence etype = ( DERSequence ) derObject;
196 modifier.setEType( EncryptionTypeDecoder.decode( etype ) );
197 break;
198
199 case 9:
200 DERSequence hostAddresses = ( DERSequence ) derObject;
201 modifier.setAddresses( HostAddressDecoder.decodeSequence( hostAddresses ) );
202 break;
203 case 10:
204 DERSequence encryptedData = ( DERSequence ) derObject;
205 modifier.setEncAuthorizationData( EncryptedDataDecoder.decode( encryptedData ) );
206 break;
207 case 11:
208 DERSequence tag11 = ( DERSequence ) derObject;
209 modifier.setAdditionalTickets( TicketDecoder.decodeSequence( tag11 ) );
210 break;
211 }
212 }
213
214 return modifier.getRequestBody();
215 }
216 }