Пример #1
0
        /// <summary>
        /// Inflate the token
        /// NOTE: This operation is not continuable and assumes that the entire token is available in the stream
        /// </summary>
        /// <param name="source">Stream to inflate the token from</param>
        /// <returns>TRUE if inflation is complete</returns>
        public override bool Inflate(Stream source)
        {
            // Read return value
            Value = TDSUtilities.ReadInt(source);

            return(true);
        }
Пример #2
0
        /// <summary>
        /// Read the raw data but don't interpret it
        /// </summary>
        protected byte[] InflateValue(Stream source)
        {
            // Read the next byte to check if length is DWORD
            int length = (int)source.ReadByte();

            // Update inflation size
            InflationSize += sizeof(byte);

            // Check
            if (length == 0xFF)
            {
                // Length is long
                length = TDSUtilities.ReadInt(source);

                // Update inflation size
                InflationSize += sizeof(int);
            }

            // Allocate a container
            byte[] value = new byte[length];

            // Read all bytes
            source.Read(value, 0, value.Length);

            // Update inflation size
            InflationSize += (uint)length;

            return(value);
        }
Пример #3
0
        public static object InflateColumnData(Stream source, TDSDataType column, Object dataTypeSpecific)
        {
            // Dispatch further reading based on the type
            switch (column)
            {
            case TDSDataType.Null:
            {
                // No data associated with it
                return(null);
            }

            case TDSDataType.DateTime:
            {
                int  daypart  = TDSUtilities.ReadInt(source);
                uint timepart = TDSUtilities.ReadUInt(source);
                return(null);
            }

            case TDSDataType.DateTime2N:
            {
                var length  = (byte)source.ReadByte();
                var rawDate = new byte[length];
                source.Read(rawDate, 0, length);
                uint secondIncrements = 0;
                for (int i = 0; i < length - 3; i++)
                {
                    secondIncrements += (uint)(rawDate[i] << (8 * i));
                }
                var days = (uint)rawDate[length - 3] + (uint)(rawDate[length - 2] << 8) +
                           (uint)(rawDate[length - 1] << 16);
                var date = new DateTime(1, 1, 1).AddDays(days).AddSeconds(secondIncrements * Math.Pow(10, -1 * 5));
                return(date);
            }

            case TDSDataType.Bit:
            case TDSDataType.Int1:
            {
                // Bit, 1 byte data representation
                return((byte)source.ReadByte());
            }

            case TDSDataType.Int2:
            {
                // SmallInt, 2 byte data representation
                return(unchecked ((short)TDSUtilities.ReadUShort(source)));
            }

            case TDSDataType.Int4:
            {
                // Int, 4 byte data representation
                return(unchecked ((int)TDSUtilities.ReadUInt(source)));
            }

            case TDSDataType.Float8:
            {
                // Float (8 byte data representation)
                return(BitConverter.ToDouble(BitConverter.GetBytes(TDSUtilities.ReadULong(source)), 0));
            }

            case TDSDataType.Int8:
            {
                // BigInt (8 byte data representation)
                return(unchecked ((long)TDSUtilities.ReadULong(source)));
            }

            case TDSDataType.BitN:
            {
                // Read length
                byte length = (byte)source.ReadByte();

                // Check if null
                if (length == 0)
                {
                    // No data
                    return(null);
                }

                // Bit, 1 byte data representation
                return((byte)source.ReadByte());
            }

            case TDSDataType.IntN:
            {
                // Read length
                byte length = (byte)source.ReadByte();

                // Check integer length
                switch (length)
                {
                case 0:
                {
                    // No data
                    return(null);
                }

                case 1:
                {
                    // Bit data
                    return((byte)source.ReadByte());
                }

                case 2:
                {
                    // Short data
                    return(unchecked ((short)TDSUtilities.ReadUShort(source)));
                }

                case 4:
                {
                    // Integer data
                    return(unchecked ((int)TDSUtilities.ReadUInt(source)));
                }

                case 8:
                {
                    // Integer data
                    return(unchecked ((long)TDSUtilities.ReadULong(source)));
                }

                default:
                {
                    // We don't know how to inflate this integer
                    throw new InvalidDataException(string.Format("Unable to inflate integer of {0} bytes", length));
                }
                }
            }

            case TDSDataType.NumericN:
            {
                // Read length
                byte length = (byte)source.ReadByte();

                // Check if null
                if (length == 0)
                {
                    // No data
                    return(null);
                }

                // Allocate value container
                byte[] guidBytes = new byte[length];

                // Read value
                source.Read(guidBytes, 0, guidBytes.Length);

                // Instantiate type
                return(guidBytes);
            }

            case TDSDataType.Guid:
            {
                // Read the length
                byte length = (byte)source.ReadByte();

                // Check if we have any data
                if (length == 0x0000)
                {
                    // No data
                    return(null);
                }

                // Allocate value container
                byte[] guidBytes = new byte[length];

                // Read value
                source.Read(guidBytes, 0, guidBytes.Length);

                // Convert to type
                return(new Guid(guidBytes));
            }

            case TDSDataType.BigVarChar:
            case TDSDataType.BigChar:
            {
                // Read length
                ushort length = TDSUtilities.ReadUShort(source);

                // Check if we have any data
                if (length == 0xFFFF)
                {
                    // No data
                    return(null);
                }

                // Allocate value container
                byte[] textBytes = new byte[length];

                // Read value
                source.Read(textBytes, 0, textBytes.Length);

                // Convert to type
                return(Encoding.ASCII.GetString(textBytes));
            }

            case TDSDataType.NVarChar:
            {
                // Check if MAX type
                if ((dataTypeSpecific as TDSShilohVarCharColumnSpecific).Length == 0xFFFF)
                {
                    // Read the length of partialy length-prefixed type
                    ulong length = TDSUtilities.ReadULong(source);

                    // Check the value
                    if (length == 0xFFFFFFFFFFFFFFFF)
                    {
                        // There's no data
                        return(null);
                    }
                    else if (length == 0xFFFFFFFFFFFFFFFE)
                    {
                        throw new NotImplementedException("UNKNOWN_PLP_LEN is not implemented yet");
                    }
                    else
                    {
                        // Allocate a memory stream
                        MemoryStream chunks = new MemoryStream();

                        // Size of the last chunk
                        uint chunkLength = 0;

                        // Iterate until we read the whole data
                        do
                        {
                            // Read the length of the chunk
                            chunkLength = TDSUtilities.ReadUInt(source);

                            // Allocate chunk container
                            byte[] chunk = new byte[chunkLength];

                            // Read value
                            source.Read(chunk, 0, chunk.Length);

                            // Append into the stream
                            chunks.Write(chunk, 0, chunk.Length);
                        }while (chunkLength > 0);

                        // Convert to byte array
                        byte[] byteString = chunks.ToArray();

                        // Serialize the data into the string
                        return(Encoding.Unicode.GetString(byteString, 0, byteString.Length));
                    }
                }
                else
                {
                    // Read length
                    ushort length = TDSUtilities.ReadUShort(source);

                    // Check if we have any data
                    if (length == 0xFFFF)
                    {
                        // No data
                        return(null);
                    }

                    // Read the whole string at once
                    return(TDSUtilities.ReadString(source, (ushort)length));
                }
            }

            case TDSDataType.BigVarBinary:
            {
                byte[] bytes = null;

                // Check if MAX type
                if ((ushort)dataTypeSpecific == 0xFFFF)
                {
                    // Read the length of partialy length-prefixed type
                    ulong length = TDSUtilities.ReadULong(source);

                    // Check the value
                    if (length == 0xFFFFFFFFFFFFFFFF)
                    {
                        // There's no data
                        return(null);
                    }
                    else if (length == 0xFFFFFFFFFFFFFFFE)
                    {
                        throw new NotImplementedException("UNKNOWN_PLP_LEN is not implemented yet");
                    }
                    else
                    {
                        // Allocate a memory stream
                        MemoryStream chunks = new MemoryStream();

                        // Size of the last chunk
                        uint chunkLength = 0;

                        // Iterate until we read the whole data
                        do
                        {
                            // Read the length of the chunk
                            chunkLength = TDSUtilities.ReadUInt(source);

                            // Allocate chunk container
                            byte[] chunk = new byte[chunkLength];

                            // Read value
                            source.Read(chunk, 0, chunk.Length);

                            // Append into the stream
                            chunks.Write(chunk, 0, chunk.Length);
                        }while (chunkLength > 0);

                        // Serialize to byte array
                        bytes = chunks.ToArray();
                    }
                }
                else
                {
                    // Read length
                    ushort length = TDSUtilities.ReadUShort(source);

                    // Check if we have any data
                    if (length == 0xFFFF)
                    {
                        // No data
                        return(null);
                    }

                    // Allocate value container
                    bytes = new byte[length];

                    // Read value
                    source.Read(bytes, 0, bytes.Length);
                }

                // Convert to type
                return(bytes);
            }

            case TDSDataType.BigBinary:
            {
                // Read length
                ushort length = TDSUtilities.ReadUShort(source);

                // Check if we have any data
                if (length == 0xFFFF)
                {
                    // No data
                    return(null);
                }

                // Allocate value container
                byte[] bytes = new byte[length];

                // Read value
                source.Read(bytes, 0, bytes.Length);

                // Convert to type
                return(bytes);
            }

            default:
            {
                // We don't know this type
                throw new NotImplementedException(string.Format("Unrecognized data type {0} for inflation", column));
            }
            }
        }
        /// <summary>
        /// Inflate the token
        /// NOTE: This operation is not continuable and assumes that the entire token is available in the stream
        /// </summary>
        /// <param name="source">Stream to inflate the token from</param>
        /// <returns>TRUE if inflation is complete</returns>
        public override bool Inflate(Stream source)
        {
            // Read packet length
            uint length = TDSUtilities.ReadUInt(source);

            // Read TDS version
            string tdsVersion = string.Format("{0:X}", TDSUtilities.ReadUInt(source));

            // Consturct TDS version
            TDSVersion = new Version(int.Parse(tdsVersion.Substring(0, 1)), int.Parse(tdsVersion.Substring(1, 1)), Convert.ToInt32(tdsVersion.Substring(2, 2), 16), Convert.ToInt32(tdsVersion.Substring(4, 4), 16));

            // Read packet length
            PacketSize = TDSUtilities.ReadUInt(source);

            // Read client program version
            ClientProgramVersion = TDSUtilities.ReadUInt(source);

            // Read client program identifier
            ClientPID = TDSUtilities.ReadUInt(source);

            // Read connection identifier
            ConnectionID = TDSUtilities.ReadUInt(source);

            // Instantiate the first optional flags
            OptionalFlags1 = new TDSLogin7TokenOptionalFlags1((byte)source.ReadByte());

            // Instantiate the second optional flags
            OptionalFlags2 = new TDSLogin7TokenOptionalFlags2((byte)source.ReadByte());

            // Instantiate type flags
            TypeFlags = new TDSLogin7TokenTypeFlags((byte)source.ReadByte());

            // Instantiate the third optional flags
            OptionalFlags3 = new TDSLogin7TokenOptionalFlags3((byte)source.ReadByte());

            // Read client time zone
            ClientTimeZone = TDSUtilities.ReadInt(source);

            // Read client locale identifier
            ClientLCID = TDSUtilities.ReadUInt(source);

            // Prepare a collection of property values that will be set later
            IList <TDSLogin7TokenOffsetProperty> variableProperties = new List <TDSLogin7TokenOffsetProperty>();

            // Read client host name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("HostName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read user name and password
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("UserID"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Password"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read application name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ApplicationName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read server name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ServerName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Check if extension is used
            if (OptionalFlags3.ExtensionFlag)
            {
                // Read Feature extension. Note that this is just an offset of the value, not the value itself
                variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("FeatureExt"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source), true));
            }
            else
            {
                // Skip unused
                TDSUtilities.ReadUShort(source);
                TDSUtilities.ReadUShort(source);
            }

            // Read client library name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("LibraryName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read language
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Language"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read database
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Database"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            ClientID = new byte[6];

            // Read unique client identifier
            source.Read(ClientID, 0, ClientID.Length);

            // Read SSPI blob
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("SSPI"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read database file to be attached
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("AttachDatabaseFile"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read password change
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ChangePassword"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read long SSPI
            uint sspiLength = TDSUtilities.ReadUInt(source);

            // At this point we surpassed the fixed packet length
            long inflationOffset = FixedPacketLength;

            // Order strings in ascending order by offset
            // For the most cases this should not change the order of the options in the stream, but just in case
            variableProperties = variableProperties.OrderBy(p => p.Position).ToList();

            // We can't use "foreach" because FeatureExt processing changes the collection hence we can only go index-based way
            int iCurrentProperty = 0;

            // Iterate over each property
            while (iCurrentProperty < variableProperties.Count)
            {
                // Get the property at the indexed position
                TDSLogin7TokenOffsetProperty property = variableProperties[iCurrentProperty];

                // Check if length is positive
                if (property.Length == 0)
                {
                    // Move to the next propety
                    iCurrentProperty++;
                    continue;
                }

                // Ensure that current offset points to the option
                while (inflationOffset < property.Position)
                {
                    // Read the stream
                    source.ReadByte();

                    // Advance position
                    inflationOffset++;
                }

                // Check special properties
                if (property.Property.Name == "Password" || property.Property.Name == "ChangePassword")
                {
                    // Read passwod string
                    property.Property.SetValue(this, TDSUtilities.ReadPasswordString(source, (ushort)(property.Length * 2)), null);

                    // Advance the position
                    inflationOffset += (property.Length * 2);
                }
                else if (property.Property.Name == "SSPI")
                {
                    // If cbSSPI < USHRT_MAX, then this length MUST be used for SSPI and cbSSPILong MUST be ignored.
                    // If cbSSPI == USHRT_MAX, then cbSSPILong MUST be checked.
                    if (property.Length == ushort.MaxValue)
                    {
                        // If cbSSPILong > 0, then that value MUST be used. If cbSSPILong ==0, then cbSSPI (USHRT_MAX) MUST be used.
                        if (sspiLength > 0)
                        {
                            // We don't know how to handle SSPI packets that exceed TDS packet size
                            throw new NotSupportedException("Long SSPI blobs are not supported yet");
                        }
                    }

                    // Use short length instead
                    sspiLength = property.Length;

                    // Allocate buffer for SSPI data
                    SSPI = new byte[sspiLength];

                    // Read SSPI blob
                    source.Read(SSPI, 0, SSPI.Length);

                    // Advance the position
                    inflationOffset += sspiLength;
                }
                else if (property.Property.Name == "FeatureExt")
                {
                    // Check if this is the property or a pointer to the property
                    if (property.IsOffsetOffset)
                    {
                        // Read the actual offset of the feature extension
                        property.Position = TDSUtilities.ReadUInt(source);

                        // Mark that now we have actual value
                        property.IsOffsetOffset = false;

                        // Advance the position
                        inflationOffset += sizeof(uint);

                        // Re-order the collection
                        variableProperties = variableProperties.OrderBy(p => p.Position).ToList();

                        // Subtract position to stay on the same spot for subsequent property
                        iCurrentProperty--;
                    }
                    else
                    {
                        // Create a list of features.
                        FeatureExt = new TDSLogin7FeatureOptionsToken();

                        // Inflate feature extension
                        FeatureExt.Inflate(source);

                        // Advance position by the size of the inflated token
                        inflationOffset += FeatureExt.InflationSize;
                    }
                }
                else
                {
                    // Read the string and assign it to the property of this instance
                    property.Property.SetValue(this, TDSUtilities.ReadString(source, (ushort)(property.Length * 2)), null);

                    // Advance the position
                    inflationOffset += (property.Length * 2);
                }

                // Advance to the next property
                iCurrentProperty++;
            }

            return(true);
        }