Example #1
0
        // make a clone of all GraphNode except that only a few GraphEdge are kept
        // remove all uneeded GraphEdge to have only one GraphEdge between 2 GraphNodes (direct or indirect link)
        private GraphNode GenerateSimplifiedGraph(GraphNodeCollection nodes, GraphNode centralNode)
        {
            List <GraphNode> nodeAlreadyExamined = new List <GraphNode>();

            GraphNode output = GraphNode.CloneWithoutTrusts(centralNode);

            Dictionary <DomainKey, GraphNode> graph = new Dictionary <DomainKey, GraphNode>();

            graph.Add(output.Domain, output);

            List <GraphNode> nodesToExamine = new List <GraphNode>();

            nodesToExamine.Add(centralNode);
            // proceed layer by layer
            for (int currentLevel = 0; ; currentLevel++)
            {
                List <GraphNode> nodesToExamineForNextLevel = new List <GraphNode>();
                // this first iteration is important
                // it avoid a recursing exploration
                foreach (GraphNode nodeToExamine in nodesToExamine)
                {
                    nodeAlreadyExamined.Add(nodeToExamine);
                }
                foreach (GraphNode nodeToExamine in nodesToExamine)
                {
                    foreach (GraphEdge edge in nodeToExamine.Trusts.Values)
                    {
                        if (!nodeAlreadyExamined.Contains(edge.Destination) &&
                            !nodesToExamine.Contains(edge.Destination) &&
                            !nodesToExamineForNextLevel.Contains(edge.Destination))
                        {
                            // make a clone and add one GraphEdge
                            nodesToExamineForNextLevel.Add(edge.Destination);
                            graph.Add(edge.Destination.Domain, GraphNode.CloneWithoutTrusts(edge.Destination));
                            GraphEdge newEdge = new GraphEdge(graph[nodeToExamine.Domain], graph[edge.Destination.Domain], null, false);
                            graph[nodeToExamine.Domain].Trusts.Add(edge.Destination.Domain, newEdge);
                        }
                    }
                }
                if (nodesToExamineForNextLevel.Count == 0)
                {
                    break;
                }
                nodesToExamine = nodesToExamineForNextLevel;
            }
            return(output);
        }
Example #2
0
        static public GraphNodeCollection BuildModel(PingCastleReportCollection <HealthcheckData> consolidation, OwnerInformationReferences EntityData)
        {
            GraphNodeCollection nodes = new GraphNodeCollection();

            // build links based on the most to the less reliable information
            Trace.WriteLine("Building model");
            int nodeNumber = 0;

            Trace.WriteLine("domain reports");
            // enumerate official domains
            foreach (HealthcheckData data in consolidation)
            {
                GraphNode node = nodes.CreateNodeIfNeeded(ref nodeNumber, data.Domain, data.NetBIOSName, data.GenerationDate);
                node.HealthCheckData = data;
                node.SetForest(data.Forest);
            }
            Trace.WriteLine("direct trust");
            // get trust map based on direct trusts data
            foreach (HealthcheckData data in consolidation)
            {
                GraphNode source = nodes.Locate(data);
                foreach (var trust in data.Trusts)
                {
                    GraphNode destination = nodes.CreateNodeIfNeeded(ref nodeNumber, trust.Domain, trust.NetBiosName, data.GenerationDate);
                    source.Link(destination, trust);
                }
            }
            Trace.WriteLine("forest trust");
            foreach (HealthcheckData data in consolidation)
            {
                foreach (var trust in data.Trusts)
                {
                    // do not examine if we have more accurate information (aka the forest report)
                    if (consolidation.GetDomain(trust.Domain) != null)
                    {
                        continue;
                    }
                    if (trust.KnownDomains != null)
                    {
                        GraphNode source = nodes.Locate(trust);
                        foreach (var domainInfo in trust.KnownDomains)
                        {
                            GraphNode destination = nodes.CreateNodeIfNeeded(ref nodeNumber, domainInfo.Domain, domainInfo.NetbiosName, data.GenerationDate);
                            source.LinkInsideAForest(destination, domainInfo.CreationDate);
                            destination.SetForest(domainInfo.Forest);
                        }
                    }
                }
            }
            Trace.WriteLine("Building reachable links");
            // make links based on reachable domains. Information is less reliable.
            foreach (HealthcheckData data in consolidation)
            {
                // ignore report without reachable domains
                if (data.ReachableDomains == null)
                {
                    continue;
                }
                // ignore reachable links if we have the forest domain report
                if (consolidation.GetDomain(data.Forest) != null)
                {
                    continue;
                }
                foreach (HealthCheckTrustDomainInfoData di in data.ReachableDomains)
                {
                    // domain info can contain only netbios name (not FQDN)
                    // enrich it
                    if (di.NetbiosName.Equals(di.DnsName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        EnrichDomainInfo(consolidation, di);
                    }
                    // if no information was given (only Netbios name!) fallback to a forest trust
                    if (String.IsNullOrEmpty(di.ForestName) || di.ForestName == di.DnsName)
                    {
                        GraphNode childDomain  = nodes.CreateNodeIfNeeded(ref nodeNumber, di.Domain, di.NetbiosName, data.GenerationDate);
                        GraphNode myForestRoot = nodes.CreateNodeIfNeeded(ref nodeNumber, data.Forest, null, data.GenerationDate);
                        myForestRoot.LinkTwoForests(childDomain);
                        myForestRoot.SetForest(myForestRoot.Domain);
                    }
                    else
                    {
                        // ignore the domain if the forest trust is known (information should be already there)
                        if (consolidation.GetDomain(di.Forest) != null)
                        {
                            continue;
                        }

                        // add the forest trust if needed
                        GraphNode remoteForestRoot = nodes.CreateNodeIfNeeded(ref nodeNumber, di.Forest, di.ForestNetbios, data.GenerationDate);
                        remoteForestRoot.SetForest(remoteForestRoot.Domain);

                        // add the forest root if needed
                        GraphNode myForestRoot = nodes.CreateNodeIfNeeded(ref nodeNumber, data.Forest, null, data.GenerationDate);
                        myForestRoot.LinkTwoForests(remoteForestRoot);
                        myForestRoot.SetForest(myForestRoot.Domain);
                        // add the trust if the domain is a child of the forest)
                        // (ignore the trust if forest root = trust)

                        GraphNode childDomain = nodes.CreateNodeIfNeeded(ref nodeNumber, di.Domain, di.NetbiosName, data.GenerationDate);
                        remoteForestRoot.LinkInsideAForest(childDomain);
                        childDomain.SetForest(remoteForestRoot.Domain);
                    }
                }
            }
            Trace.WriteLine("enrich forest information");
            nodes.EnrichForestInformation();
            Trace.WriteLine("done");
            nodes.EnrichEntity(EntityData);
            nodes.RemoveDeletedNodes();
            return(nodes);
        }