Initial commit of the ActiveDirectoryProvider for #342
This commit is contained in:
parent
c135c883fe
commit
18b2d4d66c
2 changed files with 410 additions and 4 deletions
|
@ -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.
|
||||
/// </summary>
|
||||
public class ActiveDirectoryProvider {
|
||||
// Placeholder
|
||||
|
||||
private const string HELP_HELP = "Configuration is set with the following parameters:<br/>domain - The domain name (e.g. DOMAIN or DOMAIN.COM)<br/>server - A domain controller to authenticate against (e.g. MYDC1)<br/>admingroup - The AD group that will have admin access to the Wiki<br/>usergroup The AD group that will have user access to the Wiki<br/>username - An AD account username that has at minimum read access to the domain.<br/>password - The password for the above username.<br/><br/>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;
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public bool TestAccount(UserInfo user, string password) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserInfo[] GetUsers() {
|
||||
return new UserInfo[] { };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserInfo AddUser(string username, string displayName, string password, string email, bool active, DateTime dateTime) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserInfo ModifyUser(UserInfo user, string newDisplayName, string newPassword, string newEmail, bool newActive) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public bool RemoveUser(UserInfo user) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserGroup[] GetUserGroups() {
|
||||
return new UserGroup[] { };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserGroup AddUserGroup(string name, string description) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserGroup ModifyUserGroup(UserGroup group, string description) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public bool RemoveUserGroup(UserGroup group) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented
|
||||
/// </summary>
|
||||
public UserInfo SetUserMembership(UserInfo user, string[] groups) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to log the user in manually
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to log the user in automagically
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user info object for the currently logged in user.
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
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<string>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the account.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public UserInfo GetUserByEmail(string email) {
|
||||
|
||||
return m_StorageProvider.GetUserByEmail(email);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public void NotifyCookieLogin(UserInfo user) {
|
||||
|
||||
m_StorageProvider.NotifyCookieLogin(user);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public void NotifyLogout(UserInfo user) {
|
||||
|
||||
m_StorageProvider.NotifyLogout(user);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public bool StoreUserData(UserInfo user, string key, string value) {
|
||||
|
||||
return m_StorageProvider.StoreUserData(user, key, value);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public string RetrieveUserData(UserInfo user, string key) {
|
||||
|
||||
return m_StorageProvider.RetrieveUserData(user, key);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public IDictionary<string, string> RetrieveAllUserData(UserInfo user) {
|
||||
|
||||
return m_StorageProvider.RetrieveAllUserData(user);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented - Passed Directly to the IUsersStorageProviderV30
|
||||
/// </summary>
|
||||
public IDictionary<UserInfo, string> GetUsersWithData(string key) {
|
||||
|
||||
return m_StorageProvider.GetUsersWithData(key);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True, always, we can't write back to AD
|
||||
/// </summary>
|
||||
public bool UserAccountsReadOnly {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No
|
||||
/// </summary>
|
||||
public bool UserGroupsReadOnly {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True, always, we can't write back to AD
|
||||
/// </summary>
|
||||
public bool GroupMembershipReadOnly {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True, always, we can't write back to AD
|
||||
/// </summary>
|
||||
public bool UsersDataReadOnly {
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inits the settings
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignored
|
||||
/// </summary>
|
||||
public void Shutdown() {
|
||||
m_StorageProvider.Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plugin Information
|
||||
/// TODO return and complete
|
||||
/// </summary>
|
||||
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"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plugin Help Text
|
||||
/// </summary>
|
||||
public string ConfigHelpHtml {
|
||||
get { return HELP_HELP; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the plugin based on the configuration settings
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue