/// <summary>
        /// [SAML2.0std] section 2.7.4
        /// </summary>
        private void ValidateAuthzDecisionStatement(AuthzDecisionStatement statement)
        {
            // This has type anyURI, and can be empty (special case in the standard), but not null.
            if (statement.Resource == null)
            {
                throw new Saml2FormatException("Resource attribute of AuthzDecisionStatement is REQUIRED");
            }

            // If it is not empty, it MUST BE a valid URI
            if (statement.Resource.Length > 0 && !Uri.IsWellFormedUriString(statement.Resource, UriKind.Absolute))
            {
                throw new Saml2FormatException("Resource attribute of AuthzDecisionStatement has a value which is not a wellformed absolute uri");
            }

            // NOTE: Decision property validation is done implicitly be the deserializer since it is represented by an enumeration
            if (statement.Action == null || statement.Action.Length == 0)
            {
                throw new Saml2FormatException("At least one Action subelement must be present for an AuthzDecisionStatement element");
            }

            foreach (my.Action action in statement.Action)
            {
                // NOTE: [SAML2.0std] claims that the Namespace is [Optional], but according to the schema definition (and Geneva)
                // NOTE: it has use="required"
                if (!Saml2Utils.ValidateRequiredString(action.Namespace))
                {
                    throw new Saml2FormatException("Namespace attribute of Action element must contain at least one non-whitespace character");
                }

                if (!Uri.IsWellFormedUriString(action.Namespace, UriKind.Absolute))
                {
                    throw new Saml2FormatException("Namespace attribute of Action element has a value which is not a wellformed absolute uri");
                }
            }
        }
        /// <summary>
        /// [SAML2.0std] section 2.7.2
        /// </summary>
        /// <param name="statement"></param>
        private void ValidateAuthnStatement(AuthnStatement statement)
        {
            if (statement.AuthnInstant == null)
            {
                throw new Saml2FormatException("AuthnStatement MUST have an AuthnInstant attribute");
            }

            if (!Saml2Utils.ValidateOptionalString(statement.SessionIndex))
            {
                throw new Saml2FormatException("SessionIndex attribute of AuthnStatement must contain at least one non-whitespace character");
            }

            if (statement.SubjectLocality != null)
            {
                if (!Saml2Utils.ValidateOptionalString(statement.SubjectLocality.Address))
                {
                    throw new Saml2FormatException("Address attribute of SubjectLocality must contain at least one non-whitespace character");
                }

                if (!Saml2Utils.ValidateOptionalString(statement.SubjectLocality.DNSName))
                {
                    throw new Saml2FormatException("DNSName attribute of SubjectLocality must contain at least one non-whitespace character");
                }
            }

            ValidateAuthnContext(statement.AuthnContext);
        }
Exemplo n.º 3
0
        public override SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri)
        {
            SymmetricAlgorithm ret = null;

            try
            {
                //first we try to decrypt with the default implementation
                //which looks for ds:KeyName XML tags
                ret = base.GetDecryptionKey(encryptedData, symmetricAlgorithmUri);
            }
            catch (CryptographicException)
            {
                // now let's try it our way:
                ret    = Saml2Utils.GetAlgorithm(encryptedData.EncryptionMethod.KeyAlgorithm);
                ret.IV = GetDecryptionIV(encryptedData, encryptedData.EncryptionMethod.KeyAlgorithm);
                X509Certificate2 decryptionKey =
                    FedletCertificateFactory.GetCertificateByFriendlyName(serviceProvider.EncryptionCertificateAlias);
                if (decryptionKey == null || !decryptionKey.HasPrivateKey)
                {
                    throw new CryptographicException(Resources.DecryptionKeyNotFound);
                }
                EncryptedKey encKey = null;
                foreach (KeyInfoClause clause in encryptedData.KeyInfo)
                {
                    if (clause is KeyInfoEncryptedKey)
                    {
                        encKey = ((KeyInfoEncryptedKey)clause).EncryptedKey;
                        break;
                    }
                }
                ret.Key = DecryptKey(encKey.CipherData.CipherValue, (RSA)decryptionKey.PrivateKey, false);
            }
            return(ret);
        }
        public void ValidateXmlAnyAttributes(XmlAttribute[] anyAttributes)
        {
            if (anyAttributes == null)
            {
                throw new ArgumentNullException("anyAttributes");
            }

            if (anyAttributes.Length == 0)
            {
                return;
            }

            foreach (XmlAttribute attr in anyAttributes)
            {
                if (!Saml2Utils.ValidateRequiredString(attr.Prefix))
                {
                    throw new Saml2FormatException("Attribute extension xml attributes MUST BE namespace qualified");
                }

                foreach (string samlns in Saml2Constants.SAML_NAMESPACES)
                {
                    if (attr.NamespaceURI == samlns)
                    {
                        throw new Saml2FormatException("Attribute extension xml attributes MUST NOT use a namespace reserved by SAML");
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// [SAML2.0std] section 2.7.3.1
        /// </summary>
        public void ValidateAttribute(SamlAttribute samlAttribute)
        {
            if (samlAttribute == null)
            {
                throw new ArgumentNullException("samlAttribute");
            }

            if (!Saml2Utils.ValidateRequiredString(samlAttribute.Name))
            {
                throw new Saml2FormatException("Name attribute of Attribute element MUST contain at least one non-whitespace character");
            }

            if (samlAttribute.AttributeValue != null)
            {
                foreach (object o in samlAttribute.AttributeValue)
                {
                    if (o == null)
                    {
                        throw new Saml2FormatException("null-AttributeValue elements are not supported");
                    }
                }
            }

            if (samlAttribute.AnyAttr != null)
            {
                AnyAttrValidator.ValidateXmlAnyAttributes(samlAttribute.AnyAttr);
            }
        }
        public void ValidateSubjectConfirmation(SubjectConfirmation subjectConfirmation)
        {
            if (subjectConfirmation == null) throw new ArgumentNullException("subjectConfirmation");

            if (!Saml2Utils.ValidateRequiredString(subjectConfirmation.Method))
                throw new Saml2FormatException("Method attribute of SubjectConfirmation MUST contain at least one non-whitespace character");

            if (!Uri.IsWellFormedUriString(subjectConfirmation.Method, UriKind.Absolute))
                throw new Saml2FormatException("SubjectConfirmation element has Method attribute which is not a wellformed absolute uri.");

            if (subjectConfirmation.Method == Saml2Constants.SubjectConfirmationMethods.HolderOfKey)
                _keyInfoValidator.ValidateKeyInfo(subjectConfirmation.SubjectConfirmationData);

            if (subjectConfirmation.Item != null)
            {
                if (subjectConfirmation.Item is NameID)
                    NameIdValidator.ValidateNameID((NameID)subjectConfirmation.Item);
                else if (subjectConfirmation.Item is EncryptedElement)
                    NameIdValidator.ValidateEncryptedID((EncryptedElement)subjectConfirmation.Item);
                else
                    throw new Saml2FormatException(string.Format("Identifier of type {0} is not supported for SubjectConfirmation", subjectConfirmation.Item.GetType()));
            }
            else if (subjectConfirmation.SubjectConfirmationData != null)
                SubjectConfirmationDataValidator.ValidateSubjectConfirmationData(subjectConfirmation.SubjectConfirmationData);
        }
Exemplo n.º 7
0
        /// <summary>
        /// [SAML2.0std] section 2.4.1.2
        /// </summary>
        /// <param name="subjectConfirmationData"></param>
        public void ValidateSubjectConfirmationData(SubjectConfirmationData subjectConfirmationData)
        {
            // If present it must be anyUri
            if (subjectConfirmationData.Recipient != null)
            {
                if (!Uri.IsWellFormedUriString(subjectConfirmationData.Recipient, UriKind.Absolute))
                {
                    throw new Saml2FormatException("Recipient of SubjectConfirmationData must be a wellformed absolute URI.");
                }
            }

            // NotBefore MUST BE striclty less than NotOnOrAfter if they are both set
            if (subjectConfirmationData.NotBefore != null && subjectConfirmationData.NotBefore.HasValue &&
                subjectConfirmationData.NotOnOrAfter != null && subjectConfirmationData.NotOnOrAfter.HasValue)
            {
                if (!(subjectConfirmationData.NotBefore < subjectConfirmationData.NotOnOrAfter))
                {
                    throw new Saml2FormatException(
                              $"NotBefore {Saml2Utils.ToUtcString(subjectConfirmationData.NotBefore.Value)} MUST BE less than NotOnOrAfter {Saml2Utils.ToUtcString(subjectConfirmationData.NotOnOrAfter.Value)} on SubjectConfirmationData");
                }
            }

            // Make sure the extension-attributes are namespace-qualified and do not use reserved namespaces
            if (subjectConfirmationData.AnyAttr != null)
            {
                _anyAttrValidator.ValidateXmlAnyAttributes(subjectConfirmationData.AnyAttr);
            }

            // Standards-defined extension type which has stricter rules than it's base type
            if (subjectConfirmationData is KeyInfoConfirmationData)
            {
                _keyInfoValidator.ValidateKeyInfo(subjectConfirmationData);
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FileFedletRepository"/> class.
        /// </summary>
        /// <param name="homeFolder">The folder containing the configuration files.</param>
        /// <param name="saml2Utils"></param>
        public FileFedletRepository(string homeFolder, Saml2Utils saml2Utils)
        {
            _saml2Utils = saml2Utils;
            if (!Directory.Exists(homeFolder))
            {
                throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityHomeFolderNotFound);
            }

            _homeFolder = new DirectoryInfo(homeFolder);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="FileWatcherFedletRepository"/> class.
 /// </summary>
 /// <param name="homeFolder">The folder containing the configuration files.</param>
 /// <param name="saml2Utils">Utilities</param>
 public FileWatcherFedletRepository(string homeFolder, Saml2Utils saml2Utils)
 {
     _homeFolder                            = homeFolder;
     _innerRepository                       = new FileFedletRepository(homeFolder, saml2Utils);
     _fileSystemWatcher                     = new FileSystemWatcher(homeFolder);
     _timer                                 = new Timer(ReplaceCache);
     _fileSystemWatcher.Changed            += ClearCache;
     _fileSystemWatcher.Created            += ClearCache;
     _fileSystemWatcher.Deleted            += ClearCache;
     _fileSystemWatcher.Renamed            += ClearCache;
     _fileSystemWatcher.EnableRaisingEvents = true;
 }
Exemplo n.º 10
0
        /// <summary>
        /// If both conditions.NotBefore and conditions.NotOnOrAfter are specified, NotBefore
        /// MUST BE less than NotOnOrAfter
        /// </summary>
        /// <exception cref="Saml2FormatException">If <param name="conditions"/>.NotBefore is not less than <paramref name="conditions"/>.NotOnOrAfter</exception>
        private static void ValidateConditionsInterval(Conditions conditions)
        {
            // No settings? No restrictions
            if (conditions.NotBefore == null && conditions.NotOnOrAfter == null)
            {
                return;
            }

            if (conditions.NotBefore != null && conditions.NotOnOrAfter != null && conditions.NotBefore.Value >= conditions.NotOnOrAfter.Value)
            {
                throw new Saml2FormatException(
                          $"NotBefore {Saml2Utils.ToUtcString(conditions.NotBefore.Value)} MUST BE less than NotOnOrAfter {Saml2Utils.ToUtcString(conditions.NotOnOrAfter.Value)} on Conditions");
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Validates that all the required attributes are present on the assertion.
        /// Furthermore it validates validity of the Issuer element.
        /// </summary>
        /// <param name="assertion"></param>
        private void ValidateAssertionAttributes(Assertion assertion)
        {
            //There must be a Version
            if (!Saml2Utils.ValidateRequiredString(assertion.Version))
            {
                throw new Saml2FormatException("Assertion element must have the Version attribute set.");
            }

            //Version must be 2.0
            if (assertion.Version != Saml2Constants.Version)
            {
                throw new Saml2FormatException("Wrong value of version attribute on Assertion element");
            }

            //Assertion must have an ID
            if (!Saml2Utils.ValidateRequiredString(assertion.ID))
            {
                throw new Saml2FormatException("Assertion element must have the ID attribute set.");
            }

            // Make sure that the ID elements is at least 128 bits in length (SAML2.0 std section 1.3.4)
            if (!Saml2Utils.ValidateIDString(assertion.ID))
            {
                throw new Saml2FormatException("Assertion element must have an ID attribute with at least 16 characters (the equivalent of 128 bits)");
            }

            //IssueInstant must be set.
            if (!assertion.IssueInstant.HasValue)
            {
                throw new Saml2FormatException("Assertion element must have the IssueInstant attribute set.");
            }

            //There must be an Issuer
            if (assertion.Issuer == null)
            {
                throw new Saml2FormatException("Assertion element must have an issuer element.");
            }

            //The Issuer element must be valid
            NameIdValidator.ValidateNameID(assertion.Issuer);
        }
        public void ValidateNameID(NameID nameID)
        {
            if (nameID == null)
            {
                throw new ArgumentNullException("nameID");
            }

            if (string.IsNullOrEmpty(nameID.Format))
            {
                return;
            }

            if (!Uri.IsWellFormedUriString(nameID.Format, UriKind.Absolute))
            {
                throw new Saml2FormatException("NameID element has Format attribute which is not a wellformed absolute uri.");
            }

            // The processing rules from [SAML2.0std] section 8.3 are implemented here
            if (nameID.Format == Saml2Constants.NameIdentifierFormats.Email)
            {
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Email Format attribute MUST contain a Value that contains more than whitespace characters");
                }

                try
                {
                    new MailAddress(nameID.Value);
                }
                catch (FormatException fe)
                {
                    throw new Saml2FormatException("Value of NameID is not a valid email address according to the IETF RFC 2822 specification", fe);
                }
                catch (IndexOutOfRangeException ie)
                {
                    throw new Saml2FormatException("Value of NameID is not a valid email address according to the IETF RFC 2822 specification", ie);
                }
            }
            else if (nameID.Format == Saml2Constants.NameIdentifierFormats.X509SubjectName)
            {
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with X509SubjectName Format attribute MUST contain a Value that contains more than whitespace characters");
                }

                // TODO: Consider checking for correct encoding of the Value according to the
                // XML Signature Recommendation (http://www.w3.org/TR/xmldsig-core/) section 4.4.4
            }
            else if (nameID.Format == Saml2Constants.NameIdentifierFormats.Windows)
            {
                // Required format is 'DomainName\UserName' but the domain name and the '\' are optional
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Windows Format attribute MUST contain a Value that contains more than whitespace characters");
                }
            }
            else if (nameID.Format == Saml2Constants.NameIdentifierFormats.Kerberos)
            {
                // Required format is 'name[/instance]@REALM'
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Kerberos Format attribute MUST contain a Value that contains more than whitespace characters");
                }

                if (nameID.Value.Length < 3)
                {
                    throw new Saml2FormatException("NameID with Kerberos Format attribute MUST contain a Value with at least 3 characters");
                }

                if (nameID.Value.IndexOf("@") < 0)
                {
                    throw new Saml2FormatException("NameID with Kerberos Format attribute MUST contain a Value that contains a '@'");
                }

                //TODO: Consider implementing the rules for 'name', 'instance' and 'REALM' found in IETF RFC 1510 (http://www.ietf.org/rfc/rfc1510.txt) here
            }
            else if (nameID.Format == Saml2Constants.NameIdentifierFormats.Entity)
            {
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Entity Format attribute MUST contain a Value that contains more than whitespace characters");
                }

                if (nameID.Value.Length > 1024)
                {
                    throw new Saml2FormatException("NameID with Entity Format attribute MUST have a Value that contains no more than 1024 characters");
                }

                if (nameID.NameQualifier != null)
                {
                    throw new Saml2FormatException("NameID with Entity Format attribute MUST NOT set the NameQualifier attribute");
                }

                if (nameID.SPNameQualifier != null)
                {
                    throw new Saml2FormatException("NameID with Entity Format attribute MUST NOT set the SPNameQualifier attribute");
                }

                if (nameID.SPProvidedID != null)
                {
                    throw new Saml2FormatException("NameID with Entity Format attribute MUST NOT set the SPProvidedID attribute");
                }
            }
            else if (nameID.Format == Saml2Constants.NameIdentifierFormats.Persistent)
            {
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Persistent Format attribute MUST contain a Value that contains more than whitespace characters");
                }

                if (nameID.Value.Length > 256)
                {
                    throw new Saml2FormatException("NameID with Persistent Format attribute MUST have a Value that contains no more than 256 characters");
                }
            }
            else if (nameID.Format == Saml2Constants.NameIdentifierFormats.Transient)
            {
                if (!Saml2Utils.ValidateRequiredString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Transient Format attribute MUST contain a Value that contains more than whitespace characters");
                }

                if (nameID.Value.Length > 256)
                {
                    throw new Saml2FormatException("NameID with Transient Format attribute MUST have a Value that contains no more than 256 characters");
                }

                if (!Saml2Utils.ValidateIDString(nameID.Value))
                {
                    throw new Saml2FormatException("NameID with Transient Format attribute MUST have a Value with at least 16 characters (the equivalent of 128 bits)");
                }
            }
        }