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
;
37 namespace System
.Security
.Principal
{
41 public class WindowsIdentity
: IIdentity
, IDeserializationCallback
, ISerializable
, IDisposable
{
42 private IntPtr _token
;
44 private WindowsAccountType _account
;
45 private bool _authenticated
;
47 private SerializationInfo _info
;
49 static private IntPtr invalidWindows
= IntPtr
.Zero
;
51 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
52 public WindowsIdentity (IntPtr userToken
)
53 : this (userToken
, null, WindowsAccountType
.Normal
, false)
57 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
58 public WindowsIdentity (IntPtr userToken
, string type
)
59 : this (userToken
, type
, WindowsAccountType
.Normal
, false)
63 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
64 public WindowsIdentity (IntPtr userToken
, string type
, WindowsAccountType acctType
)
65 : this (userToken
, type
, acctType
, false)
69 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
70 public WindowsIdentity (IntPtr userToken
, string type
, WindowsAccountType acctType
, bool isAuthenticated
)
74 _authenticated
= isAuthenticated
;
76 // last - as it can override some fields
80 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
81 public WindowsIdentity (string sUserPrincipalName
)
82 : this (sUserPrincipalName
, null)
86 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
87 public WindowsIdentity (string sUserPrincipalName
, string type
)
89 if (sUserPrincipalName
== null)
90 throw new NullReferenceException ("sUserPrincipalName");
92 // TODO: Windows 2003 compatibility should be done in runtime
93 IntPtr token
= GetUserToken (sUserPrincipalName
);
94 if ((!Environment
.IsUnix
) && (token
== IntPtr
.Zero
)) {
95 throw new ArgumentException ("only for Windows Server 2003 +");
98 _authenticated
= true;
99 _account
= WindowsAccountType
.Normal
;
101 // last - as it can override some fields
105 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
106 public WindowsIdentity (SerializationInfo info
, StreamingContext context
)
113 public void Dispose ()
115 _token
= IntPtr
.Zero
;
119 protected virtual void Dispose (bool disposing
)
121 _token
= IntPtr
.Zero
;
125 public static WindowsIdentity
GetAnonymous ()
127 WindowsIdentity id
= null;
128 if (Environment
.IsUnix
) {
129 id
= new WindowsIdentity ("nobody");
131 id
._account
= WindowsAccountType
.Anonymous
;
132 id
._authenticated
= false;
133 id
._type
= String
.Empty
;
136 id
= new WindowsIdentity (IntPtr
.Zero
, String
.Empty
, WindowsAccountType
.Anonymous
, false);
137 // special case (don't try to resolve the name)
138 id
._name
= String
.Empty
;
143 public static WindowsIdentity
GetCurrent ()
145 return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType
.Normal
, true);
147 [MonoTODO ("need icall changes")]
148 public static WindowsIdentity
GetCurrent (bool ifImpersonating
)
150 throw new NotImplementedException ();
153 [MonoTODO ("need icall changes")]
154 public static WindowsIdentity
GetCurrent (TokenAccessLevels desiredAccess
)
156 throw new NotImplementedException ();
160 public virtual WindowsImpersonationContext
Impersonate ()
162 return new WindowsImpersonationContext (_token
);
165 [SecurityPermission (SecurityAction
.Demand
, ControlPrincipal
=true)]
166 public static WindowsImpersonationContext
Impersonate (IntPtr userToken
)
168 return new WindowsImpersonationContext (userToken
);
173 public string AuthenticationType
{
174 get { return _type; }
177 public virtual bool IsAnonymous
179 get { return (_account == WindowsAccountType.Anonymous); }
182 public virtual bool IsAuthenticated
184 get { return _authenticated; }
187 public virtual bool IsGuest
189 get { return (_account == WindowsAccountType.Guest); }
192 public virtual bool IsSystem
194 get { return (_account == WindowsAccountType.System); }
197 public virtual string Name
201 // revolve name (runtime)
202 _name
= GetTokenName (_token
);
208 public virtual IntPtr Token
210 get { return _token; }
212 [MonoTODO ("not implemented")]
213 public IdentityReferenceCollection Groups
{
214 get { throw new NotImplementedException (); }
217 [MonoTODO ("not implemented")]
219 public TokenImpersonationLevel ImpersonationLevel
{
220 get { throw new NotImplementedException (); }
223 [MonoTODO ("not implemented")]
225 public SecurityIdentifier Owner
{
226 get { throw new NotImplementedException (); }
229 [MonoTODO ("not implemented")]
231 public SecurityIdentifier User
{
232 get { throw new NotImplementedException (); }
234 void IDeserializationCallback
.OnDeserialization (object sender
)
236 _token
= (IntPtr
) _info
.GetValue ("m_userToken", typeof (IntPtr
));
237 // can't trust this alone - we must validate the token
238 _name
= _info
.GetString ("m_name");
240 // validate token by comparing names
241 string name
= GetTokenName (_token
);
243 throw new SerializationException ("Token-Name mismatch.");
246 // validate token by getting name
247 _name
= GetTokenName (_token
);
248 if ((_name
== String
.Empty
) || (_name
== null))
249 throw new SerializationException ("Token doesn't match a user.");
251 _type
= _info
.GetString ("m_type");
252 _account
= (WindowsAccountType
) _info
.GetValue ("m_acctType", typeof (WindowsAccountType
));
253 _authenticated
= _info
.GetBoolean ("m_isAuthenticated");
256 void ISerializable
.GetObjectData (SerializationInfo info
, StreamingContext context
)
258 info
.AddValue ("m_userToken", _token
);
259 // can be null when not resolved
260 info
.AddValue ("m_name", _name
);
261 info
.AddValue ("m_type", _type
);
262 info
.AddValue ("m_acctType", _account
);
263 info
.AddValue ("m_isAuthenticated", _authenticated
);
266 private void SetToken (IntPtr token
)
268 if (Environment
.IsUnix
) {
274 // override user choice in this specific case
275 if (_token
== IntPtr
.Zero
)
276 _account
= WindowsAccountType
.System
;
279 if ((token
== invalidWindows
) && (_account
!= WindowsAccountType
.Anonymous
))
280 throw new ArgumentException ("Invalid token");
289 // see mono/mono/metadata/security.c for implementation
291 // Many people use reflection to get a user's roles - so many
292 // that's it's hard to say it's an "undocumented" feature -
293 // so we also implement it in Mono :-/
294 // http://www.dotnet247.com/247reference/msgs/39/195403.aspx
295 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
296 internal extern static string[] _GetRoles (IntPtr token
);
298 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
299 internal extern static IntPtr
GetCurrentToken ();
301 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
302 private extern static string GetTokenName (IntPtr token
);
304 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
305 private extern static IntPtr
GetUserToken (string username
);