summaryrefslogtreecommitdiff
path: root/qpid/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java')
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java168
1 files changed, 168 insertions, 0 deletions
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java
new file mode 100644
index 0000000000..1b483f6948
--- /dev/null
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java
@@ -0,0 +1,168 @@
+/*
+ *
+ * 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.client.transport;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.apache.qpid.client.security.AMQCallbackHandler;
+import org.apache.qpid.client.security.CallbackHandlerRegistry;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.transport.ClientDelegate;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionException;
+import org.apache.qpid.transport.ConnectionOpenOk;
+import org.apache.qpid.transport.ConnectionSettings;
+import org.apache.qpid.transport.util.Logger;
+import org.apache.qpid.util.Strings;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+
+/**
+ *
+ */
+public class ClientConnectionDelegate extends ClientDelegate
+{
+ private static final Logger LOGGER = Logger.get(ClientDelegate.class);
+
+ private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2";
+ protected static final Oid KRB5_OID;
+
+ static
+ {
+ Oid oid;
+ try
+ {
+ oid = new Oid(KRB5_OID_STR);
+ }
+ catch (GSSException ignore)
+ {
+ oid = null;
+ }
+
+ KRB5_OID = oid;
+ }
+
+ private final ConnectionURL _connectionURL;
+
+ /**
+ * @param settings
+ * @param connectionURL
+ */
+ public ClientConnectionDelegate(ConnectionSettings settings, ConnectionURL connectionURL)
+ {
+ super(settings);
+ this._connectionURL = connectionURL;
+ }
+
+ @Override
+ protected SaslClient createSaslClient(List<Object> brokerMechs) throws ConnectionException, SaslException
+ {
+ final String brokerMechanisms = Strings.join(" ", brokerMechs);
+ final String restrictionList = _conSettings.getSaslMechs();
+ final String selectedMech = CallbackHandlerRegistry.getInstance().selectMechanism(brokerMechanisms, restrictionList);
+ if (selectedMech == null)
+ {
+ throw new ConnectionException("Client and broker have no SASL mechanisms in common." +
+ " Broker allows : " + brokerMechanisms +
+ " Client has : " + CallbackHandlerRegistry.getInstance().getMechanisms() +
+ " Client restricted itself to : " + (restrictionList != null ? restrictionList : "no restriction"));
+ }
+
+ Map<String,Object> saslProps = new HashMap<String,Object>();
+ if (_conSettings.isUseSASLEncryption())
+ {
+ saslProps.put(Sasl.QOP, "auth-conf");
+ }
+
+ final AMQCallbackHandler handler = CallbackHandlerRegistry.getInstance().createCallbackHandler(selectedMech);
+ handler.initialise(_connectionURL);
+ final SaslClient sc = Sasl.createSaslClient(new String[] {selectedMech}, null, _conSettings.getSaslProtocol(), _conSettings.getSaslServerName(), saslProps, handler);
+
+ return sc;
+ }
+
+ @Override
+ public void connectionOpenOk(Connection conn, ConnectionOpenOk ok)
+ {
+ SaslClient sc = conn.getSaslClient();
+ if (sc != null)
+ {
+ if (sc.getMechanismName().equals("GSSAPI"))
+ {
+ String id = getKerberosUser();
+ if (id != null)
+ {
+ conn.setUserID(id);
+ }
+ }
+ else if (sc.getMechanismName().equals("EXTERNAL"))
+ {
+ if (conn.getSecurityLayer() != null)
+ {
+ conn.setUserID(conn.getSecurityLayer().getUserID());
+ }
+ }
+ }
+
+ super.connectionOpenOk(conn, ok);
+ }
+
+ private String getKerberosUser()
+ {
+ LOGGER.debug("Obtaining userID from kerberos");
+ String service = _conSettings.getSaslProtocol() + "@" + _conSettings.getSaslServerName();
+ GSSManager manager = GSSManager.getInstance();
+
+ try
+ {
+ GSSName acceptorName = manager.createName(service,
+ GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
+
+ GSSContext secCtx = manager.createContext(acceptorName,
+ KRB5_OID,
+ null,
+ GSSContext.INDEFINITE_LIFETIME);
+
+ secCtx.initSecContext(new byte[0], 0, 1);
+
+ if (secCtx.getSrcName() != null)
+ {
+ return secCtx.getSrcName().toString();
+ }
+
+ }
+ catch (GSSException e)
+ {
+ LOGGER.warn("Unable to retrieve userID from Kerberos due to error",e);
+ }
+
+ return null;
+ }
+}