// (c) 2006 Richard Grimes // www.grimes.demon.co.uk using System; using System.Threading; using System.Runtime.InteropServices; using System.Security.Principal; using System.Security.Permissions; class App { static void Main() { AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); Thread.CurrentPrincipal = new MyPrincipal("Richard", "NTLM", true); try { Console.WriteLine("called OnlyAdministrators"); OnlyAdministrators(); } catch (Exception e) { Console.WriteLine("failed " + e.Message); } } [PrincipalPermission(SecurityAction.Demand, Role=@"BUILTIN\Administrators")] static void OnlyAdministrators() { if (IsInRole("Administrators")) { Console.WriteLine("OnlyAdministrators called"); } else { Console.WriteLine("OnlyAdministrators failed"); } } static bool IsInRole(string group) { string[] members = NTSecurity.GetLocalGroupMembers(group); WindowsIdentity identity = WindowsIdentity.GetCurrent(); foreach (string member in members) { if (member == identity.Name) return true; } return false; } } class NTSecurity { const int MAX_PREFERRED_LENGTH = -1; [DllImport("netapi32", CharSet = CharSet.Unicode)] static extern int NetLocalGroupGetMembers(string serverName, string groupName, int level, out IntPtr buffer, int len, out int entriesRead, out int totalEntries, int handle); [DllImport("netapi32")] static extern int NetApiBufferFree(IntPtr buffer); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct LocalGroupMembersInfo3 { public string lgrmi3_domainandname; } public static string[] GetLocalGroupMembers(string group) { IntPtr lgmi = IntPtr.Zero; int entriesRead = 0; int totalEntries = 0; int ret = NetLocalGroupGetMembers(null, group, 3, out lgmi, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, 0); if (ret != 0) { return new string[0]; } string[] users = new string[entriesRead]; IntPtr iter = lgmi; for(int x = 0; x < entriesRead; ++x) { LocalGroupMembersInfo3 members = (LocalGroupMembersInfo3)Marshal.PtrToStructure(iter, typeof(LocalGroupMembersInfo3)); users[x] = members.lgrmi3_domainandname; iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LocalGroupMembersInfo3))); } NetApiBufferFree(lgmi); return users; } } class MyPrincipal : IPrincipal, IIdentity { string name; string auth; bool isAuth; public MyPrincipal(string name, string auth, bool isAuth) { this.name = name; this.auth = auth; this.isAuth = isAuth; } public IIdentity Identity { get { return this; } } public bool IsInRole(string role) { return true; } public string AuthenticationType { get { return auth; } } public bool IsAuthenticated { get { return isAuth; } } public string Name { get { return name; } } }