/// <summary> /// Puts binding elements in their correct outgoing message processing order. /// </summary> /// <param name="protection1">The first protection type to compare.</param> /// <param name="protection2">The second protection type to compare.</param> /// <returns> /// -1 if <paramref name="element1"/> should be applied to an outgoing message before <paramref name="element2"/>. /// 1 if <paramref name="element2"/> should be applied to an outgoing message before <paramref name="element1"/>. /// 0 if it doesn't matter. /// </returns> private static int BindingElementOutgoingMessageApplicationOrder(MessageProtections protection1, MessageProtections protection2) { ErrorUtilities.VerifyInternal(protection1 != MessageProtections.None || protection2 != MessageProtections.None, "This comparison function should only be used to compare protection binding elements. Otherwise we change the order of user-defined message transformations."); // Now put the protection ones in the right order. return(-((int)protection1).CompareTo((int)protection2)); // descending flag ordinal order }
/// <summary> /// Verifies the integrity and applicability of an incoming message. /// </summary> /// <param name="message">The message just received.</param> /// <exception cref="ProtocolException"> /// Thrown when the message is somehow invalid. /// This can be due to tampering, replay attack or expiration, among other things. /// </exception> protected virtual void VerifyMessageAfterReceiving(IProtocolMessage message) { Debug.Assert(message != null, "message == null"); if (Logger.IsDebugEnabled) { Logger.DebugFormat( "Preparing to receive {0} ({1}) message:{2}{3}", message.GetType().Name, message.Version, Environment.NewLine, new MessageDictionary(message).ToStringDeferred()); } MessageProtections appliedProtection = MessageProtections.None; foreach (IChannelBindingElement bindingElement in this.incomingBindingElements) { if (bindingElement.PrepareMessageForReceiving(message)) { Logger.DebugFormat("Binding element {0} applied to message.", bindingElement.GetType().FullName); // Ensure that only one protection binding element applies to this message // for each protection type. ErrorUtilities.VerifyInternal((appliedProtection & bindingElement.Protection) == 0, MessagingStrings.TooManyBindingsOfferingSameProtection, bindingElement.Protection); appliedProtection |= bindingElement.Protection; } else { Logger.DebugFormat("Binding element {0} did not apply to message.", bindingElement.GetType().FullName); } } // Ensure that the message's protection requirements have been satisfied. if ((message.RequiredProtection & appliedProtection) != message.RequiredProtection) { throw new UnprotectedMessageException(message, appliedProtection); } // Give the message a chance to do custom serialization. IMessageWithEvents eventedMessage = message as IMessageWithEvents; if (eventedMessage != null) { eventedMessage.OnReceiving(); } // We do NOT verify that all required message parts are present here... the // message deserializer did for us. It would be too late to do it here since // they might look initialized by the time we have an IProtocolMessage instance. message.EnsureValidMessage(); }
public void Deserialize(T message, IProtocolMessage containingMessage, string value, string messagePartName) { Requires.NotNull(message, "message"); Requires.NotNull(containingMessage, "containingMessage"); Requires.NotNullOrEmpty(value, "value"); Requires.NotNullOrEmpty(messagePartName, "messagePartName"); string symmetricSecretHandle = null; if (this.encrypted && this.cryptoKeyStore != null) { string valueWithoutHandle; MessagingUtilities.ExtractKeyHandleAndPayload(containingMessage, messagePartName, value, out symmetricSecretHandle, out valueWithoutHandle); value = valueWithoutHandle; } message.ContainingMessage = containingMessage; byte[] data = MessagingUtilities.FromBase64WebSafeString(value); byte[] signature = null; if (this.signed) { using (var dataStream = new MemoryStream(data)) { var dataReader = new BinaryReader(dataStream); signature = dataReader.ReadBuffer(); data = dataReader.ReadBuffer(); } // Verify that the verification code was issued by message authorization server. ErrorUtilities.VerifyProtocol(this.IsSignatureValid(data, signature, symmetricSecretHandle), MessagingStrings.SignatureInvalid); } if (this.encrypted) { data = this.Decrypt(data, symmetricSecretHandle); } if (this.compressed) { data = MessagingUtilities.Decompress(data); } this.DeserializeCore(message, data); message.Signature = signature; // TODO: we don't really need this any more, do we? if (this.maximumAge.HasValue) { // Has message verification code expired? DateTime expirationDate = message.UtcCreationDate + this.maximumAge.Value; if (expirationDate < DateTime.UtcNow) { throw new ExpiredMessageException(expirationDate, containingMessage); } } // Has message verification code already been used to obtain an access/refresh token? if (this.decodeOnceOnly != null) { ErrorUtilities.VerifyInternal(this.maximumAge.HasValue, "Oops! How can we validate a nonce without a maximum message age?"); string context = "{" + GetType().FullName + "}"; if (!this.decodeOnceOnly.StoreNonce(context, Convert.ToBase64String(message.Nonce), message.UtcCreationDate)) { Logger.OpenId.ErrorFormat("Replayed nonce detected ({0} {1}). Rejecting message.", message.Nonce, message.UtcCreationDate); throw new ReplayedMessageException(containingMessage); } } ((IMessage)message).EnsureValidMessage(); }