public void TransformClaims( ref SecurityPropertyCollection incomingClaims, ref SecurityPropertyCollection corporateClaims, ref SecurityPropertyCollection outgoingClaims, ClaimTransformStage transformStage, string strIssuer, string strTargetURI) { if (m_rules == null) { // no processing rules have been configured return; } if (incomingClaims != null) { // we are not an Account Partner, but a resource partner return; } if (transformStage != ClaimTransformStage.PostProcessing) { // we are not (yet) in the right phase return; } foreach (MappingConfigurationElement e in m_rules.GlobalMappings) { if (outgoingClaims == null) { outgoingClaims = new SecurityPropertyCollection(); } outgoingClaims.Add(SecurityProperty.CreateCustomClaimProperty(e.Name, e.Value)); } if (corporateClaims == null) { return; } if (m_rules.GroupAuthorization != null) { bool hasMatch = false; foreach (SecurityProperty securityProperty in corporateClaims) { foreach (GroupAuthorizationConfigurationElement e in m_rules.GroupAuthorization) { if (securityProperty.Equals(SecurityProperty.CreateGroupProperty(e.Group))) { hasMatch = true; } } } if (m_rules.GroupAuthorization.Mode == "include") { if (hasMatch == false) { throw new ApplicationException(m_rules.GroupAuthorization.Message); } } else if (m_rules.GroupAuthorization.Mode == "exclude") { if (hasMatch == true) { throw new ApplicationException(m_rules.GroupAuthorization.Message); } } } foreach (SecurityProperty securityProperty in corporateClaims) { foreach (GroupMappingConfigurationElement e in m_rules.GroupMappings) { if (securityProperty.Equals(SecurityProperty.CreateGroupProperty(e.Group))) { if (outgoingClaims == null) { outgoingClaims = new SecurityPropertyCollection(); } outgoingClaims.Add(SecurityProperty.CreateCustomClaimProperty(e.Name, e.Value)); } } foreach (PrefixConfigurationElement e in m_rules.Prefixes) { if (securityProperty.Name.Equals(e.Name)) { string value = e.Value + securityProperty.Value; outgoingClaims.Add( SecurityProperty.CreateCustomClaimProperty(e.Name, value)); } } } //Build a new claim with configured claimattributes and strings string claimbuilderValue = string.Empty; foreach (ClaimbuilderConfigurationElement e in m_rules.Claimbuilder) { if (!string.IsNullOrEmpty(e.ClaimValue)) { //check if the claim uri exists in the collection. SecurityPropertyCollection tempCollection = corporateClaims.GetCustomProperties(e.ClaimValue); //claim found extract value and add to claimbuilderValue. if (tempCollection.Count == 1) { claimbuilderValue = claimbuilderValue + tempCollection[0].Value; } } else if (!string.IsNullOrEmpty(e.StringValue)) { claimbuilderValue = claimbuilderValue + e.StringValue; } } if (!string.IsNullOrEmpty(claimbuilderValue)) { outgoingClaims.Add( SecurityProperty.CreateCustomClaimProperty(m_rules.Claimbuilder.ClaimName, claimbuilderValue)); } }
public SecurityProperty_VM() { securityProperty = new SecurityProperty(); }
public void TransformClaims( ref SecurityPropertyCollection incomingClaims, ref SecurityPropertyCollection corporateClaims, ref SecurityPropertyCollection outgoingClaims, ClaimTransformStage transformStage, string issuer, string target) { // Create the SamlBridge CTM's trace listener. TextWriterTraceListener twtlSamlBridgeCtmTraceListener = new TextWriterTraceListener(Constants.PATH_SAML_BRIDGE_CTM_TRACE_FILE); if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_CLAIM_TRANSFORMATION_MODULE_ENTERED); } // We only perform any mapping action in the pre-processing stage, so return // immediately if we are not at this stage. if (transformStage != ClaimTransformStage.PreProcessing) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_NOT_PREPROCESSING_STAGE); } return; } // If incomingClaims is null, then there is nothing to map. corporateClaims is // probably populated, in which case ADFS has previously authenticated the user and // is reusing the already-mapped SAML assertion from the user's cookie. if ((incomingClaims != null) && (incomingClaims.Count > 0)) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_INCOMING_CLAIMS_FOUND); } // Validate that the SAML is as expected, i.e. that we have a UPN in the // incoming claims. int iUpnClaimIndex = FindClaim(incomingClaims, WebSsoClaimType.Upn); if (iUpnClaimIndex == -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceError) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCE_NO_INCOMING_UPN_CLAIM_FOUND); } throw new SamlBridgeCctException(Constants.EXC_NO_INCOMING_UPN_CLAIM); } SecurityProperty spUpnClaim = incomingClaims[iUpnClaimIndex]; // Read out the UID from the UPN claim string sUid = spUpnClaim.Value; if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_INCOMING_UPN_CLAIM_VALUE, sUid); } // Remove the UPN claim from the collection - we will replace it with the real // UPN claim later. incomingClaims.RemoveAt(iUpnClaimIndex); #region ADFS AMPERSAND WORKAROUND // At the time of writing there appears to be a problem in ADFS whereby any // ampersand, less than, greater than, quote or apostrophe character contained // in the value of a claim in the authenticated SAML causes the ADFS Web Agent // to throw an exception. // // The following temporary workaround replaces any such characters in custom // claim values with a plain text equivalent, or, in the case of the quote and // apostrophe, nothing. for (int i = 0; i < incomingClaims.Count; i++) { SecurityProperty spThisClaim = incomingClaims[i]; string sThisClaimValue = spThisClaim.Value; if (sThisClaimValue.IndexOf("&") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "&", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("&", "and"); } if (sThisClaimValue.IndexOf("<") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "<", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("<", "lessthan"); } if (sThisClaimValue.IndexOf(">") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, ">", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace(">", "greaterthan"); } if (sThisClaimValue.IndexOf("\"") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "\"", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("\"", ""); } if (sThisClaimValue.IndexOf("'") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "'", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("'", ""); } if (spThisClaim.Value != sThisClaimValue) { SecurityProperty spNewProperty = SecurityProperty.CreateCustomClaimProperty( spThisClaim.Name, sThisClaimValue); incomingClaims[i] = spNewProperty; } } #endregion // Determine how the user's UPN should be obtained. If the SamlBridge registry // value ResourceDomainDirectoryPath exists and has a non-empty value, then the // UPN is obtained by performing a local LDAP search based on the path defined // by the value of ResourceDomainDirectoryPath for a user whose UID corresponds // to the UID extracted from the incoming claim, and taking the UPN of this // user. // // Otherwise, if ResourceDomainDirectoryPath does not exist or has an empty // value, then the value of registry value ResourceDomainUpnSuffix is used to // create the UPN directly from the UID. If ResourceDomainUpnSuffix exists and // has a non-empty value, the UPN is generated by appending an ampersand // followed by the value of ResourceDomainUpnSuffix to the UID. If // ResourceDomainUpnSuffix does not exist or is empty, the unadorned UID is used // as the UPN. string sUpn = string.Empty; if (ResourceDomainDirectoryPath.Length != 0) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_UPN_BY_DIRECTORY_LOOKUP); } sUpn = GetUpnByUid(sUid, incomingClaims); } else { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_UPN_BY_UID_SUFFIXING, ResourceDomainUpnSuffix); } if (ResourceDomainUpnSuffix.Length != 0) { sUpn = string.Format( Universal.SFMT_USER_PRINCIPAL_NAME, sUid, Universal.UPN_SUFFIX_PREFIX, ResourceDomainUpnSuffix); } else { sUpn = sUid; } } if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_OUTGOING_RESOURCE_DOMAIN_UPN, sUpn); } // Insert a new UPN claim into the incoming claims collection, containing the // newly generated UPN. incomingClaims.Add(SecurityProperty.CreateUserPrincipalNameProperty(sUpn)); } else { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceWarning) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCW_NO_INCOMING_CLAIMS_FOUND); } } }