/// <summary> /// Encrypts the stream under current security conditions. /// </summary> /// <param name="messageStream">Data to be encrypted.</param> /// <param name="outputStream">Stream to write encrypted content to.</param> /// <param name="sspiFeatureFlags">Requested features.</param> public void EncryptMessage(Stream messageStream, GenuineChunkedStream outputStream, SspiFeatureFlags sspiFeatureFlags) { // get package sizes lock (_secPkgContext_SizesLock) { if (!_secPkgContext_SizesInitialized) { SspiApi.QueryContextSizes(this._phContext, ref this._secPkgContext_Sizes); _secPkgContext_SizesInitialized = true; } } byte[] chunk = null; int position = 0; BinaryWriter outputWriter = new BinaryWriter(outputStream); if ((sspiFeatureFlags & SspiFeatureFlags.Encryption) != 0) { // it'll write signature automatically as well as encrypt content SspiApi.EncryptMessage(this._phContext, messageStream, outputWriter, ref this._secPkgContext_Sizes); } else if ((sspiFeatureFlags & SspiFeatureFlags.Signing) != 0) { // remember position to write signature size later outputStream.WriteInt32AndRememberItsLocation(0, out chunk, out position); long currentLength = outputStream.Length; // anyway will have to read this into buffer byte[] contentBuffer = new byte[(int)messageStream.Length]; GenuineUtility.ReadDataFromStream(messageStream, contentBuffer, 0, contentBuffer.Length); // write signature SspiApi.MakeSignature(this._phContext, contentBuffer, outputWriter, ref this._secPkgContext_Sizes); // update signature size MessageCoder.WriteInt32(chunk, position, (int)(outputStream.Length - currentLength)); // write the content outputWriter.Write((int)contentBuffer.Length); outputWriter.Write(contentBuffer, 0, contentBuffer.Length); } else { // just copy the source content //outputWriter.Write( (int) messageStream.Length ); GenuineUtility.CopyStreamToStream(messageStream, outputStream); } }
/// <summary> /// Sends the message to the remote host. /// </summary> /// <param name="message">The message to be sent.</param> protected override void InternalSend(Message message) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; // get IP end point of the remote host IPEndPoint remoteEndPoint; if (message.Recipient.Uri != null && message.Recipient.Uri.StartsWith("_gb")) { remoteEndPoint = this._multicastTo; } else { remoteEndPoint = message.Recipient.PhysicalAddress as IPEndPoint; } if (remoteEndPoint == null) { try { int port; string baseUrl = GenuineUtility.SplitToHostAndPort(message.Recipient.Url, out port); message.Recipient.PhysicalAddress = remoteEndPoint = new IPEndPoint(GenuineUtility.ResolveIPAddress(baseUrl), port); } catch (Exception) { throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.ToString()); } } Stream streamToSend = message.SerializedContent; // write the host URI if ((int)this.ITransportContext.IParameterProvider[GenuineParameter.CompatibilityLevel] > 0) { GenuineChunkedStream streamWith250Header = new GenuineChunkedStream(false); BinaryWriter binaryWriter = new BinaryWriter(streamWith250Header); streamWith250Header.Write(this.ITransportContext.BinaryHostIdentifier, 0, this.ITransportContext.BinaryHostIdentifier.Length); binaryWriter.Write((int)message.Recipient.LocalHostUniqueIdentifier); binaryWriter.Write((Int16)0); streamWith250Header.WriteStream(streamToSend); streamToSend = streamWith250Header; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.InternalSend", LogMessageType.MessageIsSentSynchronously, null, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, message.ConnectionLevelSecuritySession, message.ConnectionLevelSecuritySession == null ? null : message.ConnectionLevelSecuritySession.Name, -1, 0, 0, 0, remoteEndPoint.ToString(), null, null, null, "The message is being sent synchronously to {0}.", remoteEndPoint.ToString()); } // send the message byte[] streamId = Guid.NewGuid().ToByteArray(); lock (_socketLock) { for (int chunkNumber = 1; ; chunkNumber++) { // read the next chunk int chunkSize = streamToSend.Read(this._sendBuffer, HEADER_SIZE, this._sendBuffer.Length - HEADER_SIZE); // fill in the header this._sendBuffer[0] = MessageCoder.COMMAND_MAGIC_CODE; Buffer.BlockCopy(streamId, 0, this._sendBuffer, 1, 16); if (chunkSize < this._sendBuffer.Length - HEADER_SIZE) { chunkNumber = -chunkNumber; } MessageCoder.WriteInt32(this._sendBuffer, 17, chunkNumber); // and just send it! // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0) { binaryLogWriter.WriteTransportContentEvent(LogCategory.Transport, "UdpConnectionManager.InternalSend", LogMessageType.SynchronousSendingStarted, null, message, message.Recipient, binaryLogWriter[LogCategory.Transport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(this._sendBuffer, 0, chunkSize + HEADER_SIZE)) : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this.DbgConnectionId, chunkSize + HEADER_SIZE, remoteEndPoint.ToString(), null, null, "Content is sent synchronously to {0}.", remoteEndPoint.ToString()); } this._socket.SendTo(this._sendBuffer, 0, chunkSize + HEADER_SIZE, SocketFlags.None, remoteEndPoint); if (chunkNumber < 0) { break; } } } }