mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Redesign of the CIFS authentication code to support NTLMv1/NTLMv2, SPNEGO and NTLMSSP
authentication methods via the session setup. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2760 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.filesys.server.auth.spnego;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.DERApplicationSpecific;
|
||||
import org.bouncycastle.asn1.DERBitString;
|
||||
import org.bouncycastle.asn1.DERGeneralString;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERObjectIdentifier;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DEROutputStream;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.bouncycastle.asn1.DERTags;
|
||||
import org.bouncycastle.asn1.DERUnknownTag;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
/**
|
||||
* NegTokenInit Class
|
||||
*
|
||||
* <p>Contains the details of an SPNEGO NegTokenInit blob for use with CIFS.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class NegTokenInit
|
||||
{
|
||||
// Mechtypes list
|
||||
|
||||
private Oid[] m_mechTypes;
|
||||
|
||||
// Context flags
|
||||
|
||||
private int m_contextFlags = -1;
|
||||
|
||||
// Mechtoken
|
||||
|
||||
private byte[] m_mechToken;
|
||||
|
||||
// MectListMIC principal
|
||||
|
||||
private String m_mecListMICPrincipal;
|
||||
|
||||
/**
|
||||
* Class constructor for decoding
|
||||
*/
|
||||
public NegTokenInit()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor for encoding
|
||||
*
|
||||
* @param mechTypes Oid[]
|
||||
* @param mechPrinciple String
|
||||
*/
|
||||
public NegTokenInit( Oid[] mechTypes, String mechPrinciple)
|
||||
{
|
||||
m_mechTypes = mechTypes;
|
||||
m_mecListMICPrincipal = mechPrinciple;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor for encoding
|
||||
*
|
||||
* @param mechTypes Vector<Oid>
|
||||
* @param mechPrinciple String
|
||||
*/
|
||||
public NegTokenInit( Vector<Oid> mechTypes, String mechPrinciple)
|
||||
{
|
||||
// Create the mechTypes array
|
||||
|
||||
m_mechTypes = new Oid[ mechTypes.size()];
|
||||
for ( int i = 0; i < mechTypes.size(); i++)
|
||||
m_mechTypes[i] = mechTypes.get(i);
|
||||
|
||||
m_mecListMICPrincipal = mechPrinciple;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mechTypes OID list
|
||||
*
|
||||
* @return Oid[]
|
||||
*/
|
||||
public final Oid[] getOids()
|
||||
{
|
||||
return m_mechTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the context flags
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getContextFlags()
|
||||
{
|
||||
return m_contextFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mechToken
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public final byte[] getMechtoken()
|
||||
{
|
||||
return m_mechToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mechListMIC principal
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getPrincipal()
|
||||
{
|
||||
return m_mecListMICPrincipal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the OID list contains the specified OID
|
||||
*
|
||||
* @param oid Oid
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasOid( Oid oid)
|
||||
{
|
||||
boolean foundOid = false;
|
||||
|
||||
if ( m_mechTypes != null)
|
||||
{
|
||||
foundOid = oid.containedIn( m_mechTypes);
|
||||
}
|
||||
|
||||
return foundOid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of OIDs
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int numberOfOids()
|
||||
{
|
||||
return m_mechTypes != null ? m_mechTypes.length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specified OID
|
||||
*
|
||||
* @param idx int
|
||||
* @return OID
|
||||
*/
|
||||
public final Oid getOidAt(int idx)
|
||||
{
|
||||
if ( m_mechTypes != null && idx >= 0 && idx < m_mechTypes.length)
|
||||
return m_mechTypes[idx];
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an SPNEGO NegTokenInit blob
|
||||
*
|
||||
* @param buf byte[]
|
||||
* @param off int
|
||||
* @param len int
|
||||
* @exception IOException
|
||||
*/
|
||||
public void decode(byte[] buf, int off, int len) throws IOException
|
||||
{
|
||||
// Create a stream around the security blob
|
||||
|
||||
ByteArrayInputStream bytStream = new ByteArrayInputStream( buf, off, len);
|
||||
ASN1InputStream asnStream = new ASN1InputStream( bytStream);
|
||||
|
||||
// Read the top level object from the security blob
|
||||
|
||||
DERObject derObj = asnStream.readObject();
|
||||
|
||||
if ( derObj instanceof DERApplicationSpecific == false)
|
||||
throw new IOException("Bad blob format (AppSpec)");
|
||||
|
||||
// Access the application specific contents
|
||||
|
||||
DERApplicationSpecific derApp = (DERApplicationSpecific) derObj;
|
||||
|
||||
ByteArrayInputStream appStream = new ByteArrayInputStream( derApp.getContents());
|
||||
ASN1InputStream asnAppStream = new ASN1InputStream( appStream);
|
||||
|
||||
// First object should be an OID, make sure it is the SPNEGO OID
|
||||
|
||||
derObj = asnAppStream.readObject();
|
||||
if ( derObj instanceof DERObjectIdentifier == false)
|
||||
throw new IOException("Bad blob format (SPNEGO OID)");
|
||||
|
||||
DERObjectIdentifier derOid = (DERObjectIdentifier) derObj;
|
||||
if ( derOid.getId().equals( OID.ID_SPNEGO) == false)
|
||||
throw new IOException("Not an SPNEGO blob");
|
||||
|
||||
// Next object should be a tagged object with a sequence
|
||||
|
||||
derObj = asnAppStream.readObject();
|
||||
if ( derObj instanceof DERTaggedObject == false)
|
||||
throw new IOException("Bad blob format, tagged object missing");
|
||||
|
||||
DERTaggedObject derTagSeq = (DERTaggedObject) derObj;
|
||||
if ( derTagSeq.getTagNo() != 0 || derTagSeq.getObject() instanceof DERSequence == false)
|
||||
throw new IOException("Bad blob format, sequence missing");
|
||||
|
||||
// Enumerate the main NegTokenInit sequence
|
||||
|
||||
DERSequence negTokInitSeq = (DERSequence) derTagSeq.getObject();
|
||||
Enumeration seqEnum = negTokInitSeq.getObjects();
|
||||
|
||||
while ( seqEnum.hasMoreElements())
|
||||
{
|
||||
// Read an object from the sequence
|
||||
|
||||
derObj = (DERObject) seqEnum.nextElement();
|
||||
if ( derObj instanceof DERTaggedObject)
|
||||
{
|
||||
// Tag 0 should be a sequence of object identifiers
|
||||
|
||||
DERTaggedObject derTag = (DERTaggedObject) derObj;
|
||||
if ( derTag.getTagNo() == 0 && derTag.getObject() instanceof DERSequence)
|
||||
{
|
||||
DERSequence derSeq = (DERSequence) derTag.getObject();
|
||||
Enumeration typesEnum = derSeq.getObjects();
|
||||
|
||||
// Allocate the OID list
|
||||
|
||||
m_mechTypes = new Oid[derSeq.size()];
|
||||
int idx = 0;
|
||||
|
||||
while( typesEnum.hasMoreElements())
|
||||
{
|
||||
derObj = (DERObject) typesEnum.nextElement();
|
||||
if ( derObj instanceof DERObjectIdentifier)
|
||||
{
|
||||
derOid = (DERObjectIdentifier) derObj;
|
||||
try
|
||||
{
|
||||
m_mechTypes[idx++] = new Oid( derOid.getId());
|
||||
}
|
||||
catch (GSSException ex)
|
||||
{
|
||||
throw new IOException("Bad mechType OID");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( derTag.getTagNo() == 1 && derTag.getObject() instanceof DERBitString)
|
||||
{
|
||||
// Context flags
|
||||
|
||||
}
|
||||
else if ( derTag.getTagNo() == 2 && derTag.getObject() instanceof DEROctetString)
|
||||
{
|
||||
// Unpack the mechToken
|
||||
|
||||
DEROctetString derStr = (DEROctetString) derTag.getObject();
|
||||
m_mechToken = derStr.getOctets();
|
||||
}
|
||||
else if ( derTag.getTagNo() == 3 &&derTag.getObject() instanceof DEROctetString)
|
||||
{
|
||||
// mechListMIC
|
||||
|
||||
}
|
||||
else if ( derTag.getTagNo() == 3 && derTag.getObject() instanceof DERSequence)
|
||||
{
|
||||
// mechListMIC (Microsoft)
|
||||
|
||||
DERSequence derSeq = (DERSequence) derTag.getObject();
|
||||
|
||||
Enumeration subEnum = derSeq.getObjects();
|
||||
while( subEnum.hasMoreElements())
|
||||
{
|
||||
derObj = (DERObject) subEnum.nextElement();
|
||||
System.out.println("mechListMIC Seq: " + derObj);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new IOException("Bad format, unexpected type");
|
||||
}
|
||||
else
|
||||
throw new IOException("Bad format, untagged type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an SPNEGO NegTokenInit blob
|
||||
*
|
||||
* @return byte[]
|
||||
* @exception IOException
|
||||
*/
|
||||
public byte[] encode() throws IOException
|
||||
{
|
||||
ByteArrayOutputStream tokStream = new ByteArrayOutputStream();
|
||||
|
||||
// Create an SPNEGO NegTokenInit token
|
||||
|
||||
DEROutputStream derOut = new DEROutputStream( tokStream);
|
||||
|
||||
derOut.writeObject( new DERObjectIdentifier( OID.ID_SPNEGO));
|
||||
ASN1EncodableVector asnList = new ASN1EncodableVector();
|
||||
|
||||
// Build the mechTypes sequence
|
||||
|
||||
ASN1EncodableVector mechTypesList = new ASN1EncodableVector();
|
||||
|
||||
for ( Oid mechType : m_mechTypes)
|
||||
{
|
||||
mechTypesList.add( new DERObjectIdentifier( mechType.toString()));
|
||||
}
|
||||
|
||||
asnList.add( new DERTaggedObject( true, 0, new DERSequence( mechTypesList)));
|
||||
|
||||
// Build the mechListMIC
|
||||
//
|
||||
// Note: This field is not as specified
|
||||
|
||||
if ( m_mecListMICPrincipal != null)
|
||||
{
|
||||
ASN1EncodableVector micList = new ASN1EncodableVector();
|
||||
|
||||
micList.add( new DERTaggedObject( true, 0, new DERGeneralString( m_mecListMICPrincipal)));
|
||||
asnList.add( new DERTaggedObject( true, 3, new DERSequence( micList)));
|
||||
}
|
||||
|
||||
// Generate the SPNEGO NegTokenInit blob
|
||||
|
||||
derOut.writeObject( new DERTaggedObject( true, 0, new DERSequence( asnList)));
|
||||
DERObject token = new DERUnknownTag( DERTags.CONSTRUCTED | DERTags.APPLICATION, tokStream.toByteArray());
|
||||
|
||||
tokStream = new ByteArrayOutputStream();
|
||||
derOut = new DEROutputStream( tokStream);
|
||||
derOut.writeObject( token);
|
||||
|
||||
return tokStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the NegTokenInit object as a string
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
str.append("[NegTokenInit ");
|
||||
|
||||
if ( m_mechTypes != null)
|
||||
{
|
||||
str.append("mechTypes=");
|
||||
for ( Oid oid : m_mechTypes)
|
||||
{
|
||||
str.append(oid.toString());
|
||||
str.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_contextFlags != -1)
|
||||
{
|
||||
str.append(" context=0x");
|
||||
str.append(Integer.toHexString(m_contextFlags));
|
||||
}
|
||||
|
||||
if ( m_mechToken != null)
|
||||
{
|
||||
str.append(" token=");
|
||||
str.append(m_mechToken.length);
|
||||
str.append(" bytes");
|
||||
}
|
||||
|
||||
if ( m_mecListMICPrincipal != null)
|
||||
{
|
||||
str.append(" principal=");
|
||||
str.append(m_mecListMICPrincipal);
|
||||
}
|
||||
str.append("]");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.filesys.server.auth.spnego;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.DEREnumerated;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERObjectIdentifier;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DEROutputStream;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
/**
|
||||
* NegTokenTarg Class
|
||||
*
|
||||
* <p>Contains the details of an SPNEGO NegTokenTarg blob for use with CIFS.
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class NegTokenTarg
|
||||
{
|
||||
// Result code
|
||||
|
||||
private int m_result;
|
||||
|
||||
// Supported mechanism
|
||||
|
||||
private Oid m_supportedMech;
|
||||
|
||||
// Response token
|
||||
|
||||
private byte[] m_responseToken;
|
||||
|
||||
/**
|
||||
* Class constructor for decoding
|
||||
*/
|
||||
public NegTokenTarg()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param result int
|
||||
* @param mech Oid
|
||||
* @param response byte[]
|
||||
*/
|
||||
public NegTokenTarg(int result, Oid mech, byte[] response)
|
||||
{
|
||||
m_result = result;
|
||||
m_supportedMech = mech;
|
||||
m_responseToken = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getResult()
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the supported mech type Oid
|
||||
*
|
||||
* @return Oid
|
||||
*/
|
||||
public final Oid getSupportedMech()
|
||||
{
|
||||
return m_supportedMech;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if there is a valid response token
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasResponseToken()
|
||||
{
|
||||
return m_responseToken != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response token
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public final byte[] getResponseToken()
|
||||
{
|
||||
return m_responseToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an SPNEGO NegTokenTarg blob
|
||||
*
|
||||
* @param buf byte[]
|
||||
* @param off int
|
||||
* @param len int
|
||||
* @exception IOException
|
||||
*/
|
||||
public void decode(byte[] buf, int off, int len) throws IOException
|
||||
{
|
||||
// Create a stream around the security blob
|
||||
|
||||
ByteArrayInputStream bytStream = new ByteArrayInputStream( buf, off, len);
|
||||
ASN1InputStream asnStream = new ASN1InputStream( bytStream);
|
||||
|
||||
// Read the top level object from the security blob
|
||||
|
||||
DERObject derObj = asnStream.readObject();
|
||||
|
||||
if ( derObj instanceof DERTaggedObject == false)
|
||||
throw new IOException("Bad blob format (Tagged)");
|
||||
|
||||
// Access the sequence
|
||||
|
||||
DERTaggedObject derTag = (DERTaggedObject) derObj;
|
||||
if ( derTag.getObject() instanceof DERSequence == false)
|
||||
throw new IOException("Bad blob format (Seq)");
|
||||
|
||||
DERSequence derSeq = (DERSequence) derTag.getObject();
|
||||
Enumeration seqEnum = derSeq.getObjects();
|
||||
|
||||
while ( seqEnum.hasMoreElements())
|
||||
{
|
||||
// Read an object from the sequence
|
||||
|
||||
derObj = (DERObject) seqEnum.nextElement();
|
||||
if ( derObj instanceof DERTaggedObject)
|
||||
{
|
||||
// Tag 0 should be a status
|
||||
|
||||
derTag = (DERTaggedObject) derObj;
|
||||
if ( derTag.getTagNo() == 0 && derTag.getObject() instanceof DEREnumerated)
|
||||
{
|
||||
// Result code
|
||||
|
||||
DEREnumerated derEnum = (DEREnumerated) derTag.getObject();
|
||||
m_result = derEnum.getValue().intValue();
|
||||
}
|
||||
else if ( derTag.getTagNo() == 1 && derTag.getObject() instanceof DERObjectIdentifier)
|
||||
{
|
||||
// Mech type
|
||||
|
||||
DERObjectIdentifier derOid = (DERObjectIdentifier) derTag.getObject();
|
||||
try
|
||||
{
|
||||
m_supportedMech = new Oid(derOid.getId());
|
||||
}
|
||||
catch (GSSException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
else if ( derTag.getTagNo() == 2 && derTag.getObject() instanceof DEROctetString)
|
||||
{
|
||||
// Unpack the response token
|
||||
|
||||
DEROctetString derStr = (DEROctetString) derTag.getObject();
|
||||
m_responseToken = derStr.getOctets();
|
||||
}
|
||||
else if ( derTag.getTagNo() == 3 &&derTag.getObject() instanceof DEROctetString)
|
||||
{
|
||||
// mechListMIC
|
||||
|
||||
}
|
||||
else
|
||||
throw new IOException("Bad format, unexpected type");
|
||||
}
|
||||
else
|
||||
throw new IOException("Bad format, untagged type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an SPNEGO NegTokenTarg blob
|
||||
*
|
||||
* @return byte[]
|
||||
* @exception IOException
|
||||
*/
|
||||
public byte[] encode() throws IOException
|
||||
{
|
||||
ByteArrayOutputStream tokStream = new ByteArrayOutputStream();
|
||||
|
||||
// Create an SPNEGO NegTokenTarg token
|
||||
|
||||
DEROutputStream derOut = new DEROutputStream( tokStream);
|
||||
|
||||
ASN1EncodableVector asnList = new ASN1EncodableVector();
|
||||
|
||||
// Pack the result code
|
||||
|
||||
asnList.add( new DERTaggedObject( true, 0, new DEREnumerated(m_result)));
|
||||
|
||||
// Pack the supportedMech field
|
||||
|
||||
if ( m_supportedMech != null)
|
||||
asnList.add( new DERTaggedObject( true, 1, new DERObjectIdentifier( m_supportedMech.toString())));
|
||||
|
||||
// Pack the response token
|
||||
|
||||
if ( m_responseToken != null)
|
||||
asnList.add( new DERTaggedObject( true, 2, new DEROctetString(m_responseToken)));
|
||||
|
||||
// Generate the SPNEGO NegTokenTarg blob
|
||||
|
||||
derOut.writeObject( new DERTaggedObject( true, SPNEGO.NegTokenTarg, new DERSequence( asnList)));
|
||||
return tokStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the NegtokenTarg object as a string
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
str.append("[NegtokenTarg result=");
|
||||
str.append( SPNEGO.asResultString( getResult()));
|
||||
|
||||
str.append(" oid=");
|
||||
str.append( getSupportedMech());
|
||||
|
||||
str.append(" response=");
|
||||
if ( hasResponseToken())
|
||||
{
|
||||
str.append(getResponseToken().length);
|
||||
str.append(" bytes");
|
||||
}
|
||||
else
|
||||
str.append("null");
|
||||
str.append("]");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
74
source/java/org/alfresco/filesys/server/auth/spnego/OID.java
Normal file
74
source/java/org/alfresco/filesys/server/auth/spnego/OID.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.filesys.server.auth.spnego;
|
||||
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
/**
|
||||
* OID Class
|
||||
*
|
||||
* <p>Contains Oids used by SPNEGO
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class OID
|
||||
{
|
||||
// IDs
|
||||
|
||||
public static final String ID_SPNEGO = "1.3.6.1.5.5.2";
|
||||
|
||||
// Kerberos providers
|
||||
|
||||
public static final String ID_KERBEROS5 = "1.2.840.113554.1.2.2";
|
||||
public static final String ID_MSKERBEROS5 = "1.2.840.48018.1.2.2";
|
||||
|
||||
// Microsoft NTLM security support provider
|
||||
|
||||
public static final String ID_NTLMSSP = "1.3.6.1.4.1.311.2.2.10";
|
||||
|
||||
// OIDs
|
||||
|
||||
public static Oid SPNEGO;
|
||||
|
||||
public static Oid KERBEROS5;
|
||||
public static Oid MSKERBEROS5;
|
||||
|
||||
public static Oid NTLMSSP;
|
||||
|
||||
/**
|
||||
* Static initializer
|
||||
*/
|
||||
|
||||
static {
|
||||
|
||||
// Create the OIDs
|
||||
|
||||
try
|
||||
{
|
||||
SPNEGO = new Oid(ID_SPNEGO);
|
||||
|
||||
KERBEROS5 = new Oid(ID_KERBEROS5);
|
||||
MSKERBEROS5 = new Oid( ID_MSKERBEROS5);
|
||||
|
||||
NTLMSSP = new Oid(ID_NTLMSSP);
|
||||
}
|
||||
catch ( GSSException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
132
source/java/org/alfresco/filesys/server/auth/spnego/SPNEGO.java
Normal file
132
source/java/org/alfresco/filesys/server/auth/spnego/SPNEGO.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.filesys.server.auth.spnego;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.DERApplicationSpecific;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
|
||||
/**
|
||||
* SPNEGO Class
|
||||
*
|
||||
* <p>Contains SPNEGO constants
|
||||
*
|
||||
* @author gkspencer
|
||||
*/
|
||||
public class SPNEGO
|
||||
{
|
||||
// Message types
|
||||
|
||||
public static final int NegTokenInit = 0;
|
||||
public static final int NegTokenTarg = 1;
|
||||
|
||||
// NegTokenInit context flags
|
||||
|
||||
public static final int ContextDelete = 0;
|
||||
public static final int ContextMutual = 1;
|
||||
public static final int ContextReplay = 2;
|
||||
public static final int ContextSequence = 3;
|
||||
public static final int ContextAnon = 4;
|
||||
public static final int ContextConf = 5;
|
||||
public static final int ContextInteg = 6;
|
||||
|
||||
// NegTokenTarg result codes
|
||||
|
||||
public static final int AcceptCompleted = 0;
|
||||
public static final int AcceptIncomplete = 1;
|
||||
public static final int Reject = 2;
|
||||
|
||||
/**
|
||||
* Return a result code as a string
|
||||
*
|
||||
* @param res int
|
||||
* @return String
|
||||
*/
|
||||
public static String asResultString(int res)
|
||||
{
|
||||
String resStr = null;
|
||||
|
||||
switch ( res)
|
||||
{
|
||||
case AcceptCompleted:
|
||||
resStr = "AcceptCompleted";
|
||||
break;
|
||||
case AcceptIncomplete:
|
||||
resStr = "AcceptIncomplete";
|
||||
break;
|
||||
case Reject:
|
||||
resStr = "Reject";
|
||||
break;
|
||||
default:
|
||||
resStr = "" + res;
|
||||
break;
|
||||
}
|
||||
|
||||
return resStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the SPNEGO token type
|
||||
*
|
||||
* @param buf byte[]
|
||||
* @param off int
|
||||
* @param len int
|
||||
* @return int
|
||||
* @exception IOException
|
||||
*/
|
||||
public static int checkTokenType( byte[] buf, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
// Create a stream around the security blob
|
||||
|
||||
ByteArrayInputStream bytStream = new ByteArrayInputStream( buf, off, len);
|
||||
ASN1InputStream asnStream = new ASN1InputStream( bytStream);
|
||||
|
||||
// Read the top level object from the security blob
|
||||
|
||||
DERObject derObj = asnStream.readObject();
|
||||
int tokType = -1;
|
||||
|
||||
if ( derObj instanceof DERApplicationSpecific)
|
||||
{
|
||||
// Looks like a NegTokenInit token
|
||||
|
||||
tokType = NegTokenInit;
|
||||
}
|
||||
else if ( derObj instanceof DERTaggedObject)
|
||||
{
|
||||
// Check the tag number
|
||||
|
||||
DERTaggedObject derTag = (DERTaggedObject) derObj;
|
||||
if ( derTag.getTagNo() == 1)
|
||||
tokType = NegTokenTarg;
|
||||
}
|
||||
|
||||
// Close the streams
|
||||
|
||||
asnStream.close();
|
||||
bytStream.close();
|
||||
|
||||
// Return the token type
|
||||
|
||||
return tokType;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user