/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed 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.wildfly.security.sasl.test;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.RealmCallback;
import javax.security.sasl.SaslException;
import org.junit.Assert;
import org.wildfly.security.auth.callback.AnonymousAuthorizationCallback;
import org.wildfly.security.auth.callback.ChannelBindingCallback;
import org.wildfly.security.auth.callback.CredentialCallback;
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
import org.wildfly.security.auth.callback.FastUnsupportedCallbackException;
import org.wildfly.security.credential.PasswordCredential;
import org.wildfly.security.evidence.PasswordGuessEvidence;
import org.wildfly.security.password.Password;
import org.wildfly.security.password.PasswordFactory;
/**
* A server side callback handler for use with the test cases to trigger
* required failures.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
* @deprecated Use real callback handlers where possible
*/
@Deprecated
public class ServerCallbackHandler implements CallbackHandler {
private final String expectedUsername;
private final char[] expectedPassword;
private final String expectedAuthzid;
private final KeySpec keySpec;
private final String algorithm;
private String bindingType = null;
private byte[] bindingData = null;
public ServerCallbackHandler(final String expectedUsername, final char[] expectedPassword) {
this.expectedUsername = expectedUsername;
this.expectedPassword = expectedPassword;
expectedAuthzid = null;
keySpec = null;
algorithm = null;
}
public ServerCallbackHandler(final String expectedUsername, final String algorithm, KeySpec keyspec) {
this.expectedUsername = expectedUsername;
this.algorithm = algorithm;
this.keySpec = keyspec;
expectedAuthzid = null;
expectedPassword = null;
}
public ServerCallbackHandler(final String expectedUsername, final String algorithm, KeySpec keyspec, String authzid) {
this.expectedUsername = expectedUsername;
this.algorithm = algorithm;
this.keySpec = keyspec;
expectedAuthzid = authzid;
expectedPassword = null;
}
public void setBinding(String bindingType, byte[] bindingData){
this.bindingType = bindingType;
this.bindingData = bindingData;
}
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback current : callbacks) {
if (current instanceof NameCallback) {
String username = ((NameCallback) current).getDefaultName();
if (username == null || username.equals(expectedUsername) == false) {
throw new SaslException("Invalid username received (expected \"" + expectedUsername + "\", received \"" + username + "\"");
}
} else if (current instanceof EvidenceVerifyCallback && expectedPassword != null) {
EvidenceVerifyCallback pvc = (EvidenceVerifyCallback) current;
pvc.setVerified(Arrays.equals(expectedPassword, pvc.applyToEvidence(PasswordGuessEvidence.class, PasswordGuessEvidence::getGuess)));
} else if (current instanceof PasswordCallback && expectedPassword != null) {
PasswordCallback pcb = (PasswordCallback) current;
pcb.setPassword(expectedPassword);
} else if (current instanceof AnonymousAuthorizationCallback) {
((AnonymousAuthorizationCallback) current).setAuthorized(true);
} else if (current instanceof AuthorizeCallback) {
AuthorizeCallback acb = (AuthorizeCallback) current;
Assert.assertEquals(expectedUsername, acb.getAuthenticationID());
if(expectedAuthzid != null){
acb.setAuthorized(expectedAuthzid.equals(acb.getAuthorizationID()));
}else{
acb.setAuthorized(expectedUsername.equals(acb.getAuthorizationID()));
}
} else if (current instanceof RealmCallback) {
} else if (current instanceof CredentialCallback && algorithm != null && keySpec != null) {
CredentialCallback ccb = (CredentialCallback) current;
try {
PasswordFactory passwordFactory = PasswordFactory.getInstance(algorithm);
Password password = passwordFactory.generatePassword(keySpec);
if (ccb.isCredentialTypeSupported(PasswordCredential.class, password.getAlgorithm())) {
ccb.setCredential(new PasswordCredential(password));
} else {
throw new FastUnsupportedCallbackException(current);
}
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new IOException("Password object generation failed", e);
}
} else if (current instanceof ChannelBindingCallback && bindingType != null) {
ChannelBindingCallback cbc = (ChannelBindingCallback) current;
cbc.setBindingType(bindingType);
cbc.setBindingData(bindingData);
} else {
throw new UnsupportedCallbackException(current, current.getClass().getSimpleName() + " not supported.");
}
}
}
}