Esempio n. 1
0
		/// <summary>
		/// Deserializes a handshake instance from the specified byte array.
		/// </summary>
		/// <param name="data">An array of bytes containing handshake data.</param>
		/// <returns>An initialized instance of the Handshake class deserialized
		/// from the specified byte array.</returns>
		/// <exception cref="SerializationException">Thrown if the specified byte
		/// array does not contain valid handshake data.</exception>
		public static Handshake Deserialize(byte[] data) {
			Handshake hs = new Handshake();
			using (var ms = new MemoryStream(data)) {
				using (var r = new BinaryReader(ms)) {
					try {
						hs.MessageId = (HandshakeType) r.ReadByte();
						hs.MajorVersion = r.ReadByte();
						hs.MinorVersion = r.ReadByte();
						// The payload size is in network byte order (big endian).
						hs.PayloadSize = r.ReadUInt16(true);
					} catch (Exception e) {
						throw new SerializationException("The specified byte array contains " +
							"invalid data.", e);
					}
				}
			}
			// According to specification, version _must_ be 1.0
			if (hs.MajorVersion != majorVersion || hs.MinorVersion != minorVersion) {
				throw new SerializationException("Unexpected handshake version: " +
					hs.MajorVersion + "." + hs.MinorVersion);
			}
			// When the handshake message has a MessageId of HandshakeError, the
			// AuthPayload field _must_ have a length of 8 bytes.
			if (hs.MessageId == HandshakeType.HandshakeError && hs.PayloadSize != 8) {
				throw new SerializationException("Unexpected payload size. Expected " +
					"8, but was: " + hs.PayloadSize);
			}
			return hs;
		}
Esempio n. 2
0
		/// <summary>
		/// Reads the client's handshake from the specified buffer.
		/// </summary>
		/// <param name="buffer">A byte array from which the handshake data
		/// will be read.</param>
		/// <param name="offset">The zero-based index in the buffer at which to
		/// begin reading bytes.</param>
		/// <param name="count">The number of bytes to read from buffer.</param>
		/// <returns>True if the handshake has been read completely, otherwise
		/// false.</returns>
		bool ReadHandshake(byte[] buffer, int offset, int count) {
			// Accumulate data into buffer until 5 bytes have been read.
			int read = Math.Min(count, 5 - handshakeData.Length);
			handshakeData.Append(buffer, offset, read);
			if (handshakeData.Length == 5) {
				// We're now expecting the payload data.
				state = FilterStreamState.ReadingPayload;

				handshake = Handshake.Deserialize(handshakeData.ToArray());
				handshakeData.Clear();
				// Append rest of buffer to payloadData.
				payloadData.Append(buffer, offset + read, count - read);
				return true;
			}
			// We haven't read 5 bytes yet.
			return false;
		}
Esempio n. 3
0
		/// <summary>
		/// Reads the server response from the underlying inner stream.
		/// </summary>
		void ReadServerResponse() {
			// We get a base64-encoded ASCII string back from the server.
			string base64 = ReadLine(innerStream);
			HandshakeType type = HandshakeType.HandshakeInProgress;
			byte[] decoded;

			try {
				// Strip off "+ " continuation command; IMAP and POP3 both use this syntax
				// whereas SMTP uses "334 ".
				base64 = Regex.Replace(base64, @"^(\+|334)\s", String.Empty);
				decoded = Convert.FromBase64String(base64);
			} catch (FormatException) {
				// If the server didn't respond with base64-data, something must have gone
				// wrong and we should gracefully shut down.
				type = HandshakeType.HandshakeError;
				decoded = errorCode;
			}

			// Prepare a new handshake to hand to the NegotiateStream instance.
			Handshake hs = new Handshake(type, (ushort) decoded.Length);
			receivedData = new ByteBuilder()
				.Append(hs.Serialize())
				.Append(decoded)
				.ToArray();
			receivedConsumed = 0;
		}