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