示例#1
0
        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);
        }
示例#2
0
        // ============================================================================== 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);
        }
示例#3
0
        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);
                }
            }
        }
示例#4
0
        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);
        }
示例#5
0
        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]);
        }
示例#6
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);
        }
示例#7
0
        /* ==================================================================================== 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);
        }