Exemplo n.º 1
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();
            }
        }
Exemplo n.º 2
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());
        }
Exemplo n.º 3
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());
        }
Exemplo n.º 4
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();
            }
        }
Exemplo n.º 5
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();
            }
        }