diff --git a/ActiveDirectoryProvider/ActiveDirectoryProvider.cs b/ActiveDirectoryProvider/ActiveDirectoryProvider.cs index 9b3c6a0..238c5c0 100644 --- a/ActiveDirectoryProvider/ActiveDirectoryProvider.cs +++ b/ActiveDirectoryProvider/ActiveDirectoryProvider.cs @@ -1,8 +1,9 @@ - -using System; +using System; using System.Collections.Generic; +using System.DirectoryServices; using System.Linq; -using System.Text; +using System.Web; +using ScrewTurn.Wiki.PluginFramework; namespace ScrewTurn.Wiki.Plugins.ActiveDirectory { @@ -10,7 +11,410 @@ namespace ScrewTurn.Wiki.Plugins.ActiveDirectory { /// Implements a Users Storage Provider for Active Directory. /// public class ActiveDirectoryProvider { - // Placeholder + + 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); + } + } } } diff --git a/ActiveDirectoryProvider/ActiveDirectoryProvider.csproj b/ActiveDirectoryProvider/ActiveDirectoryProvider.csproj index 141b625..0437b8d 100644 --- a/ActiveDirectoryProvider/ActiveDirectoryProvider.csproj +++ b/ActiveDirectoryProvider/ActiveDirectoryProvider.csproj @@ -39,6 +39,8 @@ 3.5 + + 3.5