1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.kerberos.shared.keytab;
21
22
23 import java.io.IOException;
24 import java.io.UnsupportedEncodingException;
25 import java.nio.ByteBuffer;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.directory.shared.kerberos.KerberosTime;
30 import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
31 import org.apache.directory.shared.kerberos.components.EncryptionKey;
32
33
34
35
36
37
38
39 class KeytabDecoder
40 {
41
42
43
44
45 byte[] getKeytabVersion( ByteBuffer buffer )
46 {
47 byte[] version = new byte[2];
48 buffer.get( version );
49
50 return version;
51 }
52
53
54
55
56
57
58
59
60
61 List<KeytabEntry> getKeytabEntries( ByteBuffer buffer ) throws IOException
62 {
63 List<KeytabEntry> entries = new ArrayList<>();
64
65 while ( buffer.remaining() > 0 )
66 {
67 int size = buffer.getInt();
68
69 if ( ( size < 0 ) || ( size > buffer.capacity() ) )
70 {
71 throw new IOException( "Invalid size for the keytab entry" );
72 }
73
74 byte[] entry = new byte[size];
75
76 buffer.get( entry );
77 entries.add( getKeytabEntry( ByteBuffer.wrap( entry ) ) );
78 }
79
80 return entries;
81 }
82
83
84
85
86
87
88 private KeytabEntry getKeytabEntry( ByteBuffer buffer ) throws IOException
89 {
90 String principalName = getPrincipalName( buffer );
91
92 int principalType = buffer.getInt();
93
94 long time = buffer.getInt();
95 KerberosTimekerberos/KerberosTime.html#KerberosTime">KerberosTime timeStamp = new KerberosTime( time * 1000 );
96
97 byte keyVersion = buffer.get();
98
99 EncryptionKey key = getKeyBlock( buffer );
100
101 return new KeytabEntry( principalName, principalType, timeStamp, keyVersion, key );
102 }
103
104
105
106
107
108
109
110
111 private String getPrincipalName( ByteBuffer buffer ) throws IOException
112 {
113 int count = buffer.getShort();
114
115
116 String realm = getCountedString( buffer );
117
118 StringBuilder principalNameBuffer = new StringBuilder();
119
120 for ( int i = 0; i < count; i++ )
121 {
122 String nameComponent = getCountedString( buffer );
123
124 principalNameBuffer.append( nameComponent );
125
126 if ( i < count - 1 )
127 {
128 principalNameBuffer.append( "/" );
129 }
130 }
131
132 principalNameBuffer.append( "@" ).append( realm );
133
134 return principalNameBuffer.toString();
135 }
136
137
138
139
140
141 private EncryptionKey getKeyBlock( ByteBuffer buffer ) throws IOException
142 {
143 int type = buffer.getShort();
144 byte[] keyblock = getCountedBytes( buffer );
145
146 EncryptionType encryptionType = EncryptionType.getTypeByValue( type );
147
148 return new EncryptionKey( encryptionType, keyblock );
149 }
150
151
152
153
154
155
156 private String getCountedString( ByteBuffer buffer ) throws IOException
157 {
158 int length = buffer.getShort();
159
160 if ( ( length < 0 ) || ( length > buffer.capacity() ) )
161 {
162 throw new IOException( "Invalid size for the keytab entry" );
163 }
164
165 byte[] data = new byte[length];
166 buffer.get( data );
167
168 try
169 {
170 return new String( data, "ASCII" );
171 }
172 catch ( UnsupportedEncodingException uee )
173 {
174
175 return "";
176 }
177 }
178
179
180
181
182
183 private byte[] getCountedBytes( ByteBuffer buffer ) throws IOException
184 {
185 int length = buffer.getShort();
186
187 if ( ( length < 0 ) || ( length > buffer.capacity() ) )
188 {
189 throw new IOException( "Invalid size for the keytab entry" );
190 }
191
192 byte[] data = new byte[length];
193 buffer.get( data );
194
195 return data;
196 }
197 }