internal void RegisterMockResponse(IncomingWebResponse response) { Requires.NotNull(response, "response"); if (this.registeredMockResponses.ContainsKey(response.RequestUri)) { Logger.Http.WarnFormat("Mock HTTP response already registered for {0}.", response.RequestUri); } else { this.registeredMockResponses.Add(response.RequestUri, response); } }
internal void RegisterMockResponse(IncomingWebResponse response) { Contract.Requires<ArgumentNullException>(response != null); if (this.registeredMockResponses.ContainsKey(response.RequestUri)) { Logger.Http.WarnFormat("Mock HTTP response already registered for {0}.", response.RequestUri); } else { this.registeredMockResponses.Add(response.RequestUri, response); } }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { // The spec says direct responses should be JSON objects, but Facebook uses HttpFormUrlEncoded instead, calling it text/plain // Others return text/javascript. Again bad. string body = response.GetResponseReader().ReadToEnd(); if (response.ContentType.MediaType == JsonEncoded || response.ContentType.MediaType == JsonTextEncoded) { return this.DeserializeFromJson(body); } else if (response.ContentType.MediaType == HttpFormUrlEncoded || response.ContentType.MediaType == PlainTextEncoded) { return HttpUtility.ParseQueryString(body).ToDictionary(); } else { throw ErrorUtilities.ThrowProtocol("Unexpected response Content-Type {0}", response.ContentType.MediaType); } }
protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { throw new NotImplementedException("ReadFromResponseInternal"); }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { Requires.NotNull(response, "response"); throw new NotImplementedException(); }
/// <summary> /// Validates the XML digital signature on an XRDS document. /// </summary> /// <param name="document">The XRDS document whose signature should be validated.</param> /// <param name="identifier">The identifier under discovery.</param> /// <param name="response">The response.</param> /// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param> /// <exception cref="ProtocolException">Thrown if the XRDS document has an invalid or a missing signature.</exception> private static void ValidateXmlDSig(XrdsDocument document, UriIdentifier identifier, IncomingWebResponse response, string signingHost) { Contract.Requires<ArgumentNullException>(document != null); Contract.Requires<ArgumentNullException>(identifier != null); Contract.Requires<ArgumentNullException>(response != null); var signatureNode = document.Node.SelectSingleNode("/xrds:XRDS/ds:Signature", document.XmlNamespaceResolver); ErrorUtilities.VerifyProtocol(signatureNode != null, OpenIdStrings.MissingElement, "Signature"); var signedInfoNode = signatureNode.SelectSingleNode("ds:SignedInfo", document.XmlNamespaceResolver); ErrorUtilities.VerifyProtocol(signedInfoNode != null, OpenIdStrings.MissingElement, "SignedInfo"); ErrorUtilities.VerifyProtocol( signedInfoNode.SelectSingleNode("ds:CanonicalizationMethod[@Algorithm='http://docs.oasis-open.org/xri/xrd/2009/01#canonicalize-raw-octets']", document.XmlNamespaceResolver) != null, "Unrecognized or missing canonicalization method."); ErrorUtilities.VerifyProtocol( signedInfoNode.SelectSingleNode("ds:SignatureMethod[@Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1']", document.XmlNamespaceResolver) != null, "Unrecognized or missing signature method."); var certNodes = signatureNode.Select("ds:KeyInfo/ds:X509Data/ds:X509Certificate", document.XmlNamespaceResolver); ErrorUtilities.VerifyProtocol(certNodes.Count > 0, OpenIdStrings.MissingElement, "X509Certificate"); var certs = certNodes.Cast<XPathNavigator>().Select(n => new X509Certificate2(Convert.FromBase64String(n.Value.Trim()))).ToList(); // Verify that we trust the signer of the certificates. // Start by trying to validate just the certificate used to sign the XRDS document, // since we can do that with partial trust. Logger.OpenId.Debug("Verifying that we trust the certificate used to sign the discovery document."); if (!certs[0].Verify()) { // We couldn't verify just the signing certificate, so try to verify the whole certificate chain. try { Logger.OpenId.Debug("Verifying the whole certificate chain."); VerifyCertChain(certs); Logger.OpenId.Debug("Certificate chain verified."); } catch (SecurityException) { Logger.Yadis.Warn("Signing certificate verification failed and we have insufficient code access security permissions to perform certificate chain validation."); ErrorUtilities.ThrowProtocol(OpenIdStrings.X509CertificateNotTrusted); } } // Verify that the certificate is issued to the host on whom we are performing discovery. string hostName = certs[0].GetNameInfo(X509NameType.DnsName, false); ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), "X.509 signing certificate issued to {0}, but a certificate for {1} was expected.", hostName, signingHost); // Verify the signature itself byte[] signature = Convert.FromBase64String(response.Headers["Signature"]); var provider = (RSACryptoServiceProvider)certs.First().PublicKey.Key; byte[] data = new byte[response.ResponseStream.Length]; response.ResponseStream.Seek(0, SeekOrigin.Begin); response.ResponseStream.Read(data, 0, data.Length); ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), "Invalid XmlDSig signature on XRDS document."); }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { Contract.Requires(response != null); throw new NotImplementedException(); }
/// <summary> /// Called when receiving a direct response message, before deserialization begins. /// </summary> /// <param name="response">The HTTP direct response.</param> /// <param name="message">The newly instantiated message, prior to deserialization.</param> protected override void OnReceivingDirectResponse(IncomingWebResponse response, IDirectResponseProtocolMessage message) { base.OnReceivingDirectResponse(response, message); // Verify that the expected HTTP status code was used for the message, // per OpenID 2.0 section 5.1.2.2. // Note: The v1.1 spec doesn't require 400 responses for some error messages if (message.Version.Major >= 2) { var httpDirectResponse = message as IHttpDirectResponse; if (httpDirectResponse != null) { ErrorUtilities.VerifyProtocol( httpDirectResponse.HttpStatusCode == response.Status, MessagingStrings.UnexpectedHttpStatusCode, (int)httpDirectResponse.HttpStatusCode, (int)response.Status); } } }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { try { return this.keyValueForm.GetDictionary(response.ResponseStream); } catch (FormatException ex) { throw ErrorUtilities.Wrap(ex, ex.Message); } }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { string body = response.GetResponseReader().ReadToEnd(); return HttpUtility.ParseQueryString(body).ToDictionary(); }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { ErrorUtilities.VerifyArgumentNotNull(response, "response"); string body = response.GetResponseReader().ReadToEnd(); return HttpUtility.ParseQueryString(body).ToDictionary(); }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { // We never expect resource servers to send out direct requests, // and therefore won't have direct responses. throw new NotImplementedException(); }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary <string, string> ReadFromResponseCore(IncomingWebResponse response) { Contract.Requires <ArgumentNullException>(response != null); throw new NotImplementedException(); }
private static void ValidateXmlDSig(XrdsDocument document, UriIdentifier identifier, IncomingWebResponse response, string signingHost) { Requires.NotNull(document, "document"); Requires.NotNull(identifier, "identifier"); Requires.NotNull(response, "response"); var signatureNode = document.Node.SelectSingleNode("/xrds:XRDS/ds:Signature", document.XmlNamespaceResolver); ErrorUtilities.VerifyProtocol(signatureNode != null, OpenIdStrings.MissingElement, "Signature"); var signedInfoNode = signatureNode.SelectSingleNode("ds:SignedInfo", document.XmlNamespaceResolver); ErrorUtilities.VerifyProtocol(signedInfoNode != null, OpenIdStrings.MissingElement, "SignedInfo"); ErrorUtilities.VerifyProtocol( signedInfoNode.SelectSingleNode("ds:CanonicalizationMethod[@Algorithm='http://docs.oasis-open.org/xri/xrd/2009/01#canonicalize-raw-octets']", document.XmlNamespaceResolver) != null, OpenIdStrings.UnsupportedCanonicalizationMethod); ErrorUtilities.VerifyProtocol( signedInfoNode.SelectSingleNode("ds:SignatureMethod[@Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1']", document.XmlNamespaceResolver) != null, OpenIdStrings.UnsupportedSignatureMethod); var certNodes = signatureNode.Select("ds:KeyInfo/ds:X509Data/ds:X509Certificate", document.XmlNamespaceResolver); ErrorUtilities.VerifyProtocol(certNodes.Count > 0, OpenIdStrings.MissingElement, "X509Certificate"); var certs = certNodes.Cast<XPathNavigator>().Select(n => new X509Certificate2(Convert.FromBase64String(n.Value.Trim()))).ToList(); VerifyCertificateChain(certs); // Verify that the certificate is issued to the host on whom we are performing discovery. string hostName = certs[0].GetNameInfo(X509NameType.DnsName, false); ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), OpenIdStrings.MisdirectedSigningCertificate, hostName, signingHost); // Verify the signature itself byte[] signature = Convert.FromBase64String(response.Headers["Signature"]); var provider = (RSACryptoServiceProvider)certs.First().PublicKey.Key; byte[] data = new byte[response.ResponseStream.Length]; response.ResponseStream.Seek(0, SeekOrigin.Begin); response.ResponseStream.Read(data, 0, data.Length); ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), OpenIdStrings.InvalidDSig); }
/// <summary> /// Gets the protocol message that may be in the given HTTP response. /// </summary> /// <param name="response">The response that is anticipated to contain an protocol message.</param> /// <returns> /// The deserialized message parts, if found. Null otherwise. /// </returns> /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> protected override IDictionary <string, string> ReadFromResponseCore(IncomingWebResponse response) { Requires.NotNull(response, "response"); throw new NotImplementedException(); }