AmqPlainSaslServer.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.security.auth.sasl.amqplain;
022 
023 import java.io.IOException;
024 
025 import javax.security.auth.callback.Callback;
026 import javax.security.auth.callback.CallbackHandler;
027 import javax.security.auth.callback.NameCallback;
028 import javax.security.auth.callback.PasswordCallback;
029 import javax.security.auth.callback.UnsupportedCallbackException;
030 import javax.security.sasl.AuthorizeCallback;
031 import javax.security.sasl.SaslException;
032 import javax.security.sasl.SaslServer;
033 
034 import org.apache.mina.common.ByteBuffer;
035 import org.apache.qpid.framing.AMQFrameDecodingException;
036 import org.apache.qpid.framing.FieldTable;
037 import org.apache.qpid.framing.FieldTableFactory;
038 
039 public class AmqPlainSaslServer implements SaslServer
040 {
041     public static final String MECHANISM = "AMQPLAIN";
042 
043     private CallbackHandler _cbh;
044 
045     private String _authorizationId;
046 
047     private boolean _complete = false;
048 
049     public AmqPlainSaslServer(CallbackHandler cbh)
050     {
051         _cbh = cbh;
052     }
053 
054     public String getMechanismName()
055     {
056         return MECHANISM;
057     }
058 
059     public byte[] evaluateResponse(byte[] responsethrows SaslException
060     {
061         try
062         {
063             final FieldTable ft = FieldTableFactory.newFieldTable(ByteBuffer.wrap(response), response.length);
064             String username = (Stringft.getString("LOGIN");
065             // we do not care about the prompt but it throws if null
066             NameCallback nameCb = new NameCallback("prompt", username);
067             // we do not care about the prompt but it throws if null
068             PasswordCallback passwordCb = new PasswordCallback("prompt"false);
069             // TODO: should not get pwd as a String but as a char array...
070             String pwd = (Stringft.getString("PASSWORD");
071             AuthorizeCallback authzCb = new AuthorizeCallback(username, username);
072             Callback[] callbacks = new Callback[]{nameCb, passwordCb, authzCb};
073             _cbh.handle(callbacks);
074             String storedPwd = new String(passwordCb.getPassword());
075             if (storedPwd.equals(pwd))
076             {
077                 _complete = true;
078             }
079             if (authzCb.isAuthorized() && _complete)
080             {
081                 _authorizationId = authzCb.getAuthenticationID();
082                 return null;
083             }
084             else
085             {
086                 throw new SaslException("Authentication failed");
087             }
088         }
089         catch (AMQFrameDecodingException e)
090         {
091             throw new SaslException("Unable to decode response: " + e, e);
092         }
093         catch (IOException e)
094         {
095             throw new SaslException("Error processing data: " + e, e);
096         }
097         catch (UnsupportedCallbackException e)
098         {
099             throw new SaslException("Unable to obtain data from callback handler: " + e, e);
100         }
101     }
102 
103     public boolean isComplete()
104     {
105         return _complete;
106     }
107 
108     public String getAuthorizationID()
109     {
110         return _authorizationId;
111     }
112 
113     public byte[] unwrap(byte[] incoming, int offset, int lenthrows SaslException
114     {
115         throw new SaslException("Unsupported operation");
116     }
117 
118     public byte[] wrap(byte[] outgoing, int offset, int lenthrows SaslException
119     {
120         throw new SaslException("Unsupported operation");
121     }
122 
123     public Object getNegotiatedProperty(String propName)
124     {
125         return null;
126     }
127 
128     public void dispose() throws SaslException
129     {
130         _cbh = null;
131     }
132 }