41889337d15b3aaaf7753a2dffd8777409e40676
[mono.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap.Security.jvm / Krb5Helper.cs
1 // 
2 // Novell.Directory.Ldap.Security.Krb5Helper.cs
3 //
4 // Authors:
5 //  Boris Kirzner <borsk@mainsoft.com>
6 //      Konstantin Triger <kostat@mainsoft.com>
7 //      
8 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //\r
31 \r
32 using System;\r
33 using vmw.common;\r
34 \r
35 using java.security;\r
36 using javax.security.auth;\r
37 using org.ietf.jgss;\r
38 \r
39 \r
40 namespace Novell.Directory.Ldap.Security\r
41 {\r
42         internal class Krb5Helper\r
43         {\r
44                 enum QOP {\r
45                         NO_PROTECTION = 1,
46                         INTEGRITY_ONLY_PROTECTION = 2,
47                         PRIVACY_PROTECTION = 4\r
48                 }\r
49 \r
50                 #region Fields\r
51 \r
52                 internal static readonly sbyte [] EmptyToken = new sbyte [0];\r
53                      \r
54                 private readonly bool _encryption;\r
55                 private readonly bool _signing;\r
56                 private readonly bool _delegation;\r
57 \r
58                 private readonly GSSContext _context;\r
59 \r
60                 private readonly string _name;\r
61                 private readonly Subject _subject;\r
62                 private readonly string _mech;\r
63 \r
64                 #endregion // Fields\r
65 \r
66                 #region Constructors\r
67 \r
68                 public Krb5Helper(string name, Subject subject, AuthenticationTypes authenticationTypes, string mech)\r
69                 {\r
70                         _name = name;\r
71                         _subject = subject;\r
72                         _mech = mech;\r
73 \r
74                         _encryption = (authenticationTypes & AuthenticationTypes.Sealing) != 0;\r
75                         _signing = (authenticationTypes & AuthenticationTypes.Signing) != 0;\r
76                         _delegation = (authenticationTypes & AuthenticationTypes.Delegation) != 0;\r
77 \r
78                         CreateContextPrivilegedAction action = new CreateContextPrivilegedAction (_name,_mech,_encryption,_signing,_delegation);\r
79                         _context = (GSSContext) Subject.doAs (_subject,action);\r
80                 }\r
81 \r
82                 #endregion // Constructors\r
83 \r
84                 #region Properties\r
85 \r
86                 internal GSSContext Context\r
87                 {\r
88                         get { return _context; }\r
89                 }\r
90 \r
91                 #endregion // Properties\r
92 \r
93                 #region Methods\r
94 \r
95                 public sbyte [] ExchangeTokens(sbyte [] clientToken)\r
96                 {\r
97                         if (Context.isEstablished ()) {\r
98                                 if (clientToken == null || clientToken.Length == 0)\r
99                                         return Krb5Helper.EmptyToken;\r
100 \r
101                                 //final handshake\r
102                                 byte [] challengeData = (byte []) TypeUtils.ToByteArray (clientToken);\r
103                                 byte [] gssOutToken = Unwrap (challengeData, 0, challengeData.Length, new MessageProp (false));\r
104 \r
105                                 QOP myCop = QOP.NO_PROTECTION;\r
106 \r
107                                 if (_encryption)\r
108                                         myCop = QOP.PRIVACY_PROTECTION;\r
109                                 else if (_signing || (((QOP)gssOutToken [0] & QOP.INTEGRITY_ONLY_PROTECTION) != 0))\r
110                                         myCop = QOP.INTEGRITY_ONLY_PROTECTION;\r
111 \r
112                                 if ((myCop & (QOP)gssOutToken [0]) == 0)\r
113                                         throw new LdapException ("Server does not support the requested security level", 80, "");\r
114 \r
115                                 int srvMaxBufSize = SecureStream.NetworkByteOrderToInt (gssOutToken, 1, 3);\r
116 \r
117                                 //int rawSendSize = Context.getWrapSizeLimit(0, _encryption, srvMaxBufSize);\r
118 \r
119                                 byte [] gssInToken = new byte [4];
120                                 gssInToken [0] = (byte) myCop;\r
121 \r
122                                 SecureStream.IntToNetworkByteOrder (srvMaxBufSize, gssInToken, 1, 3);\r
123 \r
124                                 gssOutToken = Wrap (gssInToken, 0, gssInToken.Length, new MessageProp (true));\r
125 \r
126                                 return TypeUtils.ToSByteArray (gssOutToken);\r
127                         }\r
128 \r
129                         sbyte [] token;\r
130                         try {\r
131                                 ExchangeTokenPrivilegedAction action = new ExchangeTokenPrivilegedAction (Context, clientToken);
132                                 token = (sbyte []) Subject.doAs (_subject, action);\r
133                         } \r
134                         catch (PrivilegedActionException e) {\r
135                                 throw new LdapException ("Problem performing token exchange with the server",LdapException.OTHER,"",e); \r
136                         }\r
137 \r
138                         if (Context.isEstablished ()) {\r
139                                 \r
140                                 if (Context.getConfState () != _encryption)\r
141                                         throw new LdapException ("Encryption protocol was not established layer between client and server", 80, "");\r
142                                         \r
143                                 if (Context.getCredDelegState () != _delegation) \r
144                                         throw new LdapException ("Credential delegation was not established layer between client and server", 80, "");\r
145                                         \r
146                                 if (_signing && (Context.getIntegState () != _signing))\r
147                                         throw new LdapException ("Signing protocol was not established layer between client and server", 80, "");\r
148                                         \r
149                                 if (token == null) \r
150                                         return EmptyToken;\r
151                         }\r
152                         return token;\r
153                 }\r
154 \r
155                 public byte [] Wrap(byte [] outgoing, int start, int len) \r
156                 {\r
157                         return Wrap (outgoing, start, len, new MessageProp(true));\r
158                 }\r
159 \r
160                 public byte [] Wrap(byte [] outgoing, int start, int len, MessageProp messageProp)\r
161                 {\r
162                         if (!Context.isEstablished ())\r
163                                 throw new LdapException ("GSSAPI authentication not completed",LdapException.OTHER,"");\r
164 \r
165                         if (!(Context.getConfState () || Context.getIntegState ())) {\r
166                                 // in the case no encryption and no integrity required - return the original data\r
167                                 byte [] buff = new byte [len];\r
168                                 Array.Copy (outgoing, start, buff, 0, len);\r
169                                 return buff;\r
170                         }\r
171 \r
172                         try {\r
173                                 WrapPrivilegedAction action = new WrapPrivilegedAction (Context, outgoing, start, len, messageProp);\r
174                                 return (byte []) Subject.doAs (_subject, action);                               \r
175                         } \r
176                         catch (PrivilegedActionException e) {\r
177                                 throw new LdapException ("Problem performing GSS wrap",LdapException.OTHER,"",e); \r
178                         }\r
179                 }\r
180 \r
181                 public byte [] Unwrap(byte [] incoming, int start, int len) \r
182                 {\r
183                         return Unwrap (incoming, start, len, new MessageProp(true));\r
184                 }\r
185 \r
186                 public byte [] Unwrap(byte [] incoming, int start, int len, MessageProp messageProp)\r
187                 {\r
188                         if (!Context.isEstablished ())\r
189                                 throw new LdapException ("GSSAPI authentication not completed",LdapException.OTHER,"");\r
190 \r
191                         if (!(Context.getConfState () || Context.getIntegState ())) {\r
192                                 // in the case no encryption and no integrity required - return the original data\r
193                                 byte [] buff = new byte [len];\r
194                                 Array.Copy (incoming, start, buff, 0, len);\r
195                                 return buff;\r
196                         }\r
197 \r
198                         try {\r
199                                 UnwrapPrivilegedAction action = new UnwrapPrivilegedAction (Context, incoming, start, len, messageProp);\r
200                                 return (byte []) Subject.doAs (_subject, action);\r
201                         } \r
202                         catch (PrivilegedActionException e) {\r
203                                 throw new LdapException("Problems unwrapping SASL buffer",LdapException.OTHER,"",e);\r
204                         }\r
205                 }\r
206 \r
207                 #endregion // Methods\r
208         }\r
209 }\r