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.encoder;
021
022
023 import java.io.ByteArrayOutputStream;
024 import java.io.IOException;
025 import java.nio.ByteBuffer;
026
027 import org.apache.directory.server.kerberos.shared.messages.KdcRequest;
028 import org.apache.directory.server.kerberos.shared.messages.value.PaData;
029 import org.apache.directory.server.kerberos.shared.messages.value.RequestBody;
030 import org.apache.directory.shared.asn1.der.ASN1OutputStream;
031 import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
032 import org.apache.directory.shared.asn1.der.DERBitString;
033 import org.apache.directory.shared.asn1.der.DERGeneralString;
034 import org.apache.directory.shared.asn1.der.DERInteger;
035 import org.apache.directory.shared.asn1.der.DEROctetString;
036 import org.apache.directory.shared.asn1.der.DERSequence;
037 import org.apache.directory.shared.asn1.der.DERTaggedObject;
038
039
040 /**
041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042 * @version $Rev: 587624 $, $Date: 2007-10-23 22:22:08 +0300 (Tue, 23 Oct 2007) $
043 */
044 public class KdcRequestEncoder
045 {
046 /**
047 * Encodes a {@link KdcRequest} into a {@link ByteBuffer}.
048 *
049 * AS-REQ ::= [APPLICATION 10] KDC-REQ
050 * TGS-REQ ::= [APPLICATION 12] KDC-REQ
051 *
052 * @param request
053 * @param out
054 * @throws IOException
055 */
056 public void encode( KdcRequest request, ByteBuffer out ) throws IOException
057 {
058 ASN1OutputStream aos = new ASN1OutputStream( out );
059
060 DERSequence kdcRequest = encodeInitialSequence( request );
061 aos.writeObject( DERApplicationSpecific.valueOf( request.getMessageType().getOrdinal(), kdcRequest ) );
062 aos.close();
063 }
064
065
066 /*
067 KDC-REQ ::= SEQUENCE {
068 pvno[1] INTEGER,
069 msg-type[2] INTEGER,
070 padata[3] SEQUENCE OF PA-DATA OPTIONAL,
071 req-body[4] KDC-REQ-BODY
072 }*/
073 private DERSequence encodeInitialSequence( KdcRequest app )
074 {
075 DERSequence sequence = new DERSequence();
076
077 sequence.add( new DERTaggedObject( 1, DERInteger.valueOf( app.getProtocolVersionNumber() ) ) );
078
079 sequence.add( new DERTaggedObject( 2, DERInteger.valueOf( app.getMessageType().getOrdinal() ) ) );
080
081 if ( app.getPreAuthData() != null )
082 {
083 sequence.add( new DERTaggedObject( 3, encodePreAuthData( app.getPreAuthData() ) ) );
084 }
085
086 sequence.add( new DERTaggedObject( 4, encodeKdcRequestBody( app.getRequestBody() ) ) );
087
088 return sequence;
089 }
090
091
092 /**
093 * Encodes a {@link KdcRequest} into a byte[].
094 *
095 * @param requestBody
096 * @return The encoded {@link KdcRequest}.
097 * @throws IOException
098 */
099 public byte[] encodeRequestBody( RequestBody requestBody ) throws IOException
100 {
101 ByteArrayOutputStream baos = new ByteArrayOutputStream();
102 ASN1OutputStream aos = new ASN1OutputStream( baos );
103
104 aos.writeObject( encodeKdcRequestBody( requestBody ) );
105 aos.close();
106
107 return baos.toByteArray();
108 }
109
110
111 /**
112 * KDC-REQ-BODY ::= SEQUENCE {
113 * kdc-options[0] KDCOptions,
114 * cname[1] PrincipalName OPTIONAL,
115 * -- Used only in AS-REQ
116 * realm[2] Realm, -- Server's realm
117 * -- Also client's in AS-REQ
118 * sname[3] PrincipalName OPTIONAL,
119 * from[4] KerberosTime OPTIONAL,
120 * till[5] KerberosTime,
121 * rtime[6] KerberosTime OPTIONAL,
122 * nonce[7] INTEGER,
123 *
124 * etype[8] SEQUENCE OF INTEGER, -- EncryptionEngine,
125 * -- in preference order
126 * addresses[9] HostAddresses OPTIONAL,
127 * enc-authorization-data[10] EncryptedData OPTIONAL,
128 * -- Encrypted AuthorizationData encoding
129 * additional-tickets[11] SEQUENCE OF Ticket OPTIONAL
130 * }
131 */
132 private DERSequence encodeKdcRequestBody( RequestBody requestBody )
133 {
134 DERSequence sequence = new DERSequence();
135
136 sequence.add( new DERTaggedObject( 0, new DERBitString( requestBody.getKdcOptions().getBytes() ) ) );
137
138 // OPTIONAL
139 if ( requestBody.getClientPrincipal() != null )
140 {
141 sequence.add( new DERTaggedObject( 1, PrincipalNameEncoder.encode( requestBody.getClientPrincipal() ) ) );
142 }
143
144 sequence.add( new DERTaggedObject( 2, DERGeneralString.valueOf( requestBody.getServerPrincipal().getRealm()
145 .toString() ) ) );
146
147 // OPTIONAL
148 if ( requestBody.getServerPrincipal() != null )
149 {
150 sequence.add( new DERTaggedObject( 3, PrincipalNameEncoder.encode( requestBody.getServerPrincipal() ) ) );
151 }
152
153 // OPTIONAL
154 if ( requestBody.getFrom() != null )
155 {
156 sequence.add( new DERTaggedObject( 4, KerberosTimeEncoder.encode( requestBody.getFrom() ) ) );
157 }
158
159 sequence.add( new DERTaggedObject( 5, KerberosTimeEncoder.encode( requestBody.getTill() ) ) );
160
161 // OPTIONAL
162 if ( requestBody.getRtime() != null )
163 {
164 sequence.add( new DERTaggedObject( 6, KerberosTimeEncoder.encode( requestBody.getRtime() ) ) );
165 }
166
167 sequence.add( new DERTaggedObject( 7, DERInteger.valueOf( requestBody.getNonce() ) ) );
168
169 sequence.add( new DERTaggedObject( 8, EncryptionTypeEncoder.encode( requestBody.getEType() ) ) );
170
171 // OPTIONAL
172 if ( requestBody.getAddresses() != null )
173 {
174 sequence.add( new DERTaggedObject( 9, HostAddressesEncoder.encodeSequence( requestBody.getAddresses() ) ) );
175 }
176
177 // OPTIONAL
178 if ( requestBody.getEncAuthorizationData() != null )
179 {
180 sequence.add( new DERTaggedObject( 10, EncryptedDataEncoder.encodeSequence( requestBody
181 .getEncAuthorizationData() ) ) );
182 }
183
184 // OPTIONAL
185 if ( requestBody.getAdditionalTickets() != null )
186 {
187 sequence
188 .add( new DERTaggedObject( 11, TicketEncoder.encodeSequence( requestBody.getAdditionalTickets() ) ) );
189 }
190
191 return sequence;
192 }
193
194
195 /*
196 PA-DATA ::= SEQUENCE {
197 padata-type[1] INTEGER,
198 padata-value[2] OCTET STRING,
199 -- might be encoded AP-REQ
200 }*/
201 private DERSequence encodePreAuthData( PaData[] preAuthData )
202 {
203 DERSequence preAuth = new DERSequence();
204
205 for ( int ii = 0; ii < preAuthData.length; ii++ )
206 {
207 DERSequence sequence = new DERSequence();
208
209 sequence.add( new DERTaggedObject( 1, DERInteger.valueOf( preAuthData[ii].getPaDataType().getOrdinal() ) ) );
210 sequence.add( new DERTaggedObject( 2, new DEROctetString( preAuthData[ii].getPaDataValue() ) ) );
211 preAuth.add( sequence );
212 }
213
214 return preAuth;
215 }
216 }