Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...


Sneak preview sequel : the Principal

Because of OS identities restrictions, mainly how we create them, my previous blog sample wasn't portable (i.e. limited to Linux and other Unix operating system). Thankfully things are easier when dealing with principals.

The IPrincipal interface has one property, Identity, and one method, bool IsInRole(string). The WindowsPrincipal implementation provides overloaded IsInRole methods but this just adds other ways to get the same results.

The goal of classes implementing IPrincipal is to allow a consistent way to use Role Based Access Control (RBAC). The GenericPrincipal let you supply an array of string, in the constructor, with the roles you want to associate with the identity. The WindowsPrincipal use the Windows local or network group (either an NT domain or an Active Directory). So it only seems natural to map this functionality to Unix's group when running on *x operating systems.

The following sample use the WindowsPrincipal class in a simple interactive console application that let you query users and groups.

using System; using System.Runtime.InteropServices; using System.Security.Principal; class WinPrincipal { [DllImport ("advapi32.dll", CallingConvention=CallingConvention.StdCall)] public static extern bool LogonUser (string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); static void Principal (WindowsIdentity user) { WindowsPrincipal wp = new WindowsPrincipal (user); while (true) { Console.Write ("Enter group name: "); string group = Console.ReadLine (); if (group == String.Empty) break; Console.WriteLine ("\t{0} is {1}a member of {2}{3}", user.Name, (wp.IsInRole (group) ? String.Empty : "NOT "), group, Environment.NewLine); } } [STAThread] static void Main (string[] args) { bool posix = ((int) Environment.OSVersion.Platform == 128); while (true) { Console.Write ("Enter username:\t"); string username = Console.ReadLine (); if (username == String.Empty) break; WindowsIdentity user = null; // check for Posix versus Windows if (posix) { user = new WindowsIdentity (username); } else { Console.Write ("Enter domain:\t"); string domain = Console.ReadLine (); Console.Write ("Enter password:\t"); string password = Console.ReadLine (); IntPtr token = IntPtr.Zero; // note: we should close that handle LogonUser (username, domain, password, 2, 0, ref token); if (token == IntPtr.Zero) { Console.WriteLine ("Invalid username/domain/password"); continue; } user = new WindowsIdentity (token); } Principal (user); } } }

As we can see the only difference between the Windows and Linux version is done at runtime. The Windows version requires the domain and password to obtain a token (the only part requiring P/Invoke in the sample). Note that no impersonation is done in the sample (neither on Linux nor on Windows - as we don't change the process identity) so it doesn't require root access to be run.

WARNING: Again this is a sneak preview of uncommitted stuff, i.e. this isn't part of the latest Mono release (0.31).

Running on Windows

This is what the sample looks when run on Windows.

Enter username: test Enter domain: farscape Enter password: ******** Enter group name: BUILTIN\Administrators FARSCAPE\test is NOT a member of BUILTIN\Administrators Enter group name: BUILTIN\Users FARSCAPE\test is a member of BUILTIN\Users Enter group name: Enter username:

Running on Linux

This is what the sample looks when run on Linux.

Enter username: root Enter group name: root root is a member of root Enter group name: bin root is a member of bin Enter group name: adm root is a member of adm Enter group name: sys root is a member of sys Enter group name: nobody root is NOT a member of nobody Enter group name: Enter username: nobody Enter group name: nobody nobody is a member of nobody Enter group name: root nobody is NOT a member of root Enter group name: Enter username:

Now I have to merge the Linux and Windows versions of WindowsIdentity, WindowsImpersonationContext and WindowsPrincipal into a single version, test again and commit :-).

4/7/2004 22:39:07 | Comments

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.