//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
-// Sebastien Pouliot (spouliot@motus.com)
+// Sebastien Pouliot (sebastien@ximian.com)
//
// (C) 2002 Ximian, Inc (http://www.ximian.com)
// Portions (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// (C) 2004 Novell (http://www.novell.com)
//
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System.Security.Principal {
private bool _authenticated;
private string _name;
+ static private IntPtr invalidWindows = IntPtr.Zero;
+ // that seems to be the value used for (at least) AIX and MacOSX
+ static private IntPtr invalidPosix = (IntPtr) unchecked (-2);
+
public WindowsIdentity (IntPtr userToken)
- : this (userToken, "NTLM", WindowsAccountType.Normal, false) {}
+ : this (userToken, null, WindowsAccountType.Normal, false)
+ {
+ }
public WindowsIdentity (IntPtr userToken, string type)
- : this (userToken, type, WindowsAccountType.Normal, false) {}
+ : this (userToken, type, WindowsAccountType.Normal, false)
+ {
+ }
public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType)
- : this (userToken, type, acctType, false) {}
+ : this (userToken, type, acctType, false)
+ {
+ }
public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
{
- if (userToken == IntPtr.Zero)
- throw new ArgumentException ("Invalid token");
-
- _token = userToken;
_type = type;
_account = acctType;
_authenticated = isAuthenticated;
_name = null;
+ // last - as it can override some fields
+ SetToken (userToken);
}
#if !NET_1_0
public WindowsIdentity (string sUserPrincipalName)
- : this (sUserPrincipalName, null) {}
+ : this (sUserPrincipalName, null)
+ {
+ }
- [MonoTODO]
public WindowsIdentity (string sUserPrincipalName, string type)
{
if (sUserPrincipalName == null)
throw new NullReferenceException ("sUserPrincipalName");
- throw new ArgumentException ("only for Windows Server 2003 +");
+ // TODO: Windows 2003 compatibility should be done in runtime
+ IntPtr token = GetUserToken (sUserPrincipalName);
+ if ((!IsPosix) && (token == IntPtr.Zero)) {
+ throw new ArgumentException ("only for Windows Server 2003 +");
+ }
+
+ _authenticated = true;
+ _account = WindowsAccountType.Normal;
+ _type = type;
+ // last - as it can override some fields
+ SetToken (token);
}
[MonoTODO]
- public WindowsIdentity (SerializationInfo info, StreamingContext context) {}
+ public WindowsIdentity (SerializationInfo info, StreamingContext context)
+ {
+ }
#endif
- [MonoTODO]
+
~WindowsIdentity ()
{
+ // clear our copy but don't close it
+ // http://www.develop.com/kbrown/book/html/whatis_windowsprincipal.html
_token = IntPtr.Zero;
}
public static WindowsIdentity GetAnonymous ()
{
- WindowsIdentity id = new WindowsIdentity ((IntPtr)1, String.Empty, WindowsAccountType.Anonymous, false);
- // special case
- id._token = IntPtr.Zero;
- id._name = String.Empty;
+ WindowsIdentity id = null;
+ if (IsPosix) {
+ id = new WindowsIdentity ("nobody");
+ // special case
+ id._account = WindowsAccountType.Anonymous;
+ id._authenticated = false;
+ id._type = String.Empty;
+ }
+ else {
+ id = new WindowsIdentity (IntPtr.Zero, String.Empty, WindowsAccountType.Anonymous, false);
+ // special case (don't try to resolve the name)
+ id._name = String.Empty;
+ }
return id;
}
- [MonoTODO]
public static WindowsIdentity GetCurrent ()
{
- throw new NotImplementedException ();
+ return new WindowsIdentity (GetCurrentToken (), null, WindowsAccountType.Normal, true);
}
// methods
get { return (_account == WindowsAccountType.System); }
}
- [MonoTODO ("resolve missing")]
public virtual string Name
{
get {
if (_name == null) {
- // TODO: resolve name from token
- throw new NotImplementedException ();
+ // revolve name (runtime)
+ _name = GetTokenName (_token);
}
return _name;
}
throw new NotImplementedException ();
}
#endif
+ private static bool IsPosix {
+ get { return ((int) Environment.Platform == 128); }
+ }
+
+ private void SetToken (IntPtr token)
+ {
+ if (IsPosix) {
+ if (token == invalidPosix)
+ throw new ArgumentException ("Invalid token");
+
+ _token = token;
+ // apply defaults
+ if (_type == null)
+ _type = "POSIX";
+ // override user choice in this specific case
+ if (_token == IntPtr.Zero)
+ _account = WindowsAccountType.System;
+ }
+ else {
+ if ((token == invalidWindows) && (_account != WindowsAccountType.Anonymous))
+ throw new ArgumentException ("Invalid token");
+
+ _token = token;
+ // apply defaults
+ if (_type == null)
+ _type = "NTLM";
+ }
+ }
+
+ // see mono/mono/metadata/security.c for implementation
+
+ // Many people use reflection to get a user's roles - so many
+ // that's it's hard to say it's an "undocumented" feature -
+ // so we also implement it in Mono :-/
+ // http://www.dotnet247.com/247reference/msgs/39/195403.aspx
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal extern static string[] _GetRoles (IntPtr token);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal extern static IntPtr GetCurrentToken ();
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static string GetTokenName (IntPtr token);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static IntPtr GetUserToken (string username);
}
}
-
//
// Authors:
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Sebastien Pouliot (sebastien@ximian.com)
//
// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell (http://www.novell.com)
//
using System;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Security.Principal {
+
+ public class WindowsImpersonationContext {
-namespace System.Security.Principal
-{
- [MonoTODO]
- public class WindowsImpersonationContext
- {
private IntPtr _token;
+ private bool undo;
internal WindowsImpersonationContext (IntPtr token)
{
- _token = token;
- throw new NotImplementedException ();
+ // we get a copy to control it's lifetime
+ _token = DuplicateToken (token);
+ if (!SetCurrentToken (token)) {
+ throw new SecurityException ("Couldn't impersonate token.");
+ }
+ undo = false;
}
~WindowsImpersonationContext ()
{
- _token = (IntPtr) 0;
+ if (!undo) {
+ Undo ();
+ }
}
- [MonoTODO]
public void Undo ()
{
- throw new NotImplementedException ();
+ if (!RevertToSelf ()) {
+ CloseToken (_token);
+ throw new SecurityException ("Couldn't switch back to original token.");
+ }
+ CloseToken (_token);
+ undo = true;
+ GC.SuppressFinalize (this);
}
+
+ // see mono/mono/metadata/security.c for implementation
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static bool CloseToken (IntPtr token);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static IntPtr DuplicateToken (IntPtr token);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static bool SetCurrentToken (IntPtr token);
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static bool RevertToSelf ();
}
}
-
// WindowsPrincipal.cs: Windows IPrincipal implementation
//
// Author:
-// Sebastien Pouliot (spouliot@motus.com)
+// Sebastien Pouliot (sebastien@ximian.com)
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// (C) 2004 Novell (http://www.novell.com)
//
using System;
+using System.Collections;
+using System.Runtime.CompilerServices;
namespace System.Security.Principal {
public class WindowsPrincipal : IPrincipal {
private WindowsIdentity _identity;
+ // http://groups.google.ca/groups?q=WindowsPrincipal+m_roles&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=OghXf4OgCHA.4228%40tkmsftngp08&rnum=4
+ private string [] m_roles;
+
+ // case sensitivity versus number of groups
+ // http://groups.google.ca/groups?q=WindowsPrincipal+m_roles&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=%23JEMHsMQCHA.1916%40tkmsftngp13&rnum=5
public WindowsPrincipal (WindowsIdentity ntIdentity)
{
// methods
- [MonoTODO]
public virtual bool IsInRole (int rid)
{
- throw new NotImplementedException ();
+ if (IsPosix) {
+ return IsMemberOfGroupId (Token, (IntPtr) rid);
+ }
+ else {
+ string role = null;
+ switch (rid) {
+ case 544: // Administrator
+ role = "BUILTIN\\Administrators";
+ break;
+ case 545: // User
+ role = "BUILTIN\\Users";
+ break;
+ case 546: // Guest
+ role = "BUILTIN\\Guests";
+ break;
+ case 547: // PowerUser
+ role = "BUILTIN\\Power Users";
+ break;
+ case 548: // AccountOperator
+ role = "BUILTIN\\Account Operators";
+ break;
+ case 549: // SystemOperator
+ role = "BUILTIN\\System Operators";
+ break;
+ case 550: // PrintOperator
+ role = "BUILTIN\\Print Operators";
+ break;
+ case 551: // BackupOperator
+ role = "BUILTIN\\Backup Operators";
+ break;
+ case 552: // Replicator
+ role = "BUILTIN\\Replicator";
+ break;
+ default:
+ return false;
+ }
+ return IsInRole (role);
+ }
}
- [MonoTODO]
public virtual bool IsInRole (string role)
{
if (role == null)
return false; // ArgumentNullException
+
+ if (IsPosix) {
+ // note: Posix is always case-sensitive
+ return IsMemberOfGroupName (Token, role);
+ }
+ else {
+ // Windows specific code that
+ // (a) build the role cache like the MS framework (for compatibility)
+ // (b) case sensitive (for Fx 1.0) and case insensitive (later Fx)
+ if (m_roles == null) {
+ m_roles = WindowsIdentity._GetRoles (Token);
+ }
+#if !NET_1_0
+ role = role.ToUpper ();
+#endif
+ foreach (string check in m_roles) {
#if NET_1_0
- // case sensitive (for 1.0)
+ if (role == check)
+ return true;
#else
- // case insensitive (for 1.1 and later)
+ Console.WriteLine ("> {0}", check);
+ if ((check != null) && (role == check.ToUpper ()))
+ return true;
#endif
- throw new NotImplementedException ();
+ }
+ return false;
+ }
}
public virtual bool IsInRole (WindowsBuiltInRole role)
{
- return IsInRole ((int)role);
+ if (IsPosix) {
+ // right now we only map Administrator == root
+ string group = null;
+ switch (role) {
+ case WindowsBuiltInRole.Administrator:
+ group = "root";
+ break;
+ default:
+ return false;
+ }
+ return IsInRole (group);
+ }
+ else {
+ return IsInRole ((int) role);
+ }
+ }
+
+ private static bool IsPosix {
+ get { return ((int) Environment.Platform == 128); }
}
+
+ private IntPtr Token {
+ get { return (_identity as WindowsIdentity).Token; }
+ }
+
+ // see mono/mono/metadata/security.c for implementation
+
+ // note: never called by Win32 code (i.e. always return false)
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static bool IsMemberOfGroupId (IntPtr user, IntPtr group);
+
+ // note: never called by Win32 code (i.e. always return false)
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private extern static bool IsMemberOfGroupName (IntPtr user, string group);
}
}