예제 #1
0
        /// <summary>
        /// [SAML2.0std] section 2.7.3.1
        /// </summary>
        public void ValidateAttribute(SamlAttribute samlAttribute)
        {
            if (samlAttribute == null)
            {
                throw new ArgumentNullException("samlAttribute");
            }

            if (!Saml20Utils.ValidateRequiredString(samlAttribute.Name))
            {
                throw new Saml20FormatException("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 Saml20FormatException("null-AttributeValue elements are not supported");
                    }
                }
            }

            if (samlAttribute.AnyAttr != null)
            {
                AnyAttrValidator.ValidateXmlAnyAttributes(samlAttribute.AnyAttr);
            }
        }
예제 #2
0
        /// <summary>
        /// Validate <c>AuthzDecisionStatement</c>.
        /// </summary>
        /// <remarks>
        /// [SAML2.0 standard] section 2.7.4
        /// </remarks>
        /// <param name="statement">The statement.</param>
        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 Saml20FormatException("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 Saml20FormatException("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 Saml20FormatException("At least one Action subelement must be present for an AuthzDecisionStatement element");
            }

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

                if (!Uri.IsWellFormedUriString(action.Namespace, UriKind.Absolute))
                {
                    throw new Saml20FormatException("Namespace attribute of Action element has a value which is not a wellformed absolute uri");
                }
            }
        }
예제 #3
0
        public void ValidateSubjectConfirmation(SubjectConfirmation subjectConfirmation)
        {
            if (subjectConfirmation.Method == SubjectConfirmation.BEARER_METHOD)
            {
                if (subjectConfirmation.SubjectConfirmationData == null)
                {
                    throw new DKSaml20FormatException("The SAML profile requires that the bearer \"SubjectConfirmation\" element contains a \"SubjectConfirmationData\" element.");
                }

                if (!Saml20Utils.ValidateRequiredString(subjectConfirmation.SubjectConfirmationData.Recipient))
                {
                    throw new DKSaml20FormatException("The SAML profile requires that the \"SubjectConfirmationData\" element contains the \"Recipient\" attribute.");
                }

                if (!subjectConfirmation.SubjectConfirmationData.NotOnOrAfter.HasValue)
                {
                    throw new DKSaml20FormatException("The SAML profile requires that the \"SubjectConfirmationData\" element contains the \"NotOnOrAfter\" attribute.");
                }

                if (subjectConfirmation.SubjectConfirmationData.NotBefore.HasValue)
                {
                    throw new DKSaml20FormatException("The SAML profile disallows the use of the \"NotBefore\" attribute of the \"SubjectConfirmationData\" element.");
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Validates the XML any attributes.
        /// </summary>
        /// <param name="anyAttributes">Any attributes.</param>
        public void ValidateXmlAnyAttributes(XmlAttribute[] anyAttributes)
        {
            if (anyAttributes == null)
            {
                throw new ArgumentNullException("anyAttributes");
            }

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

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

                foreach (var samlns in Saml20Constants.SamlNamespaces)
                {
                    if (attr.NamespaceURI == samlns)
                    {
                        throw new Saml20FormatException("Attribute extension xml attributes MUST NOT use a namespace reserved by SAML");
                    }
                }
            }
        }
예제 #5
0
 /// <summary>
 /// Validates the <c>AuthnStatement</c>.
 /// </summary>
 /// <param name="authnStatement">The <c>AuthnStatement</c>.</param>
 /// <exception cref="SAML2.Profiles.DKSAML20.DKSaml20FormatException">The DK-SAML 2.0 profile requires that the <c>\AuthnStatement\</c> element contains the <c>\SessionIndex\</c> attribute.</exception>
 private void ValidateAuthnStatement(AuthnStatement authnStatement)
 {
     if (!Saml20Utils.ValidateRequiredString(authnStatement.SessionIndex))
     {
         throw new DKSaml20FormatException("The DK-SAML 2.0 profile requires that the \"AuthnStatement\" element contains the \"SessionIndex\" attribute.");
     }
 }
        public void ValidateSubjectConfirmation(SubjectConfirmation subjectConfirmation)
        {
            if (subjectConfirmation == null)
            {
                throw new ArgumentNullException("subjectConfirmation");
            }

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

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

            if (subjectConfirmation.Method == Saml20Constants.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 Saml20FormatException(String.Format("Identifier of type {0} is not supported for SubjectConfirmation", subjectConfirmation.Item.GetType()));
                }
            }
            else if (subjectConfirmation.SubjectConfirmationData != null)
            {
                SubjectConfirmationDataValidator.ValidateSubjectConfirmationData(subjectConfirmation.SubjectConfirmationData);
            }
        }
예제 #7
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">The assertion.</param>
        private void ValidateAssertionAttributes(Assertion assertion)
        {
            // There must be a Version
            if (!Saml20Utils.ValidateRequiredString(assertion.Version))
            {
                throw new Saml20FormatException("Assertion element must have the Version attribute set.");
            }

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

            // Assertion must have an ID
            if (!Saml20Utils.ValidateRequiredString(assertion.Id))
            {
                throw new Saml20FormatException("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 (!Saml20Utils.ValidateIdString(assertion.Id))
            {
                throw new Saml20FormatException("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 Saml20FormatException("Assertion element must have the IssueInstant attribute set.");
            }

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

            // The Issuer element must be valid
            _nameIdValidator.ValidateNameId(assertion.Issuer);
        }
예제 #8
0
        /// <summary>
        /// Validates the name ID.
        /// </summary>
        /// <param name="nameId">The name ID.</param>
        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 Saml20FormatException("NameID element has Format attribute which is not a wellformed absolute uri.");
            }

            // The processing rules from [SAML2.0 standard] section 8.3 are implemented here
            if (nameId.Format == Saml20Constants.NameIdentifierFormats.Email)
            {
                if (!Saml20Utils.ValidateRequiredString(nameId.Value))
                {
                    throw new Saml20FormatException("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 Saml20FormatException("Value of NameID is not a valid email address according to the IETF RFC 2822 specification", fe);
                }
                catch (IndexOutOfRangeException ie)
                {
                    throw new Saml20FormatException("Value of NameID is not a valid email address according to the IETF RFC 2822 specification", ie);
                }
            }
            else if (nameId.Format == Saml20Constants.NameIdentifierFormats.X509SubjectName)
            {
                if (!Saml20Utils.ValidateRequiredString(nameId.Value))
                {
                    throw new Saml20FormatException("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 == Saml20Constants.NameIdentifierFormats.Windows)
            {
                // Required format is 'DomainName\UserName' but the domain name and the '\' are optional
                if (!Saml20Utils.ValidateRequiredString(nameId.Value))
                {
                    throw new Saml20FormatException("NameID with Windows Format attribute MUST contain a Value that contains more than whitespace characters");
                }
            }
            else if (nameId.Format == Saml20Constants.NameIdentifierFormats.Kerberos)
            {
                // Required format is 'name[/instance]@REALM'
                if (!Saml20Utils.ValidateRequiredString(nameId.Value))
                {
                    throw new Saml20FormatException("NameID with Kerberos Format attribute MUST contain a Value that contains more than whitespace characters");
                }

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

                if (nameId.Value.IndexOf("@") < 0)
                {
                    throw new Saml20FormatException("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 == Saml20Constants.NameIdentifierFormats.Entity)
            {
                if (!Saml20Utils.ValidateRequiredString(nameId.Value))
                {
                    throw new Saml20FormatException("NameID with Entity Format attribute MUST contain a Value that contains more than whitespace characters");
                }

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

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

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

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

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

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

                if (!Saml20Utils.ValidateIdString(nameId.Value))
                {
                    throw new Saml20FormatException("NameID with Transient Format attribute MUST have a Value with at least 16 characters (the equivalent of 128 bits)");
                }
            }
        }