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[] response) throws SaslException
060 {
061 try
062 {
063 final FieldTable ft = FieldTableFactory.newFieldTable(ByteBuffer.wrap(response), response.length);
064 String username = (String) ft.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 = (String) ft.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 len) throws SaslException
114 {
115 throw new SaslException("Unsupported operation");
116 }
117
118 public byte[] wrap(byte[] outgoing, int offset, int len) throws 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 }
|