2 // Novell.Directory.Ldap.Security.Krb5Helper.cs
\r
5 // Boris Kirzner <borsk@mainsoft.com>
\r
6 // Konstantin Triger <kostat@mainsoft.com>
\r
8 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
\r
12 // Permission is hereby granted, free of charge, to any person obtaining
\r
13 // a copy of this software and associated documentation files (the
\r
14 // "Software"), to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify, merge, publish,
\r
16 // distribute, sublicense, and/or sell copies of the Software, and to
\r
17 // permit persons to whom the Software is furnished to do so, subject to
\r
18 // the following conditions:
\r
20 // The above copyright notice and this permission notice shall be
\r
21 // included in all copies or substantial portions of the Software.
\r
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
35 using java.security;
\r
36 using javax.security.auth;
\r
37 using org.ietf.jgss;
\r
40 namespace Novell.Directory.Ldap.Security
\r
42 internal class Krb5Helper : IDisposable
\r
46 INTEGRITY_ONLY_PROTECTION = 2,
\r
47 PRIVACY_PROTECTION = 4
\r
52 internal static readonly sbyte [] EmptyToken = new sbyte [0];
\r
54 private readonly bool _encryption;
\r
55 private readonly bool _signing;
\r
56 private readonly bool _delegation;
\r
58 private readonly GSSContext _context;
\r
60 #endregion // Fields
\r
62 #region Constructors
\r
64 public Krb5Helper(string name, string clientName, Subject subject, AuthenticationTypes authenticationTypes, string mech)
\r
66 _encryption = (authenticationTypes & AuthenticationTypes.Sealing) != 0;
\r
67 _signing = (authenticationTypes & AuthenticationTypes.Signing) != 0;
\r
68 _delegation = (authenticationTypes & AuthenticationTypes.Delegation) != 0;
\r
70 CreateContextPrivilegedAction action = new CreateContextPrivilegedAction (name, clientName, mech,_encryption,_signing,_delegation);
\r
72 _context = (GSSContext) Subject.doAs (subject,action);
\r
74 catch (PrivilegedActionException e) {
\r
75 throw new LdapException ("Problem performing token exchange with the server",LdapException.OTHER,"",e.getCause());
\r
79 #endregion // Constructors
\r
83 internal GSSContext Context
\r
85 get { return _context; }
\r
88 #endregion // Properties
\r
92 public sbyte [] ExchangeTokens(sbyte [] clientToken)
\r
94 if (Context.isEstablished ()) {
\r
95 if (clientToken == null || clientToken.Length == 0)
\r
96 return Krb5Helper.EmptyToken;
\r
99 byte [] challengeData = (byte []) TypeUtils.ToByteArray (clientToken);
\r
100 byte [] gssOutToken = Unwrap (challengeData, 0, challengeData.Length, new MessageProp (false));
\r
102 QOP myCop = QOP.NO_PROTECTION;
\r
105 myCop = QOP.PRIVACY_PROTECTION;
\r
106 else if (_signing || (((QOP)gssOutToken [0] & QOP.INTEGRITY_ONLY_PROTECTION) != 0))
\r
107 myCop = QOP.INTEGRITY_ONLY_PROTECTION;
\r
109 if ((myCop & (QOP)gssOutToken [0]) == 0)
\r
110 throw new LdapException ("Server does not support the requested security level", 80, "");
\r
112 int srvMaxBufSize = SecureStream.NetworkByteOrderToInt (gssOutToken, 1, 3);
\r
114 //int rawSendSize = Context.getWrapSizeLimit(0, _encryption, srvMaxBufSize);
\r
116 byte [] gssInToken = new byte [4];
\r
117 gssInToken [0] = (byte) myCop;
\r
119 SecureStream.IntToNetworkByteOrder (srvMaxBufSize, gssInToken, 1, 3);
\r
121 gssOutToken = Wrap (gssInToken, 0, gssInToken.Length, new MessageProp (true));
\r
123 return TypeUtils.ToSByteArray (gssOutToken);
\r
126 sbyte [] token = Context.initSecContext (clientToken, 0, clientToken.Length);
\r
128 if (Context.isEstablished ()) {
\r
130 if (Context.getConfState () != _encryption)
\r
131 throw new LdapException ("Encryption protocol was not established layer between client and server", 80, "");
\r
133 if (Context.getCredDelegState () != _delegation)
\r
134 throw new LdapException ("Credential delegation was not established layer between client and server", 80, "");
\r
136 if (_signing && (Context.getIntegState () != _signing))
\r
137 throw new LdapException ("Signing protocol was not established layer between client and server", 80, "");
\r
139 if (token == null)
\r
145 public byte [] Wrap(byte [] outgoing, int start, int len)
\r
147 return Wrap (outgoing, start, len, new MessageProp(true));
\r
150 public byte [] Wrap(byte [] outgoing, int start, int len, MessageProp messageProp)
\r
152 if (!Context.isEstablished ())
\r
153 throw new LdapException ("GSSAPI authentication not completed",LdapException.OTHER,"");
\r
155 if (!(Context.getConfState () || Context.getIntegState ())) {
\r
156 // in the case no encryption and no integrity required - return the original data
\r
157 byte [] buff = new byte [len];
\r
158 Array.Copy (outgoing, start, buff, 0, len);
\r
162 sbyte [] result = Context.wrap (TypeUtils.ToSByteArray (outgoing), start, len, messageProp);
\r
163 return (byte []) TypeUtils.ToByteArray (result);
\r
166 public byte [] Unwrap(byte [] incoming, int start, int len)
\r
168 return Unwrap (incoming, start, len, new MessageProp(true));
\r
171 public byte [] Unwrap(byte [] incoming, int start, int len, MessageProp messageProp)
\r
173 if (!Context.isEstablished ())
\r
174 throw new LdapException ("GSSAPI authentication not completed",LdapException.OTHER,"");
\r
176 if (!(Context.getConfState () || Context.getIntegState ())) {
\r
177 // in the case no encryption and no integrity required - return the original data
\r
178 byte [] buff = new byte [len];
\r
179 Array.Copy (incoming, start, buff, 0, len);
\r
183 sbyte [] result = Context.unwrap (TypeUtils.ToSByteArray (incoming), start, len, messageProp);
\r
184 return (byte []) TypeUtils.ToByteArray (result);
\r
187 #endregion // Methods
\r
189 #region IDisposable Members
\r
191 public void Dispose() {
\r