ConnectionStartOkMethodHandler.java
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 channelIdthrows 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