public string ResolveGroupName(string name) { ImportedPrincipalInfo info = ResolveInfo(name, this.Groups); if (info == null) { return(null); } return(info.LoginName); }
public Principal ResolveGroup(ClientContext ctx, string name) { ImportedPrincipalInfo info = ResolveInfo(name, this.Groups); if (info == null) { return(null); } return(info.Resolve(ctx)); }
public Principal ResolveUser(ClientContext ctx, string name) { // dm_group is ignored because there is no analog in SharePoint if (name == DM_GROUP) { return(null); } ImportedPrincipalInfo info = ResolveInfo(name, this.Users); if (info == null) { return(null); } return(info.Resolve(ctx)); }
public string ResolveUserName(string name) { // The "special" names get...well..."specialed handling" switch (name) { case DM_OWNER: case DM_GROUP: case DM_WORLD: return(name); default: break; } ImportedPrincipalInfo info = ResolveInfo(name, this.Users); if (info == null) { return(null); } return(info.Name); }
private Dictionary <string, ImportedPrincipalInfo> generateGroupMappings(DirectoryEntry ldapDirectory, string ldapSyncAlias, string fallbackName, string internalName) { Dictionary <string, ImportedPrincipalInfo> groups = new Dictionary <string, ImportedPrincipalInfo>(); string domain = ((string)ldapDirectory.Properties["name"][0]).ToUpper(); Log.Info(string.Format("Loading LDAP Groups from {0}", ldapDirectory.Path)); Dictionary <string, ImportedPrincipalInfo> groupsByGUID = new Dictionary <string, ImportedPrincipalInfo>(); Dictionary <string, ImportedPrincipalInfo> groupsByLogin = new Dictionary <string, ImportedPrincipalInfo>(); XmlReader cache = LoadCache(ldapDirectory, "groups"); bool cacheLoaded = false; if (cache != null) { try { using (cache) { int c = 0; Log.Info("Loading groups from the cache..."); while (cache.ReadToFollowing("entry")) { ImportedPrincipalInfo info = new ImportedPrincipalInfo(XElement.Load(cache.ReadSubtree())); groupsByGUID[info.Guid] = info; groupsByLogin[info.LoginName] = info; if ((++c % PAGE_SIZE) == 0) { Log.Info(string.Format("Loaded {0} users from the cache", c)); } } cacheLoaded = true; } } catch (Exception e) { groupsByGUID.Clear(); groupsByLogin.Clear(); Log.Warn(string.Format("Failed to load data from the group cache for LDAP directory [{0}] (for {1})", ldapDirectory.Path, domain), e); } finally { cache = null; } } if (!cacheLoaded) { using (DirectorySearcher ldapSearch = new DirectorySearcher(ldapDirectory)) { ldapSearch.Filter = "(objectClass=group)"; ldapSearch.PageSize = PAGE_SIZE; using (SearchResultCollection ldapResults = ldapSearch.FindAll()) { int c = 0; foreach (SearchResult r in ldapResults) { ImportedPrincipalInfo info = new ImportedPrincipalInfo(r, domain); groupsByGUID[info.Guid] = info; groupsByLogin[info.LoginName] = info; if ((++c % ldapSearch.PageSize) == 0) { Log.Info(string.Format("Loaded {0} groups", c)); } } } } List <string> logins = new List <string>(groupsByLogin.Keys); List <ImportedPrincipalInfo> items = new List <ImportedPrincipalInfo>(groupsByLogin.Count); logins.Sort(); foreach (string l in logins) { items.Add(groupsByLogin[l]); } try { StoreCache(ldapDirectory, "groups", items); } catch (Exception e) { Log.Warn(string.Format("Failed to write the group cache for the LDAP directory at [{0}] (domain {1})", ldapDirectory.Path, ldapDirectory.Name), e); } } // Step 2: sanitize the fallback groups. Their non-existance is an error if ((fallbackName != null) && !groupsByLogin.ContainsKey(fallbackName)) { fallbackName = null; } if ((internalName != null) && !groupsByLogin.ContainsKey(internalName)) { internalName = null; } // Step 3: Scan through the XML file generating the mappings for the groups being referenced using (XmlReader groupsXml = this.ImportContext.LoadIndex("groups")) { Log.Info(string.Format("Loaded {0} LDAP groups, resolving the groups in XML...", groupsByGUID.Count)); while (groupsXml.ReadToFollowing("group")) { using (XmlReader groupxml = groupsXml.ReadSubtree()) { XElement group = XElement.Load(groupxml); XNamespace ns = group.GetDefaultNamespace(); string name = (string)group.Element(ns + "name"); string source = (string)group.Element(ns + "source"); string type = (string)group.Element(ns + "type"); IEnumerable <XElement> attributes = group.Element(ns + "attributes").Elements(ns + "attribute"); ImportedPrincipalInfo info = null; switch (source) { case "LDAP": string ldapGuid = ((string)attributes.FirstOrDefault(a => a.Attribute("name").Value == "dctm:group_global_unique_id")).ToLower().Trim(); // ldapGuid will be of the form DIRECTORY:hexGuid, so we have to parse the directory name. If it's the same directory // as our domain uses, then we can search by guid directly. Otherwise, we have to search by samaccountname string[] data = ldapGuid.Split(':'); if (data[0] == ldapSyncAlias && groupsByGUID.ContainsKey(data[1])) { info = groupsByGUID[data[1]]; } if (info == null) { // Either not the same domain, or couldn't find the GUID in question, so... if (groupsByLogin.ContainsKey(name)) { info = groupsByLogin[name]; } else if (fallbackName != null) { info = groupsByLogin[fallbackName]; } } break; default: string key = (name.StartsWith("dm_") || name.StartsWith("${") ? internalName : fallbackName); if (key != null) { info = groupsByLogin[key]; } break; } if (info != null) { groups[name] = info; } } } // Make sure the fallbacks are in place if (fallbackName != null && !groups.ContainsKey(fallbackName)) { groups[fallbackName] = groupsByLogin[fallbackName]; } if (internalName != null && !groups.ContainsKey(internalName)) { groups[internalName] = groupsByLogin[internalName]; } } return(groups); }
private Dictionary <string, ImportedPrincipalInfo> generateUserMappings(DirectoryEntry ldapDirectory, string ldapSyncAlias, string fallbackName, string internalName) { Dictionary <string, ImportedPrincipalInfo> users = new Dictionary <string, ImportedPrincipalInfo>(); // Step 1: Get all the AD users in one pass - this is quicker string domain = ((string)ldapDirectory.Properties["name"][0]).ToUpper(); Log.Info(string.Format("Loading LDAP Users from {0} (domain = {1})", ldapDirectory.Path, domain)); Dictionary <string, ImportedPrincipalInfo> usersByGUID = new Dictionary <string, ImportedPrincipalInfo>(); Dictionary <string, ImportedPrincipalInfo> usersByLogin = new Dictionary <string, ImportedPrincipalInfo>(); Dictionary <string, ImportedPrincipalInfo> usersByKerberosId = new Dictionary <string, ImportedPrincipalInfo>(); XmlReader cache = LoadCache(ldapDirectory, "users"); bool cacheLoaded = false; if (cache != null) { try { using (cache) { int c = 0; Log.Info("Loading users from the cache..."); while (cache.ReadToFollowing("entry")) { ImportedPrincipalInfo info = new ImportedPrincipalInfo(XElement.Load(cache.ReadSubtree())); if (info.Enabled) { usersByGUID[info.Guid] = info; usersByLogin[info.LoginName] = info; if (info.KerberosId != null) { usersByKerberosId[info.KerberosId] = info; } } if ((++c % PAGE_SIZE) == 0) { Log.Info(string.Format("Loaded {0} users from the cache", c)); } } cacheLoaded = true; } } catch (Exception e) { usersByGUID.Clear(); usersByLogin.Clear(); usersByKerberosId.Clear(); Log.Warn(string.Format("Failed to load data from the user cache for LDAP directory [{0}] (for {1})", ldapDirectory.Path, domain), e); } finally { cache = null; } } if (!cacheLoaded) { using (DirectorySearcher ldapSearch = new DirectorySearcher(ldapDirectory)) { ldapSearch.Filter = "(&(objectClass=user)(objectCategory=person))"; ldapSearch.PageSize = PAGE_SIZE; using (SearchResultCollection ldapResults = ldapSearch.FindAll()) { int c = 0; foreach (SearchResult r in ldapResults) { ImportedPrincipalInfo info = new ImportedPrincipalInfo(r, domain); if (info.Enabled) { usersByGUID[info.Guid] = info; usersByLogin[info.LoginName] = info; if (info.KerberosId != null) { usersByKerberosId[info.KerberosId] = info; } } if ((++c % ldapSearch.PageSize) == 0) { Log.Info(string.Format("Loaded {0} users", c)); } } } } List <string> logins = new List <string>(usersByLogin.Keys); List <ImportedPrincipalInfo> items = new List <ImportedPrincipalInfo>(usersByLogin.Count); logins.Sort(); foreach (string l in logins) { items.Add(usersByLogin[l]); } try { StoreCache(ldapDirectory, "users", items); } catch (Exception e) { Log.Warn(string.Format("Failed to write the user cache for the LDAP directory at [{0}] (domain {1})", ldapDirectory.Path, ldapDirectory.Name), e); } } // Step 2: sanitize the fallback users. if ((fallbackName != null) && !usersByLogin.ContainsKey(fallbackName)) { fallbackName = null; } if ((internalName != null) && !usersByLogin.ContainsKey(internalName)) { internalName = null; } // Step 3: Scan through the XML file generating the mappings for the users being referenced using (XmlReader usersXml = this.ImportContext.LoadIndex("users")) { Log.Info(string.Format("Loaded {0} LDAP users, resolving the users in XML...", usersByGUID.Count)); while (usersXml.ReadToFollowing("user")) { using (XmlReader userXml = usersXml.ReadSubtree()) { XElement user = XElement.Load(userXml); XNamespace ns = user.GetDefaultNamespace(); string name = (string)user.Element(ns + "name"); string source = (string)user.Element(ns + "source"); string loginName = (string)user.Element(ns + "loginName"); string osName = (string)user.Element(ns + "osName"); IEnumerable <XElement> attributes = user.Element(ns + "attributes").Elements(ns + "attribute"); ImportedPrincipalInfo info = null; switch (source) { case "LDAP": string ldapGuid = ((string)attributes.FirstOrDefault(a => a.Attribute("name").Value == "dctm:user_global_unique_id")).ToLower().Trim(); // ldapGuid will be of the form DIRECTORY:hexGuid, so we have to parse the directory name. If it's the same directory // as our domain uses, then we can search by guid directly. Otherwise, we have to search by samaccountname string[] data = ldapGuid.Split(':'); if (data[0] == ldapSyncAlias && usersByGUID.ContainsKey(data[1])) { info = usersByGUID[data[1]]; } if (info == null) { // Either not the same domain, or couldn't find the GUID in question, so... if (usersByLogin.ContainsKey(loginName)) { info = usersByLogin[loginName]; } else if (usersByLogin.ContainsKey(osName)) { info = usersByLogin[osName]; } else if (fallbackName != null) { info = usersByLogin[fallbackName]; } } break; case "dm_krb": // We do things differently here... if (usersByKerberosId.ContainsKey(osName)) { info = usersByKerberosId[osName]; } else if (usersByLogin.ContainsKey(loginName)) { info = usersByLogin[loginName]; } else if (fallbackName != null) { info = usersByLogin[fallbackName]; } break; default: if (name.StartsWith("dm_")) { if (internalName != null) { info = usersByLogin[internalName]; } } else { if (usersByLogin.ContainsKey(loginName)) { info = usersByLogin[loginName]; } else if (usersByLogin.ContainsKey(osName)) { info = usersByLogin[osName]; } else { string key = (name.StartsWith("${") ? internalName : fallbackName); if (key != null) { info = usersByLogin[key]; } } } break; } if (info != null) { users[name] = info; if (name.StartsWith("${")) { users[loginName] = info; } } } } // Make sure the fallbacks are in place if (fallbackName != null && !users.ContainsKey(fallbackName)) { users[fallbackName] = usersByLogin[fallbackName]; } if (internalName != null && !users.ContainsKey(internalName)) { users[internalName] = usersByLogin[internalName]; } // Add the DM_WORLD mapping users[DM_WORLD] = new ImportedPrincipalInfo(EVERYONE_NAME, null, EVERYONE_ID); } return(users); }