Example #1
0
        public void EnhancedBlockStream_Bytes32()
        {
            var es = new EnhancedBlockStream();

            byte[] read, write;

            es.WriteBytes32(null);
            es.Seek(0, SeekOrigin.Begin);
            read = es.ReadBytes32();
            Assert.IsNull(read);

            write = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            es.Seek(0, SeekOrigin.Begin);
            es.WriteBytes32(write);
            es.Seek(0, SeekOrigin.Begin);
            read = es.ReadBytes32();
            CollectionAssert.AreEqual(write, read);

            write = new byte[40000];
            for (int i = 0; i < write.Length; i++)
            {
                write[i] = (byte)i;
            }

            es.Seek(0, SeekOrigin.Begin);
            es.WriteBytes32(write);
            es.Seek(0, SeekOrigin.Begin);
            read = es.ReadBytes32();
            CollectionAssert.AreEqual(write, read);
        }
Example #2
0
        /// <summary>
        /// Constuctor.
        /// </summary>
        /// <param name="operation">Specifies how the message should be interpreted.</param>
        /// <param name="timestamp">The time (UTC) when the delivery was completed successfully or was aborted.</param>
        /// <param name="targetEP">The original target or cluster endpoint.</param>
        /// <param name="confirmEP">The confirmation endpoint (or <c>null</c>).</param>
        /// <param name="query">The query message.</param>
        /// <param name="topologyID">The globally unique cluster topology provider instance ID or <see cref="Guid.Empty" />.</param>
        /// <param name="topologyInfo">The serialized cluster itopology nformation (or <c>null</c>).</param>
        /// <param name="topologyParam">The serialized topology parameter (or <c>null</c>).</param>
        /// <param name="exception">The exception for failed deliveries or queries.</param>
        /// <param name="response">The response message (or <c>null</c>).</param>
        public DeliveryMsg(DeliveryOperation operation, DateTime timestamp, MsgEP targetEP, MsgEP confirmEP, Msg query,
                           Guid topologyID, string topologyInfo, string topologyParam, Exception exception, Msg response)
        {
            this.Operation     = operation;
            this.Timestamp     = timestamp;
            this.TargetEP      = targetEP;
            this.ConfirmEP     = confirmEP;
            this.TopologyID    = topologyID;
            this.TopologyInfo  = topologyInfo;
            this.TopologyParam = topologyParam;
            this.Exception     = exception;
            this.query         = query;
            this.response      = response;

            // Serialize the query and responses to the message blob

            EnhancedBlockStream es = new EnhancedBlockStream();

            try
            {
                Msg.Save(es, query);

                if (response != null)
                {
                    Msg.Save(es, response);
                }

                base._Data = es.ToArray();
            }
            finally
            {
                es.Close();
            }
        }
Example #3
0
        /// <summary>
        /// Handles the deserialization of the <see cref="Query" /> and <see cref="Response" />
        /// messages from the blob data.
        /// </summary>
        /// <param name="es">The enhanced stream holding the payload data.</param>
        protected override void ReadFrom(EnhancedStream es)
        {
            // Let the base message class load the properties and the data blob.

            base.ReadFrom(es);

            // Now parse the query and (optional) response messages from the blob

            es = new EnhancedBlockStream(base._Data);

            try
            {
                query = Msg.Load(es);

                if (es.Eof)
                {
                    response = null;
                }
                else
                {
                    response = Msg.Load(es);
                }
            }
            finally
            {
                es.Close();
            }
        }
Example #4
0
        /// <summary>
        /// Uses the HMAC/SHA256 algorithm to hash data from a buffer and returns the result.
        /// </summary>
        /// <param name="key">The secret key.</param>
        /// <param name="data">The input buffer.</param>
        /// <param name="pos">Index of the first byte to be hashed.</param>
        /// <param name="length">The number of bytes to hash.</param>
        /// <returns>The hashed digest.</returns>
        public static byte[] Compute(byte[] key, byte[] data, int pos, int length)
        {
            byte[] xorBuf = new byte[64];
            byte[] hash;
            EnhancedBlockStream es;

            // If the key length is greater than 64 bytes then hash the key
            // first to get it down to a reasonable size.

            if (key.Length > 64)
            {
                key = Compute(key);
            }

            // Pad the key with zeros to 64 bytes in length.

            if (key.Length < 64)
            {
                byte[] newKey = new byte[64];

                for (int i = 0; i < newKey.Length; i++)
                {
                    if (i < key.Length)
                    {
                        newKey[i] = key[i];
                    }
                    else
                    {
                        newKey[i] = 0;
                    }
                }

                key = newKey;
            }

            // XOR the key with iPad and put the result in xorBuf

            for (int i = 0; i < 64; i++)
            {
                xorBuf[i] = (byte)(key[i] ^ iPad);
            }

            // Hash the result of the data appended to xorBuf

            es   = new EnhancedBlockStream(new Block(xorBuf), new Block(data, pos, length));
            hash = Compute(es, xorBuf.Length + length);

            // XOR the key with oPad and put the result in xorBuf

            for (int i = 0; i < 64; i++)
            {
                xorBuf[i] = (byte)(key[i] ^ oPad);
            }

            // The result is the hash of the combination of hash appended to xorBuf

            es = new EnhancedBlockStream(new Block(xorBuf), new Block(hash));

            return(Compute(es, xorBuf.Length + hash.Length));
        }
Example #5
0
        public void EnhancedBlockStream_ReadWriteBytesNoLen()
        {
            var es = new EnhancedBlockStream();

            es.WriteBytesNoLen(new byte[] { 0, 1, 2, 3 });
            es.Seek(0, SeekOrigin.Begin);
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3 }, es.ReadBytes(4));
        }
Example #6
0
        public void EnhancedBlockStream_Float()
        {
            var   es = new EnhancedBlockStream();
            float f;

            es.WriteFloat((float)123.456);
            es.Seek(0, SeekOrigin.Begin);
            f = es.ReadFloat();
            Assert.AreEqual((float)123.456, f);
        }
Example #7
0
        public void EnhancedBlockStream_ReadStringCb()
        {
            var es = new EnhancedBlockStream();
            int cb;

            es.WriteStringNoLen("Hello World!");
            cb = (int)es.Position;

            es.Seek(0, SeekOrigin.Begin);
            Assert.AreEqual("Hello World!", es.ReadString(cb));
        }
Example #8
0
        /// <summary>
        /// Constructs a database package builder that will create a
        /// package at the specified file system path.
        /// </summary>
        /// <param name="setupPath">Path of the setup information.</param>
        /// <remarks>
        /// <para>
        /// The setupInfo file must define these values:
        /// </para>
        /// <code language="cs">
        ///     SetupTitle      = [database setup wizard title]
        ///     ProductName     = [product name]
        ///     ProductID       = [GUID]
        ///     ProductVersion  = [version]
        ///     DatabaseType    = [purpose]
        ///     SchemaVersion   = [version]
        ///  </code>
        /// </remarks>
        public DBPackageBuilder(string setupPath)
        {
            const string MissingValue = "Missing setup value [{0}].";

            bs      = new EnhancedBlockStream();
            package = new Package();
            package.Create(bs);

            package.AddFolder("/Schema");
            package.AddFolder("/Procs");
            package.AddFolder("/Funcs");
            package.AddFolder("/Upgrade");

            package.AddFile("/Setup.ini", setupPath);

            // Validate setup.ini

            Config       config;
            StreamReader reader;

            reader = new StreamReader(setupPath, Helper.AnsiEncoding);
            try
            {
                config = new Config(null, reader);
                if (config.Get("SetupTitle") == null)
                {
                    throw new ArgumentException(string.Format(MissingValue, "SetupTitle"));
                }
                if (config.Get("ProductName") == null)
                {
                    throw new ArgumentException(string.Format(MissingValue, "ProductName"));
                }
                if (config.Get("ProductID") == null)
                {
                    throw new ArgumentException(string.Format(MissingValue, "ProductID"));
                }
                if (config.Get("ProductVersion") == null)
                {
                    throw new ArgumentException(string.Format(MissingValue, "ProductVersion"));
                }
                if (config.Get("DatabaseType") == null)
                {
                    throw new ArgumentException(string.Format(MissingValue, "DatabaseType"));
                }
                if (config.Get("SchemaVersion") == null)
                {
                    throw new ArgumentException(string.Format(MissingValue, "SchemaVersion"));
                }
            }
            finally
            {
                reader.Close();
            }
        }
Example #9
0
        public void EnhancedBlockStream_Bool()
        {
            var es = new EnhancedBlockStream();

            es.WriteBool(true);
            es.WriteBool(false);

            es.Seek(0, SeekOrigin.Begin);

            Assert.IsTrue(es.ReadBool());
            Assert.IsFalse(es.ReadBool());
        }
Example #10
0
        public void EnhancedBlockStream_Byte()
        {
            var es = new EnhancedBlockStream();

            es.WriteByte(77);
            es.WriteByte(99);

            es.Seek(0, SeekOrigin.Begin);

            Assert.AreEqual(77, es.ReadByte());
            Assert.AreEqual(99, es.ReadByte());
        }
Example #11
0
        public void EnhancedBlockStream_String32()
        {
            var es = new EnhancedBlockStream();

            es.WriteString32(null);
            es.WriteString32("Hello World!");
            es.WriteString32(new String('a', 45000));

            es.Seek(0, SeekOrigin.Begin);
            Assert.IsNull(es.ReadString32());
            Assert.AreEqual("Hello World!", es.ReadString32());
            Assert.AreEqual(new String('a', 45000), es.ReadString32());
        }
Example #12
0
        public void Package_HashVerify()
        {
            Package              package;
            EnhancedBlockStream  bs = new EnhancedBlockStream();
            EnhancedMemoryStream es = new EnhancedMemoryStream();
            PackageEntry         entry;

            byte[] buf;
            byte   v;

            buf = new byte[37000];
            for (int i = 0; i < buf.Length; i++)
            {
                buf[i] = (byte)i;
            }

            //-------------------------

            package = new Package();
            package.Create(es);

            bs.WriteBytes32(buf);
            bs.Position = 0;

            entry = package.AddFile("/Foo/Bar/Test1.dat", bs, (int)bs.Length);
            Assert.IsTrue(bs.Eof);
            Assert.IsTrue(entry.IsFile);
            Assert.IsTrue(package["/Foo"].IsFolder);
            Assert.IsTrue(package["/Foo/Bar"].IsFolder);
            Assert.IsTrue(package["/Foo/Bar/Test1.dat"].IsFile);

            package.Close(true);

            es.Position = es.Length / 2;  // Corrupt a byte in the middle of the stream
                                          // to verify that the MD5 hash comparision
                                          // catches it.
            v = (byte)es.ReadByte();
            es.Seek(-1, SeekOrigin.Current);
            es.WriteByte((byte)~v);

            es.Position = 0;

            try
            {
                package = new Package(es);
                Assert.Fail();
            }
            catch (PackageException)
            {
            }
        }
Example #13
0
        public void EnhancedBlockStream_ToByteArray()
        {
            var es = new EnhancedBlockStream();

            byte[] buf;

            es.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 0, 10);
            buf = es.ToArray();
            CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, buf);

            buf[0]      = 255;
            es.Position = 0;
            Assert.AreEqual(0, es.ReadByte());
        }
Example #14
0
        public void EnhancedBlockStream_Int16()
        {
            var es = new EnhancedBlockStream();

            es.WriteInt16(0);
            es.WriteInt16(55);
            es.WriteInt16(0x1234);

            es.Seek(0, SeekOrigin.Begin);

            Assert.AreEqual(0, es.ReadInt16());
            Assert.AreEqual(55, es.ReadInt16());
            Assert.AreEqual(0x1234, es.ReadInt16());
        }
Example #15
0
        public void EnhancedBlockStream_Int32()
        {
            var es = new EnhancedBlockStream();

            es.WriteInt32(0);
            es.WriteInt32(65121);
            es.WriteInt32(0x12345678);

            es.Seek(0, SeekOrigin.Begin);

            Assert.AreEqual(0, es.ReadInt32());
            Assert.AreEqual(65121, es.ReadInt32());
            Assert.AreEqual(0x12345678, es.ReadInt32());
        }
Example #16
0
        public void Package_AddStream()
        {
            Package              package;
            EnhancedBlockStream  bs = new EnhancedBlockStream();
            EnhancedMemoryStream es = new EnhancedMemoryStream();
            PackageEntry         entry;

            byte[] buf;

            buf = new byte[37000];
            for (int i = 0; i < buf.Length; i++)
            {
                buf[i] = (byte)i;
            }

            //-------------------------

            package = new Package();
            package.Create(es);

            bs.WriteBytes32(buf);
            bs.Position = 0;

            entry = package.AddFile("/Foo/Bar/Test1.dat", bs, (int)bs.Length);
            Assert.IsTrue(bs.Eof);
            Assert.IsTrue(entry.IsFile);
            Assert.IsTrue(package["/Foo"].IsFolder);
            Assert.IsTrue(package["/Foo/Bar"].IsFolder);
            Assert.IsTrue(package["/Foo/Bar/Test1.dat"].IsFile);

            package.Close(true);

            //-------------------------

            es.Position = 0;
            package     = new Package(es);

            Assert.IsTrue(entry.IsFile);
            Assert.IsTrue(package["/Foo"].IsFolder);
            Assert.IsTrue(package["/Foo/Bar"].IsFolder);
            Assert.IsTrue(package["/Foo/Bar/Test1.dat"].IsFile);

            bs.SetLength(0);
            package["/Foo/Bar/Test1.dat"].GetContents(bs);

            bs.Position = 0;
            CollectionAssert.AreEqual(buf, bs.ReadBytes32());

            package.Close();
        }
Example #17
0
        /// <summary>
        /// Generates a clone of this message instance, generating a new
        /// <see cref="_MsgID" /> property if the original ID is
        /// not empty.
        /// </summary>
        /// <returns>Returns a clone of the message.</returns>
        /// <remarks>
        /// <para>
        /// This base method works by serializing and then deseralizing a new copy of
        /// the message to a buffer and then generating a new <see cref="_MsgID" /> GUID.  This
        /// implementation will be relatively costly in terms of processor and
        /// memory resources.
        /// </para>
        /// <para>
        /// Derived messages can choose to override this and implement a shallow
        /// clone instead, using the <see cref="CopyBaseFields" /> method.  Note that
        /// the <see cref="CopyBaseFields" /> method ensures that a new <see cref="_MsgID" />
        /// property is regenerated if the original ID field is not empty.
        /// </para>
        /// </remarks>
        public virtual Msg Clone()
        {
            var es = new EnhancedBlockStream(1024, 1024);
            Msg clone;

            Msg.Save(es, this);
            es.Position = 0;
            clone       = Msg.Load(es);

            if (this.msgID != Guid.Empty)
            {
                clone.msgID = Helper.NewGuid();
            }

            return(clone);
        }
Example #18
0
        public void EnhancedBlockStream_Int64()
        {
            var es = new EnhancedBlockStream();

            es.WriteInt64(0);
            es.WriteInt64(65121);
            es.WriteInt64(0x12345678);
            es.WriteInt64((((long)0x12345678) << 32) | (long)0xaabbccddee);

            es.Seek(0, SeekOrigin.Begin);

            Assert.AreEqual(0, es.ReadInt64());
            Assert.AreEqual(65121, es.ReadInt64());
            Assert.AreEqual(0x12345678, es.ReadInt64());
            Assert.AreEqual((((long)0x12345678) << 32) | (long)0xaabbccddee, es.ReadInt64());
        }
Example #19
0
        public void EnhancedBlockStream_VerifyBufLength()
        {
            var es = new EnhancedBlockStream();

            es.WriteInt16(5000);
            es.Seek(0, SeekOrigin.Begin);
            try
            {
                es.ReadBytes16();
                Assert.Fail();
            }
            catch
            {
            }

            es.Seek(0, SeekOrigin.Begin);
            try
            {
                es.ReadString16();
                Assert.Fail();
            }
            catch
            {
            }

            es.Seek(0, SeekOrigin.Begin);
            es.WriteInt32(500000);
            try
            {
                es.ReadBytes32();
                Assert.Fail();
            }
            catch
            {
            }

            es.Seek(0, SeekOrigin.Begin);
            try
            {
                es.ReadString32();
                Assert.Fail();
            }
            catch
            {
            }
        }
Example #20
0
        /// <summary>
        /// Renders the packet into a form suitable for transmission via UDP.
        /// </summary>
        /// <returns>The raw packet byte array.</returns>
        public byte[] ToArray()
        {
            var bs = new EnhancedBlockStream(0, 2048);

            bs.WriteByte((byte)this.Code);
            bs.WriteByte((byte)this.Identifier);
            bs.WriteInt16(0);   // Put a zero in for the length and come back and fill
            // this in after we know what the actual length is.

            bs.WriteBytesNoLen(this.Authenticator);

            for (int i = 0; i < this.Attributes.Count; i++)
            {
                var attr = this.Attributes[i];

                if (attr.Value.Length > RadiusAttribute.MaxValueLen)
                {
                    throw new RadiusException("Attribute value size exceeds 253 bytes.");
                }

                bs.WriteByte((byte)attr.Type);
                bs.WriteByte((byte)(attr.Value.Length + 2));
                bs.WriteBytesNoLen(attr.Value);
            }

            // Go back and write the actual length

            if (bs.Length > short.MaxValue)
            {
                throw new RadiusException("RADIUS packet is too large.");
            }

            bs.Position = 2;
            bs.WriteInt16((int)bs.Length);

            return(bs.ToArray());
        }
Example #21
0
        /// <summary>
        /// Decrypts a user password by encrypted using <see cref="EncryptUserPassword" />
        /// using the message authenticator and the shared NAS secret.
        /// </summary>
        /// <param name="encryptedPassword">The encrypted password.</param>
        /// <param name="secret">The shared NAS secret.</param>
        /// <returns>The decrypted password.</returns>
        /// <exception cref="RadiusException">Thrown if the encrypted password is invalid.</exception>
        public string DecryptUserPassword(byte[] encryptedPassword, string secret)
        {
            var bs = new EnhancedBlockStream(128, 128);

            byte[] secretBytes = Helper.ToAnsi(secret);
            byte[] clearBlock  = new byte[16];
            byte[] xorHash;
            byte[] decrypted;
            int    pos;
            int    zeroPos;

            try
            {
                // The encrypted password length must be a non-zero multiple of 16 bytes.

                if (encryptedPassword.Length == 0 || encryptedPassword.Length % 16 != 0)
                {
                    throw new RadiusException("Encrypted user password length must be a positive multiple of 16 bytes.");
                }

                // The first XOR hash is MD5(secret + authenticator)

                xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, this.Authenticator));

                // Perform the decryption.  The trick here is to unmunge the 16 byte
                // blocks by XORing them with the current XOR hash.

                pos = 0;
                while (true)
                {
                    // clearBlock = XOR hash ^ next 16 encrypted bytes

                    for (int i = 0; i < 16; i++)
                    {
                        clearBlock[i] = (byte)(xorHash[i] ^ encryptedPassword[pos + i]);
                    }

                    bs.WriteBytesNoLen(clearBlock);

                    pos += 16;
                    if (pos >= encryptedPassword.Length)
                    {
                        break;
                    }

                    // Next XOR hash = MD5(secret + last cypherblock)

                    xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, Helper.Extract(encryptedPassword, pos - 16, 16)));
                }

                // Scan forward to the first zero byte.  If we find one, we're going
                // to assume that it was a padding byte.

                decrypted = bs.ToArray();
                zeroPos   = -1;

                for (int i = 0; i < decrypted.Length; i++)
                {
                    if (decrypted[i] == 0)
                    {
                        zeroPos = i;
                        break;
                    }
                }

                if (zeroPos == -1)
                {
                    return(Helper.FromAnsi(decrypted));
                }
                else
                {
                    return(Helper.FromAnsi(decrypted, 0, zeroPos));
                }
            }
            finally
            {
                bs.Close();
            }
        }
Example #22
0
        /// <summary>
        /// Encrypts a user password string by combining it with the shared NAS
        /// secret and the message authenticator as described in RFC 2865 page 27.
        /// </summary>
        /// <param name="userPassword">The user password to be encrypted.</param>
        /// <param name="secret">The shared NAS secret.</param>
        /// <returns>The encrypted password.</returns>
        /// <exception cref="RadiusException">Thrown if the password is too large or too small.</exception>
        public byte[] EncryptUserPassword(string userPassword, string secret)
        {
            var bs = new EnhancedBlockStream(128, 128);

            byte[] secretBytes = Helper.ToAnsi(secret);
            byte[] cypherBlock = new byte[16];
            byte[] rawPwd;
            byte[] xorHash;
            byte[] pwd;
            int    pos;

            try
            {
                rawPwd = Helper.ToAnsi(userPassword);
                if (rawPwd.Length == 0)
                {
                    throw new RadiusException("Zero length password is not allowed.");
                }

                // Copy userPassword into pwd, padding the result out with zeros
                // to a multiple of 16 bytes

                if (rawPwd.Length % 16 == 0)
                {
                    pwd = rawPwd;
                }
                else
                {
                    pwd = new byte[(rawPwd.Length / 16 + 1) * 16];
                    Array.Copy(rawPwd, pwd, rawPwd.Length);
                }

                // The first XOR hash is MD5(secret + authenticator)

                xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, this.Authenticator));

                // Perform the encryption

                pos = 0;
                while (true)
                {
                    // Cyperblock = XOR hash ^ next 16 bytes of password

                    for (int i = 0; i < 16; i++)
                    {
                        cypherBlock[i] = (byte)(xorHash[i] ^ pwd[pos + i]);
                    }

                    bs.WriteBytesNoLen(cypherBlock);

                    pos += 16;
                    if (pos >= pwd.Length)
                    {
                        break;
                    }

                    // Next XOR hash is MD5(secret + cypherblock)

                    xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, cypherBlock));
                }

                if (bs.Length > 128)
                {
                    throw new RadiusException("Encrypted password exceeds 128 bytes.");
                }

                return(bs.ToArray());
            }
            finally
            {
                bs.Close();
            }
        }