package org.jboss.iiop.csiv2;
import java.net.InetAddress;
import java.io.UnsupportedEncodingException;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.ORB;
import org.omg.IOP.Codec;
import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
import org.omg.IOP.TaggedComponent;
import org.omg.CSI.ITTAbsent;
import org.omg.CSI.ITTAnonymous;
import org.omg.CSI.ITTPrincipalName;
import org.omg.CSI.ITTX509CertChain;
import org.omg.CSI.ITTDistinguishedName;
import org.omg.CSIIOP.AS_ContextSec;
import org.omg.CSIIOP.CompoundSecMech;
import org.omg.CSIIOP.CompoundSecMechList;
import org.omg.CSIIOP.CompoundSecMechListHelper;
import org.omg.CSIIOP.Confidentiality;
import org.omg.CSIIOP.DetectMisordering;
import org.omg.CSIIOP.DetectReplay;
import org.omg.CSIIOP.EstablishTrustInClient;
import org.omg.CSIIOP.EstablishTrustInTarget;
import org.omg.CSIIOP.IdentityAssertion;
import org.omg.CSIIOP.Integrity;
import org.omg.CSIIOP.SAS_ContextSec;
import org.omg.CSIIOP.ServiceConfiguration;
import org.omg.CSIIOP.TAG_CSI_SEC_MECH_LIST;
import org.omg.CSIIOP.TAG_NULL_TAG;
import org.omg.CSIIOP.TAG_TLS_SEC_TRANS;
import org.omg.CSIIOP.TLS_SEC_TRANS;
import org.omg.CSIIOP.TLS_SEC_TRANSHelper;
import org.omg.CSIIOP.TransportAddress;
import org.omg.GSSUP.GSSUPMechOID;
import org.omg.GSSUP.InitialContextToken;
import org.omg.GSSUP.InitialContextTokenHelper;
import org.omg.PortableInterceptor.ClientRequestInfo;
import org.omg.SSLIOP.SSL;
import org.omg.SSLIOP.SSLHelper;
import org.omg.SSLIOP.TAG_SSL_SEC_TRANS;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import org.jboss.metadata.IorSecurityConfigMetaData;
import org.jboss.metadata.IorSecurityConfigMetaData.TransportConfig;
import org.jboss.metadata.IorSecurityConfigMetaData.AsContext;
import org.jboss.metadata.IorSecurityConfigMetaData.SasContext;
import org.jboss.logging.Logger;
public final class CSIv2Util
{
private static final Logger log = Logger.getLogger(CSIv2Util.class);
private static final byte[] gssUpMechOidArray = createGSSUPMechOID();
private CSIv2Util()
{
}
public static TaggedComponent createCopy(TaggedComponent tc)
{
TaggedComponent copy = null;
if( tc != null )
{
byte[] buf = new byte[tc.component_data.length];
System.arraycopy(tc.component_data, 0, buf, 0, tc.component_data.length);
copy = new TaggedComponent(tc.tag, buf);
}
return copy;
}
public static TaggedComponent createSSLTaggedComponent(
IorSecurityConfigMetaData metadata,
Codec codec,
int sslPort,
ORB orb)
{
if( metadata == null )
{
log.debug("createSSLTaggedComponent() called with null metadata");
return null;
}
TaggedComponent tc = null;
try
{
int supports = createTargetSupports(metadata.getTransportConfig());
int requires = createTargetRequires(metadata.getTransportConfig());
SSL ssl = new SSL((short) supports, (short) requires, (short) sslPort);
Any any = orb.create_any();
SSLHelper.insert(any, ssl);
byte[] componentData = codec.encode_value(any);
tc = new TaggedComponent(TAG_SSL_SEC_TRANS.value, componentData);
}
catch(InvalidTypeForEncoding e)
{
log.warn("Caught unexcepted exception while encoding SSL component", e);
throw new RuntimeException(e);
}
return tc;
}
public static TaggedComponent createSecurityTaggedComponent(
IorSecurityConfigMetaData metadata,
Codec codec,
int sslPort,
ORB orb
)
{
if( metadata == null )
{
log.debug("createSecurityTaggedComponent() called with null metadata");
return null;
}
TaggedComponent tc = null;
CompoundSecMech[] mechList =
createCompoundSecMechanisms(metadata, codec, sslPort, orb);
CompoundSecMechList csmList = new CompoundSecMechList(false,
mechList);
try
{
Any any = orb.create_any();
CompoundSecMechListHelper.insert(any, csmList);
byte[] b = codec.encode_value(any);
tc = new TaggedComponent(TAG_CSI_SEC_MECH_LIST.value, b);
}
catch(InvalidTypeForEncoding e)
{
log.warn("Caught unexcepted exception while encoding CompoundSecMechList", e);
throw new RuntimeException(e);
}
return tc;
}
public static CompoundSecMech[] createCompoundSecMechanisms(
IorSecurityConfigMetaData metadata,
Codec codec,
int sslPort,
ORB orb
)
{
CompoundSecMech[] csmList = new CompoundSecMech[1];
TaggedComponent transport_mech = createTransportMech(
metadata.getTransportConfig(), codec, sslPort, orb
);
AS_ContextSec asContext = createAuthenticationServiceContext(metadata);
SAS_ContextSec sasContext = createSecureAttributeServiceContext(metadata);
int target_requires =
createTargetRequires(metadata.getTransportConfig()) |
asContext.target_requires |
sasContext.target_requires;
CompoundSecMech csm = new CompoundSecMech((short) target_requires,
transport_mech,
asContext,
sasContext);
csmList[0] = csm;
return csmList;
}
public static SAS_ContextSec createSecureAttributeServiceContext(
IorSecurityConfigMetaData metadata
)
{
SAS_ContextSec context = null;
int support = 0;
int require = 0;
ServiceConfiguration[] privilAuth = new ServiceConfiguration[0];
byte[][] supNamMechs = {};
int supIdenTypes = 0;
SasContext sasMeta = metadata.getSasContext();
if( sasMeta == null || !sasMeta.isCallerPropagationSupported() )
{
context = new SAS_ContextSec((short) support,
(short) require,
privilAuth,
supNamMechs,
supIdenTypes);
}
else
{
support = IdentityAssertion.value;
byte[] upMech = createGSSUPMechOID();
supNamMechs = new byte[1][upMech.length];
System.arraycopy(upMech, 0, supNamMechs[0], 0, upMech.length);
supIdenTypes = ITTAnonymous.value |
ITTPrincipalName.value |
ITTX509CertChain.value |
ITTDistinguishedName.value;
context = new SAS_ContextSec((short) support,
(short) require,
privilAuth,
supNamMechs,
supIdenTypes);
}
return context;
}
public static AS_ContextSec createAuthenticationServiceContext(
IorSecurityConfigMetaData metadata
)
{
AS_ContextSec context = null;
int support = 0;
int require = 0;
byte[] clientAuthMech = {};
byte[] targetName = {};
AsContext asMeta = metadata.getAsContext();
if( asMeta == null || asMeta.getAuthMethod().equals(AsContext.AUTH_METHOD_NONE)
|| asMeta.isRequired() == false )
{
context = new AS_ContextSec((short) support,
(short) require,
clientAuthMech,
targetName);
}
else
{
support = EstablishTrustInClient.value;
if( asMeta.isRequired() )
require = EstablishTrustInClient.value;
clientAuthMech = createGSSUPMechOID();
String realm = asMeta.getRealm();
targetName = createGSSExportedName(clientAuthMech, realm.getBytes());
context = new AS_ContextSec((short) support,
(short) require,
clientAuthMech,
targetName);
}
return context;
}
public static TaggedComponent createTransportMech(
TransportConfig tconfig,
Codec codec,
int sslPort,
ORB orb
)
{
TaggedComponent tc = null;
int support = 0;
int require = 0;
if( tconfig != null )
{
require = createTargetRequires(tconfig);
support = createTargetSupports(tconfig);
}
if( tconfig == null || support == 0 || sslPort < 0 )
{
tc = new TaggedComponent(TAG_NULL_TAG.value, new byte[0]);
}
else
{
String host;
try
{
host = InetAddress.getLocalHost().getHostAddress();
}
catch(java.net.UnknownHostException e)
{
host = "127.0.0.1";
}
TransportAddress[] taList = createTransportAddress(host, sslPort);
TLS_SEC_TRANS tst = new TLS_SEC_TRANS((short) support,
(short) require,
taList);
try
{
Any any = orb.create_any();
TLS_SEC_TRANSHelper.insert(any, tst);
byte[] b = codec.encode_value(any);
tc = new TaggedComponent(TAG_TLS_SEC_TRANS.value, b);
}
catch(InvalidTypeForEncoding e)
{
log.warn("Caught unexcepted exception while encoding TLS_SEC_TRANS", e);
throw new RuntimeException(e);
}
}
return tc;
}
public static TransportAddress[] createTransportAddress(
String host, int port
)
{
short short_port = (port > 32767) ? (short) (port - 65536) : (short) port;
TransportAddress ta = new TransportAddress(host, short_port);
TransportAddress[] taList = new TransportAddress[1];
taList[0] = ta;
return taList;
}
public static int createTargetRequires(TransportConfig tc)
{
int requires = 0;
if( tc != null )
{
if( tc.getIntegrity().equals(TransportConfig.INTEGRITY_REQUIRED) )
requires = requires | Integrity.value;
if( tc.getConfidentiality().equals(TransportConfig.CONFIDENTIALITY_REQUIRED) )
requires = requires | Confidentiality.value;
if( tc.getDetectMisordering().equalsIgnoreCase(TransportConfig.DETECT_MISORDERING_REQUIRED) )
requires = requires | DetectMisordering.value;
if( tc.getDetectReplay().equalsIgnoreCase(TransportConfig.DETECT_REPLAY_REQUIRED) )
requires = requires | DetectReplay.value;
if( tc.getEstablishTrustInClient().equals(TransportConfig.ESTABLISH_TRUST_IN_CLIENT_REQUIRED) )
requires = requires | EstablishTrustInClient.value;
}
return requires;
}
public static int createTargetSupports(TransportConfig tc)
{
int supports = 0;
if( tc != null )
{
if( !tc.getIntegrity().equals(TransportConfig.INTEGRITY_NONE) )
supports = supports | Integrity.value;
if( !tc.getConfidentiality().equals(TransportConfig.CONFIDENTIALITY_NONE) )
supports = supports | Confidentiality.value;
if( !tc.getDetectMisordering().equalsIgnoreCase(TransportConfig.DETECT_MISORDERING_NONE) )
supports = supports | DetectMisordering.value;
if( !tc.getDetectReplay().equalsIgnoreCase(TransportConfig.DETECT_REPLAY_NONE) )
supports = supports | DetectReplay.value;
if( !tc.getEstablishTrustInTarget().equals(TransportConfig.ESTABLISH_TRUST_IN_TARGET_NONE) )
supports = supports | EstablishTrustInTarget.value;
if( !tc.getEstablishTrustInClient().equals(TransportConfig.ESTABLISH_TRUST_IN_CLIENT_NONE) )
supports = supports | EstablishTrustInClient.value;
}
return supports;
}
public static byte[] createGSSUPMechOID()
{
byte[] retval = {};
try
{
Oid oid = new Oid(GSSUPMechOID.value.substring(4));
retval = oid.getDER();
}
catch(GSSException e)
{
log.warn("Caught exception while encoding GSSUPMechOID", e);
}
return retval;
}
public static byte[] gssUpMechOid()
{
return (byte[])gssUpMechOidArray.clone();
}
public static byte[] createGSSExportedName(byte[] oid, byte[] name)
{
int olen = oid.length;
int nlen = name.length;
int size = 2 + 2 + olen + 4 + nlen;
byte[] buf = new byte[size];
int i = 0;
buf[i++] = 0x04;
buf[i++] = 0x01;
buf[i++] = (byte) (olen & 0xFF00);
buf[i++] = (byte) (olen & 0x00FF);
System.arraycopy(oid, 0, buf, i, olen);
i += olen;
buf[i++] = (byte) (nlen & 0xFF000000);
buf[i++] = (byte) (nlen & 0x00FF0000);
buf[i++] = (byte) (nlen & 0x0000FF00);
buf[i++] = (byte) (nlen & 0x000000FF);
System.arraycopy(name, 0, buf, i, nlen);
return buf;
}
public static byte[] encodeInitialContextToken(InitialContextToken authToken,
Codec codec)
{
byte[] out = null;
Any any = ORB.init().create_any();
InitialContextTokenHelper.insert(any, authToken);
try
{
out = codec.encode_value(any);
}
catch (Exception e)
{
return new byte[0];
}
int length = out.length + gssUpMechOidArray.length;
int n;
if (length < (1 << 7))
n = 0;
else if (length < (1 << 8))
n = 1;
else if (length < (1 << 16))
n = 2;
else if (length < (1 << 24))
n = 3;
else n = 4;
byte[] encodedToken = new byte[2 + n + length];
encodedToken[0] = 0x60;
if (n == 0)
encodedToken[1] = (byte)length;
else
{
encodedToken[1] = (byte)(n | 0x80);
switch (n)
{
case 1:
encodedToken[2] = (byte)length;
break;
case 2:
encodedToken[2] = (byte)(length >> 8);
encodedToken[3] = (byte)length;
break;
case 3:
encodedToken[2] = (byte)(length >> 16);
encodedToken[3] = (byte)(length >> 8);
encodedToken[4] = (byte)length;
break;
default: encodedToken[2] = (byte)(length >> 24);
encodedToken[3] = (byte)(length >> 16);
encodedToken[4] = (byte)(length >> 8);
encodedToken[5] = (byte)length;
}
}
System.arraycopy(gssUpMechOidArray, 0,
encodedToken, 2 + n,
gssUpMechOidArray.length);
System.arraycopy(out, 0,
encodedToken, 2 + n + gssUpMechOidArray.length,
out.length);
return encodedToken;
}
public static InitialContextToken decodeInitialContextToken(
byte[] encodedToken,
Codec codec)
{
if(encodedToken[0] != 0x60)
return null;
int encodedLength = 0;
int n = 0;
if(encodedToken[1] >= 0)
encodedLength = encodedToken[1];
else
{
n = encodedToken[1] & 0x7F;
for(int i = 1; i <= n; i++)
encodedLength += (encodedToken[1 + i] & 0xFF) << (n-i)*8;
}
int length = encodedLength - gssUpMechOidArray.length;
byte[] encodedInitialContextToken = new byte[length];
System.arraycopy(encodedToken, 2 + n + gssUpMechOidArray.length,
encodedInitialContextToken, 0,
length);
Any any = null;
try
{
any = codec.decode_value(encodedInitialContextToken,
InitialContextTokenHelper.type());
}
catch(Exception e)
{
return null;
}
InitialContextToken contextToken =
InitialContextTokenHelper.extract(any);
return contextToken;
}
public static byte[] encodeGssExportedName(byte[] name)
{
return createGSSExportedName(gssUpMechOidArray, name);
}
public static byte[] decodeGssExportedName(byte[] encodedName)
{
if(encodedName[0] != 0x04 || encodedName[1] != 0x01)
return null;
int mechOidLength = (encodedName[2] & 0xFF) << 8; mechOidLength += (encodedName[3] & 0xFF);
byte[] oidArray = new byte[mechOidLength];
System.arraycopy(encodedName, 4,
oidArray, 0,
mechOidLength);
for(int i = 0; i < mechOidLength; i++)
{
if(gssUpMechOidArray[i] != oidArray[i])
return null;
}
int offset = 4 + mechOidLength;
int nameLength = (encodedName[ offset] & 0xFF) << 24;
nameLength += (encodedName[++offset] & 0xFF) << 16;
nameLength += (encodedName[++offset] & 0xFF) << 8;
nameLength += (encodedName[++offset] & 0xFF);
byte[] name = new byte[nameLength];
System.arraycopy(encodedName, ++offset,
name, 0,
nameLength);
return name;
}
public static CompoundSecMech getMatchingSecurityMech(ClientRequestInfo ri,
Codec codec,
short clientSupports,
short clientRequires)
{
CompoundSecMechList csmList = null;
try
{
TaggedComponent tc =
ri.get_effective_component(TAG_CSI_SEC_MECH_LIST.value);
Any any = codec.decode_value(tc.component_data,
CompoundSecMechListHelper.type());
csmList = CompoundSecMechListHelper.extract(any);
for(int i = 0; i < csmList.mechanism_list.length; i++)
{
CompoundSecMech securityMech = csmList.mechanism_list[i];
AS_ContextSec authConfig = securityMech.as_context_mech;
if( (EstablishTrustInTarget.value
& (clientRequires ^ authConfig.target_supports)
& ~authConfig.target_supports) != 0 )
{
continue; }
if( (EstablishTrustInClient.value
& (authConfig.target_requires ^ clientSupports)
& ~clientSupports) != 0 )
{
continue; }
SAS_ContextSec identityConfig = securityMech.sas_context_mech;
if( (IdentityAssertion.value
& (identityConfig.target_requires ^ clientSupports)
& ~clientSupports) != 0 )
{
continue; }
return securityMech;
}
return null;
}
catch(BAD_PARAM e)
{
return null;
}
catch(org.omg.IOP.CodecPackage.TypeMismatch e)
{
throw new MARSHAL("Unexpected exception: " + e);
}
catch(org.omg.IOP.CodecPackage.FormatMismatch e)
{
throw new MARSHAL("Unexpected exception: " + e);
}
}
public static void toString(CompoundSecMech securityMech, StringBuffer buffer)
{
AS_ContextSec asMech = securityMech != null ? securityMech.as_context_mech : null;
SAS_ContextSec sasMech = securityMech != null ? securityMech.sas_context_mech : null;
if( securityMech != null )
{
buffer.append("CompoundSecMech[");
buffer.append("target_requires: ");
buffer.append(securityMech.target_requires);
if( asMech != null )
{
buffer.append("AS_ContextSec[");
buffer.append("client_authentication_mech: ");
try
{
buffer.append(new String(asMech.client_authentication_mech, "UTF-8"));
}
catch(UnsupportedEncodingException e)
{
buffer.append(e.getMessage());
}
buffer.append(", target_name: ");
try
{
buffer.append(new String(asMech.target_name, "UTF-8"));
}
catch(UnsupportedEncodingException e)
{
buffer.append(e.getMessage());
}
buffer.append(", target_requires: ");
buffer.append(asMech.target_requires);
buffer.append(", target_supports: ");
buffer.append(asMech.target_supports);
buffer.append("]");
}
if( sasMech != null )
{
buffer.append("SAS_ContextSec[");
buffer.append("supported_identity_types: ");
buffer.append(sasMech.supported_identity_types);
buffer.append(", target_requires: ");
buffer.append(sasMech.target_requires);
buffer.append(", target_supports: ");
buffer.append(sasMech.target_supports);
buffer.append("]");
}
buffer.append("]");
}
}
}