Hello,
This post contains code for a RoleProvider that allows you to assign
ADAM roles to ADAM users only.
To make it work, just paste it into a new cs file, add a reference to
the Microsoft.Interop.Security.AzRoles dll
I hope someone with knowledge of ADAM and/or Active Directory will
assist in completing the last two methods of this provider!
Here's the code for so far:
==========================================
using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Collections;
using System;
using System.Resources;
using System.Data;
using System.Data.Odbc;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Security;
using System.Globalization;
using Microsoft.Interop.Security;
using Microsoft.Interop.Security.AzRoles;
using System.Security.Principal;
using System.DirectoryServices;
using System.Runtime.InteropServices;
namespace InSumma.Security.Adam.Roles
{
/// <summary>
/// Implementation of a .NET 2.0 Role Provider that supports
/// assigning roles to ADAM users. The standard AzMan Role Provider
/// only supports assigning roles to Windows Users.
/// </summary>
public sealed class AdamRoleProvider : RoleProvider
{
//
// Global connection string, generic exception message, event
log info.
//
private string eventSource = "AdamRoleProvider";
private string eventLog = "Application";
private string exceptionMessage = "Er is een fout opgetreden in
de RoleProvider. Meer details staan in de Event Log.";
private string azManApplicationName="";
private ConnectionStringSettings pConnectionStringSettings;
private string azManConnectionString="";
//
// If false, exceptions are thrown to the caller. If true,
// exceptions are written to the event log.
//
private bool pWriteExceptionsToEventLog = false;
public bool WriteExceptionsToEventLog
{
get { return pWriteExceptionsToEventLog; }
set { pWriteExceptionsToEventLog = value; }
}
//
// System.Configuration.Provider.ProviderBase.Initialize Method
//
public override void Initialize(string name,
NameValueCollection config)
{
//
// Initialize values from web.config.
//
System.Diagnostics.TextWriterTraceListener twtl = new
TextWriterTraceListener(@"c:\AdamRoleProvider.txt");
System.Diagnostics.Trace.Listeners.Add(twtl);
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
Initialize");
System.Diagnostics.Trace.Flush();
if (config == null)
throw new ArgumentNullException("config");
if (name == null || name.Length == 0)
name = "AdamRoleProvider";
if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Role Provider supporting
assignment of roles to ADAM users");
}
// Initialize the abstract base class.
base.Initialize(name, config);
if (config["applicationName"] == null ||
config["applicationName"].Trim() == "")
azManApplicationName =
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
else
azManApplicationName = config["applicationName"];
if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() ==
"TRUE")
{
pWriteExceptionsToEventLog = true;
}
}
//
// Initialize AdamRoleProvider
//
// Read connectionstring only if it's not yet set by the
property
if (azManConnectionString=="")
{
pConnectionStringSettings =
ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (pConnectionStringSettings == null ||
pConnectionStringSettings.ConnectionString.Trim() == "")
throw new ProviderException("AdamRoleProvider
connection string cannot be blank.");
azManConnectionString =
pConnectionStringSettings.ConnectionString;
}
}
//
// Allow to set a connectionstring by code (for testing)
//
public string ConnectionString
{
set { azManConnectionString = value; }
}
//
// System.Web.Security.RoleProvider properties.
//
public override string ApplicationName
{
get { return azManApplicationName; }
set { azManApplicationName = value; }
}
#region Implementation of AdamRoleProvider
//
// System.Web.Security.RoleProvider methods.
//
//
// RoleProvider.AddUsersToRoles
//
public override void AddUsersToRoles(string[] usernames,
string[] rolenames)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
AddUsersToRoles");
System.Diagnostics.Trace.Flush();
// Check for duplicate roles
foreach (string rolename in rolenames)
{
if (!RoleExists(rolename))
throw new ProviderException("Role name not
found.");
}
foreach (string username in usernames)
{
if (username.IndexOf(',') > 0)
throw new ArgumentException("User names cannot
contain commas.");
foreach (string rolename in rolenames)
{
if (IsUserInRole(username, rolename))
throw new ProviderException("User is already in
role.");
}
}
try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();
// Loop users and roles
foreach (string username in usernames)
{
MembershipUser user = Membership.GetUser(username);
foreach (string rolename in rolenames)
{
IAzRole role = _azApp.OpenRole(rolename, null);
role.AddMember(user.ProviderUserKey.ToString(),
null);
role.Submit(0, null);
}
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "AddUsersToRoles");
else
throw e;
}
}
//
// RoleProvider.CreateRole
//
public override void CreateRole(string rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
CreateRole");
System.Diagnostics.Trace.Flush();
// Check precondition
if (rolename.IndexOf(',') > 0)
throw new ArgumentException("Role names cannot contain
commas.");
if (RoleExists(rolename))
throw new ProviderException("Role name already
exists.");
try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();
// Add a role
IAzTask task = _azApp.CreateTask(rolename, null);
task.IsRoleDefinition = 1;
task.Submit(0, null);
IAzRole role = _azApp.CreateRole(rolename, null);
role.AddTask(rolename, null);
role.Submit(0, null);
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "CreateRole");
else
throw e;
}
}
//
// RoleProvider.DeleteRole
//
public override bool DeleteRole(string rolename, bool
throwOnPopulatedRole)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
DeleteRole");
System.Diagnostics.Trace.Flush();
// Check preconditions
if (!RoleExists(rolename))
throw new ProviderException("Role does not exist.");
if (throwOnPopulatedRole && GetUsersInRole(rolename).Length
throw new ProviderException("Cannot delete a populated
role.");
try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();
// Delete a role
_azApp.DeleteTask(rolename, null);
_azApp.Submit(0, null);
_azApp.DeleteRole(rolename, null);
_azApp.Submit(0, null);
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "DeleteRole");
return false;
}
else
throw e;
}
return true;
}
//
// RoleProvider.GetAllRoles
//
public override string[] GetAllRoles()
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
GetAllRoles");
System.Diagnostics.Trace.Flush();
try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();
int i = 1;
string[] roles = new string[_azApp.Roles.Count];
while (i <= _azApp.Roles.Count)
{
IAzRole role = (IAzRole)_azApp.Roles
;
roles[i-1] = role.Name;
i++;
}
return roles;
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "GetAllRoles");
else
throw e;
}
return new string[0];
}
//
// RoleProvider.GetRolesForUser
//
public override string[] GetRolesForUser(string username)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
GetRolesForUser");
System.Diagnostics.Trace.Flush();
try
{
throw new NotSupportedException("GetRolesForUser is not
supported by the AdamRoleProvider");
//TODO Implement this method!!!
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "GetRolesForUser");
else
throw e;
}
return new string[0];
}
//
// RoleProvider.GetUsersInRole
//
public override string[] GetUsersInRole(string rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
GetUsersInRole");
System.Diagnostics.Trace.Flush();
try
{
// Connect to the ADAM store
IAzApplication _azApp = GetAdamApp();
IAzRole role = _azApp.OpenRole(rolename, null);
if (role == null) throw new ProviderException("Role
"+rolename+" was not found");
object[] members = (object[]) role.Members;
string[] usernames = new string[members.Length];
int i = 1;
while(i <= members.Length)
{
usernames[i-1] = members[i-1].ToString();
i++;
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "GetUsersInRole");
else
throw e;
}
return new string[0];
}
//
// RoleProvider.IsUserInRole
//
public override bool IsUserInRole(string username, string
rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
IsUserInRole");
System.Diagnostics.Trace.Flush();
try
{
string[] roles = GetRolesForUser(username);
foreach(string role in roles)
{
if (role==rolename)
return true;
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "IsUserInRole");
else
throw e;
}
return false;
}
//
// RoleProvider.RemoveUsersFromRoles
//
public override void RemoveUsersFromRoles(string[] usernames,
string[] rolenames)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
RemoveUsersFromRoles");
System.Diagnostics.Trace.Flush();
foreach (string rolename in rolenames)
{
if (!RoleExists(rolename))
throw new ProviderException("Role name not
found.");
}
foreach (string username in usernames)
{
foreach (string rolename in rolenames)
{
if (!IsUserInRole(username, rolename))
throw new ProviderException("User is not in
role.");
}
}
try
{
IAzApplication _azApp = GetAdamApp();
foreach (string username in usernames)
{
MembershipUser user = Membership.GetUser(username);
foreach (string rolename in rolenames)
{
IAzRole role = _azApp.OpenRole(rolename, null);
role.DeleteMember(user.ProviderUserKey.ToString(), null);
role.Submit(0, null);
}
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "RemoveUsersFromRoles");
else
throw e;
}
}
//
// RoleProvider.RoleExists
//
public override bool RoleExists(string rolename)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
RoleExists");
System.Diagnostics.Trace.Flush();
bool exists = false;
try
{
IAzApplication _azApp = GetAdamApp();
// Warning! The Roles collection is 1-bases instead of
0-based!!
int i = 1;
while (i <= _azApp.Roles.Count && !exists)
{
IAzRole role = (IAzRole)_azApp.Roles;
if (role.Name == rolename)
exists = true;
i++;
}
}
catch (Exception ex)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(ex, "RoleExists");
else
throw ex;
}
return exists;
}
//
// RoleProvider.FindUsersInRole
//
public override string[] FindUsersInRole(string rolename,
string usernameToMatch)
{
// Show entry of method
System.Diagnostics.Trace.WriteLine("AdamRoleProvider:
FindUsersInRole");
System.Diagnostics.Trace.Flush();
try
{
throw new NotSupportedException("FindUsersInRole is not
supported by the AdamRoleProvider");
//TODO Implement this method!!!
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
WriteToEventLog(e, "FindUsersInRole");
else
throw e;
}
return new string[0];
}
#endregion
#region Support methods
//
// WriteToEventLog
// A helper function that writes exception detail to the
event log. Exceptions
// are written to the event log as a security measure to avoid
private database
// details from being returned to the browser. If a method does
not return a status
// or boolean indicating the action succeeded or failed, a
generic exception is also
// thrown by the caller.
//
private void WriteToEventLog(Exception e, string action)
{
EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;
string message = exceptionMessage + "\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e.ToString();
log.WriteEntry(message);
}
/// <summary>
/// Initializes communication with ADAM
/// </summary>
/// <returns>A reference to the ADAM application</returns>
private IAzApplication GetAdamApp()
{
AzAuthorizationStore _azStore = new
AzAuthorizationStoreClass();
_azStore.Initialize(0, azManConnectionString, null);
IAzApplication _azApp =
_azStore.OpenApplication(azManApplicationName, null);
return _azApp;
}
#endregion
}
}