blob: 99a1d4342c9a4a6e6764e6170e17a006b3255e41 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.qpid.management.common.sasl;
import org.apache.harmony.javax.security.auth.callback.Callback;
import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
import org.apache.harmony.javax.security.auth.callback.NameCallback;
import org.apache.harmony.javax.security.auth.callback.PasswordCallback;
import org.apache.harmony.javax.security.auth.callback.UnsupportedCallbackException;
import de.measite.smack.Sasl;
import org.apache.harmony.javax.security.sasl.SaslClient;
import org.apache.harmony.javax.security.sasl.SaslException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class PlainSaslClient implements SaslClient
{
private boolean completed;
private CallbackHandler cbh;
private String authorizationID;
private String authenticationID;
private byte password[];
private static byte SEPARATOR = 0;
public PlainSaslClient(String authorizationID, CallbackHandler cbh) throws SaslException
{
completed = false;
this.cbh = cbh;
Object[] userInfo = getUserInfo();
this.authorizationID = authorizationID;
this.authenticationID = (String) userInfo[0];
this.password = (byte[]) userInfo[1];
if (authenticationID == null || password == null)
{
throw new SaslException("PLAIN: authenticationID and password must be specified");
}
}
public byte[] evaluateChallenge(byte[] challenge) throws SaslException
{
if (completed)
{
throw new IllegalStateException("PLAIN: authentication already " +
"completed");
}
completed = true;
try
{
byte authzid[] =
authorizationID == null ? null : authorizationID.getBytes("UTF8");
byte authnid[] = authenticationID.getBytes("UTF8");
byte response[] =
new byte[
password.length +
authnid.length +
2 + // SEPARATOR
(authzid != null ? authzid.length : 0)
];
int size = 0;
if (authzid != null) {
System.arraycopy(authzid, 0, response, 0, authzid.length);
size = authzid.length;
}
response[size++] = SEPARATOR;
System.arraycopy(authnid, 0, response, size, authnid.length);
size += authnid.length;
response[size++] = SEPARATOR;
System.arraycopy(password, 0, response, size, password.length);
clearPassword();
return response;
} catch (UnsupportedEncodingException e) {
throw new SaslException("PLAIN: Cannot get UTF-8 encoding of ids",
e);
}
}
public String getMechanismName()
{
return "PLAIN";
}
public boolean hasInitialResponse()
{
return true;
}
public boolean isComplete()
{
return completed;
}
public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
{
if (completed) {
throw new IllegalStateException("PLAIN: this mechanism supports " +
"neither integrity nor privacy");
} else {
throw new IllegalStateException("PLAIN: authentication not " +
"completed");
}
}
public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
{
if (completed)
{
throw new IllegalStateException("PLAIN: this mechanism supports " +
"neither integrity nor privacy");
}
else
{
throw new IllegalStateException("PLAIN: authentication not " +
"completed");
}
}
public Object getNegotiatedProperty(String propName)
{
if (completed)
{
if (propName.equals(Sasl.QOP))
{
return "auth";
}
else
{
return null;
}
}
else
{
throw new IllegalStateException("PLAIN: authentication not " +
"completed");
}
}
private void clearPassword()
{
if (password != null)
{
for (int i = 0 ; i < password.length ; i++)
{
password[i] = 0;
}
password = null;
}
}
public void dispose() throws SaslException
{
clearPassword();
}
protected void finalize()
{
clearPassword();
}
private Object[] getUserInfo() throws SaslException
{
try
{
final String userPrompt = "PLAIN authentication id: ";
final String pwPrompt = "PLAIN password: ";
NameCallback nameCb = new NameCallback(userPrompt);
PasswordCallback passwordCb = new PasswordCallback(pwPrompt, false);
cbh.handle(new Callback[] { nameCb, passwordCb });
String userid = nameCb.getName();
char pwchars[] = passwordCb.getPassword();
byte pwbytes[];
if (pwchars != null)
{
pwbytes = (new String(pwchars)).getBytes("UTF8");
passwordCb.clearPassword();
}
else
{
pwbytes = null;
}
return (new Object[] { userid, pwbytes });
}
catch (IOException e)
{
throw new SaslException("Cannot get password", e);
}
catch (UnsupportedCallbackException e)
{
throw new SaslException("Cannot get userid/password", e);
}
}
}