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.core.security;
21
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.security.Key;
27 import java.security.KeyPair;
28 import java.security.KeyStoreException;
29 import java.security.KeyStoreSpi;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.UnrecoverableKeyException;
32 import java.security.cert.Certificate;
33 import java.security.cert.CertificateException;
34 import java.security.cert.X509Certificate;
35 import java.util.Date;
36 import java.util.Enumeration;
37
38 import org.apache.commons.lang.ArrayUtils;
39 import org.apache.commons.lang.NotImplementedException;
40 import org.apache.directory.server.core.CoreSession;
41 import org.apache.directory.server.core.DirectoryService;
42 import org.apache.directory.server.core.authn.LdapPrincipal;
43 import org.apache.directory.server.core.entry.ServerEntry;
44 import org.apache.directory.server.core.partition.PartitionNexus;
45 import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
46 import org.apache.directory.shared.ldap.name.LdapDN;
47 import org.apache.directory.shared.ldap.util.SingletonEnumeration;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51
52
53
54
55
56
57
58
59
60 public class CoreKeyStoreSpi extends KeyStoreSpi
61 {
62 private static final String APACHEDS_ALIAS = "apacheds";
63
64 private static final Logger LOG = LoggerFactory.getLogger( CoreKeyStoreSpi.class );
65
66 private DirectoryService directoryService;
67
68
69
70
71
72 public CoreKeyStoreSpi( DirectoryService directoryService )
73 {
74 LOG.debug( "Constructor called." );
75 this.directoryService = directoryService;
76 }
77
78
79 private ServerEntry getTlsEntry() throws Exception
80 {
81 LdapDN adminDn = PartitionNexus.getAdminName();
82 LdapPrincipal principal = new LdapPrincipal( adminDn, AuthenticationLevel.SIMPLE );
83 CoreSession session = directoryService.getSession( principal );
84 return session.lookup( adminDn );
85 }
86
87
88
89
90
91 @Override
92 public Enumeration<String> engineAliases()
93 {
94 LOG.debug( "engineAliases() called." );
95 return new SingletonEnumeration<String>( APACHEDS_ALIAS );
96 }
97
98
99
100
101
102 @Override
103 public boolean engineContainsAlias( String alias )
104 {
105 LOG.debug( "engineContainsAlias({}) called.", alias );
106
107 if ( alias.equalsIgnoreCase( APACHEDS_ALIAS ) )
108 {
109 return true;
110 }
111
112 return false;
113 }
114
115
116
117
118
119 @Override
120 public void engineDeleteEntry( String alias ) throws KeyStoreException
121 {
122 LOG.debug( "engineDeleteEntry({}) called.", alias );
123 throw new UnsupportedOperationException();
124 }
125
126
127
128
129
130 @Override
131 public Certificate engineGetCertificate( String alias )
132 {
133 LOG.debug( "engineGetCertificate({}) called.", alias );
134 if ( alias.equalsIgnoreCase( APACHEDS_ALIAS ) )
135 {
136 try
137 {
138 ServerEntry entry = getTlsEntry();
139 return TlsKeyGenerator.getCertificate( entry );
140 }
141 catch ( Exception e )
142 {
143 LOG.error( "Failed to access certificate in DIT.", e );
144 }
145 }
146
147 return null;
148 }
149
150
151
152
153
154 @Override
155 public String engineGetCertificateAlias( Certificate cert )
156 {
157 LOG.debug( "engineGetCertificateAlias({}) called.", cert );
158
159 if ( cert instanceof X509Certificate )
160 {
161 LOG.debug( "Certificate in alias request is X.509 based." );
162 X509Certificate xcert = ( X509Certificate ) cert;
163 if ( xcert.getSubjectDN().toString().equals( TlsKeyGenerator.CERTIFICATE_PRINCIPAL_DN ) )
164 {
165 return APACHEDS_ALIAS;
166 }
167 }
168
169 try
170 {
171 ServerEntry entry = getTlsEntry();
172 if ( ArrayUtils.isEquals( cert.getEncoded(), entry.get( TlsKeyGenerator.USER_CERTIFICATE_AT ).getBytes() ) )
173 {
174 return APACHEDS_ALIAS;
175 }
176 }
177 catch ( Exception e )
178 {
179 LOG.error( "Failed on attempt to compare certificate bytes to determine alias.", e );
180 }
181
182 return null;
183 }
184
185
186
187
188
189 @Override
190 public Certificate[] engineGetCertificateChain( String alias )
191 {
192 LOG.debug( "engineGetCertificateChain({}) called.", alias );
193 try
194 {
195 ServerEntry entry = getTlsEntry();
196 LOG.debug( "Entry:\n{}", entry );
197 return new Certificate[] { TlsKeyGenerator.getCertificate( entry ) };
198 }
199 catch ( Exception e )
200 {
201 LOG.error( "Failed on attempt to compare certificate bytes to determine alias.", e );
202 }
203
204 return new Certificate[0];
205 }
206
207
208
209
210
211 @Override
212 public Date engineGetCreationDate( String alias )
213 {
214 LOG.debug( "engineGetCreationDate({}) called.", alias );
215 return new Date();
216 }
217
218
219
220
221
222 @Override
223 public Key engineGetKey( String alias, char[] password ) throws NoSuchAlgorithmException, UnrecoverableKeyException
224 {
225 LOG.debug( "engineGetKey({}, {}) called.", alias, password );
226
227 try
228 {
229 ServerEntry entry = getTlsEntry();
230 KeyPair keyPair = TlsKeyGenerator.getKeyPair( entry );
231 return keyPair.getPrivate();
232 }
233 catch ( Exception e )
234 {
235 LOG.error( "Failed on attempt to extract key.", e );
236 }
237
238 return null;
239 }
240
241
242
243
244
245 @Override
246 public boolean engineIsCertificateEntry( String alias )
247 {
248 LOG.debug( "engineIsCertificateEntry({}) called.", alias );
249 return false;
250 }
251
252
253
254
255
256 @Override
257 public boolean engineIsKeyEntry( String alias )
258 {
259 LOG.debug( "engineIsKeyEntry({}) called.", alias );
260 return true;
261 }
262
263
264
265
266
267 @Override
268 public void engineLoad( InputStream stream, char[] password ) throws IOException, NoSuchAlgorithmException,
269 CertificateException
270 {
271 LOG.debug( "engineLoad({}, {}) called.", stream, password );
272 }
273
274
275
276
277
278 @Override
279 public void engineSetCertificateEntry( String alias, Certificate cert ) throws KeyStoreException
280 {
281 LOG.debug( "engineSetCertificateEntry({}, {}) called.", alias, cert );
282 throw new NotImplementedException();
283 }
284
285
286
287
288
289 @Override
290 public void engineSetKeyEntry( String alias, byte[] key, Certificate[] chain ) throws KeyStoreException
291 {
292 LOG.debug( "engineSetKeyEntry({}, key, {}) called.", alias, chain );
293 throw new NotImplementedException();
294 }
295
296
297
298
299
300 @Override
301 public void engineSetKeyEntry( String alias, Key key, char[] password, Certificate[] chain )
302 throws KeyStoreException
303 {
304 LOG.debug( "engineSetKeyEntry({}, key, {}, chain) called.", alias, new String( password ) );
305 throw new NotImplementedException();
306 }
307
308
309
310
311
312 @Override
313 public int engineSize()
314 {
315 LOG.debug( "engineSize() called." );
316 return 1;
317 }
318
319
320
321
322
323 @Override
324 public void engineStore( OutputStream stream, char[] password ) throws IOException, NoSuchAlgorithmException,
325 CertificateException
326 {
327 LOG.debug( "engineStore(stream, {}) called.", new String( password ) );
328 }
329 }