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.shared.kerberos.codec;
21  
22  
23  import java.nio.ByteBuffer;
24  
25  import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswdErrorType;
26  import org.apache.directory.server.kerberos.changepwd.exceptions.ChangePasswordException;
27  import org.apache.directory.api.asn1.DecoderException;
28  import org.apache.directory.api.asn1.ber.Asn1Container;
29  import org.apache.directory.api.asn1.ber.Asn1Decoder;
30  import org.apache.directory.api.asn1.ber.tlv.TLVStateEnum;
31  import org.apache.directory.shared.kerberos.codec.EncKdcRepPart.EncKdcRepPartContainer;
32  import org.apache.directory.shared.kerberos.codec.apRep.ApRepContainer;
33  import org.apache.directory.shared.kerberos.codec.apReq.ApReqContainer;
34  import org.apache.directory.shared.kerberos.codec.authenticator.AuthenticatorContainer;
35  import org.apache.directory.shared.kerberos.codec.authorizationData.AuthorizationDataContainer;
36  import org.apache.directory.shared.kerberos.codec.encApRepPart.EncApRepPartContainer;
37  import org.apache.directory.shared.kerberos.codec.encAsRepPart.EncAsRepPartContainer;
38  import org.apache.directory.shared.kerberos.codec.encKrbPrivPart.EncKrbPrivPartContainer;
39  import org.apache.directory.shared.kerberos.codec.encTgsRepPart.EncTgsRepPartContainer;
40  import org.apache.directory.shared.kerberos.codec.encTicketPart.EncTicketPartContainer;
41  import org.apache.directory.shared.kerberos.codec.encryptedData.EncryptedDataContainer;
42  import org.apache.directory.shared.kerberos.codec.encryptionKey.EncryptionKeyContainer;
43  import org.apache.directory.shared.kerberos.codec.krbPriv.KrbPrivContainer;
44  import org.apache.directory.shared.kerberos.codec.paEncTsEnc.PaEncTsEncContainer;
45  import org.apache.directory.shared.kerberos.codec.principalName.PrincipalNameContainer;
46  import org.apache.directory.shared.kerberos.codec.ticket.TicketContainer;
47  import org.apache.directory.shared.kerberos.components.AuthorizationData;
48  import org.apache.directory.shared.kerberos.components.EncKdcRepPart;
49  import org.apache.directory.shared.kerberos.components.EncKrbPrivPart;
50  import org.apache.directory.shared.kerberos.components.EncTicketPart;
51  import org.apache.directory.shared.kerberos.components.EncryptedData;
52  import org.apache.directory.shared.kerberos.components.EncryptionKey;
53  import org.apache.directory.shared.kerberos.components.PaEncTsEnc;
54  import org.apache.directory.shared.kerberos.components.PrincipalName;
55  import org.apache.directory.shared.kerberos.exceptions.ErrorType;
56  import org.apache.directory.shared.kerberos.exceptions.KerberosException;
57  import org.apache.directory.shared.kerberos.messages.ApRep;
58  import org.apache.directory.shared.kerberos.messages.ApReq;
59  import org.apache.directory.shared.kerberos.messages.Authenticator;
60  import org.apache.directory.shared.kerberos.messages.EncApRepPart;
61  import org.apache.directory.shared.kerberos.messages.EncAsRepPart;
62  import org.apache.directory.shared.kerberos.messages.EncTgsRepPart;
63  import org.apache.directory.shared.kerberos.messages.KrbPriv;
64  import org.apache.directory.shared.kerberos.messages.Ticket;
65  import org.slf4j.Logger;
66  import org.slf4j.LoggerFactory;
67  
68  
69  /**
70   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
71   */
72  public class KerberosDecoder
73  {
74  
75      /** The logger */
76      private static Logger LOG = LoggerFactory.getLogger( KerberosDecoder.class );
77  
78      /** A speedup for logger */
79      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
80  
81  
82      public static Object decode( KerberosMessageContainer kerberosMessageContainer ) throws DecoderException
83      {
84          ByteBuffer buf = kerberosMessageContainer.getStream();
85          
86          if ( kerberosMessageContainer.isTCP() )
87          {
88              if ( buf.remaining() > 4 )
89              {
90                  kerberosMessageContainer.setTcpLength( buf.getInt() );
91                  buf.mark();
92              }
93              else
94              {
95                  return null;
96              }
97          }
98          else
99          {
100             buf.mark();
101         }
102 
103         while ( buf.hasRemaining() )
104         {
105             try
106             {
107                 Asn1Decoder.decode( buf, kerberosMessageContainer );
108                 
109                 if ( kerberosMessageContainer.getState() == TLVStateEnum.PDU_DECODED )
110                 {
111                     if ( IS_DEBUG )
112                     {
113                         LOG.debug( "Decoded KerberosMessage : {}", kerberosMessageContainer.getMessage() );
114                         buf.mark();
115                     }
116         
117                     return kerberosMessageContainer.getMessage();
118                 }
119             }
120             catch ( DecoderException de )
121             {
122                 LOG.warn( "error while decoding", de );
123                 buf.clear();
124                 kerberosMessageContainer.clean();
125                 throw de;
126             }
127         }
128         
129         return null;
130     }
131     
132     
133     /**
134      * Decode an EncrytedData structure
135      * 
136      * @param data The byte array containing the data structure to decode
137      * @return An instance of EncryptedData
138      * @throws KerberosException If the decoding fails
139      */
140     public static EncryptedData decodeEncryptedData( byte[] data ) throws KerberosException
141     {
142         ByteBuffer stream = ByteBuffer.allocate( data.length );
143         stream.put( data );
144         stream.flip();
145         
146         // Allocate a EncryptedData Container
147         Asn1Container encryptedDataContainer = new EncryptedDataContainer();
148 
149         // Decode the EncryptedData PDU
150         try
151         {
152             Asn1Decoder.decode( stream, encryptedDataContainer );
153         }
154         catch ( DecoderException de )
155         {
156             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
157         }
158 
159         // get the decoded EncryptedData
160         return ( ( EncryptedDataContainer ) encryptedDataContainer ).getEncryptedData();
161     }
162     
163     
164     /**
165      * Decode an PaEncTsEnc structure
166      * 
167      * @param data The byte array containing the data structure to decode
168      * @return An instance of PaEncTsEnc
169      * @throws KerberosException If the decoding fails
170      */
171     public static PaEncTsEnc decodePaEncTsEnc( byte[] data ) throws KerberosException
172     {
173         ByteBuffer stream = ByteBuffer.allocate( data.length );
174         stream.put( data );
175         stream.flip();
176         
177         // Allocate a PaEncTsEnc Container
178         Asn1Container paEncTsEncContainer = new PaEncTsEncContainer();
179 
180         // Decode the PaEncTsEnc PDU
181         try
182         {
183             Asn1Decoder.decode( stream, paEncTsEncContainer );
184         }
185         catch ( DecoderException de )
186         {
187             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
188         }
189 
190         // get the decoded PaEncTsEnc
191         return ( ( PaEncTsEncContainer ) paEncTsEncContainer ).getPaEncTsEnc();
192     }
193     
194     
195     /**
196      * Decode an EncApRepPart structure
197      * 
198      * @param data The byte array containing the data structure to decode
199      * @return An instance of EncApRepPart
200      * @throws KerberosException If the decoding fails
201      */
202     public static EncApRepPart decodeEncApRepPart( byte[] data ) throws KerberosException
203     {
204         ByteBuffer stream = ByteBuffer.allocate( data.length );
205         stream.put( data );
206         stream.flip();
207         
208         // Allocate a EncApRepPart Container
209         Asn1Container encApRepPartContainer = new EncApRepPartContainer( stream );
210 
211         // Decode the EncApRepPart PDU
212         try
213         {
214             Asn1Decoder.decode( stream, encApRepPartContainer );
215         }
216         catch ( DecoderException de )
217         {
218             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
219         }
220 
221         // get the decoded EncApRepPart
222         return ( ( EncApRepPartContainer ) encApRepPartContainer ).getEncApRepPart();
223     }
224     
225     
226     /**
227      * Decode an EncKdcRepPart structure
228      * 
229      * @param data The byte array containing the data structure to decode
230      * @return An instance of EncKdcRepPart
231      * @throws KerberosException If the decoding fails
232      */
233     public static EncKdcRepPart decodeEncKdcRepPart( byte[] data ) throws KerberosException
234     {
235         ByteBuffer stream = ByteBuffer.allocate( data.length );
236         stream.put( data );
237         stream.flip();
238         
239         // Allocate a EncKdcRepPart Container
240         Asn1Container encKdcRepPartContainer = new EncKdcRepPartContainer( stream );
241 
242         // Decode the EncKdcRepPart PDU
243         try
244         {
245             Asn1Decoder.decode( stream, encKdcRepPartContainer );
246         }
247         catch ( DecoderException de )
248         {
249             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
250         }
251 
252         // get the decoded EncKdcRepPart
253         return ( ( EncKdcRepPartContainer ) encKdcRepPartContainer ).getEncKdcRepPart();
254     }
255     
256     
257     /**
258      * Decode an EncKrbPrivPart structure
259      * 
260      * @param data The byte array containing the data structure to decode
261      * @return An instance of EncKrbPrivPart
262      * @throws KerberosException If the decoding fails
263      */
264     public static EncKrbPrivPart decodeEncKrbPrivPart( byte[] data ) throws KerberosException
265     {
266         ByteBuffer stream = ByteBuffer.allocate( data.length );
267         stream.put( data );
268         stream.flip();
269         
270         // Allocate a EncKrbPrivPart Container
271         Asn1Container encKrbPrivPartContainer = new EncKrbPrivPartContainer( stream );
272 
273         // Decode the EncKrbPrivPart PDU
274         try
275         {
276             Asn1Decoder.decode( stream, encKrbPrivPartContainer );
277         }
278         catch ( DecoderException de )
279         {
280             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
281         }
282 
283         // get the decoded EncKrbPrivPart
284         return ( ( EncKrbPrivPartContainer ) encKrbPrivPartContainer ).getEncKrbPrivPart();
285     }
286     
287     
288     /**
289      * Decode an EncTicketPart structure
290      * 
291      * @param data The byte array containing the data structure to decode
292      * @return An instance of EncTicketPart
293      * @throws KerberosException If the decoding fails
294      */
295     public static EncTicketPart decodeEncTicketPart( byte[] data ) throws KerberosException
296     {
297         ByteBuffer stream = ByteBuffer.allocate( data.length );
298         stream.put( data );
299         stream.flip();
300         
301         // Allocate a EncTicketPart Container
302         Asn1Container encTicketPartContainer = new EncTicketPartContainer( stream );
303 
304         // Decode the EncTicketPart PDU
305         try
306         {
307             Asn1Decoder.decode( stream, encTicketPartContainer );
308         }
309         catch ( DecoderException de )
310         {
311             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
312         }
313 
314         // get the decoded EncTicketPart
315         return ( ( EncTicketPartContainer ) encTicketPartContainer ).getEncTicketPart();
316     }
317     
318     
319     /**
320      * Decode an EncryptionKey structure
321      * 
322      * @param data The byte array containing the data structure to decode
323      * @return An instance of EncryptionKey
324      * @throws KerberosException If the decoding fails
325      */
326     public static EncryptionKey decodeEncryptionKey( byte[] data ) throws KerberosException
327     {
328         ByteBuffer stream = ByteBuffer.allocate( data.length );
329         stream.put( data );
330         stream.flip();
331         
332         // Allocate a EncryptionKey Container
333         Asn1Container encryptionKeyContainer = new EncryptionKeyContainer();
334 
335         // Decode the EncryptionKey PDU
336         try
337         {
338             Asn1Decoder.decode( stream, encryptionKeyContainer );
339         }
340         catch ( DecoderException de )
341         {
342             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
343         }
344 
345         // get the decoded EncryptionKey
346         return ( ( EncryptionKeyContainer ) encryptionKeyContainer ).getEncryptionKey();
347     }
348     
349     
350     /**
351      * Decode an PrincipalName structure
352      * 
353      * @param data The byte array containing the data structure to decode
354      * @return An instance of PrincipalName
355      * @throws KerberosException If the decoding fails
356      */
357     public static PrincipalName decodePrincipalName( byte[] data ) throws KerberosException
358     {
359         ByteBuffer stream = ByteBuffer.allocate( data.length );
360         stream.put( data );
361         stream.flip();
362         
363         // Allocate a PrincipalName Container
364         Asn1Container principalNameContainer = new PrincipalNameContainer();
365 
366         // Decode the PrincipalName PDU
367         try
368         {
369             Asn1Decoder.decode( stream, principalNameContainer );
370         }
371         catch ( DecoderException de )
372         {
373             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
374         }
375 
376         // get the decoded PrincipalName
377         return ( ( PrincipalNameContainer ) principalNameContainer ).getPrincipalName();
378     }
379     
380     
381     /**
382      * Decode a Ticket structure
383      * 
384      * @param data The byte array containing the data structure to decode
385      * @return An instance of Ticket
386      * @throws KerberosException If the decoding fails
387      */
388     public static Ticket decodeTicket( byte[] data ) throws KerberosException
389     {
390         ByteBuffer stream = ByteBuffer.allocate( data.length );
391         stream.put( data );
392         stream.flip();
393         
394         // Allocate a Ticket Container
395         Asn1Container ticketContainer = new TicketContainer( stream );
396 
397         // Decode the Ticket PDU
398         try
399         {
400             Asn1Decoder.decode( stream, ticketContainer );
401         }
402         catch ( DecoderException de )
403         {
404             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
405         }
406 
407         // get the decoded Ticket
408         return ( ( TicketContainer ) ticketContainer ).getTicket();
409     }
410     
411     
412     /**
413      * Decode a Authenticator structure
414      * 
415      * @param data The byte array containing the data structure to decode
416      * @return An instance of Authenticator
417      * @throws KerberosException If the decoding fails
418      */
419     public static Authenticator decodeAuthenticator( byte[] data ) throws KerberosException
420     {
421         ByteBuffer stream = ByteBuffer.allocate( data.length );
422         stream.put( data );
423         stream.flip();
424         
425         // Allocate a Authenticator Container
426         Asn1Container authenticatorContainer = new AuthenticatorContainer( stream );
427 
428         // Decode the Ticket PDU
429         try
430         {
431             Asn1Decoder.decode( stream, authenticatorContainer );
432         }
433         catch ( DecoderException de )
434         {
435             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
436         }
437 
438         // get the decoded Authenticator
439         return ( ( AuthenticatorContainer ) authenticatorContainer ).getAuthenticator();
440     }
441     
442     
443     /**
444      * Decode a AuthorizationData structure
445      * 
446      * @param data The byte array containing the data structure to decode
447      * @return An instance of AuthorizationData
448      * @throws KerberosException If the decoding fails
449      */
450     public static AuthorizationData decodeAuthorizationData( byte[] data ) throws KerberosException
451     {
452         ByteBuffer stream = ByteBuffer.allocate( data.length );
453         stream.put( data );
454         stream.flip();
455         
456         // Allocate a AuthorizationData Container
457         Asn1Container authorizationDataContainer = new AuthorizationDataContainer();
458 
459         // Decode the Ticket PDU
460         try
461         {
462             Asn1Decoder.decode( stream, authorizationDataContainer );
463         }
464         catch ( DecoderException de )
465         {
466             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
467         }
468 
469         // get the decoded AuthorizationData
470         return ( ( AuthorizationDataContainer ) authorizationDataContainer ).getAuthorizationData();
471     }
472 
473     
474     /**
475      * Decode a AP-REP structure
476      * 
477      * @param data The byte array containing the data structure to decode
478      * @return An instance of ApRep
479      * @throws KerberosException If the decoding fails
480      */
481     public static ApRep decodeApRep( byte[] data ) throws KerberosException
482     {
483         ByteBuffer stream = ByteBuffer.allocate( data.length );
484         stream.put( data );
485         stream.flip();
486         
487         // Allocate a ApRep Container
488         Asn1Container apRepContainer = new ApRepContainer( stream );
489 
490         // Decode the ApRep PDU
491         try
492         {
493             Asn1Decoder.decode( stream, apRepContainer );
494         }
495         catch ( DecoderException de )
496         {
497             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
498         }
499 
500         // get the decoded ApRep
501         return ( ( ApRepContainer ) apRepContainer ).getApRep();
502     }
503 
504     
505     /**
506      * Decode a AP-REQ structure
507      * 
508      * @param data The byte array containing the data structure to decode
509      * @return An instance of ApReq
510      * @throws KerberosException If the decoding fails
511      */
512     public static ApReq decodeApReq( byte[] data ) throws KerberosException
513     {
514         ByteBuffer stream = ByteBuffer.allocate( data.length );
515         stream.put( data );
516         stream.flip();
517         
518         // Allocate a ApReq Container
519         Asn1Container apReqContainer = new ApReqContainer( stream );
520 
521         // Decode the ApReq PDU
522         try
523         {
524             Asn1Decoder.decode( stream, apReqContainer );
525         }
526         catch ( DecoderException de )
527         {
528             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
529         }
530 
531         // get the decoded ApReq
532         return ( ( ApReqContainer ) apReqContainer ).getApReq();
533     }
534 
535     
536     /**
537      * Decode a KRB-PRIV structure
538      * 
539      * @param data The byte array containing the data structure to decode
540      * @return An instance of KrbPriv
541      * @throws KerberosException If the decoding fails
542      */
543     public static KrbPriv decodeKrbPriv( byte[] data ) throws KerberosException
544     {
545         ByteBuffer stream = ByteBuffer.allocate( data.length );
546         stream.put( data );
547         stream.flip();
548         
549         // Allocate a KrbPriv Container
550         Asn1Container krbPrivContainer = new KrbPrivContainer( stream );
551 
552         // Decode the KrbPriv PDU
553         try
554         {
555             Asn1Decoder.decode( stream, krbPrivContainer );
556         }
557         catch ( DecoderException de )
558         {
559             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
560         }
561 
562         // get the decoded KrbPriv
563         return ( ( KrbPrivContainer ) krbPrivContainer ).getKrbPriv();
564     }
565     
566     
567     /**
568      * Decode an EncAsRepPart structure
569      * 
570      * @param data The byte array containing the data structure to decode
571      * @return An instance of EncAsRepPart
572      * @throws KerberosException If the decoding fails
573      */
574     public static EncAsRepPart decodeEncAsRepPart( byte[] data ) throws KerberosException
575     {
576         ByteBuffer stream = ByteBuffer.allocate( data.length );
577         stream.put( data );
578         stream.flip();
579         
580         // Allocate a EncAsRepPart Container
581         Asn1Container encAsRepPartContainer = new EncAsRepPartContainer( stream );
582 
583         // Decode the EncAsRepPart PDU
584         try
585         {
586             Asn1Decoder.decode( stream, encAsRepPartContainer );
587         }
588         catch ( DecoderException de )
589         {
590             throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, de );
591         }
592 
593         // get the decoded EncAsRepPart
594         return ( ( EncAsRepPartContainer ) encAsRepPartContainer ).getEncAsRepPart();
595     }
596 
597     
598     /**
599      * Decode an EncTgsRepPart structure
600      * 
601      * @param data The byte array containing the data structure to decode
602      * @return An instance of EncTgsRepPart
603      * @throws ChangePasswordException If the decoding fails
604      */
605     public static EncTgsRepPart decodeEncTgsRepPart( byte[] data ) throws ChangePasswordException
606     {
607         ByteBuffer stream = ByteBuffer.allocate( data.length );
608         stream.put( data );
609         stream.flip();
610         
611         // Allocate a EncTgsRepPart Container
612         Asn1Container encTgsRepPartContainer = new EncTgsRepPartContainer( stream );
613 
614         // Decode the EncTgsRepPart PDU
615         try
616         {
617             Asn1Decoder.decode( stream, encTgsRepPartContainer );
618         }
619         catch ( DecoderException de )
620         {
621             throw new ChangePasswordException( ChangePasswdErrorType.KRB5_KPASSWD_MALFORMED, de );
622         }
623 
624         // get the decoded EncTgsRepPart
625         return ( ( EncTgsRepPartContainer ) encTgsRepPartContainer ).getEncTgsRepPart();
626     }
627 }