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.keytab;
21  
22  
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
27  import org.apache.mina.common.ByteBuffer;
28  
29  
30  /**
31   * Encode keytab fields into a {@link ByteBuffer}.
32   *
33   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
34   * @version $Rev$, $Date$
35   */
36  class KeytabEncoder
37  {
38      /**
39       * Write the keytab version and entries into a {@link ByteBuffer}.
40       *
41       * @param keytabVersion
42       * @param entries
43       * @return The ByteBuffer.
44       */
45      ByteBuffer write( byte[] keytabVersion, List<KeytabEntry> entries )
46      {
47          ByteBuffer buffer = ByteBuffer.allocate( 512 );
48          putKeytabVersion( buffer, keytabVersion );
49          putKeytabEntries( buffer, entries );
50          buffer.flip();
51  
52          return buffer;
53      }
54  
55  
56      /**
57       * Encode the 16-bit file format version.  This
58       * keytab reader currently only support verision 5.2.
59       */
60      private void putKeytabVersion( ByteBuffer buffer, byte[] version )
61      {
62          buffer.put( version );
63      }
64  
65  
66      /**
67       * Encode the keytab entries.
68       *
69       * @param buffer
70       * @param entries
71       */
72      private void putKeytabEntries( ByteBuffer buffer, List<KeytabEntry> entries )
73      {
74          Iterator<KeytabEntry> iterator = entries.iterator();
75  
76          while ( iterator.hasNext() )
77          {
78              ByteBuffer entryBuffer = putKeytabEntry( iterator.next() );
79              int size = entryBuffer.position();
80  
81              entryBuffer.flip();
82  
83              buffer.putInt( size );
84              buffer.put( entryBuffer );
85          }
86      }
87  
88  
89      /**
90       * Encode a "keytab entry," which consists of a principal name,
91       * principal type, key version number, and key material.
92       */
93      private ByteBuffer putKeytabEntry( KeytabEntry entry )
94      {
95          ByteBuffer buffer = ByteBuffer.allocate( 100 );
96  
97          putPrincipalName( buffer, entry.getPrincipalName() );
98  
99          buffer.putInt( ( int ) entry.getPrincipalType() );
100 
101         buffer.putInt( ( int ) ( entry.getTimeStamp().getTime() / 1000 ) );
102 
103         buffer.put( entry.getKeyVersion() );
104 
105         putKeyBlock( buffer, entry.getKey() );
106 
107         return buffer;
108     }
109 
110 
111     /**
112      * Encode a principal name.
113      *
114      * @param buffer
115      * @param principalName
116      */
117     private void putPrincipalName( ByteBuffer buffer, String principalName )
118     {
119         String[] split = principalName.split( "@" );
120         String nameComponent = split[0];
121         String realm = split[1];
122 
123         String[] nameComponents = nameComponent.split( "/" );
124 
125         // increment for v1
126         buffer.putShort( ( short ) nameComponents.length );
127 
128         putCountedString( buffer, realm );
129         // write components
130 
131         for ( int ii = 0; ii < nameComponents.length; ii++ )
132         {
133             putCountedString( buffer, nameComponents[ii] );
134         }
135     }
136 
137 
138     /**
139      * Encode a 16-bit encryption type and symmetric key material.
140      */
141     private void putKeyBlock( ByteBuffer buffer, EncryptionKey key )
142     {
143         buffer.putShort( ( short ) key.getKeyType().getOrdinal() );
144         putCountedBytes( buffer, key.getKeyValue() );
145     }
146 
147 
148     /**
149      * Use a prefixed 16-bit length to encode a String.  Realm and name
150      * components are ASCII encoded text with no zero terminator.
151      */
152     private void putCountedString( ByteBuffer buffer, String string )
153     {
154         byte[] data = string.getBytes();
155         buffer.putShort( ( short ) data.length );
156         buffer.put( data );
157     }
158 
159 
160     /**
161      * Use a prefixed 16-bit length to encode raw bytes.
162      */
163     private void putCountedBytes( ByteBuffer buffer, byte[] data )
164     {
165         buffer.putShort( ( short ) data.length );
166         buffer.put( data );
167     }
168 }