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