001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2007-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS 026 */ 027package org.opends.server.backends; 028 029import static org.forgerock.util.Reject.*; 030import static org.opends.messages.BackendMessages.*; 031import static org.opends.server.config.ConfigConstants.*; 032import static org.opends.server.util.ServerConstants.*; 033import static org.opends.server.util.StaticUtils.*; 034 035import java.io.BufferedReader; 036import java.io.File; 037import java.io.FileInputStream; 038import java.io.FileOutputStream; 039import java.io.FileReader; 040import java.io.FileWriter; 041import java.io.IOException; 042import java.io.PrintWriter; 043import java.net.UnknownHostException; 044import java.security.Key; 045import java.security.KeyStore; 046import java.security.KeyStoreException; 047import java.security.cert.Certificate; 048import java.util.Collections; 049import java.util.Iterator; 050import java.util.LinkedHashMap; 051import java.util.List; 052import java.util.Random; 053import java.util.Set; 054import java.util.SortedSet; 055 056import javax.naming.ldap.Rdn; 057import javax.net.ssl.KeyManager; 058import javax.net.ssl.KeyManagerFactory; 059import javax.net.ssl.TrustManager; 060import javax.net.ssl.TrustManagerFactory; 061 062import org.forgerock.i18n.LocalizableMessage; 063import org.forgerock.i18n.slf4j.LocalizedLogger; 064import org.forgerock.opendj.config.server.ConfigChangeResult; 065import org.forgerock.opendj.config.server.ConfigException; 066import org.forgerock.opendj.ldap.ByteString; 067import org.forgerock.opendj.ldap.ConditionResult; 068import org.forgerock.opendj.ldap.ResultCode; 069import org.forgerock.opendj.ldap.SearchScope; 070import org.forgerock.util.Reject; 071import org.opends.server.admin.server.ConfigurationChangeListener; 072import org.opends.server.admin.std.server.TrustStoreBackendCfg; 073import org.opends.server.api.Backend; 074import org.opends.server.core.AddOperation; 075import org.opends.server.core.DeleteOperation; 076import org.opends.server.core.DirectoryServer; 077import org.opends.server.core.ModifyDNOperation; 078import org.opends.server.core.ModifyOperation; 079import org.opends.server.core.SearchOperation; 080import org.opends.server.core.ServerContext; 081import org.opends.server.types.*; 082import org.opends.server.util.CertificateManager; 083import org.opends.server.util.SetupUtils; 084 085/** 086 * This class defines a backend used to provide an LDAP view of public keys 087 * stored in a key store. 088 */ 089public class TrustStoreBackend extends Backend<TrustStoreBackendCfg> 090 implements ConfigurationChangeListener<TrustStoreBackendCfg> 091{ 092 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 093 094 095 096 /** The current configuration state. */ 097 private TrustStoreBackendCfg configuration; 098 099 /** The DN for the base entry. */ 100 private DN baseDN; 101 102 /** The set of base DNs for this backend. */ 103 private DN[] baseDNs; 104 105 /** The base entry. */ 106 private Entry baseEntry; 107 108 /** The PIN needed to access the trust store backing file. */ 109 private char[] trustStorePIN; 110 111 /** The path to the trust store backing file. */ 112 private String trustStoreFile; 113 114 /** The type of trust store backing file to use. */ 115 private String trustStoreType; 116 117 /** The certificate manager for the trust store. */ 118 private CertificateManager certificateManager; 119 120 121 122 /** 123 * Creates a new backend. All backend 124 * implementations must implement a default constructor that use 125 * <CODE>super()</CODE> to invoke this constructor. 126 */ 127 public TrustStoreBackend() 128 { 129 super(); 130 131 // Perform all initialization in initializeBackend. 132 } 133 134 /** {@inheritDoc} */ 135 @Override 136 public void configureBackend(TrustStoreBackendCfg config, ServerContext serverContext) throws ConfigException 137 { 138 Reject.ifNull(config); 139 configuration = config; 140 } 141 142 /** {@inheritDoc} */ 143 @Override 144 public void openBackend() throws ConfigException, InitializationException 145 { 146 DN configEntryDN = configuration.dn(); 147 148 // Create the set of base DNs that we will handle. In this case, it's just 149 // the DN of the base trust store entry. 150 SortedSet<DN> baseDNSet = configuration.getBaseDN(); 151 if (baseDNSet.size() != 1) 152 { 153 throw new InitializationException(ERR_TRUSTSTORE_REQUIRES_ONE_BASE_DN.get(configEntryDN)); 154 } 155 baseDN = baseDNSet.first(); 156 baseDNs = new DN[] {baseDN}; 157 158 // Get the path to the trust store file. 159 trustStoreFile = configuration.getTrustStoreFile(); 160 161 162 // Get the trust store type. If none is specified, then use the default 163 // type. 164 trustStoreType = configuration.getTrustStoreType(); 165 if (trustStoreType == null) 166 { 167 trustStoreType = KeyStore.getDefaultType(); 168 } 169 170 try 171 { 172 KeyStore.getInstance(trustStoreType); 173 } 174 catch (KeyStoreException kse) 175 { 176 logger.traceException(kse); 177 throw new InitializationException(ERR_TRUSTSTORE_INVALID_TYPE.get( 178 trustStoreType, configEntryDN, getExceptionMessage(kse))); 179 } 180 181 182 // Get the PIN needed to access the contents of the trust store file. We 183 // will offer several places to look for the PIN, and we will do so in the 184 // following order: 185 // - In a specified Java property 186 // - In a specified environment variable 187 // - In a specified file on the server filesystem. 188 // - As the value of a configuration attribute. 189 // In any case, the PIN must be in the clear. If no PIN is provided, then 190 // it will be assumed that none is required to access the information in the 191 // trust store. 192 String pinProperty = configuration.getTrustStorePinProperty(); 193 if (pinProperty == null) 194 { 195 String pinEnVar = configuration.getTrustStorePinEnvironmentVariable(); 196 if (pinEnVar == null) 197 { 198 String pinFilePath = configuration.getTrustStorePinFile(); 199 if (pinFilePath == null) 200 { 201 String pinStr = configuration.getTrustStorePin(); 202 if (pinStr == null) 203 { 204 // This should be an Error. Otherwise, programs fails. 205 // Is there a Unit Test? 206 trustStorePIN = null; 207 } 208 else 209 { 210 trustStorePIN = pinStr.toCharArray(); 211 } 212 } 213 else 214 { 215 File pinFile = getFileForPath(pinFilePath); 216 if (! pinFile.exists()) 217 { 218 try 219 { 220 // Generate a PIN. 221 trustStorePIN = createKeystorePassword(); 222 223 // Store the PIN in the pin file. 224 createPINFile(pinFile.getPath(), new String(trustStorePIN)); 225 } 226 catch (Exception e) 227 { 228 throw new InitializationException( 229 ERR_TRUSTSTORE_PIN_FILE_CANNOT_CREATE.get(pinFilePath, configEntryDN)); 230 } 231 } 232 else 233 { 234 String pinStr; 235 236 BufferedReader br = null; 237 try 238 { 239 br = new BufferedReader(new FileReader(pinFile)); 240 pinStr = br.readLine(); 241 } 242 catch (IOException ioe) 243 { 244 LocalizableMessage message = ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ. 245 get(pinFilePath, configEntryDN, getExceptionMessage(ioe)); 246 throw new InitializationException(message, ioe); 247 } 248 finally 249 { 250 close(br); 251 } 252 253 if (pinStr == null) 254 { 255 throw new InitializationException( 256 ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(pinFilePath, configEntryDN)); 257 } 258 trustStorePIN = pinStr.toCharArray(); 259 } 260 } 261 } 262 else 263 { 264 String pinStr = System.getenv(pinEnVar); 265 if (pinStr == null) 266 { 267 throw new InitializationException( 268 ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(pinProperty, configEntryDN)); 269 } 270 trustStorePIN = pinStr.toCharArray(); 271 } 272 } 273 else 274 { 275 String pinStr = System.getProperty(pinProperty); 276 if (pinStr == null) 277 { 278 throw new InitializationException(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(pinProperty, configEntryDN)); 279 } 280 trustStorePIN = pinStr.toCharArray(); 281 } 282 283 // Create a certificate manager. 284 certificateManager = 285 new CertificateManager(getFileForPath(trustStoreFile).getPath(), 286 trustStoreType, 287 new String(trustStorePIN)); 288 289 // Generate a self-signed certificate, if there is none. 290 generateInstanceCertificateIfAbsent(); 291 292 // Construct the trust store base entry. 293 LinkedHashMap<ObjectClass,String> objectClasses = new LinkedHashMap<>(2); 294 objectClasses.put(DirectoryServer.getTopObjectClass(), OC_TOP); 295 296 ObjectClass branchOC = 297 DirectoryServer.getObjectClass("ds-cfg-branch", true); 298 objectClasses.put(branchOC, "ds-cfg-branch"); 299 300 LinkedHashMap<AttributeType,List<Attribute>> opAttrs = new LinkedHashMap<>(0); 301 LinkedHashMap<AttributeType,List<Attribute>> userAttrs = new LinkedHashMap<>(1); 302 303 RDN rdn = baseDN.rdn(); 304 int numAVAs = rdn.getNumValues(); 305 for (int i=0; i < numAVAs; i++) 306 { 307 AttributeType attrType = rdn.getAttributeType(i); 308 userAttrs.put(attrType, Attributes.createAsList(attrType, rdn.getAttributeValue(i))); 309 } 310 311 baseEntry = new Entry(baseDN, objectClasses, userAttrs, opAttrs); 312 313 // Register this as a change listener. 314 configuration.addTrustStoreChangeListener(this); 315 316 317 // Register the trust store base as a private suffix. 318 try 319 { 320 DirectoryServer.registerBaseDN(baseDN, this, true); 321 } 322 catch (Exception e) 323 { 324 logger.traceException(e); 325 throw new InitializationException(ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(baseDN, e), e); 326 } 327 } 328 329 /** {@inheritDoc} */ 330 @Override 331 public void closeBackend() 332 { 333 configuration.addTrustStoreChangeListener(this); 334 335 try 336 { 337 DirectoryServer.deregisterBaseDN(baseDN); 338 } 339 catch (Exception e) 340 { 341 logger.traceException(e); 342 } 343 } 344 345 /** {@inheritDoc} */ 346 @Override 347 public DN[] getBaseDNs() 348 { 349 return baseDNs; 350 } 351 352 /** {@inheritDoc} */ 353 @Override 354 public long getEntryCount() 355 { 356 int numEntries = 1; 357 358 try 359 { 360 String[] aliases = certificateManager.getCertificateAliases(); 361 if (aliases != null) 362 { 363 numEntries += aliases.length; 364 } 365 } 366 catch (KeyStoreException e) 367 { 368 logger.traceException(e); 369 } 370 371 return numEntries; 372 } 373 374 /** {@inheritDoc} */ 375 @Override 376 public boolean isIndexed(AttributeType attributeType, IndexType indexType) 377 { 378 // All searches in this backend will always be considered indexed. 379 return true; 380 } 381 382 /** {@inheritDoc} */ 383 @Override 384 public Entry getEntry(DN entryDN) throws DirectoryException 385 { 386 // If the requested entry was null, then throw an exception. 387 if (entryDN == null) 388 { 389 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 390 ERR_BACKEND_GET_ENTRY_NULL.get(getBackendID())); 391 } 392 393 394 // If the requested entry was the backend base entry, then retrieve it. 395 if (entryDN.equals(baseDN)) 396 { 397 return baseEntry.duplicate(true); 398 } 399 400 401 // See if the requested entry was one level below the backend base entry. 402 // If so, then it must point to a trust store entry. 403 DN parentDN = entryDN.getParentDNInSuffix(); 404 if (parentDN != null && parentDN.equals(baseDN)) 405 { 406 try 407 { 408 return getCertEntry(entryDN); 409 } 410 catch (DirectoryException e) 411 { 412 logger.traceException(e); 413 } 414 } 415 return null; 416 } 417 418 419 420 /** 421 * Generates an entry for a certificate based on the provided DN. The 422 * DN must contain an RDN component that specifies the alias of the 423 * certificate, and that certificate alias must exist in the key store. 424 * 425 * @param entryDN The DN of the certificate to retrieve. 426 * 427 * @return The requested certificate entry. 428 * 429 * @throws DirectoryException If the specified alias does not exist, or if 430 * the DN does not specify any alias. 431 */ 432 private Entry getCertEntry(DN entryDN) 433 throws DirectoryException 434 { 435 // Make sure that the DN specifies a certificate alias. 436 AttributeType t = DirectoryServer.getAttributeTypeOrDefault(ATTR_CRYPTO_KEY_ID); 437 ByteString v = entryDN.rdn().getAttributeValue(t); 438 if (v == null) 439 { 440 LocalizableMessage message = ERR_TRUSTSTORE_DN_DOES_NOT_SPECIFY_CERTIFICATE.get(entryDN); 441 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message, baseDN, null); 442 } 443 444 String certAlias = v.toString(); 445 ByteString certValue; 446 try 447 { 448 Certificate cert = certificateManager.getCertificate(certAlias); 449 if (cert == null) 450 { 451 LocalizableMessage message = ERR_TRUSTSTORE_CERTIFICATE_NOT_FOUND.get(entryDN, certAlias); 452 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 453 } 454 certValue = ByteString.wrap(cert.getEncoded()); 455 } 456 catch (Exception e) 457 { 458 logger.traceException(e); 459 460 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_RETRIEVE_CERT.get( 461 certAlias, trustStoreFile, e.getMessage()); 462 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 463 } 464 465 // Construct the certificate entry to return. 466 LinkedHashMap<ObjectClass,String> ocMap = new LinkedHashMap<>(2); 467 ocMap.put(DirectoryServer.getTopObjectClass(), OC_TOP); 468 469 ObjectClass objectClass = 470 DirectoryServer.getObjectClass(OC_CRYPTO_INSTANCE_KEY, true); 471 ocMap.put(objectClass, OC_CRYPTO_INSTANCE_KEY); 472 473 LinkedHashMap<AttributeType,List<Attribute>> opAttrs = new LinkedHashMap<>(0); 474 LinkedHashMap<AttributeType,List<Attribute>> userAttrs = new LinkedHashMap<>(3); 475 476 userAttrs.put(t, Attributes.createAsList(t, v)); 477 478 479 t = DirectoryServer.getAttributeTypeOrDefault(ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); 480 AttributeBuilder builder = new AttributeBuilder(t); 481 builder.setOption("binary"); 482 builder.add(certValue); 483 userAttrs.put(t, builder.toAttributeList()); 484 485 486 Entry e = new Entry(entryDN, ocMap, userAttrs, opAttrs); 487 e.processVirtualAttributes(); 488 return e; 489 } 490 491 /** {@inheritDoc} */ 492 @Override 493 public void addEntry(Entry entry, AddOperation addOperation) 494 throws DirectoryException 495 { 496 DN entryDN = entry.getName(); 497 498 if (entryDN.equals(baseDN)) 499 { 500 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(entryDN); 501 throw new DirectoryException(ResultCode.ENTRY_ALREADY_EXISTS, message); 502 } 503 504 DN parentDN = entryDN.getParentDNInSuffix(); 505 if (parentDN == null) 506 { 507 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(entryDN); 508 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 509 } 510 511 if (parentDN.equals(baseDN)) 512 { 513 addCertificate(entry); 514 } 515 else 516 { 517 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(entryDN); 518 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 519 } 520 } 521 522 /** {@inheritDoc} */ 523 @Override 524 public void deleteEntry(DN entryDN, DeleteOperation deleteOperation) 525 throws DirectoryException 526 { 527 if (entryDN.equals(baseDN)) 528 { 529 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(entryDN); 530 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 531 } 532 533 DN parentDN = entryDN.getParentDNInSuffix(); 534 if (parentDN == null || !parentDN.equals(baseDN)) 535 { 536 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(entryDN); 537 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 538 } 539 540 deleteCertificate(entryDN); 541 } 542 543 /** {@inheritDoc} */ 544 @Override 545 public void replaceEntry(Entry oldEntry, Entry newEntry, 546 ModifyOperation modifyOperation) throws DirectoryException 547 { 548 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 549 ERR_BACKEND_MODIFY_NOT_SUPPORTED.get(oldEntry.getName(), getBackendID())); 550 } 551 552 /** {@inheritDoc} */ 553 @Override 554 public void renameEntry(DN currentDN, Entry entry, 555 ModifyDNOperation modifyDNOperation) 556 throws DirectoryException 557 { 558 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 559 ERR_BACKEND_MODIFY_DN_NOT_SUPPORTED.get(currentDN, getBackendID())); 560 } 561 562 /** {@inheritDoc} */ 563 @Override 564 public void search(SearchOperation searchOperation) 565 throws DirectoryException 566 { 567 // Get the base entry for the search, if possible. If it doesn't exist, 568 // then this will throw an exception. 569 DN baseDN = searchOperation.getBaseDN(); 570 Entry baseEntry = getEntry(baseDN); 571 572 573 // Look at the base DN and see if it's the trust store base DN, or a 574 // trust store entry DN. 575 SearchScope scope = searchOperation.getScope(); 576 SearchFilter filter = searchOperation.getFilter(); 577 if (this.baseDN.equals(baseDN)) 578 { 579 if ((scope == SearchScope.BASE_OBJECT || scope == SearchScope.WHOLE_SUBTREE) 580 && filter.matchesEntry(baseEntry)) 581 { 582 searchOperation.returnEntry(baseEntry, null); 583 } 584 585 String[] aliases = null; 586 try 587 { 588 aliases = certificateManager.getCertificateAliases(); 589 } 590 catch (KeyStoreException e) 591 { 592 logger.traceException(e); 593 } 594 595 if (aliases == null) 596 { 597 aliases = new String[0]; 598 } 599 600 if (scope != SearchScope.BASE_OBJECT && aliases.length != 0) 601 { 602 AttributeType certAliasType = DirectoryServer.getAttributeTypeOrDefault(ATTR_CRYPTO_KEY_ID); 603 for (String alias : aliases) 604 { 605 DN certDN = makeChildDN(this.baseDN, certAliasType, alias); 606 607 Entry certEntry; 608 try 609 { 610 certEntry = getCertEntry(certDN); 611 } 612 catch (Exception e) 613 { 614 logger.traceException(e); 615 continue; 616 } 617 618 if (filter.matchesEntry(certEntry)) 619 { 620 searchOperation.returnEntry(certEntry, null); 621 } 622 } 623 } 624 } 625 else if (this.baseDN.equals(baseDN.getParentDNInSuffix())) 626 { 627 Entry certEntry = getCertEntry(baseDN); 628 629 if ((scope == SearchScope.BASE_OBJECT || scope == SearchScope.WHOLE_SUBTREE) 630 && filter.matchesEntry(certEntry)) 631 { 632 searchOperation.returnEntry(certEntry, null); 633 } 634 } 635 else 636 { 637 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(baseDN); 638 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 639 } 640 } 641 642 /** {@inheritDoc} */ 643 @Override 644 public Set<String> getSupportedControls() 645 { 646 return Collections.emptySet(); 647 } 648 649 /** {@inheritDoc} */ 650 @Override 651 public Set<String> getSupportedFeatures() 652 { 653 return Collections.emptySet(); 654 } 655 656 /** {@inheritDoc} */ 657 @Override 658 public boolean supports(BackendOperation backendOperation) 659 { 660 return false; 661 } 662 663 /** {@inheritDoc} */ 664 @Override 665 public void exportLDIF(LDIFExportConfig exportConfig) 666 throws DirectoryException 667 { 668 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 669 ERR_BACKEND_IMPORT_AND_EXPORT_NOT_SUPPORTED.get(getBackendID())); 670 } 671 672 /** {@inheritDoc} */ 673 @Override 674 public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) 675 throws DirectoryException 676 { 677 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 678 ERR_BACKEND_IMPORT_AND_EXPORT_NOT_SUPPORTED.get(getBackendID())); 679 } 680 681 /** {@inheritDoc} */ 682 @Override 683 public void createBackup(BackupConfig backupConfig) 684 throws DirectoryException 685 { 686 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 687 ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); 688 } 689 690 /** {@inheritDoc} */ 691 @Override 692 public void removeBackup(BackupDirectory backupDirectory, 693 String backupID) 694 throws DirectoryException 695 { 696 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 697 ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); 698 } 699 700 /** {@inheritDoc} */ 701 @Override 702 public void restoreBackup(RestoreConfig restoreConfig) 703 throws DirectoryException 704 { 705 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 706 ERR_BACKEND_BACKUP_AND_RESTORE_NOT_SUPPORTED.get(getBackendID())); 707 } 708 709 /** {@inheritDoc} */ 710 @Override 711 public ConditionResult hasSubordinates(DN entryDN) 712 throws DirectoryException 713 { 714 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, 715 ERR_HAS_SUBORDINATES_NOT_SUPPORTED.get()); 716 } 717 718 /** {@inheritDoc} */ 719 @Override 720 public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException 721 { 722 checkNotNull(baseDN, "baseDN must not be null"); 723 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, ERR_NUM_SUBORDINATES_NOT_SUPPORTED.get()); 724 } 725 726 /** {@inheritDoc} */ 727 @Override 728 public long getNumberOfChildren(DN parentDN) throws DirectoryException 729 { 730 checkNotNull(parentDN, "parentDN must not be null"); 731 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, ERR_NUM_SUBORDINATES_NOT_SUPPORTED.get()); 732 } 733 734 /** {@inheritDoc} */ 735 @Override 736 public boolean isConfigurationChangeAcceptable( 737 TrustStoreBackendCfg configuration, List<LocalizableMessage> unacceptableReasons) 738 { 739 boolean configAcceptable = true; 740 DN cfgEntryDN = configuration.dn(); 741 742 743 // Get the path to the trust store file. 744 String newTrustStoreFile = configuration.getTrustStoreFile(); 745 try 746 { 747 File f = getFileForPath(newTrustStoreFile); 748 if (!f.exists() || !f.isFile()) 749 { 750 unacceptableReasons.add(ERR_TRUSTSTORE_NO_SUCH_FILE.get(newTrustStoreFile, cfgEntryDN)); 751 configAcceptable = false; 752 } 753 } 754 catch (Exception e) 755 { 756 logger.traceException(e); 757 758 unacceptableReasons.add(ERR_TRUSTSTORE_CANNOT_DETERMINE_FILE.get(cfgEntryDN, getExceptionMessage(e))); 759 configAcceptable = false; 760 } 761 762 763 // Check to see if the trust store type is acceptable. 764 String storeType = configuration.getTrustStoreType(); 765 if (storeType != null) 766 { 767 try 768 { 769 KeyStore.getInstance(storeType); 770 } 771 catch (KeyStoreException kse) 772 { 773 logger.traceException(kse); 774 775 unacceptableReasons.add(ERR_TRUSTSTORE_INVALID_TYPE.get( 776 storeType, cfgEntryDN, getExceptionMessage(kse))); 777 configAcceptable = false; 778 } 779 } 780 781 782 // If there is a PIN property, then make sure the corresponding 783 // property is set. 784 String pinProp = configuration.getTrustStorePinProperty(); 785 if (pinProp != null && System.getProperty(pinProp) == null) 786 { 787 unacceptableReasons.add(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(pinProp, cfgEntryDN)); 788 configAcceptable = false; 789 } 790 791 792 // If there is a PIN environment variable, then make sure the corresponding 793 // environment variable is set. 794 String pinEnVar = configuration.getTrustStorePinEnvironmentVariable(); 795 if (pinEnVar != null && System.getenv(pinEnVar) == null) 796 { 797 unacceptableReasons.add(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(pinEnVar, cfgEntryDN)); 798 configAcceptable = false; 799 } 800 801 802 // If there is a PIN file, then make sure the file is readable if it exists. 803 String pinFile = configuration.getTrustStorePinFile(); 804 if (pinFile != null) 805 { 806 File f = new File(pinFile); 807 if (f.exists()) 808 { 809 String pinStr = null; 810 811 BufferedReader br = null; 812 try 813 { 814 br = new BufferedReader(new FileReader(pinFile)); 815 pinStr = br.readLine(); 816 } 817 catch (IOException ioe) 818 { 819 unacceptableReasons.add(ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ.get( 820 pinFile, cfgEntryDN, getExceptionMessage(ioe))); 821 configAcceptable = false; 822 } 823 finally 824 { 825 close(br); 826 } 827 828 if (pinStr == null) 829 { 830 unacceptableReasons.add(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(pinFile, cfgEntryDN)); 831 configAcceptable = false; 832 } 833 } 834 } 835 836 837 return configAcceptable; 838 } 839 840 /** {@inheritDoc} */ 841 @Override 842 public ConfigChangeResult applyConfigurationChange(TrustStoreBackendCfg cfg) 843 { 844 final ConfigChangeResult ccr = new ConfigChangeResult(); 845 DN configEntryDN = cfg.dn(); 846 847 // Get the path to the trust store file. 848 String newTrustStoreFile = cfg.getTrustStoreFile(); 849 File f = getFileForPath(newTrustStoreFile); 850 if (!f.exists() || !f.isFile()) 851 { 852 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 853 ccr.addMessage(ERR_TRUSTSTORE_NO_SUCH_FILE.get(newTrustStoreFile, configEntryDN)); 854 } 855 856 857 // Get the trust store type. If none is specified, then use the default 858 // type. 859 String newTrustStoreType = cfg.getTrustStoreType(); 860 if (newTrustStoreType == null) 861 { 862 newTrustStoreType = KeyStore.getDefaultType(); 863 } 864 865 try 866 { 867 KeyStore.getInstance(newTrustStoreType); 868 } 869 catch (KeyStoreException kse) 870 { 871 logger.traceException(kse); 872 873 ccr.addMessage(ERR_TRUSTSTORE_INVALID_TYPE.get(newTrustStoreType, configEntryDN, getExceptionMessage(kse))); 874 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 875 } 876 877 878 // Get the PIN needed to access the contents of the trust store file. We 879 // will offer several places to look for the PIN, and we will do so in the 880 // following order: 881 // - In a specified Java property 882 // - In a specified environment variable 883 // - In a specified file on the server filesystem. 884 // - As the value of a configuration attribute. 885 // In any case, the PIN must be in the clear. If no PIN is provided, then 886 // it will be assumed that none is required to access the information in the 887 // trust store. 888 char[] newPIN = null; 889 String newPINProperty = cfg.getTrustStorePinProperty(); 890 if (newPINProperty == null) 891 { 892 String newPINEnVar = cfg.getTrustStorePinEnvironmentVariable(); 893 if (newPINEnVar == null) 894 { 895 String newPINFile = cfg.getTrustStorePinFile(); 896 if (newPINFile == null) 897 { 898 String pinStr = cfg.getTrustStorePin(); 899 if (pinStr == null) 900 { 901 newPIN = null; 902 } 903 else 904 { 905 newPIN = pinStr.toCharArray(); 906 } 907 } 908 else 909 { 910 File pinFile = getFileForPath(newPINFile); 911 if (! pinFile.exists()) 912 { 913 try 914 { 915 // Generate a PIN. 916 newPIN = createKeystorePassword(); 917 918 // Store the PIN in the pin file. 919 createPINFile(pinFile.getPath(), new String(newPIN)); 920 } 921 catch (Exception e) 922 { 923 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 924 ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_CANNOT_CREATE.get(newPINFile, configEntryDN)); 925 } 926 } 927 else 928 { 929 String pinStr = null; 930 931 BufferedReader br = null; 932 try 933 { 934 br = new BufferedReader(new FileReader(pinFile)); 935 pinStr = br.readLine(); 936 } 937 catch (IOException ioe) 938 { 939 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 940 ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_CANNOT_READ.get( 941 newPINFile, configEntryDN, getExceptionMessage(ioe))); 942 } 943 finally 944 { 945 close(br); 946 } 947 948 if (pinStr == null) 949 { 950 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 951 ccr.addMessage(ERR_TRUSTSTORE_PIN_FILE_EMPTY.get(newPINFile, configEntryDN)); 952 } 953 else 954 { 955 newPIN = pinStr.toCharArray(); 956 } 957 } 958 } 959 } 960 else 961 { 962 String pinStr = System.getenv(newPINEnVar); 963 if (pinStr == null) 964 { 965 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 966 ccr.addMessage(ERR_TRUSTSTORE_PIN_ENVAR_NOT_SET.get(newPINEnVar, configEntryDN)); 967 } 968 else 969 { 970 newPIN = pinStr.toCharArray(); 971 } 972 } 973 } 974 else 975 { 976 String pinStr = System.getProperty(newPINProperty); 977 if (pinStr == null) 978 { 979 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 980 ccr.addMessage(ERR_TRUSTSTORE_PIN_PROPERTY_NOT_SET.get(newPINProperty, configEntryDN)); 981 } 982 else 983 { 984 newPIN = pinStr.toCharArray(); 985 } 986 } 987 988 989 if (ccr.getResultCode() == ResultCode.SUCCESS) 990 { 991 trustStoreFile = newTrustStoreFile; 992 trustStoreType = newTrustStoreType; 993 trustStorePIN = newPIN; 994 configuration = cfg; 995 certificateManager = 996 new CertificateManager(getFileForPath(trustStoreFile).getPath(), 997 trustStoreType, 998 new String(trustStorePIN)); 999 } 1000 1001 return ccr; 1002 } 1003 1004 /** 1005 * Create a new child DN from a given parent DN. The child RDN is formed 1006 * from a given attribute type and string value. 1007 * @param parentDN The DN of the parent. 1008 * @param rdnAttrType The attribute type of the RDN. 1009 * @param rdnStringValue The string value of the RDN. 1010 * @return A new child DN. 1011 */ 1012 public static DN makeChildDN(DN parentDN, AttributeType rdnAttrType, 1013 String rdnStringValue) 1014 { 1015 ByteString attrValue = ByteString.valueOf(rdnStringValue); 1016 return parentDN.child(RDN.create(rdnAttrType, attrValue)); 1017 } 1018 1019 1020 /** 1021 * Retrieves a set of <CODE>KeyManager</CODE> objects that may be used for 1022 * interactions requiring access to a key manager. 1023 * 1024 * @return A set of <CODE>KeyManager</CODE> objects that may be used for 1025 * interactions requiring access to a key manager. 1026 * 1027 * @throws DirectoryException If a problem occurs while attempting to obtain 1028 * the set of key managers. 1029 */ 1030 public KeyManager[] getKeyManagers() 1031 throws DirectoryException 1032 { 1033 KeyStore keyStore; 1034 FileInputStream inputStream = null; 1035 try 1036 { 1037 keyStore = KeyStore.getInstance(trustStoreType); 1038 1039 inputStream = 1040 new FileInputStream(getFileForPath(trustStoreFile)); 1041 keyStore.load(inputStream, trustStorePIN); 1042 } 1043 catch (Exception e) 1044 { 1045 logger.traceException(e); 1046 1047 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get( 1048 trustStoreFile, getExceptionMessage(e)); 1049 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 1050 message, e); 1051 } 1052 finally 1053 { 1054 close(inputStream); 1055 } 1056 1057 1058 try 1059 { 1060 String keyManagerAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); 1061 KeyManagerFactory keyManagerFactory = 1062 KeyManagerFactory.getInstance(keyManagerAlgorithm); 1063 keyManagerFactory.init(keyStore, trustStorePIN); 1064 return keyManagerFactory.getKeyManagers(); 1065 } 1066 catch (Exception e) 1067 { 1068 logger.traceException(e); 1069 1070 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_CREATE_FACTORY.get( 1071 trustStoreFile, getExceptionMessage(e)); 1072 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 1073 message, e); 1074 } 1075 } 1076 1077 1078 /** 1079 * Retrieves a set of {@code TrustManager} objects that may be used 1080 * for interactions requiring access to a trust manager. 1081 * 1082 * @return A set of {@code TrustManager} objects that may be used 1083 * for interactions requiring access to a trust manager. 1084 * 1085 * @throws DirectoryException If a problem occurs while attempting 1086 * to obtain the set of trust managers. 1087 */ 1088 public TrustManager[] getTrustManagers() 1089 throws DirectoryException 1090 { 1091 KeyStore trustStore; 1092 FileInputStream inputStream = null; 1093 try 1094 { 1095 trustStore = KeyStore.getInstance(trustStoreType); 1096 1097 inputStream = 1098 new FileInputStream(getFileForPath(trustStoreFile)); 1099 trustStore.load(inputStream, trustStorePIN); 1100 } 1101 catch (Exception e) 1102 { 1103 logger.traceException(e); 1104 1105 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get( 1106 trustStoreFile, getExceptionMessage(e)); 1107 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 1108 message, e); 1109 } 1110 finally 1111 { 1112 close(inputStream); 1113 } 1114 1115 1116 try 1117 { 1118 String trustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 1119 TrustManagerFactory trustManagerFactory = 1120 TrustManagerFactory.getInstance(trustManagerAlgorithm); 1121 trustManagerFactory.init(trustStore); 1122 return trustManagerFactory.getTrustManagers(); 1123 } 1124 catch (Exception e) 1125 { 1126 logger.traceException(e); 1127 1128 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_CREATE_FACTORY.get( 1129 trustStoreFile, getExceptionMessage(e)); 1130 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 1131 message, e); 1132 } 1133 } 1134 1135 1136 /** 1137 * Returns the key associated with the given alias, using the trust 1138 * store pin to recover it. 1139 * 1140 * @param alias The alias name. 1141 * 1142 * @return The requested key, or null if the given alias does not exist 1143 * or does not identify a key-related entry. 1144 * 1145 * @throws DirectoryException If an error occurs while retrieving the key. 1146 */ 1147 public Key getKey(String alias) 1148 throws DirectoryException 1149 { 1150 KeyStore trustStore; 1151 FileInputStream inputStream = null; 1152 try 1153 { 1154 trustStore = KeyStore.getInstance(trustStoreType); 1155 1156 inputStream = 1157 new FileInputStream(getFileForPath(trustStoreFile)); 1158 trustStore.load(inputStream, trustStorePIN); 1159 } 1160 catch (Exception e) 1161 { 1162 logger.traceException(e); 1163 1164 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_LOAD.get( 1165 trustStoreFile, getExceptionMessage(e)); 1166 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 1167 message, e); 1168 } 1169 finally 1170 { 1171 close(inputStream); 1172 } 1173 1174 try 1175 { 1176 return trustStore.getKey(alias, trustStorePIN); 1177 } 1178 catch (Exception e) 1179 { 1180 logger.traceException(e); 1181 1182 LocalizableMessage message = ERR_TRUSTSTORE_ERROR_READING_KEY.get( 1183 alias, trustStoreFile, getExceptionMessage(e)); 1184 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 1185 message, e); 1186 } 1187 } 1188 1189 1190 private void addCertificate(Entry entry) 1191 throws DirectoryException 1192 { 1193 DN entryDN = entry.getName(); 1194 1195 // Make sure that the DN specifies a certificate alias. 1196 AttributeType t = DirectoryServer.getAttributeTypeOrDefault(ATTR_CRYPTO_KEY_ID); 1197 ByteString v = entryDN.rdn().getAttributeValue(t); 1198 if (v == null) 1199 { 1200 LocalizableMessage message = ERR_TRUSTSTORE_DN_DOES_NOT_SPECIFY_CERTIFICATE.get(entryDN); 1201 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message, baseDN, null); 1202 } 1203 1204 String certAlias = v.toString(); 1205 try 1206 { 1207 if (certificateManager.aliasInUse(certAlias)) 1208 { 1209 LocalizableMessage message = ERR_TRUSTSTORE_ALIAS_IN_USE.get(entryDN); 1210 throw new DirectoryException(ResultCode.ENTRY_ALREADY_EXISTS, message); 1211 } 1212 1213 ObjectClass ocSelfSignedCertRequest = 1214 DirectoryServer.getObjectClass(OC_SELF_SIGNED_CERT_REQUEST, true); 1215 if (entry.hasObjectClass(ocSelfSignedCertRequest)) 1216 { 1217 try 1218 { 1219 certificateManager.generateSelfSignedCertificate( 1220 certAlias, 1221 getADSCertificateSubjectDN(), 1222 getADSCertificateValidity()); 1223 } 1224 catch (Exception e) 1225 { 1226 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_GENERATE_CERT.get( 1227 certAlias, trustStoreFile, getExceptionMessage(e)); 1228 throw new DirectoryException( 1229 DirectoryServer.getServerErrorResultCode(), message, e); 1230 } 1231 } 1232 else 1233 { 1234 List<Attribute> certAttrs = entry.getAttribute( 1235 ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); 1236 if (certAttrs == null) 1237 { 1238 LocalizableMessage message = 1239 ERR_TRUSTSTORE_ENTRY_MISSING_CERT_ATTR.get(entryDN, ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); 1240 throw new DirectoryException( 1241 DirectoryServer.getServerErrorResultCode(), message); 1242 } 1243 if (certAttrs.size() != 1) 1244 { 1245 LocalizableMessage message = 1246 ERR_TRUSTSTORE_ENTRY_HAS_MULTIPLE_CERT_ATTRS.get(entryDN, ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); 1247 throw new DirectoryException( 1248 DirectoryServer.getServerErrorResultCode(), message); 1249 } 1250 1251 Attribute certAttr = certAttrs.get(0); 1252 Iterator<ByteString> i = certAttr.iterator(); 1253 1254 if (!i.hasNext()) 1255 { 1256 LocalizableMessage message = 1257 ERR_TRUSTSTORE_ENTRY_MISSING_CERT_VALUE.get(entryDN, ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); 1258 throw new DirectoryException( 1259 DirectoryServer.getServerErrorResultCode(), message); 1260 } 1261 1262 ByteString certBytes = i.next(); 1263 1264 if (i.hasNext()) 1265 { 1266 LocalizableMessage message = 1267 ERR_TRUSTSTORE_ENTRY_HAS_MULTIPLE_CERT_VALUES.get(entryDN, ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE); 1268 throw new DirectoryException( 1269 DirectoryServer.getServerErrorResultCode(), message); 1270 } 1271 1272 try 1273 { 1274 File tempDir = getFileForPath("config"); 1275 File tempFile = File.createTempFile(configuration.getBackendId(), 1276 certAlias, tempDir); 1277 try 1278 { 1279 FileOutputStream outputStream = 1280 new FileOutputStream(tempFile.getPath(), false); 1281 try 1282 { 1283 certBytes.copyTo(outputStream); 1284 } 1285 finally 1286 { 1287 outputStream.close(); 1288 } 1289 1290 certificateManager.addCertificate(certAlias, tempFile); 1291 } 1292 finally 1293 { 1294 tempFile.delete(); 1295 } 1296 } 1297 catch (IOException e) 1298 { 1299 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_WRITE_CERT.get( 1300 certAlias, getExceptionMessage(e)); 1301 throw new DirectoryException( 1302 DirectoryServer.getServerErrorResultCode(), message, e); 1303 } 1304 } 1305 } 1306 catch (Exception e) 1307 { 1308 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_ADD_CERT.get( 1309 certAlias, trustStoreFile, getExceptionMessage(e)); 1310 throw new DirectoryException( 1311 DirectoryServer.getServerErrorResultCode(), message, e); 1312 } 1313 1314 } 1315 1316 1317 private void deleteCertificate(DN entryDN) 1318 throws DirectoryException 1319 { 1320 // Make sure that the DN specifies a certificate alias. 1321 AttributeType t = DirectoryServer.getAttributeTypeOrDefault(ATTR_CRYPTO_KEY_ID); 1322 ByteString v = entryDN.rdn().getAttributeValue(t); 1323 if (v == null) 1324 { 1325 LocalizableMessage message = ERR_TRUSTSTORE_DN_DOES_NOT_SPECIFY_CERTIFICATE.get(entryDN); 1326 throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message, baseDN, null); 1327 } 1328 1329 String certAlias = v.toString(); 1330 try 1331 { 1332 if (!certificateManager.aliasInUse(certAlias)) 1333 { 1334 LocalizableMessage message = ERR_TRUSTSTORE_INVALID_BASE.get(entryDN); 1335 throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message); 1336 } 1337 1338 certificateManager.removeCertificate(certAlias); 1339 } 1340 catch (Exception e) 1341 { 1342 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_DELETE_CERT.get( 1343 certAlias, trustStoreFile, getExceptionMessage(e)); 1344 throw new DirectoryException( 1345 DirectoryServer.getServerErrorResultCode(), message, e); 1346 } 1347 } 1348 1349 1350 /** 1351 * Returns the validity period to be used to generate the ADS certificate. 1352 * @return The validity period to be used to generate the ADS certificate. 1353 */ 1354 private static int getADSCertificateValidity() 1355 { 1356 return 20 * 365; 1357 } 1358 1359 /** 1360 * Returns the Subject DN to be used to generate the ADS certificate. 1361 * @return The Subject DN to be used to generate the ADS certificate. 1362 * @throws java.net.UnknownHostException If the server host name could not be 1363 * determined. 1364 */ 1365 private static String getADSCertificateSubjectDN() 1366 throws UnknownHostException 1367 { 1368 String hostName = 1369 SetupUtils.getHostNameForCertificate(DirectoryServer.getServerRoot()); 1370 return "cn=" + Rdn.escapeValue(hostName) + ",O=OpenDJ Certificate"; 1371 } 1372 1373 /** 1374 * Create a randomly generated password for a certificate keystore. 1375 * @return A randomly generated password for a certificate keystore. 1376 */ 1377 private static char[] createKeystorePassword() { 1378 int pwdLength = 50; 1379 char[] pwd = new char[pwdLength]; 1380 Random random = new Random(); 1381 for (int pos=0; pos < pwdLength; pos++) { 1382 int type = getRandomInt(random,3); 1383 char nextChar = getRandomChar(random,type); 1384 pwd[pos] = nextChar; 1385 } 1386 return pwd; 1387 } 1388 1389 private static char getRandomChar(Random random, int type) 1390 { 1391 char generatedChar; 1392 int next = random.nextInt(); 1393 int d; 1394 1395 switch (type) 1396 { 1397 case 0: 1398 // Will return a digit 1399 d = next % 10; 1400 if (d < 0) 1401 { 1402 d = d * -1; 1403 } 1404 generatedChar = (char) (d+48); 1405 break; 1406 case 1: 1407 // Will return a lower case letter 1408 d = next % 26; 1409 if (d < 0) 1410 { 1411 d = d * -1; 1412 } 1413 generatedChar = (char) (d + 97); 1414 break; 1415 default: 1416 // Will return a capital letter 1417 d = next % 26; 1418 if (d < 0) 1419 { 1420 d = d * -1; 1421 } 1422 generatedChar = (char) (d + 65) ; 1423 } 1424 1425 return generatedChar; 1426 } 1427 1428 private static int getRandomInt(Random random,int modulo) 1429 { 1430 return random.nextInt() & modulo; 1431 } 1432 1433 /** 1434 * Creates a PIN file on the specified path. 1435 * @param path the path where the PIN file will be created. 1436 * @param pin The PIN to store in the file. 1437 * @throws IOException if something goes wrong. 1438 */ 1439 public static void createPINFile(String path, String pin) 1440 throws IOException 1441 { 1442 FileWriter file = new FileWriter(path); 1443 PrintWriter out = new PrintWriter(file); 1444 1445 out.println(pin); 1446 1447 out.flush(); 1448 out.close(); 1449 1450 try { 1451 if (!FilePermission.setPermissions(new File(path), 1452 new FilePermission(0600))) 1453 { 1454 // Log a warning that the permissions were not set. 1455 logger.warn(WARN_TRUSTSTORE_SET_PERMISSIONS_FAILED, path); 1456 } 1457 } catch(DirectoryException e) { 1458 // Log a warning that the permissions were not set. 1459 logger.warn(WARN_TRUSTSTORE_SET_PERMISSIONS_FAILED, path); 1460 } 1461 } 1462 1463 /** 1464 * Generates a self-signed certificate with well-known alias if there is none. 1465 * @throws InitializationException If an error occurs while interacting with 1466 * the key store. 1467 */ 1468 private void generateInstanceCertificateIfAbsent() 1469 throws InitializationException 1470 { 1471 String certAlias = ADS_CERTIFICATE_ALIAS; 1472 1473 try 1474 { 1475 if (certificateManager.aliasInUse(certAlias)) 1476 { 1477 return; 1478 } 1479 } 1480 catch (Exception e) 1481 { 1482 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_ADD_CERT.get( 1483 certAlias, trustStoreFile, getExceptionMessage(e)); 1484 throw new InitializationException(message, e); 1485 } 1486 1487 try 1488 { 1489 certificateManager.generateSelfSignedCertificate( 1490 certAlias, 1491 getADSCertificateSubjectDN(), 1492 getADSCertificateValidity()); 1493 } 1494 catch (Exception e) 1495 { 1496 LocalizableMessage message = ERR_TRUSTSTORE_CANNOT_GENERATE_CERT.get( 1497 certAlias, trustStoreFile, getExceptionMessage(e)); 1498 throw new InitializationException(message, e); 1499 } 1500 1501 } 1502} 1503