001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.server.core; 018 019import java.util.*; 020 021import org.forgerock.i18n.LocalizableMessage; 022import org.forgerock.opendj.config.server.ConfigChangeResult; 023import org.forgerock.opendj.config.server.ConfigException; 024import org.forgerock.opendj.ldap.DN; 025import org.forgerock.opendj.ldap.ResultCode; 026import org.forgerock.opendj.config.server.ConfigurationChangeListener; 027import org.forgerock.opendj.server.config.meta.GlobalCfgDefn; 028import org.forgerock.opendj.server.config.meta.GlobalCfgDefn.DisabledPrivilege; 029import org.forgerock.opendj.server.config.meta.GlobalCfgDefn.InvalidAttributeSyntaxBehavior; 030import org.forgerock.opendj.server.config.meta.GlobalCfgDefn.SingleStructuralObjectclassBehavior; 031import org.forgerock.opendj.server.config.server.GlobalCfg; 032import org.opends.server.api.AuthenticationPolicy; 033import org.opends.server.loggers.CommonAudit; 034import org.opends.server.types.*; 035 036import static org.forgerock.opendj.ldap.schema.SchemaOptions.*; 037import static org.opends.messages.ConfigMessages.*; 038import static org.opends.server.core.DirectoryServer.*; 039import static org.opends.server.util.ServerConstants.*; 040 041/** 042 * This class defines a utility that will be used to manage the set of core 043 * configuration attributes defined in the Directory Server. These 044 * configuration attributes appear in the "cn=config" configuration entry. 045 */ 046public class CoreConfigManager 047 implements ConfigurationChangeListener<GlobalCfg> 048{ 049 private final ServerContext serverContext; 050 051 /** 052 * Creates a new instance of this core config manager. 053 * 054 * @param serverContext 055 * The server context. 056 */ 057 public CoreConfigManager(ServerContext serverContext) 058 { 059 this.serverContext = serverContext; 060 } 061 062 /** 063 * Initializes the Directory Server's core configuration. This should only be 064 * called at server startup. 065 * 066 * @throws ConfigException 067 * If a configuration problem causes the identity mapper 068 * initialization process to fail. 069 * @throws InitializationException 070 * If a problem occurs while initializing the identity mappers that 071 * is not related to the server configuration. 072 */ 073 public void initializeCoreConfig() 074 throws ConfigException, InitializationException 075 { 076 GlobalCfg globalConfig = serverContext.getRootConfig().getGlobalConfiguration(); 077 globalConfig.addChangeListener(this); 078 079 080 // Validate any specified SMTP servers 081 Set<String> smtpServers = globalConfig.getSMTPServer(); 082 if (smtpServers != null) 083 { 084 for (String server : smtpServers) 085 { 086 try 087 { 088 HostPort.valueOf(server, SMTP_DEFAULT_PORT); 089 } 090 catch (RuntimeException e) 091 { 092 LocalizableMessage message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server); 093 throw new ConfigException(message, e); 094 } 095 } 096 } 097 098 applyGlobalConfiguration(globalConfig, serverContext); 099 } 100 101 /** 102 * Applies the settings in the provided configuration to the Directory Server. 103 * 104 * @param globalConfig The configuration settings to be applied. 105 */ 106 private static void applyGlobalConfiguration(final GlobalCfg globalConfig, final ServerContext serverContext) 107 throws ConfigException 108 { 109 setCheckSchema(globalConfig.isCheckSchema()); 110 setDefaultPasswordPolicyDN(globalConfig.getDefaultPasswordPolicyDN()); 111 setAddMissingRDNAttributes(globalConfig.isAddMissingRDNAttributes()); 112 setAllowAttributeNameExceptions(globalConfig.isAllowAttributeNameExceptions()); 113 setSyntaxEnforcementPolicy(convert(globalConfig.getInvalidAttributeSyntaxBehavior())); 114 setServerErrorResultCode(ResultCode.valueOf(globalConfig.getServerErrorResultCode())); 115 setSingleStructuralObjectClassPolicy(convert(globalConfig.getSingleStructuralObjectclassBehavior())); 116 117 setNotifyAbandonedOperations(globalConfig.isNotifyAbandonedOperations()); 118 setSizeLimit(globalConfig.getSizeLimit()); 119 setTimeLimit((int) globalConfig.getTimeLimit()); 120 setProxiedAuthorizationIdentityMapperDN(globalConfig.getProxiedAuthorizationIdentityMapperDN()); 121 setWritabilityMode(convert(globalConfig.getWritabilityMode())); 122 setRejectUnauthenticatedRequests(globalConfig.isRejectUnauthenticatedRequests()); 123 setBindWithDNRequiresPassword(globalConfig.isBindWithDNRequiresPassword()); 124 setLookthroughLimit(globalConfig.getLookthroughLimit()); 125 126 setMailServerPropertySets(getMailServerProperties(globalConfig.getSMTPServer())); 127 setAllowedTasks(globalConfig.getAllowedTask()); 128 setDisabledPrivileges(convert(globalConfig.getDisabledPrivilege())); 129 setReturnBindErrorMessages(globalConfig.isReturnBindErrorMessages()); 130 setIdleTimeLimit(globalConfig.getIdleTimeLimit()); 131 setSaveConfigOnSuccessfulStartup(globalConfig.isSaveConfigOnSuccessfulStartup()); 132 133 setUseNanoTime(globalConfig.getEtimeResolution() == GlobalCfgDefn.EtimeResolution.NANOSECONDS); 134 setMaxAllowedConnections(globalConfig.getMaxAllowedClientConnections()); 135 setMaxPersistentSearchLimit(globalConfig.getMaxPsearches()); 136 setMaxInternalBufferSize((int) globalConfig.getMaxInternalBufferSize()); 137 138 // For tools, common audit may not be available 139 CommonAudit commonAudit = serverContext.getCommonAudit(); 140 if (commonAudit != null) 141 { 142 commonAudit.setTrustTransactionIds(globalConfig.isTrustTransactionIds()); 143 } 144 145 // Update the "new" schema with configuration changes if necessary 146 try 147 { 148 final boolean allowMalformedNames = globalConfig.isAllowAttributeNameExceptions(); 149 serverContext.getSchema().updateSchemaOption(ALLOW_MALFORMED_NAMES_AND_OPTIONS, allowMalformedNames); 150 } 151 catch (DirectoryException e) 152 { 153 throw new ConfigException(e.getMessageObject(), e); 154 } 155 } 156 157 private static AcceptRejectWarn convert(InvalidAttributeSyntaxBehavior invalidAttributeSyntaxBehavior) 158 { 159 switch (invalidAttributeSyntaxBehavior) 160 { 161 case ACCEPT: 162 return AcceptRejectWarn.ACCEPT; 163 case WARN: 164 return AcceptRejectWarn.WARN; 165 case REJECT: 166 default: 167 return AcceptRejectWarn.REJECT; 168 } 169 } 170 171 private static AcceptRejectWarn convert(SingleStructuralObjectclassBehavior singleStructuralObjectclassBehavior) 172 { 173 switch (singleStructuralObjectclassBehavior) 174 { 175 case ACCEPT: 176 return AcceptRejectWarn.ACCEPT; 177 case WARN: 178 return AcceptRejectWarn.WARN; 179 case REJECT: 180 default: 181 return AcceptRejectWarn.REJECT; 182 } 183 } 184 185 private static WritabilityMode convert(GlobalCfgDefn.WritabilityMode writabilityMode) 186 { 187 switch (writabilityMode) 188 { 189 case ENABLED: 190 return WritabilityMode.ENABLED; 191 case INTERNAL_ONLY: 192 return WritabilityMode.INTERNAL_ONLY; 193 case DISABLED: 194 default: 195 return WritabilityMode.DISABLED; 196 } 197 } 198 199 private static List<Properties> getMailServerProperties(Set<String> smtpServers) 200 { 201 List<Properties> mailServerProperties = new ArrayList<>(); 202 if (smtpServers != null && !smtpServers.isEmpty()) 203 { 204 for (String smtpServer : smtpServers) 205 { 206 final Properties properties = new Properties(); 207 try 208 { 209 final HostPort hp = HostPort.valueOf(smtpServer, SMTP_DEFAULT_PORT); 210 211 properties.setProperty(SMTP_PROPERTY_HOST, hp.getHost()); 212 properties.setProperty(SMTP_PROPERTY_PORT, 213 String.valueOf(hp.getPort())); 214 properties.setProperty(SMTP_PROPERTY_CONNECTION_TIMEOUT, 215 SMTP_DEFAULT_TIMEOUT_VALUE); 216 properties.setProperty(SMTP_PROPERTY_IO_TIMEOUT, 217 SMTP_DEFAULT_TIMEOUT_VALUE); 218 } 219 catch (RuntimeException e) 220 { 221 // no valid port provided 222 properties.setProperty(SMTP_PROPERTY_HOST, smtpServer); 223 } 224 mailServerProperties.add(properties); 225 } 226 } 227 return mailServerProperties; 228 } 229 230 private static HashSet<Privilege> convert(Set<DisabledPrivilege> configuredDisabledPrivs) 231 { 232 HashSet<Privilege> disabledPrivileges = new HashSet<>(); 233 if (configuredDisabledPrivs != null) 234 { 235 for (DisabledPrivilege p : configuredDisabledPrivs) 236 { 237 final Privilege privilege = convert(p); 238 if (privilege != null) 239 { 240 disabledPrivileges.add(privilege); 241 } 242 } 243 } 244 return disabledPrivileges; 245 } 246 247 private static Privilege convert(DisabledPrivilege privilege) 248 { 249 switch (privilege) 250 { 251 case BACKEND_BACKUP: 252 return Privilege.BACKEND_BACKUP; 253 case BACKEND_RESTORE: 254 return Privilege.BACKEND_RESTORE; 255 case BYPASS_ACL: 256 return Privilege.BYPASS_ACL; 257 case CANCEL_REQUEST: 258 return Privilege.CANCEL_REQUEST; 259 case CONFIG_READ: 260 return Privilege.CONFIG_READ; 261 case CONFIG_WRITE: 262 return Privilege.CONFIG_WRITE; 263 case DATA_SYNC: 264 return Privilege.DATA_SYNC; 265 case DISCONNECT_CLIENT: 266 return Privilege.DISCONNECT_CLIENT; 267 case JMX_NOTIFY: 268 return Privilege.JMX_NOTIFY; 269 case JMX_READ: 270 return Privilege.JMX_READ; 271 case JMX_WRITE: 272 return Privilege.JMX_WRITE; 273 case LDIF_EXPORT: 274 return Privilege.LDIF_EXPORT; 275 case LDIF_IMPORT: 276 return Privilege.LDIF_IMPORT; 277 case MODIFY_ACL: 278 return Privilege.MODIFY_ACL; 279 case PASSWORD_RESET: 280 return Privilege.PASSWORD_RESET; 281 case PRIVILEGE_CHANGE: 282 return Privilege.PRIVILEGE_CHANGE; 283 case PROXIED_AUTH: 284 return Privilege.PROXIED_AUTH; 285 case SERVER_RESTART: 286 return Privilege.SERVER_RESTART; 287 case SERVER_SHUTDOWN: 288 return Privilege.SERVER_SHUTDOWN; 289 case UNINDEXED_SEARCH: 290 return Privilege.UNINDEXED_SEARCH; 291 case UPDATE_SCHEMA: 292 return Privilege.UPDATE_SCHEMA; 293 case SUBENTRY_WRITE: 294 return Privilege.SUBENTRY_WRITE; 295 default: 296 return null; 297 } 298 } 299 300 @Override 301 public boolean isConfigurationChangeAcceptable(GlobalCfg configuration, 302 List<LocalizableMessage> unacceptableReasons) 303 { 304 boolean configAcceptable = true; 305 306 Set<String> smtpServers = configuration.getSMTPServer(); 307 if (smtpServers != null) 308 { 309 for (String server : smtpServers) 310 { 311 try 312 { 313 // validate provided string 314 HostPort.valueOf(server, SMTP_DEFAULT_PORT); 315 } 316 catch (RuntimeException e) 317 { 318 unacceptableReasons.add(ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server)); 319 configAcceptable = false; 320 } 321 } 322 } 323 324 // Ensure that the default password policy always points to a password 325 // policy and not another type of authentication policy. 326 DN defaultPasswordPolicyDN = configuration.getDefaultPasswordPolicyDN(); 327 AuthenticationPolicy policy = DirectoryServer 328 .getAuthenticationPolicy(defaultPasswordPolicyDN); 329 if (!policy.isPasswordPolicy()) 330 { 331 LocalizableMessage message = 332 ERR_CONFIG_PWPOLICY_CANNOT_CHANGE_DEFAULT_POLICY_WRONG_TYPE 333 .get(configuration.getDefaultPasswordPolicy()); 334 unacceptableReasons.add(message); 335 configAcceptable = false; 336 } 337 338 return configAcceptable; 339 } 340 341 @Override 342 public ConfigChangeResult applyConfigurationChange(GlobalCfg configuration) 343 { 344 final ConfigChangeResult ccr = new ConfigChangeResult(); 345 try 346 { 347 applyGlobalConfiguration(configuration, serverContext); 348 } 349 catch (ConfigException e) 350 { 351 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 352 ccr.addMessage(e.getMessageObject()); 353 } 354 return ccr; 355 } 356}