Ejemplo n.º 1
0
        private double ParameterizedCheckIdTest(Protocol protocol, string assocType)
        {
            Association assoc = HmacShaAssociation.Create(
                protocol,
                assocType,
                AssociationRelyingPartyType.Smart,
                this.provider.SecuritySettings);

            this.provider.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, assoc);
            var       checkidRequest = this.CreateCheckIdRequest(true);
            Stopwatch timer          = new Stopwatch();

            timer.Start();
            int iterations;

            for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++)
            {
                var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
                request.IsAuthenticated = true;
                var response = this.provider.PrepareResponse(request);
                Assert.IsInstanceOf <PositiveAssertionResponse>(response.OriginalMessage);
            }
            timer.Stop();
            double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);

            TestUtilities.TestLogger.InfoFormat("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
            return(executionsPerSecond);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a Provider's response to an incoming association request.
        /// </summary>
        /// <param name="requestMessage">The request message.</param>
        /// <param name="associationStore">The association store.</param>
        /// <param name="securitySettings">The security settings on the Provider.</param>
        /// <returns>
        /// The appropriate association response that is ready to be sent back to the Relying Party.
        /// </returns>
        /// <remarks>
        ///   <para>If an association is created, it will be automatically be added to the provided
        /// association store.</para>
        ///   <para>Successful association response messages will derive from <see cref="AssociateSuccessfulResponse"/>.
        /// Failed association response messages will derive from <see cref="AssociateUnsuccessfulResponse"/>.</para>
        /// </remarks>
        internal static IProtocolMessage CreateResponse(IAssociateRequestProvider requestMessage, IProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings)
        {
            Requires.NotNull(requestMessage, "requestMessage");
            Requires.NotNull(associationStore, "associationStore");
            Requires.NotNull(securitySettings, "securitySettings");

            AssociateRequest request = (AssociateRequest)requestMessage;
            IProtocolMessage response;
            var protocol = requestMessage.GetProtocol();

            if (securitySettings.IsAssociationInPermittedRange(protocol, request.AssociationType) &&
                HmacShaAssociation.IsDHSessionCompatible(protocol, request.AssociationType, request.SessionType))
            {
                response = requestMessage.CreateResponseCore();

                // Create and store the association if this is a successful response.
                var successResponse = response as IAssociateSuccessfulResponseProvider;
                if (successResponse != null)
                {
                    OpenIdProviderUtilities.CreateAssociation(request, successResponse, associationStore, securitySettings);
                }
            }
            else
            {
                response = CreateUnsuccessfulResponse(requestMessage, securitySettings);
            }

            return(response);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a response that notifies the Relying Party that the requested
        /// association type is not supported by this Provider, and offers
        /// an alternative association type, if possible.
        /// </summary>
        /// <param name="requestMessage">The request message.</param>
        /// <param name="securitySettings">The security settings that apply to this Provider.</param>
        /// <returns>
        /// The response to send to the Relying Party.
        /// </returns>
        private static AssociateUnsuccessfulResponse CreateUnsuccessfulResponse(IAssociateRequestProvider requestMessage, ProviderSecuritySettings securitySettings)
        {
            Requires.NotNull(requestMessage, "requestMessage");
            Requires.NotNull(securitySettings, "securitySettings");

            var unsuccessfulResponse = new AssociateUnsuccessfulResponse(requestMessage.Version, (AssociateRequest)requestMessage);

            // The strategy here is to suggest that the RP try again with the lowest
            // permissible security settings, giving the RP the best chance of being
            // able to match with a compatible request.
            bool   unencryptedAllowed = requestMessage.Recipient.IsTransportSecure();
            bool   useDiffieHellman = !unencryptedAllowed;
            var    request = (AssociateRequest)requestMessage;
            var    protocol = requestMessage.GetProtocol();
            string associationType, sessionType;

            if (HmacShaAssociation.TryFindBestAssociation(protocol, false, securitySettings, useDiffieHellman, out associationType, out sessionType))
            {
                ErrorUtilities.VerifyInternal(request.AssociationType != associationType, "The RP asked for an association that should have been allowed, but the OP is trying to suggest the same one as an alternative!");
                unsuccessfulResponse.AssociationType = associationType;
                unsuccessfulResponse.SessionType     = sessionType;
                Logger.OpenId.InfoFormat(
                    "Association requested of type '{0}' and session '{1}', which the Provider does not support.  Sending back suggested alternative of '{0}' with session '{1}'.",
                    request.AssociationType,
                    request.SessionType,
                    unsuccessfulResponse.AssociationType,
                    unsuccessfulResponse.SessionType);
            }
            else
            {
                Logger.OpenId.InfoFormat("Association requested of type '{0}' and session '{1}', which the Provider does not support.  No alternative association type qualified for suggesting back to the Relying Party.", request.AssociationType, request.SessionType);
            }

            return(unsuccessfulResponse);
        }
Ejemplo n.º 4
0
        public void Sign()
        {
            Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h1", this.sha1Secret, TimeSpan.FromMinutes(2));
            Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h2", this.sha1Secret2, TimeSpan.FromMinutes(2));

            var data = new byte[] { 0xdd, 0xcc };

            // sign once and verify that it's sane
            byte[] signature1 = assoc1.Sign(data);
            Assert.IsNotNull(signature1);
            Assert.AreNotEqual(0, signature1.Length);

            // sign again and make sure it's different
            byte[] signature2 = assoc2.Sign(data);
            Assert.IsNotNull(signature2);
            Assert.AreNotEqual(0, signature2.Length);
            Assert.IsFalse(MessagingUtilities.AreEquivalent(signature1, signature2));

            // sign again with the same secret and make sure it's the same.
            Assert.IsTrue(MessagingUtilities.AreEquivalent(signature1, assoc1.Sign(data)));

            // now change the data and make sure signature changes
            data[1] = 0xee;
            Assert.IsFalse(MessagingUtilities.AreEquivalent(signature1, assoc1.Sign(data)));
        }
Ejemplo n.º 5
0
        public void SignSome()
        {
            Association assoc = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                          "h1", sha1Secret, TimeSpan.FromMinutes(2));
            const string prefix = "q.";

            var dict = new Dictionary <string, string>();

            dict.Add("q.a", "b");
            dict.Add("q.c", "d");
            dict.Add("q.e", "f");

            var signKeys = new List <string> {
                "a", "c"
            };                                                        // don't sign e

            byte[] sig1 = assoc.Sign(dict, signKeys, prefix);

            // change the unsigned value and verify that the sig doesn't change
            dict["q.e"] = "g";
            Assert.IsTrue(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));
            // change a signed value and verify that the sig does change.
            dict["q.c"] = "D";
            Assert.IsFalse(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));

            // change the ordering of signed fields and verify that the signature changes.
            dict["q.c"] = "d";             // put this back first.
            Assert.IsTrue(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));
            signKeys.Insert(0, signKeys[1]);
            signKeys.RemoveAt(2);
            Assert.IsFalse(Util.ArrayEquals(sig1, assoc.Sign(dict, signKeys, prefix)));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Creates a new association of a given type at an OpenID Provider.
        /// </summary>
        /// <param name="protocol">The protocol.</param>
        /// <param name="associationType">Type of the association (i.e. HMAC-SHA1 or HMAC-SHA256)</param>
        /// <param name="associationUse">A value indicating whether the new association will be used privately by the Provider for "dumb mode" authentication
        /// or shared with the Relying Party for "smart mode" authentication.</param>
        /// <param name="associationStore">The Provider's association store.</param>
        /// <param name="securitySettings">The security settings of the Provider.</param>
        /// <returns>
        /// The newly created association.
        /// </returns>
        /// <remarks>
        /// The new association is NOT automatically put into an association store.  This must be done by the caller.
        /// </remarks>
        internal static HmacShaAssociation Create(Protocol protocol, string associationType, AssociationRelyingPartyType associationUse, IProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings)
        {
            Requires.NotNull(protocol, "protocol");
            Requires.NotNullOrEmpty(associationType, "associationType");
            Requires.NotNull(associationStore, "associationStore");
            Requires.NotNull(securitySettings, "securitySettings");

            int secretLength = HmacShaAssociation.GetSecretLength(protocol, associationType);

            // Generate the secret that will be used for signing
            byte[] secret = MessagingUtilities.GetCryptoRandomData(secretLength);

            TimeSpan lifetime;

            if (associationUse == AssociationRelyingPartyType.Smart)
            {
                if (!securitySettings.AssociationLifetimes.TryGetValue(associationType, out lifetime))
                {
                    lifetime = DefaultMaximumLifetime;
                }
            }
            else
            {
                lifetime = HmacShaAssociation.DumbSecretLifetime;
            }

            string handle = associationStore.Serialize(secret, DateTime.UtcNow + lifetime, associationUse == AssociationRelyingPartyType.Dumb);

            Assumes.True(protocol != null);             // All the way up to the method call, the condition holds, yet we get a Requires failure next
            Assumes.True(secret != null);
            Assumes.True(!string.IsNullOrEmpty(associationType));
            var result = HmacShaAssociation.Create(protocol, associationType, handle, secret, lifetime);

            return(result);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Creates a Provider's response to an incoming association request.
        /// </summary>
        /// <param name="associationStore">The association store where a new association (if created) will be stored.  Must not be null.</param>
        /// <param name="securitySettings">The security settings on the Provider.</param>
        /// <returns>
        /// The appropriate association response that is ready to be sent back to the Relying Party.
        /// </returns>
        /// <remarks>
        /// <para>If an association is created, it will be automatically be added to the provided
        /// association store.</para>
        /// <para>Successful association response messages will derive from <see cref="AssociateSuccessfulResponse"/>.
        /// Failed association response messages will derive from <see cref="AssociateUnsuccessfulResponse"/>.</para>
        /// </remarks>
        internal IProtocolMessage CreateResponse(IAssociationStore <AssociationRelyingPartyType> associationStore, ProviderSecuritySettings securitySettings)
        {
            Contract.Requires <ArgumentNullException>(associationStore != null);
            Contract.Requires <ArgumentNullException>(securitySettings != null);

            IProtocolMessage response;

            if (securitySettings.IsAssociationInPermittedRange(Protocol, this.AssociationType) &&
                HmacShaAssociation.IsDHSessionCompatible(Protocol, this.AssociationType, this.SessionType))
            {
                response = this.CreateResponseCore();

                // Create and store the association if this is a successful response.
                var successResponse = response as AssociateSuccessfulResponse;
                if (successResponse != null)
                {
                    Association association = successResponse.CreateAssociation(this, securitySettings);
                    associationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association);
                }
            }
            else
            {
                response = this.CreateUnsuccessfulResponse(securitySettings);
            }

            return(response);
        }
Ejemplo n.º 8
0
        public void Sign()
        {
            Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h1", this.sha1Secret, TimeSpan.FromMinutes(2));
            Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h2", this.sha1Secret2, TimeSpan.FromMinutes(2));

            var data = new byte[] { 0xdd, 0xcc };

            // sign once and verify that it's sane
            byte[] signature1 = assoc1.Sign(data);
            Assert.That(signature1, Is.Not.Null);
            Assert.That(signature1.Length, Is.Not.EqualTo(0));

            // sign again and make sure it's different
            byte[] signature2 = assoc2.Sign(data);
            Assert.That(signature2, Is.Not.Null);
            Assert.That(signature2.Length, Is.Not.EqualTo(0));
            Assert.That(signature1, Is.Not.EqualTo(signature2));

            // sign again with the same secret and make sure it's the same.
            Assert.That(assoc1.Sign(data), Is.EqualTo(signature1));

            // now change the data and make sure signature changes
            data[1] = 0xee;
            Assert.That(assoc1.Sign(data), Is.Not.EqualTo(signature1));
        }
Ejemplo n.º 9
0
        public static AssociateRequest Create(OpenIdRelyingParty relyingParty, ServiceEndpoint provider)
        {
            if (relyingParty == null)
            {
                throw new ArgumentNullException("relyingParty");
            }
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            string assoc_type, session_type;

            if (HmacShaAssociation.TryFindBestAssociation(provider.Protocol,
                                                          relyingParty.Settings.MinimumHashBitLength, relyingParty.Settings.MaximumHashBitLength,
                                                          true, out assoc_type, out session_type))
            {
                return(Create(relyingParty, provider, assoc_type, session_type, true));
            }
            else
            {
                // There are no associations that meet all requirements.
                Logger.Warn("Security requirements and protocol combination knock out all possible association types.  Dumb mode forced.");
                return(null);
            }
        }
Ejemplo n.º 10
0
        public static AssociateRequest Create(OpenIdRelyingParty relyingParty, ServiceEndpoint provider)
        {
            if (relyingParty == null)
            {
                throw new ArgumentNullException("relyingParty");
            }
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            string assoc_type, session_type;
            bool   requireDiffieHellman = !string.Equals(provider.ProviderEndpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase);

            if (HmacShaAssociation.TryFindBestAssociation(provider.Protocol,
                                                          relyingParty.Settings.MinimumHashBitLength, relyingParty.Settings.MaximumHashBitLength,
                                                          requireDiffieHellman, out assoc_type, out session_type))
            {
                return(Create(relyingParty, provider, assoc_type, session_type, true));
            }
            else
            {
                // There are no associations that meet all requirements.
                //Logger.Warn("Security requirements and protocol combination knock out all possible association types.  Dumb mode forced.");
                return(null);
            }
        }
        /// <summary>
        /// Called to create the Association based on a request previously given by the Relying Party.
        /// </summary>
        /// <param name="request">The prior request for an association.</param>
        /// <param name="securitySettings">The security settings of the Provider.</param>
        /// <returns>The created association.</returns>
        /// <remarks>
        ///     <para>The caller will update this message's
        /// <see cref="AssociateSuccessfulResponse.ExpiresIn"/> and
        /// <see cref="AssociateSuccessfulResponse.AssociationHandle"/>
        /// properties based on the <see cref="Association"/> returned by this method, but any other
        /// association type specific properties must be set by this method.</para>
        ///     <para>The response message is updated to include the details of the created association by this method,
        /// but the resulting association is <i>not</i> added to the association store and must be done by the caller.</para>
        /// </remarks>
        protected override Association CreateAssociationAtProvider(AssociateRequest request, ProviderSecuritySettings securitySettings)
        {
            Association association = HmacShaAssociation.Create(Protocol, this.AssociationType, AssociationRelyingPartyType.Smart, securitySettings);

            this.MacKey = association.SecretKey;
            return(association);
        }
Ejemplo n.º 12
0
        public void Best()
        {
            Association a = HmacShaAssociation.Create(
                Protocol.Default,
                Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                "h1",
                this.sha1Secret,
                TimeSpan.FromHours(1));
            Association b = HmacShaAssociation.Create(
                Protocol.Default,
                Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                "h2",
                this.sha1Secret,
                TimeSpan.FromHours(1));

            this.assocs.Set(a);
            this.assocs.Set(b);

            // make b the best by making a older
            a.Issued -= TimeSpan.FromHours(1);
            Assert.AreSame(b, this.assocs.Best.FirstOrDefault());
            // now make a the best
            b.Issued -= TimeSpan.FromHours(2);
            Assert.AreSame(a, this.assocs.Best.FirstOrDefault());
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Creates the association at the provider side after the association request has been received.
        /// </summary>
        /// <param name="request">The association request.</param>
        /// <param name="securitySettings">The security settings of the Provider.</param>
        /// <returns>The newly created association.</returns>
        /// <remarks>
        /// The response message is updated to include the details of the created association by this method,
        /// but the resulting association is <i>not</i> added to the association store and must be done by the caller.
        /// </remarks>
        protected override Association CreateAssociationAtProvider(AssociateRequest request, ProviderSecuritySettings securitySettings)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            var diffieHellmanRequest = request as AssociateDiffieHellmanRequest;

            ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, "request");
            ErrorUtilities.VerifyArgumentNotNull(securitySettings, "securitySettings");

            this.SessionType = this.SessionType ?? request.SessionType;

            // Go ahead and create the association first, complete with its secret that we're about to share.
            Association association = HmacShaAssociation.Create(this.Protocol, this.AssociationType, AssociationRelyingPartyType.Smart, securitySettings);

            this.AssociationHandle = association.Handle;
            this.ExpiresIn         = association.SecondsTillExpiration;

            // We now need to securely communicate the secret to the relying party using Diffie-Hellman.
            // We do this by performing a DH algorithm on the secret and setting a couple of properties
            // that will be transmitted to the Relying Party.  The RP will perform an inverse operation
            // using its part of a DH secret in order to decrypt the shared secret we just invented
            // above when we created the association.
            DiffieHellman dh = new DiffieHellmanManaged(
                diffieHellmanRequest.DiffieHellmanModulus ?? AssociateDiffieHellmanRequest.DefaultMod,
                diffieHellmanRequest.DiffieHellmanGen ?? AssociateDiffieHellmanRequest.DefaultGen,
                AssociateDiffieHellmanRequest.DefaultX);
            HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(this.Protocol, this.SessionType);

            this.DiffieHellmanServerPublic = DiffieHellmanUtilities.EnsurePositive(dh.CreateKeyExchange());
            this.EncodedMacKey             = DiffieHellmanUtilities.SHAHashXorSecret(hasher, dh, diffieHellmanRequest.DiffieHellmanConsumerPublic, association.SecretKey);

            return(association);
        }
Ejemplo n.º 14
0
        public async Task CreateRequest()
        {
            var rp = this.CreateRelyingParty();

            StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
            Identifier id  = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));
            var        req = await rp.CreateRequestAsync(id, RPRealmUri, RPUri);

            Assert.IsNotNull(req);
        }
Ejemplo n.º 15
0
        public void CreateRequests()
        {
            var rp = this.CreateRelyingParty();

            StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
            Identifier id       = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));
            var        requests = rp.CreateRequests(id, RPRealmUri, RPUri);

            Assert.AreEqual(1, requests.Count());
        }
Ejemplo n.º 16
0
        public void HandleLifecycle()
        {
            Association a = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                      "somehandle", sha1Secret, TimeSpan.FromDays(1));

            assocs.Set(a);
            Assert.AreSame(a, assocs.Get(a.Handle));
            Assert.IsTrue(assocs.Remove(a.Handle));
            Assert.IsNull(assocs.Get(a.Handle));
            Assert.IsFalse(assocs.Remove(a.Handle));
        }
Ejemplo n.º 17
0
        public void Properties()
        {
            string      handle   = "somehandle";
            TimeSpan    lifetime = TimeSpan.FromMinutes(2);
            Association assoc    = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, handle, this.sha1Secret, lifetime);

            Assert.IsFalse(assoc.IsExpired);
            Assert.IsTrue(Math.Abs((DateTime.Now - assoc.Issued.ToLocalTime()).TotalSeconds) < deltaDateTime.TotalSeconds);
            Assert.IsTrue(Math.Abs((DateTime.Now.ToLocalTime() + lifetime - assoc.Expires.ToLocalTime()).TotalSeconds) < deltaDateTime.TotalSeconds);
            Assert.AreEqual(handle, assoc.Handle);
            Assert.IsTrue(Math.Abs(lifetime.TotalSeconds - assoc.SecondsTillExpiration) < deltaDateTime.TotalSeconds);
            Assert.IsTrue(MessagingUtilities.AreEquivalent(this.sha1Secret, assoc.SecretKey));
            Assert.AreEqual(0, assoc.Issued.Millisecond, "No milliseconds because this can be cut off in conversions.");
        }
Ejemplo n.º 18
0
        public void Properties()
        {
            string      handle   = "somehandle";
            TimeSpan    lifetime = TimeSpan.FromMinutes(2);
            Association assoc    = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, handle, this.sha1Secret, lifetime);

            Assert.IsFalse(assoc.IsExpired);
            Assert.That(assoc.Issued, Is.EqualTo(DateTime.UtcNow).Within(deltaDateTime));
            Assert.That(assoc.Expires, Is.EqualTo(DateTime.UtcNow + lifetime).Within(deltaDateTime));
            Assert.That(assoc.Handle, Is.EqualTo(handle));
            Assert.That(assoc.SecondsTillExpiration, Is.EqualTo(lifetime.TotalSeconds).Within(deltaDateTime.TotalSeconds));
            Assert.That(assoc.SecretKey, Is.EqualTo(this.sha1Secret));
            Assert.That(assoc.Issued.Millisecond, Is.EqualTo(0), "No milliseconds because this can be cut off in conversions.");
        }
        /// <summary>
        /// Creates the association at relying party side after the association response has been received.
        /// </summary>
        /// <param name="request">The original association request that was already sent and responded to.</param>
        /// <returns>The newly created association.</returns>
        /// <remarks>
        /// The resulting association is <i>not</i> added to the association store and must be done by the caller.
        /// </remarks>
        public Association CreateAssociationAtRelyingParty(AssociateRequest request)
        {
            var diffieHellmanRequest = request as AssociateDiffieHellmanRequest;

            ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, OpenIdStrings.DiffieHellmanAssociationRequired);

            HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(Protocol, this.SessionType);

            byte[] associationSecret = DiffieHellmanUtilities.SHAHashXorSecret(hasher, diffieHellmanRequest.Algorithm, this.DiffieHellmanServerPublic, this.EncodedMacKey);

            Association association = HmacShaAssociation.Create(Protocol, this.AssociationType, this.AssociationHandle, associationSecret, TimeSpan.FromSeconds(this.ExpiresIn));

            return(association);
        }
Ejemplo n.º 20
0
        public virtual Association CreateAssociation(AssociationRelyingPartyType associationType, OpenIdProvider provider)
        {
            if (provider == null && associationType == AssociationRelyingPartyType.Smart)
            {
                throw new ArgumentNullException("provider", "For Smart associations, the provider must be given.");
            }

            string   assoc_type;
            Protocol associationProtocol;

            if (associationType == AssociationRelyingPartyType.Dumb)
            {
                // We'll just use the best association available.
                associationProtocol = Protocol.Default;
                assoc_type          = associationProtocol.Args.SignatureAlgorithm.Best;
            }
            else
            {
                associationProtocol = provider.Protocol;
                assoc_type          = Util.GetRequiredArg(provider.Query, provider.Protocol.openid.assoc_type);
                Debug.Assert(Array.IndexOf(provider.Protocol.Args.SignatureAlgorithm.All, assoc_type) >= 0, "This should have been checked by our caller.");
            }
            int secretLength = HmacShaAssociation.GetSecretLength(associationProtocol, assoc_type);

            RNGCryptoServiceProvider generator = new RNGCryptoServiceProvider();

            byte[]             secret     = new byte[secretLength];
            byte[]             uniq_bytes = new byte[4];
            string             uniq;
            string             handle;
            HmacShaAssociation assoc;

            generator.GetBytes(secret);
            generator.GetBytes(uniq_bytes);

            uniq = Convert.ToBase64String(uniq_bytes);

            double seconds = DateTime.UtcNow.Subtract(Association.UnixEpoch).TotalSeconds;

            handle = "{{" + assoc_type + "}{" + seconds + "}{" + uniq + "}";

            TimeSpan lifeSpan = associationType == AssociationRelyingPartyType.Dumb ? dumbSecretLifetime : smartAssociationLifetime;

            assoc = HmacShaAssociation.Create(secretLength, handle, secret, lifeSpan);

            store.StoreAssociation(associationType, assoc);

            return(assoc);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Gets a private Provider association used for signing messages in "dumb" mode.
        /// </summary>
        /// <returns>An existing or newly created association.</returns>
        private Association GetDumbAssociationForSigning()
        {
            // If no assoc_handle was given or it was invalid, the only thing
            // left to do is sign a message using a 'dumb' mode association.
            Protocol    protocol    = Protocol.Default;
            Association association = this.opAssociations.GetAssociation(AssociationRelyingPartyType.Dumb, this.opSecuritySettings);

            if (association == null)
            {
                association = HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.HMAC_SHA256, AssociationRelyingPartyType.Dumb, this.opSecuritySettings);
                this.opAssociations.StoreAssociation(AssociationRelyingPartyType.Dumb, association);
            }

            return(association);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Simulates an extension request and response.
        /// </summary>
        /// <param name="protocol">The protocol to use in the roundtripping.</param>
        /// <param name="requests">The extensions to add to the request message.</param>
        /// <param name="responses">The extensions to add to the response message.</param>
        /// <remarks>
        /// This method relies on the extension objects' Equals methods to verify
        /// accurate transport.  The Equals methods should be verified by separate tests.
        /// </remarks>
        internal static void Roundtrip(
            Protocol protocol,
            IEnumerable <IOpenIdMessageExtension> requests,
            IEnumerable <IOpenIdMessageExtension> responses)
        {
            ProviderSecuritySettings securitySettings = new ProviderSecuritySettings();
            Association association = HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, securitySettings);
            var         coordinator = new OpenIdCoordinator(
                rp => {
                RegisterExtension(rp.Channel, Mocks.MockOpenIdExtension.Factory);
                var requestBase = new CheckIdRequest(protocol.Version, OpenIdTestBase.OPUri, AuthenticationRequestMode.Immediate);
                OpenIdTestBase.StoreAssociation(rp, OpenIdTestBase.OPUri, association);
                requestBase.AssociationHandle = association.Handle;
                requestBase.ClaimedIdentifier = "http://claimedid";
                requestBase.LocalIdentifier   = "http://localid";
                requestBase.ReturnTo          = OpenIdTestBase.RPUri;

                foreach (IOpenIdMessageExtension extension in requests)
                {
                    requestBase.Extensions.Add(extension);
                }

                rp.Channel.Send(requestBase);
                var response = rp.Channel.ReadFromRequest <PositiveAssertionResponse>();

                var receivedResponses = response.Extensions.Cast <IOpenIdMessageExtension>();
                CollectionAssert <IOpenIdMessageExtension> .AreEquivalentByEquality(responses.ToArray(), receivedResponses.ToArray());
            },
                op => {
                RegisterExtension(op.Channel, Mocks.MockOpenIdExtension.Factory);
                op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association);
                var request          = op.Channel.ReadFromRequest <CheckIdRequest>();
                var response         = new PositiveAssertionResponse(request);
                var receivedRequests = request.Extensions.Cast <IOpenIdMessageExtension>();
                CollectionAssert <IOpenIdMessageExtension> .AreEquivalentByEquality(requests.ToArray(), receivedRequests.ToArray());

                foreach (var extensionResponse in responses)
                {
                    response.Extensions.Add(extensionResponse);
                }

                op.Channel.Send(response);
            });

            coordinator.Run();
        }
Ejemplo n.º 23
0
        public async Task CreateRequestsWithEndpointFilter()
        {
            var rp = this.CreateRelyingParty();

            StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
            Identifier id = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));

            rp.EndpointFilter = opendpoint => true;
            var requests = await rp.CreateRequestsAsync(id, RPRealmUri, RPUri);

            Assert.AreEqual(1, requests.Count());

            rp.EndpointFilter = opendpoint => false;
            requests          = await rp.CreateRequestsAsync(id, RPRealmUri, RPUri);

            Assert.AreEqual(0, requests.Count());
        }
        void initializeAssociation()
        {
            string assoc_type = Util.GetRequiredArg(Args, Protocol.openidnp.assoc_type);

            if (Array.IndexOf(Protocol.Args.SignatureAlgorithm.All, assoc_type) >= 0)
            {
                byte[] secret;

                string session_type;
                if (!Args.TryGetValue(Protocol.openidnp.session_type, out session_type) ||
                    Protocol.Args.SessionType.NoEncryption.Equals(session_type, StringComparison.Ordinal))
                {
                    secret = getDecoded(Protocol.openidnp.mac_key);
                }
                else
                {
                    try {
                        byte[] dh_server_public = getDecoded(Protocol.openidnp.dh_server_public);
                        byte[] enc_mac_key      = getDecoded(Protocol.openidnp.enc_mac_key);
                        secret = DiffieHellmanUtil.SHAHashXorSecret(DiffieHellmanUtil.Lookup(Protocol, session_type), DH, dh_server_public, enc_mac_key);
                    } catch (ArgumentException ex) {
                        throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
                                                                Strings.InvalidOpenIdQueryParameterValue,
                                                                Protocol.openid.session_type, session_type), ex);
                    }
                }

                string   assocHandle = Util.GetRequiredArg(Args, Protocol.openidnp.assoc_handle);
                TimeSpan expiresIn   = new TimeSpan(0, 0, Convert.ToInt32(Util.GetRequiredArg(Args, Protocol.openidnp.expires_in), CultureInfo.InvariantCulture));

                try {
                    Association = HmacShaAssociation.Create(Protocol, assoc_type,
                                                            assocHandle, secret, expiresIn);
                } catch (ArgumentException ex) {
                    throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
                                                            Strings.InvalidOpenIdQueryParameterValue,
                                                            Protocol.openid.assoc_type, assoc_type), ex);
                }
            }
            else
            {
                throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.InvalidOpenIdQueryParameterValue,
                                                        Protocol.openid.assoc_type, assoc_type));
            }
        }
Ejemplo n.º 25
0
        public void Sign()
        {
            Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                           "h1", sha1Secret, TimeSpan.FromMinutes(2));
            Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1,
                                                           "h2", sha1Secret2, TimeSpan.FromMinutes(2));

            var dict = new Dictionary <string, string>();

            dict.Add("a", "b");
            dict.Add("c", "d");
            var keys = new List <string>();

            keys.Add("a");
            keys.Add("c");

            // sign once and verify that it's sane
            byte[] signature1 = assoc1.Sign(dict, keys);
            Assert.IsNotNull(signature1);
            Assert.AreNotEqual(0, signature1.Length);

            // sign again and make sure it's different
            byte[] signature2 = assoc2.Sign(dict, keys);
            Assert.IsNotNull(signature2);
            Assert.AreNotEqual(0, signature2.Length);
            Assert.IsFalse(Util.ArrayEquals(signature1, signature2));

            // sign again with the same secret and make sure it's the same.
            Assert.IsTrue(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));

            // now add data and make sure signature changes
            dict.Add("g", "h");
            keys.Add("g");
            Assert.IsFalse(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));

            // now change existing data.
            dict.Remove("g");
            keys.Remove("g");
            dict["c"] = "e";
            Assert.IsFalse(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));
            dict.Remove("c");
            keys.Remove("c");
            Assert.IsFalse(Util.ArrayEquals(signature1, assoc1.Sign(dict, keys)));
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Creates an association request message that is appropriate for a given Provider.
        /// </summary>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>
        /// The message to send to the Provider to request an association.
        /// Null if no association could be created that meet the security requirements
        /// and the provider OpenID version.
        /// </returns>
        internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements");
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // Apply our knowledge of the endpoint's transport, OpenID version, and
            // security requirements to decide the best association.
            bool   unencryptedAllowed = provider.Endpoint.IsTransportSecure();
            bool   useDiffieHellman = !unencryptedAllowed;
            string associationType, sessionType;

            if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.ProtocolVersion), true, securityRequirements, useDiffieHellman, out associationType, out sessionType))
            {
                // There are no associations that meet all requirements.
                Logger.Warn("Security requirements and protocol combination knock out all possible association types.  Dumb mode forced.");
                return(null);
            }

            return(Create(securityRequirements, provider, associationType, sessionType));
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Creates an association request message that is appropriate for a given Provider.
        /// </summary>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>
        /// The message to send to the Provider to request an association.
        /// Null if no association could be created that meet the security requirements
        /// and the provider OpenID version.
        /// </returns>
        internal static AssociateRequest Create(SecuritySettings securityRequirements, IProviderEndpoint provider)
        {
            Contract.Requires <ArgumentNullException>(securityRequirements != null);
            Contract.Requires <ArgumentNullException>(provider != null);

            // Apply our knowledge of the endpoint's transport, OpenID version, and
            // security requirements to decide the best association.
            bool   unencryptedAllowed = provider.Uri.IsTransportSecure();
            bool   useDiffieHellman = !unencryptedAllowed;
            string associationType, sessionType;

            if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.Version), true, securityRequirements, useDiffieHellman, out associationType, out sessionType))
            {
                // There are no associations that meet all requirements.
                Logger.OpenId.Warn("Security requirements and protocol combination knock out all possible association types.  Dumb mode forced.");
                return(null);
            }

            return(Create(securityRequirements, provider, associationType, sessionType));
        }
        /// <summary>
        /// Gets an association to use for signing new data.
        /// </summary>
        /// <returns>
        /// The association, which may have previously existed or
        /// may have been created as a result of this call.
        /// </returns>
        private Association GetAssociation()
        {
            Association privateAssociation = this.store.GetAssociation(SecretUri, this.securitySettings);

            if (privateAssociation == null || !privateAssociation.HasUsefulLifeRemaining)
            {
                int    secretLength = HmacShaAssociation.GetSecretLength(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.Best);
                byte[] secret       = MessagingUtilities.GetCryptoRandomData(secretLength);
                privateAssociation = HmacShaAssociation.Create(this.CreateNewAssociationHandle(), secret, this.securitySettings.PrivateSecretMaximumAge);
                if (!privateAssociation.HasUsefulLifeRemaining)
                {
                    Logger.WarnFormat(
                        "Brand new private association has a shorter lifespan ({0}) than the maximum allowed authentication time for a user ({1}).  This may lead to login failures.",
                        this.securitySettings.PrivateSecretMaximumAge,
                        DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime);
                }

                this.store.StoreAssociation(SecretUri, privateAssociation);
            }

            return(privateAssociation);
        }
        public void SignaturesMatchKnownGood()
        {
            Protocol protocol = Protocol.V20;
            var      settings = new ProviderSecuritySettings();
            var      store    = new AssociationMemoryStore <AssociationRelyingPartyType>();

            byte[]      associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
            Association association       = HmacShaAssociation.Create("mock", associationSecret, TimeSpan.FromDays(1));

            store.StoreAssociation(AssociationRelyingPartyType.Smart, association);
            SigningBindingElement signer = new SigningBindingElement(store, settings);

            signer.Channel = new TestChannel(this.MessageDescriptions);

            IndirectSignedResponse        message       = new IndirectSignedResponse(protocol.Version, new Uri("http://rp"));
            ITamperResistantOpenIdMessage signedMessage = message;

            message.ProviderEndpoint        = new Uri("http://provider");
            signedMessage.UtcCreationDate   = DateTime.Parse("1/1/2009");
            signedMessage.AssociationHandle = association.Handle;
            Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
            Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Creates a new association with a given Provider.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <param name="associateRequest">The associate request.  May be <c>null</c>, which will always result in a <c>null</c> return value..</param>
        /// <param name="retriesRemaining">The number of times to try the associate request again if the Provider suggests it.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The newly created association, or null if no association can be created with
        /// the given Provider given the current security settings.
        /// </returns>
        /// <exception cref="ProtocolException">Create if an error occurs while creating the new association.</exception>
        private async Task <Association> CreateNewAssociationAsync(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining, CancellationToken cancellationToken)
        {
            Requires.NotNull(provider, "provider");

            if (associateRequest == null || retriesRemaining < 0)
            {
                // this can happen if security requirements and protocol conflict
                // to where there are no association types to choose from.
                return(null);
            }

            Exception exception = null;

            try {
                var associateResponse = await this.channel.RequestAsync(associateRequest, cancellationToken);

                var associateSuccessfulResponse   = associateResponse as IAssociateSuccessfulResponseRelyingParty;
                var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
                if (associateSuccessfulResponse != null)
                {
                    Association association = associateSuccessfulResponse.CreateAssociationAtRelyingParty(associateRequest);
                    this.associationStore.StoreAssociation(provider.Uri, association);
                    return(association);
                }
                else if (associateUnsuccessfulResponse != null)
                {
                    if (string.IsNullOrEmpty(associateUnsuccessfulResponse.AssociationType))
                    {
                        Logger.OpenId.Debug("Provider rejected an association request and gave no suggestion as to an alternative association type.  Giving up.");
                        return(null);
                    }

                    if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.Version), associateUnsuccessfulResponse.AssociationType))
                    {
                        Logger.OpenId.DebugFormat("Provider rejected an association request and suggested '{0}' as an association to try, which this Relying Party does not support.  Giving up.", associateUnsuccessfulResponse.AssociationType);
                        return(null);
                    }

                    if (retriesRemaining <= 0)
                    {
                        Logger.OpenId.Debug("Unable to agree on an association type with the Provider in the allowed number of retries.  Giving up.");
                        return(null);
                    }

                    // Make sure the Provider isn't suggesting an incompatible pair of association/session types.
                    Protocol protocol = Protocol.Lookup(provider.Version);
                    ErrorUtilities.VerifyProtocol(
                        HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType),
                        OpenIdStrings.IncompatibleAssociationAndSessionTypes,
                        associateUnsuccessfulResponse.AssociationType,
                        associateUnsuccessfulResponse.SessionType);

                    associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType);
                    return(await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken));
                }
                else
                {
                    throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany);
                }
            } catch (ProtocolException ex) {
                exception = ex;
            }

            Assumes.NotNull(exception);

            // If the association failed because the remote server can't handle Expect: 100 Continue headers,
            // then our web request handler should have already accomodated for future calls.  Go ahead and
            // immediately make one of those future calls now to try to get the association to succeed.
            if (UntrustedWebRequestHandler.IsExceptionFrom417ExpectationFailed(exception))
            {
                return(await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken));
            }

            // Since having associations with OPs is not totally critical, we'll log and eat
            // the exception so that auth may continue in dumb mode.
            Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}.  {1}", provider.Uri, exception);
            return(null);
        }