[System.Web.Services] Test DiscoveryClientProtocol
[mono.git] / mcs / class / corlib / System.Security.Principal / WindowsIdentity.cs
1 //
2 // System.Security.Principal.WindowsIdentity
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // (C) 2002 Ximian, Inc (http://www.ximian.com)
9 // Portions (C) 2003 Motus Technologies Inc. (http://www.motus.com)
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
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 //
31
32 using System.Runtime.CompilerServices;
33 using System.Runtime.InteropServices;
34 using System.Runtime.Serialization;
35 using System.Security.Permissions;
36 using System.Security.Claims;
37
38 namespace System.Security.Principal {
39
40         [Serializable]
41         [ComVisible (true)]
42         public class WindowsIdentity :
43         System.Security.Claims.ClaimsIdentity,
44         IIdentity, IDeserializationCallback, ISerializable, IDisposable {
45                 private IntPtr _token;
46                 private string _type;
47                 private WindowsAccountType _account;
48                 private bool _authenticated;
49                 private string _name;
50                 private SerializationInfo _info;
51
52                 static private IntPtr invalidWindows = IntPtr.Zero;
53
54                 [NonSerialized]
55                 public new const string DefaultIssuer = "AD AUTHORITY";
56
57                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
58                 public WindowsIdentity (IntPtr userToken) 
59                         : this (userToken, null, WindowsAccountType.Normal, false)
60                 {
61                 }
62
63                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
64                 public WindowsIdentity (IntPtr userToken, string type) 
65                         : this (userToken, type, WindowsAccountType.Normal, false)
66                 {
67                 }
68
69                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
70                 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType)
71                         : this (userToken, type, acctType, false)
72                 {
73                 }
74
75                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
76                 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
77                 {
78                         _type = type;
79                         _account = acctType;
80                         _authenticated = isAuthenticated;
81                         _name = null;
82                         // last - as it can override some fields
83                         SetToken (userToken);
84                 }
85
86                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
87                 public WindowsIdentity (string sUserPrincipalName) 
88                         : this (sUserPrincipalName, null)
89                 {
90                 }
91
92                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
93                 public WindowsIdentity (string sUserPrincipalName, string type)
94                 {
95                         if (sUserPrincipalName == null)
96                                 throw new NullReferenceException ("sUserPrincipalName");
97
98                         // TODO: Windows 2003 compatibility should be done in runtime
99                         IntPtr token = GetUserToken (sUserPrincipalName);
100                         if ((!Environment.IsUnix) && (token == IntPtr.Zero)) {
101                                 throw new ArgumentException ("only for Windows Server 2003 +");
102                         }
103
104                         _authenticated = true;
105                         _account = WindowsAccountType.Normal;
106                         _type = type;
107                         // last - as it can override some fields
108                         SetToken (token);
109                 }
110
111                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
112                 public WindowsIdentity (SerializationInfo info, StreamingContext context)
113                 {
114                         _info = info;
115                 }
116
117                 internal WindowsIdentity (ClaimsIdentity claimsIdentity, IntPtr userToken)
118                         : base (claimsIdentity)
119                 {
120                         if (userToken != IntPtr.Zero && userToken.ToInt64() > 0)
121                         {
122                                 SetToken (userToken);
123                         }
124                 }
125
126                 [ComVisible (false)]
127                 public void Dispose ()
128                 {
129                         _token = IntPtr.Zero;
130                 }
131                 
132                 [ComVisible (false)]
133                 protected virtual void Dispose (bool disposing)
134                 {
135                         _token = IntPtr.Zero;
136                 }
137                 // static methods
138
139                 public static WindowsIdentity GetAnonymous ()
140                 {
141                         WindowsIdentity id = null;
142                         if (Environment.IsUnix) {
143                                 id = new WindowsIdentity ("nobody");
144                                 // special case
145                                 id._account = WindowsAccountType.Anonymous;
146                                 id._authenticated = false;
147                                 id._type = String.Empty;
148                         }
149                         else {
150                                 id = new WindowsIdentity (IntPtr.Zero, String.Empty, WindowsAccountType.Anonymous, false);
151                                 // special case (don't try to resolve the name)
152                                 id._name = String.Empty;
153                         }
154                         return id;
155                 }
156
157                 public static WindowsIdentity GetCurrent ()
158                 {
159                         return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType.Normal, true);
160                 }
161                 [MonoTODO ("need icall changes")]
162                 public static WindowsIdentity GetCurrent (bool ifImpersonating)
163                 {
164                         throw new NotImplementedException ();
165                 }
166
167                 [MonoTODO ("need icall changes")]
168                 public static WindowsIdentity GetCurrent (TokenAccessLevels desiredAccess)
169                 {
170                         throw new NotImplementedException ();
171                 }
172                 // methods
173
174                 public virtual WindowsImpersonationContext Impersonate ()
175                 {
176                         return new WindowsImpersonationContext (_token);
177                 }
178
179                 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
180                 public static WindowsImpersonationContext Impersonate (IntPtr userToken)
181                 {
182                         return new WindowsImpersonationContext (userToken);
183                 }
184
185                 // properties
186                 sealed override
187                 public string AuthenticationType {
188                         get { return _type; }
189                 }
190
191                 public virtual bool IsAnonymous
192                 {
193                         get { return (_account == WindowsAccountType.Anonymous); }
194                 }
195
196                 override
197                 public bool IsAuthenticated
198                 {
199                         get { return _authenticated; }
200                 }
201
202                 public virtual bool IsGuest
203                 {
204                         get { return (_account == WindowsAccountType.Guest); }
205                 }
206
207                 public virtual bool IsSystem
208                 {
209                         get { return (_account == WindowsAccountType.System); }
210                 }
211
212                 override
213                 public string Name
214                 {
215                         get {
216                                 if (_name == null) {
217                                         // revolve name (runtime)
218                                         _name = GetTokenName (_token);
219                                 }
220                                 return _name; 
221                         }
222                 }
223
224                 public virtual IntPtr Token
225                 {
226                         get { return _token; }
227                 }
228                 [MonoTODO ("not implemented")]
229                 public IdentityReferenceCollection Groups {
230                         get { throw new NotImplementedException (); }
231                 }
232
233                 [MonoTODO ("not implemented")]
234                 [ComVisible (false)]
235                 public TokenImpersonationLevel ImpersonationLevel {
236                         get { throw new NotImplementedException (); }
237                 }
238
239                 [MonoTODO ("not implemented")]
240                 [ComVisible (false)]
241                 public SecurityIdentifier Owner {
242                         get { throw new NotImplementedException (); }
243                 }
244
245                 [MonoTODO ("not implemented")]
246                 [ComVisible (false)]
247                 public SecurityIdentifier User {
248                         get { throw new NotImplementedException (); }
249                 }
250                 void IDeserializationCallback.OnDeserialization (object sender)
251                 {
252                         _token = (IntPtr) _info.GetValue ("m_userToken", typeof (IntPtr));
253                         // can't trust this alone - we must validate the token
254                         _name = _info.GetString ("m_name");
255                         if (_name != null) {
256                                 // validate token by comparing names
257                                 string name = GetTokenName (_token);
258                                 if (name != _name)
259                                         throw new SerializationException ("Token-Name mismatch.");
260                         }
261                         else {
262                                 // validate token by getting name
263                                 _name = GetTokenName (_token);
264                                 if (_name == null)
265                                         throw new SerializationException ("Token doesn't match a user.");
266                         }
267                         _type = _info.GetString ("m_type");
268                         _account = (WindowsAccountType) _info.GetValue ("m_acctType", typeof (WindowsAccountType));
269                         _authenticated = _info.GetBoolean ("m_isAuthenticated");
270                 }
271
272                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) 
273                 {
274                         info.AddValue ("m_userToken", _token);
275                         // can be null when not resolved
276                         info.AddValue ("m_name", _name);
277                         info.AddValue ("m_type", _type);
278                         info.AddValue ("m_acctType", _account);
279                         info.AddValue ("m_isAuthenticated", _authenticated);
280                 }
281
282                 internal ClaimsIdentity CloneAsBase ()
283                 {
284                         return base.Clone();
285                 }
286
287                 internal IntPtr GetTokenInternal ()
288                 {
289                         return _token;
290                 }
291
292                 private void SetToken (IntPtr token) 
293                 {
294                         if (Environment.IsUnix) {
295
296                                 _token = token;
297                                 // apply defaults
298                                 if (_type == null)
299                                         _type = "POSIX";
300                                 // override user choice in this specific case
301                                 if (_token == IntPtr.Zero)
302                                         _account = WindowsAccountType.System;
303                         }
304                         else {
305                                 if ((token == invalidWindows) && (_account != WindowsAccountType.Anonymous))
306                                         throw new ArgumentException ("Invalid token");
307
308                                 _token = token;
309                                 // apply defaults
310                                 if (_type == null)
311                                         _type = "NTLM";
312                         }
313                 }
314
315                 // see mono/mono/metadata/security.c for implementation
316
317                 // Many people use reflection to get a user's roles - so many 
318                 // that's it's hard to say it's an "undocumented" feature -
319                 // so we also implement it in Mono :-/
320                 // http://www.dotnet247.com/247reference/msgs/39/195403.aspx
321                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
322                 internal extern static string[] _GetRoles (IntPtr token);
323
324                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
325                 internal extern static IntPtr GetCurrentToken ();
326
327                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
328                 private extern static string GetTokenName (IntPtr token);
329
330                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
331                 private extern static IntPtr GetUserToken (string username);
332         }
333 }