using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Web;
using ScrewTurn.Wiki.PluginFramework;
namespace ScrewTurn.Wiki.Plugins.ActiveDirectory {
///
/// Implements a Users Storage Provider for Active Directory.
///
public class ActiveDirectoryProvider {
private const string HELP_HELP = "Configuration is set with the following parameters:
domain - The domain name (e.g. DOMAIN or DOMAIN.COM)
server - A domain controller to authenticate against (e.g. MYDC1)
admingroup - The AD group that will have admin access to the Wiki
usergroup The AD group that will have user access to the Wiki
username - An AD account username that has at minimum read access to the domain.
password - The password for the above username.
You will also need to adjust your web.config to set Authentication mode to Windows, and turn on NTLM on the server as well.";
private IHostV30 m_Host;
private string m_Server;
private string m_Domain;
private string m_SearchRoot;
private string m_AdminGroup;
private string m_UserGroup;
private string m_Username;
private string m_Password;
private IUsersStorageProviderV30 m_StorageProvider;
///
/// Not Implemented
///
public bool TestAccount(UserInfo user, string password) {
return false;
}
///
/// Not Implemented
///
public UserInfo[] GetUsers() {
return new UserInfo[] { };
}
///
/// Not Implemented
///
public UserInfo AddUser(string username, string displayName, string password, string email, bool active, DateTime dateTime) {
throw new NotImplementedException();
}
///
/// Not Implemented
///
public UserInfo ModifyUser(UserInfo user, string newDisplayName, string newPassword, string newEmail, bool newActive) {
throw new NotImplementedException();
}
///
/// Not Implemented
///
public bool RemoveUser(UserInfo user) {
throw new NotImplementedException();
}
///
/// Not Implemented
///
public UserGroup[] GetUserGroups() {
return new UserGroup[] { };
}
///
/// Not Implemented
///
public UserGroup AddUserGroup(string name, string description) {
throw new NotImplementedException();
}
///
/// Not Implemented
///
public UserGroup ModifyUserGroup(UserGroup group, string description) {
throw new NotImplementedException();
}
///
/// Not Implemented
///
public bool RemoveUserGroup(UserGroup group) {
throw new NotImplementedException();
}
///
/// Not Implemented
///
public UserInfo SetUserMembership(UserInfo user, string[] groups) {
throw new NotImplementedException();
}
///
/// Tries to log the user in manually
///
public UserInfo TryManualLogin(string username, string password) {
var info = m_StorageProvider.TryManualLogin(username, password);
if (info != null)
return info;
try {
using (var rootEntry = new DirectoryEntry(m_SearchRoot, username, password, AuthenticationTypes.Delegation | AuthenticationTypes.ReadonlyServer | AuthenticationTypes.Secure)) {
var nativeObject = rootEntry.NativeObject;
return GetUser(username);
}
} catch {
return null;
}
}
///
/// Tries to log the user in automagically
///
public UserInfo TryAutoLogin(HttpContext context) {
try {
if (!context.User.Identity.IsAuthenticated)
return null;
var username = context.User.Identity.Name.Substring(context.User.Identity.Name.IndexOf("\\") + 1);
return GetUser(username);
} catch {
return null;
}
}
///
/// Gets the user info object for the currently logged in user.
///
///
///
public UserInfo GetUser(string username) {
var user = m_StorageProvider.GetUser(username);
if (user != null)
return user;
using (var rootEntry = new DirectoryEntry(m_SearchRoot, m_Username, m_Password, AuthenticationTypes.Secure)) {
using (var searcher = new DirectorySearcher(rootEntry) {
Filter = string.Format("(&(objectClass=user)(objectCategory=person)(sAMAccountName={0}))", username)
})
{
searcher.PropertiesToLoad.Add("objectClass");
searcher.PropertiesToLoad.Add("member");
searcher.PropertiesToLoad.Add("sAMAccountName");
searcher.PropertiesToLoad.Add("sn");
searcher.PropertiesToLoad.Add("givenName");
searcher.PropertiesToLoad.Add("department");
searcher.PropertiesToLoad.Add("title");
searcher.PropertiesToLoad.Add("mail");
searcher.PropertiesToLoad.Add("displayName");
DirectoryEntry entry;
try {
entry = searcher.FindOne().GetDirectoryEntry();
} catch {
return null;
}
var displayName = string.Empty;
var emailAddress = string.Empty;
var adminGroup = false;
var userGroup = false;
var values = entry.Properties["displayName"];
if (values != null && values.Count > 0)
displayName = values[0].ToString();
values = entry.Properties["mail"];
if (values != null && values.Count > 0)
emailAddress = values[0].ToString();
var rootPath = entry.Path;
rootPath = rootPath.Substring(0, rootPath.IndexOf("/", 7) + 1);
for (var i = 0; i < entry.Properties["memberOf"].Count; i++) {
using (var currentEntry = new DirectoryEntry(rootPath + entry.Properties["memberOf"][i])) {
if (IsAccountTypeGroup(currentEntry)) {
values = currentEntry.Properties["sAMAccountName"];
if (values != null && values.Count > 0) {
if (values[0].ToString() == m_AdminGroup)
adminGroup = true;
if (values[0].ToString() == m_UserGroup)
userGroup = true;
}
}
}
}
var userGroups = new List();
if (adminGroup)
userGroups.Add("Administrators");
if (userGroup)
userGroups.Add("Users");
user = m_StorageProvider.AddUser(username, displayName, "jdzs98duadj2918j9sdjasd", emailAddress, true, DateTime.Now);
user = m_StorageProvider.SetUserMembership(user, userGroups.ToArray());
return user;
}
}
}
///
/// Gets the type of the account.
///
private static bool IsAccountTypeGroup(DirectoryEntry entry) {
var objectClass = entry.Properties["objectClass"];
for (var i = 0; i < objectClass.Count; i++)
if ((string)objectClass[i] == "group")
return true;
return false;
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public UserInfo GetUserByEmail(string email) {
return m_StorageProvider.GetUserByEmail(email);
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public void NotifyCookieLogin(UserInfo user) {
m_StorageProvider.NotifyCookieLogin(user);
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public void NotifyLogout(UserInfo user) {
m_StorageProvider.NotifyLogout(user);
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public bool StoreUserData(UserInfo user, string key, string value) {
return m_StorageProvider.StoreUserData(user, key, value);
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public string RetrieveUserData(UserInfo user, string key) {
return m_StorageProvider.RetrieveUserData(user, key);
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public IDictionary RetrieveAllUserData(UserInfo user) {
return m_StorageProvider.RetrieveAllUserData(user);
}
///
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
///
public IDictionary GetUsersWithData(string key) {
return m_StorageProvider.GetUsersWithData(key);
}
///
/// True, always, we can't write back to AD
///
public bool UserAccountsReadOnly {
get { return true; }
}
///
/// No
///
public bool UserGroupsReadOnly {
get { return true; }
}
///
/// True, always, we can't write back to AD
///
public bool GroupMembershipReadOnly {
get { return true; }
}
///
/// True, always, we can't write back to AD
///
public bool UsersDataReadOnly {
get { return false; }
}
///
/// Inits the settings
///
public void Init(IHostV30 host, string config) {
m_Host = host;
var provider = (from a in host.GetUsersStorageProviders(true)
where a.Information.Name != this.Information.Name
select a).FirstOrDefault();
if (provider == null)
throw new InvalidConfigurationException("This provider require an additional active storage provider for storing of active directory user information.");
m_StorageProvider = provider;
InitConfig(config);
}
///
/// Ignored
///
public void Shutdown() {
m_StorageProvider.Shutdown();
}
///
/// Plugin Information
/// TODO return and complete
///
public ComponentInformation Information {
get { return new ComponentInformation("ActiveDirectoryProvider", "ScrewTurn Software", "3.0.1.417", "http://www.screwturn.eu", "http://www.screwturn.eu/Version/ActiveDirectoryProvider.txt"); }
}
///
/// Plugin Help Text
///
public string ConfigHelpHtml {
get { return HELP_HELP; }
}
///
/// Configures the plugin based on the configuration settings
///
///
private void InitConfig(string config)
{
if (string.IsNullOrEmpty(config))
throw new InvalidConfigurationException("Config settings must be set before plugin can be used.");
try {
var configParts = config.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var configPart in configParts) {
var setting = configPart.Substring(0, configPart.IndexOf("="));
var value = configPart.Substring(configPart.IndexOf("=") + 1);
switch (setting.ToLower().Trim())
{
case "domain":
m_Domain = value;
break;
case "server":
m_Server = value;
break;
case "admingroup":
m_AdminGroup = value;
break;
case "usergroup":
m_UserGroup = value;
break;
case "username":
m_Username = value;
break;
case "password":
m_Password = value;
break;
}
}
var ldap = string.Empty;
if (!string.IsNullOrEmpty(m_Server))
ldap = string.Format("{0}/", m_Server);
var ldapParts = m_Domain.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
m_SearchRoot = string.Format("LDAP://{0}DC={1}", ldap, string.Join(",DC=", ldapParts));
} catch (Exception ex) {
throw new InvalidConfigurationException("The configuration is invalid.", ex);
}
}
}
}