Add license and copyright to all source files in corlib
[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 // (C) 2004 Novell (http://www.novell.com)
11 //
12
13 //
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 //
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:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
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.
34 //
35
36 using System;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.Serialization;
39
40 namespace System.Security.Principal {
41
42         [Serializable]
43 #if NET_1_0
44         public class WindowsIdentity : IIdentity, IDeserializationCallback {
45 #else
46         public class WindowsIdentity : IIdentity, IDeserializationCallback, ISerializable {
47 #endif
48                 private IntPtr _token;
49                 private string _type;
50                 private WindowsAccountType _account;
51                 private bool _authenticated;
52                 private string _name;
53                 private SerializationInfo _info;
54
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);
58
59                 public WindowsIdentity (IntPtr userToken) 
60                         : this (userToken, null, WindowsAccountType.Normal, false)
61                 {
62                 }
63
64                 public WindowsIdentity (IntPtr userToken, string type) 
65                         : this (userToken, type, WindowsAccountType.Normal, false)
66                 {
67                 }
68
69                 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType)
70                         : this (userToken, type, acctType, false)
71                 {
72                 }
73
74                 public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
75                 {
76                         _type = type;
77                         _account = acctType;
78                         _authenticated = isAuthenticated;
79                         _name = null;
80                         // last - as it can override some fields
81                         SetToken (userToken);
82                 }
83 #if !NET_1_0
84                 public WindowsIdentity (string sUserPrincipalName) 
85                         : this (sUserPrincipalName, null)
86                 {
87                 }
88
89                 public WindowsIdentity (string sUserPrincipalName, string type)
90                 {
91                         if (sUserPrincipalName == null)
92                                 throw new NullReferenceException ("sUserPrincipalName");
93
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 +");
98                         }
99
100                         _authenticated = true;
101                         _account = WindowsAccountType.Normal;
102                         _type = type;
103                         // last - as it can override some fields
104                         SetToken (token);
105                 }
106
107                 public WindowsIdentity (SerializationInfo info, StreamingContext context)
108                 {
109                         _info = info;
110                 }
111 #endif
112
113                 ~WindowsIdentity ()
114                 {
115                         // clear our copy but don't close it
116                         // http://www.develop.com/kbrown/book/html/whatis_windowsprincipal.html
117                         _token = IntPtr.Zero;
118                 }
119
120                 // static methods
121
122                 public static WindowsIdentity GetAnonymous ()
123                 {
124                         WindowsIdentity id = null;
125                         if (IsPosix) {
126                                 id = new WindowsIdentity ("nobody");
127                                 // special case
128                                 id._account = WindowsAccountType.Anonymous;
129                                 id._authenticated = false;
130                                 id._type = String.Empty;
131                         }
132                         else {
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;
136                         }
137                         return id;
138                 }
139
140                 public static WindowsIdentity GetCurrent ()
141                 {
142                         return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType.Normal, true);
143                 }
144
145                 // methods
146
147                 public virtual WindowsImpersonationContext Impersonate ()
148                 {
149                         return new WindowsImpersonationContext (_token);
150                 }
151
152                 public static WindowsImpersonationContext Impersonate (IntPtr userToken)
153                 {
154                         return new WindowsImpersonationContext (userToken);
155                 }
156
157                 // properties
158
159                 public virtual string AuthenticationType
160                 {
161                         get { return _type; }
162                 }
163
164                 public virtual bool IsAnonymous
165                 {
166                         get { return (_account == WindowsAccountType.Anonymous); }
167                 }
168
169                 public virtual bool IsAuthenticated
170                 {
171                         get { return _authenticated; }
172                 }
173
174                 public virtual bool IsGuest
175                 {
176                         get { return (_account == WindowsAccountType.Guest); }
177                 }
178
179                 public virtual bool IsSystem
180                 {
181                         get { return (_account == WindowsAccountType.System); }
182                 }
183
184                 public virtual string Name
185                 {
186                         get {
187                                 if (_name == null) {
188                                         // revolve name (runtime)
189                                         _name = GetTokenName (_token);
190                                 }
191                                 return _name; 
192                         }
193                 }
194
195                 public virtual IntPtr Token
196                 {
197                         get { return _token; }
198                 }
199
200                 void IDeserializationCallback.OnDeserialization (object sender)
201                 {
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");
205                         if (_name != null) {
206                                 // validate token by comparing names
207                                 string name = GetTokenName (_token);
208                                 if (name != _name)
209                                         throw new SerializationException ("Token-Name mismatch.");
210                         }
211                         else {
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.");
216                         }
217                         _type = _info.GetString ("m_type");
218                         _account = (WindowsAccountType) _info.GetValue ("m_acctType", typeof (WindowsAccountType));
219                         _authenticated = _info.GetBoolean ("m_isAuthenticated");
220                 }
221 #if !NET_1_0
222                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) 
223                 {
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);
230                 }
231 #endif
232                 private static bool IsPosix {
233                         get { return ((int) Environment.Platform == 128); }
234                 }
235
236                 private void SetToken (IntPtr token) 
237                 {
238                         if (IsPosix) {
239                                 if (token == invalidPosix)
240                                         throw new ArgumentException ("Invalid token");
241
242                                 _token = token;
243                                 // apply defaults
244                                 if (_type == null)
245                                         _type = "POSIX";
246                                 // override user choice in this specific case
247                                 if (_token == IntPtr.Zero)
248                                         _account = WindowsAccountType.System;
249                         }
250                         else {
251                                 if ((token == invalidWindows) && (_account != WindowsAccountType.Anonymous))
252                                         throw new ArgumentException ("Invalid token");
253
254                                 _token = token;
255                                 // apply defaults
256                                 if (_type == null)
257                                         _type = "NTLM";
258                         }
259                 }
260
261                 // see mono/mono/metadata/security.c for implementation
262
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);
269
270                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
271                 internal extern static IntPtr GetCurrentToken ();
272
273                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
274                 private extern static string GetTokenName (IntPtr token);
275
276                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
277                 private extern static IntPtr GetUserToken (string username);
278         }
279 }