/// <summary> /// load claims from dc /// </summary> /// <param name="principal">Distinguished Name of principal</param> /// <param name="principalClass">class type of principal</param> /// <param name="dc">Domain Controller name or address</param> /// <param name="domain">domain DNS name</param> /// <param name="user">admin user name</param> /// <param name="password">admin user password</param> public static void LoadClaims(string principal, ClaimsPrincipalClass principalClass, string dc, string domain, string user, string password) { ClaimsLoader cLoader = new ClaimsLoader(dc, domain, user, password); List <CLAIMS_ARRAY> adClaims = cLoader.GetClaimsForPrincipalWithoutEncode(principal, ClaimsPrincipalClass.User, ClaimsSource.AD | ClaimsSource.Certificate); sourceClaims = adClaims.ToArray(); }
/// <summary> /// Find same claim record from internal database /// </summary> /// <param name="principalDN">Distinguished Name of principal</param> /// <param name="principalClass">principal type</param> /// <param name="sourceType">claim source type, AD or certificate</param> /// <param name="claimID">ID of claim</param> /// <param name="valueType">claim value type</param> /// <param name="unobjected_values">values parsed into string and split with |ClaimUtilitySpliter|</param> /// <returns>true if found matched</returns> public static bool FoundMatchedClaim(string principalDN, ClaimsPrincipalClass principalClass, CLAIMS_SOURCE_TYPE sourceType, string claimID, CLAIM_TYPE valueType, string unobjected_values) { #region parse values from the string object[] values = ClaimUtility.ConvertStringToEntryUnion(valueType, unobjected_values); #endregion #region find same claim record for (int i = 0; i < sourceClaims.Length; i++) { if (sourceClaims[i].usClaimsSourceType == (short)sourceType) { for (int j = 0; j < sourceClaims[i].ClaimEntries.Length; j++) { CLAIM_ENTRY entry = sourceClaims[i].ClaimEntries[j]; if (entry.Id == claimID && entry.Type == valueType) { //found claim with same ID and value type, need to check values switch (valueType) { case CLAIM_TYPE.CLAIM_TYPE_BOOLEAN: { if (entry.Values.Struct4.BooleanValues.Length != values.Length) return false; for (int k = 0; k < entry.Values.Struct4.BooleanValues.Length; k++) { if ((bool)values[k] != entry.Values.Struct4.BooleanValues[k]) return false; } return true; } case CLAIM_TYPE.CLAIM_TYPE_INT64: { if (entry.Values.Struct1.Int64Values.Length != values.Length) return false; for (int k = 0; k < entry.Values.Struct1.Int64Values.Length; k++) { if ((int)values[k] != entry.Values.Struct1.Int64Values[k]) return false; } return true; } case CLAIM_TYPE.CLAIM_TYPE_STRING: { if (entry.Values.Struct3.StringValues.Length != values.Length) return false; for (int k = 0; k < entry.Values.Struct3.StringValues.Length; k++) { if ((string)values[k] != entry.Values.Struct3.StringValues[k]) return false; } return true; } case CLAIM_TYPE.CLAIM_TYPE_UINT64: { if (entry.Values.Struct2.Uint64Values.Length != values.Length) return false; for (int k = 0; k < entry.Values.Struct2.Uint64Values.Length; k++) { if ((uint)values[k] != entry.Values.Struct2.Uint64Values[k]) return false; } return true; } } } } } } #endregion return false; }
/// <summary> /// load claims from dc /// </summary> /// <param name="principal">Distinguished Name of principal</param> /// <param name="principalClass">class type of principal</param> /// <param name="dc">Domain Controller name or address</param> /// <param name="domain">domain DNS name</param> /// <param name="user">admin user name</param> /// <param name="password">admin user password</param> public static void LoadClaims(string principal, ClaimsPrincipalClass principalClass, string dc, string domain, string user, string password) { ClaimsLoader cLoader = new ClaimsLoader(dc, domain, user, password); List<CLAIMS_ARRAY> adClaims = cLoader.GetClaimsForPrincipalWithoutEncode(principal, ClaimsPrincipalClass.User, ClaimsSource.AD | ClaimsSource.Certificate); sourceClaims = adClaims.ToArray(); }
/// <summary> /// Get Claims for provided principal without encode /// </summary> /// <param name="principal">Distinguished Name of the principal</param> /// <param name="principalClass">class of principal, user or device</param> /// <param name="source">claim source type, AD or Certificate</param> /// <returns>a list of CLAIMS_ARRAY for the principal</returns> public List <CLAIMS_ARRAY> GetClaimsForPrincipalWithoutEncode(string principal, ClaimsPrincipalClass principalClass, ClaimsSource source) { List <CLAIMS_ARRAY> ret = new List <CLAIMS_ARRAY>(); #region get principal object using (DirectoryEntry princ = new DirectoryEntry("LDAP://" + principal, domainDNS + "\\" + UserName, Password, AuthenticationTypes.Secure)) { #endregion #region AD source if (source.HasFlag(ClaimsSource.AD)) { CLAIMS_ARRAY ad = getADSoucredClaims(princ, principalClass); ret.Add(ad); //Constructed claims use the CLAIMS_SOURCE_TYPE_AD source type ad = getConstructedClaims(princ, principalClass); ret.Add(ad); } #endregion #region certificate source //not implemented #endregion return(ret); } }
/// <summary> /// get Constructed claims for a principal /// </summary> /// <param name="principal">the target principal</param> /// <param name="principalClass">user or device</param> /// <returns>a CLAIMS_ARRAY contains claims of the principal</returns> CLAIMS_ARRAY getConstructedClaims(DirectoryEntry principal, ClaimsPrincipalClass principalClass) { CLAIMS_ARRAY ret = new CLAIMS_ARRAY(); DirectoryEntry root = new DirectoryEntry(ConstValue.claimTypesPath + domainNC); List <CLAIM_ENTRY> claims = new List <CLAIM_ENTRY>(); DirectoryEntries children = root.Children; foreach (DirectoryEntry de in children) { //source type should be Constructed if ((de.Properties[ConstValue.msDSClaimSourceType] == null) || ((ClaimsSourceType)Enum.Parse(typeof(ClaimsSourceType), de.Properties[ConstValue.msDSClaimSourceType].Value.ToString(), true) != ClaimsSourceType.Constructed) || (de.Properties[ConstValue.msDSClaimTypeAppliesToClass] == null)) { continue; } //should applies to this principal class bool classMatched = false; foreach (object str in de.Properties[ConstValue.msDSClaimTypeAppliesToClass]) { string tmp = str.ToString(); if (tmp.ToLower() == (ConstValue.userRDN + domainNC.ToLower()) && principalClass == ClaimsPrincipalClass.User) { classMatched = true; break; } if ((tmp.ToLower() == (ConstValue.computerRDN + domainNC).ToLower()) && principalClass == ClaimsPrincipalClass.Device) { classMatched = true; break; } } if (!classMatched) { continue; } //validate claim definition if (!validateClaimDefinition(de)) { continue; } if (de.Properties[ConstValue.name] == null || de.Properties[ConstValue.name].Value == null) { continue; } //Currently only the AuthenticationSilo claim is supported if (de.Properties[ConstValue.name].Value.ToString().Equals(ConstValue.authSiloClaimName, StringComparison.OrdinalIgnoreCase)) { CLAIM_ENTRY?claim = getAuthSiloClaim(principal); if (claim.HasValue) { claims.Add(claim.Value); } break; } } ret.ulClaimsCount = (uint)claims.Count; ret.ClaimEntries = claims.ToArray(); ret.usClaimsSourceType = 1; return(ret); }
/// <summary> /// get AD sourced claims for a principal /// </summary> /// <param name="principal">the target principal</param> /// <param name="principalClass">user or device</param> /// <returns>a CLAIMS_ARRAY contains claims of the principal</returns> CLAIMS_ARRAY getADSoucredClaims(DirectoryEntry principal, ClaimsPrincipalClass principalClass) { CLAIMS_ARRAY ret = new CLAIMS_ARRAY(); using (DirectoryEntry root = new DirectoryEntry(ConstValue.claimTypesPath + domainNC)) { List <CLAIM_ENTRY> claims = new List <CLAIM_ENTRY>(); DirectoryEntries children = root.Children; foreach (DirectoryEntry de in children) { //source type should be AD if ((!de.Properties.Contains(ConstValue.msDSClaimSourceType)) || ((ClaimsSourceType)Enum.Parse(typeof(ClaimsSourceType), de.Properties[ConstValue.msDSClaimSourceType].Value.ToString(), true) != ClaimsSourceType.AD) || (!de.Properties.Contains(ConstValue.msDSClaimTypeAppliesToClass))) { continue; } //should applies to this principal class bool classMatched = false; foreach (object str in de.Properties[ConstValue.msDSClaimTypeAppliesToClass]) { string tmp = str.ToString(); if (tmp.ToLower() == (ConstValue.userRDN + domainNC.ToLower()) && principalClass == ClaimsPrincipalClass.User) { classMatched = true; break; } if ((tmp.ToLower() == (ConstValue.computerRDN + domainNC).ToLower()) && principalClass == ClaimsPrincipalClass.Device) { classMatched = true; break; } } if (!classMatched) { continue; } //validate claim definition if (!validateClaimDefinition(de)) { continue; } //create CLAIM_ENTRY record CLAIM_ENTRY claim; claim.Id = de.Properties["cn"].Value.ToString(); claim.Type = getClaimValueType(de.Properties[ConstValue.distinguishedname].Value.ToString(), DomainController); claim.Values = new CLAIM_ENTRY_VALUE_UNION(); using (DirectoryEntry source = new DirectoryEntry("LDAP://" + de.Properties[ConstValue.msDSClaimAttributeSource].Value.ToString())) { PropertyValueCollection values = principal.Properties[source.Properties["ldapdisplayName"].Value.ToString()]; //parse values switch (claim.Type) { case CLAIM_TYPE.CLAIM_TYPE_STRING: claim.Values.Struct3 = new CLAIM_TYPE_VALUE_LPWSTR(); claim.Values.Struct3.ValueCount = (uint)values.Count; claim.Values.Struct3.StringValues = new string[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct3.StringValues[i] = values[i].ToString(); } break; case CLAIM_TYPE.CLAIM_TYPE_INT64: claim.Values.Struct1 = new CLAIM_TYPE_VALUE_INT64(); claim.Values.Struct1.ValueCount = (uint)values.Count; claim.Values.Struct1.Int64Values = new long[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct1.Int64Values[i] = (long)values[i]; } break; case CLAIM_TYPE.CLAIM_TYPE_UINT64: claim.Values.Struct2 = new CLAIM_TYPE_VALUE_UINT64(); claim.Values.Struct2.ValueCount = (uint)values.Count; claim.Values.Struct2.Uint64Values = new ulong[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct2.Uint64Values[i] = (ulong)values[i]; } break; case CLAIM_TYPE.CLAIM_TYPE_BOOLEAN: claim.Values.Struct4 = new CLAIM_TYPE_VALUE_BOOL(); claim.Values.Struct4.ValueCount = (uint)values.Count; claim.Values.Struct4.BooleanValues = new bool[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct4.BooleanValues[i] = (bool)values[i]; } break; } claims.Add(claim); ret.ulClaimsCount = (uint)claims.Count; ret.ClaimEntries = claims.ToArray(); ret.usClaimsSourceType = 1; } } } return(ret); }
/// <summary> /// Find same claim record from internal database /// </summary> /// <param name="principalDN">Distinguished Name of principal</param> /// <param name="principalClass">principal type</param> /// <param name="sourceType">claim source type, AD or certificate</param> /// <param name="claimID">ID of claim</param> /// <param name="valueType">claim value type</param> /// <param name="unobjected_values">values parsed into string and split with |ClaimUtilitySpliter|</param> /// <returns>true if found matched</returns> public static bool FoundMatchedClaim(string principalDN, ClaimsPrincipalClass principalClass, CLAIMS_SOURCE_TYPE sourceType, string claimID, CLAIM_TYPE valueType, string unobjected_values) { #region parse values from the string object[] values = ClaimUtility.ConvertStringToEntryUnion(valueType, unobjected_values); #endregion #region find same claim record for (int i = 0; i < sourceClaims.Length; i++) { if (sourceClaims[i].usClaimsSourceType == (short)sourceType) { for (int j = 0; j < sourceClaims[i].ClaimEntries.Length; j++) { CLAIM_ENTRY entry = sourceClaims[i].ClaimEntries[j]; if (entry.Id == claimID && entry.Type == valueType) { //found claim with same ID and value type, need to check values switch (valueType) { case CLAIM_TYPE.CLAIM_TYPE_BOOLEAN: { if (entry.Values.Struct4.BooleanValues.Length != values.Length) { return(false); } for (int k = 0; k < entry.Values.Struct4.BooleanValues.Length; k++) { if ((bool)values[k] != entry.Values.Struct4.BooleanValues[k]) { return(false); } } return(true); } case CLAIM_TYPE.CLAIM_TYPE_INT64: { if (entry.Values.Struct1.Int64Values.Length != values.Length) { return(false); } for (int k = 0; k < entry.Values.Struct1.Int64Values.Length; k++) { if ((int)values[k] != entry.Values.Struct1.Int64Values[k]) { return(false); } } return(true); } case CLAIM_TYPE.CLAIM_TYPE_STRING: { if (entry.Values.Struct3.StringValues.Length != values.Length) { return(false); } for (int k = 0; k < entry.Values.Struct3.StringValues.Length; k++) { if ((string)values[k] != entry.Values.Struct3.StringValues[k]) { return(false); } } return(true); } case CLAIM_TYPE.CLAIM_TYPE_UINT64: { if (entry.Values.Struct2.Uint64Values.Length != values.Length) { return(false); } for (int k = 0; k < entry.Values.Struct2.Uint64Values.Length; k++) { if ((uint)values[k] != entry.Values.Struct2.Uint64Values[k]) { return(false); } } return(true); } } } } } } #endregion return(false); }
/// <summary> /// get Constructed claims for a principal /// </summary> /// <param name="principal">the target principal</param> /// <param name="principalClass">user or device</param> /// <returns>a CLAIMS_ARRAY contains claims of the principal</returns> CLAIMS_ARRAY getConstructedClaims(DirectoryEntry principal, ClaimsPrincipalClass principalClass) { CLAIMS_ARRAY ret = new CLAIMS_ARRAY(); DirectoryEntry root = new DirectoryEntry(ConstValue.claimTypesPath + domainNC); List<CLAIM_ENTRY> claims = new List<CLAIM_ENTRY>(); DirectoryEntries children = root.Children; foreach (DirectoryEntry de in children) { //source type should be Constructed if ((de.Properties[ConstValue.msDSClaimSourceType] == null) || ((ClaimsSourceType)Enum.Parse(typeof(ClaimsSourceType), de.Properties[ConstValue.msDSClaimSourceType].Value.ToString(), true) != ClaimsSourceType.Constructed) || (de.Properties[ConstValue.msDSClaimTypeAppliesToClass] == null)) continue; //should applies to this principal class bool classMatched = false; foreach (object str in de.Properties[ConstValue.msDSClaimTypeAppliesToClass]) { string tmp = str.ToString(); if (tmp.ToLower() == (ConstValue.userRDN + domainNC.ToLower()) && principalClass == ClaimsPrincipalClass.User) { classMatched = true; break; } if ((tmp.ToLower() == (ConstValue.computerRDN + domainNC).ToLower()) && principalClass == ClaimsPrincipalClass.Device) { classMatched = true; break; } } if (!classMatched) continue; //validate claim definition if (!validateClaimDefinition(de)) continue; if (de.Properties[ConstValue.name] == null || de.Properties[ConstValue.name].Value == null) continue; //Currently only the AuthenticationSilo claim is supported if (de.Properties[ConstValue.name].Value.ToString().Equals(ConstValue.authSiloClaimName, StringComparison.OrdinalIgnoreCase)) { CLAIM_ENTRY? claim = getAuthSiloClaim(principal); if (claim.HasValue) { claims.Add(claim.Value); } break; } } ret.ulClaimsCount = (uint)claims.Count; ret.ClaimEntries = claims.ToArray(); ret.usClaimsSourceType = 1; return ret; }
/// <summary> /// get AD sourced claims for a principal /// </summary> /// <param name="principal">the target principal</param> /// <param name="principalClass">user or device</param> /// <returns>a CLAIMS_ARRAY contains claims of the principal</returns> CLAIMS_ARRAY getADSoucredClaims(DirectoryEntry principal, ClaimsPrincipalClass principalClass) { CLAIMS_ARRAY ret = new CLAIMS_ARRAY(); using (DirectoryEntry root = new DirectoryEntry(ConstValue.claimTypesPath + domainNC)) { List<CLAIM_ENTRY> claims = new List<CLAIM_ENTRY>(); DirectoryEntries children = root.Children; foreach (DirectoryEntry de in children) { //source type should be AD if ((!de.Properties.Contains(ConstValue.msDSClaimSourceType)) || ((ClaimsSourceType)Enum.Parse(typeof(ClaimsSourceType), de.Properties[ConstValue.msDSClaimSourceType].Value.ToString(), true) != ClaimsSourceType.AD) || (!de.Properties.Contains(ConstValue.msDSClaimTypeAppliesToClass))) continue; //should applies to this principal class bool classMatched = false; foreach (object str in de.Properties[ConstValue.msDSClaimTypeAppliesToClass]) { string tmp = str.ToString(); if (tmp.ToLower() == (ConstValue.userRDN + domainNC.ToLower()) && principalClass == ClaimsPrincipalClass.User) { classMatched = true; break; } if ((tmp.ToLower() == (ConstValue.computerRDN + domainNC).ToLower()) && principalClass == ClaimsPrincipalClass.Device) { classMatched = true; break; } } if (!classMatched) continue; //validate claim definition if (!validateClaimDefinition(de)) continue; //create CLAIM_ENTRY record CLAIM_ENTRY claim; claim.Id = de.Properties["cn"].Value.ToString(); claim.Type = getClaimValueType(de.Properties[ConstValue.distinguishedname].Value.ToString(), DomainController); claim.Values = new CLAIM_ENTRY_VALUE_UNION(); using (DirectoryEntry source = new DirectoryEntry("LDAP://" + de.Properties[ConstValue.msDSClaimAttributeSource].Value.ToString())) { PropertyValueCollection values = principal.Properties[source.Properties["ldapdisplayName"].Value.ToString()]; //parse values switch (claim.Type) { case CLAIM_TYPE.CLAIM_TYPE_STRING: claim.Values.Struct3 = new CLAIM_TYPE_VALUE_LPWSTR(); claim.Values.Struct3.ValueCount = (uint)values.Count; claim.Values.Struct3.StringValues = new string[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct3.StringValues[i] = values[i].ToString(); } break; case CLAIM_TYPE.CLAIM_TYPE_INT64: claim.Values.Struct1 = new CLAIM_TYPE_VALUE_INT64(); claim.Values.Struct1.ValueCount = (uint)values.Count; claim.Values.Struct1.Int64Values = new long[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct1.Int64Values[i] = (long)values[i]; } break; case CLAIM_TYPE.CLAIM_TYPE_UINT64: claim.Values.Struct2 = new CLAIM_TYPE_VALUE_UINT64(); claim.Values.Struct2.ValueCount = (uint)values.Count; claim.Values.Struct2.Uint64Values = new ulong[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct2.Uint64Values[i] = (ulong)values[i]; } break; case CLAIM_TYPE.CLAIM_TYPE_BOOLEAN: claim.Values.Struct4 = new CLAIM_TYPE_VALUE_BOOL(); claim.Values.Struct4.ValueCount = (uint)values.Count; claim.Values.Struct4.BooleanValues = new bool[values.Count]; for (int i = 0; i < values.Count; i++) { claim.Values.Struct4.BooleanValues[i] = (bool)values[i]; } break; } claims.Add(claim); ret.ulClaimsCount = (uint)claims.Count; ret.ClaimEntries = claims.ToArray(); ret.usClaimsSourceType = 1; } } } return ret; }
/// <summary> /// Get Claims for provided principal without encode /// </summary> /// <param name="principal">Distinguished Name of the principal</param> /// <param name="principalClass">class of principal, user or device</param> /// <param name="source">claim source type, AD or Certificate</param> /// <returns>a list of CLAIMS_ARRAY for the principal</returns> public List<CLAIMS_ARRAY> GetClaimsForPrincipalWithoutEncode(string principal, ClaimsPrincipalClass principalClass, ClaimsSource source) { List<CLAIMS_ARRAY> ret = new List<CLAIMS_ARRAY>(); #region get principal object using (DirectoryEntry princ = new DirectoryEntry("LDAP://" + principal, domainDNS + "\\" + UserName, Password, AuthenticationTypes.Secure)) { #endregion #region AD source if (source.HasFlag(ClaimsSource.AD)) { CLAIMS_ARRAY ad = getADSoucredClaims(princ, principalClass); ret.Add(ad); //Constructed claims use the CLAIMS_SOURCE_TYPE_AD source type ad = getConstructedClaims(princ, principalClass); ret.Add(ad); } #endregion #region certificate source //not implemented #endregion return ret; } }