예제 #1
0
 public string GenerateRawContent(PingCastleReportCollection <HealthcheckData> report)
 {
     data      = NetworkMapData.BuildFromConsolidation(report);
     sb.Length = 0;
     GenerateContent();
     return(sb.ToString());
 }
예제 #2
0
 public string GenerateRawContent(PingCastleReportCollection <HealthcheckData> report, string selectedTab = null)
 {
     Report    = report;
     sb.Length = 0;
     GenerateContent(selectedTab);
     return(sb.ToString());
 }
예제 #3
0
        // sometimes we have only the netbios name. Try to find if we know the FQDN
        private static void EnrichDomainInfo(PingCastleReportCollection <HealthcheckData> consolidation, HealthCheckTrustDomainInfoData di)
        {
            bool enriched = false;

            // search direct report
            foreach (HealthcheckData data in consolidation)
            {
                if (data.NetBIOSName.Equals(di.NetbiosName, StringComparison.InvariantCultureIgnoreCase))
                {
                    di.DnsName    = data.DomainFQDN;
                    di.ForestName = data.ForestFQDN;
                    di.Forest     = data.Forest;
                    di.Domain     = data.Domain;
                    break;
                }
                foreach (var trust in data.Trusts)
                {
                    // for old report: no netbios name defined in domain object !
                    string[] values  = trust.TrustPartner.Split('.');
                    string   netbios = values[0];
                    if (!String.IsNullOrEmpty(trust.NetBiosName))
                    {
                        netbios = trust.NetBiosName;
                    }
                    if (netbios.Equals(di.NetbiosName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        di.DnsName = trust.TrustPartner;
                        // unknown forest name
                        enriched = true;
                        break;
                    }
                    foreach (var forestinfo in trust.KnownDomains)
                    {
                        if (!String.IsNullOrEmpty(forestinfo.NetbiosName) && forestinfo.NetbiosName.Equals(di.NetbiosName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            di.DnsName    = forestinfo.DnsName;
                            di.ForestName = trust.TrustPartner;
                            di.Forest     = trust.Domain;
                            di.Domain     = forestinfo.Domain;
                            enriched      = true;
                            break;
                        }
                    }
                    if (enriched)
                    {
                        break;
                    }
                }
                if (enriched)
                {
                    break;
                }
            }
        }
        HealthcheckData GetItem(PingCastleReportCollection <HealthcheckData> reports, int rank)
        {
            var e = reports.GetEnumerator();

            e.MoveNext();
            for (int i = 0; i < rank; i++)
            {
                e.MoveNext();
            }
            return(e.Current);
        }
예제 #5
0
        public PingCastleReportCollection <T> ToLatestReportCollection()
        {
            var output = new PingCastleReportCollection <T>();

            foreach (var sid in data.Keys)
            {
                DateTime maxDate = DateTime.MinValue;
                foreach (var date in data[sid].Keys)
                {
                    if (maxDate < date)
                    {
                        maxDate = date;
                    }
                }
                output.Add(data[sid][maxDate]);
            }
            output.EnrichInformation();
            return(output);
        }
예제 #6
0
        public PingCastleReportCollection <T> GetDataReportAtDate(DateTime dateToIssueReport)
        {
            var output = new PingCastleReportCollection <T>();

            foreach (var sid in data.Keys)
            {
                DateTime min = DateTime.MinValue;
                foreach (var date in data[sid].Keys)
                {
                    if (date > min && date <= dateToIssueReport)
                    {
                        min = date;
                    }
                }
                if (min != DateTime.MinValue)
                {
                    output.Add(data[sid][min]);
                }
            }
            output.EnrichInformation();
            return(output);
        }
예제 #7
0
 public string GenerateReportFile(PingCastleReportCollection <HealthcheckData> report, ADHealthCheckingLicense license, string filename)
 {
     Report = report;
     Brand(license);
     return(GenerateReportFile(filename));
 }
예제 #8
0
        public bool CartoTask(bool PerformHealthCheckGenerateDemoReports)
        {
            List <HealthcheckAnalyzer.ReachableDomainInfo> domains = null;

            StartTask("Exploration",
                      () =>
            {
                HealthcheckAnalyzer hcroot = new HealthcheckAnalyzer();
                domains = hcroot.GetAllReachableDomains(Port, Credential);
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("List of domains that will be queried");
                Console.ResetColor();
                foreach (var domain in domains)
                {
                    Console.WriteLine(domain.domain);
                }
            });
            var consolidation = new PingCastleReportCollection <HealthcheckData>();

            StartTask("Examining all domains in parallele (this can take a few minutes)",
                      () =>
            {
                BlockingQueue <string> queue = new BlockingQueue <string>(30);
                int numberOfThread           = 100;
                Thread[] threads             = new Thread[numberOfThread];
                try
                {
                    ThreadStart threadFunction = () =>
                    {
                        for (; ;)
                        {
                            string domain = null;
                            if (!queue.Dequeue(out domain))
                            {
                                break;
                            }
                            try
                            {
                                Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] " + "Starting the analysis of " + domain);
                                HealthcheckAnalyzer hc = new HealthcheckAnalyzer();
                                var data = hc.GenerateCartoReport(domain, Port, Credential, AnalyzeReachableDomains);
                                consolidation.Add(data);
                                Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] " + "Analysis of " + domain + " completed with success");
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] " + "Analysis of " + domain + " failed");
                                Trace.WriteLine("Exception while analysing domain " + domain + " : " + ex.Message);
                                Trace.WriteLine(ex.StackTrace);
                            }
                        }
                    };
                    // Consumers
                    for (int i = 0; i < numberOfThread; i++)
                    {
                        threads[i] = new Thread(threadFunction);
                        threads[i].Start();
                    }
                    foreach (var domain in domains)
                    {
                        queue.Enqueue(domain.domain);
                    }
                    queue.Quit();
                    Trace.WriteLine("examining domains file completed. Waiting for worker thread to complete");
                    for (int i = 0; i < numberOfThread; i++)
                    {
                        threads[i].Join();
                    }
                    Trace.WriteLine("Done examining domains");
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("Exception while analysing domain in carto: " + ex.Message);
                    Trace.WriteLine(ex.StackTrace);
                }
                finally
                {
                    queue.Quit();
                    for (int i = 0; i < numberOfThread; i++)
                    {
                        if (threads[i] != null)
                        {
                            if (threads[i].ThreadState == System.Threading.ThreadState.Running)
                            {
                                threads[i].Abort();
                            }
                        }
                    }
                }
            });
            if (PerformHealthCheckGenerateDemoReports)
            {
                Console.WriteLine("Performing demo report transformation");
                Trace.WriteLine("Performing demo report transformation");
                consolidation = PingCastleReportHelper <HealthcheckData> .TransformReportsToDemo(consolidation);
            }
            if (!StartTask("Healthcheck consolidation",
                           () =>
            {
                consolidation.EnrichInformation();
                ReportHealthCheckMapBuilder nodeAnalyzer = new ReportHealthCheckMapBuilder(consolidation, License);
                nodeAnalyzer.Log = Console.WriteLine;
                nodeAnalyzer.CenterDomainForSimpliedGraph = CenterDomainForSimpliedGraph;
                nodeAnalyzer.GenerateReportFile("ad_carto_full_node_map.html");
                nodeAnalyzer.FullNodeMap = false;
                nodeAnalyzer.CenterDomainForSimpliedGraph = CenterDomainForSimpliedGraph;
                nodeAnalyzer.GenerateReportFile("ad_carto_simple_node_map.html");
            }
                           ))
            {
                return(false);
            }
            return(true);
        }
예제 #9
0
            public static NetworkMapData BuildFromConsolidation(PingCastleReportCollection <HealthcheckData> reports)
            {
                var data = new NetworkMapData()
                {
                    Views = new List <NetworkMapDataView>()
                    {
                        new NetworkMapDataView()
                        {
                            framenetwork = Subnet.Parse("10.0.0.0/8"),
                            order        = 1024,
                        },
                        new NetworkMapDataView()
                        {
                            framenetwork = Subnet.Parse("192.168.0.0/16"),
                            order        = 256,
                        }
                    },
                };

                data.networkrange      = new Dictionary <string, List <NetworkMapDataItem> >();
                data.DomainControllers = new List <NetworkMapDCItem>();
                var latestForestReports = new Dictionary <string, HealthcheckData>();

                foreach (var report in reports)
                {
                    // select latest forest report to have the latest network information
                    var version = new Version(report.EngineVersion.Split(' ')[0]);
                    if (!(version.Major < 2 || (version.Major == 2 && version.Minor < 6)))
                    {
                        if (!latestForestReports.ContainsKey(report.Forest.DomainSID) || latestForestReports[report.Forest.DomainSID].GenerationDate < report.GenerationDate)
                        {
                            latestForestReports[report.Forest.DomainSID] = report;
                        }
                    }
                }

                // store network information
                foreach (var report in latestForestReports.Values)
                {
                    var list = new List <NetworkMapDataItem>();
                    data.networkrange.Add(report.Forest.DomainSID, list);
                    foreach (var site in report.Sites)
                    {
                        foreach (var network in site.Networks)
                        {
                            list.Add(new NetworkMapDataItem()
                            {
                                Network     = Subnet.Parse(network),
                                Source      = report.Forest.DomainName,
                                Description = site.Description,
                                Location    = site.Location,
                                Name        = site.SiteName,
                            });
                        }
                    }
                }
                // tag the network
                foreach (var report in reports)
                {
                    IEnumerable <NetworkMapDataItem> networks = null;
                    if (data.networkrange.ContainsKey(report.Forest.DomainSID))
                    {
                        networks = data.networkrange[report.Forest.DomainSID];
                    }
                    // collect DC info
                    foreach (var dc in report.DomainControllers)
                    {
                        foreach (string ip in dc.IP)
                        {
                            IPAddress i;
                            if (!IPAddress.TryParse(ip, out i))
                            {
                                continue;
                            }
                            if (i.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
                            {
                                continue;
                            }
                            data.DomainControllers.Add(new NetworkMapDCItem()
                            {
                                Name   = dc.DCName,
                                Source = report.DomainFQDN,
                                Ip     = i,
                            });
                            if (networks != null)
                            {
                                foreach (var network in networks)
                                {
                                    if (network.Network.MatchIp(i))
                                    {
                                        if (string.IsNullOrEmpty(network.DomainFQDN))
                                        {
                                            network.DomainFQDN = report.DomainFQDN;
                                        }
                                        else if (network.DomainFQDN == report.DomainFQDN)
                                        {
                                        }
                                        else
                                        {
                                            network.DomainFQDN = "_multiple_";
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return(data);
            }
예제 #10
0
 public ReportHealthCheckMapBuilder(PingCastleReportCollection <HealthcheckData> consolidation) : this(consolidation, null)
 {
 }
예제 #11
0
 public string GenerateReportFile(PingCastleReportCollection <HealthcheckData> report, ADHealthCheckingLicense license, string filename)
 {
     data = NetworkMapData.BuildFromConsolidation(report);
     return(GenerateReportFile(filename));
 }
예제 #12
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);
        }
        public PingCastleReportCollection <HealthcheckData> GenerateForest(int maxDomain = 15)
        {
            int numberDomains = rnd.Next(5, maxDomain > 15 ? 15 : maxDomain);
            var children      = new PingCastleReportCollection <HealthcheckData>();
            // head of forest
            var root = GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel()
            {
                Size = DomainSizeModel.VerySmall
            });

            for (int i = 0; i < numberDomains; i++)
            {
                var child = GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel()
                {
                    Size = DomainSizeModel.Medium, Forest = root
                });
                children.Add(child);
            }
            foreach (var child in children)
            {
                // root trust
                var trust = new HealthCheckTrustData();
                trust.CreationDate    = child.DomainCreation;
                trust.IsActive        = true;
                trust.NetBiosName     = child.NetBIOSName;
                trust.SID             = child.DomainSid;
                trust.TrustDirection  = 3;
                trust.TrustAttributes = 32;
                trust.TrustType       = 2;
                trust.TrustPartner    = child.DomainFQDN;
                trust.SID             = child.DomainSid;
                trust.KnownDomains    = new List <HealthCheckTrustDomainInfoData>();
                root.Trusts.Add(trust);

                // child trust
                trust = new HealthCheckTrustData();
                trust.CreationDate    = child.DomainCreation;
                trust.IsActive        = true;
                trust.NetBiosName     = root.NetBIOSName;
                trust.SID             = child.DomainSid;
                trust.TrustDirection  = 3;
                trust.TrustAttributes = 32;
                trust.TrustType       = 2;
                trust.TrustPartner    = root.DomainFQDN;
                trust.SID             = root.DomainSid;
                trust.KnownDomains    = new List <HealthCheckTrustDomainInfoData>();
                child.Trusts.Add(trust);

                foreach (var child2 in children)
                {
                    if (child2.DomainSid == child.DomainSid)
                    {
                        continue;
                    }
                    var kdomain = new HealthCheckTrustDomainInfoData();
                    kdomain.CreationDate  = child2.DomainCreation;
                    kdomain.DnsName       = child2.DomainFQDN;
                    kdomain.ForestName    = child2.ForestFQDN;
                    kdomain.ForestNetbios = root.NetBIOSName;
                    kdomain.ForestSid     = root.DomainSid;
                    kdomain.NetbiosName   = child2.NetBIOSName;
                    kdomain.Sid           = child2.DomainSid;
                    trust.KnownDomains.Add(kdomain);
                }
            }
            // output all domains
            children.Add(root);
            return(children);
        }
        public PingCastleReportCollection <HealthcheckData> GenerateData(FakeHealthCheckDataGeneratorModel model)
        {
            var output = new PingCastleReportCollection <HealthcheckData>();

            var num = 0;

            while (num < model.NumberOfDomains - 1)
            {
                int value = rnd.Next(100);
                if (value < 20 && model.NumberOfDomains - num > 6)
                {
                    foreach (var d in GenerateForest(model.NumberOfDomains - num))
                    {
                        output.Add(d);
                        num++;
                    }
                }
                if (value < 60)
                {
                    output.Add(GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel()
                    {
                        Size = DomainSizeModel.Small
                    }));
                    num++;
                }
                else if (value < 80)
                {
                    output.Add(GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel()
                    {
                        Size = DomainSizeModel.Medium
                    }));
                    num++;
                }
                else
                {
                    output.Add(GenerateSingleReport(new FakeHealthCheckDataGeneratorDomainModel()
                    {
                        Size = DomainSizeModel.Large
                    }));
                    num++;
                }
            }
            int numberOfTrust = model.NumberOfDomains * model.TrustRatioInPercent / 100;

            for (int i = 0; i < numberOfTrust; i++)
            {
                //take 2 random domains
                int a = rnd.Next(output.Count);
                int b = rnd.Next(output.Count);
                while (a == b)
                {
                    b = rnd.Next(output.Count);
                }
                var source      = GetItem(output, a);
                var destination = GetItem(output, b);

                //bool forestTrust = false;

                bool uniDirectional = false;

                bool sidfiltering = false;

                DateTime trustCreation = DateBetween2Dates(new DateTime(Math.Max(source.DomainCreation.Ticks, destination.DomainCreation.Ticks)), DateTime.Now);

                var trust = new HealthCheckTrustData();
                trust.CreationDate    = trustCreation;
                trust.IsActive        = true;
                trust.NetBiosName     = destination.NetBIOSName;
                trust.SID             = destination.DomainSid;
                trust.TrustDirection  = (uniDirectional ? 1 : 3);
                trust.TrustAttributes = (sidfiltering ? 4 : 0);
                trust.TrustType       = 2;
                trust.TrustPartner    = destination.DomainFQDN;
                trust.SID             = destination.DomainSid;
                trust.KnownDomains    = new List <HealthCheckTrustDomainInfoData>();
                source.Trusts.Add(trust);

                trust = new HealthCheckTrustData();
                trust.CreationDate    = trustCreation;
                trust.IsActive        = true;
                trust.NetBiosName     = source.NetBIOSName;
                trust.SID             = source.DomainSid;
                trust.TrustDirection  = (uniDirectional ? 2 : 3);
                trust.TrustAttributes = (sidfiltering ? 4 : 0);
                trust.TrustType       = 2;
                trust.TrustPartner    = source.DomainFQDN;
                trust.SID             = source.DomainSid;
                trust.KnownDomains    = new List <HealthCheckTrustDomainInfoData>();
                destination.Trusts.Add(trust);
            }
            return(output);
        }
예제 #15
0
 public ReportHealthCheckMapBuilder(PingCastleReportCollection <HealthcheckData> consolidation, ADHealthCheckingLicense license) : this(consolidation, (OwnerInformationReferences)null)
 {
     Brand(license);
 }
예제 #16
0
 public ReportHealthCheckMapBuilder(PingCastleReportCollection <HealthcheckData> consolidation, OwnerInformationReferences ownerInformationReferences)
 {
     this.Report = consolidation;
     EntityData  = ownerInformationReferences;
     FullNodeMap = true;
 }
예제 #17
0
 public string GenerateReportFile(PingCastleReportCollection <CompromiseGraphData> report, ADHealthCheckingLicense license, string filename)
 {
     Report = report;
     return(GenerateReportFile(filename));
 }