001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.server.handler;
022
023 import javax.security.sasl.SaslException;
024 import javax.security.sasl.SaslServer;
025
026 import org.apache.log4j.Logger;
027 import org.apache.qpid.AMQException;
028 import org.apache.qpid.framing.ConnectionCloseBody;
029 import org.apache.qpid.framing.ConnectionSecureBody;
030 import org.apache.qpid.framing.ConnectionStartOkBody;
031 import org.apache.qpid.framing.ConnectionTuneBody;
032 import org.apache.qpid.framing.MethodRegistry;
033 import org.apache.qpid.protocol.AMQConstant;
034 import org.apache.qpid.server.configuration.ServerConfiguration;
035 import org.apache.qpid.server.protocol.AMQProtocolSession;
036 import org.apache.qpid.server.registry.ApplicationRegistry;
037 import org.apache.qpid.server.security.auth.AuthenticationResult;
038 import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
039 import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
040 import org.apache.qpid.server.state.AMQState;
041 import org.apache.qpid.server.state.AMQStateManager;
042 import org.apache.qpid.server.state.StateAwareMethodListener;
043
044
045 public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<ConnectionStartOkBody>
046 {
047 private static final Logger _logger = Logger.getLogger(ConnectionStartOkMethodHandler.class);
048
049 private static ConnectionStartOkMethodHandler _instance = new ConnectionStartOkMethodHandler();
050
051 public static ConnectionStartOkMethodHandler getInstance()
052 {
053 return _instance;
054 }
055
056 private ConnectionStartOkMethodHandler()
057 {
058 }
059
060 public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException
061 {
062 AMQProtocolSession session = stateManager.getProtocolSession();
063
064 _logger.info("SASL Mechanism selected: " + body.getMechanism());
065 _logger.info("Locale selected: " + body.getLocale());
066
067 AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();//session.getVirtualHost().getAuthenticationManager();
068
069 SaslServer ss = null;
070 try
071 {
072 ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN());
073
074 if (ss == null)
075 {
076 throw body.getConnectionException(AMQConstant.RESOURCE_ERROR, "Unable to create SASL Server:" + body.getMechanism()
077 );
078 }
079
080 session.setSaslServer(ss);
081
082 AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
083
084 //save clientProperties
085 if (session.getClientProperties() == null)
086 {
087 session.setClientProperties(body.getClientProperties());
088 }
089
090 MethodRegistry methodRegistry = session.getMethodRegistry();
091
092 switch (authResult.status)
093 {
094 case ERROR:
095 Exception cause = authResult.getCause();
096
097 _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
098
099 stateManager.changeState(AMQState.CONNECTION_CLOSING);
100
101 ConnectionCloseBody closeBody =
102 methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
103 AMQConstant.NOT_ALLOWED.getName(),
104 body.getClazz(),
105 body.getMethod());
106
107 session.writeFrame(closeBody.generateFrame(0));
108 disposeSaslServer(session);
109 break;
110
111 case SUCCESS:
112 _logger.info("Connected as: " + ss.getAuthorizationID());
113 session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
114
115 stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
116
117 ConnectionTuneBody tuneBody = methodRegistry.createConnectionTuneBody(0xFFFF,
118 getConfiguredFrameSize(),
119 ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
120 session.writeFrame(tuneBody.generateFrame(0));
121 break;
122 case CONTINUE:
123 stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
124
125 ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
126 session.writeFrame(secureBody.generateFrame(0));
127 }
128 }
129 catch (SaslException e)
130 {
131 disposeSaslServer(session);
132 throw new AMQException("SASL error: " + e, e);
133 }
134 }
135
136 private void disposeSaslServer(AMQProtocolSession ps)
137 {
138 SaslServer ss = ps.getSaslServer();
139 if (ss != null)
140 {
141 ps.setSaslServer(null);
142 try
143 {
144 ss.dispose();
145 }
146 catch (SaslException e)
147 {
148 _logger.error("Error disposing of Sasl server: " + e);
149 }
150 }
151 }
152
153 static int getConfiguredFrameSize()
154 {
155 final ServerConfiguration config = ApplicationRegistry.getInstance().getConfiguration();
156 final int framesize = config.getFrameSize();
157 _logger.info("Framesize set to " + framesize);
158 return framesize;
159 }
160 }
161
162
|