in TestSuites/ADFamily/src/TestSuite/MS-ADTS-Schema/ConstructedAttributes.cs [3084:4247]
public void ValidateLDSConstructedAttributes()
{
//Directory Entry for holding the objects required.
DirectoryEntry dirEntry = new DirectoryEntry();
//Common Variable used.
int wrongLocation = -1;
string[] serverValue = null;
string[] actualValue = null;
List<string> sampleClasses = new List<string>();
string distinguishedName = String.Empty;
//Checking the some of the constructed attributes for the object Users.
if (!adAdapter.GetLdsObjectByDN("CN=Account-Expires,CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName, out dirEntry))
{
DataSchemaSite.Assert.IsTrue(
false,
"CN=Account-Expires,CN=Schema,CN=Configuration,"
+ adAdapter.LDSRootObjectName
+ " Object is not found in server");
}
CommonAttributesValidation(dirEntry, false);
#region allowedChildClasses
List<string> expectedAllowedChildClasses = new List<string>();
List<string> objectClasses = new List<string>();
List<string> classes = new List<string>();
List<string> actualAllowedClasses = new List<string>();
List<string> possSuperiors = new List<string>();
//Get the configurationNC object from server.
if (!adAdapter.GetLdsObjectByDN("CN=Configuration," + adAdapter.LDSRootObjectName, out dirEntry))
{
DataSchemaSite.Assume.IsTrue(
false,
"CN=Configuration,"
+ adAdapter.LDSRootObjectName
+ " Object is not found in server");
}
//Get its first child.
foreach (DirectoryEntry child in dirEntry.Children)
{
dirEntry = child;
break;
}
//Collect its objectClass values.
foreach (String values in dirEntry.Properties["objectClass"])
{
objectClasses.Add(values);
}
//Collect its allowedChildClasses values.
dirEntry.RefreshCache(new string[] { "allowedChildClasses" });
foreach (String values in dirEntry.Properties["allowedChildClasses"])
{
actualAllowedClasses.Add(values.ToLower());
}
//Construct this attribute value from Test suite.
if (!adAdapter.GetLdsObjectByDN("CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName, out dirEntry))
{
DataSchemaSite.Assume.IsTrue(
false,
"CN=Schema,CN=Configuration,"
+ adAdapter.LDSRootObjectName
+ " Object is not found in server");
}
//Evaluating the conditions given in ADTS regarding allowedChildClasses.
DirectoryEntries allSchemaEntries = dirEntry.Children;
foreach (DirectoryEntry entry in allSchemaEntries)
{
if (entry.Properties["distinguishedName"].Value.ToString().ToLower().Contains("cn=schema"))
{
PropertyValueCollection objectClassValues = entry.Properties["objectClass"];
if (
objectClassValues.Contains("classSchema")
&& entry.Properties["systemOnly"].Value.ToString().ToLower().Contains("false")
&& !entry.Properties["objectClassCategory"].Value.ToString().ToLower().Contains("2")
&& !entry.Properties["objectClassCategory"].Value.ToString().ToLower().Contains("3"))
{
//Get the entry object from model.
ModelObject modelEntry = null;
adamModel.TryGetClass(entry.Properties["ldapdisplayname"].Value.ToString().ToLower(), out modelEntry);
if (modelEntry == null)
continue;
ConstructedAttributeHelper helper = new ConstructedAttributeHelper();
helper.possSuperiorList = new List<string>();
//Get its possSuperiors.
possSuperiors = helper.GetPossSuperiorsList(modelEntry, adamModel);
foreach (string clsval in objectClasses)
{
//If this list contains the class name, add it in the list.
if (possSuperiors.Contains(clsval))
{
expectedAllowedChildClasses.Add(entry.Properties["ldapDisplayName"].Value.ToString().ToLower());
break;
}
}
}
}
continue;
}
actualAllowedClasses.Sort();
expectedAllowedChildClasses.Sort();
//Checking passing condition.
bool isR2795Satisfied = true;
if (actualAllowedClasses.Count != expectedAllowedChildClasses.Count)
{
//If counts are not equal.
isR2795Satisfied = false;
}
else
{
//Check value by value.
serverValue = actualAllowedClasses.ToArray();
actualValue = expectedAllowedChildClasses.ToArray();
for (int i = 0; i < actualAllowedClasses.Count; i++)
{
if (!serverValue[i].Equals(actualValue[i]))
{
//If any one is not exist, make the condition false.
isR2795Satisfied = false;
wrongLocation = i;
break;
}
}
}
//Validating MS-AD_Schema_R279.
DataSchemaSite.CaptureRequirementIfIsTrue(
isR2795Satisfied,
279,
@"The value of TO!allowedChildClasses, where
TO be the object from which the allowedChildClasses attribute is being read, is the set of
lDAPDisplayNames read from each Object O where(O.distinguishedName is in the schema NC)and
(O!objectClass is classSchema)and (not O!systemOnly)and (not O!objectClassCategory is 2)and
(not O!objectClassCategory is 3)and (there exists C in TO!objectClass such that C is in
POSSSUPERIORS(O)).");
#endregion
#region allowedAttributes
List<string> serverAllowedAttributes = new List<string>();
List<string> modelAllowedAttributes = new List<string>();
sampleClasses = new List<string>();
DirectoryEntry reqEnt = null;
//Add sample classes here.
sampleClasses.Add("CN=Account-Expires,CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName);
//For each sample class,
foreach (string sampleClass in sampleClasses)
{
serverAllowedAttributes = new List<string>();
modelAllowedAttributes = new List<string>();
//Reading the allowedAttributes for given object from server.
if (!adAdapter.GetLdsObjectByDN(sampleClass, out reqEnt))
{
DataSchemaSite.Assume.IsTrue(false, sampleClass + " Object is not found in server");
}
reqEnt.RefreshCache(new string[] { "allowedAttributes" });
foreach (string item in reqEnt.Properties["allowedAttributes"])
{
serverAllowedAttributes.Add(item);
}
serverAllowedAttributes.Sort();
//Reading the allowedAttributes for given object from Model.
modelAllowedAttributes = ConstructedAttributes.GetAllowedAttributes((string)reqEnt.Properties["ldapdisplayname"].Value, adamModel);
modelAllowedAttributes.Sort();
//Checking condition.
bool isR290Satisfied = true;
wrongLocation = -1;
if (serverAllowedAttributes.Count != modelAllowedAttributes.Count)
{
isR290Satisfied = false;
}
else
{
serverValue = serverAllowedAttributes.ToArray();
actualValue = modelAllowedAttributes.ToArray();
for (int i = 0; i < serverAllowedAttributes.Count; i++)
{
if (!serverValue[i].Equals(actualValue[i]))
{
isR290Satisfied = false;
wrongLocation = i;
break;
}
}
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isR290Satisfied,
290,
@"The value of TO!allowedAttributes, where TO be the object from which the allowedAttributes
attribute is being read, is the set of lDAPDisplayNames read from each Object O where:
(O.dn is in the schema NC) and (O!objectClass is attributeSchema) and
(there exists C in TO!objectClass such that O is in CLASSATTS(C)).");
}
#endregion
#region possibleInferiors
List<string> serverPossInferiors = new List<string>();
List<string> modelPossInferiors = new List<string>();
sampleClasses = new List<string>();
reqEnt = null;
//Adding Sample classes for this testing purpose.
sampleClasses.Add("CN=DMD,CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName);
sampleClasses.Add("CN=Configuration,CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName);
//For each sample class,
foreach (string sampleClass in sampleClasses)
{
serverPossInferiors = new List<string>();
modelPossInferiors = new List<string>();
//Getting possibleInferiors of this sample class from server.
if (!adAdapter.GetLdsObjectByDN(sampleClass, out reqEnt))
{
DataSchemaSite.Assume.IsTrue(false, sampleClass + " Object is not found in server");
}
reqEnt.RefreshCache(new string[] { "possibleInferiors" });
foreach (string item in reqEnt.Properties["possibleInferiors"])
{
serverPossInferiors.Add(item);
}
serverPossInferiors.Sort();
//Getting possibleInferiors of this sample class from Model.
modelPossInferiors = ConstructedAttributes.GetPossibleInferiors((string)reqEnt.Properties["ldapdisplayname"].Value, adamModel);
modelPossInferiors.Sort();
string reqEntPath = (string)reqEnt.Properties["distinguishedname"].Value;
//Checking condition.
bool isR332Satisfied = true;
if (serverPossInferiors.Count != modelPossInferiors.Count)
{
isR332Satisfied = false;
}
else
{
string[] serverValues = serverPossInferiors.ToArray();
string[] modelValues = modelPossInferiors.ToArray();
int loopVar = 0;
for (loopVar = 0; loopVar < serverValues.Length; loopVar++)
{
if (!serverValues[loopVar].ToLower().Equals(modelValues[loopVar].ToLower()))
{
isR332Satisfied = false;
break;
}
}
}
//MS-AD_Schema_R332.
DataSchemaSite.CaptureRequirementIfIsTrue(
isR332Satisfied,
332,
@"The value of TO!possibleInferiors,
where TO be the object from which the possibleInferiors attribute is being read. and
C be the classSchema object corresponding to TO!governsID.The value of
TO!possibleInferiors is the set of O!governsID for each Object O where(O is in the
schema NC)and (O!objectClass is classSchema)and (not O!systemOnly)and (not
O!objectClassCategory is 2)and (not O!objectClassCategory is 3)and ((C is contained in
POSSSUPERIORS(O)).");
}
#endregion
#region msDS-Auxiliary-Classes
List<string> serverMsdsAuxClass = new List<string>();
List<string> modelMsdsAuxClass = new List<string>();
sampleClasses = new List<string>();
reqEnt = null;
//Add sample classes here.
sampleClasses.Add("CN=User,CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName);
foreach (string sampleClass in sampleClasses)
{
serverMsdsAuxClass = new List<string>();
modelMsdsAuxClass = new List<string>();
//Getting msDS-Auxiliary-Classes of this sample class from server.
if (!adAdapter.GetLdsObjectByDN(sampleClass, out reqEnt))
{
DataSchemaSite.Assume.IsTrue(false, sampleClass + " Object is not found in server");
}
reqEnt.RefreshCache(new string[] { "msds-auxiliary-classes" });
foreach (string item in reqEnt.Properties["msDS-Auxiliary-Classes"])
{
serverMsdsAuxClass.Add(item);
}
serverMsdsAuxClass.Sort();
//Getting msDS-Auxiliary-Classes of this sample class from Model.
modelMsdsAuxClass = ConstructedAttributes.GetMsdsAuxiliaryClasses((string)reqEnt.Properties["ldapdisplayname"].Value, adamModel);
modelMsdsAuxClass.Sort();
//Checking condition.
bool isR324Satisfied = true;
if (serverMsdsAuxClass.Count == modelMsdsAuxClass.Count)
{
foreach (string element in serverMsdsAuxClass)
{
if (!modelMsdsAuxClass.Contains(element))
{
isR324Satisfied = false;
break;
}
}
}
else
{
isR324Satisfied = false;
}
//MS-AD_Schema_R324.
DataSchemaSite.CaptureRequirementIfIsTrue(
isR324Satisfied,
324,
@"The value of TO!msDS-Auxiliary-Classes,
where TO be the object from which the msDS-Auxiliary-Classes attribute is being read, is
the set of lDAPDisplayNames from each Object O such that (O is in TO!objectClass) and
(O is not in SUPCLASSES(Most Specific class of TO)).");
}
#endregion
#region primaryGroupToken
int serverPrimariyGroupToken = 0;
int modelPrimaryGroupToken = 0;
sampleClasses = new List<string>();
reqEnt = null;
//Add sample classes here.
sampleClasses.Add("CN=Users,CN=Roles,CN=Configuration," + adAdapter.LDSRootObjectName);
sampleClasses.Add("CN=Roles,CN=Configuration," + adAdapter.LDSRootObjectName);
foreach (string sampleClass in sampleClasses)
{
serverPrimariyGroupToken = 0;
modelPrimaryGroupToken = 0;
//Getting msDS-Auxiliary-Classes of this sample class from server.
if (!adAdapter.GetLdsObjectByDN(sampleClass, out reqEnt))
{
DataSchemaSite.Assume.IsTrue(false, sampleClass + " Object is not found in server");
}
PropertyValueCollection objectClasValues = reqEnt.Properties["objectClass"];
//If it is group object,
if (objectClasValues.Contains("group"))
{
//Get the Primary group token.
reqEnt.RefreshCache(new string[] { "primarygrouptoken", "objectsid" });
serverPrimariyGroupToken = (int)reqEnt.Properties["primarygrouptoken"].Value;
//Construct the Primary group token.
byte[] byteArray = (byte[])reqEnt.Properties["objectSid"].Value;
System.Security.Principal.SecurityIdentifier identifier = new System.Security.Principal.SecurityIdentifier(byteArray, 0);
string primaryGroupTokenString = identifier.Value.ToString();
primaryGroupTokenString = primaryGroupTokenString.Substring(primaryGroupTokenString.LastIndexOf('-') + 1);
modelPrimaryGroupToken = int.Parse(primaryGroupTokenString);
//MS-AD_Schema_R301.
DataSchemaSite.CaptureRequirementIfAreEqual<int>(
serverPrimariyGroupToken,
modelPrimaryGroupToken,
301,
@"The value of TO!primaryGroupToken, where TO be the object
from which the primaryGroupToken attribute is being read, is the RID from
TO!objectSid when there exists C in TO!objectClass such that C is the group class.");
}
//If it is not group object,
else
{
reqEnt.RefreshCache(new string[] { "primarygrouptoken", "objectsid" });
//Get the Primary group token.
if (reqEnt.Properties["primarygrouptoken"].Value != null)
{
serverPrimariyGroupToken = (int)reqEnt.Properties["primarygrouptoken"].Value;
}
else
{
serverPrimariyGroupToken = -1;
}
//Construct the Primary group token.
if (reqEnt.Properties["objectSid"].Value != null)
{
byte[] byteArray = (byte[])reqEnt.Properties["objectSid"].Value;
System.Security.Principal.SecurityIdentifier identifier = new System.Security.Principal.SecurityIdentifier(byteArray, 0);
string primaryGroupTokenString = identifier.Value.ToString();
primaryGroupTokenString = primaryGroupTokenString.Substring(primaryGroupTokenString.LastIndexOf('-') + 1);
modelPrimaryGroupToken = int.Parse(primaryGroupTokenString);
}
else
{
modelPrimaryGroupToken = -1;
}
//MS-AD_Schema_R302.
DataSchemaSite.CaptureRequirementIfAreEqual<int>(
serverPrimariyGroupToken,
modelPrimaryGroupToken,
302,
@"If TO is not a group, no value is returned for
TO!primaryGroupToken, where TO be the object from which the primaryGroupToken attribute
is being read, when this attribute is read from TO.");
}
}
#endregion
#region entryTTL
//Create dynamic object on server.
distinguishedName = "CN=TestDynamicContainer,CN=Roles," +
adAdapter.LDSApplicationNC;
DateTime now = DateTime.UtcNow;
string timeFormat = now.Year.ToString();
if (now.Month.ToString().Length < 2)
{
timeFormat += "0" + now.Month.ToString();
}
else
{
timeFormat += now.Month.ToString();
}
if (now.Day.ToString().Length < 2)
{
timeFormat += "0" + now.Day.ToString();
}
else
{
timeFormat += now.Day.ToString();
}
if (now.Hour.ToString().Length < 2)
{
timeFormat += "0" + now.Hour.ToString();
}
else
{
timeFormat += now.Hour.ToString();
}
//minimum entryTTL is 900 seconds by default
now = now.AddMinutes(16);
if (now.Minute.ToString().Length < 2)
{
timeFormat += "0" + now.Minute.ToString();
}
else
{
timeFormat += now.Minute.ToString();
}
if (now.Second.ToString().Length < 2)
{
timeFormat += "0" + now.Second.ToString();
}
else
{
timeFormat += now.Second.ToString();
}
List<DirectoryAttribute> atts = new List<DirectoryAttribute>();
atts.Add(new DirectoryAttribute("objectClass", new String[] { "dynamicobject", "Container" }));
atts.Add(new DirectoryAttribute("msDS-Entry-Time-To-Die", new String[] { timeFormat + ".0Z" }));
string ret = AdLdapClient.Instance().ConnectAndBind(
adAdapter.PDCNetbiosName,
adAdapter.PDCIPAddr,
Convert.ToInt32(adAdapter.ADLDSPortNum),
adAdapter.ClientUserName,
adAdapter.ClientUserPassword,
adAdapter.PrimaryDomainNetBiosName,
AuthType.Basic | AuthType.Ntlm);
if (ret.Equals("Success_STATUS_SUCCESS"))
{
DirectoryEntry dynamicObject = null;
if (adAdapter.GetLdsObjectByDN(distinguishedName, out dynamicObject))
{
AdLdapClient.Instance().DeleteObject(distinguishedName,null);
}
Thread.Sleep(1000);
ret = AdLdapClient.Instance().AddObject(distinguishedName, atts, null);
if (ret.Equals("Success_STATUS_SUCCESS"))
{
if (!adAdapter.GetLdsObjectByDN(distinguishedName, out dynamicObject))
{
DataSchemaSite.Assume.IsTrue(false, distinguishedName + " Object is not found in server");
}
dynamicObject.RefreshCache(new string[] { "entryttl" });
dynamicObject.RefreshCache(new string[] { "msDS-Entry-Time-To-Die" });
DateTime currentTime = DateTime.UtcNow;
DateTime objectTime = (DateTime)dynamicObject.Properties["msDS-Entry-Time-To-Die"].Value;
//Get the values.
uint actualTimeRemaining;
if (DateTime.Compare(currentTime, objectTime) > 0)
{
actualTimeRemaining = 0;
}
else
{
actualTimeRemaining = (uint)objectTime.Subtract(currentTime).TotalSeconds;
if (actualTimeRemaining > 0xFFFFFFFF)
actualTimeRemaining = 0xFFFFFFFF;
}
int expectedTimeRemaining = int.Parse(dynamicObject.Properties["entryttl"].Value.ToString());
//Checking condition.
bool isR304AndR305Satisfied = false;
if (actualTimeRemaining == expectedTimeRemaining
|| actualTimeRemaining >= expectedTimeRemaining - 10)
{
isR304AndR305Satisfied = true;
}
else
{
isR304AndR305Satisfied = false;
}
//MS-AD_Schema_R304.
DataSchemaSite.CaptureRequirementIfIsTrue(
isR304AndR305Satisfied,
304,
@"The value of TO!entryTTL, where TO be the
object from which the entryTTL attribute is being read, is the number of seconds in
TO!msDS-Entry-Time-To-Die minus the current system time, and is constrained to the range
0..0xFFFFFFFF by returning 0 if the difference is less than 0.");
//MS-AD_Schema_R305.
DataSchemaSite.CaptureRequirementIfIsTrue(
isR304AndR305Satisfied,
305,
@"The value of TO!entryTTL, where TO be the
object from which the entryTTL attribute is being read, is the number of seconds in
TO!msDS-Entry-Time-To-Die minus the current system time, and is constrained to the range
0..0xFFFFFFFF by returning 0xFFFFFFFF if the difference is greater than 0xFFFFFFFF.");
AdLdapClient.Instance().DeleteObject(distinguishedName, null);
}
else
{
DataSchemaSite.Assume.Fail("The specified dynamic object may already exist.");
}
}
#endregion
#region parentGUID For AD/LDS
//Implementation should be presented in LDS constructed attributes.
DirectoryEntry rootEntry = null;
bool isParentGUIDEqualToObjectGUID = true;
if (!adAdapter.GetLdsObjectByDN("CN=Configuration," + adAdapter.LDSRootObjectName, out rootEntry))
{
DataSchemaSite.Assert.IsTrue(false, adAdapter.rootDomainDN + "Object is not found in server");
}
string hostOrDomainName = adAdapter.adamServerPort;
string targetOu = "CN=Configuration," + adAdapter.LDSRootObjectName;
string ldapSearchFilter = "((objectClass=container))";
string attributeToReturn = "parentguid";
LdapConnection connection = new LdapConnection(hostOrDomainName);
SearchRequest searchRequest = new SearchRequest(
targetOu,
ldapSearchFilter,
System.DirectoryServices.Protocols.SearchScope.OneLevel,
attributeToReturn);
SearchResponse searchResponse = null;
try
{
searchResponse = (SearchResponse)connection.SendRequest(searchRequest);
}
catch (Exception ex)
{
DataSchemaSite.Log.Add(LogEntryKind.Warning, ex.Message);
}
foreach (SearchResultEntry entry in searchResponse.Entries)
{
if (entry.DistinguishedName == "CN=DirectoryUpdates," + targetOu)
{
SearchResultAttributeCollection attributes = entry.Attributes;
foreach (DirectoryAttribute attribute in attributes.Values)
{
// Count the number of values associated with this attribute
for (int i = 0; i < attribute.Count; i++)
{
byte[] x = attribute[i] as byte[];
Guid guid = new Guid(x);
string parentGUID = guid.ToString();
byte[] objectGUID = (byte[])rootEntry.Properties["objectGUID"].Value;
Guid id = new Guid(objectGUID);
string objectGUIDValue = id.ToString();
if (parentGUID != objectGUIDValue)
{
isParentGUIDEqualToObjectGUID = !isParentGUIDEqualToObjectGUID;
}
}
}
}
}
#endregion
#region msDS-UserPasswordExpired
List<string> listOfObjects = new List<string>();
listOfObjects.Add(
"CN=UserObject1,CN=Query-Policies,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,"
+ adAdapter.LDSRootObjectName);
foreach (string entryDN in listOfObjects)
{
bool expected = false;
bool actual = false;
DirectoryEntry dsEntry = null;
DirectoryEntry userEntry = null;
if (!adAdapter.GetLdsObjectByDN(
"CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,"
+ adAdapter.LDSRootObjectName,
out dsEntry))
{
AdLdapClient.Instance().AddObject(entryDN, atts, null);
}
PropertyValueCollection value = dsEntry.Properties["msDS-Other-Settings"];
object[] valueArray = (object[])value.Value;
string element = String.Empty;
foreach (string tempElement in valueArray)
{
if (tempElement.Contains("ADAMDisablePasswordPolicies"))
{
element = tempElement;
break;
}
}
if (!element.Equals("ADAMDisablePasswordPolicies=1"))
{
expected = true;
}
else
{
expected = false;
}
if (!adAdapter.GetLdsObjectByDN(entryDN, out userEntry))
{
DirectoryEntry parentEntry = null;
string tt = entryDN.Substring(entryDN.IndexOf(',') + 1);
adAdapter.GetLdsObjectByDN(entryDN.Substring(entryDN.IndexOf(',') + 1), out parentEntry);
try
{
string tempUserName = entryDN.Substring(entryDN.IndexOf('=') + 1);
tempUserName = tempUserName.Substring(0, tempUserName.IndexOf(','));
DirectoryEntry newUser = parentEntry.Children.Add("CN=" + tempUserName, "user");
// Checking whether the temporary User (from config file) is already exists or not.
if (!adAdapter.GetLdsObjectByDN(entryDN, out userEntry))
{
newUser.CommitChanges();
newUser.Close();
}
}
catch (Exception ex)
{
DataSchemaSite.Log.Add(LogEntryKind.Warning, ex.Message);
}
adAdapter.GetLdsObjectByDN(entryDN, out userEntry);
}
if (expected)
{
DirectoryEntry userAccEntry = null;
adAdapter.GetLdsObjectByDN(entryDN, out userAccEntry);
userEntry.RefreshCache(new string[] { "msDS-User-Account-Control-Computed" });
int uacComputed = int.Parse(userEntry.Properties["msDS-User-Account-Control-Computed"].Value.ToString());
int uacFlag = ParseUserAccountControlValue(
"ADS_UF_DONT_EXPIRE_PASSWD|ADS_UF_SMARTCARD_REQUIRED|"
+ "ADS_UF_WORKSTATION_TRUST_ACCOUNT|ADS_UF_SERVER_TRUST_ACCOUNT|ADS_UF_INTERDOMAIN_TRUST_ACCOUNT");
expected = ((uacComputed & uacFlag) == 0);
}
if (expected)
{
DirectorySearcher ds = new DirectorySearcher(userEntry, "(objectClass=*)",
new string[] { "pwdLastSet" },
System.DirectoryServices.SearchScope.Base);
System.DirectoryServices.SearchResult result = ds.FindOne();
string pwdLastSet = result.Properties["pwdLastSet"][0].ToString();
DirectoryEntry rootDomainEntry = null;
adAdapter.GetObjectByDN(adAdapter.rootDomainDN, out rootDomainEntry);
ds = new DirectorySearcher(rootDomainEntry, "(objectClass=*)",
new string[] { "maxPwdAge" },
System.DirectoryServices.SearchScope.Base);
result = ds.FindOne();
long maxPwdAge = (long)result.Properties["maxPwdAge"][0];
//9223372036854775808
DateTime st = DateTime.Now;
DateTime pLastSet = new DateTime(long.Parse(pwdLastSet));
expected = (
(pwdLastSet.Equals(null))
|| (pwdLastSet.Equals("0"))
|| ((maxPwdAge != -9223372036854775808)
&& -(st.Ticks - long.Parse(pwdLastSet)) > maxPwdAge));
}
userEntry.RefreshCache(new string[] { "msDS-UserPasswordExpired" });
actual = bool.Parse(userEntry.Properties["msDS-UserPasswordExpired"].Value.ToString());
DataSchemaSite.CaptureRequirementIfAreEqual<bool>(
expected,
actual,
346,
@"In construction of msDS-UserPasswordExpired attribute, TO be the object from which the
msDS-UserPasswordExpired attribute is being read and ST be the current time, read from the system
clock. If the machine running AD/LDS is joined to a domain, let D be the root of the domain NC of
the joined domain. Then TO!msDS-UserPasswordExpired is true if three of the following are true:
1. The LDAP configurable setting ADAMDisablePasswordPolicies ≠ 1.
2. None of bits ADS_UF_SMARTCARD_REQUIRED, ADS_UF_DONT_EXPIRE_PASSWD,
ADS_UF_WORKSTATION_TRUST_ACCOUNT, ADS_UF_SERVER_TRUST_ACCOUNT, ADS_UF_INTERDOMAIN_TRUST_ACCOUNT is
set in TO!userAccountControl. 3. TO!pwdLastSet = null, or TO!pwdLastSet = 0,
or (D!maxPwdAge ≠ 0x8000000000000000 and (ST - TO!pwdLastSet) > D!maxPwdAge)).");
}
AdLdapClient.Instance().Unbind();
#endregion
#region ms-DS-UserAccountAutoLocked
foreach (string entryDN in listOfObjects)
{
bool expected = false;
bool actual = false;
DirectoryEntry dsEntry = null;
DirectoryEntry userEntry = null;
adAdapter.GetLdsObjectByDN(
"CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,"
+ adAdapter.LDSRootObjectName,
out dsEntry);
PropertyValueCollection value = dsEntry.Properties["msDS-Other-Settings"];
object[] valueArray = (object[])value.Value;
string element = String.Empty;
foreach (string tempElement in valueArray)
{
if (tempElement.Contains("ADAMDisablePasswordPolicies"))
{
element = tempElement;
break;
}
}
if (!element.Equals("ADAMDisablePasswordPolicies=1"))
{
expected = true;
}
else
{
expected = false;
}
if (!adAdapter.GetLdsObjectByDN(entryDN, out userEntry))
{
DirectoryEntry parentEntry = null;
string tt = entryDN.Substring(entryDN.IndexOf(',') + 1);
adAdapter.GetLdsObjectByDN(entryDN.Substring(entryDN.IndexOf(',') + 1), out parentEntry);
try
{
string tempUserName = entryDN.Substring(entryDN.IndexOf('=') + 1);
tempUserName = tempUserName.Substring(0, tempUserName.IndexOf(','));
DirectoryEntry newUser = parentEntry.Children.Add("CN=" + tempUserName, "user");
// Checking whether the temporary User (from config file) is already exists or not.
if (!adAdapter.GetLdsObjectByDN(entryDN, out userEntry))
{
newUser.CommitChanges();
newUser.Close();
}
}
catch (Exception ex)
{
DataSchemaSite.Log.Add(LogEntryKind.Warning, ex.Message);
}
adAdapter.GetLdsObjectByDN(entryDN, out userEntry);
}
if (expected)
{
DirectoryEntry rootDomainEntry = null;
adAdapter.GetObjectByDN(adAdapter.rootDomainDN, out rootDomainEntry);
DirectorySearcher ds = new DirectorySearcher(rootDomainEntry, "(objectClass=*)",
new string[] { "lockoutDuration" },
System.DirectoryServices.SearchScope.Base);
System.DirectoryServices.SearchResult result = ds.FindOne();
long lockOutDuration = (long)result.Properties["lockoutDuration"][0];
ds = new DirectorySearcher(userEntry, "(objectClass=*)",
new string[] { "lockoutTime" },
System.DirectoryServices.SearchScope.Base);
result = ds.FindOne();
long lockOutTime = 0;
if (result.Properties.Contains("lockoutTime"))
{
lockOutTime = (long)result.Properties["lockoutTime"][0];
}
DateTime st = DateTime.Now;
expected = (lockOutTime != 0)
&& ((lockOutDuration < -9223372036854775808)
|| ((lockOutDuration + st.Ticks) <= lockOutTime));
}
userEntry.RefreshCache(new string[] { "ms-DS-UserAccountAutoLocked" });
actual = bool.Parse(userEntry.Properties["ms-DS-UserAccountAutoLocked"].Value.ToString());
DataSchemaSite.CaptureRequirementIfAreEqual<bool>(
expected,
actual,
343,
@"In construction of ms-DS-UserAccountAutoLocked attribute, TO be the object from which the
ms-DS-UserAccountAutoLocked attribute is being read, and ST be the current time, read from the
system clock. If the machine running AD/LDS is joined to a domain D, TO!ms-DS-UserAccountAutoLocked
is true if the following are true: 1. The LDAP configurable setting ADAMDisablePasswordPolicies ≠ 1.
2. TO!lockoutTime ≠ 0 and either (1) D!lockoutDuration (regarded as an unsigned quantity) <
0x8000000000000000, or (2) ST + D!lockoutDuration (regarded as a signed quantity) ≤ TO!lockoutTime.");
}
#endregion
#region msDS-User-Account-Control-Computed
bool isLDS = adAdapter.RunLDSTestCases;
if (isLDS)
{
listOfObjects = new List<string>();
listOfObjects.Add(
"CN=UserObject1,CN=Query-Policies,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,"
+ adAdapter.LDSRootObjectName);
bool isR317Satisfied = false, isR318De317Satisfied = false, isR319De317Satisfied = false,
isR320De317Satisfied = false, isR321De317Satisfied = false, isR322De317Satisfied = false;
foreach (string entryDN in listOfObjects)
{
DirectoryEntry userEntry = null;
adAdapter.GetLdsObjectByDN(entryDN, out userEntry);
userEntry.RefreshCache(new string[] { "msDS-User-Account-Control-Computed" });
PropertyValueCollection userAccountControl = userEntry.Properties["msDS-User-Account-Control-Computed"];
int uacComputed = int.Parse(userAccountControl.Value.ToString());
DirectorySearcher ds = new DirectorySearcher(userEntry, "(objectClass=*)",
new string[] { "msDS-UserAccountDisabled" ,"ms-DS-UserAccountAutoLocked" ,
"sd syncms-DS-UserPasswordNotRequired","msDS-UserDontExpirePassword","msDS-UserPasswordExpired"},
System.DirectoryServices.SearchScope.Base);
System.DirectoryServices.SearchResult result = ds.FindOne();
if (result.Properties.Contains("msDS-UserAccountDisabled"))
{
bool tempValue = false;
try
{
tempValue = bool.Parse(result.Properties["msDS-UserAccountDisabled"][0].ToString());
}
catch (Exception ex)
{
DataSchemaSite.Log.Add(LogEntryKind.Warning, ex.Message);
}
if (tempValue)
{
isR318De317Satisfied = ((uacComputed & 2) == 2);
}
else
{
isR318De317Satisfied = ((uacComputed & 2) == 0);
}
}
else
{
isR318De317Satisfied = ((uacComputed & 2) == 0);
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isR318De317Satisfied,
318,
@"In AD/LDS, The value of
TO!msDS-User-Account-Control-Computed attribute is the bit pattern where (AD is
Account Disable) AD (ADS_UF_ACCOUNT_DISABLE) is set if TO!msDS-UserAccountDisabled is
true[AD is Account Disable].");
if (result.Properties.Contains("ms-DS-UserAccountAutoLocked"))
{
bool tempValue = bool.Parse(result.Properties["ms-DS-UserAccountAutoLocked"][0].ToString());
if (tempValue)
{
isR319De317Satisfied = ((uacComputed & 16) == 16);
}
else
{
isR319De317Satisfied = ((uacComputed & 16) == 0);
}
}
else
{
isR319De317Satisfied = ((uacComputed & 16) == 0);
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isR319De317Satisfied,
319,
@"In AD/LDS, The value of
TO!msDS-User-Account-Control-Computed attribute is the bit pattern where LO
(ADS_UF_LOCKOUT) is set if TO!ms-DS-UserAccountAutoLocked is true[LO is Lockout].");
if (result.Properties.Contains("ms-DS-UserPasswordNotRequired"))
{
bool tempValue = bool.Parse(result.Properties["ms-DS-UserPasswordNotRequired"][0].ToString());
if (tempValue)
{
isR320De317Satisfied = ((uacComputed & 32) == 32);
}
else
{
isR320De317Satisfied = ((uacComputed & 32) == 0);
}
}
else
{
isR320De317Satisfied = ((uacComputed & 32) == 0);
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isR320De317Satisfied,
320,
@"In AD/LDS, The value of
TO!msDS-User-Account-Control-Computed attribute is the bit pattern where PNR
(ADS_UF_PASSWD_NOTREQD) is set if TO!ms-DS-UserPasswordNotRequired is true[PNR is Password
not required].");
if (result.Properties.Contains("msDS-UserDontExpirePassword"))
{
bool tempValue = bool.Parse(result.Properties["msDS-UserDontExpirePassword"][0].ToString());
if (tempValue)
{
isR321De317Satisfied = ((uacComputed & 65536) == 65536);
}
else
{
isR321De317Satisfied = ((uacComputed & 65536) == 0);
}
}
else
{
isR321De317Satisfied = ((uacComputed & 65536) == 0);
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isR321De317Satisfied,
321,
@"In AD/LDS, The value of TO!msDS-User-Account-Control-Computed attribute is the bit pattern
where DEP (ADS_UF_DONT_EXPIRE_PASSWD) is set if TO!msDS-UserDontExpirePassword is true[DEP is
Don’t expire password].");
if (result.Properties.Contains("msDS-UserPasswordExpired"))
{
bool tempValue = bool.Parse(result.Properties["msDS-UserPasswordExpired"][0].ToString());
if (tempValue)
{
isR322De317Satisfied = ((uacComputed & 8388608) == 8388608);
}
else
{
isR322De317Satisfied = ((uacComputed & 8388608) == 0);
}
}
else
{
isR322De317Satisfied = ((uacComputed & 8388608) == 0);
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isR322De317Satisfied,
322,
@"In AD/LDS, The value of
TO!msDS-User-Account-Control-Computed attribute is the bit pattern where PE
(ADS_UF_PASSWORD_EXPIRED) is set if TO!msDS-UserPasswordExpired is true[PE is Password
Expired].");
}
isR317Satisfied = isR318De317Satisfied && isR319De317Satisfied && isR320De317Satisfied &&
isR321De317Satisfied && isR322De317Satisfied;
DataSchemaSite.CaptureRequirementIfIsTrue(
isR317Satisfied,
317,
@"In AD/LDS, The value of TO!msDS-User-Account-Control-Computed attribute is the bit pattern where
AD (ADS_UF_ACCOUNT_DISABLE) is set if TO!msDS-UserAccountDisabled is true,
O (ADS_UF_LOCKOUT) is set if TO!ms-DS-UserAccountAutoLocked is true,
PNR (ADS_UF_PASSWD_NOTREQD) is set if TO!ms-DS-UserPasswordNotRequired is true,
DEP (ADS_UF_DONT_EXPIRE_PASSWD) is set if TO!msDS-UserDontExpirePassword is true,
PE (ADS_UF_PASSWORD_EXPIRED) is set if TO!msDS-UserPasswordExpired is true.");
}
#endregion
#region allowedChildClassesEffective
if (isLDS)
{
listOfObjects = new List<string>();
listOfObjects.Add(
"CN=Query-Policies,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,"
+ adAdapter.LDSRootObjectName);
IADsSecurityDescriptor sd = null;
IADsAccessControlList dacl = null;
string ownerSid = String.Empty;
bool isSuccess = false;
foreach (string entryDN in listOfObjects)
{
DirectoryEntry userEntry = null;
adAdapter.GetLdsObjectByDN(entryDN, out userEntry);
userEntry.RefreshCache(new string[] { "allowedChildClasses", "allowedChildClassesEffective" });
object[] childClasses = null;
object[] actualChildClassesEffective = null;
object[] expectedChildClassesEffective = null;
childClasses = (object[])userEntry.Properties["allowedChildClasses"].Value;
actualChildClassesEffective = (object[])userEntry.Properties["allowedChildClassesEffective"].Value;
expectedChildClassesEffective = new object[actualChildClassesEffective.Length];
sd = (IADsSecurityDescriptor)userEntry.Properties["ntsecuritydescriptor"].Value;
dacl = (IADsAccessControlList)sd.DiscretionaryAcl;
bool isCreateChild = false;
bool fAllowPrinicipals = true;
bool spcOfO = false;
bool isConfig = false;
bool isSchema = false;
ownerSid = "";
DirectoryEntry ownerEntry = null;
adAdapter.GetObjectByDN("CN=Enterprise Admins,CN=Users," + adAdapter.rootDomainDN, out ownerEntry);
byte[] sidArray = (byte[])ownerEntry.Properties["objectsid"].Value;
ownerSid = new SecurityIdentifier(sidArray, 0).ToString();
ownerSid = ownerSid.Substring(ownerSid.LastIndexOf('-') + 1);
foreach (IADsAccessControlEntry ace in dacl)
{
if (ace.Trustee.Contains(ownerSid))
{
if ((ace.AccessMask & 1) == 1)
{
isCreateChild = true;
break;
}
}
}
int loopVar = 0;
foreach (string childClass in childClasses)
{
spcOfO = SPCForLDS(childClass);
isConfig = entryDN.ToLower().Contains("schema");
isSchema = entryDN.ToLower().Contains("configuration");
if (isCreateChild
&& (fAllowPrinicipals || !isConfig || !spcOfO)
&& (fAllowPrinicipals || !isSchema || !spcOfO))
{
expectedChildClassesEffective[loopVar++] = childClass;
}
}
isSuccess = false;
for (loopVar = 0; loopVar < expectedChildClassesEffective.Length; loopVar++)
{
if (((string)actualChildClassesEffective[loopVar]).Equals(((string)expectedChildClassesEffective[loopVar])))
{
isSuccess = true;
}
else
{
isSuccess = false;
break;
}
}
DataSchemaSite.CaptureRequirementIfIsTrue(
isSuccess,
287,
@"If the DC is running as AD LDS, then let fAllowPrincipals equal false if the value of the ADAMAllowADAMSecurityPrincipalsInConfigPartition
configuration setting (section 3.1.1.3.4.7) is other than 1.
Let TO be the object from which the allowedChildClassesEffective attribute is being read, contains each object class O in TO!allowedChildClasses such that:
-> (
(TO!nTSecurityDescriptor grants RIGHT_DS_CREATE_CHILD via a simple access control entry (ACE) to the client for instantiating an object beneath TO) or
(TO.nTSecurityDescriptor grants RIGHT_DS_CREATE_CHILD via an object-specific ACE to the client for instantiating an object of class O beneath TO)
)
-> and (fAllowPrincipals or (not TO!distinguishedName in config NC) or (not SPC(O)))
-> and (fAllowPrincipals or (not TO!distinguishedName in schema NC) or (not SPC(O))).");
}
}
#endregion
#region msDS-LocalEffectiveRecycleTime
//Verify MS-AD_Schema requirement:MS-AD_Schema_R4282
//The msDS-LocalEffectiveDeletionTime attribute itsself is a new property for the Windows Server 2008R2 DS and LDS
//And before calling the method,it has been determined the platform for AD DS and AD LDS.
DataSchemaSite.CaptureRequirement(
"MS-ADTS-Schema",
4282,
@"The msDS-LocalEffectiveDeletionTime attribute exists on AD DS and AD LDS,
beginning with Windows Server� 2008 R2 operating system.");
#endregion
#region msDS-LocalEffectiveRecycleTime
//Verify MS-AD_Schema requirement:MS-AD_Schema_R4292
//The msDS-LocalEffectiveDeletionTime attribute itsself is a new property for the Windows Server 2008R2 DS and LDS
//And before calling the method,it has been determined the platform for AD DS and AD LDS.
DataSchemaSite.CaptureRequirement(
"MS-ADTS-Schema",
4292,
@"The msDS-LocalEffectiveRecycleTime attribute exists on AD DS and AD LDS,
beginning with Windows Server� 2008 R2 operating system.");
#endregion
}