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 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Runtime.CompilerServices;
38 using System.Runtime.Serialization;
40 namespace System.Security.Principal {
44 public class WindowsIdentity : IIdentity, IDeserializationCallback {
46 public class WindowsIdentity : IIdentity, IDeserializationCallback, ISerializable {
48 private IntPtr _token;
50 private WindowsAccountType _account;
51 private bool _authenticated;
53 private SerializationInfo _info;
55 static private IntPtr invalidWindows = IntPtr.Zero;
56 // that seems to be the value used for (at least) AIX and MacOSX
57 static private IntPtr invalidPosix = (IntPtr) unchecked (-2);
59 public WindowsIdentity (IntPtr userToken)
60 : this (userToken, null, WindowsAccountType.Normal, false)
64 public WindowsIdentity (IntPtr userToken, string type)
65 : this (userToken, type, WindowsAccountType.Normal, false)
69 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType)
70 : this (userToken, type, acctType, false)
74 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
78 _authenticated = isAuthenticated;
80 // last - as it can override some fields
84 public WindowsIdentity (string sUserPrincipalName)
85 : this (sUserPrincipalName, null)
89 public WindowsIdentity (string sUserPrincipalName, string type)
91 if (sUserPrincipalName == null)
92 throw new NullReferenceException ("sUserPrincipalName");
94 // TODO: Windows 2003 compatibility should be done in runtime
95 IntPtr token = GetUserToken (sUserPrincipalName);
96 if ((!IsPosix) && (token == IntPtr.Zero)) {
97 throw new ArgumentException ("only for Windows Server 2003 +");
100 _authenticated = true;
101 _account = WindowsAccountType.Normal;
103 // last - as it can override some fields
107 public WindowsIdentity (SerializationInfo info, StreamingContext context)
115 // clear our copy but don't close it
116 // http://www.develop.com/kbrown/book/html/whatis_windowsprincipal.html
117 _token = IntPtr.Zero;
122 public static WindowsIdentity GetAnonymous ()
124 WindowsIdentity id = null;
126 id = new WindowsIdentity ("nobody");
128 id._account = WindowsAccountType.Anonymous;
129 id._authenticated = false;
130 id._type = String.Empty;
133 id = new WindowsIdentity (IntPtr.Zero, String.Empty, WindowsAccountType.Anonymous, false);
134 // special case (don't try to resolve the name)
135 id._name = String.Empty;
140 public static WindowsIdentity GetCurrent ()
142 return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType.Normal, true);
147 public virtual WindowsImpersonationContext Impersonate ()
149 return new WindowsImpersonationContext (_token);
152 public static WindowsImpersonationContext Impersonate (IntPtr userToken)
154 return new WindowsImpersonationContext (userToken);
159 public virtual string AuthenticationType
161 get { return _type; }
164 public virtual bool IsAnonymous
166 get { return (_account == WindowsAccountType.Anonymous); }
169 public virtual bool IsAuthenticated
171 get { return _authenticated; }
174 public virtual bool IsGuest
176 get { return (_account == WindowsAccountType.Guest); }
179 public virtual bool IsSystem
181 get { return (_account == WindowsAccountType.System); }
184 public virtual string Name
188 // revolve name (runtime)
189 _name = GetTokenName (_token);
195 public virtual IntPtr Token
197 get { return _token; }
200 void IDeserializationCallback.OnDeserialization (object sender)
202 _token = (IntPtr) _info.GetValue ("m_userToken", typeof (IntPtr));
203 // can't trust this alone - we must validate the token
204 _name = _info.GetString ("m_name");
206 // validate token by comparing names
207 string name = GetTokenName (_token);
209 throw new SerializationException ("Token-Name mismatch.");
212 // validate token by getting name
213 _name = GetTokenName (_token);
214 if ((_name == String.Empty) || (_name == null))
215 throw new SerializationException ("Token doesn't match a user.");
217 _type = _info.GetString ("m_type");
218 _account = (WindowsAccountType) _info.GetValue ("m_acctType", typeof (WindowsAccountType));
219 _authenticated = _info.GetBoolean ("m_isAuthenticated");
222 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
224 info.AddValue ("m_userToken", _token);
225 // can be null when not resolved
226 info.AddValue ("m_name", _name);
227 info.AddValue ("m_type", _type);
228 info.AddValue ("m_acctType", _account);
229 info.AddValue ("m_isAuthenticated", _authenticated);
232 private static bool IsPosix {
233 get { return ((int) Environment.Platform == 128); }
236 private void SetToken (IntPtr token)
239 if (token == invalidPosix)
240 throw new ArgumentException ("Invalid token");
246 // override user choice in this specific case
247 if (_token == IntPtr.Zero)
248 _account = WindowsAccountType.System;
251 if ((token == invalidWindows) && (_account != WindowsAccountType.Anonymous))
252 throw new ArgumentException ("Invalid token");
261 // see mono/mono/metadata/security.c for implementation
263 // Many people use reflection to get a user's roles - so many
264 // that's it's hard to say it's an "undocumented" feature -
265 // so we also implement it in Mono :-/
266 // http://www.dotnet247.com/247reference/msgs/39/195403.aspx
267 [MethodImplAttribute (MethodImplOptions.InternalCall)]
268 internal extern static string[] _GetRoles (IntPtr token);
270 [MethodImplAttribute (MethodImplOptions.InternalCall)]
271 internal extern static IntPtr GetCurrentToken ();
273 [MethodImplAttribute (MethodImplOptions.InternalCall)]
274 private extern static string GetTokenName (IntPtr token);
276 [MethodImplAttribute (MethodImplOptions.InternalCall)]
277 private extern static IntPtr GetUserToken (string username);