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