package org.jacorb.security.sas;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 2002-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import org.jacorb.config.Configuration;
import org.jacorb.config.ConfigurationException;
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CSIIOP.CompoundSecMechList;
import org.omg.GSSUP.GSSUPMechOID;
import org.omg.GSSUP.InitialContextToken;
import org.omg.GSSUP.InitialContextTokenHelper;
import org.omg.IOP.Codec;
import org.slf4j.Logger;
public class GssUpContext
implements ISASContext
{
private Logger logger = null;
private static String username = "";
private static String password = "";
protected InitialContextToken initialContextToken = null;
private static Oid mechOid;
static
{
try
{
mechOid = new Oid("2.23.130.1.1.1");
}
catch (GSSException e)
{
}
}
public void configure(Configuration configuration)
throws ConfigurationException
{
logger =
configuration.getLogger("org.jacorb.security.sas.GSSUP.log.verbosity");
}
public static void setUsernamePassword(String username, String password) {
GssUpContext.username = username;
GssUpContext.password = password;
}
public String getMechOID()
{
return GSSUPMechOID.value.substring(4);
}
/* (non-Javadoc)
* @see org.jacorb.security.sas.ISASContext#createContext(org.omg.PortableInterceptor.ClientRequestInfo)
*/
public byte[] createClientContext(ORB orb, Codec codec, CompoundSecMechList csmList)
{
byte[] contextToken;
if ((csmList == null) || (csmList.mechanism_list == null) || (csmList.mechanism_list.length == 0))
{
contextToken = GssUpContext.encode(orb, codec, username, password, new byte[0]);
}
else
{
// XXX: not sure how do we select mechanism so let's try to take target_name from the first one
contextToken = GssUpContext.encode(orb, codec, username, password,
csmList.mechanism_list[0].as_context_mech.target_name);
}
initialContextToken = GssUpContext.decode(orb, codec, contextToken);
return contextToken;
}
/* (non-Javadoc)
* @see org.jacorb.security.sas.ISASContext#getCreatedPrincipal()
*/
public String getClientPrincipal()
{
return username;
}
/* (non-Javadoc)
* @see org.jacorb.security.sas.ISASContext#validateContext(org.omg.PortableInterceptor.ServerRequestInfo, byte[])
*/
public boolean validateContext(ORB orb, Codec codec, byte[] contextToken)
{
initialContextToken = GssUpContext.decode(orb, codec, contextToken);
return (initialContextToken != null);
}
/* (non-Javadoc)
* @see org.jacorb.security.sas.ISASContext#getValidatedPrincipal()
*/
public String getValidatedPrincipal() {
if (initialContextToken == null) return null;
return new String(initialContextToken.username);
}
/* (non-Javadoc)
* @see org.jacorb.security.sas.ISASContext#initClient()
*/
public void initClient() {
}
/* (non-Javadoc)
* @see org.jacorb.security.sas.ISASContext#initTarget()
*/
public void initTarget() {
}
public static byte[] encode(ORB orb, Codec codec, String username, String password, byte[] target_name)
{
InitialContextToken subject = null;
try
{
subject = new InitialContextToken( username.getBytes("UTF-8"),
password.getBytes("UTF-8"),
target_name);
}
catch(java.io.UnsupportedEncodingException e)
{
//should never happen
// logger.error("Error creating InitialContextToken: " + e);
return new byte[0];
}
byte[] out = null;
Any any = orb.create_any();
InitialContextTokenHelper.insert( any, subject );
try
{
out = codec.encode_value( any );
}
catch (Exception e)
{
// logger.error("Error encoding for GSSNameSpi: " + e);
return new byte[0];
}
byte[] mechOidArray = null;
try
{
mechOidArray = mechOid.getDER();
}
catch(org.ietf.jgss.GSSException e)
{
// logger.error("Error retrieving mechOid DER: " + e);
return new byte[0];
}
int length = out.length + mechOidArray.length;
byte[] encodedLength = null;
if((length >> 7) == 0)
{
//length fits into 7 bit
encodedLength = new byte[]{(byte) 0x60,
(byte) length};
}
else if((length >> 14) == 0)
{
//length fits into 14 bit
encodedLength = new byte[]{(byte) 0x60,
(byte) ((length >> 7) | 0x80),
(byte) (length & 0x7F)};
}
else if((length >> 21) == 0)
{
//length fits into 21 bit
encodedLength = new byte[]{(byte) 0x60,
(byte) ((length >> 14) | 0x80),
(byte) (((length >> 7) & 0x7F) | 0x80),
(byte) (length & 0x7F)};
}
else if((length >> 28) == 0)
{
//length fits into 28 bit
encodedLength = new byte[]{(byte) 0x60,
(byte) ((length >> 21) | 0x80),
(byte) (((length >> 14) & 0x7F) | 0x80),
(byte) (((length >> 7) & 0x7F) | 0x80),
(byte) (length & 0x7F)};
}
else
{
//length fits into 32 bit
encodedLength = new byte[]{(byte) 0x60,
(byte) ((length >> 28) | 0x80),
(byte) (((length >> 21) & 0x7F) | 0x80),
(byte) (((length >> 14) & 0x7F) | 0x80),
(byte) (((length >> 7) & 0x7F) | 0x80),
(byte) (length & 0x7F)};
}
byte[] completeContext = new byte[length + encodedLength.length];
System.arraycopy(encodedLength, 0,
completeContext, 0,
encodedLength.length);
System.arraycopy(mechOidArray, 0,
completeContext, encodedLength.length,
mechOidArray.length);
System.arraycopy(out, 0,
completeContext, encodedLength.length + mechOidArray.length,
out.length);
return completeContext;
}
public static byte[] encode(ORB orb, Codec codec, String username, char[] password, String target_name)
{
return encode(orb, codec, username, new String(password), target_name.getBytes());
}
public static InitialContextToken decode(ORB orb, Codec codec, byte[] gssToken)
{
if(gssToken[0] != 0x60)
{
// logger.error("GSSToken doesn't start with expected value '0x60'");
return null;
}
//skip total size, the GSSToken already has the correct length
//find first octet where the MSB is zero
int index = 1;
while(index < gssToken.length &&
(gssToken[index] & 0x80) == 1)
{
++index;
}
if(index == gssToken.length)
{
//end not found
// logger.error("GSSToken doesn't contain valid length");
return null;
}
byte[] mechOidArray = null;
try
{
mechOidArray = mechOid.getDER();
}
catch(org.ietf.jgss.GSSException e)
{
// logger.error("Error retrieving mechOid DER: " + e);
return null;
}
//skip last octet of length
++index;
if((index + mechOidArray.length) >= gssToken.length)
{
// logger.error("GSSToken doesn't contain OID");
return null;
}
for(int i = 0; i < mechOidArray.length; ++i)
{
if(mechOidArray[i] != gssToken[index + i])
{
// logger.error("GSSToken doesn't contain GSSUPMechOID");
return null;
}
}
//skip oid
index += mechOidArray.length;
byte[] icToken = new byte[gssToken.length - index];
System.arraycopy(gssToken, index, icToken, 0, icToken.length);
try
{
Any any =
codec.decode_value(
icToken,
InitialContextTokenHelper.type());
return InitialContextTokenHelper.extract(any);
}
catch (Exception e)
{
// logger.error("Error decoding for GSSNameSpi: " + e);
}
//logger.error("Bailout - GSSUP");
return null;
}
}