diff options
Diffstat (limited to 'java/broker-core/src/main/java/org/apache/qpid')
47 files changed, 1623 insertions, 584 deletions
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index 0b925d130c..7780f060bb 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -58,6 +58,17 @@ public class Broker implements BrokerShutdownProvider private EventLogger _eventLogger; private boolean _configuringOwnLogging = false; private final TaskExecutor _taskExecutor = new TaskExecutorImpl(); + private final boolean _exitJVMOnShutdownWithNonZeroExitCode; + + public Broker() + { + this(false); + } + + public Broker(boolean exitJVMOnShutdownWithNonZeroExitCode) + { + this._exitJVMOnShutdownWithNonZeroExitCode = exitJVMOnShutdownWithNonZeroExitCode; + } protected static class InitException extends RuntimeException { @@ -71,6 +82,12 @@ public class Broker implements BrokerShutdownProvider public void shutdown() { + shutdown(0); + } + + @Override + public void shutdown(int exitStatusCode) + { try { removeShutdownHook(); @@ -92,6 +109,11 @@ public class Broker implements BrokerShutdownProvider { LogManager.shutdown(); } + + if (_exitJVMOnShutdownWithNonZeroExitCode && exitStatusCode != 0) + { + System.exit(exitStatusCode); + } } } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java index 9d8df844c9..21715f7406 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.server.configuration.store; +import java.util.Collection; + import org.apache.qpid.server.model.ConfigurationChangeListener; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.State; @@ -47,13 +49,24 @@ public class StoreConfigurationChangeListener implements ConfigurationChangeList } @Override - public void childAdded(ConfiguredObject object, ConfiguredObject child) + public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child) { // exclude VirtualHostNode children from storing in broker store if (!(object instanceof VirtualHostNode)) { child.addChangeListener(this); _store.update(true,child.asObjectRecord()); + + Class<? extends ConfiguredObject> categoryClass = child.getCategoryClass(); + Collection<Class<? extends ConfiguredObject>> childTypes = child.getModel().getChildTypes(categoryClass); + + for(Class<? extends ConfiguredObject> childClass : childTypes) + { + for (ConfiguredObject<?> grandchild : child.getChildren(childClass)) + { + childAdded(child, grandchild); + } + } } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java index 064c9788b2..cd21f533a4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java @@ -57,6 +57,7 @@ public class BrokerMessages public static final String SHUTTING_DOWN_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.shutting_down"; public static final String MANAGEMENT_MODE_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.management_mode"; public static final String STARTUP_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.startup"; + public static final String FATAL_ERROR_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.fatal_error"; public static final String READY_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.ready"; static @@ -75,6 +76,7 @@ public class BrokerMessages Logger.getLogger(SHUTTING_DOWN_LOG_HIERARCHY); Logger.getLogger(MANAGEMENT_MODE_LOG_HIERARCHY); Logger.getLogger(STARTUP_LOG_HIERARCHY); + Logger.getLogger(FATAL_ERROR_LOG_HIERARCHY); Logger.getLogger(READY_LOG_HIERARCHY); _messages = ResourceBundle.getBundle("org.apache.qpid.server.logging.messages.Broker_logmessages", _currentLocale); @@ -493,6 +495,38 @@ public class BrokerMessages /** * Log a Broker message of the Format: + * <pre>BRK-1016 : Fatal error : {0} : See log file for more information</pre> + * Optional values are contained in [square brackets] and are numbered + * sequentially in the method call. + * + */ + public static LogMessage FATAL_ERROR(String param1) + { + String rawMessage = _messages.getString("FATAL_ERROR"); + + final Object[] messageArguments = {param1}; + // Create a new MessageFormat to ensure thread safety. + // Sharing a MessageFormat and using applyPattern is not thread safe + MessageFormat formatter = new MessageFormat(rawMessage, _currentLocale); + + final String message = formatter.format(messageArguments); + + return new LogMessage() + { + public String toString() + { + return message; + } + + public String getLogHierarchy() + { + return FATAL_ERROR_LOG_HIERARCHY; + } + }; + } + + /** + * Log a Broker message of the Format: * <pre>BRK-1004 : Qpid Broker Ready</pre> * Optional values are contained in [square brackets] and are numbered * sequentially in the method call. diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties index d764145ec8..322335a956 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties +++ b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties @@ -52,4 +52,6 @@ MANAGEMENT_MODE = BRK-1012 : Management Mode : User Details : {0} / {1} # 0 - Total message size # 1 - Target memory size FLOW_TO_DISK_ACTIVE = BRK-1014 : Message flow to disk active : Message memory use {0,number,#}KB exceeds threshold {1,number,#.##}KB -FLOW_TO_DISK_INACTIVE = BRK-1015 : Message flow to disk inactive : Message memory use {0,number,#}KB within threshold {1,number,#.##}KB
\ No newline at end of file +FLOW_TO_DISK_INACTIVE = BRK-1015 : Message flow to disk inactive : Message memory use {0,number,#}KB within threshold {1,number,#.##}KB + +FATAL_ERROR = BRK-1016 : Fatal error : {0} : See log file for more information
\ No newline at end of file diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java index e6f79fef16..4edfbe0331 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java @@ -1361,6 +1361,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im _desiredState = State.DELETED; } setDesiredState(State.DELETED); + } public final void start() { setDesiredState(State.ACTIVE); } @@ -1578,7 +1579,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im @Override public Set<String> getContextKeys(final boolean excludeSystem) { - Map<String,String> inheritedContext = new HashMap<>(); + Map<String,String> inheritedContext = new HashMap<>(_model.getTypeRegistry().getDefaultContext()); if(!excludeSystem) { inheritedContext.putAll(System.getenv()); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java index 021431b756..99ffa38173 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java @@ -48,13 +48,13 @@ public interface AuthenticationProvider<X extends AuthenticationProvider<X>> ext * Returns the preferences provider associated with this authentication provider * @return PreferencesProvider */ - PreferencesProvider getPreferencesProvider(); + PreferencesProvider<?> getPreferencesProvider(); /** * Sets the preferences provider * @param preferencesProvider */ - void setPreferencesProvider(PreferencesProvider preferencesProvider); + void setPreferencesProvider(PreferencesProvider<?> preferencesProvider); void recoverUser(User user); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java index 02c9ccf8e1..3dfc272053 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java @@ -44,7 +44,7 @@ public final class BrokerModel extends Model * 2.0 Introduce VirtualHostNode as a child of a Broker instead of VirtualHost */ public static final int MODEL_MAJOR_VERSION = 2; - public static final int MODEL_MINOR_VERSION = 0; + public static final int MODEL_MINOR_VERSION = 1; public static final String MODEL_VERSION = MODEL_MAJOR_VERSION + "." + MODEL_MINOR_VERSION; private static final Model MODEL_INSTANCE = new BrokerModel(); private final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>> _parents = @@ -81,7 +81,6 @@ public final class BrokerModel extends Model addRelationship(VirtualHost.class, Exchange.class); addRelationship(VirtualHost.class, Queue.class); addRelationship(VirtualHost.class, Connection.class); - addRelationship(VirtualHost.class, VirtualHostAlias.class); addRelationship(Port.class, VirtualHostAlias.class); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java index 5c8ab3e850..7eb0d3cc64 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java @@ -22,5 +22,5 @@ package org.apache.qpid.server.model; public interface BrokerShutdownProvider { - void shutdown(); + void shutdown(int exitStatusCode); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java index e377d31baf..ac980568b6 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java @@ -854,6 +854,9 @@ public class ConfiguredObjectTypeRegistry return map != null ? Collections.unmodifiableMap(map) : Collections.<State, Map<State, Method>>emptyMap(); } - + public Map<String,String> getDefaultContext() + { + return Collections.unmodifiableMap(_defaultContext); + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java new file mode 100644 index 0000000000..5265cf462c --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java @@ -0,0 +1,31 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = DefaultVirtualHostAlias.TYPE_NAME) +public interface DefaultVirtualHostAlias<X extends VirtualHostAlias<X>> extends VirtualHostAlias<X> +{ + + String TYPE_NAME = "defaultAlias"; + + @ManagedAttribute( defaultValue = "500" ) + int getPriority(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java new file mode 100644 index 0000000000..6b41a84d0d --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +public interface FixedVirtualHostNodeAlias<X extends FixedVirtualHostNodeAlias<X>> extends VirtualHostAlias<X> +{ + String VIRTUAL_HOST_NODE = "virtualHostNode"; + + @ManagedAttribute + VirtualHostNode<?> getVirtualHostNode(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java new file mode 100644 index 0000000000..1206c0e126 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = HostNameAlias.TYPE_NAME) +public interface HostNameAlias<X extends HostNameAlias<X>> extends FixedVirtualHostNodeAlias<X> +{ + + String TYPE_NAME = "hostnameAlias"; + + @ManagedAttribute( defaultValue = "750" ) + int getPriority(); + + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java new file mode 100644 index 0000000000..d602858628 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = PatternMatchingAlias.TYPE_NAME) +public interface PatternMatchingAlias<X extends PatternMatchingAlias<X>> extends FixedVirtualHostNodeAlias<X> +{ + + String TYPE_NAME = "patternMatchingAlias"; + + String PATTERN = "pattern"; + + @ManagedAttribute( defaultValue = "200" ) + int getPriority(); + + @ManagedAttribute( mandatory = true) + public String getPattern(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java index d8b81a25b5..24528b9a4e 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java @@ -60,12 +60,8 @@ public interface Port<X extends Port<X>> extends ConfiguredObject<X> @ManagedAttribute Collection<TrustStore> getTrustStores(); - //children - Collection<VirtualHostAlias> getVirtualHostBindings(); Collection<Connection> getConnections(); void start(); - boolean isLocalMachine(final String host); - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java index 4af5fbfde5..0cd4773d4b 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java @@ -20,18 +20,17 @@ */ package org.apache.qpid.server.model; -import java.util.Collection; - -@ManagedObject +@ManagedObject( creatable = false ) public interface VirtualHostAlias<X extends VirtualHostAlias<X>> extends ConfiguredObject<X> { + String PRIORITY = "priority"; + // parents Port getPort(); - VirtualHost getVirtualHost(); - - // children - Collection<AuthenticationMethod> getAuthenticationMethods(); + @ManagedAttribute( defaultValue = "100" ) + int getPriority(); + VirtualHostNode getVirtualHostNode(String name); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java new file mode 100644 index 0000000000..2d114f21a2 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = VirtualHostNameAlias.TYPE_NAME) +public interface VirtualHostNameAlias<X extends VirtualHostNameAlias<X>> extends VirtualHostAlias<X> +{ + String TYPE_NAME = "nameAlias"; +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index ee008b1642..d413050cef 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -969,7 +969,8 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple BrokerShutdownProvider shutdownProvider = systemConfig.getBrokerShutdownProvider(); if (shutdownProvider != null) { - shutdownProvider.shutdown(); + _eventLogger.message(BrokerMessages.FATAL_ERROR(e.getMessage())); + shutdownProvider.shutdown(1); } else { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java deleted file mode 100644 index 0ea9079ebb..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.model.adapter; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.AuthenticationMethod; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostAlias; - -public class VirtualHostAliasAdapter extends AbstractConfiguredObject<VirtualHostAliasAdapter> implements VirtualHostAlias<VirtualHostAliasAdapter> -{ - private VirtualHost _vhost; - private Port _port; - - public VirtualHostAliasAdapter(VirtualHost virtualHost, Port port) - { - super(parentsMap(virtualHost,port), createAttributes(virtualHost, port)); - _vhost = virtualHost; - _port = port; - setState(State.ACTIVE); - } - - private static Map<String, Object> createAttributes(final VirtualHost virtualHost, final Port port) - { - final Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(ID, UUID.randomUUID()); - attributes.put(NAME, virtualHost.getName()); - attributes.put(DURABLE, false); - return attributes; - } - - @Override - public Port getPort() - { - return _port; - } - - @Override - public VirtualHost getVirtualHost() - { - return _vhost; - } - - @Override - public Collection<AuthenticationMethod> getAuthenticationMethods() - { - return Collections.emptySet(); // TODO - Implement - } - - @Override - public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) - { - return Collections.emptySet(); - } - - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java index e2e7eff322..6d8e65cd17 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java @@ -21,23 +21,12 @@ package org.apache.qpid.server.model.port; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import org.apache.log4j.Logger; @@ -54,69 +43,12 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostAlias; -import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.access.Operation; abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractConfiguredObject<X> implements Port<X> { private static final Logger LOGGER = Logger.getLogger(AbstractPort.class); - private static final Set<InetAddress> LOCAL_ADDRESSES = new CopyOnWriteArraySet<>(); - private static final Set<String> LOCAL_ADDRESS_NAMES = new CopyOnWriteArraySet<>(); - private static final Lock ADDRESS_LOCK = new ReentrantLock(); - private static final AtomicBoolean ADDRESSES_COMPUTED = new AtomicBoolean(); - - static - { - Thread thread = new Thread(new Runnable() - { - public void run() - { - Lock lock = ADDRESS_LOCK; - - lock.lock(); - try - { - for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) - { - for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses()) - { - InetAddress address = inetAddress.getAddress(); - LOCAL_ADDRESSES.add(address); - String hostAddress = address.getHostAddress(); - if (hostAddress != null) - { - LOCAL_ADDRESS_NAMES.add(hostAddress); - } - String hostName = address.getHostName(); - if (hostName != null) - { - LOCAL_ADDRESS_NAMES.add(hostName); - } - String canonicalHostName = address.getCanonicalHostName(); - if (canonicalHostName != null) - { - LOCAL_ADDRESS_NAMES.add(canonicalHostName); - } - } - } - } - catch (SocketException e) - { - // ignore - } - finally - { - ADDRESSES_COMPUTED.set(true); - lock.unlock(); - } - } - }, "Network Address Resolver"); - thread.start(); - } - private final Broker<?> _broker; @ManagedAttributeField @@ -271,27 +203,6 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo } @Override - public Collection<VirtualHostAlias> getVirtualHostBindings() - { - List<VirtualHostAlias> aliases = new ArrayList<VirtualHostAlias>(); - for(VirtualHostNode<?> vhn : _broker.getVirtualHostNodes()) - { - VirtualHost<?, ?, ?> vh = vhn.getVirtualHost(); - if (vh != null) - { - for(VirtualHostAlias<?> alias : vh.getAliases()) - { - if(alias.getPort().equals(this)) - { - aliases.add(alias); - } - } - } - } - return Collections.unmodifiableCollection(aliases); - } - - @Override public Collection<Connection> getConnections() { return null; @@ -306,7 +217,7 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo } else { - return Collections.emptySet(); + return super.getChildren(clazz); } } @@ -412,38 +323,4 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo } } - public boolean isLocalMachine(final String host) - { - while(!ADDRESSES_COMPUTED.get()) - { - Lock lock = ADDRESS_LOCK; - lock.lock(); - lock.unlock(); - } - - boolean isNetworkAddress = true; - if (!LOCAL_ADDRESS_NAMES.contains(host)) - { - try - { - InetAddress inetAddress = InetAddress.getByName(host); - if (!LOCAL_ADDRESSES.contains(inetAddress)) - { - isNetworkAddress = false; - } - else - { - LOCAL_ADDRESS_NAMES.add(host); - } - } - catch (UnknownHostException e) - { - // ignore - isNetworkAddress = false; - } - } - return isNetworkAddress; - - } - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java index f7eeca354a..ade9055b5a 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java @@ -20,15 +20,16 @@ */ package org.apache.qpid.server.model.port; +import java.util.Map; import java.util.Set; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.ManagedAttribute; import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.VirtualHostAlias; import org.apache.qpid.server.virtualhost.VirtualHostImpl; @ManagedObject( category = false, type = "AMQP") @@ -80,4 +81,5 @@ public interface AmqpPort<X extends AmqpPort<X>> extends ClientAuthCapablePort<X VirtualHostImpl getVirtualHost(String name); + VirtualHostAlias createVirtualHostAlias(Map<String, Object> attributes); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java index afe3c9a44e..fd8c402344 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java @@ -25,35 +25,42 @@ import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; -import org.apache.qpid.server.util.PortUtil; import org.codehaus.jackson.map.ObjectMapper; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.DefaultVirtualHostAlias; +import org.apache.qpid.server.model.HostNameAlias; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNameAlias; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.plugin.ProtocolEngineCreator; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.plugin.TransportProviderFactory; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.transport.TransportProvider; +import org.apache.qpid.server.util.PortUtil; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; @@ -63,6 +70,29 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< public static final String DEFAULT_BINDING_ADDRESS = "*"; + + private static final Comparator<VirtualHostAlias> VIRTUAL_HOST_ALIAS_COMPARATOR = new Comparator<VirtualHostAlias>() + { + @Override + public int compare(final VirtualHostAlias left, final VirtualHostAlias right) + { + int comparison = left.getPriority() - right.getPriority(); + if (comparison == 0) + { + long createCompare = left.getCreatedTime() - right.getCreatedTime(); + if (createCompare == 0) + { + comparison = left.getName().compareTo(right.getName()); + } + else + { + comparison = createCompare < 0l ? -1 : 1; + } + } + return comparison; + } + }; + @ManagedAttributeField private boolean _tcpNoDelay; @@ -111,15 +141,47 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< } @Override + protected void onCreate() + { + super.onCreate(); + + Map<String, Object> attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "nameAlias"); + attributes.put(VirtualHostAlias.TYPE, VirtualHostNameAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.DURABLE, true); + createVirtualHostAlias(attributes); + + attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "defaultAlias"); + attributes.put(VirtualHostAlias.TYPE, DefaultVirtualHostAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.DURABLE, true); + createVirtualHostAlias(attributes); + + + attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "hostnameAlias"); + attributes.put(VirtualHostAlias.TYPE, HostNameAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.DURABLE, true); + createVirtualHostAlias(attributes); + + } + + @Override public VirtualHostImpl getVirtualHost(String name) { - // TODO - aliases - if(name == null || name.trim().length() == 0) + Collection<VirtualHostAlias> aliases = new TreeSet<>(VIRTUAL_HOST_ALIAS_COMPARATOR); + + aliases.addAll(getChildren(VirtualHostAlias.class)); + + for(VirtualHostAlias alias : aliases) { - name = _broker.getDefaultVirtualHost(); + VirtualHostNode vhn = alias.getVirtualHostNode(name); + if (vhn != null) + { + return (VirtualHostImpl) vhn.getVirtualHost(); + } } - - return (VirtualHostImpl) _broker.findVirtualHostByName(name); + return null; } @Override @@ -156,7 +218,6 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< { sslContext = createSslContext(); } - Protocol defaultSupportedProtocolReply = getDefaultAmqpSupportedReply(); _transport = transportProvider.createTransport(transportSet, @@ -189,6 +250,20 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< } @Override + public VirtualHostAlias createVirtualHostAlias(Map<String, Object> attributes) + { + VirtualHostAlias child = addVirtualHostAlias(attributes); + childAdded(child); + return child; + } + + private VirtualHostAlias addVirtualHostAlias(Map<String,Object> attributes) + { + return getObjectFactory().create(VirtualHostAlias.class, attributes, this); + } + + + @Override public void validateOnCreate() { super.validateOnCreate(); @@ -215,6 +290,7 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< try { SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManager[] keyManagers = keyStore.getKeyManagers(); TrustManager[] trustManagers; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 0eabcd725e..ef45971858 100755 --- a/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -45,6 +45,7 @@ import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.transport.network.security.SSLStatus; import org.apache.qpid.transport.network.security.ssl.SSLBufferingSender; import org.apache.qpid.transport.network.security.ssl.SSLReceiver; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class MultiVersionProtocolEngine implements ServerProtocolEngine { @@ -480,6 +481,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine _engine = _sslContext.createSSLEngine(); _engine.setUseClientMode(false); + SSLUtil.removeSSLv3Support(_engine); if(_needClientAuth) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index acfe7856c3..d32f0299d5 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -32,6 +32,7 @@ import org.apache.qpid.server.logging.MessageLogger; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer; import org.apache.qpid.server.store.DurableConfigurationStore; @@ -77,17 +78,17 @@ public class ApplicationRegistry implements IApplicationRegistry logStartupMessages(startupLogger); BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(_systemConfig); - _broker = upgrader.perform(_store); + Broker broker = upgrader.perform(_store); + _broker = broker; - _broker.setEventLogger(startupLogger); - _broker.open(); - - // starting the broker - //_broker.setDesiredState(State.ACTIVE); - - startupLogger.message(BrokerMessages.READY()); - _broker.setEventLogger(eventLogger); + broker.setEventLogger(startupLogger); + broker.open(); + if (broker.getState() == State.ACTIVE) + { + startupLogger.message(BrokerMessages.READY()); + broker.setEventLogger(eventLogger); + } } public void close() diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java index ac8d002577..bbec239d74 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java @@ -53,10 +53,10 @@ public class SubjectCreator { private final boolean _secure; private AuthenticationProvider<?> _authenticationProvider; - private Collection<GroupProvider> _groupProviders; + private Collection<GroupProvider<?>> _groupProviders; public SubjectCreator(AuthenticationProvider<?> authenticationProvider, - Collection<GroupProvider> groupProviders, + Collection<GroupProvider<?>> groupProviders, final boolean secure) { _authenticationProvider = authenticationProvider; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java index b2cf1739ab..7f98468726 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java @@ -53,13 +53,13 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica { private static final Logger LOGGER = Logger.getLogger(AbstractAuthenticationManager.class); - private final Broker _broker; - private PreferencesProvider _preferencesProvider; + private final Broker<?> _broker; + private PreferencesProvider<?> _preferencesProvider; @ManagedAttributeField private List<String> _secureOnlyMechanisms; - protected AbstractAuthenticationManager(final Map<String, Object> attributes, final Broker broker) + protected AbstractAuthenticationManager(final Map<String, Object> attributes, final Broker<?> broker) { super(parentsMap(broker), attributes); _broker = broker; @@ -120,13 +120,13 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica } @Override - public PreferencesProvider getPreferencesProvider() + public PreferencesProvider<?> getPreferencesProvider() { return _preferencesProvider; } @Override - public void setPreferencesProvider(final PreferencesProvider preferencesProvider) + public void setPreferencesProvider(final PreferencesProvider<?> preferencesProvider) { _preferencesProvider = preferencesProvider; } @@ -143,8 +143,8 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica { if(childClass == PreferencesProvider.class) { - attributes = new HashMap<String, Object>(attributes); - PreferencesProvider pp = getObjectFactory().create(PreferencesProvider.class, attributes, this); + attributes = new HashMap<>(attributes); + PreferencesProvider<?> pp = getObjectFactory().create(PreferencesProvider.class, attributes, this); _preferencesProvider = pp; return (C)pp; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java index 152a9086ec..6887cb99d4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java @@ -20,52 +20,38 @@ */ package org.apache.qpid.server.security.auth.manager; -import java.io.IOException; -import java.nio.charset.Charset; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.SecureRandom; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import javax.security.auth.login.AccountNotFoundException; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import javax.xml.bind.DatatypeConverter; -import org.apache.qpid.server.configuration.updater.Task; -import org.apache.qpid.server.configuration.updater.VoidTaskWithException; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; -import org.apache.qpid.server.model.User; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer; import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServer; public abstract class AbstractScramAuthenticationManager<X extends AbstractScramAuthenticationManager<X>> - extends AbstractAuthenticationManager<X> + extends ConfigModelPasswordManagingAuthenticationProvider<X> implements PasswordCredentialManagingAuthenticationProvider<X> { - static final Charset ASCII = Charset.forName("ASCII"); public static final String PLAIN = "PLAIN"; private final SecureRandom _random = new SecureRandom(); private int _iterationCount = 4096; - private Map<String, ScramAuthUser> _users = new ConcurrentHashMap<String, ScramAuthUser>(); - protected AbstractScramAuthenticationManager(final Map<String, Object> attributes, final Broker broker) { @@ -103,33 +89,9 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram protected abstract String getDigestName(); @Override - public AuthenticationResult authenticate(final SaslServer server, final byte[] response) - { - try - { - // Process response from the client - byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); - - if (server.isComplete() && (challenge == null || challenge.length == 0)) - { - final String userId = server.getAuthorizationID(); - return new AuthenticationResult(new UsernamePrincipal(userId)); - } - else - { - return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); - } - } - catch (SaslException e) - { - return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); - } - } - - @Override public AuthenticationResult authenticate(final String username, final String password) { - ScramAuthUser user = getUser(username); + ManagedUser user = getUser(username); if(user != null) { final String[] usernamePassword = user.getPassword().split(","); @@ -142,7 +104,7 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram return new AuthenticationResult(new UsernamePrincipal(username)); } } - catch (SaslException e) + catch (IllegalArgumentException e) { return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e); } @@ -162,7 +124,7 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram public byte[] getSalt(final String username) { - ScramAuthUser user = getUser(username); + ManagedUser user = getUser(username); if(user == null) { @@ -183,7 +145,7 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram public byte[] getSaltedPassword(final String username) throws SaslException { - ScramAuthUser user = getUser(username); + ManagedUser user = getUser(username); if(user == null) { throw new SaslException("Authentication Failed"); @@ -194,14 +156,9 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram } } - private ScramAuthUser getUser(final String username) - { - return _users.get(username); - } - - private byte[] createSaltedPassword(byte[] salt, String password) throws SaslException + private byte[] createSaltedPassword(byte[] salt, String password) { - Mac mac = createSha1Hmac(password.getBytes(ASCII)); + Mac mac = createShaHmac(password.getBytes(ASCII)); mac.update(salt); mac.update(INT_1); @@ -222,8 +179,7 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram } - private Mac createSha1Hmac(final byte[] keyBytes) - throws SaslException + private Mac createShaHmac(final byte[] keyBytes) { try { @@ -232,132 +188,16 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram mac.init(key); return mac; } - catch (NoSuchAlgorithmException e) - { - throw new SaslException(e.getMessage(), e); - } - catch (InvalidKeyException e) + catch (NoSuchAlgorithmException | InvalidKeyException e) { - throw new SaslException(e.getMessage(), e); + throw new IllegalArgumentException(e.getMessage(), e); } } protected abstract String getHmacName(); @Override - public boolean createUser(final String username, final String password, final Map<String, String> attributes) - { - return runTask(new Task<Boolean>() - { - @Override - public Boolean execute() - { - getSecurityManager().authoriseUserOperation(Operation.CREATE, username); - if (_users.containsKey(username)) - { - throw new IllegalArgumentException("User '" + username + "' already exists"); - } - try - { - Map<String, Object> userAttrs = new HashMap<String, Object>(); - userAttrs.put(User.ID, UUID.randomUUID()); - userAttrs.put(User.NAME, username); - userAttrs.put(User.PASSWORD, createStoredPassword(password)); - userAttrs.put(User.TYPE, ScramAuthUser.SCRAM_USER_TYPE); - ScramAuthUser user = new ScramAuthUser(userAttrs, AbstractScramAuthenticationManager.this); - user.create(); - - return true; - } - catch (SaslException e) - { - throw new IllegalArgumentException(e); - } - } - }); - } - - org.apache.qpid.server.security.SecurityManager getSecurityManager() - { - return getBroker().getSecurityManager(); - } - - @Override - public void deleteUser(final String user) throws AccountNotFoundException - { - runTask(new VoidTaskWithException<AccountNotFoundException>() - { - @Override - public void execute() throws AccountNotFoundException - { - final ScramAuthUser authUser = getUser(user); - if(authUser != null) - { - authUser.delete(); - } - else - { - throw new AccountNotFoundException("No such user: '" + user + "'"); - } - } - }); - } - - @Override - public void setPassword(final String username, final String password) throws AccountNotFoundException - { - runTask(new VoidTaskWithException<AccountNotFoundException>() - { - @Override - public void execute() throws AccountNotFoundException - { - - final ScramAuthUser authUser = getUser(username); - if (authUser != null) - { - authUser.setPassword(password); - } - else - { - throw new AccountNotFoundException("No such user: '" + username + "'"); - } - } - }); - - } - - @Override - public Map<String, Map<String, String>> getUsers() - { - return runTask(new Task<Map<String, Map<String, String>>>() - { - @Override - public Map<String, Map<String, String>> execute() - { - - Map<String, Map<String, String>> users = new HashMap<String, Map<String, String>>(); - for (String user : _users.keySet()) - { - users.put(user, Collections.<String, String>emptyMap()); - } - return users; - } - }); - } - - @Override - public void reload() throws IOException - { - - } - - @Override - public void recoverUser(final User user) - { - _users.put(user.getName(), (ScramAuthUser) user); - } - - protected String createStoredPassword(final String password) throws SaslException + protected String createStoredPassword(final String password) { byte[] salt = new byte[32]; _random.nextBytes(salt); @@ -366,33 +206,11 @@ public abstract class AbstractScramAuthenticationManager<X extends AbstractScram } @Override - public <C extends ConfiguredObject> C addChild(final Class<C> childClass, - final Map<String, Object> attributes, - final ConfiguredObject... otherParents) + void validateUser(final ManagedUser managedUser) { - if(childClass == User.class) + if(!ASCII.newEncoder().canEncode(managedUser.getName())) { - String username = (String) attributes.get("name"); - String password = (String) attributes.get("password"); - - if(createUser(username, password,null)) - { - @SuppressWarnings("unchecked") - C user = (C) _users.get(username); - return user; - } - else - { - return null; - - } + throw new IllegalArgumentException("User names are restricted to characters in the ASCII charset"); } - return super.addChild(childClass, attributes, otherParents); } - - Map<String, ScramAuthUser> getUserMap() - { - return _users; - } - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java new file mode 100644 index 0000000000..5126e6978d --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java @@ -0,0 +1,229 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import javax.security.auth.login.AccountNotFoundException; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.configuration.updater.Task; +import org.apache.qpid.server.configuration.updater.VoidTaskWithException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; + +public abstract class ConfigModelPasswordManagingAuthenticationProvider<X extends ConfigModelPasswordManagingAuthenticationProvider<X>> + extends AbstractAuthenticationManager<X> + implements PasswordCredentialManagingAuthenticationProvider<X> +{ + static final Charset ASCII = Charset.forName("ASCII"); + protected Map<String, ManagedUser> _users = new ConcurrentHashMap<>(); + + protected ConfigModelPasswordManagingAuthenticationProvider(final Map<String, Object> attributes, + final Broker broker) + { + super(attributes, broker); + } + + ManagedUser getUser(final String username) + { + return _users.get(username); + } + + @Override + public boolean createUser(final String username, final String password, final Map<String, String> attributes) + { + return runTask(new Task<Boolean>() + { + @Override + public Boolean execute() + { + getSecurityManager().authoriseUserOperation(Operation.CREATE, username); + if (_users.containsKey(username)) + { + throw new IllegalArgumentException("User '" + username + "' already exists"); + } + + Map<String, Object> userAttrs = new HashMap<>(); + userAttrs.put(User.ID, UUID.randomUUID()); + userAttrs.put(User.NAME, username); + userAttrs.put(User.PASSWORD, createStoredPassword(password)); + userAttrs.put(User.TYPE, ManagedUser.MANAGED_USER_TYPE); + ManagedUser user = new ManagedUser(userAttrs, ConfigModelPasswordManagingAuthenticationProvider.this); + user.create(); + + return true; + + } + }); + } + + SecurityManager getSecurityManager() + { + return getBroker().getSecurityManager(); + } + + @Override + public void deleteUser(final String user) throws AccountNotFoundException + { + runTask(new VoidTaskWithException<AccountNotFoundException>() + { + @Override + public void execute() throws AccountNotFoundException + { + final ManagedUser authUser = getUser(user); + if(authUser != null) + { + authUser.delete(); + } + else + { + throw new AccountNotFoundException("No such user: '" + user + "'"); + } + } + }); + } + + @Override + public Map<String, Map<String, String>> getUsers() + { + return runTask(new Task<Map<String, Map<String, String>>>() + { + @Override + public Map<String, Map<String, String>> execute() + { + + Map<String, Map<String, String>> users = new HashMap<>(); + for (String user : _users.keySet()) + { + users.put(user, Collections.<String, String>emptyMap()); + } + return users; + } + }); + } + + @Override + public void reload() throws IOException + { + + } + + @Override + public void recoverUser(final User user) + { + _users.put(user.getName(), (ManagedUser) user); + } + + @Override + public void setPassword(final String username, final String password) throws AccountNotFoundException + { + runTask(new VoidTaskWithException<AccountNotFoundException>() + { + @Override + public void execute() throws AccountNotFoundException + { + + final ManagedUser authUser = getUser(username); + if (authUser != null) + { + authUser.setPassword(password); + } + else + { + throw new AccountNotFoundException("No such user: '" + username + "'"); + } + } + }); + + } + + @Override + public AuthenticationResult authenticate(final SaslServer server, final byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete() && (challenge == null || challenge.length == 0)) + { + final String userId = server.getAuthorizationID(); + return new AuthenticationResult(new UsernamePrincipal(userId)); + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + protected abstract String createStoredPassword(String password); + + Map<String, ManagedUser> getUserMap() + { + return _users; + } + + @Override + public <C extends ConfiguredObject> C addChild(final Class<C> childClass, + final Map<String, Object> attributes, + final ConfiguredObject... otherParents) + { + if(childClass == User.class) + { + String username = (String) attributes.get("name"); + String password = (String) attributes.get("password"); + + if(createUser(username, password,null)) + { + @SuppressWarnings("unchecked") + C user = (C) getUser(username); + return user; + } + else + { + return null; + + } + } + return super.addChild(childClass, attributes, otherParents); + } + + abstract void validateUser(final ManagedUser managedUser); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java new file mode 100644 index 0000000000..cdb2f3dcc7 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java @@ -0,0 +1,227 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import javax.xml.bind.DatatypeConverter; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedSaslServer; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexSaslServer; +import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; +import org.apache.qpid.server.util.ServerScopedRuntimeException; + +@ManagedObject( category = false, type = "MD5" ) +public class MD5AuthenticationProvider + extends ConfigModelPasswordManagingAuthenticationProvider<MD5AuthenticationProvider> +{ + private final List<String> _mechanisms = Collections.unmodifiableList(Arrays.asList(PlainSaslServer.MECHANISM, + CRAMMD5HashedSaslServer.MECHANISM, + CRAMMD5HexSaslServer.MECHANISM)); + + + @ManagedObjectFactoryConstructor + protected MD5AuthenticationProvider(final Map<String, Object> attributes, final Broker broker) + { + super(attributes, broker); + } + + @Override + protected String createStoredPassword(final String password) + { + byte[] data = password.getBytes(StandardCharsets.UTF_8); + MessageDigest md = null; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) + { + throw new ServerScopedRuntimeException("MD5 not supported although Java compliance requires it"); + } + + md.update(data); + return DatatypeConverter.printBase64Binary(md.digest()); + } + + @Override + void validateUser(final ManagedUser managedUser) + { + } + + @Override + public List<String> getMechanisms() + { + return _mechanisms; + } + + @Override + public SaslServer createSaslServer(final String mechanism, + final String localFQDN, + final Principal externalPrincipal) + throws SaslException + { + if(PlainSaslServer.MECHANISM.equals(mechanism)) + { + return new PlainAdapterSaslServer(this); + } + else if(CRAMMD5HashedSaslServer.MECHANISM.equals(mechanism)) + { + //simply delegate to the built in CRAM-MD5 SaslServer + return new CRAMMD5HashedSaslServer(mechanism, "AMQP", localFQDN, null, new MD5Callbackhandler(false)); + } + else if(CRAMMD5HexSaslServer.MECHANISM.equals(mechanism)) + { + //simply delegate to the built in CRAM-MD5 SaslServer + return new CRAMMD5HashedSaslServer(mechanism, "AMQP", localFQDN, null, new MD5Callbackhandler(true)); + } + else + { + throw new SaslException("Unsupported mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(final String username, final String password) + { + ManagedUser user = getUser(username); + AuthenticationResult result; + if(user != null && user.getPassword().equals(createStoredPassword(password))) + { + result = new AuthenticationResult(new UsernamePrincipal(username)); + } + else + { + result = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + return result; + } + private static final char[] HEX_CHARACTERS = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + private class MD5Callbackhandler implements CallbackHandler + { + private final boolean _hexify; + private String _username; + + public MD5Callbackhandler(final boolean hexify) + { + _hexify = hexify; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + List<Callback> callbackList = new ArrayList<>(Arrays.asList(callbacks)); + Iterator<Callback> iter = callbackList.iterator(); + while(iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof NameCallback) + { + _username = ((NameCallback) callback).getDefaultName(); + iter.remove(); + break; + } + } + + if(_username != null) + { + iter = callbackList.iterator(); + while (iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof PasswordCallback) + { + iter.remove(); + ManagedUser user = getUser(_username); + if(user != null) + { + String passwordData = user.getPassword(); + byte[] passwordBytes = DatatypeConverter.parseBase64Binary(passwordData); + char[] password; + if(_hexify) + { + password = new char[passwordBytes.length]; + + for(int i = 0; i < passwordBytes.length; i--) + { + password[2*i] = HEX_CHARACTERS[(((int)passwordBytes[i]) & 0xf0)>>4]; + password[(2*i)+1] = HEX_CHARACTERS[(((int)passwordBytes[i]) & 0x0f)]; + } + } + else + { + password = new char[passwordBytes.length]; + for(int i = 0; i < passwordBytes.length; i++) + { + password[i] = (char) passwordBytes[i]; + } + } + ((PasswordCallback) callback).setPassword(password); + } + else + { + ((PasswordCallback) callback).setPassword(null); + } + break; + } + } + } + + for (Callback callback : callbackList) + { + + if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java index b3de1d1f17..c8884e15a8 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java @@ -27,8 +27,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import javax.security.sasl.SaslException; - import org.apache.qpid.server.configuration.updater.VoidTask; import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.ConfiguredObject; @@ -41,24 +39,21 @@ import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.User; import org.apache.qpid.server.security.access.Operation; -@ManagedObject( category = false, type = ScramAuthUser.SCRAM_USER_TYPE) -class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements User<ScramAuthUser> +@ManagedObject( category = false, type = ManagedUser.MANAGED_USER_TYPE) +class ManagedUser extends AbstractConfiguredObject<ManagedUser> implements User<ManagedUser> { - public static final String SCRAM_USER_TYPE = "scram"; + public static final String MANAGED_USER_TYPE = "managed"; - private AbstractScramAuthenticationManager _authenticationManager; + private ConfigModelPasswordManagingAuthenticationProvider<?> _authenticationManager; @ManagedAttributeField private String _password; @ManagedObjectFactoryConstructor - ScramAuthUser(final Map<String, Object> attributes, AbstractScramAuthenticationManager parent) + ManagedUser(final Map<String, Object> attributes, ConfigModelPasswordManagingAuthenticationProvider<?> parent) { super(parentsMap(parent), attributes); _authenticationManager = parent; - if(!ScramSHA1AuthenticationManager.ASCII.newEncoder().canEncode(getName())) - { - throw new IllegalArgumentException("Scram SHA1 user names are restricted to characters in the ASCII charset"); - } + setState(State.ACTIVE); } @@ -73,6 +68,7 @@ class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements U public void onValidate() { super.onValidate(); + _authenticationManager.validateUser(this); if(!isDurable()) { throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable"); @@ -122,17 +118,11 @@ class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements U if (attributes.containsKey(User.PASSWORD) && !newPassword.equals(getActualAttributes().get(User.PASSWORD))) { - try - { - modifiedAttributes.put(User.PASSWORD, - _authenticationManager.createStoredPassword(newPassword)); - } - catch (SaslException e) - { - throw new IllegalArgumentException(e); - } + modifiedAttributes.put(User.PASSWORD, + _authenticationManager.createStoredPassword(newPassword)); + } - ScramAuthUser.super.setAttributes(modifiedAttributes); + ManagedUser.super.setAttributes(modifiedAttributes); } }); @@ -150,15 +140,9 @@ class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements U { _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.UPDATE, getName()); - try - { - changeAttribute(User.PASSWORD, getAttribute(User.PASSWORD), _authenticationManager.createStoredPassword( - password)); - } - catch (SaslException e) - { - throw new IllegalArgumentException(e); - } + changeAttribute(User.PASSWORD, getAttribute(User.PASSWORD), + _authenticationManager.createStoredPassword(password)); + } @Override @@ -170,7 +154,7 @@ class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements U @Override public Map<String, Object> getPreferences() { - PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); + PreferencesProvider<?> preferencesProvider = _authenticationManager.getPreferencesProvider(); if (preferencesProvider == null) { return null; @@ -192,7 +176,7 @@ class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements U @Override public Map<String, Object> setPreferences(Map<String, Object> preferences) { - PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); + PreferencesProvider<?> preferencesProvider = _authenticationManager.getPreferencesProvider(); if (preferencesProvider == null) { return null; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java new file mode 100644 index 0000000000..5c79253ebb --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java @@ -0,0 +1,176 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.io.IOException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser; +import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; + +@ManagedObject( category = false, type = "Plain" ) +public class PlainAuthenticationProvider + extends ConfigModelPasswordManagingAuthenticationProvider<PlainAuthenticationProvider> +{ + private final List<String> _mechanisms = Collections.unmodifiableList(Arrays.asList(PlainSaslServer.MECHANISM, + CRAMMD5Initialiser.MECHANISM)); + + + @ManagedObjectFactoryConstructor + protected PlainAuthenticationProvider(final Map<String, Object> attributes, final Broker broker) + { + super(attributes, broker); + } + + @Override + protected String createStoredPassword(final String password) + { + return password; + } + + @Override + void validateUser(final ManagedUser managedUser) + { + // NOOP + } + + @Override + public List<String> getMechanisms() + { + return _mechanisms; + } + + @Override + public SaslServer createSaslServer(final String mechanism, + final String localFQDN, + final Principal externalPrincipal) + throws SaslException + { + if(PlainSaslServer.MECHANISM.equals(mechanism)) + { + return new PlainAdapterSaslServer(this); + } + else if(CRAMMD5Initialiser.MECHANISM.equals(mechanism)) + { + //simply delegate to the built in CRAM-MD5 SaslServer + return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, new ServerCallbackHandler()); + } + else + { + throw new SaslException("Unsupported mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(final String username, final String password) + { + ManagedUser user = getUser(username); + AuthenticationResult result; + if(user != null && user.getPassword().equals(password)) + { + result = new AuthenticationResult(new UsernamePrincipal(username)); + } + else + { + result = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + return result; + } + + private class ServerCallbackHandler implements CallbackHandler + { + String _username; + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + List<Callback> callbackList = new ArrayList<>(Arrays.asList(callbacks)); + Iterator<Callback> iter = callbackList.iterator(); + while(iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof NameCallback) + { + _username = ((NameCallback) callback).getDefaultName(); + iter.remove(); + break; + } + } + + if(_username != null) + { + iter = callbackList.iterator(); + while (iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof PasswordCallback) + { + iter.remove(); + ManagedUser user = getUser(_username); + if(user != null) + { + ((PasswordCallback) callback).setPassword(user.getPassword().toCharArray()); + } + else + { + ((PasswordCallback) callback).setPassword(null); + } + break; + } + } + } + + for (Callback callback : callbackList) + { + + if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java index be7db10773..08440826be 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java @@ -19,6 +19,7 @@ * */ package org.apache.qpid.server.store; + import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -26,12 +27,15 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.UUID; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.SystemConfig; +import org.apache.qpid.server.model.VirtualHostAlias; import org.apache.qpid.server.util.Action; public class BrokerStoreUpgraderAndRecoverer @@ -49,6 +53,7 @@ public class BrokerStoreUpgraderAndRecoverer register(new Upgrader_1_1_to_1_2()); register(new Upgrader_1_2_to_1_3()); register(new Upgrader_1_3_to_2_0()); + register(new Upgrader_2_0_to_2_1()); } private void register(StoreUpgraderPhase upgrader) @@ -207,6 +212,71 @@ public class BrokerStoreUpgraderAndRecoverer } } + private class Upgrader_2_0_to_2_1 extends StoreUpgraderPhase + { + public Upgrader_2_0_to_2_1() + { + super("modelVersion", "2.0", "2.1"); + } + + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + if(record.getType().equals("Port") && isAmqpPort(record.getAttributes())) + { + createAliasRecord(record, "nameAlias", "nameAlias"); + createAliasRecord(record, "defaultAlias", "defaultAlias"); + createAliasRecord(record, "hostnameAlias", "hostnameAlias"); + + } + else if(record.getType().equals("User") && "scram".equals(record.getAttributes().get("type")) ) + { + Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); + updatedAttributes.put("type", "managed"); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); + getUpdateMap().put(record.getId(), record); + } + else if (record.getType().equals("Broker")) + { + record = upgradeRootRecord(record); + } + + getNextUpgrader().configuredObject(record); + } + + private boolean isAmqpPort(final Map<String, Object> attributes) + { + Object type = attributes.get(ConfiguredObject.TYPE); + Object protocols = attributes.get(Port.PROTOCOLS); + String protocolString = protocols == null ? null : protocols.toString(); + return "AMQP".equals(type) + || protocolString == null + || !protocolString.matches(".*\\w.*") + || protocolString.contains("AMQP"); + + } + + private void createAliasRecord(ConfiguredObjectRecord parent, String name, String type) + { + Map<String,Object> attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, name); + attributes.put(VirtualHostAlias.TYPE, type); + + final ConfiguredObjectRecord record = new ConfiguredObjectRecordImpl(UUID.randomUUID(), + "VirtualHostAlias", + attributes, + Collections.singletonMap("Port", parent.getId())); + getUpdateMap().put(record.getId(), record); + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + + } private static class VirtualHostEntryUpgrader { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java index 5f1c0b4b7f..8d8b62ffdd 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java @@ -98,7 +98,8 @@ public class ConfiguredObjectRecordConverter for(Class<? extends ConfiguredObject> childClass : childClasses) { final String childType = childClass.getSimpleName(); - String attrName = childType.toLowerCase() + "s"; + String singularName = childType.toLowerCase(); + String attrName = singularName + (singularName.endsWith("s") ? "es" : "s"); Object children = data.remove(attrName); if(children != null) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java index 2d1b08aa50..8044afafdc 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java @@ -79,7 +79,7 @@ public class ConfiguredObjectRecordImpl implements ConfiguredObjectRecord @Override public String toString() { - return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + "]"; + return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + ", parents=" + _parents + "]"; } @Override diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java index 55de8f6852..b3e9d39a55 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java @@ -445,7 +445,8 @@ public class JsonFileConfigStore implements DurableConfigurationStore // only add if this is the "first" parent if(_parent.getModel().getParentTypes(childClass).iterator().next() == type) { - String attrName = childClass.getSimpleName().toLowerCase() + "s"; + String singularName = childClass.getSimpleName().toLowerCase(); + String attrName = singularName + (singularName.endsWith("s") ? "es" : "s"); List<UUID> childIds = _idsByType.get(childClass.getSimpleName()); if(childIds != null) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java index 5565ea6175..f1372882a8 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java @@ -61,6 +61,7 @@ public class VirtualHostStoreUpgraderAndRecoverer register(new Upgrader_0_2_to_0_3()); register(new Upgrader_0_3_to_0_4()); register(new Upgrader_0_4_to_2_0()); + register(new Upgrader_2_0_to_2_1()); Map<String, UUID> defaultExchangeIds = new HashMap<String, UUID>(); for (String exchangeName : DEFAULT_EXCHANGES.keySet()) @@ -400,6 +401,32 @@ public class VirtualHostStoreUpgraderAndRecoverer } + private class Upgrader_2_0_to_2_1 extends StoreUpgraderPhase + { + public Upgrader_2_0_to_2_1() + { + super("modelVersion", "2.0", "2.1"); + } + + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + + if("VirtualHost".equals(record.getType())) + { + record = upgradeRootRecord(record); + } + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + + } + public void perform(DurableConfigurationStore durableConfigurationStore) { String virtualHostCategory = VirtualHost.class.getSimpleName(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java index e6bf0c1f89..b1f6b84b72 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java @@ -42,13 +42,13 @@ class TCPandSSLTransport implements AcceptingTransport private Set<Transport> _transports; private SSLContext _sslContext; private InetSocketAddress _bindingSocketAddress; - private Port<?> _port; + private AmqpPort<?> _port; private Set<Protocol> _supported; private Protocol _defaultSupportedProtocolReply; TCPandSSLTransport(final Set<Transport> transports, final SSLContext sslContext, - final Port<?> port, + final AmqpPort<?> port, final Set<Protocol> supported, final Protocol defaultSupportedProtocolReply) { @@ -62,12 +62,12 @@ class TCPandSSLTransport implements AcceptingTransport @Override public void start() { - String bindingAddress = (String) _port.getAttribute(Port.BINDING_ADDRESS); + String bindingAddress = ((AmqpPort<?>)_port).getBindingAddress(); if (WILDCARD_ADDRESS.equals(bindingAddress)) { bindingAddress = null; } - Integer port = (Integer) _port.getAttribute(Port.PORT); + int port = _port.getPort(); if ( bindingAddress == null ) { _bindingSocketAddress = new InetSocketAddress(port); @@ -91,6 +91,11 @@ class TCPandSSLTransport implements AcceptingTransport _networkTransport.accept(settings, protocolEngineFactory, _transports.contains(Transport.TCP) ? null : _sslContext); } + public int getAcceptingPort() + { + return _networkTransport.getAcceptingPort(); + } + @Override public void close() { @@ -106,31 +111,31 @@ class TCPandSSLTransport implements AcceptingTransport @Override public boolean wantClientAuth() { - return (Boolean)_port.getAttribute(Port.WANT_CLIENT_AUTH); + return _port.getWantClientAuth(); } @Override public boolean needClientAuth() { - return (Boolean)_port.getAttribute(Port.NEED_CLIENT_AUTH); + return _port.getNeedClientAuth(); } @Override public Boolean getTcpNoDelay() { - return (Boolean)_port.getAttribute(Port.TCP_NO_DELAY); + return _port.isTcpNoDelay(); } @Override public Integer getSendBufferSize() { - return (Integer)_port.getAttribute(AmqpPort.SEND_BUFFER_SIZE); + return _port.getSendBufferSize(); } @Override public Integer getReceiveBufferSize() { - return (Integer)_port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE); + return _port.getReceiveBufferSize(); } @Override diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java index 7c7d0ea9e6..fa0d9bfcff 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java @@ -24,16 +24,16 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; class TCPandSSLTransportProvider implements TransportProvider { @Override public AcceptingTransport createTransport(final Set<Transport> transports, final SSLContext sslContext, - final Port port, + final AmqpPort<?> port, final Set<Protocol> supported, final Protocol defaultSupportedProtocolReply) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java index 04b4b44c2e..24061562e5 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java @@ -24,15 +24,15 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; public interface TransportProvider { AcceptingTransport createTransport(Set<Transport> transports, SSLContext sslContext, - Port port, + AmqpPort<?> port, Set<Protocol> supported, Protocol defaultSupportedProtocolReply); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index 48077ba503..56e28bd870 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -60,7 +60,6 @@ import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.*; import org.apache.qpid.server.model.adapter.ConnectionAdapter; -import org.apache.qpid.server.model.adapter.VirtualHostAliasAdapter; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.plugin.SystemNodeCreator; import org.apache.qpid.server.protocol.AMQConnectionModel; @@ -284,18 +283,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); - - synchronized(_aliases) - { - for(Port port :_broker.getPorts()) - { - if (Protocol.hasAmqpProtocol(port.getProtocols())) - { - _aliases.add(new VirtualHostAliasAdapter(this, port)); - } - } - } - addChangeListener(new StoreUpdatingChangeListener()); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java new file mode 100644 index 0000000000..2ec2c4390e --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.FixedVirtualHostNodeAlias; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNode; + +abstract class AbstractFixedVirtualHostNodeAlias<X extends AbstractFixedVirtualHostNodeAlias<X>> + extends AbstractVirtualHostAlias<X> implements FixedVirtualHostNodeAlias<X> +{ + @ManagedAttributeField + private VirtualHostNode _virtualHostNode; + + protected AbstractFixedVirtualHostNodeAlias(final Map<String, Object> attributes, + final Port port) + { + super(attributes, port); + } + + + @Override + public VirtualHostNode<?> getVirtualHostNode() + { + return _virtualHostNode; + } + + @Override + public VirtualHostNode<?> getVirtualHostNode(final String name) + { + return matches(name) ? getVirtualHostNode() : null; + } + + protected abstract boolean matches(final String name); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java new file mode 100644 index 0000000000..bf705e5f96 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObject; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHostAlias; + +abstract class AbstractVirtualHostAlias<X extends AbstractVirtualHostAlias<X>> + extends AbstractConfiguredObject<X> implements VirtualHostAlias<X> +{ + + @ManagedAttributeField + private int _priority; + + protected AbstractVirtualHostAlias(Map<String, Object> attributes, Port port) + { + super(parentsMap(port), attributes); + } + + @Override + public Port<?> getPort() + { + return getParent(Port.class); + } + + @Override + public int getPriority() + { + return _priority; + } + + @Override + public State getState() + { + return State.ACTIVE; + } + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java new file mode 100644 index 0000000000..cab9794375 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java @@ -0,0 +1,61 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.DefaultVirtualHostAlias; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNode; + +public final class DefaultVirtualHostAliasImpl + extends AbstractVirtualHostAlias<DefaultVirtualHostAliasImpl> + implements DefaultVirtualHostAlias<DefaultVirtualHostAliasImpl> +{ + + @ManagedObjectFactoryConstructor + protected DefaultVirtualHostAliasImpl(final Map<String, Object> attributes, final Port port) + { + super(attributes, port); + } + + @Override + public VirtualHostNode getVirtualHostNode(final String name) + { + if(name == null || name.trim().equals("")) + { + Broker<?> broker = getPort().getParent(Broker.class); + String defaultHostName = broker.getDefaultVirtualHost(); + for(VirtualHostNode<?> vhn : broker.getVirtualHostNodes()) + { + if(vhn.getName().equals(defaultHostName)) + { + return vhn; + } + } + + } + return null; + } + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java new file mode 100644 index 0000000000..9abeac5f31 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java @@ -0,0 +1,193 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.HostNameAlias; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.model.port.AmqpPort; + +public class HostNameAliasImpl + extends AbstractFixedVirtualHostNodeAlias<HostNameAliasImpl> + implements HostNameAlias<HostNameAliasImpl> +{ + + private final Set<InetAddress> _localAddresses = new CopyOnWriteArraySet<>(); + private final Set<String> _localAddressNames = new CopyOnWriteArraySet<>(); + private final Lock _addressLock = new ReentrantLock(); + private final AtomicBoolean _addressesComputed = new AtomicBoolean(); + + + @ManagedObjectFactoryConstructor + protected HostNameAliasImpl(final Map<String, Object> attributes, final Port port) + { + super(attributes, port); + } + + protected void onOpen() + { + super.onOpen(); + Thread thread = new Thread(new NetworkAddressResolver(), "Network Address Resolver"); + thread.start(); + } + + + @Override + public VirtualHostNode<?> getVirtualHostNode(final String name) + { + VirtualHostNode<?> node = null; + if(matches(name)) + { + node = getVirtualHostNode(); + if(node == null) + { + Broker<?> broker = getPort().getParent(Broker.class); + String defaultHostName = broker.getDefaultVirtualHost(); + for (VirtualHostNode<?> vhn : broker.getVirtualHostNodes()) + { + if (vhn.getName().equals(defaultHostName)) + { + return vhn; + } + } + } + + } + return node; + } + + @Override + protected boolean matches(final String host) + { + while(!_addressesComputed.get()) + { + Lock lock = _addressLock; + lock.lock(); + lock.unlock(); + } + + boolean isNetworkAddress = true; + if (!_localAddressNames.contains(host)) + { + try + { + InetAddress inetAddress = InetAddress.getByName(host); + if (!_localAddresses.contains(inetAddress)) + { + isNetworkAddress = false; + } + else + { + _localAddressNames.add(host); + } + } + catch (UnknownHostException e) + { + // ignore + isNetworkAddress = false; + } + } + return isNetworkAddress; + + } + + private class NetworkAddressResolver implements Runnable + { + public void run() + { + _addressesComputed.set(false); + Lock lock = _addressLock; + + lock.lock(); + String bindingAddress = ((AmqpPort<?>)getPort()).getBindingAddress(); + try + { + Collection<InetAddress> inetAddresses; + if(bindingAddress == null || bindingAddress.trim().equals("") || bindingAddress.trim().equals("*")) + { + inetAddresses = getAllInetAddresses(); + } + else + { + inetAddresses = Collections.singleton(InetAddress.getByName(bindingAddress)); + } + for (InetAddress address : inetAddresses) + { + _localAddresses.add(address); + String hostAddress = address.getHostAddress(); + if (hostAddress != null) + { + _localAddressNames.add(hostAddress); + } + String hostName = address.getHostName(); + if (hostName != null) + { + _localAddressNames.add(hostName); + } + String canonicalHostName = address.getCanonicalHostName(); + if (canonicalHostName != null) + { + _localAddressNames.add(canonicalHostName); + } + } + } + catch (SocketException | UnknownHostException e) + { + // ignore + } + finally + { + _addressesComputed.set(true); + lock.unlock(); + } + } + + private Collection<InetAddress> getAllInetAddresses() throws SocketException + { + Set<InetAddress> addresses = new HashSet<>(); + for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) + { + for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses()) + { + addresses.add(inetAddress.getAddress()); + } + } + return addresses; + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java new file mode 100644 index 0000000000..df47b1a94e --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.PatternMatchingAlias; + +public final class PatternMatchingAliasImpl + extends AbstractFixedVirtualHostNodeAlias<PatternMatchingAliasImpl> + implements PatternMatchingAlias<PatternMatchingAliasImpl> +{ + @ManagedAttributeField + private String _pattern; + + @ManagedObjectFactoryConstructor + protected PatternMatchingAliasImpl(final Map<String, Object> attributes, final Port port) + { + super(attributes, port); + } + + @Override + protected boolean matches(final String name) + { + return name == null ? "".matches(_pattern) : name.matches(_pattern); + } + + @Override + public String getPattern() + { + return _pattern; + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java new file mode 100644 index 0000000000..f55367a89d --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNameAlias; +import org.apache.qpid.server.model.VirtualHostNode; + +public final class VirtualHostNameAliasImpl + extends AbstractVirtualHostAlias<VirtualHostNameAliasImpl> + implements VirtualHostNameAlias<VirtualHostNameAliasImpl> +{ + @ManagedObjectFactoryConstructor + protected VirtualHostNameAliasImpl(final Map<String, Object> attributes, final Port port) + { + super(attributes, port); + } + + @Override + public VirtualHostNode getVirtualHostNode(final String name) + { + Broker<?> broker = getPort().getParent(Broker.class); + for(VirtualHostNode<?> vhn : broker.getVirtualHostNodes()) + { + if(vhn.getName().equals(name)) + { + return vhn; + } + } + return null; + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java index aea07e3ed3..f4c0576d79 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java @@ -107,6 +107,11 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< return LifetimePolicy.PERMANENT; } + @Override + protected void onCreate() + { + super.onCreate(); + } @StateTransition( currentState = {State.UNINITIALIZED, State.STOPPED, State.ERRORED }, desiredState = State.ACTIVE ) protected void doActivate() diff --git a/java/broker-core/src/main/java/org/apache/qpid/tools/security/Passwd.java b/java/broker-core/src/main/java/org/apache/qpid/tools/security/Passwd.java deleted file mode 100644 index cd833c89c4..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/tools/security/Passwd.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.tools.security; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.apache.commons.codec.binary.Base64; - -/** - * Utility to generate user:encodedPassword string for use in md5passwd - */ -public class Passwd -{ - public static void main(String args[]) throws NoSuchAlgorithmException, DigestException, IOException - { - if (args.length != 2) - { - System.out.println("Passwd <username> <password>"); - System.exit(0); - } - - Passwd passwd = new Passwd(); - String output = passwd.getOutput(args[0], args[1]); - System.out.println(output); - } - - public String getOutput(String userName, String password) throws UnsupportedEncodingException, NoSuchAlgorithmException - { - byte[] data = password.getBytes("utf-8"); - - MessageDigest md = MessageDigest.getInstance("MD5"); - - for (byte b : data) - { - md.update(b); - } - - byte[] digest = md.digest(); - - Base64 b64 = new Base64(); - - byte[] encoded = b64.encode(digest); - - String encodedStr = new String(encoded, Charset.forName("utf-8")); - return userName + ":" + encodedStr; - } -} |