Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

198 lines
6.4 KiB
C#

//
// Novell.Directory.Ldap.Security.Krb5Helper.cs
//
// Authors:
// Boris Kirzner <borsk@mainsoft.com>
// Konstantin Triger <kostat@mainsoft.com>
//
// (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using vmw.common;
using java.security;
using javax.security.auth;
using org.ietf.jgss;
namespace Novell.Directory.Ldap.Security
{
internal class Krb5Helper : IDisposable
{
enum QOP {
NO_PROTECTION = 1,
INTEGRITY_ONLY_PROTECTION = 2,
PRIVACY_PROTECTION = 4
}
#region Fields
internal static readonly sbyte [] EmptyToken = new sbyte [0];
private readonly bool _encryption;
private readonly bool _signing;
private readonly bool _delegation;
private readonly GSSContext _context;
#endregion // Fields
#region Constructors
public Krb5Helper(string name, string clientName, Subject subject, AuthenticationTypes authenticationTypes, string mech)
{
_encryption = (authenticationTypes & AuthenticationTypes.Sealing) != 0;
_signing = (authenticationTypes & AuthenticationTypes.Signing) != 0;
_delegation = (authenticationTypes & AuthenticationTypes.Delegation) != 0;
CreateContextPrivilegedAction action = new CreateContextPrivilegedAction (name, clientName, mech,_encryption,_signing,_delegation);
try {
_context = (GSSContext) Subject.doAs (subject,action);
}
catch (PrivilegedActionException e) {
throw new LdapException ("Problem performing token exchange with the server",LdapException.OTHER,"",e.getCause());
}
}
#endregion // Constructors
#region Properties
internal GSSContext Context
{
get { return _context; }
}
#endregion // Properties
#region Methods
public sbyte [] ExchangeTokens(sbyte [] clientToken)
{
if (Context.isEstablished ()) {
if (clientToken == null || clientToken.Length == 0)
return Krb5Helper.EmptyToken;
//final handshake
byte [] challengeData = (byte []) TypeUtils.ToByteArray (clientToken);
byte [] gssOutToken = Unwrap (challengeData, 0, challengeData.Length, new MessageProp (false));
QOP myCop = QOP.NO_PROTECTION;
if (_encryption)
myCop = QOP.PRIVACY_PROTECTION;
else if (_signing || (((QOP)gssOutToken [0] & QOP.INTEGRITY_ONLY_PROTECTION) != 0))
myCop = QOP.INTEGRITY_ONLY_PROTECTION;
if ((myCop & (QOP)gssOutToken [0]) == 0)
throw new LdapException ("Server does not support the requested security level", 80, "");
int srvMaxBufSize = SecureStream.NetworkByteOrderToInt (gssOutToken, 1, 3);
//int rawSendSize = Context.getWrapSizeLimit(0, _encryption, srvMaxBufSize);
byte [] gssInToken = new byte [4];
gssInToken [0] = (byte) myCop;
SecureStream.IntToNetworkByteOrder (srvMaxBufSize, gssInToken, 1, 3);
gssOutToken = Wrap (gssInToken, 0, gssInToken.Length, new MessageProp (true));
return TypeUtils.ToSByteArray (gssOutToken);
}
sbyte [] token = Context.initSecContext (clientToken, 0, clientToken.Length);
if (Context.isEstablished ()) {
if (Context.getConfState () != _encryption)
throw new LdapException ("Encryption protocol was not established layer between client and server", 80, "");
if (Context.getCredDelegState () != _delegation)
throw new LdapException ("Credential delegation was not established layer between client and server", 80, "");
if (_signing && (Context.getIntegState () != _signing))
throw new LdapException ("Signing protocol was not established layer between client and server", 80, "");
if (token == null)
return EmptyToken;
}
return token;
}
public byte [] Wrap(byte [] outgoing, int start, int len)
{
return Wrap (outgoing, start, len, new MessageProp(true));
}
public byte [] Wrap(byte [] outgoing, int start, int len, MessageProp messageProp)
{
if (!Context.isEstablished ())
throw new LdapException ("GSSAPI authentication not completed",LdapException.OTHER,"");
if (!(Context.getConfState () || Context.getIntegState ())) {
// in the case no encryption and no integrity required - return the original data
byte [] buff = new byte [len];
Array.Copy (outgoing, start, buff, 0, len);
return buff;
}
sbyte [] result = Context.wrap (TypeUtils.ToSByteArray (outgoing), start, len, messageProp);
return (byte []) TypeUtils.ToByteArray (result);
}
public byte [] Unwrap(byte [] incoming, int start, int len)
{
return Unwrap (incoming, start, len, new MessageProp(true));
}
public byte [] Unwrap(byte [] incoming, int start, int len, MessageProp messageProp)
{
if (!Context.isEstablished ())
throw new LdapException ("GSSAPI authentication not completed",LdapException.OTHER,"");
if (!(Context.getConfState () || Context.getIntegState ())) {
// in the case no encryption and no integrity required - return the original data
byte [] buff = new byte [len];
Array.Copy (incoming, start, buff, 0, len);
return buff;
}
sbyte [] result = Context.unwrap (TypeUtils.ToSByteArray (incoming), start, len, messageProp);
return (byte []) TypeUtils.ToByteArray (result);
}
#endregion // Methods
#region IDisposable Members
public void Dispose() {
Context.dispose();
}
#endregion
}
}