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 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS. 026 */ 027package org.opends.server.core; 028 029import java.util.*; 030 031import org.forgerock.i18n.LocalizableMessage; 032import org.forgerock.opendj.config.server.ConfigChangeResult; 033import org.forgerock.opendj.config.server.ConfigException; 034import org.forgerock.opendj.ldap.ResultCode; 035import org.forgerock.opendj.ldap.schema.Schema; 036import org.forgerock.opendj.ldap.schema.SchemaBuilder; 037import org.forgerock.opendj.ldap.schema.SchemaOptions; 038import org.opends.server.admin.server.ConfigurationChangeListener; 039import org.opends.server.admin.server.ServerManagementContext; 040import org.opends.server.admin.std.meta.GlobalCfgDefn; 041import org.opends.server.admin.std.meta.GlobalCfgDefn.DisabledPrivilege; 042import org.opends.server.admin.std.meta.GlobalCfgDefn.InvalidAttributeSyntaxBehavior; 043import org.opends.server.admin.std.meta.GlobalCfgDefn.SingleStructuralObjectclassBehavior; 044import org.opends.server.admin.std.server.GlobalCfg; 045import org.opends.server.admin.std.server.RootCfg; 046import org.opends.server.api.AuthenticationPolicy; 047import org.opends.server.schema.SchemaUpdater; 048import org.opends.server.types.*; 049 050import static org.opends.messages.ConfigMessages.*; 051import static org.opends.server.core.DirectoryServer.*; 052import static org.opends.server.util.ServerConstants.*; 053 054/** 055 * This class defines a utility that will be used to manage the set of core 056 * configuration attributes defined in the Directory Server. These 057 * configuration attributes appear in the "cn=config" configuration entry. 058 */ 059public class CoreConfigManager 060 implements ConfigurationChangeListener<GlobalCfg> 061{ 062 private final ServerContext serverContext; 063 064 /** 065 * Creates a new instance of this core config manager. 066 * 067 * @param serverContext 068 * The server context. 069 */ 070 public CoreConfigManager(ServerContext serverContext) 071 { 072 this.serverContext = serverContext; 073 } 074 075 /** 076 * Initializes the Directory Server's core configuration. This should only be 077 * called at server startup. 078 * 079 * @throws ConfigException 080 * If a configuration problem causes the identity mapper 081 * initialization process to fail. 082 * @throws InitializationException 083 * If a problem occurs while initializing the identity mappers that 084 * is not related to the server configuration. 085 */ 086 public void initializeCoreConfig() 087 throws ConfigException, InitializationException 088 { 089 // Get the root configuration object. 090 ServerManagementContext managementContext = 091 ServerManagementContext.getInstance(); 092 RootCfg rootConfiguration = 093 managementContext.getRootConfiguration(); 094 095 096 // Get the global configuration and register with it as a change listener. 097 GlobalCfg globalConfig = rootConfiguration.getGlobalConfiguration(); 098 globalConfig.addChangeListener(this); 099 100 101 // If there are any STMP servers specified, then make sure that if the value 102 // contains a colon that the portion after it is an integer between 1 and 103 // 65535. 104 Set<String> smtpServers = globalConfig.getSMTPServer(); 105 if (smtpServers != null) 106 { 107 for (String server : smtpServers) 108 { 109 try 110 { 111 // validate provided string 112 HostPort.valueOf(server); 113 } 114 catch (RuntimeException e) 115 { 116 LocalizableMessage message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server); 117 throw new ConfigException(message, e); 118 } 119 } 120 } 121 122 123 // Apply the configuration to the server. 124 applyGlobalConfiguration(globalConfig, serverContext); 125 } 126 127 128 129 /** 130 * Applies the settings in the provided configuration to the Directory Server. 131 * 132 * @param globalConfig The configuration settings to be applied. 133 */ 134 private static void applyGlobalConfiguration(GlobalCfg globalConfig, ServerContext serverContext) 135 { 136 setCheckSchema(globalConfig.isCheckSchema()); 137 setDefaultPasswordPolicyDN(globalConfig.getDefaultPasswordPolicyDN()); 138 setAddMissingRDNAttributes(globalConfig.isAddMissingRDNAttributes()); 139 setAllowAttributeNameExceptions(globalConfig.isAllowAttributeNameExceptions()); 140 setSyntaxEnforcementPolicy(convert(globalConfig.getInvalidAttributeSyntaxBehavior())); 141 setServerErrorResultCode(ResultCode.valueOf(globalConfig.getServerErrorResultCode())); 142 setSingleStructuralObjectClassPolicy(convert(globalConfig.getSingleStructuralObjectclassBehavior())); 143 144 setNotifyAbandonedOperations(globalConfig.isNotifyAbandonedOperations()); 145 setSizeLimit(globalConfig.getSizeLimit()); 146 setTimeLimit((int) globalConfig.getTimeLimit()); 147 setProxiedAuthorizationIdentityMapperDN(globalConfig.getProxiedAuthorizationIdentityMapperDN()); 148 setWritabilityMode(convert(globalConfig.getWritabilityMode())); 149 setRejectUnauthenticatedRequests(globalConfig.isRejectUnauthenticatedRequests()); 150 setBindWithDNRequiresPassword(globalConfig.isBindWithDNRequiresPassword()); 151 setLookthroughLimit(globalConfig.getLookthroughLimit()); 152 153 setMailServerPropertySets(getMailServerProperties(globalConfig.getSMTPServer())); 154 setAllowedTasks(globalConfig.getAllowedTask()); 155 setDisabledPrivileges(convert(globalConfig.getDisabledPrivilege())); 156 setReturnBindErrorMessages(globalConfig.isReturnBindErrorMessages()); 157 setIdleTimeLimit(globalConfig.getIdleTimeLimit()); 158 setSaveConfigOnSuccessfulStartup(globalConfig.isSaveConfigOnSuccessfulStartup()); 159 160 setUseNanoTime(globalConfig.getEtimeResolution() == GlobalCfgDefn.EtimeResolution.NANOSECONDS); 161 setMaxAllowedConnections(globalConfig.getMaxAllowedClientConnections()); 162 setMaxPersistentSearchLimit(globalConfig.getMaxPsearches()); 163 setMaxInternalBufferSize((int) globalConfig.getMaxInternalBufferSize()); 164 165 // Update the "new" schema with configuration changes 166 SchemaUpdater schemaUpdater = serverContext.getSchemaUpdater(); 167 SchemaBuilder schemaBuilder = schemaUpdater.getSchemaBuilder(); 168 boolean allowMalformedNames = globalConfig.isAllowAttributeNameExceptions(); 169 schemaBuilder.setOption(SchemaOptions.ALLOW_MALFORMED_NAMES_AND_OPTIONS, allowMalformedNames); 170 Schema schema = schemaBuilder.toSchema(); 171 if (!globalConfig.isCheckSchema()) 172 { 173 schema = schema.asNonStrictSchema(); 174 } 175 schemaUpdater.updateSchema(schema); 176 } 177 178 private static AcceptRejectWarn convert(InvalidAttributeSyntaxBehavior invalidAttributeSyntaxBehavior) 179 { 180 switch (invalidAttributeSyntaxBehavior) 181 { 182 case ACCEPT: 183 return AcceptRejectWarn.ACCEPT; 184 case WARN: 185 return AcceptRejectWarn.WARN; 186 case REJECT: 187 default: 188 return AcceptRejectWarn.REJECT; 189 } 190 } 191 192 private static AcceptRejectWarn convert(SingleStructuralObjectclassBehavior singleStructuralObjectclassBehavior) 193 { 194 switch (singleStructuralObjectclassBehavior) 195 { 196 case ACCEPT: 197 return AcceptRejectWarn.ACCEPT; 198 case WARN: 199 return AcceptRejectWarn.WARN; 200 case REJECT: 201 default: 202 return AcceptRejectWarn.REJECT; 203 } 204 } 205 206 private static WritabilityMode convert(GlobalCfgDefn.WritabilityMode writabilityMode) 207 { 208 switch (writabilityMode) 209 { 210 case ENABLED: 211 return WritabilityMode.ENABLED; 212 case INTERNAL_ONLY: 213 return WritabilityMode.INTERNAL_ONLY; 214 case DISABLED: 215 default: 216 return WritabilityMode.DISABLED; 217 } 218 } 219 220 private static List<Properties> getMailServerProperties(Set<String> smtpServers) 221 { 222 List<Properties> mailServerProperties = new ArrayList<>(); 223 if (smtpServers != null && !smtpServers.isEmpty()) 224 { 225 for (String smtpServer : smtpServers) 226 { 227 final Properties properties = new Properties(); 228 try 229 { 230 final HostPort hp = HostPort.valueOf(smtpServer); 231 232 properties.setProperty(SMTP_PROPERTY_HOST, hp.getHost()); 233 properties.setProperty(SMTP_PROPERTY_PORT, 234 String.valueOf(hp.getPort())); 235 properties.setProperty(SMTP_PROPERTY_CONNECTION_TIMEOUT, 236 SMTP_DEFAULT_TIMEOUT_VALUE); 237 properties.setProperty(SMTP_PROPERTY_IO_TIMEOUT, 238 SMTP_DEFAULT_TIMEOUT_VALUE); 239 } 240 catch (RuntimeException e) 241 { 242 // no valid port provided 243 properties.setProperty(SMTP_PROPERTY_HOST, smtpServer); 244 } 245 mailServerProperties.add(properties); 246 } 247 } 248 return mailServerProperties; 249 } 250 251 private static HashSet<Privilege> convert(Set<DisabledPrivilege> configuredDisabledPrivs) 252 { 253 HashSet<Privilege> disabledPrivileges = new HashSet<>(); 254 if (configuredDisabledPrivs != null) 255 { 256 for (DisabledPrivilege p : configuredDisabledPrivs) 257 { 258 final Privilege privilege = convert(p); 259 if (privilege != null) 260 { 261 disabledPrivileges.add(privilege); 262 } 263 } 264 } 265 return disabledPrivileges; 266 } 267 268 private static Privilege convert(DisabledPrivilege privilege) 269 { 270 switch (privilege) 271 { 272 case BACKEND_BACKUP: 273 return Privilege.BACKEND_BACKUP; 274 case BACKEND_RESTORE: 275 return Privilege.BACKEND_RESTORE; 276 case BYPASS_ACL: 277 return Privilege.BYPASS_ACL; 278 case CANCEL_REQUEST: 279 return Privilege.CANCEL_REQUEST; 280 case CONFIG_READ: 281 return Privilege.CONFIG_READ; 282 case CONFIG_WRITE: 283 return Privilege.CONFIG_WRITE; 284 case DATA_SYNC: 285 return Privilege.DATA_SYNC; 286 case DISCONNECT_CLIENT: 287 return Privilege.DISCONNECT_CLIENT; 288 case JMX_NOTIFY: 289 return Privilege.JMX_NOTIFY; 290 case JMX_READ: 291 return Privilege.JMX_READ; 292 case JMX_WRITE: 293 return Privilege.JMX_WRITE; 294 case LDIF_EXPORT: 295 return Privilege.LDIF_EXPORT; 296 case LDIF_IMPORT: 297 return Privilege.LDIF_IMPORT; 298 case MODIFY_ACL: 299 return Privilege.MODIFY_ACL; 300 case PASSWORD_RESET: 301 return Privilege.PASSWORD_RESET; 302 case PRIVILEGE_CHANGE: 303 return Privilege.PRIVILEGE_CHANGE; 304 case PROXIED_AUTH: 305 return Privilege.PROXIED_AUTH; 306 case SERVER_RESTART: 307 return Privilege.SERVER_RESTART; 308 case SERVER_SHUTDOWN: 309 return Privilege.SERVER_SHUTDOWN; 310 case UNINDEXED_SEARCH: 311 return Privilege.UNINDEXED_SEARCH; 312 case UPDATE_SCHEMA: 313 return Privilege.UPDATE_SCHEMA; 314 case SUBENTRY_WRITE: 315 return Privilege.SUBENTRY_WRITE; 316 default: 317 return null; 318 } 319 } 320 321 322 /** {@inheritDoc} */ 323 @Override 324 public boolean isConfigurationChangeAcceptable(GlobalCfg configuration, 325 List<LocalizableMessage> unacceptableReasons) 326 { 327 boolean configAcceptable = true; 328 329 Set<String> smtpServers = configuration.getSMTPServer(); 330 if (smtpServers != null) 331 { 332 for (String server : smtpServers) 333 { 334 try 335 { 336 // validate provided string 337 HostPort.valueOf(server); 338 } 339 catch (RuntimeException e) 340 { 341 LocalizableMessage message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server); 342 unacceptableReasons.add(message); 343 configAcceptable = false; 344 } 345 } 346 } 347 348 // Ensure that the default password policy always points to a password 349 // policy and not another type of authentication policy. 350 DN defaultPasswordPolicyDN = configuration.getDefaultPasswordPolicyDN(); 351 AuthenticationPolicy policy = DirectoryServer 352 .getAuthenticationPolicy(defaultPasswordPolicyDN); 353 if (!policy.isPasswordPolicy()) 354 { 355 LocalizableMessage message = 356 ERR_CONFIG_PWPOLICY_CANNOT_CHANGE_DEFAULT_POLICY_WRONG_TYPE 357 .get(configuration.getDefaultPasswordPolicy()); 358 unacceptableReasons.add(message); 359 configAcceptable = false; 360 } 361 362 return configAcceptable; 363 } 364 365 366 367 /** {@inheritDoc} */ 368 @Override 369 public ConfigChangeResult applyConfigurationChange(GlobalCfg configuration) 370 { 371 final ConfigChangeResult ccr = new ConfigChangeResult(); 372 373 applyGlobalConfiguration(configuration, serverContext); 374 375 return ccr; 376 } 377} 378