Skip to content

Commit fc0148c

Browse files
Merge pull request #13 from microsoft/20210714SQLCheckCollectors
20210714sql check collectors
2 parents 674fcff + 93d3e5b commit fc0148c

File tree

11 files changed

+469
-22
lines changed

11 files changed

+469
-22
lines changed
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
4.02 KB
Binary file not shown.

SQLCheck/SQLCheck/Collectors.cs

Lines changed: 238 additions & 10 deletions
Large diffs are not rendered by default.

SQLCheck/SQLCheck/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("1.0.0.1100")]
36-
[assembly: AssemblyFileVersion("1.0.0.1100")]
35+
[assembly: AssemblyVersion("1.0.1126.0")]
36+
[assembly: AssemblyFileVersion("1.0.1126.0")]

SQLCheck/SQLCheck/Storage.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public static DataSet CreateDataSet(String ComputerName)
3434
dt.AddColumn("TableRow", "Integer");
3535
dt.AddColumn("Severity", "Integer");
3636
dt.AddColumn("Message", "String");
37+
dt.AddColumn("ExceptionTypeName", "String");
3738
dt.AddColumn("ExMessage", "String");
3839
dt.AddColumn("ExSource", "String");
3940
dt.AddColumn("ExStackTrace", "String");
@@ -68,6 +69,45 @@ public static DataSet CreateDataSet(String ComputerName)
6869
dt.AddColumn("TrustType", "String");
6970
dt.AddColumn("TrustDirection", "String");
7071
dt.AddColumn("SelectiveAuthentication", "Boolean");
72+
dt.AddColumn("TrustAttributes", "String");
73+
dt.AddColumn("SupportedEncryptionTypes", "String");
74+
dt.AddColumn("Message", "String");
75+
ds.Tables.Add(dt);
76+
77+
//
78+
// Root Domain Related Domains - entries not having FOREST_TRANSITIVE flag set
79+
//
80+
81+
dt = new DataTable("RootDomainRelatedDomain");
82+
dt.AddColumn("ID", "Integer");
83+
dt.Columns["ID"].AutoIncrement = true;
84+
dt.AddColumn("ParentID", "Integer");
85+
dt.AddColumn("SourceDomain", "String");
86+
dt.AddColumn("TargetDomain", "String");
87+
dt.AddColumn("TrustType", "String");
88+
dt.AddColumn("TrustDirection", "String");
89+
dt.AddColumn("SelectiveAuthentication", "Boolean");
90+
dt.AddColumn("TrustAttributes", "String");
91+
dt.AddColumn("SupportedEncryptionTypes", "String");
92+
dt.AddColumn("Message", "String");
93+
ds.Tables.Add(dt);
94+
95+
//
96+
// Forest Related Domains - entries having FOREST_TRANSITIVE flag set
97+
//
98+
99+
dt = new DataTable("ForestRelatedDomain");
100+
dt.AddColumn("ID", "Integer");
101+
dt.Columns["ID"].AutoIncrement = true;
102+
dt.AddColumn("ParentID", "Integer");
103+
dt.AddColumn("SourceForest", "String");
104+
dt.AddColumn("TargetDomain", "String");
105+
dt.AddColumn("TrustType", "String");
106+
dt.AddColumn("TrustDirection", "String");
107+
dt.AddColumn("SelectiveAuthentication", "Boolean");
108+
dt.AddColumn("TrustAttributes", "String");
109+
dt.AddColumn("SupportedEncryptionTypes", "String");
110+
dt.AddColumn("Message", "String");
71111
ds.Tables.Add(dt);
72112

73113
//
@@ -115,6 +155,7 @@ public static DataSet CreateDataSet(String ComputerName)
115155
dt.Columns["ID"].AutoIncrement = true;
116156
dt.AddColumn("ParentID", "Integer");
117157
dt.AddColumn("CrashOnAuditFail", "String", @"HKLM\SYSTEM\CurrentControlSet\Control\Lsa!CrashOnAuditFail");
158+
dt.AddColumn("LanmanCompatibilityLevel", "String", @"HKLM\SYSTEM\CurrentControlSet\Control\Lsa!LMCompatibilityLevel");
118159
dt.AddColumn("DisableLoopbackCheck", "String", @"HKLM\SYSTEM\CurrentControlSet\Control\Lsa!DisableLoopbackCheck");
119160
dt.AddColumn("BackConnectionHostNames", "String", @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0!BackConnectionHostNames");
120161
dt.AddColumn("MaxTokenSize", "String", @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA\Kerberos\Parameters!MaxTokenSize");
@@ -200,6 +241,30 @@ public static DataSet CreateDataSet(String ComputerName)
200241
dt.AddColumn("NICTeaming", "Boolean");
201242
ds.Tables.Add(dt);
202243

244+
//
245+
// FLTMC filters
246+
//
247+
248+
dt = new DataTable("FLTMC");
249+
dt.AddColumn("ID", "Integer");
250+
dt.Columns["ID"].AutoIncrement = true;
251+
dt.AddColumn("ParentID", "Integer");
252+
dt.AddColumn("Name", "String");
253+
ds.Tables.Add(dt);
254+
255+
//
256+
// Network Mini Driver
257+
//
258+
259+
dt = new DataTable("NetworkMiniDriver");
260+
dt.AddColumn("ID", "Integer");
261+
dt.Columns["ID"].AutoIncrement = true;
262+
dt.AddColumn("ParentID", "Integer");
263+
dt.AddColumn("Service", "String", @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4d36e974-e325-11ce-bfc1-08002be10318}\*\Ndi!Service");
264+
dt.AddColumn("HelpText", "String", @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4d36e974-e325-11ce-bfc1-08002be10318}\*\Ndi!HelpText");
265+
dt.AddColumn("FilterMediaTypes", "String", @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4d36e974-e325-11ce-bfc1-08002be10318}\*\Ndi\Interfaces!FilterMediaTypes");
266+
ds.Tables.Add(dt);
267+
203268
//
204269
// Disk Drive
205270
//
@@ -572,6 +637,7 @@ public static void LogMessage(this DataRow dr, string message, SeverityLevel sev
572637
{
573638
drMessage["Severity"] = SeverityLevel.Exception;
574639
drMessage["ExMessage"] = exRecord.Message;
640+
drMessage["ExceptionTypeName"] = exRecord.GetType().Name;
575641
drMessage["ExSource"] = exRecord.Source;
576642
drMessage["ExStacktrace"] = exRecord.StackTrace;
577643
}

SQLCheck/SQLCheck/TextReport.cs

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,90 @@ static void ReportComputer(DataSet ds, TextWriter s) // outputs computer and do
114114
s.WriteLine($"Forest Domain: {Domain.GetString("ForestName")}");
115115
s.WriteLine($"Forest Mode: {Domain.GetString("ForestMode")}");
116116
s.WriteLine();
117+
118+
// domains trusted by this domain
117119
if (ds.Tables["RelatedDomain"].Rows.Count == 0)
118120
{
119121
s.WriteLine("There do not appear to be any other domains in this organization.");
120122
}
121123
else
122124
{
125+
s.WriteLine($"Domains trusted by {Domain.GetString("DomainName")}.");
126+
s.WriteLine();
123127
DataTable dtRelatedDomain = ds.Tables["RelatedDomain"];
124128
ReportFormatter rf = new ReportFormatter();
125-
rf.SetColumnNames("Source Domain:L", "TargetDomain:L","Trust Type:L", "Direction:L", "Selective Auth:L");
129+
rf.SetColumnNames("Target Domain:L","Trust Type:L", "Direction:L", "Selective Auth:L", "Encryption:L", "Attributes:L", "Message:L");
126130
foreach (DataRow RelatedDomain in dtRelatedDomain.Rows)
127131
{
128-
rf.SetcolumnData(RelatedDomain.GetString("SourceDomain"),
129-
RelatedDomain.GetString("TargetDomain"),
132+
rf.SetcolumnData(RelatedDomain.GetString("TargetDomain"),
130133
RelatedDomain.GetString("TrustType"),
131134
RelatedDomain.GetString("TrustDirection"),
132-
RelatedDomain.GetBoolean("SelectiveAuthentication").ToString());
135+
RelatedDomain.GetBoolean("SelectiveAuthentication").ToString(),
136+
RelatedDomain.GetString("SupportedEncryptionTypes"),
137+
RelatedDomain.GetString("TrustAttributes"),
138+
RelatedDomain.GetString("Message"));
139+
}
140+
s.WriteLine(rf.GetHeaderText());
141+
s.WriteLine(rf.GetSeparatorText());
142+
for (int i = 0; i < rf.GetRowCount(); i++)
143+
{
144+
s.WriteLine(rf.GetDataText(i));
145+
}
146+
}
147+
s.WriteLine();
148+
149+
// domains trusted by the root domain
150+
if (ds.Tables["RootDomainRelatedDomain"].Rows.Count == 0)
151+
{
152+
s.WriteLine($"There do not appear to be any domains trusted by root domain {Domain.GetString("RootDomain")}.");
153+
}
154+
else
155+
{
156+
s.WriteLine($"Domains trusted by root domain {Domain.GetString("RootDomain")}.");
157+
s.WriteLine();
158+
DataTable dtRelatedDomain = ds.Tables["RootDomainRelatedDomain"];
159+
ReportFormatter rf = new ReportFormatter();
160+
rf.SetColumnNames("Target Domain:L", "Trust Type:L", "Direction:L", "Selective Auth:L", "Encryption:L", "Attributes:L", "Message:L");
161+
foreach (DataRow RelatedDomain in dtRelatedDomain.Rows)
162+
{
163+
rf.SetcolumnData(RelatedDomain.GetString("TargetDomain"),
164+
RelatedDomain.GetString("TrustType"),
165+
RelatedDomain.GetString("TrustDirection"),
166+
RelatedDomain.GetBoolean("SelectiveAuthentication").ToString(),
167+
RelatedDomain.GetString("SupportedEncryptionTypes"),
168+
RelatedDomain.GetString("TrustAttributes"),
169+
RelatedDomain.GetString("Message"));
170+
}
171+
s.WriteLine(rf.GetHeaderText());
172+
s.WriteLine(rf.GetSeparatorText());
173+
for (int i = 0; i < rf.GetRowCount(); i++)
174+
{
175+
s.WriteLine(rf.GetDataText(i));
176+
}
177+
}
178+
s.WriteLine();
179+
180+
// domains trusted by the forest
181+
if (ds.Tables["ForestRelatedDomain"].Rows.Count == 0)
182+
{
183+
s.WriteLine($"There do not appear to be any domains trusted by forest {Domain.GetString("ForestName")}.");
184+
}
185+
else
186+
{
187+
s.WriteLine($"Forests trusted by root domain {Domain.GetString("ForestName")}.");
188+
s.WriteLine();
189+
DataTable dtRelatedDomain = ds.Tables["ForestRelatedDomain"];
190+
ReportFormatter rf = new ReportFormatter();
191+
rf.SetColumnNames("Target Forest:L", "Trust Type:L", "Direction:L", "Selective Auth:L", "Encryption:L", "Attributes:L", "Message:L");
192+
foreach (DataRow RelatedDomain in dtRelatedDomain.Rows)
193+
{
194+
rf.SetcolumnData(RelatedDomain.GetString("TargetDomain"),
195+
RelatedDomain.GetString("TrustType"),
196+
RelatedDomain.GetString("TrustDirection"),
197+
RelatedDomain.GetBoolean("SelectiveAuthentication").ToString(),
198+
RelatedDomain.GetString("SupportedEncryptionTypes"),
199+
RelatedDomain.GetString("TrustAttributes"),
200+
RelatedDomain.GetString("Message"));
133201
}
134202
s.WriteLine(rf.GetHeaderText());
135203
s.WriteLine(rf.GetSeparatorText());
@@ -194,6 +262,7 @@ static void ReportNetwork(DataSet ds, TextWriter s) // outputs network settings
194262
DataTable dtNetworkAdapter = ds.Tables["NetworkAdapter"];
195263
DataTable dtHostAlias = ds.Tables["HostAlias"];
196264
DataTable dtIPAddress = ds.Tables["IPAddress"];
265+
DataTable dtFLTMC = ds.Tables["FLTMC"];
197266

198267
s.WriteLine("Network Settings:");
199268
s.WriteLine();
@@ -245,6 +314,45 @@ static void ReportNetwork(DataSet ds, TextWriter s) // outputs network settings
245314
for (int i = 0; i < rf.GetRowCount(); i++) s.WriteLine(rf.GetDataText(i));
246315
s.WriteLine();
247316

317+
// FLTMC Filters
318+
319+
string filterNames = "";
320+
foreach (DataRow FLTMC in dtFLTMC.Rows)
321+
{
322+
filterNames += "|" + FLTMC.GetString("Name");
323+
}
324+
filterNames = filterNames == "" ? "<none>" : filterNames.Substring(1);
325+
s.WriteLine($"FLTMC Filters: {filterNames}");
326+
s.WriteLine();
327+
328+
// network mini drivers
329+
330+
DataTable dtNetworkMiniDriver = ds.Tables["NetworkMiniDriver"];
331+
if (dtNetworkMiniDriver.Rows.Count == 0)
332+
{
333+
s.WriteLine("Network Mini-Drivers: none found");
334+
s.WriteLine();
335+
}
336+
else
337+
{
338+
s.WriteLine("Network Mini-Drivers:");
339+
s.WriteLine();
340+
341+
rf = new ReportFormatter();
342+
rf.SetColumnNames("Service Name:L", "Filter Media Types:L", "Help Text:L");
343+
foreach (DataRow NetworkMiniDriver in dtNetworkMiniDriver.Rows)
344+
{
345+
rf.SetcolumnData(NetworkMiniDriver.GetString("Service"),
346+
NetworkMiniDriver.GetString("FilterMediaTypes"),
347+
NetworkMiniDriver.GetString("HelpText"));
348+
}
349+
s.WriteLine(rf.GetHeaderText());
350+
s.WriteLine(rf.GetSeparatorText());
351+
for (int i = 0; i < rf.GetRowCount(); i++) s.WriteLine(rf.GetDataText(i));
352+
s.WriteLine();
353+
}
354+
355+
248356
// network adapters
249357

250358
s.WriteLine("Network Adapters:");
@@ -272,6 +380,7 @@ static void ReportSecurity(DataSet ds, TextWriter s) // outputs computer and do
272380
s.WriteLine("Security Settings:");
273381
s.WriteLine();
274382
s.WriteLine($"Crash on Audit Fail: {Security.GetString("CrashOnAuditFail")}");
383+
s.WriteLine($"Lanman Compatibility Level: {Security.GetString("lanmanCompatibilityLevel")}");
275384
s.WriteLine($"Disable Loopback Check: {Security.GetString("DisableLoopbackCheck")}");
276385
s.WriteLine($"Back Connection Host Names: {Security.GetString("BackConnectionHostNames")}");
277386
s.WriteLine($"Max Kerberos Token Size: {Security.GetString("MaxTokenSize")}");
@@ -787,7 +896,10 @@ static void ReportMessages(DataSet ds, TextWriter s, string tableName, int table
787896
}
788897
break;
789898
case Storage.SeverityLevel.Exception:
899+
string src = drv["exSource"].ToString();
900+
if (src != "") src = "Source: " + src;
790901
s.WriteLine($"{sev.ToString()}: {drv["Message"].ToString()}");
902+
s.WriteLine($"Exception Type: {drv["ExceptionTypeName"].ToString()} {src}");
791903
s.WriteLine($"{drv["exMessage"].ToString()}");
792904
s.WriteLine($"{drv["exStackTrace"].ToString()}");
793905
messagesOutput = true;

SQLCheck/SQLCheck/Utility.cs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,25 @@ public static string Translate(string index, params string[] Values)
329329
return Translate(i, Values);
330330
}
331331

332+
//
333+
// Converts Lanman compatibility levels to string
334+
//
335+
336+
public static string LanmanNames(string value)
337+
{
338+
switch (value)
339+
{
340+
case "0": return "Send LM & NTLM responses";
341+
case "1": return "Send LM & NTLM – use NTLMv2 session security if negotiated";
342+
case "2": return "Send NTLM response only";
343+
case "3": return "Send NTLMv2 response only";
344+
case "4": return "Send NTLMv2 response only. Refuse LM";
345+
case "5": return "Send NTLMv2 response only. Refuse LM & NTLM";
346+
default: return "";
347+
}
348+
}
349+
350+
332351
//
333352
// Converts a Kerberos encryption bitmask to string
334353
//
@@ -338,12 +357,34 @@ public static string KerbEncryptNames(int bitmask)
338357
string s = "";
339358
if (bitmask == 0) return "RC4_HMAC_MD5";
340359
if ((bitmask & 0x00000001) != 0) s += "DES_CBC_CRC";
341-
if ((bitmask & 0x00000002) != 0) s += "+DES_CBC_MD5";
342-
if ((bitmask & 0x00000004) != 0) s += "+RC4_HMAC_MD5";
343-
if ((bitmask & 0x00000008) != 0) s += "+AES128_HMAC_SHA1";
344-
if ((bitmask & 0x00000010) != 0) s += "+AES256_HMAC_SHA1";
345-
if (bitmask > 0x0000001F) s += "+Future";
346-
return (s.StartsWith("+") ? s.Substring(1) : s);
360+
if ((bitmask & 0x00000002) != 0) s += "|DES_CBC_MD5";
361+
if ((bitmask & 0x00000004) != 0) s += "|RC4_HMAC_MD5";
362+
if ((bitmask & 0x00000008) != 0) s += "|AES128_HMAC_SHA1";
363+
if ((bitmask & 0x00000010) != 0) s += "|AES256_HMAC_SHA1";
364+
if (bitmask > 0x0000001F) s += "|Future";
365+
return (s.StartsWith("|") ? s.Substring(1) : s);
366+
}
367+
368+
//
369+
// Converts a domain trust attribute bitmask to a string
370+
//
371+
372+
public static string DomainTrustAttributeNames(int bitmask)
373+
{
374+
string s = "";
375+
if ((bitmask & 0x00000001) != 0) s += "NON_TRANSITIVE";
376+
if ((bitmask & 0x00000002) != 0) s += "|UPLEVEL_ONLY";
377+
if ((bitmask & 0x00000004) != 0) s += "|QUARANTINED_DOMAIN";
378+
if ((bitmask & 0x00000008) != 0) s += "|FOREST_TRANSITIVE";
379+
if ((bitmask & 0x00000010) != 0) s += "|CROSS_ORGANIZATION";
380+
if ((bitmask & 0x00000020) != 0) s += "|WITHIN_FOREST";
381+
if ((bitmask & 0x00000040) != 0) s += "|TREAT_AS_EXTERNAL";
382+
if ((bitmask & 0x00000080) != 0) s += "|USES_RC4_ENCRYPTION";
383+
if ((bitmask & 0x00000100) != 0) s += "|RESERVED_USES_AES_KEYS"; // RESERVED in MSFT documentation; USES_AES_KEYS in some 3rd-party dcumentation
384+
if ((bitmask & 0x00000200) != 0) s += "|CROSS_ORGANIZATION_NO_TGT_DELEGATION";
385+
if ((bitmask & 0x00000400) != 0) s += "|PIM_TRUST";
386+
if ((bitmask & 0x00000800) != 0) s += "|CROSS_ORGANIZATION_ENABLE_TGT_DELEGATION";
387+
return (s.StartsWith("|") ? s.Substring(1) : s);
347388
}
348389

349390
//
1.5 KB
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)