View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.kerberos.shared.io.encoder;
21  
22  
23  import java.io.ByteArrayOutputStream;
24  import java.io.IOException;
25  import java.nio.ByteBuffer;
26  
27  import org.apache.directory.server.kerberos.shared.messages.KdcRequest;
28  import org.apache.directory.server.kerberos.shared.messages.value.PaData;
29  import org.apache.directory.server.kerberos.shared.messages.value.RequestBody;
30  import org.apache.directory.shared.asn1.der.ASN1OutputStream;
31  import org.apache.directory.shared.asn1.der.DERApplicationSpecific;
32  import org.apache.directory.shared.asn1.der.DERBitString;
33  import org.apache.directory.shared.asn1.der.DERGeneralString;
34  import org.apache.directory.shared.asn1.der.DERInteger;
35  import org.apache.directory.shared.asn1.der.DEROctetString;
36  import org.apache.directory.shared.asn1.der.DERSequence;
37  import org.apache.directory.shared.asn1.der.DERTaggedObject;
38  
39  
40  /**
41   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
42   * @version $Rev: 587624 $, $Date: 2007-10-23 21:22:08 +0200 (Di, 23 Okt 2007) $
43   */
44  public class KdcRequestEncoder
45  {
46      /**
47       * Encodes a {@link KdcRequest} into a {@link ByteBuffer}.
48       * 
49       * AS-REQ ::=         [APPLICATION 10] KDC-REQ
50       * TGS-REQ ::=        [APPLICATION 12] KDC-REQ
51       *
52       * @param request
53       * @param out
54       * @throws IOException
55       */
56      public void encode( KdcRequest request, ByteBuffer out ) throws IOException
57      {
58          ASN1OutputStream aos = new ASN1OutputStream( out );
59  
60          DERSequence kdcRequest = encodeInitialSequence( request );
61          aos.writeObject( DERApplicationSpecific.valueOf( request.getMessageType().getOrdinal(), kdcRequest ) );
62          aos.close();
63      }
64  
65  
66      /*
67       KDC-REQ ::=        SEQUENCE {
68       pvno[1]               INTEGER,
69       msg-type[2]           INTEGER,
70       padata[3]             SEQUENCE OF PA-DATA OPTIONAL,
71       req-body[4]           KDC-REQ-BODY
72       }*/
73      private DERSequence encodeInitialSequence( KdcRequest app )
74      {
75          DERSequence sequence = new DERSequence();
76  
77          sequence.add( new DERTaggedObject( 1, DERInteger.valueOf( app.getProtocolVersionNumber() ) ) );
78  
79          sequence.add( new DERTaggedObject( 2, DERInteger.valueOf( app.getMessageType().getOrdinal() ) ) );
80  
81          if ( app.getPreAuthData() != null )
82          {
83              sequence.add( new DERTaggedObject( 3, encodePreAuthData( app.getPreAuthData() ) ) );
84          }
85  
86          sequence.add( new DERTaggedObject( 4, encodeKdcRequestBody( app.getRequestBody() ) ) );
87  
88          return sequence;
89      }
90  
91  
92      /**
93       * Encodes a {@link KdcRequest} into a byte[].
94       *
95       * @param requestBody
96       * @return The encoded {@link KdcRequest}.
97       * @throws IOException
98       */
99      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 }