ConnectionSecureOkMethodHandler.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.ConnectionSecureOkBody;
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.protocol.AMQProtocolSession;
035 import org.apache.qpid.server.registry.ApplicationRegistry;
036 import org.apache.qpid.server.security.auth.AuthenticationResult;
037 import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
038 import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
039 import org.apache.qpid.server.state.AMQState;
040 import org.apache.qpid.server.state.AMQStateManager;
041 import org.apache.qpid.server.state.StateAwareMethodListener;
042 
043 public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener<ConnectionSecureOkBody>
044 {
045     private static final Logger _logger = Logger.getLogger(ConnectionSecureOkMethodHandler.class);
046 
047     private static ConnectionSecureOkMethodHandler _instance = new ConnectionSecureOkMethodHandler();
048 
049     public static ConnectionSecureOkMethodHandler getInstance()
050     {
051         return _instance;
052     }
053 
054     private ConnectionSecureOkMethodHandler()
055     {
056     }
057 
058     public void methodReceived(AMQStateManager stateManager, ConnectionSecureOkBody body, int channelIdthrows AMQException
059     {
060         AMQProtocolSession session = stateManager.getProtocolSession();
061 
062         AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();
063 
064         SaslServer ss = session.getSaslServer();
065         if (ss == null)
066         {
067             throw new AMQException("No SASL context set up in session");
068         }
069         MethodRegistry methodRegistry = session.getMethodRegistry();
070         AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
071         switch (authResult.status)
072         {
073             case ERROR:
074                 Exception cause = authResult.getCause();
075 
076                 _logger.info("Authentication failed:" (cause == null "" : cause.getMessage()));
077 
078                 // This should be abstracted
079                 stateManager.changeState(AMQState.CONNECTION_CLOSING);
080 
081                 ConnectionCloseBody connectionCloseBody =
082                         methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),
083                                                                  AMQConstant.NOT_ALLOWED.getName(),
084                                                                  body.getClazz(),
085                                                                  body.getMethod());
086 
087                 session.writeFrame(connectionCloseBody.generateFrame(0));
088                 disposeSaslServer(session);
089                 break;
090             case SUCCESS:
091                 _logger.info("Connected as: " + ss.getAuthorizationID());
092                 stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
093 
094                 ConnectionTuneBody tuneBody =
095                         methodRegistry.createConnectionTuneBody(0xFFFF,
096                                                                 ConnectionStartOkMethodHandler.getConfiguredFrameSize(),
097                                                                 ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
098                 session.writeFrame(tuneBody.generateFrame(0));
099                 session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
100                 disposeSaslServer(session);
101                 break;
102             case CONTINUE:
103                 stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
104 
105                 ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
106                 session.writeFrame(secureBody.generateFrame(0));
107         }
108     }
109 
110     private void disposeSaslServer(AMQProtocolSession ps)
111     {
112         SaslServer ss = ps.getSaslServer();
113         if (ss != null)
114         {
115             ps.setSaslServer(null);
116             try
117             {
118                 ss.dispose();
119             }
120             catch (SaslException e)
121             {
122                 _logger.error("Error disposing of Sasl server: " + e);
123             }
124         }
125     }
126 }