/// <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)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(VerifyPullRequestAuthorizationStep)} requires a MessagingContext with a AS4Message to verify the PullRequest");
            }

            AS4Message as4Message = messagingContext.AS4Message;

            var authorizationMap = new PullAuthorizationMapService(_pullAuthorizationMapProvider);

            if (authorizationMap.IsPullRequestAuthorized(as4Message))
            {
                return(StepResult.SuccessAsync(messagingContext));
            }

            string mpc = (as4Message.FirstSignalMessage as PullRequest)?.Mpc ?? string.Empty;

            throw new SecurityException(
                      $"{messagingContext.LogTag} PullRequest for MPC {mpc} is not authorized. " +
                      "Either change the PullRequest MPC or add the MPC value to the authorization map");
        }
Пример #2
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 Task <StepResult> HandleResponse(IAS4Response response)
        {
            response.OriginalRequest.ModifyContext(response.ReceivedStream, response.OriginalRequest.Mode);
            response.OriginalRequest.ModifyContext(response.ReceivedAS4Message);

            return(StepResult.SuccessAsync(response.OriginalRequest));
        }
Пример #3
0
        /// <summary>
        /// Start creating a <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.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(CreateDefaultAS4MessageStep)} requires an AS4Message to assign the default UserMessage to but no AS4Message is present in the MessagingContext");
            }

            SendingProcessingMode pmode = _config.GetSendingPMode(DefaultPmode);

            IEnumerable <PartInfo> parts =
                messagingContext.AS4Message.Attachments.Select(PartInfo.CreateFor);

            UserMessage userMessage =
                SendingPModeMap.CreateUserMessage(pmode, parts.ToArray());

            messagingContext.AS4Message.AddMessageUnit(userMessage);
            messagingContext.SendingPMode = pmode;

            Logger.Info($"{messagingContext.LogTag} Default AS4Message is created using SendingPMode {pmode.Id}");
            return(await StepResult.SuccessAsync(messagingContext));
        }
Пример #4
0
        /// <summary>
        /// Execute the step for a given <paramref name="messagingContext"/>.
        /// </summary>
        /// <param name="messagingContext">The Message used during the step execution.</param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext?.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(StoreAS4MessageStep)} requires an AS4Message to save but no AS4Message is present in the MessagingContext");
            }

            Logger.Trace("Storing the AS4Message with Operation=ToBeProcessed...");
            using (DatastoreContext context = _createContext())
            {
                var repository = new DatastoreRepository(context);
                var service    = new OutMessageService(_config, repository, _messageBodyStore);
                service.InsertAS4Message(
                    messagingContext.AS4Message,
                    messagingContext.SendingPMode,
                    messagingContext.ReceivingPMode);

                try
                {
                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
                catch
                {
                    messagingContext.ErrorResult = new ErrorResult(
                        "Unable to store the received message due to an exception occured during the saving operation",
                        ErrorAlias.Other);

                    throw;
                }
            }

            Logger.Trace("Stored the AS4Message with Operation=ToBeProcesed");
            return(await StepResult.SuccessAsync(messagingContext));
        }
Пример #5
0
        /// <summary>
        /// Sign 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.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SignAS4MessageStep)} requires an AS4Message to sign but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.AS4Message.IsEmpty)
            {
                Logger.Debug("No signing will be performed on the message because it's empty");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            Signing signInfo = RetrieveSigningInformation(
                messagingContext.AS4Message,
                messagingContext.SendingPMode,
                messagingContext.ReceivingPMode);

            if (signInfo == null)
            {
                Logger.Trace("No signing will be performend on the message because no signing information was found in either Sending or Receiving PMode");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            if (signInfo.IsEnabled == false)
            {
                Logger.Trace("No signing will be performend on the message because the PMode siging information is disabled");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            Logger.Info($"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Sign AS4Message with given signing information of the PMode");

            X509Certificate2 certificate = RetrieveCertificate(signInfo);
            var settings =
                new CalculateSignatureConfig(
                    signingCertificate: certificate,
                    referenceTokenType: signInfo.KeyReferenceMethod,
                    signingAlgorithm: signInfo.Algorithm,
                    hashFunction: signInfo.HashFunction);

            SignAS4Message(settings, messagingContext.AS4Message);

            JournalLogEntry logEntry = JournalLogEntry.CreateFrom(
                messagingContext.AS4Message,
                $"Signed with certificate {settings.SigningCertificate.FriendlyName} and reference {settings.ReferenceTokenType} "
                + $"using algorithm {settings.SigningAlgorithm} and hash {settings.HashFunction}");

            return(await StepResult
                   .Success(messagingContext)
                   .WithJournalAsync(logEntry));
        }
        /// <summary>
        /// Start Encrypting AS4 Message
        /// </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(EncryptAS4MessageStep)} requires an AS4Message to encrypt but no AS4Message is present in the MessagingContext");
            }

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

            if (messagingContext.SendingPMode.Security?.Encryption == null ||
                messagingContext.SendingPMode.Security.Encryption.IsEnabled == false)
            {
                Logger.Trace(
                    "No encryption of the AS4Message will happen because the " +
                    $"SendingPMode {messagingContext.SendingPMode?.Id} Security.Encryption.IsEnabled is disabled");

                return(await StepResult.SuccessAsync(messagingContext));
            }

            Logger.Info(
                $"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Encrypt AS4Message with given encryption information " +
                $"configured in the SendingPMode: {messagingContext.SendingPMode.Id}");

            KeyEncryptionConfiguration keyEncryptionConfig = RetrieveKeyEncryptionConfig(messagingContext.SendingPMode);
            Encryption encryptionSettings   = messagingContext.SendingPMode.Security.Encryption;
            var        dataEncryptionConfig = new DataEncryptionConfiguration(
                encryptionMethod: encryptionSettings.Algorithm,
                algorithmKeySize: encryptionSettings.AlgorithmKeySize);

            EncryptAS4Message(
                messagingContext.AS4Message,
                keyEncryptionConfig,
                dataEncryptionConfig);

            var journal = JournalLogEntry.CreateFrom(
                messagingContext.AS4Message,
                $"Encrypted using certificate {keyEncryptionConfig.EncryptionCertificate.FriendlyName} and "
                + $"key encryption method: {keyEncryptionConfig.EncryptionMethod}, key digest method: {keyEncryptionConfig.DigestMethod}, "
                + $"key mgf: {keyEncryptionConfig.Mgf} and Data encryption method: {dataEncryptionConfig.EncryptionMethod}, "
                + $" data encryption type: {dataEncryptionConfig.EncryptionType}, data transport algorithm: {dataEncryptionConfig.TransformAlgorithm}");

            return(await StepResult
                   .Success(messagingContext)
                   .WithJournalAsync(journal));
        }
Пример #7
0
        /// <summary>
        /// Validates whether the configured Sending PMode is valid and can be used.
        /// </summary>
        /// <param name="messagingContext">Message used during the step execution.</param>
        /// <returns></returns>
        public Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            var result = SendingProcessingModeValidator.Instance.Validate(messagingContext.SendingPMode);

            if (result.IsValid)
            {
                return(StepResult.SuccessAsync(messagingContext));
            }

            string description = result.AppendValidationErrorsToErrorMessage($"Sending PMode {messagingContext.SendingPMode.Id} was invalid:");

            return(StepResult.FailedAsync(new MessagingContext(new ConfigurationErrorsException(description))));
        }
        /// <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)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.ReceivedMessage == null)
            {
                throw new NotSupportedException(
                          "DetermineRoutingStep requires a 'ReceivedMessage'");
            }

            if (messagingContext.ReceivingPMode == null)
            {
                throw new InvalidOperationException(
                          "No ReceivingPMode available is set." +
                          "The ReceivingPMode is used to correctly forward the message with the provided configured values inside this PMode.");
            }

            if (messagingContext.ReceivingPMode.MessageHandling?.ForwardInformation == null)
            {
                throw new ConfigurationErrorsException(
                          "The ReceivingPMode does not contain a MessageHandling.Forward element." +
                          "This element is required in a Forwarding scenario.");
            }

            string sendingPModeId = messagingContext.ReceivingPMode.MessageHandling.ForwardInformation.SendingPMode;

            Logger.Trace($"SendingPMode {sendingPModeId} must be used to forward Message with Id {messagingContext.EbmsMessageId}");

            if (String.IsNullOrWhiteSpace(sendingPModeId))
            {
                throw new ConfigurationErrorsException(
                          "The ReceivingPMode does not contain a SendingPMode-Id in the MessageHandling.Forward element." +
                          "This SendingPMode-Id is required in a Forwarding scenario and will be used to forward the message to the next MSH.");
            }

            SendingProcessingMode sendingPMode = _configuration.GetSendingPMode(sendingPModeId);

            if (sendingPMode == null)
            {
                throw new ConfigurationErrorsException(
                          $"No Sending Processing Mode found for {sendingPModeId}." +
                          "Please provide a valid Id that points to a configured Sending PMode." +
                          @"SendingPModes are configured in the .\config\send-pmodes\ folder.");
            }

            messagingContext.SendingPMode = sendingPMode;
            return(StepResult.SuccessAsync(messagingContext));
        }
Пример #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>
        /// Retrieve the PMode that must be used to send the SubmitMessage that is in the current Messagingcontext />
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.SubmitMessage == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(RetrieveSendingPModeStep)} requires an SubmitMessage to retrieve the SendingPMode from but no SubmitMessage is present in the MessagingContext");
            }

            messagingContext.SubmitMessage.PMode = RetrieveSendPMode(messagingContext);
            messagingContext.SendingPMode        = messagingContext.SubmitMessage.PMode;

            return(await StepResult.SuccessAsync(messagingContext));
        }
Пример #11
0
        /// <summary>
        /// Start creating <see cref="Error"/>
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        /// <exception cref="System.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.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(CreateAS4ErrorStep)} requires an AS4Message to create an Error but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.AS4Message.IsEmpty && messagingContext?.ErrorResult == null)
            {
                Logger.Warn("Skip creating AS4 Error because AS4Message and ErrorResult is empty in the MessagingContext");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            ErrorResult errorResult = messagingContext.ErrorResult;

            AS4Message errorMessage = CreateAS4ErrorWithPossibleMultihop(received: messagingContext.AS4Message,
                                                                         occurredError: errorResult);

            if (errorResult != null)
            {
                Logger.Error($"AS4 Error(s) created with {errorResult.Code.GetString()} {errorResult.Alias}, {errorResult.Description}");

                await InsertInExceptionsForNowExceptionedInMessageAsync(
                    messagingContext.AS4Message.SignalMessages,
                    messagingContext.ErrorResult,
                    messagingContext.ReceivingPMode);
            }

            messagingContext.ModifyContext(errorMessage);

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

            return(await StepResult.SuccessAsync(messagingContext));
        }
Пример #12
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)
 {
     return(StepResult.SuccessAsync(messagingContext));
 }
Пример #13
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 Task <StepResult> HandleResponse(IAS4Response response)
        {
            IsCalled = true;

            return(StepResult.SuccessAsync(new MessagingContext(response.ReceivedStream, MessagingContextMode.Send)));
        }
Пример #14
0
 public Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
 {
     return(StepResult.SuccessAsync(new MessagingContext(AS4Message.Empty, MessagingContextMode.Submit)));
 }
        /// <summary>
        /// Execute the step for a given <paramref name="context"/>.
        /// </summary>
        /// <param name="context">Message used during the step execution.</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(ValidateAS4MessageStep)} requires an AS4Message to validate but no AS4Message is present in the MessagingContext");
            }

            Logger.Trace("Validating the received AS4Message ...");
            if (SoapBodyIsNotEmpty(context.AS4Message))
            {
                context.ErrorResult = SoapBodyAttachmentsNotSupported();
                return(ValidationFailure(context));
            }

            IEnumerable <PartInfo> notSupportedPartInfos =
                context.AS4Message.UserMessages.SelectMany(
                    message => message.PayloadInfo.Where(payload => payload.Href.StartsWith("cid:") == false));

            if (notSupportedPartInfos.Any())
            {
                context.ErrorResult = ExternalPayloadError(notSupportedPartInfos);
                return(ValidationFailure(context));
            }

            if (context.AS4Message.IsUserMessage)
            {
                AS4Message message = context.AS4Message;

                IEnumerable <PartInfo> unreferencedPartInfos =
                    message.UserMessages
                    .SelectMany(u => u.PayloadInfo)
                    .Where(p => message.Attachments.FirstOrDefault(a => a.Matches(p)) == null);

                if (unreferencedPartInfos.Any())
                {
                    context.ErrorResult = AttachmentNotFoundInvalidHeaderError(unreferencedPartInfos);
                    return(ValidationFailure(context));
                }

                IEnumerable <IGrouping <string, PartInfo> > duplicatePartInfos =
                    message.UserMessages
                    .SelectMany(u => u.PayloadInfo)
                    .GroupBy(p => p.Href)
                    .Where(g => g.Count() != 1);

                if (duplicatePartInfos.Any())
                {
                    context.ErrorResult = DuplicateAttachmentInvalidHeaderError(duplicatePartInfos);
                    return(ValidationFailure(context));
                }
            }

            Logger.Trace($"{context.LogTag} Received AS4Message is valid");
            return(await StepResult.SuccessAsync(context));
        }