diff options
author | Boris Kirzner <borisk@mono-cvs.ximian.com> | 2005-08-14 19:56:10 +0400 |
---|---|---|
committer | Boris Kirzner <borisk@mono-cvs.ximian.com> | 2005-08-14 19:56:10 +0400 |
commit | aa6f208f1f237d9181b9bb9b778b0b4a76a26bcd (patch) | |
tree | e5f9932741fb53ea55c174eb0831d3ac410987ba /mcs/class/Novell.Directory.Ldap | |
parent | 0f84ad9c484d1c247a9fa4f0914d79b4d4bdd611 (diff) |
Fixes for TARGET_JVM secure binding.
svn path=/trunk/mcs/; revision=48365
Diffstat (limited to 'mcs/class/Novell.Directory.Ldap')
5 files changed, 120 insertions, 25 deletions
diff --git a/mcs/class/Novell.Directory.Ldap/ChangeLog b/mcs/class/Novell.Directory.Ldap/ChangeLog index a144e2f4114..64d36848e9f 100644 --- a/mcs/class/Novell.Directory.Ldap/ChangeLog +++ b/mcs/class/Novell.Directory.Ldap/ChangeLog @@ -1,3 +1,9 @@ +2005-14-08 Boris Kirzner <borisk@mainsoft.com> + * LdapConnection.cs: + - Values from app settings are not stored anymore in app domain. + - Exchange tokens until negotiatin is complete. + - Added new property for authentication mech, stored in app settings. + 2005-28-07 Boris Kirzner <borisk@mainsoft.com> * Novell.Directory.Ldap.Security.jvm: added new directory containing TARGET_JVM specific classes for kerberos authentication. diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/ChangeLog b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/ChangeLog index df96b0968cb..7cba50782e6 100644 --- a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/ChangeLog +++ b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/ChangeLog @@ -1,3 +1,9 @@ +2005-14-08 Boris Kirzner <borisk@mainsoft.com> + * Krb5Helper.cs: ExchangeTokens does proper final handshaking. Wrap/Unwrap + perform no action if no integrity and encryption accured. + * SecureStream.cs: Private convertion methods became internal, used by + Krb5Helper. + 2005-28-07 Boris Kirzner <borisk@mainsoft.com> * Novell.Directory.Ldap.Security.jvm/ExchangeTokenPrivilegedAction.cs,
Novell.Directory.Ldap.Security.jvm/CreateContextPrivilegedAction.cs,
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/Krb5Helper.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/Krb5Helper.cs index 86f7f18ebcd..a83d2afe917 100644 --- a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/Krb5Helper.cs +++ b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/Krb5Helper.cs @@ -41,6 +41,12 @@ namespace Novell.Directory.Ldap.Security {
internal class Krb5Helper
{
+ enum QOP {
+ NO_PROTECTION = 1, + INTEGRITY_ONLY_PROTECTION = 2, + PRIVACY_PROTECTION = 4
+ }
+
#region Fields
internal static readonly sbyte [] EmptyToken = new sbyte [0];
@@ -92,8 +98,39 @@ namespace Novell.Directory.Ldap.Security public sbyte [] ExchangeTokens(sbyte [] clientToken)
{
- if (Context.isEstablished ())
- return Krb5Helper.EmptyToken;
+ if (Context.isEstablished ()) {
+ if (clientToken == null || clientToken.Length == 0)
+ return Krb5Helper.EmptyToken;
+
+ MessageProp messageProp = new MessageProp (0, false);
+
+ //final handshake
+ byte [] challengeData = (byte []) TypeUtils.ToByteArray (clientToken);
+ byte [] gssOutToken = Unwrap (challengeData, 0, challengeData.Length, messageProp);
+
+ 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, messageProp);
+
+ return TypeUtils.ToSByteArray (gssOutToken);
+ }
sbyte [] token;
try {
@@ -121,13 +158,25 @@ namespace Novell.Directory.Ldap.Security return token;
}
- public byte [] Wrap(byte [] outgoing, int start, int len)
+ public byte [] Wrap(byte [] outgoing, int start, int len)
+ {
+ return Wrap (outgoing, start, len, _messageProperties);
+ }
+
+ 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;
+ }
+
try {
- WrapPrivilegedAction action = new WrapPrivilegedAction (Context, outgoing, start, len, _messageProperties);
+ WrapPrivilegedAction action = new WrapPrivilegedAction (Context, outgoing, start, len, messageProp);
return (byte []) Subject.doAs (_subject, action);
}
catch (PrivilegedActionException e) {
@@ -135,13 +184,25 @@ namespace Novell.Directory.Ldap.Security }
}
- public byte [] Unwrap(byte [] incoming, int start, int len)
+ public byte [] Unwrap(byte [] incoming, int start, int len)
+ {
+ return Unwrap (incoming, start, len, _messageProperties);
+ }
+
+ 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;
+ }
+
try {
- UnwrapPrivilegedAction action = new UnwrapPrivilegedAction (Context, incoming, start, len, _messageProperties);
+ UnwrapPrivilegedAction action = new UnwrapPrivilegedAction (Context, incoming, start, len, messageProp);
return (byte []) Subject.doAs (_subject, action);
}
catch (PrivilegedActionException e) {
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/SecureStream.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/SecureStream.cs index f37ef8517ff..43508c33313 100644 --- a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/SecureStream.cs +++ b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Security.jvm/SecureStream.cs @@ -180,7 +180,7 @@ namespace Novell.Directory.Ldap.Security _stream.Write (wrappedToken, 0, wrappedToken.Length);
}
- private static int NetworkByteOrderToInt(byte [] buf, int start, int count)
+ internal static int NetworkByteOrderToInt(byte [] buf, int start, int count)
{
int answer = 0;
for (int i = 0; i < count; i++) {
@@ -190,7 +190,7 @@ namespace Novell.Directory.Ldap.Security return answer;
}
- private static void IntToNetworkByteOrder(int num, byte [] buf, int start, int count)
+ internal static void IntToNetworkByteOrder(int num, byte [] buf, int start, int count)
{
for (int i = count-1; i >= 0; i--) {
buf [start + i] = (byte)(num & 0xff);
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap/LdapConnection.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap/LdapConnection.cs index a8bfd4aa834..374b3f61b5c 100644 --- a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap/LdapConnection.cs +++ b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap/LdapConnection.cs @@ -480,9 +480,6 @@ namespace Novell.Directory.Ldap private static System.Object nameLock; // protect agentNum private static int lConnNum = 0; // Debug, LdapConnection number private System.String name; // String name for debug - - private const string LDAP_SECURITY_MECH = "System.DirectoryServices.SecurityMech"; - private const string LDAP_SECURITY_APP_NAME = "System.DirectoryServices.SecurityAppName"; /// <summary> Used with search to specify that the scope of entrys to search is to /// search only the base obect. @@ -1559,7 +1556,17 @@ namespace Novell.Directory.Ldap #if TARGET_JVM // stopping reader to enable stream replace after secure binding is complete, see Connection.ReplaceStreams() if (mech != null) + { + if (conn.BindSemIdClear) { + // need to acquire a semaphore only if bindSemId is clear + // because if we receive SASL_BIND_IN_PROGRESS the semaphore is not + // released when the response is queued + conn.acquireWriteSemaphore(msgId); + conn.BindSemId = msgId; + } conn.stopReaderOnReply(msgId); + } + else #endif // The semaphore is released when the bind response is queued. conn.acquireWriteSemaphore(msgId); @@ -1586,11 +1593,19 @@ namespace Novell.Directory.Ldap Krb5Helper krb5Helper = new Krb5Helper ("ldap@" + conn.Host, subject, authenticationTypes, SecurityMech); sbyte [] token = krb5Helper.ExchangeTokens (Krb5Helper.EmptyToken); - LdapResponseQueue queue = Bind(LdapConnection.Ldap_V3, username, token, null, null, "GSS-SPNEGO"); - LdapResponse res = (LdapResponse) queue.getResponse (); - token = ((RfcBindResponse)res.Asn1Object.Response).ServerSaslCreds.byteValue (); + for (;;) { + LdapResponseQueue queue = Bind(LdapConnection.Ldap_V3, username, token, null, null, AuthenticationMech); + LdapResponse res = (LdapResponse) queue.getResponse (); + Asn1OctetString serverSaslCreds = ((RfcBindResponse)res.Asn1Object.Response).ServerSaslCreds; + token = serverSaslCreds != null ? serverSaslCreds.byteValue () : null; - token = krb5Helper.ExchangeTokens(token == null ? Krb5Helper.EmptyToken : token); + token = krb5Helper.ExchangeTokens(token == null ? Krb5Helper.EmptyToken : token); + + if (res.ResultCode != LdapException.SASL_BIND_IN_PROGRESS) + break; + + conn.ReplaceStreams (conn.InputStream,conn.OutputStream); + } System.IO.Stream inStream = conn.InputStream; System.IO.Stream newIn = new SecureStream (inStream, krb5Helper); @@ -1603,9 +1618,7 @@ namespace Novell.Directory.Ldap private string SecurityMech { get { - string securityMech = (string) AppDomain.CurrentDomain.GetData (LDAP_SECURITY_MECH); - - if (securityMech == null) { + string securityMech = null; NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("System.DirectoryServices/Settings"); if (config != null) securityMech = config ["securitymech"]; @@ -1613,8 +1626,6 @@ namespace Novell.Directory.Ldap if (securityMech == null) throw new ArgumentException("Security mechanism id not found in application settings"); - AppDomain.CurrentDomain.SetData (LDAP_SECURITY_MECH,securityMech); - } return securityMech; } } @@ -1622,9 +1633,7 @@ namespace Novell.Directory.Ldap private string SecurityAppName { get { - string securityAppName = (string) AppDomain.CurrentDomain.GetData (LDAP_SECURITY_APP_NAME); - - if (securityAppName == null) { + string securityAppName = null; NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("System.DirectoryServices/Settings"); if (config != null) securityAppName = config ["securityappname"]; @@ -1632,11 +1641,24 @@ namespace Novell.Directory.Ldap if (securityAppName == null) throw new ArgumentException("Application section name not found in application settings"); - AppDomain.CurrentDomain.SetData (LDAP_SECURITY_APP_NAME,securityAppName); - } return securityAppName; } } + + private string AuthenticationMech + { + get { + string authenticationMech = null; + NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("System.DirectoryServices/Settings"); + if (config != null) + authenticationMech = config ["authenticationmech"]; + + if (authenticationMech == null) + throw new ArgumentException("Authentication mechanism not found in application settings"); + + return authenticationMech; + } + } #endif //************************************************************************* |