public void _0001_NameID_Invalid_EmptyEmail()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Email;
     nameID.Value = " ";
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
        public void _0001_NameID_Invalid_Email()
        {
            NameID nameID = new NameID();
            nameID.Format = Saml20Constants.NameIdentifierFormats.Email;
            Saml20NameIDValidator validator = new Saml20NameIDValidator();

            string[] invalidEmails =
                new string[]
                    {
                        "thisisnotavalid.email@ ", 
                        "thisisnotavalidemail", 
                        "thisisnotavalidemail.com", 
                        "@thisisnotavalidemail.com", 
                        " @thisisnotavalidemail.com", 
                        "@ @thisisnotavalidemail.com", 
                        " @ @thisisnotavalidemail.com", 
                        " . @thisisnotavalidemail.com", 
                        @"\. @thisisnotavalidemail.com", 
                        @"\.\@thisisnotavalidemail.com", 
                        @"a.\@thisisnotavalidemail.com", 
                        @"*****@*****.**", 
                        @"<.>@thisisnotavalidemail.com", 
                        @"<*****@*****.**", 
                        "thisisnotavalid.email@", 
                        "thisisnotavalid.email@ @", 
                        "thisisnotavalid.email@ @ ", 
                    };

            foreach (string email in invalidEmails)
            {
                nameID.Value = email;

                try
                {
                    validator.ValidateNameID(nameID);
                    Assert.Fail("Email address " + email + " is not supposed to be valid");
                }
                catch (Saml20FormatException sfe)
                {
                    Assert.AreEqual(sfe.Message, "Value of NameID is not a valid email address according to the IETF RFC 2822 specification");
                }
            }
        }
        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.0std] 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)");
                
            }
        }
        private Assertion CreateAssertion(User user, string receiver)
        {
            Assertion assertion = new Assertion();

            { // Subject element
                assertion.Subject = new Subject();
                assertion.ID = "id" + Guid.NewGuid().ToString("N");
                assertion.IssueInstant = DateTime.Now.AddMinutes(10);

                assertion.Issuer = new NameID();
                assertion.Issuer.Value = IDPConfig.ServerBaseUrl;

                SubjectConfirmation subjectConfirmation = new SubjectConfirmation();
                subjectConfirmation.Method = SubjectConfirmation.BEARER_METHOD;
                subjectConfirmation.SubjectConfirmationData = new SubjectConfirmationData();
                subjectConfirmation.SubjectConfirmationData.NotOnOrAfter = DateTime.Now.AddHours(1);
                subjectConfirmation.SubjectConfirmationData.Recipient = receiver;

                NameID nameId = new NameID();
                nameId.Format = Saml20Constants.NameIdentifierFormats.Persistent;
                nameId.Value = user.ppid;

                assertion.Subject.Items = new object[] { nameId, subjectConfirmation };
            }

            { // Conditions element
                assertion.Conditions = new Conditions();
                assertion.Conditions.Items = new List<ConditionAbstract>();

                assertion.Conditions.NotOnOrAfter = DateTime.Now.AddHours(1);

                AudienceRestriction audienceRestriction = new AudienceRestriction();
                audienceRestriction.Audience = new List<string>();
                audienceRestriction.Audience.Add(receiver);
                assertion.Conditions.Items.Add(audienceRestriction);
            }

            List<StatementAbstract> statements = new List<StatementAbstract>(2);
            { // AuthnStatement element
                AuthnStatement authnStatement = new AuthnStatement();
                authnStatement.AuthnInstant = DateTime.Now;
                authnStatement.SessionIndex = Convert.ToString(new Random().Next());

                authnStatement.AuthnContext = new AuthnContext();

                authnStatement.AuthnContext.Items =
                    new object[] {"urn:oasis:names:tc:SAML:2.0:ac:classes:X509"};

                // Wow! Setting the AuthnContext is .... verbose.
                authnStatement.AuthnContext.ItemsElementName =
                    new ItemsChoiceType5[] { ItemsChoiceType5.AuthnContextClassRef };

                statements.Add(authnStatement);
            }

            { // Generate attribute list.
                AttributeStatement attributeStatement = new AttributeStatement();

                List<SamlAttribute> attributes = new List<SamlAttribute>(user.Attributes.Count);
                foreach (KeyValuePair<string, string> att in user.Attributes)
                {
                    SamlAttribute attribute = new SamlAttribute();
                    attribute.Name = att.Key;
                    attribute.AttributeValue = new string[] { att.Value };
                    attribute.NameFormat = SamlAttribute.NAMEFORMAT_BASIC;
                    attributes.Add(attribute);
                }
                attributeStatement.Items = attributes.ToArray();

                statements.Add(attributeStatement);
            }

            assertion.Items = statements.ToArray();

            return assertion;
        }
        public void _0002_NameID_Valid_Transient()
        {
            NameID nameID = new NameID();
            nameID.Format = Saml20Constants.NameIdentifierFormats.Transient;
            Saml20NameIDValidator validator = new Saml20NameIDValidator();

            nameID.Value = new string('f', 256);
            validator.ValidateNameID(nameID);

            nameID.Value = new string('f', 16);
            validator.ValidateNameID(nameID);
        }
 public void _0002_NameID_Invalid_Persistent()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Persistent;
     nameID.Value = " ";
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
 public void _0002_NameID_Invalid_Persistent_Length()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Persistent;
     nameID.Value = new string('f', 257);
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
 public void _0002_NameID_Invalid_Entity_Length()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Entity;
     nameID.Value = new string('f', 1025);
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
 public void _0002_NameID_Invalid_Entity_SPProvidedID()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Entity;
     nameID.Value = new string('f', 1024);
     nameID.SPProvidedID = "ksljdf";
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
 public void _0002_NameID_Valid_Kerberos()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Kerberos;
     nameID.Value = "a@b";
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
        public void _0002_NameID_Valid_WindowsDomainQualifiedName()
        {
            NameID nameID = new NameID();
            nameID.Format = Saml20Constants.NameIdentifierFormats.Windows;
            Saml20NameIDValidator validator = new Saml20NameIDValidator();

            nameID.Value = "a";
            validator.ValidateNameID(nameID);

            nameID.Value = "b\a";
            validator.ValidateNameID(nameID);
        }
 public void _0002_NameID_Invalid_X509SubjecName()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.X509SubjectName;
     nameID.Value = " ";
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
 public void _0001_NameID_Valid_Email()
 {
     NameID nameID = new NameID();
     nameID.Format = Saml20Constants.NameIdentifierFormats.Email;
     nameID.Value = "*****@*****.**";
     Saml20NameIDValidator validator = new Saml20NameIDValidator();
     validator.ValidateNameID(nameID);
 }
        /// <summary>
        /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current.
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <param name="endPoint">The IdP to perform the query against.</param>
        /// <param name="nameIdFormat">The nameid format.</param>
        public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat)
        {
            Trace.TraceMethodCalled(GetType(), "PerformQuery()");

            HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context);

            NameID name = new NameID();
            name.Value = Saml20Identity.Current.Name;
            name.Format = nameIdFormat;
            _attrQuery.Subject.Items = new object[] { name };

            _attrQuery.SamlAttribute = _attributes.ToArray();
            XmlDocument query = new XmlDocument();
            query.LoadXml(Serialization.SerializeToXmlString(_attrQuery));

            XmlSignatureUtils.SignDocument(query, ID);
            if(query.FirstChild is XmlDeclaration)
                query.RemoveChild(query.FirstChild);

            Stream s;

            if (Trace.ShouldTrace(TraceEventType.Information))
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml));

            try
            {
                 s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml,
                                               endPoint.AttributeQuery);

            }catch(Exception e)
            {
                Trace.TraceData(TraceEventType.Error, e.ToString());
                throw;
            }

            HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s);

            Status status = parser.GetStatus();

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                Trace.TraceData(TraceEventType.Error,
                                string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status)));
                throw new Saml20Exception(status.StatusMessage);
            }

            bool isEncrypted;

            XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted);

            if (isEncrypted)
            {
                Saml20EncryptedAssertion ass =
                    new Saml20EncryptedAssertion(
                        (RSA) FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey);
                ass.LoadXml(xmlAssertion);
                ass.Decrypt();
                xmlAssertion = ass.Assertion.DocumentElement;
            }

            Saml20Assertion assertion =
                    new Saml20Assertion(xmlAssertion, null,
                                        AssertionProfile.Core, endPoint.QuirksMode);

            if(Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml));
            }

            if(!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint))){
                Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid);
                throw new Saml20Exception(Resources.SignatureInvalid);
            }

            foreach (SamlAttribute attr in assertion.Attributes)
            {
                Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr);
            }
        }