/*
* JBoss, Home of Professional Open Source.
* Copyright 2015 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.gs2;
import static org.wildfly.security.sasl.gs2.Gs2.*;
import java.util.ArrayList;
import org.ietf.jgss.ChannelBinding;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import org.wildfly.security.sasl.WildFlySasl;
import org.wildfly.security.util.ByteStringBuilder;
/**
* @author <a href="mailto:fjuma@redhat.com">Farah Juma</a>
*/
class Gs2Util {
public static final int TOKEN_HEADER_TAG = 0x60;
/**
* Get the array of supported SASL mechanism names that corresponds to the given array of GSS-API
* mechanism object identifiers.
*
* @param mechanismOids the array of GSS-API mechanism object identifiers
* @return the array of supported SASL mechanism names that corresponds to the given array of GSS-API
* mechanism object identifiers
* @throws GSSException if an error occurs while mapping the GSS-API object identifiers to SASL names
*/
public static String[] getSupportedSaslNamesForMechanisms(Oid[] mechanismOids) throws GSSException {
if (mechanismOids == null) {
return WildFlySasl.NO_NAMES;
}
ArrayList<String> saslNames = new ArrayList<String>();
String name;
for (int i = 0; i < mechanismOids.length; i++) {
name = getSaslNameForMechanism(mechanismOids[i]);
// Note: SPNEGO must not be used as a GS2 mechanism (see https://tools.ietf.org/html/rfc5801#section-14.3).
// Future mechanisms that negotiate other mechanisms would need to be forbidden as well.
if (! name.equals(SPNEGO)) {
saslNames.add(name);
saslNames.add(name + PLUS_SUFFIX);
}
}
return saslNames.toArray(new String[saslNames.size()]);
}
/**
* Determine if the given mechanism name is among the given array of mechanism names.
*
* @param name the mechanism name
* @param mechanisms the array of mechanism names
* @return {@code true} if the given name is among the given mechanism names and
* {@code false} otherwise
*/
public static boolean isIncluded(String name, String[] mechanisms) {
if ((name == null) || (mechanisms == null)) {
return false;
}
for (String mechanism : mechanisms) {
if (name.equals(mechanism)) {
return true;
}
}
return false;
}
public static String[] getPlusMechanisms(String[] mechanisms) {
ArrayList<String> plusMechanisms = new ArrayList<String>();
for (String mechanism : mechanisms) {
if (mechanism.endsWith(PLUS_SUFFIX)) {
plusMechanisms.add(mechanism);
}
}
return plusMechanisms.toArray(new String[plusMechanisms.size()]);
}
/**
* Create a {@code ChannelBinding} whose application data field is set to the given GS2 header,
* concatenated with, when a gs2-cb-flag of "p" is used, the given channel binding data.
*
* @param header the GS2 header, excluding the initial gs2-nonstd-flag
* @param gs2CbFlagPUsed whether or not a gs2-cb-flag of "p" is used
* @param bindingData the channel binding data
* @return the {@code ChannelBinding}
*/
public static ChannelBinding createChannelBinding(ByteStringBuilder header, boolean gs2CbFlagPUsed, byte[] bindingData) {
byte[] appData;
if (gs2CbFlagPUsed) {
appData = (header.append(bindingData)).toArray();
} else {
appData = header.toArray();
}
return new ChannelBinding(appData);
}
}