2 // System.Security.Principal.WindowsIdentity
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Sebastien Pouliot (sebastien@ximian.com)
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)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
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 using Microsoft.Win32.SafeHandles;
39 namespace System.Security.Principal {
43 public class WindowsIdentity :
44 System.Security.Claims.ClaimsIdentity,
45 IIdentity, IDeserializationCallback, ISerializable, IDisposable {
46 private IntPtr _token;
48 private WindowsAccountType _account;
49 private bool _authenticated;
51 private SerializationInfo _info;
53 static private IntPtr invalidWindows = IntPtr.Zero;
56 public new const string DefaultIssuer = "AD AUTHORITY";
58 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
59 public WindowsIdentity (IntPtr userToken)
60 : this (userToken, null, WindowsAccountType.Normal, false)
64 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
65 public WindowsIdentity (IntPtr userToken, string type)
66 : this (userToken, type, WindowsAccountType.Normal, false)
70 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
71 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType)
72 : this (userToken, type, acctType, false)
76 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
77 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
81 _authenticated = isAuthenticated;
83 // last - as it can override some fields
87 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
88 public WindowsIdentity (string sUserPrincipalName)
89 : this (sUserPrincipalName, null)
93 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
94 public WindowsIdentity (string sUserPrincipalName, string type)
96 if (sUserPrincipalName == null)
97 throw new NullReferenceException ("sUserPrincipalName");
99 // TODO: Windows 2003 compatibility should be done in runtime
100 IntPtr token = GetUserToken (sUserPrincipalName);
101 if ((!Environment.IsUnix) && (token == IntPtr.Zero)) {
102 throw new ArgumentException ("only for Windows Server 2003 +");
105 _authenticated = true;
106 _account = WindowsAccountType.Normal;
108 // last - as it can override some fields
112 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
113 public WindowsIdentity (SerializationInfo info, StreamingContext context)
118 internal WindowsIdentity (ClaimsIdentity claimsIdentity, IntPtr userToken)
119 : base (claimsIdentity)
121 if (userToken != IntPtr.Zero && userToken.ToInt64() > 0)
123 SetToken (userToken);
128 public void Dispose ()
130 _token = IntPtr.Zero;
134 protected virtual void Dispose (bool disposing)
136 _token = IntPtr.Zero;
140 public static WindowsIdentity GetAnonymous ()
142 WindowsIdentity id = null;
143 if (Environment.IsUnix) {
144 id = new WindowsIdentity ("nobody");
146 id._account = WindowsAccountType.Anonymous;
147 id._authenticated = false;
148 id._type = String.Empty;
151 id = new WindowsIdentity (IntPtr.Zero, String.Empty, WindowsAccountType.Anonymous, false);
152 // special case (don't try to resolve the name)
153 id._name = String.Empty;
158 public static WindowsIdentity GetCurrent ()
160 return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType.Normal, true);
162 [MonoTODO ("need icall changes")]
163 public static WindowsIdentity GetCurrent (bool ifImpersonating)
165 throw new NotImplementedException ();
168 [MonoTODO ("need icall changes")]
169 public static WindowsIdentity GetCurrent (TokenAccessLevels desiredAccess)
171 throw new NotImplementedException ();
175 public virtual WindowsImpersonationContext Impersonate ()
177 return new WindowsImpersonationContext (_token);
180 [SecurityPermission (SecurityAction.Demand, ControlPrincipal=true)]
181 public static WindowsImpersonationContext Impersonate (IntPtr userToken)
183 return new WindowsImpersonationContext (userToken);
188 public string AuthenticationType {
189 get { return _type; }
192 public virtual bool IsAnonymous
194 get { return (_account == WindowsAccountType.Anonymous); }
198 public bool IsAuthenticated
200 get { return _authenticated; }
203 public virtual bool IsGuest
205 get { return (_account == WindowsAccountType.Guest); }
208 public virtual bool IsSystem
210 get { return (_account == WindowsAccountType.System); }
218 // revolve name (runtime)
219 _name = GetTokenName (_token);
225 public virtual IntPtr Token
227 get { return _token; }
229 [MonoTODO ("not implemented")]
230 public IdentityReferenceCollection Groups {
231 get { throw new NotImplementedException (); }
234 [MonoTODO ("not implemented")]
236 public TokenImpersonationLevel ImpersonationLevel {
237 get { throw new NotImplementedException (); }
240 [MonoTODO ("not implemented")]
242 public SecurityIdentifier Owner {
243 get { throw new NotImplementedException (); }
246 [MonoTODO ("not implemented")]
248 public SecurityIdentifier User {
249 get { throw new NotImplementedException (); }
251 void IDeserializationCallback.OnDeserialization (object sender)
253 _token = (IntPtr) _info.GetValue ("m_userToken", typeof (IntPtr));
254 // can't trust this alone - we must validate the token
255 _name = _info.GetString ("m_name");
257 // validate token by comparing names
258 string name = GetTokenName (_token);
260 throw new SerializationException ("Token-Name mismatch.");
263 // validate token by getting name
264 _name = GetTokenName (_token);
266 throw new SerializationException ("Token doesn't match a user.");
268 _type = _info.GetString ("m_type");
269 _account = (WindowsAccountType) _info.GetValue ("m_acctType", typeof (WindowsAccountType));
270 _authenticated = _info.GetBoolean ("m_isAuthenticated");
273 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
275 info.AddValue ("m_userToken", _token);
276 // can be null when not resolved
277 info.AddValue ("m_name", _name);
278 info.AddValue ("m_type", _type);
279 info.AddValue ("m_acctType", _account);
280 info.AddValue ("m_isAuthenticated", _authenticated);
283 internal ClaimsIdentity CloneAsBase ()
288 internal IntPtr GetTokenInternal ()
293 private void SetToken (IntPtr token)
295 if (Environment.IsUnix) {
301 // override user choice in this specific case
302 if (_token == IntPtr.Zero)
303 _account = WindowsAccountType.System;
306 if ((token == invalidWindows) && (_account != WindowsAccountType.Anonymous))
307 throw new ArgumentException ("Invalid token");
316 public SafeAccessTokenHandle AccessToken {
317 get { throw new NotImplementedException (); }
320 // see mono/mono/metadata/security.c for implementation
322 // Many people use reflection to get a user's roles - so many
323 // that's it's hard to say it's an "undocumented" feature -
324 // so we also implement it in Mono :-/
325 // http://www.dotnet247.com/247reference/msgs/39/195403.aspx
326 [MethodImplAttribute (MethodImplOptions.InternalCall)]
327 internal extern static string[] _GetRoles (IntPtr token);
329 [MethodImplAttribute (MethodImplOptions.InternalCall)]
330 internal extern static IntPtr GetCurrentToken ();
332 [MethodImplAttribute (MethodImplOptions.InternalCall)]
333 private extern static string GetTokenName (IntPtr token);
335 [MethodImplAttribute (MethodImplOptions.InternalCall)]
336 private extern static IntPtr GetUserToken (string username);