Beispiel #1
0
        private static StepResult InvalidSignatureResult(string description, ErrorAlias errorAlias, MessagingContext context)
        {
            Logger.Error(description);

            context.ErrorResult = new ErrorResult(description, errorAlias);
            return(StepResult.Failed(context));
        }
        private async Task <StepResult> DecryptAS4MessageAsync(MessagingContext messagingContext)
        {
            try
            {
                Logger.Trace("Start decrypting AS4Message ...");
                X509Certificate2 decryptionCertificate = GetCertificate(messagingContext);
                messagingContext.AS4Message.Decrypt(decryptionCertificate);
                Logger.Info($"{messagingContext.LogTag} AS4Message is decrypted correctly");

                JournalLogEntry entry =
                    JournalLogEntry.CreateFrom(
                        messagingContext.AS4Message,
                        $"Decrypted using certificate {decryptionCertificate.FriendlyName}");

                return(await StepResult
                       .Success(messagingContext)
                       .WithJournalAsync(entry));
            }
            catch (Exception ex) when(ex is CryptoException || ex is CryptographicException)
            {
                Logger.Error(ex);

                messagingContext.ErrorResult = new ErrorResult(
                    description: "Decryption of message failed",
                    alias: ErrorAlias.FailedDecryption);

                Logger.Error(messagingContext.ErrorResult.Description);
                return(StepResult.Failed(messagingContext));
            }
        }
Beispiel #3
0
        /// <summary>
        /// Handle the given <paramref name="response" />, but delegate to the next handler if you can't.
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        public async Task <StepResult> HandleResponse(IAS4Response response)
        {
            if (response.ReceivedAS4Message.IsEmpty)
            {
                if (response.StatusCode == HttpStatusCode.Accepted)
                {
                    response.OriginalRequest.ModifyContext(response.ReceivedAS4Message, MessagingContextMode.Send);
                    return(StepResult.Success(response.OriginalRequest).AndStopExecution());
                }

                Logger.Error($"Response with HTTP status: {response.StatusCode}");

                if (Logger.IsErrorEnabled)
                {
                    using (var r = new StreamReader(response.ReceivedStream.UnderlyingStream))
                    {
                        string content = await r.ReadToEndAsync();

                        if (!string.IsNullOrEmpty(content))
                        {
                            Logger.Error("Response with HTTP content: " + content);
                        }
                    }
                }

                response.OriginalRequest.ModifyContext(response.ReceivedStream, MessagingContextMode.Send);
                return(StepResult.Failed(response.OriginalRequest).AndStopExecution());
            }

            return(await _nextHandler.HandleResponse(response));
        }
Beispiel #4
0
            /// <summary>
            /// Execute the step for a given <paramref name="messagingContext"/>.
            /// </summary>
            /// <param name="messagingContext">Message used during the step execution.</param>
            /// <returns></returns>
            public Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
            {
                var result = new ErrorResult(description: "error", alias: default(ErrorAlias));

                return(Task.FromResult(StepResult.Failed(new HappyContext {
                    ErrorResult = result
                })));
            }
Beispiel #5
0
            public void IsFalseIfStopExecutionIsCalled()
            {
                // Act
                StepResult actualStepResult = StepResult.Failed(new MessagingContext(AS4Message.Empty, MessagingContextMode.Send)).AndStopExecution();

                // Assert
                Assert.False(actualStepResult.CanProceed);
                Assert.False(actualStepResult.Succeeded);
            }
Beispiel #6
0
 public Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
 {
     return(StepResult
            .Failed(messagingContext)
            .WithJournalAsync(
                JournalLogEntry.CreateFrom(
                    messagingContext.AS4Message,
                    "Log entry 3")));
 }
        /// <summary>
        /// Send the <see cref="AS4Message" />
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.ReceivedMessage == null && messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SendAS4MessageStep)} requires a MessagingContext with a ReceivedStream or an AS4Message to correctly send the message");
            }

            if (messagingContext.ReceivedMessage == null && messagingContext.AS4Message.IsPullRequest == false)
            {
                throw new InvalidOperationException(
                          $"{nameof(SendAS4MessageStep)} expects a PullRequest AS4Message when the MessagingContext does not contain a ReceivedStream");
            }

            PushConfiguration pushConfig = GetPushConfiguration(messagingContext.SendingPMode, messagingContext.ReceivingPMode);

            if (pushConfig?.Protocol?.Url == null)
            {
                throw new ConfigurationErrorsException(
                          "Message cannot be send because neither the Sending or Receiving PMode has a Protocol.Url child in a <PushConfiguration/> or <ResponseConfiguration/> element");
            }

            AS4Message as4Message = await DeserializeUnderlyingStreamIfPresentAsync(
                messagingContext.ReceivedMessage,
                otherwise : messagingContext.AS4Message);

            try
            {
                string         contentType = messagingContext.ReceivedMessage?.ContentType ?? messagingContext.AS4Message.ContentType;
                HttpWebRequest request     = CreateWebRequest(pushConfig, contentType.Replace("charset=\"utf-8\"", ""));

                await WriteToHttpRequestStreamAsync(request, messagingContext).ConfigureAwait(false);

                messagingContext.ModifyContext(as4Message);

                return(await HandleHttpResponseAsync(request, messagingContext).ConfigureAwait(false));
            }
            catch
            {
                await UpdateRetryStatusForMessageAsync(messagingContext, SendResult.RetryableFail);

                return(StepResult.Failed(messagingContext).AndStopExecution());
            }
        }
        /// <summary>
        /// Start updating the Data store
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        /// <exception cref="Exception">A delegate callback throws an exception.</exception>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.ReceivedMessage == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SaveReceivedMessageStep)} requires a ReceivedMessage to store the incoming message into the datastore but no ReceivedMessage is present in the MessagingContext");
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SaveReceivedMessageStep)} requires an AS4Message to save but no AS4Message is present in the MessagingContext");
            }

            Logger.Trace($"{messagingContext.LogTag} Store the incoming AS4 Message to the datastore");
            MessagingContext resultContext = await InsertReceivedAS4MessageAsync(messagingContext);

            if (resultContext != null && resultContext.Exception == null)
            {
                /* PullRequests will not be notified, so we don't need a referenced Id,
                 * Receipts and Errors will need to have a referenced UserMessage
                 * if we want to know the original Sending PMode required for the notification. */

                MessageUnit primaryMessageUnit = resultContext.AS4Message.PrimaryMessageUnit;
                if ((primaryMessageUnit is Receipt || primaryMessageUnit is Error) &&
                    string.IsNullOrWhiteSpace(primaryMessageUnit.RefToMessageId))
                {
                    Logger.Warn(
                        $"{messagingContext.LogTag} Received message is a SignalMessage without RefToMessageId. " +
                        "No such SignalMessage are supported so the message cannot be processed any further");

                    return(StepResult
                           .Success(new MessagingContext(AS4Message.Empty, messagingContext.Mode))
                           .AndStopExecution());
                }

                Logger.Trace($"{messagingContext.LogTag} The AS4Message is successfully stored into the datastore");
                return(StepResult.Success(resultContext));
            }

            Logger.Error($"{messagingContext.LogTag} The AS4Message is not stored correctly into the datastore {resultContext?.Exception}");
            return(StepResult.Failed(resultContext));
        }
Beispiel #9
0
        /// <summary>
        /// It is only executed when the external message (received) is an AS4 UserMessage
        /// </summary>
        /// <param name="messagingContext"></param>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(CreateAS4ReceiptStep)} requires an AS4Message to create ebMS Receipts but no AS4Message is present in the MessagingContext");
            }

            bool receiptSigning = messagingContext.ReceivingPMode?.ReplyHandling?.ResponseSigning?.IsEnabled ?? false;
            bool useNRRFormat   = messagingContext.ReceivingPMode?.ReplyHandling?.ReceiptHandling?.UseNRRFormat ?? false;

            if (!receiptSigning && useNRRFormat)
            {
                Logger.Error(
                    "Cannot create Non-Repudiation Receipts that aren\'t signed, please change either the "
                    + $"ReceivingPMode {messagingContext.ReceivingPMode.Id} ReplyHandling.ReceiptHandling.UseNRRFormat or the ReplyHandling.ResponseSigning");

                messagingContext.ErrorResult = new ErrorResult(
                    "Cannot create Non-Repudiation Receipts that aren't signed",
                    ErrorAlias.InvalidReceipt);

                return(StepResult.Failed(messagingContext));
            }

            AS4Message receivedMessage = messagingContext.AS4Message;
            AS4Message receiptMessage  = AS4Message.Empty;

            receiptMessage.SigningId = receivedMessage.SigningId;

            foreach (UserMessage userMessage in receivedMessage.UserMessages)
            {
                Receipt receipt = CreateReferencedReceipt(userMessage, receivedMessage, messagingContext.ReceivingPMode);
                receiptMessage.AddMessageUnit(receipt);
            }

            if (Logger.IsInfoEnabled && receiptMessage.MessageUnits.Any())
            {
                Logger.Info($"{messagingContext.LogTag} {receiptMessage.MessageUnits.Count()} Receipt message(s) has been created for received AS4 UserMessages");
            }

            messagingContext.ModifyContext(receiptMessage);
            return(await StepResult.SuccessAsync(messagingContext));
        }
        /// <summary>
        /// Decompress any Attachments
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(DecompressAttachmentsStep)} requires a AS4Message but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.ReceivedMessageMustBeForwarded)
            {
                Logger.Debug("No decompression will happen because the incoming AS4Message must be forwarded unchanged");
                return(StepResult.Success(messagingContext));
            }

            if (messagingContext.AS4Message.HasAttachments == false)
            {
                Logger.Debug("No decompression will happen because the AS4Message hasn't got any attachments to decompress");
                return(StepResult.Success(messagingContext));
            }

            if (messagingContext.AS4Message.IsEncrypted)
            {
                Logger.Warn("Incoming attachmets are still encrypted will fail to decompress correctly");
            }

            try
            {
                messagingContext.AS4Message.DecompressAttachments();
                Logger.Info("(Receive) AS4Message is decompressed correctly");

                JournalLogEntry entry =
                    JournalLogEntry.CreateFrom(
                        messagingContext.AS4Message,
                        $"Decompressed {messagingContext.AS4Message.Attachments.Count()} with GZip compression");

                return(await StepResult
                       .Success(messagingContext)
                       .WithJournalAsync(entry));
            }
            catch (Exception exception)
                when(exception is ArgumentException ||
                     exception is ObjectDisposedException ||
                     exception is InvalidDataException)
                {
                    var description = "Decompression failed due to an exception";

                    if (messagingContext.AS4Message.IsEncrypted)
                    {
                        Logger.Error(
                            "Decompression failed because the incoming attachments are still encrypted. "
                            + "Make sure that you specify <Decryption/> information in the <Security/> element of the "
                            + "ReceivingPMode so the attachments are first decrypted before decompressed");

                        description = "Decompression failed because the incoming attachments are still encrypted";
                    }

                    messagingContext.ErrorResult = new ErrorResult(
                        description,
                        ErrorAlias.DecompressionFailure);

                    return(StepResult.Failed(messagingContext));
                }
        }
        /// <summary>
        /// Start uploading the AS4 Message Payloads
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.DeliverMessage == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(UploadAttachmentsStep)} requires a DeliverMessage to upload the attachments from but no DeliverMessage is present in the MessagingContext");
            }

            DeliverMessageEnvelope deliverEnvelope = messagingContext.DeliverMessage;

            if (!deliverEnvelope.Attachments.Any())
            {
                Logger.Debug("(Deliver) No attachments to upload for DeliverMessage");
                return(StepResult.Success(messagingContext));
            }

            if (messagingContext.ReceivingPMode == null)
            {
                throw new InvalidOperationException(
                          "Unable to send DeliverMessage: no ReceivingPMode is set");
            }

            if (messagingContext.ReceivingPMode.MessageHandling?.DeliverInformation?.PayloadReferenceMethod == null)
            {
                throw new InvalidOperationException(
                          $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} "
                          + "does not contain any <PayloadReferenceMethod/> element in the MessageHandling.Deliver element. "
                          + "Please provide a correct <PayloadReferenceMethod/> tag to indicate where the attachments of the DeliverMessage should be sent to.");
            }

            if (messagingContext.ReceivingPMode.MessageHandling.DeliverInformation.PayloadReferenceMethod.Type == null)
            {
                throw new InvalidOperationException(
                          $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} "
                          + "does not contain any <Type/> element in the MessageHandling.Deliver.PayloadReferenceMethod element "
                          + "that indicates which uploading strategy that must be used."
                          + "Default uploading strategies are: 'FILE' and 'HTTP'. See 'Deliver Uploading' for more information");
            }

            IAttachmentUploader uploader = GetAttachmentUploader(messagingContext.ReceivingPMode);
            var results = new Collection <UploadResult>();

            foreach (Attachment att in deliverEnvelope.Attachments)
            {
                UploadResult result = await TryUploadAttachmentAsync(att, deliverEnvelope, uploader).ConfigureAwait(false);

                results.Add(result);
            }

            SendResult accResult = results
                                   .Select(r => r.Status)
                                   .Aggregate(SendResultUtils.Reduce);

            await UpdateDeliverMessageAccordinglyToUploadResult(
                messageId : deliverEnvelope.Message.MessageInfo?.MessageId,
                status : accResult);

            if (accResult == SendResult.Success)
            {
                return(StepResult.Success(messagingContext));
            }

            return(StepResult.Failed(messagingContext));
        }
        /// <summary>
        /// Start Decrypting <see cref="AS4Message"/>
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(DecryptAS4MessageStep)} requires a AS4Message to decrypt but no AS4Message is present in the MessagingContext");
            }

            if (context.AS4Message.IsSignalMessage)
            {
                Logger.Debug("AS4Message is SignalMessage so will skip decryption since AS4.NET Component only supports encryption of payloads");
                return(StepResult.Success(context));
            }

            if (context.ReceivingPMode?.Security?.Decryption == null)
            {
                Logger.Debug("AS4Message will not be decrypted sicne ReceivingPMode hasn't got a Security.Decryption element");
                return(StepResult.Success(context));
            }

            ReceivingProcessingMode receivePMode = context.ReceivingPMode;

            if (receivePMode.Security.Decryption.Encryption == Limit.Required && !context.AS4Message.IsEncrypted)
            {
                Logger.Error(
                    $"AS4Message is not encrypted but ReceivingPMode {receivePMode.Id} requires it. "
                    + $"{Environment.NewLine} Please alter the PMode Decryption.Encryption element to Allowed or Ignored");

                context.ErrorResult = new ErrorResult("AS4Message is not encrypted but ReceivingPMode requires it", ErrorAlias.PolicyNonCompliance);
                return(StepResult.Failed(context));
            }

            if (receivePMode.Security.Decryption.Encryption == Limit.NotAllowed && context.AS4Message.IsEncrypted)
            {
                Logger.Error(
                    $"AS4Message is encrypted but ReceivingPMode {receivePMode.Id} doesn't allow it. " +
                    $"{Environment.NewLine} Please alter the PMode Decryption.Encryption element to Required, Allowed or Ignored");

                context.ErrorResult = new ErrorResult("AS4Message is encrypted but ReceivingPMode doesn't allow it", ErrorAlias.PolicyNonCompliance);
                return(StepResult.Failed(context));
            }

            if (!context.AS4Message.IsEncrypted)
            {
                Logger.Debug("AS4Message is not encrypted so will skip decryption");
                return(StepResult.Success(context));
            }

            if (context.ReceivingPMode?.Security?.Decryption?.Encryption == Limit.Ignored)
            {
                Logger.Debug($"Decryption is ignored in ReceivingPMode {receivePMode.Id}, so no decryption will take place");
                return(StepResult.Success(context));
            }

            return(await DecryptAS4MessageAsync(context).ConfigureAwait(false));
        }
 private static StepResult ValidationFailure(MessagingContext context)
 {
     Logger.Error($"{context.LogTag} AS4Message is not valid: {context.ErrorResult.Description}");
     return(StepResult.Failed(context));
 }
 private static StepResult FailedStepResult(string description, MessagingContext context)
 {
     context.ErrorResult = new ErrorResult(description, ErrorAlias.ProcessingModeMismatch);
     return(StepResult.Failed(context));
 }