public static SearchResultCollection Search(DirectoryEntry searchRoot, string filter, bool novellSupport, string guidProp) { var dsDirSearcher = new DirectorySearcher(searchRoot) { Filter = filter, SizeLimit = 10000, PageSize = 10000 }; // Set the search filter // NOVELL - force searcher to retrieve the objects' GUID // - this is not done by default when connecting to Novell eDirectory if (novellSupport) { dsDirSearcher.PropertiesToLoad.Add(guidProp); } try { return(dsDirSearcher.FindAll()); } catch (Exception e) { AdLog.LogException(e); } return(null); }
// ============================================================================== Static methods private static async Task <SyncConfiguration> LoadConfiguration() { try { dynamic settingsContent = Content.LoadAsync(SettingsPath).Result; if (settingsContent == null) { return(null); } string binaryUrl = _siteUrl.TrimEnd('/') + settingsContent.Binary.__mediaresource.media_src + "&includepasswords=true"; var settingsText = await RESTCaller.GetResponseStringAsync(new Uri(binaryUrl)); var config = JsonHelper.Deserialize <SyncConfiguration>(settingsText); // decrypt passwords and inject them back to the configuration foreach (var server in config.Servers.Where(server => server.LogonCredentials != null && !string.IsNullOrEmpty(server.LogonCredentials.Password))) { var request = new ODataRequest { ActionName = "Decrypt", Path = "Root", IsCollectionRequest = false, SiteUrl = _siteUrl }; try { server.LogonCredentials.Password = await RESTCaller.GetResponseStringAsync( request.GetUri(), ClientContext.Current.Servers[0], HttpMethod.Post, JsonHelper.Serialize(new { text = server.LogonCredentials.Password })); } catch (ClientException cex) { AdLog.LogError("Error during password decryption. " + Common.FormatClientException(cex)); } catch (Exception ex) { AdLog.LogException(ex); } } // preload all AD-related content types from the server ADRelatedContentTypes = await LoadADRelatedContentTypes(); return(config); } catch (Exception ex) { AdLog.LogException(ex); } return(null); }
public static void UpdatePortalUserCustomProperties(DirectoryEntry entry, dynamic content, SyncTree syncTree) { // sAMAccountName -> Name if (syncTree.Server.SyncUserName) { content.Name = entry.Properties[syncTree.UserNameProperty].Value.ToString(); // in case of AD users the content name and login name are the same content.LoginName = content.Name; } // user actions foreach (var propMapping in syncTree.Mappings) { if (propMapping.AdProperties.Count == 1) { if (propMapping.PortalProperties.Count == 1) { // 1 ADproperty + 1 portalproperty var portalProp = propMapping.PortalProperties[0]; var adProp = propMapping.AdProperties[0]; var adValue = GetEntryValue(entry, adProp); SetContentValue(content, portalProp, adValue, ADObjectType.User); // Email is a special case: if it is empty, the user cannot be synced, at least we log it here. if (string.CompareOrdinal(portalProp.Name, "Email") == 0 && string.IsNullOrEmpty(adValue)) { AdLog.LogWarning("Email is empty for user " + entry.Path); } } else { // 1 ADproperty + n portalproperty // split AD value (preserving spaces) and put them into portal properties var adProp = propMapping.AdProperties[0]; var adValues = GetEntryValue(entry, adProp).Split(new[] { propMapping.Separator }, StringSplitOptions.None); int index = 0; foreach (var portalProp in propMapping.PortalProperties) { var adValue = (index < adValues.Length) ? adValues[index] : null; SetContentValue(content, portalProp, adValue, ADObjectType.User); index++; } } } else { // 1 portalproperty + n ADproperty // concat AD property values and put it into the single portal property var portalProp = propMapping.PortalProperties[0]; var adValue = propMapping.ConcatAdPropValues(entry); SetContentValue(content, portalProp, adValue, ADObjectType.User); } } }
public bool VerifyConnection() { // this is clearly invalid if (string.IsNullOrEmpty(this.LdapServer)) { return(false); } // we do not have to verify certification if (!this.UseSsl || this.TrustWrongCertification || this.LogonCredentials == null || this.LogonCredentials.Anonymous) { return(true); } try { // use default port if a port is not provided var port = this.Port == 0 ? 389 : this.Port; using (var conn = new LdapConnection(new LdapDirectoryIdentifier(this.LdapServer, port))) { conn.SessionOptions.SecureSocketLayer = true; conn.SessionOptions.VerifyServerCertificate = (connection, certificate) => { return(true); }; conn.Credential = new NetworkCredential(this.LogonCredentials.Username, this.LogonCredentials.Password); conn.AuthType = AuthType.Basic; conn.Bind(); return(true); } } catch (Exception ex) { AdLog.LogError("Could not connect to server " + this.LdapServer + " " + ex); } return(false); }
public static async Task <IEnumerable <Content> > QueryContentByTypeAndPath(ADObjectType objType, string startPath, string[] select = null, int skip = 0, int top = 0) { try { var types = GetContentTypeNames(objType); QuerySettings settings = null; if (skip > 0 || top > 0) { settings = new QuerySettings { Skip = skip, Top = top }; } return(await Content.QueryForAdminAsync("+InTree:'" + startPath + "' +TypeIs:(" + string.Join(" ", types) + ") .SORT:Path", select, settings : settings)); } catch (Exception ex) { AdLog.LogException(ex); } return(new Content[0]); }
// ============================================================================== Instance methods /// <summary> /// Validates the configuration. Returns false only if it is absolutely /// not possible to execute ad sync. Othervise only logs warnings. /// </summary> public bool Validate() { if (this.Servers.Count == 0) { AdLog.LogWarning("No servers are configured."); } if (this.SyncTrees.Count == 0) { AdLog.LogWarning("No sync trees are configured."); } // validate server properties var invalidServers = new List <Server>(); foreach (var server in this.Servers) { if (string.IsNullOrEmpty(server.LdapServer)) { AdLog.LogWarning("LDAP server address is missing."); invalidServers.Add(server); } if (!server.VerifyConnection()) { AdLog.LogWarning("LDAP server connection failed."); invalidServers.Add(server); } } // remove incorrectly configured servers foreach (var server in invalidServers) { this.Servers.Remove(server); } // validate sync tree properties var invalidSyncTrees = new List <SyncTree>(); foreach (var syncTree in this.SyncTrees) { if (string.IsNullOrEmpty(syncTree.BaseDn)) { AdLog.LogWarning(string.Format("Sync tree {0} has no AD path (base DN) configured.", string.IsNullOrEmpty(syncTree.PortalPath) ? syncTree.BaseDn : syncTree.PortalPath)); invalidSyncTrees.Add(syncTree); } if (string.IsNullOrEmpty(syncTree.PortalPath)) { AdLog.LogWarning(string.Format("Sync tree {0} has no portal path configured.", syncTree.BaseDn)); invalidSyncTrees.Add(syncTree); } if (syncTree.Server == null) { AdLog.LogWarning(string.Format("Sync tree {0} has no valid server configured.", string.IsNullOrEmpty(syncTree.BaseDn) ? syncTree.PortalPath : syncTree.BaseDn)); invalidSyncTrees.Add(syncTree); } } // remove sync trees that are not possible to sync so that we do not have to deal with errors later foreach (var syncTree in invalidSyncTrees) { this.SyncTrees.Remove(syncTree); } if (this.Servers.Count == 0 || this.SyncTrees.Count == 0) { return(false); } return(true); }
/* ==================================================================================== Static Methods */ public static DirectoryEntry ConnectToAD(string ldapPath, Server server) { var deADConn = new DirectoryEntry(ldapPath); var credentials = server.LogonCredentials; if (credentials != null) { if (credentials.Anonymous) { deADConn.AuthenticationType = AuthenticationTypes.Anonymous; } else if (!string.IsNullOrEmpty(credentials.Username)) { deADConn.AuthenticationType |= AuthenticationTypes.ServerBind; deADConn.Username = credentials.Username; deADConn.Password = credentials.Password; } } else { deADConn.AuthenticationType = AuthenticationTypes.Anonymous; } if (server.UseSsl) { deADConn.AuthenticationType |= AuthenticationTypes.SecureSocketsLayer; } //TODO: authentication: use SASL Exception exADConnectException = null; var bError = false; for (var i = 0; i < 3; i++) { try { var oNativeObject = deADConn.NativeObject; bError = false; break; } catch (Exception ex) { bError = true; exADConnectException = ex; System.Threading.Thread.Sleep(3000); } } if (bError) { AdLog.LogException(exADConnectException); throw new Exception("Connecting to AD server failed", exADConnectException); } // NOVELL - use a searcher to retrieve the objects' GUID // - directoryentry properties does not include guid when connecting to Novell eDirectory if (server.Novell) { var dsDirSearcher = new DirectorySearcher(deADConn); dsDirSearcher.PropertiesToLoad.Add(server.GuidProperty); dsDirSearcher.SearchScope = SearchScope.Base; var result = dsDirSearcher.FindOne(); var guid = result.Properties[server.GuidProperty][0]; deADConn.Properties[server.GuidProperty].Add(guid); } return(deADConn); }