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 // (C) 2004 Novell (http://www.novell.com)
14 using System.Runtime.CompilerServices;
15 using System.Runtime.Serialization;
17 namespace System.Security.Principal {
21 public class WindowsIdentity : IIdentity, IDeserializationCallback {
23 public class WindowsIdentity : IIdentity, IDeserializationCallback, ISerializable {
25 private IntPtr _token;
27 private WindowsAccountType _account;
28 private bool _authenticated;
30 private SerializationInfo _info;
32 static private IntPtr invalidWindows = IntPtr.Zero;
33 // that seems to be the value used for (at least) AIX and MacOSX
34 static private IntPtr invalidPosix = (IntPtr) unchecked (-2);
36 public WindowsIdentity (IntPtr userToken)
37 : this (userToken, null, WindowsAccountType.Normal, false)
41 public WindowsIdentity (IntPtr userToken, string type)
42 : this (userToken, type, WindowsAccountType.Normal, false)
46 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType)
47 : this (userToken, type, acctType, false)
51 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
55 _authenticated = isAuthenticated;
57 // last - as it can override some fields
61 public WindowsIdentity (string sUserPrincipalName)
62 : this (sUserPrincipalName, null)
66 public WindowsIdentity (string sUserPrincipalName, string type)
68 if (sUserPrincipalName == null)
69 throw new NullReferenceException ("sUserPrincipalName");
71 // TODO: Windows 2003 compatibility should be done in runtime
72 IntPtr token = GetUserToken (sUserPrincipalName);
73 if ((!IsPosix) && (token == IntPtr.Zero)) {
74 throw new ArgumentException ("only for Windows Server 2003 +");
77 _authenticated = true;
78 _account = WindowsAccountType.Normal;
80 // last - as it can override some fields
84 public WindowsIdentity (SerializationInfo info, StreamingContext context)
92 // clear our copy but don't close it
93 // http://www.develop.com/kbrown/book/html/whatis_windowsprincipal.html
99 public static WindowsIdentity GetAnonymous ()
101 WindowsIdentity id = null;
103 id = new WindowsIdentity ("nobody");
105 id._account = WindowsAccountType.Anonymous;
106 id._authenticated = false;
107 id._type = String.Empty;
110 id = new WindowsIdentity (IntPtr.Zero, String.Empty, WindowsAccountType.Anonymous, false);
111 // special case (don't try to resolve the name)
112 id._name = String.Empty;
117 public static WindowsIdentity GetCurrent ()
119 return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType.Normal, true);
124 public virtual WindowsImpersonationContext Impersonate ()
126 return new WindowsImpersonationContext (_token);
129 public static WindowsImpersonationContext Impersonate (IntPtr userToken)
131 return new WindowsImpersonationContext (userToken);
136 public virtual string AuthenticationType
138 get { return _type; }
141 public virtual bool IsAnonymous
143 get { return (_account == WindowsAccountType.Anonymous); }
146 public virtual bool IsAuthenticated
148 get { return _authenticated; }
151 public virtual bool IsGuest
153 get { return (_account == WindowsAccountType.Guest); }
156 public virtual bool IsSystem
158 get { return (_account == WindowsAccountType.System); }
161 public virtual string Name
165 // revolve name (runtime)
166 _name = GetTokenName (_token);
172 public virtual IntPtr Token
174 get { return _token; }
177 void IDeserializationCallback.OnDeserialization (object sender)
179 _token = (IntPtr) _info.GetValue ("m_userToken", typeof (IntPtr));
180 // can't trust this alone - we must validate the token
181 _name = _info.GetString ("m_name");
183 // validate token by comparing names
184 string name = GetTokenName (_token);
186 throw new SerializationException ("Token-Name mismatch.");
189 // validate token by getting name
190 _name = GetTokenName (_token);
191 if ((_name == String.Empty) || (_name == null))
192 throw new SerializationException ("Token doesn't match a user.");
194 _type = _info.GetString ("m_type");
195 _account = (WindowsAccountType) _info.GetValue ("m_acctType", typeof (WindowsAccountType));
196 _authenticated = _info.GetBoolean ("m_isAuthenticated");
199 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
201 info.AddValue ("m_userToken", _token);
202 // can be null when not resolved
203 info.AddValue ("m_name", _name);
204 info.AddValue ("m_type", _type);
205 info.AddValue ("m_acctType", _account);
206 info.AddValue ("m_isAuthenticated", _authenticated);
209 private static bool IsPosix {
210 get { return ((int) Environment.Platform == 128); }
213 private void SetToken (IntPtr token)
216 if (token == invalidPosix)
217 throw new ArgumentException ("Invalid token");
223 // override user choice in this specific case
224 if (_token == IntPtr.Zero)
225 _account = WindowsAccountType.System;
228 if ((token == invalidWindows) && (_account != WindowsAccountType.Anonymous))
229 throw new ArgumentException ("Invalid token");
238 // see mono/mono/metadata/security.c for implementation
240 // Many people use reflection to get a user's roles - so many
241 // that's it's hard to say it's an "undocumented" feature -
242 // so we also implement it in Mono :-/
243 // http://www.dotnet247.com/247reference/msgs/39/195403.aspx
244 [MethodImplAttribute (MethodImplOptions.InternalCall)]
245 internal extern static string[] _GetRoles (IntPtr token);
247 [MethodImplAttribute (MethodImplOptions.InternalCall)]
248 internal extern static IntPtr GetCurrentToken ();
250 [MethodImplAttribute (MethodImplOptions.InternalCall)]
251 private extern static string GetTokenName (IntPtr token);
253 [MethodImplAttribute (MethodImplOptions.InternalCall)]
254 private extern static IntPtr GetUserToken (string username);