Example #1
0
 internal void OnIncomingError(IncomingMessage message, Exception error)
 {
     if (Logger.IsDebugEnabled)
     {
         Logger.Error(this.BuildVerboseErrorMessage("INCOMING", message, error));
     }
     else
     {
         Logger.Error("INCOMING_ERROR {0}", error.Message);
     }
 }
 /// <summary>
 /// To simplify outbound mail sending, SMTP Server allows you to drop new messages into a pickup folder
 /// You don't need to use SmtpClient or some other SMTP client
 /// </summary>
 public void Send(IncomingMessage envelope, string pickupFolder, DirectAddressCollection senders, MDNStandard.NotificationType notificationType)
 {
     if (string.IsNullOrEmpty(pickupFolder))
     {
         throw new ArgumentException("value null or empty", "pickupFolder");
     }
     
     if (senders.IsNullOrEmpty())
     {
         return;
     }
     
     foreach (NotificationMessage notification in this.Produce(envelope, senders.AsMailAddresses(), notificationType))
     {
         string filePath = Path.Combine(pickupFolder, Extensions.CreateUniqueFileName());
         notification.Save(filePath);
     }
 }
        internal void UpdateMdn(IncomingMessage message)
        {
            Debug.Assert(m_settings.HasMdnManager);

            using (MdnMonitorClient client = m_settings.MdnMonitor.CreateMdnMonitorClient())
            {
                var notification = MDNParser.Parse(message.Message);
                var disposition = notification.Disposition;
                var originalMessageId = notification.OriginalMessageID;
                var originalSender = message.Recipients.First().Address;
                var originalRecipient = message.Sender.Address;

                client.Update(
                    new Mdn // extract into MdnMonitorParser
                        {
                            MessageId = originalMessageId,
                            Recipient = originalRecipient,
                            Sender = originalSender,
                            Status = disposition.Notification.ToString()
                        });
            }
        }
Example #4
0
        /// <summary>
        /// Decrypt (optionally) the given message and try to extract signatures
        /// </summary>
        bool DecryptSignatures(IncomingMessage message, X509Certificate2 certificate, out SignedCms signatures, out MimeEntity payload)
        {
            MimeEntity decryptedEntity = null;
            signatures = null;
            payload = null;
            
            if (certificate != null)
            {
                decryptedEntity = m_cryptographer.DecryptEntity(message.GetEncryptedBytes(m_cryptographer), certificate);
            }
            else
            {
                decryptedEntity = message.Message;
            }
            if (decryptedEntity == null)
            {
                return false;
            }

            if (SMIMEStandard.IsContentEnvelopedSignature(decryptedEntity.ParsedContentType))
            {
                signatures = m_cryptographer.DeserializeEnvelopedSignature(decryptedEntity);
                payload = MimeSerializer.Default.Deserialize<MimeEntity>(signatures.ContentInfo.Content);
            }
            else if (SMIMEStandard.IsContentMultipartSignature(decryptedEntity.ParsedContentType))
            {
                SignedEntity signedEntity = SignedEntity.Load(decryptedEntity);
                signatures = m_cryptographer.DeserializeDetachedSignature(signedEntity);
                payload = signedEntity.Content;
            }
            else
            {
                throw new AgentException(AgentError.UnsignedMessage);
            }
            
            return true;
        }
Example #5
0
 void ValidateRoutingHeaders(IncomingMessage message)
 {
     if (!message.AreAddressesInRoutingHeaders(message.DomainRecipients))
     {
         throw new AgentException(AgentError.RecipientMismatch);
     }
 }
Example #6
0
 int CountNotificationsToBeSent(IncomingMessage incoming)
 {
     return m_producer.Produce(incoming).Count();
 }
Example #7
0
        void CollectSignatures(StringBuilder builder, IncomingMessage message)
        {
            if (!message.HasSignatures)
            {
                return;
            }

            SignerInfoCollection allSigners = message.Signatures.SignerInfos;
            foreach (SignerInfo signer in allSigners)
            {
                X509Certificate2 cert = signer.Certificate;
                string output = string.Format(
                    "E/CN={0},ValidFrom={1},ValidTo={2},IssuerName={3},Version={4},Thumbprint={5}",
                    cert.ExtractEmailNameOrName(), 
                    cert.GetEffectiveDateString(), 
                    cert.GetExpirationDateString(), 
                    cert.Issuer,
                    cert.Version,
                    cert.Thumbprint);

                builder.Append("CERT:").AppendLine(output);                
            }
        }
        /// <summary>
        /// Generate external notification messages for failed final destination delivery
        /// </summary>
        /// <param name="envelope"></param>
        /// <param name="recipients">sending failure status for these message recipients</param>
        /// <returns>An DSNmessage</returns>
        public DSNMessage ProduceFailure(IncomingMessage envelope, DirectAddressCollection recipients)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException("envelope");
            }

            if (string.IsNullOrEmpty(m_settings.ProductName))
            {
                throw new ArgumentException("reportingAgentName:AgentSettings:ProductName");  
            }

            DSNPerMessage perMessage = new DSNPerMessage(envelope.Sender.Host, envelope.Message.IDValue);

            //
            // Un-Deliverable recipients
            //
            List<DSNPerRecipient> dsnPerRecipients = envelope.CreatePerRecipientStatus(recipients.AsMailAddresses()
                , m_settings.Text, m_settings.AlwaysAck, DSNStandard.DSNAction.Failed, DSNStandard.DSNStatus.Permanent
                , DSNStandard.DSNStatus.DELIVERY_OTHER).ToList();
            

            DSN dsn = new DSN(perMessage, dsnPerRecipients);

            //Configure and/or dynamic plus refactor
            //TODO: Split messages by domain.  See envelope.Recipients[0] below.
            return envelope.Message.CreateStatusMessage(new MailAddress("Postmaster@" + envelope.Recipients[0].Host), dsn);

        }
Example #9
0
        /// <summary>
        /// Ensure that domain recipients are KNOWN - i.e. registered with the Config System
        /// If not, remove them.
        /// </summary>
        /// <param name="message"></param>
        void VerifyDomainRecipientsRegistered(IncomingMessage message)
        {            
            message.EnsureRecipientsCategorizedByDomain(this.SecurityAgent.Domains);
            if (!message.HasDomainRecipients)
            {
                throw new AgentException(AgentError.NoRecipients);
            }
            
            DirectAddressCollection recipients = message.DomainRecipients;
            if (this.Settings.MaxIncomingDomainRecipients > 0 && recipients.Count > this.Settings.MaxIncomingDomainRecipients)
            {
                throw new AgentException(AgentError.MaxDomainRecipients);
            }

            if (!m_settings.HasAddressManager)
            {
                // Address validation is turned off
                return;
            }

            Address[] resolved = m_configService.GetAddresses(recipients);
            if (resolved.IsNullOrEmpty())
            {
                throw new AgentException(AgentError.NoDomainRecipients);
            }

            // Remove any addresses that could not be resolved
            // Yes, this is currently n^2, but given the typical # of addresses, cost should be insignificant
            int i = 0;
            while (i < recipients.Count)
            {
                DirectAddress recipient = recipients[i];
                int iAddress = Array.FindIndex<Address>(resolved, x => x.Match(recipient));
                if (iAddress >= 0)
                {
                    ++i; // Found
                    recipient.Tag = resolved[iAddress];
                }
                else
                {
                    recipients.RemoveAt(i);
                }
            }
        }
Example #10
0
 /// <summary> 
 /// Decrypts and verifies trust in a signed and encrypted RFC 5322 formatted message, providing a sender and recipient addresses. 
 /// The provided sender and recipient addresses will be used instead of the header information in the <c>messageText</c>. 
 /// </summary> 
 /// <param name="messageText"> 
 /// An RFC 5322 formatted message string. 
 /// </param> 
 /// <param name="recipients"> 
 /// A <see cref="DirectAddressCollection"/> instance representing recipient addresses. 
 /// </param> 
 /// <param name="sender"> 
 /// An <see cref="DirectAddress"/> instance representing the sender address 
 /// </param> 
 /// <returns> 
 /// An <see cref="IncomingMessage"/> instance with the trust verified decrypted and verified message. 
 /// </returns> 
 public IncomingMessage ProcessIncoming(string messageText, DirectAddressCollection recipients, DirectAddress sender)
 {
     IncomingMessage message = new IncomingMessage(messageText, recipients, sender);
     return this.ProcessIncoming(message);                    
 }
 /// <summary>
 /// Generate notification messages (if any) for this source message
 /// </summary>
 /// <param name="envelope"></param>
 /// <returns>An enumeration of notification messages</returns>
 public IEnumerable<NotificationMessage> Produce(IncomingMessage envelope)
 {
     return this.Produce(envelope, envelope.HasDomainRecipients ? envelope.DomainRecipients.AsMailAddresses() : null, MDNStandard.NotificationType.Processed);
 }
Example #12
0
        protected virtual void SendNotifications(IncomingMessage envelope, DirectAddressCollection senders)
        {
            if (!m_settings.InternalMessage.HasPickupFolder || !m_settings.Notifications.AutoResponse)
            {
                return;
            }

            //
            // Its ok if we fail on sending notifications - that should never cause us to not
            // deliver the message
            //
            try
            {
                if(envelope.Message.IsMDN() || envelope.Message.IsDSN())
                {
                    return;
                }
                m_notifications.Send(envelope, m_settings.InternalMessage.PickupFolder, senders, MDNStandard.NotificationType.Processed);
                if(m_settings.Notifications.GatewayIsDestination && envelope.Message.IsTimelyAndReliable())
                {
                    m_notifications.Send(envelope, m_settings.InternalMessage.PickupFolder, senders, MDNStandard.NotificationType.Dispatched);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("While sending notification {0}", ex.ToString());
            }
        }
Example #13
0
 void Notify(IncomingMessage message, Exception ex)
 {
     try
     {
         Action<IncomingMessage, Exception> errorIncoming = ErrorIncoming;
         if (errorIncoming != null)
         {
             errorIncoming(message, ex);
         }
     }
     catch
     {
     }
 }
Example #14
0
        void SendDeliveryStatus(IEnumerable<Route> router, IncomingMessage envelope, DirectAddressCollection routedRecipients)
        {
            if (envelope.Message.IsMDN() || envelope.Message.IsDSN())
            {
                return;
            }
            
            DirectAddressCollection undeliveredRecipients = new DirectAddressCollection();
            
            foreach (var route in router)
            {
               if (route.FailedDelivery)
               {
                   foreach (var routedRecipient in routedRecipients)
                   {
                       if(route.AddressType == routedRecipient.Tag as string)
                       {
                           undeliveredRecipients.Add(routedRecipient);
                       }
                   }
               }
            }

            try
            {
                m_notifications.SendFailure(envelope, m_settings.InternalMessage.PickupFolder, undeliveredRecipients);
            }
            catch (Exception ex)
            {
                Logger.Error("While sending un-secured DSN {0}", ex.Message);
            }
        }
Example #15
0
        void PostProcessIncoming(ISmtpMessage message, IncomingMessage envelope)
        {
            this.CopyMessage(message, m_settings.Incoming);
            
            if (envelope.HasDomainRecipients)
            {
                DirectAddressCollection routedRecipients = new DirectAddressCollection();                
                m_router.Route(message, envelope, routedRecipients); 
                
                this.SendNotifications(envelope, routedRecipients);

                SendDeliveryStatus(m_router, envelope, routedRecipients);
            }
            //
            // Any recipients that were handled by routes are no longer in the DomainRecipients collection (removed)
            // Smtp Server should continue process any domain recipients whose delivery were NOT handled by routes
            //
            if (m_settings.Incoming.EnableRelay && envelope.HasDomainRecipients)
            {
                this.SendNotifications(envelope, envelope.DomainRecipients);
                //
                // We only want the incoming message sent to trusted domain recipients
                // We are not allowing arbitrary relay
                //
                message.SetRcptTo(envelope.DomainRecipients);
                m_diagnostics.LogEnvelopeHeaders(message);
            }
            else
            {
                //
                // SMTP Server need not proceed with delivery because we already routed the message to all domain recipients
                //
                message.Abort();
            }
        }
Example #16
0
 private void OnPostProcessIncoming(IncomingMessage message)
 {
     if (m_settings.HasMdnManager && message.Message.IsMDN())
     {
         m_monitorService.UpdateMdn(message);
     }
 }
Example #17
0
 //-----------------------------
 //
 // Events
 //
 //-----------------------------                
 void Notify(IncomingMessage message, Action<IncomingMessage> eventHandler)
 {
     //
     // exceptions are interpreted as: abort message
     //
     if (eventHandler != null)
     {
         eventHandler(message);
     }
 }
Example #18
0
        /// <summary>
        /// Decrypts and verifies trust in an IncomingMessage instance with signed and encrypted message content.
        /// </summary>
        /// <param name="message">
        /// A <see cref="IncomingMessage"/> instance with signed and encrypted content for decryption and trust verification.
        /// </param>
        /// <returns>
        /// An <see cref="IncomingMessage"/> instance with the trust verified decrypted and verified message. 
        /// </returns>
        public IncomingMessage ProcessIncoming(IncomingMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            try
            {
                message.Validate();

                this.Notify(message, this.PreProcessIncoming);

                this.ProcessMessage(message);

                this.Notify(message, this.PostProcessIncoming);
            }
            catch (Exception error)
            {
                this.Notify(message, error);
                throw;  // rethrow error
            }
            
            return message;
        }
        /// <summary>
        /// To simplify outbound mail sending, SMTP Server allows you to drop new messages into a pickup folder
        /// You don't need to use SmtpClient or some other SMTP client
        /// </summary>
        public void SendFailure(IncomingMessage envelope, string pickupFolder, DirectAddressCollection recipients)
        {
            if (string.IsNullOrEmpty(pickupFolder))
            {
                throw new ArgumentException("value null or empty", "pickupFolder");
            }

            if (recipients.IsNullOrEmpty())
            {
                return;
            }

            if (recipients != null)
            {
                DSNMessage notification = this.ProduceFailure(envelope, recipients);

                string filePath = Path.Combine(pickupFolder, Extensions.CreateUniqueFileName());
                notification.Save(filePath);
            }


            //Or maybe
            //
            // m_router.Route(message, envelope, routedRecipients);  
            // 
            // This would avoid loopback encrypt/decrypt...
            //
            // ISmtpMessage message
            // MessageEnvelope envelope 
            // DirectAddressCollection routedRecipients, but would use DSN in-reply-to:
            //


        }
        public void TestEndToEndTimelyAndReliableStartMdnMonitor()
        {
            CleanMessages(m_agent.Settings);
            m_agent.Settings.InternalMessage.EnableRelay = true;
            m_agent.Settings.Notifications.AutoResponse = true;
            m_agent.Settings.Notifications.AlwaysAck = true;
            m_agent.Settings.MdnMonitor = new ClientSettings();
            m_agent.Settings.MdnMonitor.Url = "http://localhost:6692/MonitorService.svc/Dispositions";

            //
            // Process loopback messages.  Leaves un-encrypted mdns in pickup folder
            // Go ahead and pick them up and Process them as if they where being handled
            // by the SmtpAgent by way of (IIS)SMTP hand off.

            string textMessage = string.Format(TestMessageTimelyAndReliableMissingTo, Guid.NewGuid());


            var sendingMessage = LoadMessage(textMessage);

            Assert.DoesNotThrow(() => RunEndToEndTest(sendingMessage));

            //
            // grab the clear text mdns and delete others.
            //
            bool foundMdns = false;
            foreach (var pickupMessage in PickupMessages())
            {
                string messageText = File.ReadAllText(pickupMessage);
                if (messageText.Contains("disposition-notification"))
                {
                    foundMdns = true;
                    var cdoMessage = LoadMessage(messageText);
                    Assert.DoesNotThrow(() => RunMdnOutBoundProcessingTest(cdoMessage));
                }
            }
            Assert.True(foundMdns);
            //
            // Now the messages are encrypted and can be handled
            // Processed Mdn's will be recorded by the MdnMonitorService
            //
            bool foundFiles = false;
            foreach (var pickupMessage in PickupMessages())
            {
                foundFiles = true;
                string messageText = File.ReadAllText(pickupMessage);
                CDO.Message message = LoadMessage(messageText);
                Assert.DoesNotThrow(() => RunMdnInBoundProcessingTest(message));
                
                TestMdnsInProcessedStatus(message, true);
            }
            Assert.True(foundFiles);

            //
            // Prepare a Dispatched MDN manually as if this was a edge client
            //

            //
            // Original message needed to create RequestNotification which is 
            // needed to use the CreateNotificationMessages
            //
            var mailMessage = MailParser.ParseMessage(textMessage);
            mailMessage.RequestNotification();
            textMessage = mailMessage.ToString();

            var incoming = new IncomingMessage(textMessage);

            List<NotificationMessage> notificationMessages = GetNotificationMessages(incoming, MDNStandard.NotificationType.Dispatched);
            Assert.True(notificationMessages.Count == 2);
            
            //
            // Simulating a destination client sending a dispatched MDN
            //
            foreach (var notification in notificationMessages)
            {
                TestMdnTimelyAndReliableExtensionField(notification, true);

                var dispatchText = MimeSerializer.Default.Serialize(notification);
                CDO.Message message = LoadMessage(dispatchText);
                
                RunEndToEndTest(message);

                var duplicateMessage = LoadMessage(dispatchText);
                //
                // Prove we cannot send duplicate MDNs.
                //
                RunMdnOutBoundProcessingTest(duplicateMessage);
                VerifyOutgoingMessage(duplicateMessage);         //Encryted Message
                m_agent.ProcessMessage(duplicateMessage);        //Decrypts Message
                //This proves we could not process the message because it is still encrypted
                //Could possibly check to see if it was dropped.  This integration test is getting ugly...
                VerifyOutgoingMessage(duplicateMessage);         //Encryted Message

            }

            m_agent.Settings.InternalMessage.EnableRelay = false;
        }
 /// <summary>
 /// Generate notification messages (if any) for this source message
 /// </summary>
 /// <param name="envelope"></param>
 /// <param name="senders">sending acks on behalf of these message recipients</param>
 /// <param name="notificationType">processed or dispatched</param>
 /// <returns>An enumeration of messages</returns>
 public IEnumerable<NotificationMessage> Produce(IncomingMessage envelope, IEnumerable<MailAddress> senders, MDNStandard.NotificationType notificationType)
 {
     if (envelope == null)
     {
         throw new ArgumentNullException("envelope");
     }              
     if (senders != null && m_settings.AutoResponse)
     {
         IEnumerable<NotificationMessage> notifications = envelope.CreateAcks(senders, m_settings.ProductName, m_settings.Text, m_settings.AlwaysAck, notificationType);
         if (notifications != null)
         {
             foreach (NotificationMessage notification in notifications)
             {
                 yield return notification;
             }
         }
     }
 }
 private List<NotificationMessage> GetNotificationMessages(IncomingMessage incoming, MDNStandard.NotificationType notificationType)
 {
     return incoming.Message.CreateNotificationMessages(
         incoming.Recipients.AsMailAddresses(),
         sender => Notification.CreateAck
                       (
                           new ReportingUserAgent
                               (
                               sender.Host
                               , m_agent.Settings.Notifications.ProductName
                               )
                           , m_agent.Settings.Notifications.Text
                           , notificationType)
         ).ToList();
 }
Example #23
0
 void ProcessMessage(IncomingMessage message)
 {
     if (message.Sender == null)
     {
         throw new AgentException(AgentError.NoSender);
     }            
     if (!message.HasRecipients)
     {
         throw new AgentException(AgentError.NoRecipients);
     }            
     message.EnsureRecipientsCategorizedByDomain(m_managedDomains);
     if (!message.HasDomainRecipients)
     {
         throw new AgentException(AgentError.NoDomainRecipients);
     }            
     //
     // Map each address to its certificates/trust settings
     //
     this.BindAddresses(message);
     //
     // Decrypt the message, extract the signature and original content
     //
     this.DecryptSignedContent(message);
     //
     // The standard requires that the original message be wrapped to protect headers
     //
     message.Message = this.UnwrapMessage(message.Message);
     this.ValidateRoutingHeaders(message);
     //
     // Enforce trust requirements, including checking signatures
     //
     m_trustModel.Enforce(message);
     //
     // Remove any untrusted recipients...
     //
     if (message.HasDomainRecipients)
     {
         message.CategorizeRecipientsByTrust(m_minTrustRequirement);
     }
     if (!message.HasDomainRecipients)
     {
         throw new AgentException(AgentError.NoTrustedRecipients);
     }
     //
     // Some recipients may not trust this message. Remove them from the To list to prevent accidental message delivery
     //
     message.UpdateRoutingHeaders();
 }
Example #24
0
 //---------------------------------------------------
 //
 //  Incoming
 //
 //---------------------------------------------------
 
 //
 // Event handler called by the agent
 // Here, if configured, we will verify that addresses are real. We don't always have to do that, especially if
 // say we are running as PURELY a gateway. However, if we are set up to e.g. route messages, then...
 //
 void OnPreProcessIncoming(IncomingMessage message)
 {
     this.VerifyDomainRecipientsRegistered(message);
 }
        public void TestMissingMdn()
        {
            CleanMessages(m_agent.Settings);
            m_agent.Settings.InternalMessage.EnableRelay = true;
            m_agent.Settings.Notifications.AutoResponse = true;
            m_agent.Settings.Notifications.AlwaysAck = true;
            m_agent.Settings.MdnMonitor = new ClientSettings();
            m_agent.Settings.MdnMonitor.Url = "http://localhost:6692/MonitorService.svc/Dispositions";

            string textMessage = string.Format(TestMessageTimelyAndReliableMissingTo, Guid.NewGuid());
            //
            // RequestNotification needed to use the CreateNotificationMessages
            //
            var mailMessage = MailParser.ParseMessage(textMessage);
            mailMessage.RequestNotification();
            textMessage = mailMessage.ToString();
            var incoming = new IncomingMessage(textMessage);

            List<NotificationMessage> notificationMessages = GetNotificationMessages(incoming, MDNStandard.NotificationType.Processed);
            Assert.True(notificationMessages.Count == 2);
            RunMdnProcessingForMissingStart(notificationMessages);

            notificationMessages = GetNotificationMessages(incoming, MDNStandard.NotificationType.Dispatched);
            Assert.True(notificationMessages.Count == 2);
            RunMdnProcessingForMissingStart(notificationMessages);
            
            notificationMessages = GetNotificationMessages(incoming, MDNStandard.NotificationType.Failed);
            Assert.True(notificationMessages.Count == 2);
            RunMdnProcessingForMissingStart(notificationMessages);

            notificationMessages = GetNotificationMessages(incoming, MDNStandard.NotificationType.Displayed); //No currently using.
            Assert.True(notificationMessages.Count == 2);
            RunMdnProcessingForMissingStart(notificationMessages);

            notificationMessages = GetNotificationMessages(incoming, MDNStandard.NotificationType.Deleted); //No currently using.
            Assert.True(notificationMessages.Count == 2);
            RunMdnProcessingForMissingStart(notificationMessages);


            m_agent.Settings.InternalMessage.EnableRelay = false;
        }
Example #26
0
 void BindAddresses(IncomingMessage message)
 {
     //
     // Bind each recpient's certs and trust settings
     //
     DirectAddressCollection recipients = message.DomainRecipients;
     for (int i = 0, count = recipients.Count; i < count; ++i)
     {
         DirectAddress recipient = recipients[i];
         recipient.Certificates = this.ResolvePrivateCerts(recipient, m_encryptionEnabled);
         recipient.TrustAnchors = m_trustAnchors.IncomingAnchors.GetCertificates(recipient);
     }
 }
Example #27
0
 internal void ProcessEndToEnd(SmtpAgent agent, Message msg, out OutgoingMessage outgoing, out IncomingMessage incoming)
 {
     outgoing = agent.SecurityAgent.ProcessOutgoing(new MessageEnvelope(msg));
     incoming = agent.SecurityAgent.ProcessIncoming(new MessageEnvelope(outgoing.SerializeMessage()));            
 }
Example #28
0
 void DecryptSignedContent(IncomingMessage message)
 {
     SignedCms signatures = null;
     MimeEntity payload = null;
     bool success = false;
     
     
     if (m_encryptionEnabled)
     {
         //
         // This can be optimized for multiple private keys and recipients where the same certs
         // are shared across recipients (org certs). But we will start with the easy to understand simple version
         //            
         // Decrypt and parse message body into a signature entity - the envelope that contains our data + signature
         // If we fail to decrypt for any recipient, we are going to treat the message as possibly compromised and reject
         // it entirely
         //
         foreach(DirectAddress recipient in message.DomainRecipients)
         {
             success = false;
             signatures = null;
             payload = null;                    
             success = this.DecryptSignedContent(message, recipient, out signatures, out payload);
             if (!success)
             {
                 // Any failures.. stop immediately. If we could not decrypt the message for any recipient,
                 // then the message is suspicious and is rejected
                 break;
             }
         }
     }
     else
     {
         success = this.DecryptSignatures(message, null, out signatures, out payload);
     }            
     if (!success)
     {
         throw new AgentException(AgentError.InvalidEncryption);
     }
     
     if (signatures == null || payload == null)
     {
         throw new AgentException(AgentError.UntrustedMessage);
     }
     
     message.Signatures = signatures;
     //
     // Alter body to contain actual content. Also clean up mime headers on the message that were there to support
     // signatures etc
     //
     HeaderCollection headers = message.Message.Headers;
     message.Message.Headers = headers.SelectNonMimeHeaders();
     message.Message.UpdateBody(payload); // this will merge in content + content specific mime headers
 }
Example #29
0
 bool DecryptSignedContent(IncomingMessage message, DirectAddress recipient, out SignedCms signatures, out MimeEntity payload)
 {
     signatures = null;
     payload = null;
     foreach (X509Certificate2 cert in recipient.Certificates)
     {
         try
         {
             if (this.DecryptSignatures(message, cert, out signatures, out payload))
             {
                 // Decrypted and extracted signatures successfully
                 return true;
             }
         }
         catch(Exception ex)
         {
             this.Notify(message, ex);
         }
     }
     
     return false;
 }
Example #30
0
        MessageSignature FindTrustedSignature(IncomingMessage message, MailAddress recipient, X509Certificate2Collection anchors)
        {
            DirectAddress sender = message.Sender;
            MessageSignatureCollection signatures = message.SenderSignatures;
            MessageSignature lastTrustedSignature = null;

            foreach (MessageSignature signature in signatures)
            {
                bool certTrustedAndInPolicy =
                    (m_certChainValidator.IsTrustedCertificate(signature.Certificate, anchors) &&
                     signature.CheckSignature());
                if (certTrustedAndInPolicy && recipient != null)
                {
                    certTrustedAndInPolicy = IsCertPolicyCompliant(recipient, signature.Certificate);
                }

                if (certTrustedAndInPolicy)
                {

                    if (!sender.HasCertificates)
                    {
                        // Can't really check thumbprints etc. So, this is about as good as its going to get
                        return signature;
                    }

                    if (signature.CheckThumbprint(sender))
                    {
                        return signature;
                    }
                    //
                    // We'll save this guy, but keep looking for a signer whose thumbprint we can verify
                    // If we can't find one, we'll use the last trusted signer we found.. and just mark the recipient's trust
                    // enforcement status as Success_ThumbprintMismatch
                    //
                    lastTrustedSignature = signature;
                }
            }
            return lastTrustedSignature;
        }