/// <summary>
        /// Requests message processing from the current sink.
        /// </summary>
        /// <param name="sinkStack">A stack of channel sinks that called the current sink.</param>
        /// <param name="requestMsg">The message that contains the request.</param>
        /// <param name="requestHeaders">Headers retrieved from the incoming message from the client.</param>
        /// <param name="requestStream">The stream that needs to be to processed and passed on to the deserialization sink.</param>
        /// <param name="responseMsg">When this method returns, contains a <see cref="T:System.Runtime.Remoting.Messaging.IMessage" /> that holds the response message. This parameter is passed uninitialized.</param>
        /// <param name="responseHeaders">When this method returns, contains a <see cref="T:System.Runtime.Remoting.Channels.ITransportHeaders" /> that holds the headers that are to be added to return message heading to the client. This parameter is passed uninitialized.</param>
        /// <param name="responseStream">When this method returns, contains a <see cref="T:System.IO.Stream" /> that is heading back to the transport sink. This parameter is passed uninitialized.</param>
        public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            // Read secure transaction identifier from request headers
            string strTransactID = (string)requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_ID];
            Guid transactID = (strTransactID == null ? Guid.Empty : new Guid(strTransactID));

            // Read current transaction step and client IP address from request headers
            SecureTransactionStage transactionStage = (SecureTransactionStage)Convert.ToInt32((string)requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE]);
            IPAddress clientAddress = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;

            // Put current channel sink to the sink stack so AsyncProcessResponse can be called asynchronously if necessary order
            sinkStack.Push(this, null);
            ServerProcessing processingResult;

            try
            {
                switch (transactionStage)
                {
                    case SecureTransactionStage.SendingPublicKey: // Client sends the public key to the server

                        // Generate shared key and encrypt with the public key of the client
                        processingResult = MakeSharedKey(transactID, requestHeaders, out responseMsg, out responseHeaders, out responseStream);

                        break;

                    case SecureTransactionStage.SendingEncryptedMessage: // Client sends the encrypted request message to the server

                        if (IsExistingSecurityTransaction(transactID))
                            processingResult = ProcessEncryptedMessage(transactID, sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
                        else
                            throw new CryptoRemotingException(string.Format(LanguageResource.CryptoRemotingException_InvalidClientRequest, SecureTransactionStage.UnknownTransactionID));

                        break;

                    case SecureTransactionStage.Uninitialized: // Uninitialized, nothing has happened

                        // Check if encryption is not required for this client address
                        if (!RequireEncryption(clientAddress))
                            processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
                        else
                            throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_ServerRequiresEncryption);

                        break;

                    default:

                        throw new CryptoRemotingException(string.Format(LanguageResource.CryptoRemotingException_InvalidClientRequest, transactionStage));
                }
            }
            catch (CryptoRemotingException)
            {
                processingResult = SendEmptyToClient(sinkStack, requestMsg, requestHeaders, requestStream,
                    transactionStage, out responseMsg, out responseHeaders, out responseStream);
                requestMsg = null;
            }

            // Pop the current sink from the sink stack
            sinkStack.Pop(this);
            return processingResult;
        }
Beispiel #2
0
        /// <summary>
        /// Requests asynchronous processing of a response to a method call on the current sink.
        /// </summary>
        /// <param name="sinkStack">A stack of sinks that called this sink.</param>
        /// <param name="state">Information generated on the request side that is associated with this sink.</param>
        /// <param name="headers">The headers retrieved from the server response stream.</param>
        /// <param name="stream">The stream coming back from the transport sink.</param>
        public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream)
        {
            // Gets the asynchronous processing state
            AsyncProcessingState asyncState = (AsyncProcessingState)state;

            try
            {
                SecureTransactionStage currentStage = (SecureTransactionStage)Convert.ToInt32((string)headers[CommonHeaderNames.SECURE_TRANSACTION_STATE]);
                switch (currentStage)
                {
                case SecureTransactionStage.SendingEncryptedResult:                         // Get the encrypted response from the server

                    lock (_lockObject)
                    {
                        if (asyncState.SecureTransactionID.Equals(_secureTransactionID))
                        {
                            stream = DecryptResponse(stream, headers);
                        }
                        else
                        {
                            throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_KeyChanged);
                        }
                    }
                    break;

                case SecureTransactionStage.UnknownTransactionID:                         // Bad transaction identifier

                    throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_InvalidTransactionID);

                default:

                case SecureTransactionStage.Uninitialized:                         // Secure transaction is not yet set up
                    break;
                }
            }
            catch (CryptoRemotingException)
            {
                lock (_lockObject)
                {
                    // If remote transaction identifier matches the local secure transaction identifier, reset the shared key
                    if (_provider == null || asyncState.SecureTransactionID.Equals(_secureTransactionID))
                    {
                        ClearSharedKey();
                    }

                    ProcessMessage(asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream);
                }
            }
            finally
            {
                // Close the input stream
                asyncState.Stream.Close();
            }

            // Pass on to the next sink to continue processing
            sinkStack.AsyncProcessResponse(headers, stream);
        }
Beispiel #3
0
        /// <summary>
        /// Erzeugt eine leere Antwortnachricht.
        /// </summary>
        /// <param name="transactionStage">Art des aktuellen Transaktionsschritts</param>
        /// <param name="responseMsg">Antwort-Nachricht</param>
        /// <param name="responseHeaders">Antwort-Header</param>
        /// <param name="responseStream">Antwort-Datenstrom</param>
        /// <returns>Verarbeitungsstatus</returns>
        private ServerProcessing SendEmptyToClient(SecureTransactionStage transactionStage, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            // Inizialisieren
            responseMsg     = null;
            responseStream  = new MemoryStream();
            responseHeaders = new TransportHeaders();

            // Aktuellen Transaktionsschritt als Antwort-Header schreiben
            responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)transactionStage).ToString();

            // Volständige Verarbeitung zurückmelden
            return(ServerProcessing.Complete);
        }
Beispiel #4
0
        /// <summary>
        /// Creates an empty response message.
        /// </summary>
        /// <param name="sinkStack">The sink stack.</param>
        /// <param name="requestMsg">Request message.</param>
        /// <param name="requestHeaders">Request transport headers.</param>
        /// <param name="requestStream">Request stream.</param>
        /// <param name="transactionStage">Current secure transaction stage.</param>
        /// <param name="responseMsg">Response message.</param>
        /// <param name="responseHeaders">Response transport headers.</param>
        /// <param name="responseStream">Response stream.</param>
        /// <returns></returns>
        private ServerProcessing SendEmptyToClient(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, SecureTransactionStage transactionStage, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            responseMsg    = null;
            requestStream  = new MemoryStream();
            responseStream = new MemoryStream();

            responseHeaders = new TransportHeaders();
            responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)transactionStage).ToString();

            ServerProcessing processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);

            return(processingResult);
        }
Beispiel #5
0
        /// <summary>
        /// Erzeugt eine leere Antwortnachricht.
        /// </summary>
        /// <param name="transactionStage">Art des aktuellen Transaktionsschritts</param>
        /// <param name="responseMsg">Antwort-Nachricht</param>
        /// <param name="responseHeaders">Antwort-Header</param>
        /// <param name="responseStream">Antwort-Datenstrom</param>
        /// <returns>Verarbeitungsstatus</returns>
        private ServerProcessing SendEmptyToClient(SecureTransactionStage transactionStage, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            // Inizialisieren
            responseMsg = null;
            responseStream = new MemoryStream();
            responseHeaders = new TransportHeaders();

            // Aktuellen Transaktionsschritt als Antwort-Header schreiben
            responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)transactionStage).ToString();

            // Volständige Verarbeitung zurückmelden
            return ServerProcessing.Complete;
        }
Beispiel #6
0
        /// <summary>
        /// Verarbeitet eine Antwort-Nachricht asynchron.
        /// </summary>
        /// <param name="sinkStack">Senkenstapel</param>
        /// <param name="state">Asynchroner Verarbeitungsstatus</param>
        /// <param name="headers">Anfrage-Header-Auflistung</param>
        /// <param name="stream">Anfrage-Datenstrom</param>
        public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream)
        {
            // Asychronen Verarbeitungsstatus abrufen
            AsyncProcessingState asyncState = (AsyncProcessingState)state;

            try
            {
                // Aktuellen Verarbeitungsschritt der Sicherheitstransaktion ermitteln
                SecureTransactionStage currentStage = (SecureTransactionStage)Convert.ToInt32((string)headers[CommonHeaderNames.SECURE_TRANSACTION_STATE]);

                // Verarbeitungsschritt auswerten
                switch (currentStage)
                {
                case SecureTransactionStage.SendingEncryptedResult:     // Verschlüsselte Daten vom Server eingtroffen

                    lock (_lockObject)
                    {
                        // Wenn die Antwort auch tatsächlich zur aktuellen Sicherheitstransaktion gehört ...
                        if (asyncState.SecureTransactionID.Equals(_secureTransactionID))
                        {
                            // Datenstrom entschlüsseln
                            stream = DecryptResponse(stream, headers);
                        }
                        // Andernfalls ...
                        else
                        {
                            // Ausnahme werfen
                            throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_KeyChanged);
                        }
                    }
                    break;

                case SecureTransactionStage.UnknownTransactionID:                         // Unbekannte Transaktionskennung

                    // Ausnahme werfen
                    throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_InvalidTransactionID);

                default:

                case SecureTransactionStage.Uninitialized:     // Keine Sicherheitstransaktion eingerichtet
                    break;
                }
            }
            catch (CryptoRemotingException)
            {
                lock (_lockObject)
                {
                    // Wenn die gesendete Transaktionskennung mit der lokalen übereinstimmt ...
                    if (_provider == null || asyncState.SecureTransactionID.Equals(_secureTransactionID))
                    {
                        // Gemeinamen Schlüssel löschen
                        ClearSharedKey();
                    }

                    // Nachricht weiterverarbeiten
                    ProcessMessage(asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream);
                }
            }
            finally
            {
                // Datenstrom schließen
                asyncState.Stream.Close();
            }
            // Verarbeitung in der nächsten Kanalsenke fortsetzen
            sinkStack.AsyncProcessResponse(headers, stream);
        }
Beispiel #7
0
        /// <summary>
        /// Creates an empty response message.
        /// </summary>
        /// <param name="sinkStack">The sink stack.</param>
        /// <param name="requestMsg">Request message.</param>
        /// <param name="requestHeaders">Request transport headers.</param>
        /// <param name="requestStream">Request stream.</param>
        /// <param name="transactionStage">Current secure transaction stage.</param>
        /// <param name="responseMsg">Response message.</param>
        /// <param name="responseHeaders">Response transport headers.</param>
        /// <param name="responseStream">Response stream.</param>
        /// <returns></returns>
        private ServerProcessing SendEmptyToClient(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, SecureTransactionStage transactionStage, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            responseMsg = null;
            requestStream = new MemoryStream();
            responseStream = new MemoryStream();

            responseHeaders = new TransportHeaders();
            responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)transactionStage).ToString();

            ServerProcessing processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
            return processingResult;
        }
Beispiel #8
0
        /// <summary>
        /// Verarbeitet eine einzele Clientanfrage
        /// </summary>
        /// <param name="sinkStack">Aufrufstapel der Kanalsenken</param>
        /// <param name="requestMsg">Anfrage-nachricht</param>
        /// <param name="requestHeaders">Anfrage-Header</param>
        /// <param name="requestStream">Anfrage-Datenstrom</param>
        /// <param name="responseMsg">Antwort-Nachricht</param>
        /// <param name="responseHeaders">Antwort-Header</param>
        /// <param name="responseStream">Antwort-Datenstrom</param>
        /// <returns>Status serverseitigen Verarbeitung der Nachricht insgesamt</returns>
        public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            // Sicherheitstransaktionskennung aus Anfrage-Header lesen
            string strTransactID = (string)requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_ID];

            // In Guid umwandeln
            Guid transactID = (strTransactID == null ? Guid.Empty : new Guid(strTransactID));

            // Aktuellen Transaktionsschritt aus Anfrage-Header lesen
            SecureTransactionStage transactionStage = (SecureTransactionStage)Convert.ToInt32((string)requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE]);

            // IP-Adresse des Clients aus Anfrage-Header lesen
            IPAddress clientAddress = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;

            // Aktuelle Kanalsenke auf den Senkenstapel legen, damit AsyncProcessResponse später ggf. asynchron aufgerufen werden kann
            sinkStack.Push(this, null);

            // Variable für Verarbeitungsstatus
            ServerProcessing processingResult;

            // Aktuellen Transaktionsschritt auswerten
            switch (transactionStage)
            {
            case SecureTransactionStage.SendingPublicKey:                     // Client sendet den öffentlichen Schlüssel an den Server

                // Gemeinsamen Schlüssel erzeugen und mit dem öffentlichen Schlüssel des Clients verschlüsseln
                processingResult = MakeSharedKey(transactID, requestHeaders, out responseMsg, out responseHeaders, out responseStream);

                break;

            case SecureTransactionStage.SendingEncryptedMessage:                     // Client sendet die verschlüsselte Anfragenachricht an den Server

                // Wenn die Sicherheitstransaktionskennung des Clients bekannt ist ...
                if (IsExistingSecurityTransaction(transactID))
                {
                    // Verschlüsselte Nachricht verarbeiten
                    processingResult = ProcessEncryptedMessage(transactID, sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
                }
                else
                {
                    // Leere Nachricht an den Client senden und Transaktionsschritt auf "Unbekannte Sicherheitstransaktionskennung". setzen.
                    processingResult = SendEmptyToClient(SecureTransactionStage.UnknownTransactionID, out responseMsg, out responseHeaders, out responseStream);
                }

                break;

            case SecureTransactionStage.Uninitialized:                     // Uninizialisiert, noch nichts geschehen

                // Wenn für diesen Client Verschlüsselung nicht zwingend notwendig ist ...
                if (!RequireEncryption(clientAddress))
                {
                    // Nachricht gleich an die nächste Senke zur Weiterverarbeitung übergeben
                    processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
                }
                else
                {
                    // Ausnahme werfen
                    throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_ServerRequiresEncryption);
                }

                break;

            default:

                // Ausnahme werfen
                throw new CryptoRemotingException(string.Format(LanguageResource.CryptoRemotingException_InvalidClientRequest, transactionStage));
            }
            // Aktuelle Senke wieder vom Senkenstapel runternehmen
            sinkStack.Pop(this);

            // Veratbeitungsstatus zurückgeben
            return(processingResult);
        }